mirror of
https://github.com/songoda/UltimateModeration.git
synced 2024-11-26 12:15:14 +01:00
Fix for anvil GUI's
This commit is contained in:
parent
5e40f09a04
commit
6b38468175
@ -1,12 +1,12 @@
|
|||||||
package com.songoda.ultimatemoderation.utils.gui;
|
package com.songoda.ultimatemoderation.utils.gui;
|
||||||
|
|
||||||
import com.songoda.ultimatemoderation.UltimateModeration;
|
import com.songoda.ultimatemoderation.UltimateModeration;
|
||||||
import com.songoda.ultimatemoderation.utils.ServerVersion;
|
|
||||||
import com.songoda.ultimatemoderation.utils.version.NMSUtil;
|
import com.songoda.ultimatemoderation.utils.version.NMSUtil;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
@ -24,97 +24,114 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class AbstractAnvilGUI {
|
public class AbstractAnvilGUI {
|
||||||
|
|
||||||
private static Class<?> BlockPosition;
|
private static Class<?> BlockPositionClass;
|
||||||
private static Class<?> PacketPlayOutOpenWindow;
|
private static Class<?> PacketPlayOutOpenWindowClass;
|
||||||
private static Class<?> ContainerAnvil;
|
private static Class<?> IChatBaseComponentClass;
|
||||||
private static Class<?> ChatMessage;
|
private static Class<?> ICraftingClass;
|
||||||
private static Class<?> EntityHuman;
|
private static Class<?> ContainerAnvilClass;
|
||||||
private static boolean loadedClasses = false;
|
private static Class<?> ChatMessageClass;
|
||||||
|
private static Class<?> EntityHumanClass;
|
||||||
|
private static Class<?> ContainerClass;
|
||||||
|
private static Class<?> ContainerAccessClass;
|
||||||
|
private static Class<?> WorldClass;
|
||||||
|
private static Class<?> PlayerInventoryClass;
|
||||||
|
private static Class<?> ContainersClass;
|
||||||
|
|
||||||
private Player player;
|
private Player player;
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private AnvilClickEventHandler handler;
|
|
||||||
private Map<AnvilSlot, ItemStack> items = new HashMap<>();
|
private Map<AnvilSlot, ItemStack> items = new HashMap<>();
|
||||||
private OnClose onClose = null;
|
private OnClose onClose = null;
|
||||||
private Inventory inv;
|
private Inventory inv;
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
|
|
||||||
private Sound closeSound = UltimateModeration.getInstance().isServerVersionAtLeast(ServerVersion.V1_12) ? Sound.ENTITY_PLAYER_LEVELUP : Sound.valueOf("LEVEL_UP");
|
private Sound closeSound = Sound.ENTITY_PLAYER_LEVELUP;
|
||||||
|
|
||||||
|
static {
|
||||||
|
BlockPositionClass = NMSUtil.getNMSClass("BlockPosition");
|
||||||
|
PacketPlayOutOpenWindowClass = NMSUtil.getNMSClass("PacketPlayOutOpenWindow");
|
||||||
|
IChatBaseComponentClass = NMSUtil.getNMSClass("IChatBaseComponent");
|
||||||
|
ICraftingClass = NMSUtil.getNMSClass("ICrafting");
|
||||||
|
ContainerAnvilClass = NMSUtil.getNMSClass("ContainerAnvil");
|
||||||
|
EntityHumanClass = NMSUtil.getNMSClass("EntityHuman");
|
||||||
|
ChatMessageClass = NMSUtil.getNMSClass("ChatMessage");
|
||||||
|
ContainerClass = NMSUtil.getNMSClass("Container");
|
||||||
|
WorldClass = NMSUtil.getNMSClass("World");
|
||||||
|
PlayerInventoryClass = NMSUtil.getNMSClass("PlayerInventory");
|
||||||
|
|
||||||
|
if (NMSUtil.getVersionNumber() > 13) {
|
||||||
|
ContainerAccessClass = NMSUtil.getNMSClass("ContainerAccess");
|
||||||
|
ContainersClass = NMSUtil.getNMSClass("Containers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public AbstractAnvilGUI(final Player player, final AnvilClickEventHandler handler) {
|
public AbstractAnvilGUI(final Player player, final AnvilClickEventHandler handler) {
|
||||||
loadClasses();
|
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.handler = handler;
|
|
||||||
|
|
||||||
this.listener = new Listener() {
|
this.listener = new Listener() {
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onInventoryClick(InventoryClickEvent event) {
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
if (!(event.getWhoClicked() instanceof Player) || !event.getInventory().equals(inv)) return;
|
if (event.getWhoClicked() instanceof Player) {
|
||||||
|
|
||||||
event.setCancelled(true);
|
if (event.getInventory().equals(inv)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
ItemStack item = event.getCurrentItem();
|
ItemStack item = event.getCurrentItem();
|
||||||
int slot = event.getRawSlot();
|
int slot = event.getRawSlot();
|
||||||
String name = "";
|
String name = "";
|
||||||
|
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
if (item.hasItemMeta()) {
|
if (item.hasItemMeta()) {
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
|
||||||
if (meta.hasDisplayName()) {
|
if (meta != null && meta.hasDisplayName()) {
|
||||||
name = meta.getDisplayName();
|
name = meta.getDisplayName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnvilClickEvent clickEvent = new AnvilClickEvent(AnvilSlot.bySlot(slot), name);
|
||||||
|
|
||||||
|
handler.onAnvilClick(clickEvent);
|
||||||
|
|
||||||
|
if (clickEvent.getWillClose()) {
|
||||||
|
event.getWhoClicked().closeInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clickEvent.getWillDestroy()) {
|
||||||
|
destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AnvilClickEvent clickEvent = new AnvilClickEvent(AnvilSlot.bySlot(slot), name);
|
|
||||||
|
|
||||||
if (clickEvent.getWillClose()) {
|
|
||||||
event.getWhoClicked().closeInventory();
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.onAnvilClick(clickEvent);
|
|
||||||
|
|
||||||
if (clickEvent.getWillDestroy()) {
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onInventoryClose(InventoryCloseEvent event) {
|
public void onInventoryClose(InventoryCloseEvent event) {
|
||||||
if (!(event.getPlayer() instanceof Player)) return;
|
if (event.getPlayer() instanceof Player) {
|
||||||
Inventory inv = event.getInventory();
|
Inventory inv = event.getInventory();
|
||||||
player.setLevel(player.getLevel() - 1);
|
player.setLevel(player.getLevel() - 1);
|
||||||
if (!inv.equals(AbstractAnvilGUI.this.inv)) return;
|
if (inv.equals(inv)) {
|
||||||
inv.clear();
|
inv.clear();
|
||||||
OnClose onClose = getOnClose();
|
player.playSound(player.getLocation(), closeSound, 1F, 1F);
|
||||||
player.playSound(player.getLocation(), closeSound, 1F, 1F);
|
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateModeration.getInstance(), () -> {
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateModeration.getInstance(), () -> {
|
if (onClose != null) onClose.OnClose(player, inv);
|
||||||
if (onClose != null) onClose.OnClose(player, inv);
|
destroy();
|
||||||
destroy();
|
}, 1L);
|
||||||
}, 1L);
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
if (!event.getPlayer().equals(getPlayer())) return;
|
if (event.getPlayer().equals(getPlayer())) {
|
||||||
player.setLevel(player.getLevel() - 1);
|
player.setLevel(player.getLevel() - 1);
|
||||||
destroy();
|
destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Bukkit.getPluginManager().registerEvents(listener, UltimateModeration.getInstance());
|
Bukkit.getPluginManager().registerEvents(listener, UltimateModeration.getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadClasses() {
|
|
||||||
if (loadedClasses) return;
|
|
||||||
BlockPosition = NMSUtil.getNMSClass("BlockPosition");
|
|
||||||
PacketPlayOutOpenWindow = NMSUtil.getNMSClass("PacketPlayOutOpenWindow");
|
|
||||||
ContainerAnvil = NMSUtil.getNMSClass("ContainerAnvil");
|
|
||||||
EntityHuman = NMSUtil.getNMSClass("EntityHuman");
|
|
||||||
ChatMessage = NMSUtil.getNMSClass("ChatMessage");
|
|
||||||
loadedClasses = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Player getPlayer() {
|
public Player getPlayer() {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
@ -128,49 +145,59 @@ public class AbstractAnvilGUI {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Object craftPlayer = NMSUtil.getCraftClass("entity.CraftPlayer").cast(player);
|
Object craftPlayer = NMSUtil.getCraftClass("entity.CraftPlayer").cast(player);
|
||||||
Method getHandleMethod = craftPlayer.getClass().getMethod("getHandle", new Class<?>[0]);
|
Method getHandleMethod = craftPlayer.getClass().getMethod("getHandle");
|
||||||
Object entityPlayer = getHandleMethod.invoke(craftPlayer, new Object[0]);
|
Object entityPlayer = getHandleMethod.invoke(craftPlayer);
|
||||||
|
Object playerInventory = NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "inventory", false));
|
||||||
|
Object world = NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "world", false));
|
||||||
|
Object blockPosition = BlockPositionClass.getConstructor(int.class, int.class, int.class).newInstance(0, 0, 0);
|
||||||
|
|
||||||
Object container;
|
Object container;
|
||||||
|
|
||||||
if (NMSUtil.getVersionNumber() == 7) {
|
if (NMSUtil.getVersionNumber() > 13) {
|
||||||
container = ContainerAnvil.getConstructor(new Class[]{NMSUtil.getNMSClass("PlayerInventory"), NMSUtil.getNMSClass("World"), Integer.TYPE, Integer.TYPE, Integer.TYPE, EntityHuman}).newInstance(new Object[]{NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "inventory", false)), NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "world", false)), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0), entityPlayer});
|
container = ContainerAnvilClass
|
||||||
|
.getConstructor(int.class, PlayerInventoryClass, ContainerAccessClass)
|
||||||
|
.newInstance(7, playerInventory, ContainerAccessClass.getMethod("at", WorldClass, BlockPositionClass).invoke(null, world, blockPosition));
|
||||||
} else {
|
} else {
|
||||||
container = ContainerAnvil.getConstructor(NMSUtil.getNMSClass("PlayerInventory"), NMSUtil.getNMSClass("World"), BlockPosition, EntityHuman).newInstance(NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "inventory", false)), NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "world", false)), BlockPosition.getConstructor(int.class, int.class, int.class).newInstance(0, 0, 0), entityPlayer);
|
container = ContainerAnvilClass
|
||||||
|
.getConstructor(PlayerInventoryClass, WorldClass, BlockPositionClass, EntityHumanClass)
|
||||||
|
.newInstance(playerInventory, world, blockPosition, entityPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
NMSUtil.getField(NMSUtil.getNMSClass("Container"), "checkReachable", true).set(container, false);
|
NMSUtil.getField(ContainerClass, "checkReachable", true).set(container, false);
|
||||||
|
|
||||||
Method getBukkitViewMethod = container.getClass().getMethod("getBukkitView", new Class<?>[0]);
|
Method getBukkitViewMethod = container.getClass().getMethod("getBukkitView");
|
||||||
Object bukkitView = getBukkitViewMethod.invoke(container);
|
Object bukkitView = getBukkitViewMethod.invoke(container);
|
||||||
Method getTopInventoryMethod = bukkitView.getClass().getMethod("getTopInventory", new Class<?>[0]);
|
Method getTopInventoryMethod = bukkitView.getClass().getMethod("getTopInventory");
|
||||||
inv = (Inventory) getTopInventoryMethod.invoke(bukkitView);
|
inv = (Inventory) getTopInventoryMethod.invoke(bukkitView);
|
||||||
|
|
||||||
for (AnvilSlot slot : items.keySet()) {
|
for (AnvilSlot slot : items.keySet()) {
|
||||||
inv.setItem(slot.getSlot(), items.get(slot));
|
inv.setItem(slot.getSlot(), items.get(slot));
|
||||||
}
|
}
|
||||||
|
|
||||||
Method nextContainerCounterMethod = entityPlayer.getClass().getMethod("nextContainerCounter", new Class<?>[0]);
|
Method nextContainerCounterMethod = entityPlayer.getClass().getMethod("nextContainerCounter");
|
||||||
int c = (int) nextContainerCounterMethod.invoke(entityPlayer);
|
int c = (int) nextContainerCounterMethod.invoke(entityPlayer);
|
||||||
|
|
||||||
Constructor<?> chatMessageConstructor = ChatMessage.getConstructor(String.class, Object[].class);
|
Constructor<?> chatMessageConstructor = ChatMessageClass.getConstructor(String.class, Object[].class);
|
||||||
Object packet;
|
Object packet;
|
||||||
|
|
||||||
if (NMSUtil.getVersionNumber() == 7) {
|
if (NMSUtil.getVersionNumber() > 13) {
|
||||||
packet = PacketPlayOutOpenWindow.getConstructor(new Class[]{Integer.TYPE, Integer.TYPE, String.class, Integer.TYPE, Boolean.TYPE, Integer.TYPE}).newInstance(new Object[]{Integer.valueOf(c), Integer.valueOf(8), "Repairing", Integer.valueOf(0), Boolean.valueOf(true), Integer.valueOf(0)});
|
packet = PacketPlayOutOpenWindowClass
|
||||||
|
.getConstructor(int.class, ContainersClass, IChatBaseComponentClass)
|
||||||
|
.newInstance(c, ContainersClass.getField("ANVIL").get(null), chatMessageConstructor.newInstance("Repairing", new Object[]{}));
|
||||||
} else {
|
} else {
|
||||||
packet = PacketPlayOutOpenWindow.getConstructor(int.class, String.class, NMSUtil.getNMSClass("IChatBaseComponent"), int.class).newInstance(c, "minecraft:anvil", chatMessageConstructor.newInstance("Repairing", new Object[]{}), 0);
|
packet = PacketPlayOutOpenWindowClass
|
||||||
|
.getConstructor(int.class, String.class, IChatBaseComponentClass, int.class)
|
||||||
|
.newInstance(c, "minecraft:anvil", chatMessageConstructor.newInstance("Repairing", new Object[]{}), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NMSUtil.sendPacket(player, packet);
|
NMSUtil.sendPacket(player, packet);
|
||||||
|
|
||||||
Field activeContainerField = NMSUtil.getField(EntityHuman, "activeContainer", true);
|
Field activeContainerField = NMSUtil.getField(EntityHumanClass, "activeContainer", true);
|
||||||
|
|
||||||
if (activeContainerField != null) {
|
if (activeContainerField != null) {
|
||||||
activeContainerField.set(entityPlayer, container);
|
activeContainerField.set(entityPlayer, container);
|
||||||
NMSUtil.getField(NMSUtil.getNMSClass("Container"), "windowId", true).set(activeContainerField.get(entityPlayer), c);
|
NMSUtil.getField(ContainerClass, "windowId", true).set(activeContainerField.get(entityPlayer), c);
|
||||||
|
Method addSlotListenerMethod = activeContainerField.get(entityPlayer).getClass().getMethod("addSlotListener", ICraftingClass);
|
||||||
Method addSlotListenerMethod = activeContainerField.get(entityPlayer).getClass().getMethod("addSlotListener", NMSUtil.getNMSClass("ICrafting"));
|
|
||||||
addSlotListenerMethod.invoke(activeContainerField.get(entityPlayer), entityPlayer);
|
addSlotListenerMethod.invoke(activeContainerField.get(entityPlayer), entityPlayer);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -179,9 +206,7 @@ public class AbstractAnvilGUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
onClose = null;
|
|
||||||
player = null;
|
player = null;
|
||||||
handler = null;
|
|
||||||
items = null;
|
items = null;
|
||||||
|
|
||||||
HandlerList.unregisterAll(listener);
|
HandlerList.unregisterAll(listener);
|
||||||
@ -208,7 +233,7 @@ public class AbstractAnvilGUI {
|
|||||||
|
|
||||||
private int slot;
|
private int slot;
|
||||||
|
|
||||||
private AnvilSlot(int slot) {
|
AnvilSlot(int slot) {
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,6 +252,7 @@ public class AbstractAnvilGUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
public interface AnvilClickEventHandler {
|
public interface AnvilClickEventHandler {
|
||||||
void onAnvilClick(AnvilClickEvent event);
|
void onAnvilClick(AnvilClickEvent event);
|
||||||
}
|
}
|
||||||
@ -268,4 +294,5 @@ public class AbstractAnvilGUI {
|
|||||||
this.destroy = destroy;
|
this.destroy = destroy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user