diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 729b0b66..8e3c469b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ stages: variables: name: "SongodaCore" path: "/builds/$CI_PROJECT_PATH" - version: "2.2.12" + version: "2.3" build: stage: build diff --git a/Core/pom.xml b/Core/pom.xml index ef0967ea..0a0a5fb3 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -114,10 +114,9 @@ - com.destroystokyo.papermc - paper - 1.14.4 - provided + org.spigotmc + spigot + 1.15 diff --git a/Core/src/main/java/com/songoda/core/commands/CommandManager.java b/Core/src/main/java/com/songoda/core/commands/CommandManager.java index 127c0afc..ef8e1626 100644 --- a/Core/src/main/java/com/songoda/core/commands/CommandManager.java +++ b/Core/src/main/java/com/songoda/core/commands/CommandManager.java @@ -315,7 +315,7 @@ public class CommandManager implements CommandExecutor, TabCompleter { // If we're on Paper 1.8, we need to register timings (spigot creates timings on init, paper creates it on register) // later versions of paper create timings if needed when the command is executed if (ServerProject.isServer(ServerProject.PAPER, ServerProject.TACO) && ServerVersion.isServerVersionBelow(ServerVersion.V1_9)) { - commandObject.timings = co.aikar.timings.TimingsManager.getCommandTiming(plugin.getName().toLowerCase(), commandObject); + // commandObject.timings = co.aikar.timings.TimingsManager.getCommandTiming(plugin.getName().toLowerCase(), commandObject); } // Set command action diff --git a/Core/src/main/java/com/songoda/core/compatibility/CompatibleMaterial.java b/Core/src/main/java/com/songoda/core/compatibility/CompatibleMaterial.java index da63007b..7abfff2f 100644 --- a/Core/src/main/java/com/songoda/core/compatibility/CompatibleMaterial.java +++ b/Core/src/main/java/com/songoda/core/compatibility/CompatibleMaterial.java @@ -30,6 +30,16 @@ public enum CompatibleMaterial { DARK_OAK_DOOR_ITEM(431), */ + + /* 1.15 */ + BEE_SPAWN_EGG(), + BEE_NEST(), + BEEHIVE(), + HONEY_BLOCK(), + HONEY_BOTTLE(), + HONEYCOMB(), + HONEYCOMB_BLOCK(), + ACACIA_BOAT("BOAT_ACACIA"), ACACIA_BUTTON(), ACACIA_DOOR("ACACIA_DOOR_ITEM"), diff --git a/Core/src/main/java/com/songoda/core/compatibility/CompatibleParticleHandler.java b/Core/src/main/java/com/songoda/core/compatibility/CompatibleParticleHandler.java index 58a35bfa..708a171d 100644 --- a/Core/src/main/java/com/songoda/core/compatibility/CompatibleParticleHandler.java +++ b/Core/src/main/java/com/songoda/core/compatibility/CompatibleParticleHandler.java @@ -1,17 +1,24 @@ package com.songoda.core.compatibility; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; import org.bukkit.Color; import org.bukkit.Effect; import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.block.BlockFace; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + public class CompatibleParticleHandler { public static enum ParticleType { + /* 1.15 */ + DRIPPING_HONEY, + FALLING_HONEY, + FALLING_NECTAR, + LANDING_HONEY, + EXPLOSION_NORMAL(), EXPLOSION_LARGE, EXPLOSION_HUGE, @@ -214,17 +221,17 @@ public class CompatibleParticleHandler { public static void redstoneParticles(Location location, int red, int green, int blue) { redstoneParticles(location, red, green, blue, 1F, 1, 0); } - + /** * Spawn colored redstone particles - * + * * @param location area to spawn the particle in - * @param red red value 0-255 - * @param green green value 0-255 - * @param blue blue value 0-255 - * @param size (1.13+) size of the particles - * @param count how many particles to spawn - * @param radius how far to spread out the particles from location + * @param red red value 0-255 + * @param green green value 0-255 + * @param blue blue value 0-255 + * @param size (1.13+) size of the particles + * @param count how many particles to spawn + * @param radius how far to spread out the particles from location */ public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius) { if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) { @@ -247,23 +254,23 @@ public class CompatibleParticleHandler { float yy = (float) (radius * (Math.random() - Math.random())); float zz = (float) (radius * (Math.random() - Math.random())); Location at = location.clone().add(xx, yy, zz); - LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE, + LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE, red / 255F, green / 255F, blue / 255F, 1F, 0, null); } } } - public static void bonemealSmoke(Location l) { - final org.bukkit.World w = l.getWorld(); - w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_EAST); - w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH); - w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_WEST); - w.playEffect(l, Effect.SMOKE, BlockFace.EAST); - w.playEffect(l, Effect.SMOKE, BlockFace.SELF); - w.playEffect(l, Effect.SMOKE, BlockFace.WEST); - w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_EAST); - w.playEffect(l, Effect.SMOKE, BlockFace.NORTH); - w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_WEST); - } + public static void bonemealSmoke(Location l) { + final org.bukkit.World w = l.getWorld(); + w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_EAST); + w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH); + w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_WEST); + w.playEffect(l, Effect.SMOKE, BlockFace.EAST); + w.playEffect(l, Effect.SMOKE, BlockFace.SELF); + w.playEffect(l, Effect.SMOKE, BlockFace.WEST); + w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_EAST); + w.playEffect(l, Effect.SMOKE, BlockFace.NORTH); + w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_WEST); + } } diff --git a/Core/src/main/java/com/songoda/core/compatibility/CompatibleSound.java b/Core/src/main/java/com/songoda/core/compatibility/CompatibleSound.java index 630fa5d5..0cb6762a 100644 --- a/Core/src/main/java/com/songoda/core/compatibility/CompatibleSound.java +++ b/Core/src/main/java/com/songoda/core/compatibility/CompatibleSound.java @@ -23,6 +23,29 @@ public enum CompatibleSound { // would using the raw strings be better? // 1.8 list: // https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments + + /* 1.15 */ + BLOCK_BEEHIVE_DRIP, + BLOCK_BEEHIVE_ENTER, + BLOCK_BEEHIVE_EXIT, + BLOCK_BEEHIVE_SHEAR, + BLOCK_BEEHIVE_WORK, + BLOCK_HONEY_BLOCK_BREAK, + BLOCK_HONEY_BLOCK_FALL, + BLOCK_HONEY_BLOCK_HIT, + BLOCK_HONEY_BLOCK_PLACE, + BLOCK_HONEY_BLOCK_SLIDE, + BLOCK_HONEY_BLOCK_STEP, + ENTITY_BEE_DEATH, + ENTITY_BEE_HURT, + ENTITY_BEE_LOOP, + ENTITY_BEE_LOOP_AGGRESSIVE, + ENTITY_BEE_POLLINATE, + ENTITY_BEE_STING, + ENTITY_IRON_GOLEM_DAMAGE, + ENTITY_IRON_GOLEM_REPAIR, + ITEM_HONEY_BOTTLE_DRINK, + AMBIENT_CAVE(ServerVersion.V1_9, v("AMBIENCE_CAVE")), AMBIENT_UNDERWATER_ENTER, AMBIENT_UNDERWATER_EXIT, 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/Core/src/main/java/com/songoda/core/utils/ItemUtils.java b/Core/src/main/java/com/songoda/core/utils/ItemUtils.java index e32b9de0..5b3c6d72 100644 --- a/Core/src/main/java/com/songoda/core/utils/ItemUtils.java +++ b/Core/src/main/java/com/songoda/core/utils/ItemUtils.java @@ -46,8 +46,6 @@ public class ItemUtils { public static String getItemName(ItemStack it) { if (it == null) { return null; - } else if (can_getI18NDisplayName) { - return it.getI18NDisplayName(); } else { return itemName(it.getType()); } diff --git a/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilInventoryCustom.java b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilInventoryCustom.java index bd55fdea..d1b112d4 100644 --- a/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilInventoryCustom.java +++ b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilInventoryCustom.java @@ -1,22 +1,22 @@ -package com.songoda.core.nms.v1_14_R1; - -import net.minecraft.server.v1_14_R1.ContainerAnvil; -import net.minecraft.server.v1_14_R1.IInventory; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_14_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; - } -} +package com.songoda.core.nms.v1_14_R1; + +import net.minecraft.server.v1_14_R1.ContainerAnvil; +import net.minecraft.server.v1_14_R1.IInventory; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_14_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_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilView.java b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilView.java index 99c98206..e89f2b65 100644 --- a/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilView.java +++ b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/AnvilView.java @@ -1,261 +1,261 @@ -package com.songoda.core.nms.v1_14_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.util.logging.Level; -import java.util.logging.Logger; -import net.minecraft.server.v1_14_R1.BlockPosition; -import net.minecraft.server.v1_14_R1.ChatMessage; -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.ContainerProperty; -import net.minecraft.server.v1_14_R1.Containers; -import net.minecraft.server.v1_14_R1.EntityHuman; -import net.minecraft.server.v1_14_R1.EntityPlayer; -import net.minecraft.server.v1_14_R1.IInventory; -import net.minecraft.server.v1_14_R1.PacketPlayOutOpenWindow; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_14_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); - } - } - - // 1.14.3 and 1.14.4 have different fields for levelCost - static boolean compat_mode = true; - static Method mc_ContainerProperty_set; - static Method mc_ContainerProperty_get; - // 1.14 also made this field private. Fun. - 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_windowId = Container.class.getDeclaredField("windowId"); - mc_Container_windowId.setAccessible(true); - mc_Container_title = Container.class.getDeclaredField("title"); - mc_Container_title.setAccessible(true); - } catch (Exception ex) { - Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); - } - for (Method m : ContainerProperty.class.getMethods()) { - if (m.getName().equals("set")) { - compat_mode = false; - break; - } - } - if (compat_mode) { - try { - mc_ContainerProperty_set = ContainerProperty.class.getDeclaredMethod("a", int.class); - mc_ContainerProperty_get = ContainerProperty.class.getDeclaredMethod("b"); - } 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) { - if (compat_mode) { - if (mc_ContainerProperty_set != null) { - try { - mc_ContainerProperty_set.invoke(this.levelCost, 0); - } catch (Exception ex) { - Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); - mc_ContainerProperty_set = null; - } - } - } else { - 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 if (compat_mode) { - if (mc_ContainerProperty_get != null) { - try { - return (int) mc_ContainerProperty_get.invoke(this.levelCost); - } catch (Exception ex) { - Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); - mc_ContainerProperty_get = null; - } - } - } else { - return this.levelCost.get(); - } - return -1; - } - - @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); - } - -} +package com.songoda.core.nms.v1_14_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.util.logging.Level; +import java.util.logging.Logger; +import net.minecraft.server.v1_14_R1.BlockPosition; +import net.minecraft.server.v1_14_R1.ChatMessage; +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.ContainerProperty; +import net.minecraft.server.v1_14_R1.Containers; +import net.minecraft.server.v1_14_R1.EntityHuman; +import net.minecraft.server.v1_14_R1.EntityPlayer; +import net.minecraft.server.v1_14_R1.IInventory; +import net.minecraft.server.v1_14_R1.PacketPlayOutOpenWindow; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_14_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); + } + } + + // 1.14.3 and 1.14.4 have different fields for levelCost + static boolean compat_mode = true; + static Method mc_ContainerProperty_set; + static Method mc_ContainerProperty_get; + // 1.14 also made this field private. Fun. + 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_windowId = Container.class.getDeclaredField("windowId"); + mc_Container_windowId.setAccessible(true); + mc_Container_title = Container.class.getDeclaredField("title"); + mc_Container_title.setAccessible(true); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + for (Method m : ContainerProperty.class.getMethods()) { + if (m.getName().equals("set")) { + compat_mode = false; + break; + } + } + if (compat_mode) { + try { + mc_ContainerProperty_set = ContainerProperty.class.getDeclaredMethod("a", int.class); + mc_ContainerProperty_get = ContainerProperty.class.getDeclaredMethod("b"); + } 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) { + if (compat_mode) { + if (mc_ContainerProperty_set != null) { + try { + mc_ContainerProperty_set.invoke(this.levelCost, 0); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); + mc_ContainerProperty_set = null; + } + } + } else { + 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 if (compat_mode) { + if (mc_ContainerProperty_get != null) { + try { + return (int) mc_ContainerProperty_get.invoke(this.levelCost); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); + mc_ContainerProperty_get = null; + } + } + } else { + return this.levelCost.get(); + } + return -1; + } + + @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_14_R1/src/com/songoda/core/nms/v1_14_R1/NMS.java b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/NMS.java index fdb8756d..499cc38c 100644 --- a/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/NMS.java +++ b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/NMS.java @@ -1,24 +1,24 @@ -package com.songoda.core.nms.v1_14_R1; - -import com.songoda.core.nms.CoreNMS; -import com.songoda.core.nms.CustomAnvil; -import net.minecraft.server.v1_14_R1.EntityPlayer; -import org.bukkit.craftbukkit.v1_14_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); - } - -} +package com.songoda.core.nms.v1_14_R1; + +import com.songoda.core.nms.CoreNMS; +import com.songoda.core.nms.CustomAnvil; +import net.minecraft.server.v1_14_R1.EntityPlayer; +import org.bukkit.craftbukkit.v1_14_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/NMS/NMS-v1_15_R1/pom.xml b/NMS/NMS-v1_15_R1/pom.xml new file mode 100644 index 00000000..b56e44d7 --- /dev/null +++ b/NMS/NMS-v1_15_R1/pom.xml @@ -0,0 +1,28 @@ + + + + com.songoda + SongodaCore-Modules + maven-version-number + ../../ + + + SongodaCore-NMS-v1_15_R1 + + 4.0.0 + jar + + + + org.spigotmc + spigot + 1.15 + + + 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..3f3d69c4 --- /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..581f172f --- /dev/null +++ b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/AnvilView.java @@ -0,0 +1,261 @@ +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.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.ContainerProperty; +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); + } + } + + // 1.14.3 and 1.14.4 have different fields for levelCost + static boolean compat_mode = true; + static Method mc_ContainerProperty_set; + static Method mc_ContainerProperty_get; + // 1.14 also made this field private. Fun. + 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_windowId = Container.class.getDeclaredField("windowId"); + mc_Container_windowId.setAccessible(true); + mc_Container_title = Container.class.getDeclaredField("title"); + mc_Container_title.setAccessible(true); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + for (Method m : ContainerProperty.class.getMethods()) { + if (m.getName().equals("set")) { + compat_mode = false; + break; + } + } + if (compat_mode) { + try { + mc_ContainerProperty_set = ContainerProperty.class.getDeclaredMethod("a", int.class); + mc_ContainerProperty_get = ContainerProperty.class.getDeclaredMethod("b"); + } 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) { + if (compat_mode) { + if (mc_ContainerProperty_set != null) { + try { + mc_ContainerProperty_set.invoke(this.levelCost, 0); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); + mc_ContainerProperty_set = null; + } + } + } else { + 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 if (compat_mode) { + if (mc_ContainerProperty_get != null) { + try { + return (int) mc_ContainerProperty_get.invoke(this.levelCost); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); + mc_ContainerProperty_get = null; + } + } + } else { + return this.levelCost.get(); + } + return -1; + } + + @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..2e546a99 --- /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 96a9a46f..3320e10a 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