Find players from forge wrapper classes
This commit is contained in:
parent
6c8d6d832a
commit
401a290c68
|
@ -4,11 +4,13 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import io.izzel.arclight.common.bridge.block.FireBlockBridge;
|
import io.izzel.arclight.common.bridge.block.FireBlockBridge;
|
||||||
import io.izzel.arclight.common.bridge.bukkit.MaterialBridge;
|
import io.izzel.arclight.common.bridge.bukkit.MaterialBridge;
|
||||||
import io.izzel.arclight.common.mod.ArclightMod;
|
import io.izzel.arclight.common.mod.ArclightMod;
|
||||||
|
import io.izzel.arclight.common.mod.server.block.ArclightTileInventory;
|
||||||
import io.izzel.arclight.i18n.LocalizedException;
|
import io.izzel.arclight.i18n.LocalizedException;
|
||||||
import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
|
import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.FallingBlock;
|
import net.minecraft.block.FallingBlock;
|
||||||
|
import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
@ -334,6 +336,7 @@ public abstract class MaterialMixin implements MaterialBridge {
|
||||||
this.setupBlockStateFunc();
|
this.setupBlockStateFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
private void setupBlockStateFunc() {
|
private void setupBlockStateFunc() {
|
||||||
if (arclight$spec.blockStateClass != null) {
|
if (arclight$spec.blockStateClass != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -368,6 +371,9 @@ public abstract class MaterialMixin implements MaterialBridge {
|
||||||
if (this.arclight$stateFunc == null) {
|
if (this.arclight$stateFunc == null) {
|
||||||
this.arclight$stateFunc = b -> {
|
this.arclight$stateFunc = b -> {
|
||||||
TileEntity tileEntity = b.getCraftWorld().getHandle().getTileEntity(b.getPosition());
|
TileEntity tileEntity = b.getCraftWorld().getHandle().getTileEntity(b.getPosition());
|
||||||
|
if (tileEntity instanceof IInventory) {
|
||||||
|
return new ArclightTileInventory(b, tileEntity.getClass());
|
||||||
|
}
|
||||||
return tileEntity == null ? new CraftBlockState(b) : new CraftBlockEntityState<>(b, tileEntity.getClass());
|
return tileEntity == null ? new CraftBlockState(b) : new CraftBlockEntityState<>(b, tileEntity.getClass());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
package io.izzel.arclight.common.mixin.core.inventory.container;
|
package io.izzel.arclight.common.mixin.core.inventory.container;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
|
|
||||||
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
|
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
|
||||||
import io.izzel.arclight.common.bridge.inventory.container.ContainerBridge;
|
import io.izzel.arclight.common.bridge.inventory.container.ContainerBridge;
|
||||||
import io.izzel.arclight.common.bridge.inventory.container.SlotBridge;
|
import io.izzel.arclight.common.bridge.inventory.container.SlotBridge;
|
||||||
import io.izzel.arclight.common.mod.ArclightMod;
|
import io.izzel.arclight.common.mod.ArclightMod;
|
||||||
import io.izzel.arclight.common.mod.util.ArclightCaptures;
|
import io.izzel.arclight.common.mod.server.ArclightContainer;
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.inventory.CraftResultInventory;
|
|
||||||
import net.minecraft.inventory.IInventory;
|
|
||||||
import net.minecraft.inventory.container.ClickType;
|
import net.minecraft.inventory.container.ClickType;
|
||||||
import net.minecraft.inventory.container.Container;
|
import net.minecraft.inventory.container.Container;
|
||||||
import net.minecraft.inventory.container.ContainerType;
|
import net.minecraft.inventory.container.ContainerType;
|
||||||
|
@ -25,13 +22,10 @@ import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
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;
|
||||||
import org.bukkit.craftbukkit.v.inventory.CraftInventoryCustom;
|
|
||||||
import org.bukkit.craftbukkit.v.inventory.CraftInventoryView;
|
|
||||||
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||||
import org.bukkit.event.inventory.InventoryType;
|
import org.bukkit.event.inventory.InventoryType;
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.InventoryView;
|
import org.bukkit.inventory.InventoryView;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
@ -42,7 +36,6 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -75,54 +68,9 @@ public abstract class ContainerMixin implements ContainerBridge {
|
||||||
public boolean checkReachable = true;
|
public boolean checkReachable = true;
|
||||||
private InventoryView bukkitView;
|
private InventoryView bukkitView;
|
||||||
|
|
||||||
// todo check this
|
|
||||||
public InventoryView getBukkitView() {
|
public InventoryView getBukkitView() {
|
||||||
if (bukkitView == null) {
|
if (bukkitView == null) {
|
||||||
PlayerEntity candidate = null;
|
bukkitView = ArclightContainer.createInvView((Container) (Object) this);
|
||||||
Set<IInventory> set = new HashSet<>();
|
|
||||||
for (Slot slot : this.inventorySlots) {
|
|
||||||
if (slot.inventory != null) {
|
|
||||||
if (slot.inventory instanceof PlayerInventory) {
|
|
||||||
if (candidate != null && ((PlayerInventory) slot.inventory).player != candidate) {
|
|
||||||
ArclightMod.LOGGER.warn("Duplicate PlayerInventory inside {}, previous {}, new {}", this, candidate, slot.inventory);
|
|
||||||
}
|
|
||||||
candidate = ((PlayerInventory) slot.inventory).player;
|
|
||||||
} else {
|
|
||||||
set.add(slot.inventory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (candidate == null) {
|
|
||||||
if (ArclightCaptures.getContainerOwner() != null) {
|
|
||||||
candidate = ArclightCaptures.getContainerOwner();
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("candidate cannot be null");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CraftResultInventory resultCandidate = null;
|
|
||||||
IInventory mainCandidate = null;
|
|
||||||
for (IInventory inventory : set) {
|
|
||||||
if (inventory instanceof CraftResultInventory) {
|
|
||||||
resultCandidate = (CraftResultInventory) inventory;
|
|
||||||
} else {
|
|
||||||
mainCandidate = inventory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Inventory inv;
|
|
||||||
if (mainCandidate == null && resultCandidate != null) {
|
|
||||||
mainCandidate = resultCandidate;
|
|
||||||
resultCandidate = null;
|
|
||||||
}
|
|
||||||
if (mainCandidate != null) {
|
|
||||||
if (resultCandidate != null) {
|
|
||||||
inv = new org.bukkit.craftbukkit.v.inventory.CraftResultInventory(mainCandidate, resultCandidate);
|
|
||||||
} else {
|
|
||||||
inv = new CraftInventory(mainCandidate);
|
|
||||||
}
|
|
||||||
} else { // container has no slots
|
|
||||||
inv = new CraftInventoryCustom(((PlayerEntityBridge) candidate).bridge$getBukkitEntity(), 0);
|
|
||||||
}
|
|
||||||
bukkitView = new CraftInventoryView(((PlayerEntityBridge) candidate).bridge$getBukkitEntity(), inv, (Container) (Object) this);
|
|
||||||
}
|
}
|
||||||
return bukkitView;
|
return bukkitView;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
package io.izzel.arclight.common.mod.server;
|
||||||
|
|
||||||
|
import io.izzel.arclight.api.Unsafe;
|
||||||
|
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
|
||||||
|
import io.izzel.arclight.common.mod.ArclightMod;
|
||||||
|
import io.izzel.arclight.common.mod.util.ArclightCaptures;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.inventory.CraftResultInventory;
|
||||||
|
import net.minecraft.inventory.IInventory;
|
||||||
|
import net.minecraft.inventory.container.Container;
|
||||||
|
import net.minecraft.inventory.container.Slot;
|
||||||
|
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.craftbukkit.v.inventory.CraftInventory;
|
||||||
|
import org.bukkit.craftbukkit.v.inventory.CraftInventoryCustom;
|
||||||
|
import org.bukkit.craftbukkit.v.inventory.CraftInventoryView;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryView;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
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 IInventory getActualInventoryForSlot(Slot slot) {
|
||||||
|
if (slot instanceof SlotItemHandler) {
|
||||||
|
return getInventoryFromWrapper(((SlotItemHandler) slot).getItemHandler());
|
||||||
|
} else {
|
||||||
|
return slot.inventory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IInventory getInventoryFromWrapper(IItemHandler handler) {
|
||||||
|
if (handler instanceof CombinedInvWrapper) {
|
||||||
|
IItemHandlerModifiable[] handlers = ((IItemHandlerModifiable[]) Unsafe.getObject(handler, HANDLERS_OFFSET));
|
||||||
|
IInventory last = null;
|
||||||
|
for (IItemHandlerModifiable modifiable : handlers) {
|
||||||
|
IInventory inventory = getInventoryFromWrapper(modifiable);
|
||||||
|
if (inventory instanceof PlayerInventory) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo check this
|
||||||
|
public static InventoryView createInvView(Container container) {
|
||||||
|
PlayerEntity candidate = null;
|
||||||
|
Set<IInventory> set = new HashSet<>();
|
||||||
|
for (Slot slot : container.inventorySlots) {
|
||||||
|
IInventory inventory = getActualInventoryForSlot(slot);
|
||||||
|
if (inventory != null) {
|
||||||
|
if (inventory instanceof PlayerInventory) {
|
||||||
|
if (candidate != null && ((PlayerInventory) inventory).player != candidate) {
|
||||||
|
ArclightMod.LOGGER.warn("Multiple player found in {}/{}, previous {}, new {}", container, container.getClass(), candidate, ((PlayerInventory) inventory).player);
|
||||||
|
}
|
||||||
|
candidate = ((PlayerInventory) inventory).player;
|
||||||
|
}
|
||||||
|
set.add(inventory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (candidate == null) {
|
||||||
|
if (ArclightCaptures.getContainerOwner() != null) {
|
||||||
|
candidate = ArclightCaptures.getContainerOwner();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("candidate cannot be null, " + container + "/" + container.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CraftResultInventory resultCandidate = null;
|
||||||
|
IInventory mainCandidate = null;
|
||||||
|
for (IInventory inventory : set) {
|
||||||
|
if (inventory instanceof CraftResultInventory) {
|
||||||
|
resultCandidate = (CraftResultInventory) inventory;
|
||||||
|
} else {
|
||||||
|
mainCandidate = inventory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Inventory inv;
|
||||||
|
if (mainCandidate == null && resultCandidate != null) {
|
||||||
|
mainCandidate = resultCandidate;
|
||||||
|
resultCandidate = null;
|
||||||
|
}
|
||||||
|
if (mainCandidate != null) {
|
||||||
|
if (resultCandidate != null) {
|
||||||
|
inv = new org.bukkit.craftbukkit.v.inventory.CraftResultInventory(mainCandidate, resultCandidate);
|
||||||
|
} else {
|
||||||
|
inv = new CraftInventory(mainCandidate);
|
||||||
|
}
|
||||||
|
} else { // container has no slots
|
||||||
|
inv = new CraftInventoryCustom(((PlayerEntityBridge) candidate).bridge$getBukkitEntity(), 0);
|
||||||
|
}
|
||||||
|
return new CraftInventoryView(((PlayerEntityBridge) candidate).bridge$getBukkitEntity(), inv, container);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package io.izzel.arclight.common.mod.server.block;
|
||||||
|
|
||||||
|
import net.minecraft.inventory.IInventory;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.craftbukkit.v.block.CraftBlockEntityState;
|
||||||
|
import org.bukkit.craftbukkit.v.inventory.CraftInventory;
|
||||||
|
import org.bukkit.inventory.BlockInventoryHolder;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ArclightTileInventory<T extends TileEntity & IInventory> extends CraftBlockEntityState<T> implements BlockInventoryHolder {
|
||||||
|
|
||||||
|
public ArclightTileInventory(Block block, Class<T> tileEntityClass) {
|
||||||
|
super(block, tileEntityClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Inventory getInventory() {
|
||||||
|
return new CraftInventory(this.getTileEntity());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user