From dd01bf7bc72967b831ab16cc8b6defc7b5191300 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Tue, 19 Sep 2023 11:43:51 -0700 Subject: [PATCH] Fix mixin conflict for fabric transfer api in hopper optimisations The mixin targetted the getSourceContainer invocation, which failed when the method was overwritten. Move the optimisations to use one redirect and one inject, which don't appear to affect the performance. --- .../mixin/explosions/ExplosionMixin.java | 2 +- .../mixin/hopper/HopperBlockEntityMixin.java | 99 +++++++++++++------ 2 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/explosions/ExplosionMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/explosions/ExplosionMixin.java index a9326cb..cc6288c 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/explosions/ExplosionMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/explosions/ExplosionMixin.java @@ -350,7 +350,7 @@ public abstract class ExplosionMixin { public void explode() { this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z)); - this.blockCache = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); + this.blockCache = new Long2ObjectOpenHashMap<>(); this.chunkPosCache = new long[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH]; Arrays.fill(this.chunkPosCache, ChunkPos.INVALID_CHUNK_POS); diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/hopper/HopperBlockEntityMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/hopper/HopperBlockEntityMixin.java index 6d7e9ea..2a4aed1 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/hopper/HopperBlockEntityMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/hopper/HopperBlockEntityMixin.java @@ -30,6 +30,11 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.List; import java.util.function.BooleanSupplier; @@ -130,46 +135,57 @@ public abstract class HopperBlockEntityMixin extends RandomizableContainerBlockE }); } + /** + * @reason Forces a return false when container is not null so that the below mixin can inject its own return logic. + * @author Spottedleaf + */ + @Redirect( + method = "suckInItems", + at = @At( + target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;isEmptyContainer(Lnet/minecraft/world/Container;Lnet/minecraft/core/Direction;)Z", + value = "INVOKE" + ) + ) + private static boolean forceReturnFalseForContainer(final Container container, final Direction direction) { + return true; + } + /** * @reason Avoid checking for empty container and remove streams / indirection * @author Spottedleaf */ - @Overwrite - public static boolean suckInItems(final Level level, final Hopper hopper) { - final Container aboveContainer = getSourceContainer(level, hopper); - if (aboveContainer != null) { - final Direction down = Direction.DOWN; + @Inject( + method = "suckInItems", + cancellable = true, + locals = LocalCapture.CAPTURE_FAILHARD, + at = @At( + value = "RETURN", + ordinal = 0 + ) + ) + private static void handleContainerSuck(final Level level, final Hopper hopper, final CallbackInfoReturnable cir, + final Container aboveContainer) { + final Direction down = Direction.DOWN; + // don't bother checking for empty, because the same logic can be done by trying to move items - as + // that checks for an empty item. - // don't bother checking for empty, because the same logic can be done by trying to move items - as - // that checks for an empty item. - - if (aboveContainer instanceof WorldlyContainer worldlyContainer) { - for (final int slot : worldlyContainer.getSlotsForFace(down)) { - if (tryTakeInItemFromSlot(hopper, aboveContainer, slot, down)) { - return true; - } + if (aboveContainer instanceof WorldlyContainer worldlyContainer) { + for (final int slot : worldlyContainer.getSlotsForFace(down)) { + if (tryTakeInItemFromSlot(hopper, aboveContainer, slot, down)) { + cir.setReturnValue(Boolean.TRUE); + return; } - return false; - } else { - for (int slot = 0, max = aboveContainer.getContainerSize(); slot < max; ++slot) { - if (tryTakeInItemFromSlot(hopper, aboveContainer, slot, down)) { - return true; - } - } - return false; } - } else { - final List items = getItemsAtAndAbove(level, hopper); - - for (int i = 0, len = items.size(); i < len; ++i) { - if (addItem(hopper, items.get(i))) { - return true; + for (int slot = 0, max = aboveContainer.getContainerSize(); slot < max; ++slot) { + if (tryTakeInItemFromSlot(hopper, aboveContainer, slot, down)) { + cir.setReturnValue(Boolean.TRUE); + return; } } - - return false; } + cir.setReturnValue(Boolean.FALSE); + return; } /** @@ -315,4 +331,29 @@ public abstract class HopperBlockEntityMixin extends RandomizableContainerBlockE return true; } } + + /** + * @reason Remove streams + * @author Spottedleaf + */ + @Overwrite + private static boolean isEmptyContainer(final Container container, final Direction direction) { + if (container instanceof WorldlyContainer worldlyContainer) { + for (final int slot : worldlyContainer.getSlotsForFace(direction)) { + final ItemStack stack = container.getItem(slot); + if (!stack.isEmpty()) { + return false; + } + } + return true; + } else { + for (int slot = 0, max = container.getContainerSize(); slot < max; ++slot) { + final ItemStack stack = container.getItem(slot); + if (!stack.isEmpty()) { + return false; + } + } + return true; + } + } }