diff --git a/main/src/main/java/net/citizensnpcs/Citizens.java b/main/src/main/java/net/citizensnpcs/Citizens.java index cdab43da2..efadae53e 100644 --- a/main/src/main/java/net/citizensnpcs/Citizens.java +++ b/main/src/main/java/net/citizensnpcs/Citizens.java @@ -15,6 +15,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.Plugin; @@ -84,6 +85,11 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { private Settings config; private boolean enabled; private final InventoryHelper inventoryHelper = new InventoryHelper() { + @Override + public InventoryView openAnvilInventory(Player player, Inventory inventory, String title) { + return NMS.openAnvilInventory(player, inventory, title); + } + @Override public void updateInventoryTitle(Player player, InventoryView view, String newTitle) { if (view.getTopInventory().getType() == InventoryType.CRAFTING diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index ff2c427fa..17c6d672b 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -20,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; @@ -454,6 +455,10 @@ public class NMS { BRIDGE.mount(entity, passenger); } + public static InventoryView openAnvilInventory(Player player, Inventory inventory, String title) { + return BRIDGE.openAnvilInventory(player, inventory, title); + } + public static void openHorseScreen(Tameable horse, Player equipper) { BRIDGE.openHorseScreen(horse, equipper); } diff --git a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java index aefe95b1a..6d2bb0e5c 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java +++ b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java @@ -15,6 +15,7 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; @@ -108,6 +109,8 @@ public interface NMSBridge { public void mount(Entity entity, Entity passenger); + InventoryView openAnvilInventory(Player player, Inventory anvil, String title); + public void openHorseScreen(Tameable horse, Player equipper); public void playAnimation(PlayerAnimation animation, Player player, int radius); diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java index 6bbf781af..c19f6330f 100644 --- a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java +++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java @@ -31,6 +31,8 @@ import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_10_R1.entity.CraftWither; import org.bukkit.craftbukkit.v1_10_R1.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.LivingEntity; @@ -40,6 +42,7 @@ import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -65,6 +68,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -163,7 +167,9 @@ import net.minecraft.server.v1_10_R1.Block; import net.minecraft.server.v1_10_R1.BlockPosition; import net.minecraft.server.v1_10_R1.BossBattleServer; import net.minecraft.server.v1_10_R1.ChatComponentText; +import net.minecraft.server.v1_10_R1.ChatMessage; import net.minecraft.server.v1_10_R1.Container; +import net.minecraft.server.v1_10_R1.ContainerAnvil; import net.minecraft.server.v1_10_R1.ControllerJump; import net.minecraft.server.v1_10_R1.ControllerMove; import net.minecraft.server.v1_10_R1.CrashReport; @@ -191,6 +197,7 @@ import net.minecraft.server.v1_10_R1.EntityTrackerEntry; import net.minecraft.server.v1_10_R1.EntityTypes; import net.minecraft.server.v1_10_R1.EntityWither; import net.minecraft.server.v1_10_R1.GenericAttributes; +import net.minecraft.server.v1_10_R1.IInventory; import net.minecraft.server.v1_10_R1.MathHelper; import net.minecraft.server.v1_10_R1.MinecraftKey; import net.minecraft.server.v1_10_R1.MobEffects; @@ -786,6 +793,52 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + final ContainerAnvil container = new ContainerAnvil(handle.inventory, handle.world, new BlockPosition(0, 0, 0), + handle) { + private CraftInventoryView bukkitEntity; + + @Override + public boolean a(EntityHuman entityhuman) { + return true; + } + + @Override + public void b(EntityHuman entityhuman) { + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + try { + this.bukkitEntity = new CraftInventoryView(player, + new CitizensInventoryAnvil(new Location(player.getWorld(), 0, 0, 0), + (IInventory) REPAIR_INVENTORY.invoke(this), + (IInventory) RESULT_INVENTORY.invoke(this), anvil), + this); + } catch (Throwable e) { + e.printStackTrace(); + return super.getBukkitView(); + } + return this.bukkitEntity; + } + } + }; + container.windowId = handle.nextContainerCounter(); + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection + .sendPacket(new PacketPlayOutOpenWindow(container.windowId, "minecraft:anvil", new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle((LivingEntity) horse); @@ -1208,6 +1261,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + Inventory wrapped) { + super(location, inventory, resultInventory); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1608,6 +1682,7 @@ public class NMSImpl implements NMSBridge { EntityType.HORSE, EntityType.GHAST); private static final Field CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getField(CraftBossBar.class, "handle"); + private static final float DEFAULT_SPEED = 1F; private static final Field ENDERDRAGON_BATTLE_BAR_FIELD = NMS.getField(EnderDragonBattle.class, "c"); private static final Field ENDERDRAGON_BATTLE_FIELD = NMS.getField(EntityEnderDragon.class, "bK"); @@ -1625,9 +1700,12 @@ public class NMSImpl implements NMSBridge { private static Field PATHFINDING_RANGE = NMS.getField(NavigationAbstract.class, "f"); private static final Field RABBIT_FIELD = NMS.getField(EntityRabbit.class, "bx"); private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle REPAIR_INVENTORY = NMS.getGetter(ContainerAnvil.class, "g"); + private static final MethodHandle RESULT_INVENTORY = NMS.getGetter(ContainerAnvil.class, "h"); private static Field SKULL_PROFILE_FIELD; private static MethodHandle TEAM_FIELD; private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c"); + private static final Field WITHER_BOSS_BAR_FIELD = NMS.getField(EntityWither.class, "bG"); static { diff --git a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java index e0691ce5e..c99e4759c 100644 --- a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java +++ b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java @@ -30,6 +30,8 @@ import org.bukkit.craftbukkit.v1_11_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_11_R1.entity.CraftWither; import org.bukkit.craftbukkit.v1_11_R1.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.LivingEntity; @@ -39,6 +41,7 @@ import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -64,6 +67,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -178,7 +182,9 @@ import net.minecraft.server.v1_11_R1.Block; import net.minecraft.server.v1_11_R1.BlockPosition; import net.minecraft.server.v1_11_R1.BossBattleServer; import net.minecraft.server.v1_11_R1.ChatComponentText; +import net.minecraft.server.v1_11_R1.ChatMessage; import net.minecraft.server.v1_11_R1.Container; +import net.minecraft.server.v1_11_R1.ContainerAnvil; import net.minecraft.server.v1_11_R1.ControllerJump; import net.minecraft.server.v1_11_R1.ControllerMove; import net.minecraft.server.v1_11_R1.CrashReport; @@ -209,6 +215,7 @@ import net.minecraft.server.v1_11_R1.EntityTypes; import net.minecraft.server.v1_11_R1.EntityWither; import net.minecraft.server.v1_11_R1.EnumMoveType; import net.minecraft.server.v1_11_R1.GenericAttributes; +import net.minecraft.server.v1_11_R1.IInventory; import net.minecraft.server.v1_11_R1.MathHelper; import net.minecraft.server.v1_11_R1.MinecraftKey; import net.minecraft.server.v1_11_R1.MobEffects; @@ -841,6 +848,52 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + final ContainerAnvil container = new ContainerAnvil(handle.inventory, handle.world, new BlockPosition(0, 0, 0), + handle) { + private CraftInventoryView bukkitEntity; + + @Override + public boolean a(EntityHuman entityhuman) { + return true; + } + + @Override + public void b(EntityHuman entityhuman) { + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + try { + this.bukkitEntity = new CraftInventoryView(player, + new CitizensInventoryAnvil(new Location(player.getWorld(), 0, 0, 0), + (IInventory) REPAIR_INVENTORY.invoke(this), + (IInventory) RESULT_INVENTORY.invoke(this), this, anvil), + this); + } catch (Throwable e) { + e.printStackTrace(); + return super.getBukkitView(); + } + return this.bukkitEntity; + } + } + }; + container.windowId = handle.nextContainerCounter(); + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection + .sendPacket(new PacketPlayOutOpenWindow(container.windowId, "minecraft:anvil", new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle((LivingEntity) horse); @@ -1272,6 +1325,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + ContainerAnvil container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1671,6 +1745,7 @@ public class NMSImpl implements NMSBridge { EntityType.HORSE, EntityType.GHAST); private static final Field CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getField(CraftBossBar.class, "handle"); + private static final float DEFAULT_SPEED = 1F; private static final Field ENDERDRAGON_BATTLE_BAR_FIELD = NMS.getField(EnderDragonBattle.class, "c"); private static final Field ENDERDRAGON_BATTLE_FIELD = NMS.getField(EntityEnderDragon.class, "bJ"); @@ -1687,9 +1762,12 @@ public class NMSImpl implements NMSBridge { private static Field PATHFINDING_RANGE = NMS.getField(NavigationAbstract.class, "f"); private static final Field RABBIT_FIELD = NMS.getField(EntityRabbit.class, "bw"); private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle REPAIR_INVENTORY = NMS.getGetter(ContainerAnvil.class, "g"); + private static final MethodHandle RESULT_INVENTORY = NMS.getGetter(ContainerAnvil.class, "h"); private static Field SKULL_PROFILE_FIELD; private static MethodHandle TEAM_FIELD; private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c"); + private static final Field WITHER_BOSS_BAR_FIELD = NMS.getField(EntityWither.class, "bF"); static { diff --git a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java index b36d7b542..84ed93738 100644 --- a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java +++ b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java @@ -30,6 +30,8 @@ import org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_12_R1.entity.CraftWither; import org.bukkit.craftbukkit.v1_12_R1.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.LivingEntity; @@ -39,6 +41,7 @@ import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -64,6 +67,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -181,7 +185,9 @@ import net.minecraft.server.v1_12_R1.Block; import net.minecraft.server.v1_12_R1.BlockPosition; import net.minecraft.server.v1_12_R1.BossBattleServer; import net.minecraft.server.v1_12_R1.ChatComponentText; +import net.minecraft.server.v1_12_R1.ChatMessage; import net.minecraft.server.v1_12_R1.Container; +import net.minecraft.server.v1_12_R1.ContainerAnvil; import net.minecraft.server.v1_12_R1.ControllerJump; import net.minecraft.server.v1_12_R1.ControllerMove; import net.minecraft.server.v1_12_R1.CrashReport; @@ -213,6 +219,7 @@ import net.minecraft.server.v1_12_R1.EntityTypes; import net.minecraft.server.v1_12_R1.EntityWither; import net.minecraft.server.v1_12_R1.EnumMoveType; import net.minecraft.server.v1_12_R1.GenericAttributes; +import net.minecraft.server.v1_12_R1.IInventory; import net.minecraft.server.v1_12_R1.MathHelper; import net.minecraft.server.v1_12_R1.MinecraftKey; import net.minecraft.server.v1_12_R1.MobEffects; @@ -849,6 +856,49 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + final ContainerAnvil container = new ContainerAnvil(handle.inventory, handle.world, new BlockPosition(0, 0, 0), + handle) { + private CraftInventoryView bukkitEntity; + + @Override + public void e() { + super.e(); + levelCost = 0; + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + try { + this.bukkitEntity = new CraftInventoryView(player, + new CitizensInventoryAnvil(new Location(player.getWorld(), 0, 0, 0), + (IInventory) REPAIR_INVENTORY.invoke(this), + (IInventory) RESULT_INVENTORY.invoke(this), this, anvil), + this); + } catch (Throwable e) { + e.printStackTrace(); + return super.getBukkitView(); + } + return this.bukkitEntity; + } + } + }; + container.windowId = handle.nextContainerCounter(); + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection + .sendPacket(new PacketPlayOutOpenWindow(container.windowId, "minecraft:anvil", new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle((LivingEntity) horse); @@ -1280,6 +1330,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + ContainerAnvil container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1655,7 +1726,7 @@ public class NMSImpl implements NMSBridge { public static void stopNavigation(NavigationAbstract navigation) { navigation.p(); - }; + } public static void updateAI(EntityLiving entity) { if (entity instanceof EntityInsentient) { @@ -1668,7 +1739,7 @@ public class NMSImpl implements NMSBridge { } else if (entity instanceof EntityHumanNPC) { ((EntityHumanNPC) entity).updateAI(); } - } + }; public static void updateNavigation(NavigationAbstract navigation) { navigation.d(); @@ -1679,6 +1750,7 @@ public class NMSImpl implements NMSBridge { private static final Set BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.SILVERFISH, EntityType.SHULKER, EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.MAGMA_CUBE, EntityType.HORSE, EntityType.GHAST); + private static final Field CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getField(CraftBossBar.class, "handle"); private static final float DEFAULT_SPEED = 1F; private static final Field ENDERDRAGON_BATTLE_BAR_FIELD = NMS.getField(EnderDragonBattle.class, "c"); @@ -1696,9 +1768,12 @@ public class NMSImpl implements NMSBridge { private static Field PATHFINDING_RANGE = NMS.getField(NavigationAbstract.class, "i"); private static final Field RABBIT_FIELD = NMS.getField(EntityRabbit.class, "bx"); private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle REPAIR_INVENTORY = NMS.getGetter(ContainerAnvil.class, "g"); + private static final MethodHandle RESULT_INVENTORY = NMS.getGetter(ContainerAnvil.class, "h"); private static Field SKULL_PROFILE_FIELD; private static MethodHandle TEAM_FIELD; private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c"); + private static final Field WITHER_BOSS_BAR_FIELD = NMS.getField(EntityWither.class, "bG"); static { diff --git a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java index e68295eff..64d63962e 100644 --- a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java +++ b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java @@ -32,6 +32,8 @@ import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity; import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_13_R2.entity.CraftWither; import org.bukkit.craftbukkit.v1_13_R2.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.LivingEntity; @@ -41,6 +43,7 @@ import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -66,6 +69,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -195,7 +199,9 @@ import net.minecraft.server.v1_13_R2.Block; import net.minecraft.server.v1_13_R2.BlockPosition; import net.minecraft.server.v1_13_R2.BossBattleServer; import net.minecraft.server.v1_13_R2.ChatComponentText; +import net.minecraft.server.v1_13_R2.ChatMessage; import net.minecraft.server.v1_13_R2.Container; +import net.minecraft.server.v1_13_R2.ContainerAnvil; import net.minecraft.server.v1_13_R2.ControllerJump; import net.minecraft.server.v1_13_R2.ControllerMove; import net.minecraft.server.v1_13_R2.CrashReport; @@ -230,6 +236,7 @@ import net.minecraft.server.v1_13_R2.EntityWither; import net.minecraft.server.v1_13_R2.EnumMoveType; import net.minecraft.server.v1_13_R2.GenericAttributes; import net.minecraft.server.v1_13_R2.IBlockData; +import net.minecraft.server.v1_13_R2.IInventory; import net.minecraft.server.v1_13_R2.IRegistry; import net.minecraft.server.v1_13_R2.MathHelper; import net.minecraft.server.v1_13_R2.MinecraftKey; @@ -884,6 +891,49 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + final ContainerAnvil container = new ContainerAnvil(handle.inventory, handle.world, new BlockPosition(0, 0, 0), + handle) { + private CraftInventoryView bukkitEntity; + + @Override + public void d() { + super.d(); + levelCost = 0; + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + try { + this.bukkitEntity = new CraftInventoryView(player, + new CitizensInventoryAnvil(new Location(player.getWorld(), 0, 0, 0), + (IInventory) REPAIR_INVENTORY.invoke(this), + (IInventory) RESULT_INVENTORY.invoke(this), this, anvil), + this); + } catch (Throwable e) { + e.printStackTrace(); + return super.getBukkitView(); + } + return this.bukkitEntity; + } + } + }; + container.windowId = handle.nextContainerCounter(); + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection + .sendPacket(new PacketPlayOutOpenWindow(container.windowId, "minecraft:anvil", new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle((LivingEntity) horse); @@ -1319,6 +1369,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + ContainerAnvil container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1812,8 +1883,11 @@ public class NMSImpl implements NMSBridge { private static final Method BLOCK_POSITION_B_D = NMS.getMethod(BlockPosition.PooledBlockPosition.class, "e", false, double.class, double.class, double.class); + private static final Field CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getField(CraftBossBar.class, "handle"); + private static final float DEFAULT_SPEED = 1F; + private static final Field ENDERDRAGON_BATTLE_BAR_FIELD = NMS.getField(EnderDragonBattle.class, "c", false); private static final Field ENDERDRAGON_BATTLE_FIELD = NMS.getField(EntityEnderDragon.class, "bR"); private static DataWatcherObject ENDERMAN_ANGRY; @@ -1831,6 +1905,8 @@ public class NMSImpl implements NMSBridge { private static Field PATHFINDING_RANGE = NMS.getField(NavigationAbstract.class, "p"); private static final Field RABBIT_FIELD = NMS.getField(EntityRabbit.class, "bC"); private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle REPAIR_INVENTORY = NMS.getGetter(ContainerAnvil.class, "repairInventory"); + private static final MethodHandle RESULT_INVENTORY = NMS.getGetter(ContainerAnvil.class, "resultInventory"); private static Field SKULL_PROFILE_FIELD; private static MethodHandle TEAM_FIELD; private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c"); diff --git a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java index 48959c342..fb6b45e99 100644 --- a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java +++ b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java @@ -33,6 +33,8 @@ import org.bukkit.craftbukkit.v1_14_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_14_R1.entity.CraftWither; import org.bukkit.craftbukkit.v1_14_R1.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.LivingEntity; @@ -41,6 +43,7 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -67,6 +70,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -209,8 +213,11 @@ import net.minecraft.server.v1_14_R1.Block; import net.minecraft.server.v1_14_R1.BlockPosition; import net.minecraft.server.v1_14_R1.BossBattleServer; import net.minecraft.server.v1_14_R1.ChatComponentText; +import net.minecraft.server.v1_14_R1.ChatMessage; import net.minecraft.server.v1_14_R1.ChunkProviderServer; import net.minecraft.server.v1_14_R1.Container; +import net.minecraft.server.v1_14_R1.ContainerAccess; +import net.minecraft.server.v1_14_R1.ContainerAnvil; import net.minecraft.server.v1_14_R1.ControllerJump; import net.minecraft.server.v1_14_R1.ControllerMove; import net.minecraft.server.v1_14_R1.CrashReport; @@ -248,6 +255,7 @@ import net.minecraft.server.v1_14_R1.EntityWither; import net.minecraft.server.v1_14_R1.EnumMoveType; import net.minecraft.server.v1_14_R1.GenericAttributes; import net.minecraft.server.v1_14_R1.IBlockData; +import net.minecraft.server.v1_14_R1.IInventory; import net.minecraft.server.v1_14_R1.IRegistry; import net.minecraft.server.v1_14_R1.MathHelper; import net.minecraft.server.v1_14_R1.MinecraftKey; @@ -951,6 +959,48 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + ContainerAccess access = ContainerAccess.at(handle.world, new BlockPosition(0, 0, 0)); + final ContainerAnvil container = new ContainerAnvil(handle.nextContainerCounter(), handle.inventory, access) { + private CraftInventoryView bukkitEntity; + + @Override + public void e() { + super.e(); + levelCost.set(0); + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + try { + this.bukkitEntity = new CraftInventoryView(player, + new CitizensInventoryAnvil(access.getLocation(), + (IInventory) REPAIR_INVENTORY.invoke(this), + (IInventory) RESULT_INVENTORY.invoke(this), this, anvil), + this); + } catch (Throwable e) { + e.printStackTrace(); + return super.getBukkitView(); + } + return this.bukkitEntity; + } + } + }; + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection.sendPacket( + new PacketPlayOutOpenWindow(container.windowId, container.getType(), new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle((LivingEntity) horse); @@ -1376,6 +1426,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + ContainerAnvil container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1905,6 +1976,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle BLOCK_POSITION_B_D = NMS.getMethodHandle(BlockPosition.PooledBlockPosition.class, "c", false, double.class, double.class, double.class); + private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity"); private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(PlayerChunkMap.class, "a", true, EntityPlayer.class, boolean.class); @@ -1944,9 +2016,12 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle PUFFERFISH_D = NMS.getSetter(EntityPufferFish.class, "d"); private static final MethodHandle RABBIT_FIELD = NMS.getGetter(EntityRabbit.class, "bz"); private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle REPAIR_INVENTORY = NMS.getGetter(ContainerAnvil.class, "repairInventory"); + private static final MethodHandle RESULT_INVENTORY = NMS.getGetter(ContainerAnvil.class, "resultInventory"); private static final MethodHandle SIZE_FIELD_GETTER = NMS.getGetter(Entity.class, "size"); private static final MethodHandle SIZE_FIELD_SETTER = NMS.getSetter(Entity.class, "size"); private static Field SKULL_PROFILE_FIELD; + private static MethodHandle TEAM_FIELD; static { diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java index 13f13c926..866890afe 100644 --- a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java @@ -33,6 +33,8 @@ import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftWither; import org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.LivingEntity; @@ -41,6 +43,7 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -67,6 +70,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -211,8 +215,11 @@ import net.minecraft.server.v1_15_R1.Block; import net.minecraft.server.v1_15_R1.BlockPosition; import net.minecraft.server.v1_15_R1.BossBattleServer; import net.minecraft.server.v1_15_R1.ChatComponentText; +import net.minecraft.server.v1_15_R1.ChatMessage; import net.minecraft.server.v1_15_R1.ChunkProviderServer; import net.minecraft.server.v1_15_R1.Container; +import net.minecraft.server.v1_15_R1.ContainerAccess; +import net.minecraft.server.v1_15_R1.ContainerAnvil; import net.minecraft.server.v1_15_R1.ControllerJump; import net.minecraft.server.v1_15_R1.ControllerMove; import net.minecraft.server.v1_15_R1.ControllerMoveFlying; @@ -252,6 +259,7 @@ import net.minecraft.server.v1_15_R1.EntityWither; import net.minecraft.server.v1_15_R1.EnumMoveType; import net.minecraft.server.v1_15_R1.GenericAttributes; import net.minecraft.server.v1_15_R1.IBlockData; +import net.minecraft.server.v1_15_R1.IInventory; import net.minecraft.server.v1_15_R1.IRegistry; import net.minecraft.server.v1_15_R1.MathHelper; import net.minecraft.server.v1_15_R1.MinecraftKey; @@ -963,6 +971,48 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + ContainerAccess access = ContainerAccess.at(handle.world, new BlockPosition(0, 0, 0)); + final ContainerAnvil container = new ContainerAnvil(handle.nextContainerCounter(), handle.inventory, access) { + private CraftInventoryView bukkitEntity; + + @Override + public void e() { + super.e(); + levelCost.set(0); + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + try { + this.bukkitEntity = new CraftInventoryView(player, + new CitizensInventoryAnvil(access.getLocation(), + (IInventory) REPAIR_INVENTORY.invoke(this), + (IInventory) RESULT_INVENTORY.invoke(this), this, anvil), + this); + } catch (Throwable e) { + e.printStackTrace(); + return super.getBukkitView(); + } + return this.bukkitEntity; + } + } + }; + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection.sendPacket( + new PacketPlayOutOpenWindow(container.windowId, container.getType(), new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle(horse); @@ -1415,6 +1465,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + ContainerAnvil container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1984,6 +2055,7 @@ public class NMSImpl implements NMSBridge { true, EntityPlayer.class, boolean.class); private static final Map, EntityTypes> CITIZENS_ENTITY_TYPES = Maps.newHashMap(); + private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getSetter(CraftBossBar.class, "handle"); private static final float DEFAULT_SPEED = 1F; private static final MethodHandle ENDERDRAGON_BATTLE_FIELD = NMS.getGetter(EntityEnderDragon.class, "bN"); @@ -2021,10 +2093,13 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle PUFFERFISH_D = NMS.getSetter(EntityPufferFish.class, "d"); private static final MethodHandle RABBIT_DATAWATCHER_FIELD = NMS.getGetter(EntityRabbit.class, "bw"); private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle REPAIR_INVENTORY = NMS.getGetter(ContainerAnvil.class, "repairInventory"); + private static final MethodHandle RESULT_INVENTORY = NMS.getGetter(ContainerAnvil.class, "resultInventory"); private static final MethodHandle SET_POSE = NMS.getMethodHandle(Entity.class, "setPose", true, EntityPose.class); private static final MethodHandle SIZE_FIELD_GETTER = NMS.getGetter(Entity.class, "size"); private static final MethodHandle SIZE_FIELD_SETTER = NMS.getSetter(Entity.class, "size"); private static Field SKULL_PROFILE_FIELD; + private static MethodHandle TEAM_FIELD; static { diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java index 381749057..3a1f968d2 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java @@ -33,6 +33,8 @@ import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftWither; import org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.LivingEntity; @@ -41,6 +43,7 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -67,6 +70,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -216,8 +220,11 @@ import net.minecraft.server.v1_16_R3.Block; import net.minecraft.server.v1_16_R3.BlockPosition; import net.minecraft.server.v1_16_R3.BossBattleServer; import net.minecraft.server.v1_16_R3.ChatComponentText; +import net.minecraft.server.v1_16_R3.ChatMessage; import net.minecraft.server.v1_16_R3.ChunkProviderServer; import net.minecraft.server.v1_16_R3.Container; +import net.minecraft.server.v1_16_R3.ContainerAccess; +import net.minecraft.server.v1_16_R3.ContainerAnvil; import net.minecraft.server.v1_16_R3.ControllerJump; import net.minecraft.server.v1_16_R3.ControllerMove; import net.minecraft.server.v1_16_R3.ControllerMoveFlying; @@ -258,6 +265,7 @@ import net.minecraft.server.v1_16_R3.EnumMoveType; import net.minecraft.server.v1_16_R3.Fluid; import net.minecraft.server.v1_16_R3.GenericAttributes; import net.minecraft.server.v1_16_R3.IBlockData; +import net.minecraft.server.v1_16_R3.IInventory; import net.minecraft.server.v1_16_R3.IRegistry; import net.minecraft.server.v1_16_R3.MathHelper; import net.minecraft.server.v1_16_R3.MinecraftKey; @@ -983,6 +991,42 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + final ContainerAnvil container = new ContainerAnvil(handle.nextContainerCounter(), handle.inventory, + ContainerAccess.at(handle.world, new BlockPosition(0, 0, 0))) { + private CraftInventoryView bukkitEntity; + + @Override + public void e() { + super.e(); + levelCost.set(0); + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), + new CitizensInventoryAnvil(this.containerAccess.getLocation(), this.repairInventory, + this.resultInventory, this, anvil), + this); + return this.bukkitEntity; + } + } + }; + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection.sendPacket( + new PacketPlayOutOpenWindow(container.windowId, container.getType(), new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle(horse); @@ -1438,6 +1482,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + ContainerAnvil container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1958,7 +2023,6 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(PlayerChunkMap.class, "a", true, EntityPlayer.class, boolean.class); - private static final Map, EntityTypes> CITIZENS_ENTITY_TYPES = Maps.newHashMap(); private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getSetter(CraftBossBar.class, "handle"); private static MethodHandle CRAFTSOUND_GETSOUND = NMS.getMethodHandle(CraftSound.class, "getSound", false, @@ -2001,6 +2065,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle SIZE_FIELD_GETTER = NMS.getGetter(Entity.class, "size"); private static final MethodHandle SIZE_FIELD_SETTER = NMS.getSetter(Entity.class, "size"); private static Field SKULL_PROFILE_FIELD; + private static MethodHandle SOUNDEFFECT_KEY = NMS.getGetter(SoundEffect.class, "b"); private static MethodHandle TEAM_FIELD; diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java index 29b8fe2ac..22049532b 100644 --- a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java @@ -33,12 +33,15 @@ import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWither; import org.bukkit.craftbukkit.v1_17_R1.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -65,6 +68,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -236,6 +240,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.FluidTags; import net.minecraft.util.Mth; +import net.minecraft.world.Container; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; @@ -271,6 +276,8 @@ import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.inventory.AnvilMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -991,6 +998,42 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + ServerPlayer handle = (ServerPlayer) getHandle(player); + final AnvilMenu container = new AnvilMenu(handle.nextContainerCounter(), handle.getInventory(), + ContainerLevelAccess.create(handle.level, new BlockPos(0, 0, 0))) { + private CraftInventoryView bukkitEntity; + + @Override + public void createResult() { + super.createResult(); + cost.set(0); + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), + new CitizensInventoryAnvil(this.access.getLocation(), this.inputSlots, this.resultSlots, + this, anvil), + this); + return this.bukkitEntity; + } + } + }; + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + handle.connection.send( + new ClientboundOpenScreenPacket(container.containerId, container.getType(), new TextComponent(title))); + handle.containerMenu = container; + handle.initMenu(container); + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { LivingEntity handle = NMSImpl.getHandle(horse); @@ -1436,6 +1479,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, Container inventory, Container resultInventory, + AnvilMenu container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class MCTargetNavigator implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final PathNavigation navigation; @@ -1955,7 +2019,6 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle BEHAVIOR_MAP = NMS.getGetter(Brain.class, "f"); private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity"); - private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(ChunkMap.class, "a", true, ServerPlayer.class, boolean.class); private static final Map, net.minecraft.world.entity.EntityType> CITIZENS_ENTITY_TYPES = Maps diff --git a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java index cecb0dde6..f96f09389 100644 --- a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java +++ b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java @@ -34,12 +34,15 @@ import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_18_R2.entity.CraftWither; import org.bukkit.craftbukkit.v1_18_R2.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_18_R2.event.CraftPortalEvent; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -67,6 +70,7 @@ import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; import net.citizensnpcs.api.event.DespawnReason; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -238,6 +242,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.FluidTags; import net.minecraft.util.Mth; +import net.minecraft.world.Container; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; @@ -274,6 +279,8 @@ import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.inventory.AnvilMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -998,6 +1005,42 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + ServerPlayer handle = (ServerPlayer) getHandle(player); + final AnvilMenu container = new AnvilMenu(handle.nextContainerCounter(), handle.getInventory(), + ContainerLevelAccess.create(handle.level, new BlockPos(0, 0, 0))) { + private CraftInventoryView bukkitEntity; + + @Override + public void createResult() { + super.createResult(); + cost.set(0); + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), + new CitizensInventoryAnvil(this.access.getLocation(), this.inputSlots, this.resultSlots, + this, anvil), + this); + return this.bukkitEntity; + } + } + }; + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + handle.connection.send( + new ClientboundOpenScreenPacket(container.containerId, container.getType(), new TextComponent(title))); + handle.containerMenu = container; + handle.initMenu(container); + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { LivingEntity handle = NMSImpl.getHandle(horse); @@ -1443,6 +1486,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, Container inventory, Container resultInventory, + AnvilMenu container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class MCTargetNavigator implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final PathNavigation navigation; diff --git a/v1_19_R1/src/main/java/net/citizensnpcs/nms/v1_19_R1/util/NMSImpl.java b/v1_19_R1/src/main/java/net/citizensnpcs/nms/v1_19_R1/util/NMSImpl.java index 7a4836983..5eb9341a3 100644 --- a/v1_19_R1/src/main/java/net/citizensnpcs/nms/v1_19_R1/util/NMSImpl.java +++ b/v1_19_R1/src/main/java/net/citizensnpcs/nms/v1_19_R1/util/NMSImpl.java @@ -34,12 +34,15 @@ import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_19_R1.entity.CraftWither; import org.bukkit.craftbukkit.v1_19_R1.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_19_R1.event.CraftPortalEvent; +import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -67,6 +70,7 @@ import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; import net.citizensnpcs.api.event.DespawnReason; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -246,6 +250,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.FluidTags; import net.minecraft.util.Mth; +import net.minecraft.world.Container; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; @@ -282,6 +287,8 @@ import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.inventory.AnvilMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -1013,6 +1020,42 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + ServerPlayer handle = (ServerPlayer) getHandle(player); + final AnvilMenu container = new AnvilMenu(handle.nextContainerCounter(), handle.getInventory(), + ContainerLevelAccess.create(handle.level, new BlockPos(0, 0, 0))) { + private CraftInventoryView bukkitEntity; + + @Override + public void createResult() { + super.createResult(); + cost.set(0); + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), + new CitizensInventoryAnvil(this.access.getLocation(), this.inputSlots, this.resultSlots, + this, anvil), + this); + return this.bukkitEntity; + } + } + }; + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + handle.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), + MutableComponent.create(new LiteralContents(title)))); + handle.containerMenu = container; + handle.initMenu(container); + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { LivingEntity handle = NMSImpl.getHandle(horse); @@ -1458,6 +1501,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, Container inventory, Container resultInventory, + AnvilMenu container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class MCTargetNavigator implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final PathNavigation navigation; diff --git a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java index 8f9eec511..3e081b2d0 100644 --- a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java +++ b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java @@ -1,5 +1,6 @@ package net.citizensnpcs.nms.v1_8_R3.util; +import java.lang.invoke.MethodHandle; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.SocketAddress; @@ -27,6 +28,8 @@ import org.bukkit.craftbukkit.v1_8_R3.block.CraftBlock; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftWither; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventoryView; import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; @@ -37,6 +40,7 @@ import org.bukkit.entity.Tameable; import org.bukkit.entity.Wither; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginLoadOrder; @@ -61,6 +65,7 @@ import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.gui.ForwardingInventory; import net.citizensnpcs.api.npc.BlockBreaker; import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; import net.citizensnpcs.api.npc.NPC; @@ -146,7 +151,9 @@ import net.minecraft.server.v1_8_R3.AxisAlignedBB; import net.minecraft.server.v1_8_R3.Block; import net.minecraft.server.v1_8_R3.BlockPosition; import net.minecraft.server.v1_8_R3.ChatComponentText; +import net.minecraft.server.v1_8_R3.ChatMessage; import net.minecraft.server.v1_8_R3.Container; +import net.minecraft.server.v1_8_R3.ContainerAnvil; import net.minecraft.server.v1_8_R3.ControllerJump; import net.minecraft.server.v1_8_R3.ControllerMove; import net.minecraft.server.v1_8_R3.CrashReport; @@ -168,6 +175,7 @@ import net.minecraft.server.v1_8_R3.EntityTrackerEntry; import net.minecraft.server.v1_8_R3.EntityTypes; import net.minecraft.server.v1_8_R3.EntityWither; import net.minecraft.server.v1_8_R3.GenericAttributes; +import net.minecraft.server.v1_8_R3.IInventory; import net.minecraft.server.v1_8_R3.MathHelper; import net.minecraft.server.v1_8_R3.Navigation; import net.minecraft.server.v1_8_R3.NavigationAbstract; @@ -730,6 +738,52 @@ public class NMSImpl implements NMSBridge { NMSImpl.getHandle(passenger).mount(NMSImpl.getHandle(entity)); } + @Override + public InventoryView openAnvilInventory(final Player player, final Inventory anvil, String title) { + EntityPlayer handle = (EntityPlayer) getHandle(player); + final ContainerAnvil container = new ContainerAnvil(handle.inventory, handle.world, new BlockPosition(0, 0, 0), + handle) { + private CraftInventoryView bukkitEntity; + + @Override + public boolean a(EntityHuman entityhuman) { + return true; + } + + @Override + public void b(EntityHuman entityhuman) { + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } else { + try { + this.bukkitEntity = new CraftInventoryView(player, + new CitizensInventoryAnvil(new Location(player.getWorld(), 0, 0, 0), + (IInventory) REPAIR_INVENTORY.invoke(this), + (IInventory) RESULT_INVENTORY.invoke(this), this, anvil), + this); + } catch (Throwable e) { + e.printStackTrace(); + return super.getBukkitView(); + } + return this.bukkitEntity; + } + } + }; + container.windowId = handle.nextContainerCounter(); + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + container.addSlotListener(handle); + handle.playerConnection + .sendPacket(new PacketPlayOutOpenWindow(container.windowId, "minecraft:anvil", new ChatMessage(title))); + handle.activeContainer = container; + return container.getBukkitView(); + } + @Override public void openHorseScreen(Tameable horse, Player equipper) { EntityLiving handle = NMSImpl.getHandle((LivingEntity) horse); @@ -1159,6 +1213,27 @@ public class NMSImpl implements NMSBridge { } } + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, IInventory inventory, IInventory resultInventory, + ContainerAnvil container, Inventory wrapped) { + super(inventory, resultInventory); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + private static class NavigationFieldWrapper implements TargetNavigator { private final org.bukkit.entity.Entity entity; private final NavigationAbstract navigation; @@ -1491,7 +1566,9 @@ public class NMSImpl implements NMSBridge { private static final Set BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.SILVERFISH, EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.MAGMA_CUBE, EntityType.HORSE, EntityType.GHAST); + private static final float DEFAULT_SPEED = 1F; + private static Method ENTITY_ATTACK_A = NMS.getMethod(Entity.class, "a", true, EntityLiving.class, Entity.class); private static Map, Integer> ENTITY_CLASS_TO_INT; private static Map, String> ENTITY_CLASS_TO_NAME; @@ -1506,6 +1583,8 @@ public class NMSImpl implements NMSBridge { public static final Location PACKET_CACHE_LOCATION = new Location(null, 0, 0, 0); private static Field PATHFINDING_RANGE = NMS.getField(NavigationAbstract.class, "a"); private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle REPAIR_INVENTORY = NMS.getGetter(ContainerAnvil.class, "g"); + private static final MethodHandle RESULT_INVENTORY = NMS.getGetter(ContainerAnvil.class, "h"); private static Field SKULL_PROFILE_FIELD; private static Field TEAM_FIELD; private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c");