diff --git a/NMS/pom.xml b/NMS/pom.xml
index adf015d8..922108f0 100644
--- a/NMS/pom.xml
+++ b/NMS/pom.xml
@@ -28,6 +28,7 @@
 		<module>v1_15_R1</module>
 		<module>v1_16_R1</module>
 		<module>v1_16_R2</module>
+		<module>v1_16_R3</module>
 	</modules>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/NMS/v1_16_R3/pom.xml b/NMS/v1_16_R3/pom.xml
new file mode 100644
index 00000000..23afc8d4
--- /dev/null
+++ b/NMS/v1_16_R3/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>com.gmail.filoghost.holographicdisplays</groupId>
+		<artifactId>holographicdisplays-nms</artifactId>
+		<version>2.4.5-SNAPSHOT</version>
+	</parent>
+
+	<artifactId>holographicdisplays-nms-v1_16_r3</artifactId>
+	<name>HolographicDisplays NMS v1_16_R3</name>
+
+	<repositories>
+		<repository>
+			<id>nms-repo</id>
+			<url>https://repo.codemc.io/repository/nms/</url>
+		</repository>
+	</repositories>
+
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>holographicdisplays-nms-interfaces</artifactId>
+		</dependency>
+		
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>holographicdisplays-utils</artifactId>
+		</dependency>
+		
+		<dependency>
+			<groupId>org.spigotmc</groupId>
+			<artifactId>spigot</artifactId>
+			<version>1.16.4-R0.1-SNAPSHOT</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+
+</project>
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSArmorStand.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSArmorStand.java
new file mode 100644
index 00000000..ffd6c879
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSArmorStand.java
@@ -0,0 +1,96 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import java.util.Collection;
+
+import org.bukkit.EntityEffect;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_16_R3.CraftServer;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftArmorStand;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.util.EulerAngle;
+import org.bukkit.util.Vector;
+
+public class CraftNMSArmorStand extends CraftArmorStand {
+
+	public CraftNMSArmorStand(CraftServer server, EntityNMSArmorStand entity) {
+		super(server, entity);
+	}
+	
+	// Disallow all the bukkit methods.
+	
+	@Override
+	public void remove() {
+		// Cannot be removed, this is the most important to override.
+	}
+
+	// Methods from ArmorStand class
+	@Override public void setArms(boolean arms) { }
+	@Override public void setBasePlate(boolean basePlate) { }
+	@Override public void setBodyPose(EulerAngle pose) { }
+	@Override public void setBoots(ItemStack item) { }
+	@Override public void setChestplate(ItemStack item) { }
+	@Override public void setHeadPose(EulerAngle pose) { }
+	@Override public void setHelmet(ItemStack item) { }
+	@Override public void setItemInHand(ItemStack item) { }
+	@Override public void setLeftArmPose(EulerAngle pose) { }
+	@Override public void setLeftLegPose(EulerAngle pose) { }
+	@Override public void setLeggings(ItemStack item) { }
+	@Override public void setRightArmPose(EulerAngle pose) { }
+	@Override public void setRightLegPose(EulerAngle pose) { }
+	@Override public void setSmall(boolean small) { }
+	@Override public void setVisible(boolean visible) { }
+	@Override public void setMarker(boolean marker) { }
+
+	// Methods from LivingEntity class
+	@Override public boolean addPotionEffect(PotionEffect effect) { return false; }
+	@Override public boolean addPotionEffect(PotionEffect effect, boolean param) { return false; }
+	@Override public boolean addPotionEffects(Collection<PotionEffect> effects) { return false; }
+	@Override public void setRemoveWhenFarAway(boolean remove) { }
+	@Override public void setAI(boolean ai) { }
+	@Override public void setCanPickupItems(boolean pickup) { }
+	@Override public void setCollidable(boolean collidable) { }
+	@Override public void setGliding(boolean gliding) {	}
+	@Override public boolean setLeashHolder(Entity holder) { return false; }
+	@Override public void setSwimming(boolean swimming) { }
+	
+	// Methods from Entity class
+	@Override public void setVelocity(Vector vel) { }
+	@Override public boolean teleport(Location loc) { return false; }
+	@Override public boolean teleport(Entity entity) { return false; }
+	@Override public boolean teleport(Location loc, TeleportCause cause) { return false; }
+	@Override public boolean teleport(Entity entity, TeleportCause cause) { return false; }
+	@Override public void setFireTicks(int ticks) { }
+	@Override public boolean setPassenger(Entity entity) { return false; }
+	@Override public boolean eject() { return false; }
+	@Override public boolean leaveVehicle() { return false; }
+	@Override public void playEffect(EntityEffect effect) { }
+	@Override public void setCustomName(String name) { }
+	@Override public void setCustomNameVisible(boolean flag) { }
+	@Override public void setGlowing(boolean flag) { }
+	@Override public void setGravity(boolean gravity) { }
+	@Override public void setInvulnerable(boolean flag) { }
+	@Override public void setMomentum(Vector value) { }
+	@Override public void setSilent(boolean flag) { }
+	@Override public void setTicksLived(int value) { }
+	@Override public void setPersistent(boolean flag) { }
+	@Override public void setRotation(float yaw, float pitch) { }
+	
+	
+}
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSItem.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSItem.java
new file mode 100644
index 00000000..6b252b15
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSItem.java
@@ -0,0 +1,65 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import org.bukkit.EntityEffect;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_16_R3.CraftServer;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftItem;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.util.Vector;
+
+public class CraftNMSItem extends CraftItem {
+
+	public CraftNMSItem(CraftServer server, EntityNMSItem entity) {
+		super(server, entity);
+	}
+
+	// Disallow all the bukkit methods.
+	
+	@Override
+	public void remove() {
+		// Cannot be removed, this is the most important to override.
+	}
+	
+	// Methods from Item class
+	@Override public void setItemStack(ItemStack stack) { }
+	@Override public void setPickupDelay(int delay) { }
+
+	// Methods from Entity class
+	@Override public void setVelocity(Vector vel) { }
+	@Override public boolean teleport(Location loc) { return false; }
+	@Override public boolean teleport(Entity entity) { return false; }
+	@Override public boolean teleport(Location loc, TeleportCause cause) { return false; }
+	@Override public boolean teleport(Entity entity, TeleportCause cause) { return false; }
+	@Override public void setFireTicks(int ticks) { }
+	@Override public boolean setPassenger(Entity entity) { return false; }
+	@Override public boolean eject() { return false; }
+	@Override public boolean leaveVehicle() { return false; }
+	@Override public void playEffect(EntityEffect effect) { }
+	@Override public void setCustomName(String name) { }
+	@Override public void setCustomNameVisible(boolean flag) { }
+	@Override public void setGlowing(boolean flag) { }
+	@Override public void setGravity(boolean gravity) { }
+	@Override public void setInvulnerable(boolean flag) { }
+	@Override public void setMomentum(Vector value) { }
+	@Override public void setSilent(boolean flag) { }
+	@Override public void setTicksLived(int value) { }
+	@Override public void setPersistent(boolean flag) { }
+	@Override public void setRotation(float yaw, float pitch) { }
+	
+}
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSSlime.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSSlime.java
new file mode 100644
index 00000000..38e57629
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/CraftNMSSlime.java
@@ -0,0 +1,85 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import java.util.Collection;
+
+import org.bukkit.EntityEffect;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_16_R3.CraftServer;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftSlime;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.bukkit.loot.LootTable;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.util.Vector;
+
+public class CraftNMSSlime extends CraftSlime {
+
+	public CraftNMSSlime(CraftServer server, EntityNMSSlime entity) {
+		super(server, entity);
+	}
+	
+	// Disallow all the bukkit methods.
+	
+	@Override
+	public void remove() {
+		// Cannot be removed, this is the most important to override.
+	}
+	
+	// Methods from Slime class
+	@Override public void setSize(int size) { }
+	@Override public void setTarget(LivingEntity target) { }
+	
+	// Methods from Mob class
+	@Override public void setLootTable(LootTable table) { }
+	@Override public void setSeed(long seed) { }
+	
+	// Methods from LivingEntity class
+	@Override public boolean addPotionEffect(PotionEffect effect) { return false; }
+	@Override public boolean addPotionEffect(PotionEffect effect, boolean param) { return false; }
+	@Override public boolean addPotionEffects(Collection<PotionEffect> effects) { return false; }
+	@Override public void setRemoveWhenFarAway(boolean remove) { }
+	@Override public void setAI(boolean ai) { }
+	@Override public void setCanPickupItems(boolean pickup) { }
+	@Override public void setCollidable(boolean collidable) { }
+	@Override public void setGliding(boolean gliding) {	}
+	@Override public boolean setLeashHolder(Entity holder) { return false; }
+	@Override public void setSwimming(boolean swimming) { }
+
+	// Methods from Entity class
+	@Override public void setVelocity(Vector vel) { }
+	@Override public boolean teleport(Location loc) { return false; }
+	@Override public boolean teleport(Entity entity) { return false; }
+	@Override public boolean teleport(Location loc, TeleportCause cause) { return false; }
+	@Override public boolean teleport(Entity entity, TeleportCause cause) { return false; }
+	@Override public void setFireTicks(int ticks) { }
+	@Override public boolean setPassenger(Entity entity) { return false; }
+	@Override public boolean eject() { return false; }
+	@Override public boolean leaveVehicle() { return false; }
+	@Override public void playEffect(EntityEffect effect) { }
+	@Override public void setCustomName(String name) { }
+	@Override public void setCustomNameVisible(boolean flag) { }
+	@Override public void setGlowing(boolean flag) { }
+	@Override public void setGravity(boolean gravity) { }
+	@Override public void setInvulnerable(boolean flag) { }
+	@Override public void setMomentum(Vector value) { }
+	@Override public void setSilent(boolean flag) { }
+	@Override public void setTicksLived(int value) { }
+	@Override public void setPersistent(boolean flag) { }
+	@Override public void setRotation(float yaw, float pitch) { }
+
+}
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSArmorStand.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSArmorStand.java
new file mode 100644
index 00000000..231a6ad6
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSArmorStand.java
@@ -0,0 +1,231 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import com.gmail.filoghost.holographicdisplays.api.line.HologramLine;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSArmorStand;
+import com.gmail.filoghost.holographicdisplays.util.Utils;
+import net.minecraft.server.v1_16_R3.*;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_16_R3.util.CraftChatMessage;
+
+public class EntityNMSArmorStand extends EntityArmorStand implements NMSArmorStand {
+
+    private HologramLine parentPiece;
+    private CraftEntity customBukkitEntity;
+    private String customName;
+
+    public EntityNMSArmorStand(World world, HologramLine parentPiece) {
+        super(EntityTypes.ARMOR_STAND, world);
+        super.setInvisible(true);
+        super.setSmall(true);
+        super.setArms(false);
+        super.setNoGravity(true);
+        super.setBasePlate(true);
+        super.setMarker(true);
+        super.collides = false;
+        this.parentPiece = parentPiece;
+        forceSetBoundingBox(new NullBoundingBox());
+        
+        this.onGround = true; // Workaround to force EntityTrackerEntry to send a teleport packet.
+    }
+    
+	@Override
+	public void tick() {
+		// Disable normal ticking for this entity.
+		
+		// Workaround to force EntityTrackerEntry to send a teleport packet immediately after spawning this entity.
+		if (this.onGround) {
+			this.onGround = false;
+		}
+	}
+	
+	@Override
+	public void inactiveTick() {
+		// Disable normal ticking for this entity.
+		
+		// Workaround to force EntityTrackerEntry to send a teleport packet immediately after spawning this entity.
+		if (this.onGround) {
+			this.onGround = false;
+		}
+	}
+
+    @Override
+    public void saveData(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+    }
+
+    @Override
+    public boolean a_(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+        return false;
+    }
+
+    @Override
+    public boolean d(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+        return false;
+    }
+
+    @Override
+    public NBTTagCompound save(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+        return nbttagcompound;
+    }
+
+    @Override
+    public void load(NBTTagCompound nbttagcompound) {
+        // Do not load NBT.
+    }
+
+    @Override
+    public void loadData(NBTTagCompound nbttagcompound) {
+        // Do not load NBT.
+    }
+
+    @Override
+    public boolean isInvulnerable(DamageSource source) {
+        /*
+         * The field Entity.invulnerable is private.
+         * It's only used while saving NBTTags, but since the entity would be killed
+         * on chunk unload, we prefer to override isInvulnerable().
+         */
+        return true;
+    }
+
+    @Override
+    public boolean isCollidable() {
+        return false;
+    }
+
+    @Override
+    public void setCustomName(IChatBaseComponent ichatbasecomponent) {
+        // Locks the custom name.
+    }
+
+    @Override
+    public void setCustomNameVisible(boolean visible) {
+        // Locks the custom name.
+    }
+
+    @Override
+    public EnumInteractionResult a(EntityHuman human, Vec3D vec3d, EnumHand enumhand) {
+        // Prevent stand being equipped
+        return EnumInteractionResult.PASS;
+    }
+
+    @Override
+    public boolean a_(int i, ItemStack item) {
+        // Prevent stand being equipped
+        return false;
+    }
+
+    @Override
+    public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) {
+        // Prevent stand being equipped
+    }
+
+    @Override
+    public void a(AxisAlignedBB boundingBox) {
+        // Do not change it!
+    }
+
+    public void forceSetBoundingBox(AxisAlignedBB boundingBox) {
+        super.a(boundingBox);
+    }
+    
+    @Override
+    public void playSound(SoundEffect soundeffect, float f, float f1) {
+        // Remove sounds.
+    }
+
+    @Override
+    public void setCustomNameNMS(String name) {
+        this.customName = Utils.limitLength(name, 300);
+        super.setCustomName(CraftChatMessage.fromStringOrNull(customName));
+        super.setCustomNameVisible(customName != null && !customName.isEmpty());
+    }
+
+    @Override
+    public String getCustomNameStringNMS() {
+        return this.customName;
+    }
+    
+	@Override
+	public Object getCustomNameObjectNMS() {
+		return super.getCustomName();
+	}
+
+    @Override
+    public void die() {
+        // Prevent being killed.
+    }
+
+    @Override
+    public CraftEntity getBukkitEntity() {
+        if (customBukkitEntity == null) {
+            customBukkitEntity = new CraftNMSArmorStand(super.world.getServer(), this);
+        }
+        return customBukkitEntity;
+    }
+
+    @Override
+    public void killEntityNMS() {
+        super.dead = true;
+    }
+
+    @Override
+    public void setLocationNMS(double x, double y, double z, boolean broadcastLocationPacket) {
+        super.setPosition(x, y, z);
+        if (broadcastLocationPacket) {
+        	broadcastLocationPacketNMS();
+        }
+    }
+    
+    private void broadcastLocationPacketNMS() {
+        PacketPlayOutEntityTeleport teleportPacket = new PacketPlayOutEntityTeleport(this);
+
+        for (Object obj : super.world.getPlayers()) {
+            if (obj instanceof EntityPlayer) {
+                EntityPlayer nmsPlayer = (EntityPlayer) obj;
+
+                double distanceSquared = Utils.square(nmsPlayer.locX() - super.locX()) + Utils.square(nmsPlayer.locZ() - super.locZ());
+                if (distanceSquared < 8192 && nmsPlayer.playerConnection != null) {
+                    nmsPlayer.playerConnection.sendPacket(teleportPacket);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean isDeadNMS() {
+        return super.dead;
+    }
+
+    @Override
+    public int getIdNMS() {
+        return super.getId();
+    }
+
+    @Override
+    public HologramLine getHologramLine() {
+        return parentPiece;
+    }
+
+    @Override
+    public org.bukkit.entity.Entity getBukkitEntityNMS() {
+        return getBukkitEntity();
+    }
+}
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSItem.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSItem.java
new file mode 100644
index 00000000..834479fd
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSItem.java
@@ -0,0 +1,249 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import java.util.logging.Level;
+
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+
+import com.gmail.filoghost.holographicdisplays.api.line.ItemLine;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.ItemPickupManager;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSEntityBase;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSItem;
+import com.gmail.filoghost.holographicdisplays.util.ConsoleLogger;
+import com.gmail.filoghost.holographicdisplays.util.ItemUtils;
+import com.gmail.filoghost.holographicdisplays.util.reflection.ReflectField;
+
+import net.minecraft.server.v1_16_R3.Blocks;
+import net.minecraft.server.v1_16_R3.DamageSource;
+import net.minecraft.server.v1_16_R3.Entity;
+import net.minecraft.server.v1_16_R3.EntityHuman;
+import net.minecraft.server.v1_16_R3.EntityItem;
+import net.minecraft.server.v1_16_R3.EntityPlayer;
+import net.minecraft.server.v1_16_R3.EntityTypes;
+import net.minecraft.server.v1_16_R3.ItemStack;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+import net.minecraft.server.v1_16_R3.NBTTagList;
+import net.minecraft.server.v1_16_R3.NBTTagString;
+import net.minecraft.server.v1_16_R3.World;
+
+public class EntityNMSItem extends EntityItem implements NMSItem {
+
+    private static final ReflectField<Entity> VEHICLE_FIELD = new ReflectField<>(Entity.class, "vehicle");
+
+    private ItemLine parentPiece;
+    private ItemPickupManager itemPickupManager;
+    private CraftEntity customBukkitEntity;
+
+    public EntityNMSItem(World world, ItemLine piece, ItemPickupManager itemPickupManager) {
+        super(EntityTypes.ITEM, world);
+        super.pickupDelay = 32767; // Lock the item pickup delay, also prevents entities from picking up the item
+        this.parentPiece = piece;
+        this.itemPickupManager = itemPickupManager;
+    }
+
+    @Override
+    public void tick() {
+    	// Disable normal ticking for this entity.
+
+        // So it won't get removed.
+        ticksLived = 0;
+    }
+    
+    @Override
+	public void inactiveTick() {
+		// Disable normal ticking for this entity.
+    	
+    	// So it won't get removed.
+    	ticksLived = 0;
+	}
+
+    // Method called when a player is near.
+    @Override
+    public void pickup(EntityHuman human) {
+
+        if (human.locY() < super.locY() - 1.5 || human.locY() > super.locY() + 1.0) {
+            // Too low or too high, it's a bit weird./
+            return;
+        }
+
+        if (parentPiece.getPickupHandler() != null && human instanceof EntityPlayer) {
+            itemPickupManager.handleItemLinePickup((Player) human.getBukkitEntity(), parentPiece.getPickupHandler(), parentPiece.getParent());
+            // It is never added to the inventory.
+        }
+    }
+
+    @Override
+    public void saveData(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+    }
+
+    @Override
+    public boolean a_(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+        return false;
+    }
+
+    @Override
+    public boolean d(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+        return false;
+    }
+
+    @Override
+    public NBTTagCompound save(NBTTagCompound nbttagcompound) {
+        // Do not save NBT.
+        return nbttagcompound;
+    }
+
+    @Override
+    public void load(NBTTagCompound nbttagcompound) {
+        // Do not load NBT.
+    }
+
+    @Override
+    public void loadData(NBTTagCompound nbttagcompound) {
+        // Do not load NBT.
+    }
+
+    @Override
+    public boolean isInvulnerable(DamageSource source) {
+        /*
+         * The field Entity.invulnerable is private.
+         * It's only used while saving NBTTags, but since the entity would be killed
+         * on chunk unload, we prefer to override isInvulnerable().
+         */
+        return true;
+    }
+
+    @Override
+    public boolean isCollidable() {
+        return false;
+    }
+    
+    @Override
+    public void die() {
+        // Prevent being killed.
+    }
+
+    @Override
+    public boolean isAlive() {
+        // This override prevents items from being picked up by hoppers.
+        // Should have no side effects.
+        return false;
+    }
+
+    @Override
+    public CraftEntity getBukkitEntity() {
+        if (customBukkitEntity == null) {
+            customBukkitEntity = new CraftNMSItem(super.world.getServer(), this);
+        }
+        return customBukkitEntity;
+    }
+
+    @Override
+    public boolean isDeadNMS() {
+        return super.dead;
+    }
+
+    @Override
+    public void killEntityNMS() {
+        super.dead = true;
+    }
+
+    @Override
+    public void setLocationNMS(double x, double y, double z) {
+        super.setPosition(x, y, z);
+    }
+
+    @Override
+    public void setItemStackNMS(org.bukkit.inventory.ItemStack stack) {
+        ItemStack newItem = CraftItemStack.asNMSCopy(stack); // ItemStack.a is returned if the stack is null, invalid or the material is not an Item
+
+        if (newItem == null || newItem == ItemStack.b) {
+            newItem = new ItemStack(Blocks.BEDROCK);
+        }
+
+        if (newItem.getTag() == null) {
+            newItem.setTag(new NBTTagCompound());
+        }
+        NBTTagCompound display = newItem.getTag().getCompound("display"); // Returns a new NBTTagCompound if not existing
+        if (!newItem.getTag().hasKey("display")) {
+            newItem.getTag().set("display", display);
+        }
+
+        NBTTagList tagList = new NBTTagList();
+        tagList.add(NBTTagString.a(ItemUtils.ANTISTACK_LORE)); // Antistack lore
+        display.set("Lore", tagList);
+
+        setItemStack(newItem);
+    }
+
+    @Override
+    public int getIdNMS() {
+        return super.getId();
+    }
+
+    @Override
+    public ItemLine getHologramLine() {
+        return parentPiece;
+    }
+
+    @Override
+    public void allowPickup(boolean pickup) {
+        if (pickup) {
+            super.pickupDelay = 0;
+        } else {
+            super.pickupDelay = 32767;
+        }
+    }
+
+    @Override
+    public org.bukkit.entity.Entity getBukkitEntityNMS() {
+        return getBukkitEntity();
+    }
+
+    @Override
+    public void setPassengerOfNMS(NMSEntityBase vehicleBase) {
+        if (vehicleBase == null || !(vehicleBase instanceof Entity)) {
+            // It should never dismount
+            return;
+        }
+
+        Entity entity = (Entity) vehicleBase;
+
+        try {
+            if (super.getVehicle() != null) {
+                Entity oldVehicle = super.getVehicle();
+                VEHICLE_FIELD.set(this, null);
+                oldVehicle.passengers.remove(this);
+            }
+
+            VEHICLE_FIELD.set(this, entity);
+            entity.passengers.clear();
+            entity.passengers.add(this);
+
+        } catch (Throwable t) {
+            ConsoleLogger.logDebug(Level.SEVERE, "Couldn't set passenger", t);
+        }
+    }
+
+    @Override
+    public Object getRawItemStack() {
+        return super.getItemStack();
+    }
+}
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSSlime.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSSlime.java
new file mode 100644
index 00000000..2c734b00
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/EntityNMSSlime.java
@@ -0,0 +1,225 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import java.util.logging.Level;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEntity;
+import org.bukkit.event.player.PlayerInteractEntityEvent;
+
+import com.gmail.filoghost.holographicdisplays.api.line.HologramLine;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSEntityBase;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSSlime;
+import com.gmail.filoghost.holographicdisplays.util.ConsoleLogger;
+import com.gmail.filoghost.holographicdisplays.util.reflection.ReflectField;
+
+import net.minecraft.server.v1_16_R3.AxisAlignedBB;
+import net.minecraft.server.v1_16_R3.DamageSource;
+import net.minecraft.server.v1_16_R3.Entity;
+import net.minecraft.server.v1_16_R3.EntityDamageSource;
+import net.minecraft.server.v1_16_R3.EntityPlayer;
+import net.minecraft.server.v1_16_R3.EntitySlime;
+import net.minecraft.server.v1_16_R3.EntityTypes;
+import net.minecraft.server.v1_16_R3.IChatBaseComponent;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+import net.minecraft.server.v1_16_R3.SoundEffect;
+import net.minecraft.server.v1_16_R3.World;
+
+public class EntityNMSSlime extends EntitySlime implements NMSSlime {
+	
+	private static final ReflectField<Entity> VEHICLE_FIELD = new ReflectField<>(Entity.class, "vehicle");
+
+	private HologramLine parentPiece;
+	private CraftEntity customBukkitEntity;
+	
+	public EntityNMSSlime(World world, HologramLine parentPiece) {
+		super(EntityTypes.SLIME, world);
+		super.persistent = true;
+		super.collides = false;
+		a(0.0F, 0.0F);
+		setSize(1, false);
+		setInvisible(true);
+		this.parentPiece = parentPiece;
+		forceSetBoundingBox(new NullBoundingBox());
+	}
+	
+	@Override
+	public void tick() {
+		// Disable normal ticking for this entity.
+		
+		// So it won't get removed.
+		ticksLived = 0;
+	}
+	
+	@Override
+	public void inactiveTick() {
+		// Disable normal ticking for this entity.
+		
+		// So it won't get removed.
+		ticksLived = 0;
+	}
+	
+	@Override
+	public void a(AxisAlignedBB boundingBox) {
+		// Do not change it!
+	}
+	
+	public void forceSetBoundingBox(AxisAlignedBB boundingBox) {
+		super.a(boundingBox);
+	}
+	
+	@Override
+	public void saveData(NBTTagCompound nbttagcompound) {
+		// Do not save NBT.
+	}
+	
+	@Override
+	public boolean a_(NBTTagCompound nbttagcompound) {
+		// Do not save NBT.
+		return false;
+	}
+
+	@Override
+	public boolean d(NBTTagCompound nbttagcompound) {
+		// Do not save NBT.
+		return false;
+	}
+	
+	@Override
+	public NBTTagCompound save(NBTTagCompound nbttagcompound) {
+		// Do not save NBT.
+		return nbttagcompound;
+	}
+	
+	@Override
+	public void load(NBTTagCompound nbttagcompound) {
+		// Do not load NBT.
+	}
+	
+	@Override
+	public void loadData(NBTTagCompound nbttagcompound) {
+		// Do not load NBT.
+	}
+	
+	@Override
+	public boolean damageEntity(DamageSource damageSource, float amount) {
+		if (damageSource instanceof EntityDamageSource) {
+			EntityDamageSource entityDamageSource = (EntityDamageSource) damageSource;
+			if (entityDamageSource.getEntity() instanceof EntityPlayer) {
+				Bukkit.getPluginManager().callEvent(new PlayerInteractEntityEvent(((EntityPlayer) entityDamageSource.getEntity()).getBukkitEntity(), getBukkitEntity())); // Bukkit takes care of the exceptions
+			}
+		}
+		return false;
+	}
+	
+	@Override
+	public boolean isInvulnerable(DamageSource source) {
+		/*
+		 * The field Entity.invulnerable is private.
+		 * It's only used while saving NBTTags, but since the entity would be killed
+		 * on chunk unload, we prefer to override isInvulnerable().
+		 */
+	    return true;
+	}
+	
+	@Override
+	public boolean isCollidable() {
+		return false;
+	}
+
+	@Override
+	public void setCustomName(IChatBaseComponent ichatbasecomponent) {
+		// Locks the custom name.
+	}
+	
+	@Override
+	public void setCustomNameVisible(boolean visible) {
+		// Locks the custom name.
+	}
+	
+	@Override
+	public void playSound(SoundEffect soundeffect, float f, float f1) {
+	    // Remove sounds.
+	}
+	
+	@Override
+	public void die() {
+		// Prevent being killed.
+	}
+	
+	@Override
+	public CraftEntity getBukkitEntity() {
+		if (customBukkitEntity == null) {
+			customBukkitEntity = new CraftNMSSlime(super.world.getServer(), this);
+	    }
+		return customBukkitEntity;
+	}
+
+	@Override
+	public boolean isDeadNMS() {
+		return super.dead;
+	}
+	
+	@Override
+	public void killEntityNMS() {
+		super.dead = true;
+	}
+	
+	@Override
+	public void setLocationNMS(double x, double y, double z) {
+		super.setPosition(x, y, z);
+	}
+	
+	@Override
+	public int getIdNMS() {
+		return super.getId();
+	}
+	
+	@Override
+	public HologramLine getHologramLine() {
+		return parentPiece;
+	}
+
+	@Override
+	public org.bukkit.entity.Entity getBukkitEntityNMS() {
+		return getBukkitEntity();
+	}
+	
+	@Override
+	public void setPassengerOfNMS(NMSEntityBase vehicleBase) {
+		if (vehicleBase == null || !(vehicleBase instanceof Entity)) {
+			// It should never dismount
+			return;
+		}
+		
+		Entity entity = (Entity) vehicleBase;
+		
+		try {
+			if (super.getVehicle() != null) {
+	        	Entity oldVehicle = super.getVehicle();
+	        	VEHICLE_FIELD.set(this, null);
+	        	oldVehicle.passengers.remove(this);
+	        }
+
+			VEHICLE_FIELD.set(this, entity);
+	        entity.passengers.clear();
+	        entity.passengers.add(this);
+
+		} catch (Throwable t) {
+			ConsoleLogger.logDebug(Level.SEVERE, "Couldn't set passenger", t);
+		}
+	}
+}
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/NmsManagerImpl.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/NmsManagerImpl.java
new file mode 100644
index 00000000..80730ed6
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/NmsManagerImpl.java
@@ -0,0 +1,190 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import java.util.List;
+
+import java.util.Map;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEntity;
+import org.bukkit.inventory.ItemStack;
+
+import com.gmail.filoghost.holographicdisplays.api.line.HologramLine;
+import com.gmail.filoghost.holographicdisplays.api.line.ItemLine;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.ChatComponentAdapter;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.ItemPickupManager;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.CustomNameHelper;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.NMSManager;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSArmorStand;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSEntityBase;
+import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSItem;
+import com.gmail.filoghost.holographicdisplays.util.ConsoleLogger;
+import com.gmail.filoghost.holographicdisplays.util.Validator;
+import com.gmail.filoghost.holographicdisplays.util.reflection.ReflectField;
+import com.gmail.filoghost.holographicdisplays.util.reflection.ReflectMethod;
+
+import net.minecraft.server.v1_16_R3.ChatComponentText;
+import net.minecraft.server.v1_16_R3.Entity;
+import net.minecraft.server.v1_16_R3.EntityTypes;
+import net.minecraft.server.v1_16_R3.EnumCreatureType;
+import net.minecraft.server.v1_16_R3.IChatBaseComponent;
+import net.minecraft.server.v1_16_R3.IRegistry;
+import net.minecraft.server.v1_16_R3.MathHelper;
+import net.minecraft.server.v1_16_R3.RegistryMaterials;
+import net.minecraft.server.v1_16_R3.WorldServer;
+
+public class NmsManagerImpl implements NMSManager {
+	
+	private static final ReflectField<Map<EntityTypes<?>, Integer>> REGISTRY_TO_ID_FIELD = new ReflectField<>(RegistryMaterials.class, "bg");
+	private static final ReflectMethod<Void> REGISTER_ENTITY_METHOD = new ReflectMethod<>(WorldServer.class, "registerEntity", Entity.class);
+	
+	@Override
+	public void setup() throws Exception {		
+		registerCustomEntity(EntityNMSSlime.class, 55, 2.04f, 2.04f);
+	}
+	
+	public void registerCustomEntity(Class<? extends Entity> entityClass, int id, float sizeWidth, float sizeHeight) throws Exception {
+		// Use reflection to map the custom entity to the correct ID
+		Map<EntityTypes<?>, Integer> entityTypesToId = REGISTRY_TO_ID_FIELD.get(IRegistry.ENTITY_TYPE);
+		EntityTypes<?> customEntityTypes = EntityTypes.Builder.a(EnumCreatureType.MONSTER).a(sizeWidth, sizeHeight).b().a((String) null);
+		entityTypesToId.put(customEntityTypes, id);
+	}
+	
+	@Override
+	public NMSItem spawnNMSItem(org.bukkit.World bukkitWorld, double x, double y, double z, ItemLine parentPiece, ItemStack stack, ItemPickupManager itemPickupManager) {
+		WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle();
+		EntityNMSItem customItem = new EntityNMSItem(nmsWorld, parentPiece, itemPickupManager);
+		customItem.setLocationNMS(x, y, z);
+		customItem.setItemStackNMS(stack);
+		if (!addEntityToWorld(nmsWorld, customItem)) {
+			ConsoleLogger.handleSpawnFail(parentPiece);
+		}
+		return customItem;
+	}
+	
+	@Override
+	public EntityNMSSlime spawnNMSSlime(org.bukkit.World bukkitWorld, double x, double y, double z, HologramLine parentPiece) {
+		WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle();
+		EntityNMSSlime touchSlime = new EntityNMSSlime(nmsWorld, parentPiece);
+		touchSlime.setLocationNMS(x, y, z);
+		if (!addEntityToWorld(nmsWorld, touchSlime)) {
+			ConsoleLogger.handleSpawnFail(parentPiece);
+		}
+		return touchSlime;
+	}
+	
+	@Override
+	public NMSArmorStand spawnNMSArmorStand(org.bukkit.World world, double x, double y, double z, HologramLine parentPiece, boolean broadcastLocationPacket) {
+		WorldServer nmsWorld = ((CraftWorld) world).getHandle();
+		EntityNMSArmorStand invisibleArmorStand = new EntityNMSArmorStand(nmsWorld, parentPiece);
+		invisibleArmorStand.setLocationNMS(x, y, z, broadcastLocationPacket);
+		if (!addEntityToWorld(nmsWorld, invisibleArmorStand)) {
+			ConsoleLogger.handleSpawnFail(parentPiece);
+		}
+		return invisibleArmorStand;
+	}
+	
+	private boolean addEntityToWorld(WorldServer nmsWorld, Entity nmsEntity) {
+		Validator.isTrue(Bukkit.isPrimaryThread(), "Async entity add");
+		
+        final int chunkX = MathHelper.floor(nmsEntity.locX() / 16.0);
+        final int chunkZ = MathHelper.floor(nmsEntity.locZ() / 16.0);
+        
+        if (!nmsWorld.isChunkLoaded(chunkX, chunkZ)) {
+        	// This should never happen
+            nmsEntity.dead = true;
+            return false;
+        }
+        
+        nmsWorld.getChunkAt(chunkX, chunkZ).a(nmsEntity);
+        try {
+        	REGISTER_ENTITY_METHOD.invoke(nmsWorld, nmsEntity);
+        	return true;
+		} catch (Exception e) {
+			e.printStackTrace();
+			return false;
+		}
+    }
+	
+	@Override
+	public boolean isNMSEntityBase(org.bukkit.entity.Entity bukkitEntity) {
+		return ((CraftEntity) bukkitEntity).getHandle() instanceof NMSEntityBase;
+	}
+
+	@Override
+	public NMSEntityBase getNMSEntityBase(org.bukkit.entity.Entity bukkitEntity) {
+		Entity nmsEntity = ((CraftEntity) bukkitEntity).getHandle();
+		
+		if (nmsEntity instanceof NMSEntityBase) {
+			return ((NMSEntityBase) nmsEntity);
+		} else {
+			return null;
+		}
+	}
+	
+	@Override
+	public NMSEntityBase getNMSEntityBaseFromID(org.bukkit.World bukkitWorld, int entityID) {
+		WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle();
+		Entity nmsEntity = nmsWorld.getEntity(entityID);
+		
+		if (nmsEntity instanceof NMSEntityBase) {
+			return ((NMSEntityBase) nmsEntity);
+		} else {
+			return null;
+		}
+	}
+	
+	@Override
+	public Object replaceCustomNameText(Object customNameObject, String target, String replacement) {
+		return CustomNameHelper.replaceCustomNameChatComponent(NMSChatComponentAdapter.INSTANCE, customNameObject, target, replacement);
+	}
+	
+	private static enum NMSChatComponentAdapter implements ChatComponentAdapter<IChatBaseComponent> {
+
+		INSTANCE {
+			
+			public ChatComponentText cast(Object chatComponentObject) {
+				return (ChatComponentText) chatComponentObject;
+			}
+			
+			@Override
+			public String getText(IChatBaseComponent chatComponent) {
+				return chatComponent.getText();
+			}
+	
+			@Override
+			public List<IChatBaseComponent> getSiblings(IChatBaseComponent chatComponent) {
+				return chatComponent.getSiblings();
+			}
+	
+			@Override
+			public void addSibling(IChatBaseComponent chatComponent, IChatBaseComponent newSibling) {
+				newSibling.getChatModifier().setChatModifier(chatComponent.getChatModifier());
+				chatComponent.getSiblings().add(newSibling);
+			}
+	
+			@Override
+			public ChatComponentText cloneComponent(IChatBaseComponent chatComponent, String newText) {
+				ChatComponentText clonedChatComponent = new ChatComponentText(newText);
+				clonedChatComponent.setChatModifier(chatComponent.getChatModifier().a());
+				return clonedChatComponent;
+			}
+			
+		}
+		
+	}
+	
+}
diff --git a/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/NullBoundingBox.java b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/NullBoundingBox.java
new file mode 100644
index 00000000..408bff2c
--- /dev/null
+++ b/NMS/v1_16_R3/src/main/java/com/gmail/filoghost/holographicdisplays/nms/v1_16_R3/NullBoundingBox.java
@@ -0,0 +1,134 @@
+/*
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.gmail.filoghost.holographicdisplays.nms.v1_16_R3;
+
+import net.minecraft.server.v1_16_R3.AxisAlignedBB;
+import net.minecraft.server.v1_16_R3.BlockPosition;
+import net.minecraft.server.v1_16_R3.EnumDirection.EnumAxis;
+import net.minecraft.server.v1_16_R3.Vec3D;
+
+public class NullBoundingBox extends AxisAlignedBB {
+
+    public NullBoundingBox() {
+        super(0, 0, 0, 0, 0, 0);
+    }
+
+    @Override
+    public double a() {
+        return 0.0;
+    }
+
+    @Override
+    public AxisAlignedBB a(AxisAlignedBB arg0) {
+        return this;
+    }
+
+    @Override
+    public AxisAlignedBB a(double arg0, double arg1, double arg2) {
+        return this;
+    }
+
+    @Override
+    public AxisAlignedBB grow(double arg0, double arg1, double arg2) {
+        return this;
+    }
+
+    @Override
+    public AxisAlignedBB shrink(double arg0) {
+        return this;
+    }
+
+    @Override
+    public AxisAlignedBB a(BlockPosition arg0) {
+        return this;
+    }
+
+    @Override
+    public boolean a(double arg0, double arg1, double arg2, double arg3, double arg4, double arg5) {
+        return false;
+    }
+
+    @Override
+    public AxisAlignedBB g(double arg0) {
+        return this;
+    }
+
+    @Override
+    public AxisAlignedBB b(Vec3D arg0) {
+        return this;
+    }
+
+    @Override
+    public AxisAlignedBB b(AxisAlignedBB arg0) {
+        return this;
+    }
+
+    @Override
+    public AxisAlignedBB b(double arg0, double arg1, double arg2) {
+        return this;
+    }
+
+    @Override
+    public boolean c(AxisAlignedBB arg0) {
+        return false;
+    }
+
+    @Override
+    public AxisAlignedBB d(double arg0, double arg1, double arg2) {
+        return this;
+    }
+
+    @Override
+    public double a(EnumAxis arg0) {
+        return 0.0;
+    }
+
+    @Override
+    public double b(EnumAxis arg0) {
+        return 0.0;
+    }
+
+    @Override
+    public boolean e(double arg0, double arg1, double arg2) {
+        return false;
+    }
+
+    @Override
+    public double b() {
+        return 0.0;
+    }
+
+    @Override
+    public double c() {
+        return 0.0;
+    }
+
+    @Override
+    public double d() {
+        return 0.0;
+    }
+
+    @Override
+    public boolean d(Vec3D var0) {
+        return false;
+    }
+
+    @Override
+    public Vec3D f() {
+        return Vec3D.ORIGIN;
+    }
+
+
+}
diff --git a/Plugin/pom.xml b/Plugin/pom.xml
index c8a8577c..5c3bd86b 100644
--- a/Plugin/pom.xml
+++ b/Plugin/pom.xml
@@ -120,6 +120,11 @@
 			<artifactId>holographicdisplays-nms-v1_16_r2</artifactId>
 		</dependency>
 
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>holographicdisplays-nms-v1_16_r3</artifactId>
+		</dependency>
+
 		<dependency>
 			<groupId>org.spigotmc</groupId>
 			<artifactId>spigot-api</artifactId>
diff --git a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java
index de842ba2..ae098b25 100644
--- a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java
+++ b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java
@@ -109,7 +109,7 @@ public class HolographicDisplays extends JavaPlugin {
 		if (!NMSVersion.isValid()) {
 			criticalShutdown(
 				"Holographic Displays does not support this server version.",
-				"Supported Spigot versions: from 1.8.3 to 1.16.");
+				"Supported Spigot versions: from 1.8.3 to 1.16.4.");
 			return;
 		}
 		
diff --git a/Utils/src/main/java/com/gmail/filoghost/holographicdisplays/util/NMSVersion.java b/Utils/src/main/java/com/gmail/filoghost/holographicdisplays/util/NMSVersion.java
index 2d45530c..7c2787fa 100644
--- a/Utils/src/main/java/com/gmail/filoghost/holographicdisplays/util/NMSVersion.java
+++ b/Utils/src/main/java/com/gmail/filoghost/holographicdisplays/util/NMSVersion.java
@@ -31,7 +31,8 @@ public enum NMSVersion {
 	v1_14_R1,
 	v1_15_R1,
 	v1_16_R1,
-	v1_16_R2;
+	v1_16_R2,
+	v1_16_R3;
 	
 	private static final NMSVersion CURRENT_VERSION = extractCurrentVersion();
 	
diff --git a/pom.xml b/pom.xml
index f2e433c8..bf89e0bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -147,6 +147,12 @@
 				<artifactId>holographicdisplays-nms-v1_16_r2</artifactId>
 				<version>${project.version}</version>
 			</dependency>
+
+			<dependency>
+				<groupId>${project.groupId}</groupId>
+				<artifactId>holographicdisplays-nms-v1_16_r3</artifactId>
+				<version>${project.version}</version>
+			</dependency>
 	
 			<dependency>
 				<groupId>org.spigotmc</groupId>