From 9e7b513288d72c3322c796d0f537c2fbf2aa7722 Mon Sep 17 00:00:00 2001 From: jascotty2 Date: Sun, 2 Feb 2020 15:10:37 -0600 Subject: [PATCH] add 1.15 anvils, add close method for Gui --- Core/pom.xml | 7 + .../songoda/core/database/MySQLConnector.java | 2 + .../main/java/com/songoda/core/gui/Gui.java | 12 + .../java/com/songoda/core/nms/NmsManager.java | 2 + NMS/NMS-v1_15_R1/pom.xml | 29 +++ .../nms/v1_15_R1/AnvilInventoryCustom.java | 22 ++ .../songoda/core/nms/v1_15_R1/AnvilView.java | 229 ++++++++++++++++++ .../com/songoda/core/nms/v1_15_R1/NMS.java | 24 ++ pom.xml | 1 + 9 files changed, 328 insertions(+) create mode 100644 NMS/NMS-v1_15_R1/pom.xml create mode 100644 NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilInventoryCustom.java create mode 100644 NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilView.java create mode 100644 NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/NMS.java diff --git a/Core/pom.xml b/Core/pom.xml index 04b9827b..53b2ea6b 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -182,6 +182,13 @@ jar compile + + ${project.groupId} + SongodaCore-NMS-v1_15_R1 + ${project.version} + jar + compile + diff --git a/Core/src/main/java/com/songoda/core/database/MySQLConnector.java b/Core/src/main/java/com/songoda/core/database/MySQLConnector.java index d072ecbc..5494e682 100644 --- a/Core/src/main/java/com/songoda/core/database/MySQLConnector.java +++ b/Core/src/main/java/com/songoda/core/database/MySQLConnector.java @@ -16,6 +16,8 @@ public class MySQLConnector implements DatabaseConnector { public MySQLConnector(Plugin plugin, String hostname, int port, String database, String username, String password, boolean useSSL) { this.plugin = plugin; + System.out.println("connecting to " + hostname + " : " + port + " with " + password); + HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database + "?useSSL=" + useSSL); config.setUsername(username); diff --git a/Core/src/main/java/com/songoda/core/gui/Gui.java b/Core/src/main/java/com/songoda/core/gui/Gui.java index ad44859a..fb36f231 100644 --- a/Core/src/main/java/com/songoda/core/gui/Gui.java +++ b/Core/src/main/java/com/songoda/core/gui/Gui.java @@ -155,6 +155,18 @@ public class Gui { .collect(Collectors.toList()) .forEach(Player::closeInventory); } + + /** + * Close the GUI as if the player closed it normally + */ + public void close() { + allowClose = true; + inventory.getViewers().stream() + .filter(e -> e instanceof Player) + .map(e -> (Player) e) + .collect(Collectors.toList()) + .forEach(Player::closeInventory); + } @NotNull public GuiType getType() { diff --git a/Core/src/main/java/com/songoda/core/nms/NmsManager.java b/Core/src/main/java/com/songoda/core/nms/NmsManager.java index e0fec81b..d7fe0795 100644 --- a/Core/src/main/java/com/songoda/core/nms/NmsManager.java +++ b/Core/src/main/java/com/songoda/core/nms/NmsManager.java @@ -40,6 +40,8 @@ public class NmsManager { return new com.songoda.core.nms.v1_13_R2.NMS(); case "v1_14_R1": return new com.songoda.core.nms.v1_14_R1.NMS(); + case "v1_15_R1": + return new com.songoda.core.nms.v1_15_R1.NMS(); } Logger.getLogger(NmsManager.class.getName()).log(Level.SEVERE, "Failed to load NMS for this server version: version {0} not found", serverPackageVersion); return null; diff --git a/NMS/NMS-v1_15_R1/pom.xml b/NMS/NMS-v1_15_R1/pom.xml new file mode 100644 index 00000000..9b46038d --- /dev/null +++ b/NMS/NMS-v1_15_R1/pom.xml @@ -0,0 +1,29 @@ + + + + com.songoda + SongodaCore-Modules + maven-version-number + ../../ + + + SongodaCore-NMS-v1_15_R1 + + 4.0.0 + jar + + + + com.destroystokyo.papermc + paper + 1.15.1 + provided + + + com.songoda + SongodaCore-NMS-API + ${project.version} + provided + + + \ No newline at end of file diff --git a/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilInventoryCustom.java b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilInventoryCustom.java new file mode 100644 index 00000000..4377c4e5 --- /dev/null +++ b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilInventoryCustom.java @@ -0,0 +1,22 @@ +package com.songoda.core.nms.v1_15_R1; + +import net.minecraft.server.v1_15_R1.ContainerAnvil; +import net.minecraft.server.v1_15_R1.IInventory; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryAnvil; +import org.bukkit.inventory.InventoryHolder; + +public class AnvilInventoryCustom extends CraftInventoryAnvil { + + final InventoryHolder holder; + + public AnvilInventoryCustom(InventoryHolder holder, Location location, IInventory inventory, IInventory resultInventory, ContainerAnvil container) { + super(location, inventory, resultInventory, container); + this.holder = holder; + } + + @Override + public InventoryHolder getHolder() { + return holder; + } +} diff --git a/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilView.java b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilView.java new file mode 100644 index 00000000..34821035 --- /dev/null +++ b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilView.java @@ -0,0 +1,229 @@ +package com.songoda.core.nms.v1_15_R1; + +import com.songoda.core.nms.CustomAnvil; +import com.songoda.core.nms.methods.AnvilTextChange; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.minecraft.server.v1_15_R1.BlockPosition; +import net.minecraft.server.v1_15_R1.ChatMessage; +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.Containers; +import net.minecraft.server.v1_15_R1.EntityHuman; +import net.minecraft.server.v1_15_R1.EntityPlayer; +import net.minecraft.server.v1_15_R1.IInventory; +import net.minecraft.server.v1_15_R1.PacketPlayOutOpenWindow; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; + +public class AnvilView extends ContainerAnvil implements CustomAnvil { + + private final EntityPlayer entity; + private final Inventory inventory; + private String customTitle = "Repairing"; + private int cost = -1; + private boolean canUse = true; + private AnvilTextChange textChange = null; + + // used for setting custom inventory + static Field mc_ContainerAnvil_repairInventory; // subcontainer with only the result + static Field mc_ContainerAnvil_resultInventory; // full inventory + static Field mc_ContainerAnvil_bukkitEntity; + + static { + try { + mc_ContainerAnvil_repairInventory = ContainerAnvil.class.getDeclaredField("repairInventory"); + mc_ContainerAnvil_repairInventory.setAccessible(true); + mc_ContainerAnvil_resultInventory = ContainerAnvil.class.getDeclaredField("resultInventory"); + mc_ContainerAnvil_resultInventory.setAccessible(true); + mc_ContainerAnvil_bukkitEntity = ContainerAnvil.class.getDeclaredField("bukkitEntity"); + mc_ContainerAnvil_bukkitEntity.setAccessible(true); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + } + + static Method mc_ContainerProperty_set; + static Method mc_ContainerProperty_get; + // 1.15 made this field public again, but now it's final. idk. + static Field mc_Container_windowId; + // 1.14 also introduced a title field, also private, which can only be set once and can't be checked + static Field mc_Container_title; + + static { + try { + mc_Container_title = Container.class.getDeclaredField("title"); + mc_Container_title.setAccessible(true); + mc_Container_windowId = Container.class.getDeclaredField("windowId"); + mc_Container_windowId.setAccessible(true); + + // remove the final modifier + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(mc_Container_windowId, mc_Container_windowId.getModifiers() & ~Modifier.FINAL); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + } + + public AnvilView(int id, EntityPlayer entity, InventoryHolder holder) { + super(id, entity.inventory, ContainerAccess.at(entity.world, new BlockPosition(0, 0, 0))); + this.setTitle(new ChatMessage(customTitle != null ? customTitle : "")); + this.checkReachable = false; + this.entity = entity; + if(holder != null) { + this.inventory = getBukkitView(entity, holder).getTopInventory(); + } else { + this.inventory = getBukkitView().getTopInventory(); + } + } + + public CraftInventoryView getBukkitView(EntityHuman player, InventoryHolder holder) { + try { + AnvilInventoryCustom craftInventory = new AnvilInventoryCustom(holder, + new Location(entity.world.getWorld(), 0, 0, 0), + (IInventory) mc_ContainerAnvil_repairInventory.get(this), + (IInventory) mc_ContainerAnvil_resultInventory.get(this), this); + CraftInventoryView view = new CraftInventoryView(player.getBukkitEntity(), craftInventory, this); + mc_ContainerAnvil_bukkitEntity.set(this, view); + return view; + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + return getBukkitView(); + } + + @Override + public boolean canUse(EntityHuman entityhuman) { + return canUse; + } + + @Override + public void e() { + super.e(); + if (cost >= 0) { + this.levelCost.set(cost); + } + textChange.onChange(); + } + + @Override + public void update() { + e(); + } + + @Override + public String getRenameText() { + return this.renameText; + } + + @Override + public void setRenameText(String text) { + this.a(text); + } + + @Override + public void setOnChange(AnvilTextChange handler) { + textChange = handler; + } + + @Override + public String getCustomTitle() { + return customTitle; + } + + @Override + public void setCustomTitle(String title) { + this.customTitle = title; + try { + mc_Container_title.set(this, new ChatMessage(customTitle != null ? customTitle : "")); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); + } + } + + @Override + public void setLevelCost(int cost) { + this.cost = cost; + } + + @Override + public int getLevelCost() { + if (cost >= 0) { + return cost; + } else { + return this.levelCost.get(); + } + } + + @Override + public void setCanUse(boolean bool) { + this.canUse = bool; + } + + @Override + public ItemStack getLeftInput() { + return inventory.getItem(0); + } + + @Override + public ItemStack getRightInput() { + return inventory.getItem(1); + } + + @Override + public ItemStack getOutput() { + return inventory.getItem(2); + } + + @Override + public void setLeftInput(ItemStack item) { + inventory.setItem(0, item); + } + + @Override + public void setRightInput(ItemStack item) { + inventory.setItem(1, item); + } + + @Override + public void setOutput(ItemStack item) { + inventory.setItem(2, item); + } + + @Override + public Inventory getInventory() { + return inventory; + } + + @Override + public void open() { + + // Counter stuff that the game uses to keep track of inventories + int id = entity.nextContainerCounter(); + + // Send the packet + entity.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.ANVIL, new ChatMessage(customTitle != null ? customTitle : ""))); + + // Set their active container to this anvil + entity.activeContainer = this; + + try { + // Set their active container window id to that counter stuff + mc_Container_windowId.set(this, id); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Create Error", ex); + } + + // Add the slot listener + entity.activeContainer.addSlotListener(entity); + } + +} diff --git a/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/NMS.java b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/NMS.java new file mode 100644 index 00000000..f27203aa --- /dev/null +++ b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/NMS.java @@ -0,0 +1,24 @@ +package com.songoda.core.nms.v1_15_R1; + +import com.songoda.core.nms.CoreNMS; +import com.songoda.core.nms.CustomAnvil; +import net.minecraft.server.v1_15_R1.EntityPlayer; +import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; + +public class NMS implements CoreNMS { + + @Override + public CustomAnvil createAnvil(Player player) { + EntityPlayer p = ((CraftPlayer) player).getHandle(); + return new AnvilView(p.nextContainerCounter(), p, null); + } + + @Override + public CustomAnvil createAnvil(Player player, InventoryHolder holder) { + EntityPlayer p = ((CraftPlayer) player).getHandle(); + return new AnvilView(p.nextContainerCounter(), p, holder); + } + +} diff --git a/pom.xml b/pom.xml index b42ccf44..3cd4a036 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ NMS/NMS-v1_13_R1 NMS/NMS-v1_13_R2 NMS/NMS-v1_14_R1 + NMS/NMS-v1_15_R1