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;
|
public boolean checkReachable = true;
|
||||||
private InventoryView bukkitView;
|
private InventoryView bukkitView;
|
||||||
private long bukkitViewHash = 0;
|
|
||||||
|
|
||||||
public InventoryView getBukkitView() {
|
public InventoryView getBukkitView() {
|
||||||
if (bukkitView != null && bukkitViewHash != bukkitViewHash()) {
|
|
||||||
ArclightContainer.updateView((AbstractContainerMenu) (Object) this, bukkitView);
|
|
||||||
bukkitViewHash = bukkitViewHash();
|
|
||||||
}
|
|
||||||
if (bukkitView == null) {
|
if (bukkitView == null) {
|
||||||
bukkitView = ArclightContainer.createInvView((AbstractContainerMenu) (Object) this);
|
bukkitView = ArclightContainer.createInvView((AbstractContainerMenu) (Object) this);
|
||||||
bukkitViewHash = bukkitViewHash();
|
|
||||||
}
|
}
|
||||||
return bukkitView;
|
return bukkitView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long bukkitViewHash() {
|
|
||||||
return (((long) this.slots.size()) << 32) | System.identityHashCode(this.slots);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void transferTo(AbstractContainerMenu other, CraftHumanEntity player) {
|
public void transferTo(AbstractContainerMenu other, CraftHumanEntity player) {
|
||||||
InventoryView source = this.getBukkitView();
|
InventoryView source = this.getBukkitView();
|
||||||
InventoryView destination = ((ContainerBridge) other).bridge$getBukkitView();
|
InventoryView destination = ((ContainerBridge) other).bridge$getBukkitView();
|
||||||
@ -100,7 +90,7 @@ public abstract class AbstractContainerMenuMixin implements ContainerBridge {
|
|||||||
|
|
||||||
private Component title;
|
private Component title;
|
||||||
|
|
||||||
public final Component getTitle() {
|
public Component getTitle() {
|
||||||
if (this.title == null) {
|
if (this.title == null) {
|
||||||
if (this.menuType != null && this.menuType.getRegistryName() != null) {
|
if (this.menuType != null && this.menuType.getRegistryName() != null) {
|
||||||
return new TextComponent(this.menuType.getRegistryName().toString());
|
return new TextComponent(this.menuType.getRegistryName().toString());
|
||||||
@ -111,7 +101,7 @@ public abstract class AbstractContainerMenuMixin implements ContainerBridge {
|
|||||||
return this.title;
|
return this.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setTitle(Component title) {
|
public void setTitle(Component title) {
|
||||||
if (this.title == null) {
|
if (this.title == null) {
|
||||||
if (title == null) {
|
if (title == null) {
|
||||||
this.title = getTitle();
|
this.title = getTitle();
|
||||||
|
|||||||
@ -1,25 +1,15 @@
|
|||||||
package io.izzel.arclight.common.mod.server;
|
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.entity.player.PlayerEntityBridge;
|
||||||
import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge;
|
import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge;
|
||||||
import io.izzel.arclight.common.bridge.core.inventory.container.PosContainerBridge;
|
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.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.Container;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
import net.minecraft.world.inventory.Slot;
|
import net.minecraft.world.inventory.Slot;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.Recipe;
|
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.Location;
|
||||||
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
|
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
|
||||||
import org.bukkit.craftbukkit.v.inventory.CraftInventory;
|
import org.bukkit.craftbukkit.v.inventory.CraftInventory;
|
||||||
@ -30,127 +20,34 @@ import org.bukkit.inventory.InventoryHolder;
|
|||||||
import org.bukkit.inventory.InventoryView;
|
import org.bukkit.inventory.InventoryView;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
|
||||||
|
|
||||||
public class ArclightContainer {
|
public class ArclightContainer {
|
||||||
|
|
||||||
private static final long HANDLERS_OFFSET;
|
/*
|
||||||
private static final long COMPOSE_OFFSET;
|
* Treat all modded containers not having a "bottom" inventory.
|
||||||
|
*/
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InventoryView createInvView(AbstractContainerMenu container) {
|
public static InventoryView createInvView(AbstractContainerMenu container) {
|
||||||
Product2<Player, Integer> containerInfo = getContainerInfo(container);
|
var containerOwner = ArclightCaptures.getContainerOwner();
|
||||||
Inventory viewing = new CraftInventory(new ContainerInvWrapper(container, containerInfo._2, containerInfo._1));
|
Inventory viewing = new CraftInventory(new ContainerInvWrapper(container, containerOwner));
|
||||||
return new CraftInventoryView(((PlayerEntityBridge) containerInfo._1).bridge$getBukkitEntity(), viewing, container);
|
return new CraftInventoryView(((PlayerEntityBridge) containerOwner).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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ContainerInvWrapper implements Container, IInventoryBridge {
|
private static class ContainerInvWrapper implements Container, IInventoryBridge {
|
||||||
|
|
||||||
private final AbstractContainerMenu container;
|
private final AbstractContainerMenu container;
|
||||||
private int size;
|
|
||||||
private InventoryHolder owner;
|
private InventoryHolder owner;
|
||||||
private final List<HumanEntity> viewers = new ArrayList<>();
|
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.container = container;
|
||||||
this.size = size;
|
|
||||||
this.owner = ((PlayerEntityBridge) owner).bridge$getBukkitEntity();
|
this.owner = ((PlayerEntityBridge) owner).bridge$getBukkitEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSize(int size) {
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getContainerSize() {
|
public int getContainerSize() {
|
||||||
return size;
|
return this.container.lastSlots.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -163,31 +60,31 @@ public class ArclightContainer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ItemStack getItem(int index) {
|
public @NotNull ItemStack getItem(int index) {
|
||||||
if (index >= size) return ItemStack.EMPTY;
|
if (index >= getContainerSize()) return ItemStack.EMPTY;
|
||||||
return container.getSlot(index).getItem();
|
return container.getSlot(index).getItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ItemStack removeItem(int index, int count) {
|
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);
|
return container.getSlot(index).remove(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ItemStack removeItemNoUpdate(int index) {
|
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);
|
return container.getSlot(index).remove(Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setItem(int index, @NotNull ItemStack stack) {
|
public void setItem(int index, @NotNull ItemStack stack) {
|
||||||
if (index >= size) return;
|
if (index >= getContainerSize()) return;
|
||||||
container.getSlot(index).set(stack);
|
container.getSlot(index).set(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxStackSize() {
|
public int getMaxStackSize() {
|
||||||
if (size <= 0) return 0;
|
if (getContainerSize() <= 0) return 0;
|
||||||
return container.getSlot(0).getMaxStackSize();
|
return container.getSlot(0).getMaxStackSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +107,7 @@ public class ArclightContainer {
|
|||||||
@Override
|
@Override
|
||||||
public List<ItemStack> getContents() {
|
public List<ItemStack> getContents() {
|
||||||
container.broadcastChanges();
|
container.broadcastChanges();
|
||||||
return container.lastSlots.subList(0, size);
|
return container.lastSlots.subList(0, getContainerSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user