Skip to content

Commit

Permalink
feat: ✨ Add support for hopper upgrade to be able to work with "autom…
Browse files Browse the repository at this point in the history
…ation entities" - in vanilla chest minecart / chest boat.
  • Loading branch information
P3pp3rF1y committed Dec 23, 2024
1 parent 1000bde commit 38dc06f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 12 deletions.
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ loader_version_range=[4,)
mod_id=sophisticatedstorage
mod_name=Sophisticated Storage
mod_license=GNU General Public License v3.0
mod_version=1.0.3
mod_version=1.0.4
mod_group_id=sophisticatedstorage
mod_authors=P3pp3rF1y, Ridanisaurus
mod_description=Fancy and functional storage containers.
Expand All @@ -35,7 +35,7 @@ jade_cf_file_id=5109393
chipped_cf_file_id=5506938
resourcefullib_cf_file_id=5483169
athena_cf_file_id=5431579
sc_version=[1.21.1-1.0.4,1.22)
sc_version=[1.21.1-1.0.5,1.22)
sb_version=[1.21,1.22)

#publish
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.MenuType;
Expand Down Expand Up @@ -60,6 +61,11 @@ public Optional<BlockPos> getBlockPosition() {
return Optional.of(storageBlockEntity.getBlockPos());
}

@Override
public Optional<Entity> getEntity() {
return Optional.empty();
}

@Override
protected StorageContainerMenuBase<IStorageWrapper>.StorageUpgradeSlot instantiateUpgradeSlot(UpgradeHandler upgradeHandler, int slotIndex) {
return new StorageUpgradeSlot(upgradeHandler, slotIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.neoforged.neoforge.capabilities.BlockCapabilityCache;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.items.IItemHandler;
Expand Down Expand Up @@ -62,13 +64,13 @@ public void tick(@Nullable Entity entity, Level level, BlockPos pos) {
}

for (Direction pushDirection : pushDirections) {
if (runOnItemHandlers(level, pos, pushDirection, this::pushItems)) {
if (runOnItemHandlers(level, pos, pushDirection, this::pushItems, entity == null)) {
break;
}
}

for (Direction pullDirection : pullDirections) {
if (runOnItemHandlers(level, pos, pullDirection, this::pullItems)) {
if (runOnItemHandlers(level, pos, pullDirection, this::pullItems, entity == null)) {
break;
}
}
Expand All @@ -87,6 +89,8 @@ private void initDirections(Level level, BlockPos pos) {
pullDirections.clear();
pushDirections.clear();
initDirections(BlockSide.BOTTOM.toDirection(horizontalDirection, verticalFacing), BlockSide.TOP.toDirection(horizontalDirection, verticalFacing));
} else {
initDirections(Direction.DOWN, Direction.UP);
}
}

Expand Down Expand Up @@ -157,6 +161,11 @@ public void updateCacheOnSide(Level level, BlockPos pos, Direction direction) {
return;
}

ItemHandlerHolder itemHandlers = getItemHandlerHolder(level, pos, direction, serverLevel);
handlerCache.put(direction, itemHandlers);
}

private ItemHandlerHolder getItemHandlerHolder(Level level, BlockPos pos, Direction direction, ServerLevel serverLevel) {
WeakReference<HopperUpgradeWrapper> existRef = new WeakReference<>(this);

BlockState storageState = level.getBlockState(pos);
Expand All @@ -175,20 +184,45 @@ public void updateCacheOnSide(Level level, BlockPos pos, Direction direction) {

caches.add(BlockCapabilityCache.create(Capabilities.ItemHandler.BLOCK, serverLevel, offsetPos, direction.getOpposite(), () -> existRef.get() != null, () -> updateCacheOnSide(level, pos, direction)));
});
handlerCache.put(direction, new ItemHandlerHolder(caches, refreshOnEveryNeighborChange.get()));
return new ItemHandlerHolder(caches, refreshOnEveryNeighborChange.get());
}

private boolean runOnItemHandlers(Level level, BlockPos pos, Direction direction, Predicate<List<IItemHandler>> run) {
if (!handlerCache.containsKey(direction)) {
updateCacheOnSide(level, pos, direction);
private boolean runOnItemHandlers(Level level, BlockPos pos, Direction direction, Predicate<List<IItemHandler>> run, boolean useCache) {
ItemHandlerHolder holder = getItemHandlerHolder(level, pos, direction, useCache);
if (holder == null) {
return runOnAutomationEntityItemHandlers(level, pos, direction, run);
}
if (handlerCache.get(direction) == null) {
return false;

List<IItemHandler> handler = holder.handlers().stream().map(BlockCapabilityCache::getCapability).filter(Objects::nonNull).toList();

return handler.isEmpty() ? runOnAutomationEntityItemHandlers(level, pos, direction, run) : run.test(handler);
}

private boolean runOnAutomationEntityItemHandlers(Level level, BlockPos pos, Direction direction, Predicate<List<IItemHandler>> run) {
List<Entity> entities = level.getEntities((Entity)null, new AABB(pos.relative(direction)), EntitySelector.ENTITY_STILL_ALIVE);
if (!entities.isEmpty()) {
Collections.shuffle(entities);
for (Entity entity : entities) {
IItemHandler entityCap = entity.getCapability(Capabilities.ItemHandler.ENTITY_AUTOMATION, direction.getOpposite());
if (entityCap != null) {
return run.test(List.of(entityCap));
}
}
}

List<IItemHandler> handler = handlerCache.get(direction).handlers().stream().map(BlockCapabilityCache::getCapability).filter(Objects::nonNull).toList();
return false;
}

@Nullable
private ItemHandlerHolder getItemHandlerHolder(Level level, BlockPos pos, Direction direction, boolean useCache) {
if (useCache) {
if (!handlerCache.containsKey(direction)) {
updateCacheOnSide(level, pos, direction);
}
return handlerCache.get(direction);
}

return run.test(handler);
return getItemHandlerHolder(level, pos, direction, (ServerLevel) level);
}

public ContentsFilterLogic getInputFilterLogic() {
Expand Down

0 comments on commit 38dc06f

Please sign in to comment.