diff --git a/Core/pom.xml b/Core/pom.xml
index 81b3b759..a7a8e164 100644
--- a/Core/pom.xml
+++ b/Core/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../
@@ -119,7 +119,7 @@
org.spigotmc
spigot
- 1.16.1
+ 1.16.4
diff --git a/Core/src/main/java/com/songoda/core/SongodaCore.java b/Core/src/main/java/com/songoda/core/SongodaCore.java
index 88279773..627f4f1a 100644
--- a/Core/src/main/java/com/songoda/core/SongodaCore.java
+++ b/Core/src/main/java/com/songoda/core/SongodaCore.java
@@ -54,7 +54,7 @@ public class SongodaCore {
/**
* This has been added as of Rev 6
*/
- private final static String coreVersion = "2.4.20";
+ private final static String coreVersion = "2.4.21";
/**
* This is specific to the website api
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 e89edaed..9745b63b 100644
--- a/Core/src/main/java/com/songoda/core/nms/NmsManager.java
+++ b/Core/src/main/java/com/songoda/core/nms/NmsManager.java
@@ -72,6 +72,10 @@ public class NmsManager {
anvil = new com.songoda.core.nms.v1_16_R2.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_16_R2.nbt.NBTCoreImpl();
break;
+ case "v1_16_R3":
+ anvil = new com.songoda.core.nms.v1_16_R3.anvil.AnvilCore();
+ nbt = new com.songoda.core.nms.v1_16_R3.nbt.NBTCoreImpl();
+ break;
default:
Logger.getLogger(NmsManager.class.getName()).log(Level.SEVERE, "Failed to load NMS for this server version: version {0} not found", serverPackageVersion);
anvil = null;
diff --git a/NMS/NMS-API/pom.xml b/NMS/NMS-API/pom.xml
index d5c067bf..c11546b1 100644
--- a/NMS/NMS-API/pom.xml
+++ b/NMS/NMS-API/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_10_R1/pom.xml b/NMS/NMS-v1_10_R1/pom.xml
index 8146f6d4..f4ce6d82 100644
--- a/NMS/NMS-v1_10_R1/pom.xml
+++ b/NMS/NMS-v1_10_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_11_R1/pom.xml b/NMS/NMS-v1_11_R1/pom.xml
index af6fe72f..2575ce37 100644
--- a/NMS/NMS-v1_11_R1/pom.xml
+++ b/NMS/NMS-v1_11_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_12_R1/pom.xml b/NMS/NMS-v1_12_R1/pom.xml
index 5c9b4faa..0d56b267 100644
--- a/NMS/NMS-v1_12_R1/pom.xml
+++ b/NMS/NMS-v1_12_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_13_R1/pom.xml b/NMS/NMS-v1_13_R1/pom.xml
index ed524b6a..9173d889 100644
--- a/NMS/NMS-v1_13_R1/pom.xml
+++ b/NMS/NMS-v1_13_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_13_R2/pom.xml b/NMS/NMS-v1_13_R2/pom.xml
index bed9ab34..b0ea71c5 100644
--- a/NMS/NMS-v1_13_R2/pom.xml
+++ b/NMS/NMS-v1_13_R2/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_14_R1/pom.xml b/NMS/NMS-v1_14_R1/pom.xml
index 8279f619..8f5a3bfd 100644
--- a/NMS/NMS-v1_14_R1/pom.xml
+++ b/NMS/NMS-v1_14_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_15_R1/pom.xml b/NMS/NMS-v1_15_R1/pom.xml
index 1b381d39..94642375 100644
--- a/NMS/NMS-v1_15_R1/pom.xml
+++ b/NMS/NMS-v1_15_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_16_R1/pom.xml b/NMS/NMS-v1_16_R1/pom.xml
index 179554ca..a246339e 100644
--- a/NMS/NMS-v1_16_R1/pom.xml
+++ b/NMS/NMS-v1_16_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_16_R2/pom.xml b/NMS/NMS-v1_16_R2/pom.xml
index 5b6763d8..6ec6a862 100644
--- a/NMS/NMS-v1_16_R2/pom.xml
+++ b/NMS/NMS-v1_16_R2/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_16_R3/pom.xml b/NMS/NMS-v1_16_R3/pom.xml
new file mode 100644
index 00000000..6f4566f0
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/pom.xml
@@ -0,0 +1,29 @@
+
+
+
+ com.songoda
+ SongodaCore-Modules
+ 2.4.21
+ ../../
+
+
+ SongodaCore-NMS-v1_16_R3
+
+ 4.0.0
+ jar
+
+
+
+ org.spigotmc
+ spigot
+ 1.16.4
+ provided
+
+
+ com.songoda
+ SongodaCore-NMS-API
+ ${project.version}
+ provided
+
+
+
\ No newline at end of file
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilCore.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilCore.java
new file mode 100644
index 00000000..53ea5814
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilCore.java
@@ -0,0 +1,23 @@
+package com.songoda.core.nms.v1_16_R3.anvil;
+
+import com.songoda.core.nms.anvil.CustomAnvil;
+import net.minecraft.server.v1_16_R3.EntityPlayer;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+
+public class AnvilCore implements com.songoda.core.nms.anvil.AnvilCore {
+
+ @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_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilInventoryCustom.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilInventoryCustom.java
new file mode 100644
index 00000000..ba067f2a
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilInventoryCustom.java
@@ -0,0 +1,22 @@
+package com.songoda.core.nms.v1_16_R3.anvil;
+
+import net.minecraft.server.v1_16_R3.ContainerAnvil;
+import net.minecraft.server.v1_16_R3.IInventory;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_16_R3.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_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilView.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilView.java
new file mode 100644
index 00000000..b60763ae
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/anvil/AnvilView.java
@@ -0,0 +1,221 @@
+package com.songoda.core.nms.v1_16_R3.anvil;
+
+import com.songoda.core.nms.anvil.CustomAnvil;
+import com.songoda.core.nms.anvil.methods.AnvilTextChange;
+import net.minecraft.server.v1_16_R3.*;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.ItemStack;
+
+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;
+
+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 = ContainerAnvilAbstract.class.getDeclaredField("repairInventory");
+ mc_ContainerAnvil_repairInventory.setAccessible(true);
+ mc_ContainerAnvil_resultInventory = ContainerAnvilAbstract.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);
+ }
+
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTCompoundImpl.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTCompoundImpl.java
new file mode 100644
index 00000000..031640ed
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTCompoundImpl.java
@@ -0,0 +1,193 @@
+package com.songoda.core.nms.v1_16_R3.nbt;
+
+import com.songoda.core.nms.nbt.NBTCompound;
+import com.songoda.core.nms.nbt.NBTObject;
+import net.minecraft.server.v1_16_R3.NBTCompressedStreamTools;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.util.Set;
+import java.util.UUID;
+
+public class NBTCompoundImpl implements NBTCompound {
+
+ protected NBTTagCompound compound;
+
+ protected NBTCompoundImpl(NBTTagCompound compound) {
+ this.compound = compound;
+ }
+
+ public NBTCompoundImpl() {
+ this.compound = new NBTTagCompound();
+ }
+
+ @Override
+ public NBTCompound set(String tag, String s) {
+ compound.setString(tag, s);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, boolean b) {
+ compound.setBoolean(tag, b);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, int i) {
+ compound.setInt(tag, i);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, double i) {
+ compound.setDouble(tag, i);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, long l) {
+ compound.setLong(tag, l);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, short s) {
+ compound.setShort(tag, s);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, byte b) {
+ compound.setByte(tag, b);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, int[] i) {
+ compound.setIntArray(tag, i);
+ return this;
+ }
+
+ @Override
+ public NBTCompound set(String tag, UUID u) {
+ compound.a(tag, u);
+ return this;
+ }
+
+ @Override
+ public NBTCompound remove(String tag) {
+ compound.remove(tag);
+ return this;
+ }
+
+ @Override
+ public boolean has(String tag) {
+ return compound.hasKey(tag);
+ }
+
+ @Override
+ public NBTObject getNBTObject(String tag) {
+ return new NBTObjectImpl(compound, tag);
+ }
+
+ @Override
+ public String getString(String tag) {
+ return getNBTObject(tag).asString();
+ }
+
+ @Override
+ public boolean getBoolean(String tag) {
+ return getNBTObject(tag).asBoolean();
+ }
+
+ @Override
+ public int getInt(String tag) {
+ return getNBTObject(tag).asInt();
+ }
+
+ @Override
+ public double getDouble(String tag) {
+ return getNBTObject(tag).asDouble();
+ }
+
+ @Override
+ public long getLong(String tag) {
+ return getNBTObject(tag).asLong();
+ }
+
+ @Override
+ public short getShort(String tag) {
+ return getNBTObject(tag).asShort();
+ }
+
+ @Override
+ public byte getByte(String tag) {
+ return getNBTObject(tag).asByte();
+ }
+
+ @Override
+ public int[] getIntArray(String tag) {
+ return getNBTObject(tag).asIntArray();
+ }
+
+ @Override
+ public NBTCompound getCompound(String tag) {
+ if (has(tag)) {
+ return getNBTObject(tag).asCompound();
+ } else {
+ NBTTagCompound newCompound = new NBTTagCompound();
+ compound.set(tag, newCompound);
+ return new NBTCompoundImpl(newCompound);
+ }
+ }
+
+ @Override
+ public Set getKeys() {
+ return compound.getKeys();
+ }
+
+ @Override
+ public Set getKeys(String tag) {
+ return compound.getCompound(tag).getKeys();
+ }
+
+ @Override
+ public byte[] serialize(String... exclusions) {
+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ObjectOutputStream dataOutput = new ObjectOutputStream(outputStream)) {
+ addExtras();
+ NBTTagCompound compound = this.compound.clone();
+
+ for (String exclusion : exclusions)
+ compound.remove(exclusion);
+
+ NBTCompressedStreamTools.a(compound, (OutputStream) dataOutput);
+
+ return outputStream.toByteArray();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public void deSerialize(byte[] serialized) {
+ try (ByteArrayInputStream inputStream = new ByteArrayInputStream(serialized);
+ ObjectInputStream dataInput = new ObjectInputStream(inputStream)) {
+ compound = NBTCompressedStreamTools.a((InputStream) dataInput);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void addExtras() {
+ // None
+ }
+}
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTCoreImpl.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTCoreImpl.java
new file mode 100644
index 00000000..fcf160a9
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTCoreImpl.java
@@ -0,0 +1,37 @@
+package com.songoda.core.nms.v1_16_R3.nbt;
+
+import com.songoda.core.nms.nbt.NBTCore;
+import com.songoda.core.nms.nbt.NBTEntity;
+import com.songoda.core.nms.nbt.NBTItem;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Entity;
+import org.bukkit.inventory.ItemStack;
+
+public class NBTCoreImpl implements NBTCore {
+
+ @Override
+ public NBTItem of(ItemStack item) {
+ return new NBTItemImpl(CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public NBTItem newItem() {
+ return new NBTItemImpl(null);
+ }
+
+ @Override
+ public NBTEntity of(Entity entity) {
+ net.minecraft.server.v1_16_R3.Entity nmsEntity = ((CraftEntity) entity).getHandle();
+ NBTTagCompound nbt = new NBTTagCompound();
+ nmsEntity.save(nbt);
+ return new NBTEntityImpl(nbt, nmsEntity);
+ }
+
+ @Override
+ public NBTEntity newEntity() {
+ return new NBTEntityImpl(new NBTTagCompound(), null);
+ }
+
+}
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTEntityImpl.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTEntityImpl.java
new file mode 100644
index 00000000..c39af315
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTEntityImpl.java
@@ -0,0 +1,62 @@
+package com.songoda.core.nms.v1_16_R3.nbt;
+
+import com.songoda.core.nms.nbt.NBTEntity;
+import net.minecraft.server.v1_16_R3.BlockPosition;
+import net.minecraft.server.v1_16_R3.Entity;
+import net.minecraft.server.v1_16_R3.EntityTypes;
+import net.minecraft.server.v1_16_R3.EnumMobSpawn;
+import net.minecraft.server.v1_16_R3.IRegistry;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
+
+import java.util.Optional;
+
+public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity {
+
+ private Entity nmsEntity;
+
+ public NBTEntityImpl(NBTTagCompound entityNBT, Entity nmsEntity) {
+ super(entityNBT);
+ this.nmsEntity = nmsEntity;
+ }
+
+ @Override
+ public org.bukkit.entity.Entity spawn(Location location) {
+ String entityType = getNBTObject("entity_type").asString();
+
+ Optional> optionalEntity = EntityTypes.a(entityType);
+ if (optionalEntity.isPresent()) {
+ Entity spawned = optionalEntity.get().spawnCreature(
+ ((CraftWorld) location.getWorld()).getHandle(),
+ compound,
+ null,
+ null,
+ new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()),
+ EnumMobSpawn.COMMAND,
+ true,
+ false
+ );
+
+ if (spawned != null) {
+ spawned.load(compound);
+ org.bukkit.entity.Entity entity = spawned.getBukkitEntity();
+ entity.teleport(location);
+ nmsEntity = spawned;
+ return entity;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public org.bukkit.entity.Entity reSpawn(Location location) {
+ nmsEntity.dead = true;
+ return spawn(location);
+ }
+
+ @Override
+ public void addExtras() {
+ compound.setString("entity_type", IRegistry.ENTITY_TYPE.getKey(nmsEntity.getEntityType()).toString());
+ }
+}
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTItemImpl.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTItemImpl.java
new file mode 100644
index 00000000..9361d85b
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTItemImpl.java
@@ -0,0 +1,28 @@
+package com.songoda.core.nms.v1_16_R3.nbt;
+
+import com.songoda.core.nms.nbt.NBTItem;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.inventory.ItemStack;
+
+public class NBTItemImpl extends NBTCompoundImpl implements NBTItem {
+
+ private net.minecraft.server.v1_16_R3.ItemStack nmsItem;
+
+ public NBTItemImpl(net.minecraft.server.v1_16_R3.ItemStack nmsItem) {
+ super(nmsItem != null && nmsItem.hasTag() ? nmsItem.getTag() : new NBTTagCompound());
+ this.nmsItem = nmsItem;
+ }
+
+ public ItemStack finish() {
+ if (nmsItem == null) {
+ return CraftItemStack.asBukkitCopy(net.minecraft.server.v1_16_R3.ItemStack.a(compound));
+ } else {
+ return CraftItemStack.asBukkitCopy(nmsItem);
+ }
+ }
+
+ @Override
+ public void addExtras() {
+ }
+}
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTObjectImpl.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTObjectImpl.java
new file mode 100644
index 00000000..bb3f2b08
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/nbt/NBTObjectImpl.java
@@ -0,0 +1,68 @@
+package com.songoda.core.nms.v1_16_R3.nbt;
+
+import com.songoda.core.nms.nbt.NBTCompound;
+import com.songoda.core.nms.nbt.NBTObject;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+
+import java.util.Set;
+
+public class NBTObjectImpl implements NBTObject {
+
+ private final NBTTagCompound compound;
+ private final String tag;
+
+ public NBTObjectImpl(NBTTagCompound compound, String tag) {
+ this.compound = compound;
+ this.tag = tag;
+ }
+
+ @Override
+ public String asString() {
+ return compound.getString(tag);
+ }
+
+ @Override
+ public boolean asBoolean() {
+ return compound.getBoolean(tag);
+ }
+
+ @Override
+ public int asInt() {
+ return compound.getInt(tag);
+ }
+
+ @Override
+ public double asDouble() {
+ return compound.getDouble(tag);
+ }
+
+ @Override
+ public long asLong() {
+ return compound.getLong(tag);
+ }
+
+ @Override
+ public short asShort() {
+ return compound.getShort(tag);
+ }
+
+ @Override
+ public byte asByte() {
+ return compound.getByte(tag);
+ }
+
+ @Override
+ public int[] asIntArray() {
+ return compound.getIntArray(tag);
+ }
+
+ @Override
+ public NBTCompound asCompound() {
+ return new NBTCompoundImpl(compound.getCompound(tag));
+ }
+
+ @Override
+ public Set getKeys() {
+ return compound.getKeys();
+ }
+}
diff --git a/NMS/NMS-v1_8_R1/pom.xml b/NMS/NMS-v1_8_R1/pom.xml
index a629f69c..0fcacbb3 100644
--- a/NMS/NMS-v1_8_R1/pom.xml
+++ b/NMS/NMS-v1_8_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_8_R2/pom.xml b/NMS/NMS-v1_8_R2/pom.xml
index 08818378..0a2fb6ee 100644
--- a/NMS/NMS-v1_8_R2/pom.xml
+++ b/NMS/NMS-v1_8_R2/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_8_R3/pom.xml b/NMS/NMS-v1_8_R3/pom.xml
index 30859828..331b4197 100644
--- a/NMS/NMS-v1_8_R3/pom.xml
+++ b/NMS/NMS-v1_8_R3/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_9_R1/pom.xml b/NMS/NMS-v1_9_R1/pom.xml
index c5b7cc1e..9a2cb6e4 100644
--- a/NMS/NMS-v1_9_R1/pom.xml
+++ b/NMS/NMS-v1_9_R1/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/NMS/NMS-v1_9_R2/pom.xml b/NMS/NMS-v1_9_R2/pom.xml
index 1979aa6e..373dd254 100644
--- a/NMS/NMS-v1_9_R2/pom.xml
+++ b/NMS/NMS-v1_9_R2/pom.xml
@@ -3,7 +3,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
../../
diff --git a/pom.xml b/pom.xml
index 832520a5..e55fd1ff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
com.songoda
SongodaCore-Modules
- 2.4.20
+ 2.4.21
4.0.0
pom
@@ -23,6 +23,7 @@
NMS/NMS-v1_15_R1
NMS/NMS-v1_16_R1
NMS/NMS-v1_16_R2
+ NMS/NMS-v1_16_R3