diff --git a/gradle.properties b/gradle.properties index de2e5f7e..2ce3cdb6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.daemon=false mod_id=sophisticatedcore mod_group_id=sophisticatedcore -mod_version=0.6.8 +mod_version=0.6.9 sonar_project_key=sophisticatedcore:SophisticatedCore github_package_url=https://maven.pkg.github.com/P3pp3rF1y/SophisticatedCore diff --git a/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/ControllerBlockEntityBase.java b/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/ControllerBlockEntityBase.java index e9da8517..b2d198c9 100644 --- a/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/ControllerBlockEntityBase.java +++ b/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/ControllerBlockEntityBase.java @@ -33,7 +33,7 @@ import java.util.*; import java.util.function.Function; -public abstract class ControllerBlockEntityBase extends BlockEntity implements IItemHandlerModifiable { +public abstract class ControllerBlockEntityBase extends BlockEntity implements IItemHandlerSimpleInserter { public static final int SEARCH_RANGE = 15; private List storagePositions = new ArrayList<>(); private List baseIndexes = new ArrayList<>(); @@ -52,9 +52,12 @@ public abstract class ControllerBlockEntityBase extends BlockEntity implements I private final Map> storageFilterItems = new HashMap<>(); private Set linkedBlocks = new TreeSet<>(distanceComparator); private Set connectingBlocks = new TreeSet<>(distanceComparator); + private Set nonConnectingBlocks = new TreeSet<>(distanceComparator); @Nullable private LazyOptional itemHandlerCap; + @Nullable + private LazyOptional noSideItemHandlerCap; public boolean addLinkedBlock(BlockPos linkedPos) { if (level != null && !level.isClientSide() && isWithinRange(linkedPos) && !linkedBlocks.contains(linkedPos) && !storagePositions.contains(linkedPos)) { @@ -66,10 +69,10 @@ public boolean addLinkedBlock(BlockPos linkedPos) { if (l.connectLinkedSelf()) { Set positionsToCheck = new LinkedHashSet<>(); positionsToCheck.add(linkedPos); - searchAndAddStorages(positionsToCheck, true); + searchAndAddBoundables(positionsToCheck, true); } - searchAndAddStorages(new LinkedHashSet<>(l.getConnectablePositions()), false); + searchAndAddBoundables(new LinkedHashSet<>(l.getConnectablePositions()), false); }); WorldHelper.notifyBlockUpdate(this); return true; @@ -101,12 +104,12 @@ public boolean isStorageConnected(BlockPos storagePos) { return storagePositions.contains(storagePos); } - public void searchAndAddStorages() { + public void searchAndAddBoundables() { Set positionsToCheck = new HashSet<>(); for (Direction dir : Direction.values()) { positionsToCheck.add(getBlockPos().offset(dir.getNormal())); } - searchAndAddStorages(positionsToCheck, false); + searchAndAddBoundables(positionsToCheck, false); } public void changeSlots(BlockPos storagePos, int newSlots, boolean hasEmptySlots) { @@ -148,7 +151,7 @@ public int getSlots(int storageIndex) { return getStorageSlots(storageIndex); } - private void searchAndAddStorages(Set positionsToCheck, boolean addingLinkedSelf) { + private void searchAndAddBoundables(Set positionsToCheck, boolean addingLinkedSelf) { Set positionsChecked = new HashSet<>(); boolean first = true; @@ -158,26 +161,30 @@ private void searchAndAddStorages(Set positionsToCheck, boolean adding it.remove(); final boolean finalFirst = first; - WorldHelper.getLoadedBlockEntity(level, posToCheck, IControllableStorage.class).ifPresentOrElse(storage -> - tryToConnectStorageAndAddPositionsToCheckAround(positionsToCheck, addingLinkedSelf, positionsChecked, posToCheck, finalFirst, storage), + WorldHelper.getLoadedBlockEntity(level, posToCheck, IControllerBoundable.class).ifPresentOrElse(boundable -> + tryToConnectStorageAndAddPositionsToCheckAround(positionsToCheck, addingLinkedSelf, positionsChecked, posToCheck, finalFirst, boundable), () -> positionsChecked.add(posToCheck) ); first = false; } } - private void tryToConnectStorageAndAddPositionsToCheckAround(Set positionsToCheck, boolean addingLinkedSelf, Set positionsChecked, BlockPos posToCheck, boolean finalFirst, IControllableStorage storage) { - if (storage.canBeConnected() || (addingLinkedSelf && finalFirst)) { - if (storage instanceof ILinkable linkable && linkable.isLinked() && (!addingLinkedSelf || !finalFirst)) { + private void tryToConnectStorageAndAddPositionsToCheckAround(Set positionsToCheck, boolean addingLinkedSelf, Set positionsChecked, BlockPos posToCheck, boolean finalFirst, IControllerBoundable boundable) { + if (boundable.canBeConnected() || (addingLinkedSelf && finalFirst)) { + if (boundable instanceof ILinkable linkable && linkable.isLinked() && (!addingLinkedSelf || !finalFirst)) { linkedBlocks.remove(posToCheck); linkable.setNotLinked(); - } else if (storage.hasStorageData()) { + } else if (boundable instanceof IControllableStorage storage && storage.hasStorageData()) { addStorageData(posToCheck); } else { - connectingBlocks.add(posToCheck); - storage.registerController(this); + if (boundable.canConnectStorages()) { + connectingBlocks.add(posToCheck); + } else { + nonConnectingBlocks.add(posToCheck); + } + boundable.registerController(this); } - if (storage.canConnectStorages()) { + if (boundable.canConnectStorages()) { addUncheckedPositionsAround(positionsToCheck, positionsChecked, posToCheck); } } @@ -186,7 +193,7 @@ private void tryToConnectStorageAndAddPositionsToCheckAround(Set posit private void addUncheckedPositionsAround(Set positionsToCheck, Set positionsChecked, BlockPos currentPos) { for (Direction dir : Direction.values()) { BlockPos pos = currentPos.offset(dir.getNormal()); - if (!positionsChecked.contains(pos) && ((!storagePositions.contains(pos) && !connectingBlocks.contains(pos)) || linkedBlocks.contains(pos)) && isWithinRange(pos)) { + if (!positionsChecked.contains(pos) && ((!storagePositions.contains(pos) && !connectingBlocks.contains(pos) && !nonConnectingBlocks.contains(pos)) || linkedBlocks.contains(pos)) && isWithinRange(pos)) { positionsToCheck.add(pos); } } @@ -204,7 +211,7 @@ public void addStorage(BlockPos storagePos) { if (isWithinRange(storagePos)) { HashSet positionsToCheck = new LinkedHashSet<>(); positionsToCheck.add(storagePos); - searchAndAddStorages(positionsToCheck, false); + searchAndAddBoundables(positionsToCheck, false); } } @@ -353,6 +360,12 @@ private void removeConnectingBlock(BlockPos storagePos) { } } + public void removeNonConnectingBlock(BlockPos storagePos) { + if (nonConnectingBlocks.remove(storagePos)) { + WorldHelper.getLoadedBlockEntity(level, storagePos, IControllerBoundable.class).ifPresent(IControllerBoundable::unregisterController); + } + } + private void removeStorageInventoryDataAndUnregisterController(BlockPos storagePos) { if (!storagePositions.contains(storagePos)) { return; @@ -429,6 +442,7 @@ private void removeStorageMemorizedStacks(BlockPos storagePos) { private void verifyStoragesConnected() { HashSet toVerify = new HashSet<>(storagePositions); toVerify.addAll(connectingBlocks); + toVerify.addAll(nonConnectingBlocks); Set positionsToCheck = new HashSet<>(); for (Direction dir : Direction.values()) { @@ -439,7 +453,7 @@ private void verifyStoragesConnected() { } Set positionsChecked = new HashSet<>(); - verifyDirectlyConnected(toVerify, positionsToCheck, positionsChecked); + verifyConnected(toVerify, positionsToCheck, positionsChecked); linkedBlocks.forEach(linkedPosition -> WorldHelper.getBlockEntity(getLevel(), linkedPosition, ILinkable.class).ifPresent(l -> { if (l.connectLinkedSelf() && toVerify.contains(linkedPosition)) { @@ -452,22 +466,23 @@ private void verifyStoragesConnected() { }); })); - verifyDirectlyConnected(toVerify, positionsToCheck, positionsChecked); + verifyConnected(toVerify, positionsToCheck, positionsChecked); toVerify.forEach(storagePos -> { removeConnectingBlock(storagePos); + removeNonConnectingBlock(storagePos); removeStorageInventoryDataAndUnregisterController(storagePos); }); } - private void verifyDirectlyConnected(HashSet toVerify, Set positionsToCheck, Set positionsChecked) { + private void verifyConnected(HashSet toVerify, Set positionsToCheck, Set positionsChecked) { while (!positionsToCheck.isEmpty()) { Iterator it = positionsToCheck.iterator(); BlockPos posToCheck = it.next(); it.remove(); positionsChecked.add(posToCheck); - WorldHelper.getLoadedBlockEntity(level, posToCheck, IControllableStorage.class).ifPresent(h -> { + WorldHelper.getLoadedBlockEntity(level, posToCheck, IControllerBoundable.class).ifPresent(h -> { toVerify.remove(posToCheck); if (h.canConnectStorages()) { for (Direction dir : Direction.values()) { @@ -500,10 +515,17 @@ protected ControllerBlockEntityBase(BlockEntityType blockEntityType, BlockPos @Override public LazyOptional getCapability(Capability cap, @Nullable Direction side) { if (cap == ForgeCapabilities.ITEM_HANDLER) { - if (itemHandlerCap == null) { - itemHandlerCap = LazyOptional.of(() -> new CachedFailedInsertInventoryHandler(() -> this, () -> level != null ? level.getGameTime() : 0)); + if (side == null) { + if (noSideItemHandlerCap == null) { + noSideItemHandlerCap = LazyOptional.of(() -> this).cast(); + } + return noSideItemHandlerCap.cast(); + } else { + if (itemHandlerCap == null) { + itemHandlerCap = LazyOptional.of(() -> new CachedFailedInsertInventoryHandler(() -> this, () -> level != null ? level.getGameTime() : 0)); + } + return itemHandlerCap.cast(); } - return itemHandlerCap.cast(); } return super.getCapability(cap, side); } @@ -515,6 +537,10 @@ public void invalidateCaps() { itemHandlerCap.invalidate(); itemHandlerCap = null; } + if (noSideItemHandlerCap != null) { + noSideItemHandlerCap.invalidate(); + noSideItemHandlerCap = null; + } } @Override @@ -591,6 +617,11 @@ public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { return insertItem(stack, simulate, true); } + @Override + public ItemStack insertItem(ItemStack stack, boolean simulate) { + return insertItem(stack, simulate, true); + } + protected ItemStack insertItem(ItemStack stack, boolean simulate, boolean insertIntoAnyEmpty) { ItemStackKey stackKey = ItemStackKey.of(stack); ItemStack remaining = stack; @@ -740,6 +771,7 @@ public void onChunkUnloaded() { public void detachFromStoragesAndUnlinkBlocks() { storagePositions.forEach(pos -> WorldHelper.getLoadedBlockEntity(level, pos, IControllableStorage.class).ifPresent(IControllableStorage::unregisterController)); connectingBlocks.forEach(pos -> WorldHelper.getLoadedBlockEntity(level, pos, IControllableStorage.class).ifPresent(IControllableStorage::unregisterController)); + nonConnectingBlocks.forEach(pos -> WorldHelper.getLoadedBlockEntity(level, pos, IControllerBoundable.class).ifPresent(IControllerBoundable::unregisterController)); new HashSet<>(linkedBlocks).forEach(linkedPos -> WorldHelper.getLoadedBlockEntity(level, linkedPos, ILinkable.class).ifPresent(ILinkable::unlinkFromController)); //copying into new hashset to prevent CME when these are removed } @@ -753,6 +785,7 @@ protected void saveAdditional(CompoundTag tag) { private CompoundTag saveData(CompoundTag tag) { NBTHelper.putList(tag, "storagePositions", storagePositions, p -> LongTag.valueOf(p.asLong())); NBTHelper.putList(tag, "connectingBlocks", connectingBlocks, p -> LongTag.valueOf(p.asLong())); + NBTHelper.putList(tag, "nonConnectingBlocks", nonConnectingBlocks, p -> LongTag.valueOf(p.asLong())); NBTHelper.putList(tag, "linkedBlocks", linkedBlocks, p -> LongTag.valueOf(p.asLong())); NBTHelper.putList(tag, "baseIndexes", baseIndexes, IntTag::valueOf); tag.putInt("totalSlots", totalSlots); @@ -766,6 +799,7 @@ public void load(CompoundTag tag) { storagePositions = NBTHelper.getCollection(tag, "storagePositions", Tag.TAG_LONG, t -> Optional.of(BlockPos.of(((LongTag) t).getAsLong())), ArrayList::new).orElseGet(ArrayList::new); connectingBlocks = NBTHelper.getCollection(tag, "connectingBlocks", Tag.TAG_LONG, t -> Optional.of(BlockPos.of(((LongTag) t).getAsLong())), LinkedHashSet::new).orElseGet(LinkedHashSet::new); + nonConnectingBlocks = NBTHelper.getCollection(tag, "nonConnectingBlocks", Tag.TAG_LONG, t -> Optional.of(BlockPos.of(((LongTag) t).getAsLong())), LinkedHashSet::new).orElseGet(LinkedHashSet::new); baseIndexes = NBTHelper.getCollection(tag, "baseIndexes", Tag.TAG_INT, t -> Optional.of(((IntTag) t).getAsInt()), ArrayList::new).orElseGet(ArrayList::new); totalSlots = tag.getInt("totalSlots"); linkedBlocks = NBTHelper.getCollection(tag, "linkedBlocks", Tag.TAG_LONG, t -> Optional.of(BlockPos.of(((LongTag) t).getAsLong())), LinkedHashSet::new).orElseGet(LinkedHashSet::new); diff --git a/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllableStorage.java b/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllableStorage.java index 4b9938c5..68a141b6 100644 --- a/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllableStorage.java +++ b/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllableStorage.java @@ -1,7 +1,6 @@ package net.p3pp3rf1y.sophisticatedcore.controller; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.p3pp3rf1y.sophisticatedcore.api.IStorageWrapper; import net.p3pp3rf1y.sophisticatedcore.settings.memory.MemorySettingsCategory; @@ -11,16 +10,11 @@ public interface IControllableStorage extends IControllerBoundable { IStorageWrapper getStorageWrapper(); - default boolean canBeConnected() { - return getControllerPos().isEmpty(); - } - - default boolean hasStorageData() { + default boolean canConnectStorages() { return true; } - @Override - default boolean canConnectStorages() { + default boolean hasStorageData() { return true; } @@ -36,28 +30,8 @@ default void removeFromController() { } } - private void addToAdjacentController() { - Level level = getStorageBlockLevel(); - if (!level.isClientSide()) { - BlockPos pos = getStorageBlockPos(); - for (Direction dir : Direction.values()) { - BlockPos offsetPos = pos.offset(dir.getNormal()); - WorldHelper.getBlockEntity(level, offsetPos, IControllerBoundable.class).ifPresentOrElse( - s -> { - if (s.canConnectStorages()) { - s.getControllerPos().ifPresent(controllerPos -> addToController(level, pos, controllerPos)); - } - }, - () -> addToController(level, pos, offsetPos) - ); - if (getControllerPos().isPresent()) { - break; - } - } - } - } - - private void addToController(Level level, BlockPos pos, BlockPos controllerPos) { + @Override + default void addToController(Level level, BlockPos pos, BlockPos controllerPos) { WorldHelper.getBlockEntity(level, controllerPos, ControllerBlockEntityBase.class).ifPresent(c -> c.addStorage(pos)); } diff --git a/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllerBoundable.java b/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllerBoundable.java index 885ff954..037658d8 100644 --- a/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllerBoundable.java +++ b/src/main/java/net/p3pp3rf1y/sophisticatedcore/controller/IControllerBoundable.java @@ -1,6 +1,7 @@ package net.p3pp3rf1y.sophisticatedcore.controller; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; import net.p3pp3rf1y.sophisticatedcore.util.NBTHelper; @@ -22,6 +23,13 @@ public interface IControllerBoundable { Level getStorageBlockLevel(); + default boolean canBeConnected() { + return getControllerPos().isEmpty(); + } + + void registerController(ControllerBlockEntityBase controllerBlockEntity); + void unregisterController(); + boolean canConnectStorages(); default void runOnController(Level level, Consumer toRun) { @@ -38,4 +46,29 @@ default void loadControllerPos(CompoundTag tag) { setControllerPos(controllerPos); }); } + + default void addToController(Level level, BlockPos pos, BlockPos controllerPos) { + //noop by default + } + + default void addToAdjacentController() { + Level level = getStorageBlockLevel(); + if (!level.isClientSide()) { + BlockPos pos = getStorageBlockPos(); + for (Direction dir : Direction.values()) { + BlockPos offsetPos = pos.offset(dir.getNormal()); + WorldHelper.getBlockEntity(level, offsetPos, IControllerBoundable.class).ifPresentOrElse( + s -> { + if (s.canConnectStorages()) { + s.getControllerPos().ifPresent(controllerPos -> addToController(level, pos, controllerPos)); + } + }, + () -> addToController(level, pos, offsetPos) + ); + if (getControllerPos().isPresent()) { + break; + } + } + } + } }