Port 1.16 container changes (#466)
This commit is contained in:
parent
d008a1e8a6
commit
8f90a71b29
@ -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();
|
||||
|
||||
@ -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<Player, Integer> 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<Player, Integer> containerInfo = getContainerInfo(container);
|
||||
((ContainerInvWrapper) inventory).setOwner(((PlayerEntityBridge) containerInfo._1).bridge$getBukkitEntity());
|
||||
((ContainerInvWrapper) inventory).setSize(containerInfo._2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo check this
|
||||
private static Product2<Player, Integer> getContainerInfo(AbstractContainerMenu container) {
|
||||
Player candidate = ArclightCaptures.getContainerOwner();
|
||||
int bottomBegin = -1, bottomEnd = -1;
|
||||
for (ListIterator<Slot> 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<HumanEntity> 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<ItemStack> getContents() {
|
||||
container.broadcastChanges();
|
||||
return container.lastSlots.subList(0, size);
|
||||
return container.lastSlots.subList(0, getContainerSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
Reference in New Issue
Block a user