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.
This commit is contained in:
Spottedleaf
2023-09-19 11:43:51 -07:00
parent 2b63a849d3
commit dd01bf7bc7
2 changed files with 71 additions and 30 deletions

View File

@@ -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);

View File

@@ -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<Boolean> 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<ItemEntity> 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;
}
}
}