diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java index 43e4b3ff..b030b433 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java @@ -71,24 +71,14 @@ public abstract class AbstractContainerMenuMixin implements ContainerBridge { public boolean checkReachable = true; private InventoryView bukkitView; - private long bukkitViewHash = 0; public InventoryView getBukkitView() { - if (bukkitView != null && bukkitViewHash != bukkitViewHash()) { - ArclightContainer.updateView((AbstractContainerMenu) (Object) this, bukkitView); - bukkitViewHash = bukkitViewHash(); - } if (bukkitView == null) { bukkitView = ArclightContainer.createInvView((AbstractContainerMenu) (Object) this); - bukkitViewHash = bukkitViewHash(); } return bukkitView; } - private long bukkitViewHash() { - return (((long) this.slots.size()) << 32) | System.identityHashCode(this.slots); - } - public void transferTo(AbstractContainerMenu other, CraftHumanEntity player) { InventoryView source = this.getBukkitView(); InventoryView destination = ((ContainerBridge) other).bridge$getBukkitView(); @@ -100,7 +90,7 @@ public abstract class AbstractContainerMenuMixin implements ContainerBridge { private Component title; - public final Component getTitle() { + public Component getTitle() { if (this.title == null) { if (this.menuType != null && this.menuType.getRegistryName() != null) { return new TextComponent(this.menuType.getRegistryName().toString()); @@ -111,7 +101,7 @@ public abstract class AbstractContainerMenuMixin implements ContainerBridge { return this.title; } - public final void setTitle(Component title) { + public void setTitle(Component title) { if (this.title == null) { if (title == null) { this.title = getTitle(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/ArclightContainer.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/ArclightContainer.java index e4cb4fee..00a95456 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/ArclightContainer.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/ArclightContainer.java @@ -1,25 +1,15 @@ package io.izzel.arclight.common.mod.server; -import io.izzel.arclight.api.Unsafe; import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.core.inventory.container.PosContainerBridge; -import io.izzel.arclight.common.mod.ArclightMod; import io.izzel.arclight.common.mod.util.ArclightCaptures; -import io.izzel.tools.product.Product; -import io.izzel.tools.product.Product2; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.SlotItemHandler; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; -import net.minecraftforge.items.wrapper.InvWrapper; -import net.minecraftforge.items.wrapper.RangedWrapper; import org.bukkit.Location; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.inventory.CraftInventory; @@ -30,127 +20,34 @@ import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; -import java.util.ListIterator; public class ArclightContainer { - private static final long HANDLERS_OFFSET; - private static final long COMPOSE_OFFSET; - - static { - try { - Unsafe.ensureClassInitialized(CombinedInvWrapper.class); - Field itemHandler = CombinedInvWrapper.class.getDeclaredField("itemHandler"); - HANDLERS_OFFSET = Unsafe.objectFieldOffset(itemHandler); - Unsafe.ensureClassInitialized(RangedWrapper.class); - Field compose = RangedWrapper.class.getDeclaredField("compose"); - COMPOSE_OFFSET = Unsafe.objectFieldOffset(compose); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - - private static Container getActualInventoryForSlot(Slot slot) { - if (slot instanceof SlotItemHandler) { - return getInventoryFromWrapper(((SlotItemHandler) slot).getItemHandler()); - } else { - return slot.container; - } - } - - private static Container getInventoryFromWrapper(IItemHandler handler) { - if (handler instanceof CombinedInvWrapper) { - IItemHandlerModifiable[] handlers = ((IItemHandlerModifiable[]) Unsafe.getObject(handler, HANDLERS_OFFSET)); - Container last = null; - for (IItemHandlerModifiable modifiable : handlers) { - Container inventory = getInventoryFromWrapper(modifiable); - if (inventory instanceof net.minecraft.world.entity.player.Inventory) { - return inventory; - } else { - last = inventory; - } - } - return last; - } else if (handler instanceof InvWrapper) { - return ((InvWrapper) handler).getInv(); - } else if (handler instanceof RangedWrapper) { - return getInventoryFromWrapper(((IItemHandler) Unsafe.getObject(handler, COMPOSE_OFFSET))); - } else { - return null; - } - } - + /* + * Treat all modded containers not having a "bottom" inventory. + */ public static InventoryView createInvView(AbstractContainerMenu container) { - Product2 containerInfo = getContainerInfo(container); - Inventory viewing = new CraftInventory(new ContainerInvWrapper(container, containerInfo._2, containerInfo._1)); - return new CraftInventoryView(((PlayerEntityBridge) containerInfo._1).bridge$getBukkitEntity(), viewing, container); - } - - public static void updateView(AbstractContainerMenu container, InventoryView inventoryView) { - Inventory topInventory = inventoryView.getTopInventory(); - if (topInventory instanceof CraftInventory) { - Container inventory = ((CraftInventory) topInventory).getInventory(); - if (inventory instanceof ContainerInvWrapper) { - Product2 containerInfo = getContainerInfo(container); - ((ContainerInvWrapper) inventory).setOwner(((PlayerEntityBridge) containerInfo._1).bridge$getBukkitEntity()); - ((ContainerInvWrapper) inventory).setSize(containerInfo._2); - } - } - } - - // todo check this - private static Product2 getContainerInfo(AbstractContainerMenu container) { - Player candidate = ArclightCaptures.getContainerOwner(); - int bottomBegin = -1, bottomEnd = -1; - for (ListIterator iterator = container.slots.listIterator(); iterator.hasNext(); ) { - Slot slot = iterator.next(); - Container inventory = getActualInventoryForSlot(slot); - if (inventory instanceof net.minecraft.world.entity.player.Inventory) { - if (candidate != null && ((net.minecraft.world.entity.player.Inventory) inventory).player != candidate) { - ArclightMod.LOGGER.warn("Multiple player found in {}/{}, previous {}, new {}", container, container.getClass(), candidate, ((net.minecraft.world.entity.player.Inventory) inventory).player); - } - candidate = ((net.minecraft.world.entity.player.Inventory) inventory).player; - if (bottomBegin == -1 || bottomBegin < bottomEnd) { - bottomBegin = iterator.previousIndex(); - } - } else { - if (bottomEnd < bottomBegin) { - bottomEnd = iterator.previousIndex(); - } - } - } - if (candidate == null) { - throw new RuntimeException("candidate cannot be null, " + container + "/" + container.getClass()); - } - if (bottomBegin < bottomEnd || bottomBegin == -1) { - bottomBegin = container.slots.size(); - } - return Product.of(candidate, bottomBegin); + var containerOwner = ArclightCaptures.getContainerOwner(); + Inventory viewing = new CraftInventory(new ContainerInvWrapper(container, containerOwner)); + return new CraftInventoryView(((PlayerEntityBridge) containerOwner).bridge$getBukkitEntity(), viewing, container); } private static class ContainerInvWrapper implements Container, IInventoryBridge { private final AbstractContainerMenu container; - private int size; private InventoryHolder owner; private final List viewers = new ArrayList<>(); - public ContainerInvWrapper(AbstractContainerMenu container, int size, Player owner) { + public ContainerInvWrapper(AbstractContainerMenu container, Player owner) { this.container = container; - this.size = size; this.owner = ((PlayerEntityBridge) owner).bridge$getBukkitEntity(); } - public void setSize(int size) { - this.size = size; - } - @Override public int getContainerSize() { - return size; + return this.container.lastSlots.size(); } @Override @@ -163,31 +60,31 @@ public class ArclightContainer { @Override public @NotNull ItemStack getItem(int index) { - if (index >= size) return ItemStack.EMPTY; + if (index >= getContainerSize()) return ItemStack.EMPTY; return container.getSlot(index).getItem(); } @Override public @NotNull ItemStack removeItem(int index, int count) { - if (index >= size) return ItemStack.EMPTY; + if (index >= getContainerSize()) return ItemStack.EMPTY; return container.getSlot(index).remove(count); } @Override public @NotNull ItemStack removeItemNoUpdate(int index) { - if (index >= size) return ItemStack.EMPTY; + if (index >= getContainerSize()) return ItemStack.EMPTY; return container.getSlot(index).remove(Integer.MAX_VALUE); } @Override public void setItem(int index, @NotNull ItemStack stack) { - if (index >= size) return; + if (index >= getContainerSize()) return; container.getSlot(index).set(stack); } @Override public int getMaxStackSize() { - if (size <= 0) return 0; + if (getContainerSize() <= 0) return 0; return container.getSlot(0).getMaxStackSize(); } @@ -210,7 +107,7 @@ public class ArclightContainer { @Override public List getContents() { container.broadcastChanges(); - return container.lastSlots.subList(0, size); + return container.lastSlots.subList(0, getContainerSize()); } @Override