diff --git a/nms/pom.xml b/nms/pom.xml
index 51913cc0..4ac65a2a 100644
--- a/nms/pom.xml
+++ b/nms/pom.xml
@@ -28,6 +28,7 @@
v1_16_r1
v1_16_r2
v1_16_r3
+ v1_17_r1
diff --git a/nms/v1_17_r1/pom.xml b/nms/v1_17_r1/pom.xml
new file mode 100644
index 00000000..40b53783
--- /dev/null
+++ b/nms/v1_17_r1/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+
+
+ me.filoghost.holographicdisplays
+ holographicdisplays-nms
+ 3.0.0-SNAPSHOT
+
+
+ holographicdisplays-nms-v1_17_r1
+ HolographicDisplays NMS v1_17_R1
+
+
+
+ ${project.groupId}
+ holographicdisplays-common
+
+
+
+ org.spigotmc
+ spigot
+ 1.17-R0.1-SNAPSHOT
+ provided
+
+
+
+
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSArmorStand.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSArmorStand.java
new file mode 100644
index 00000000..f66b0897
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSArmorStand.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import org.bukkit.EntityEffect;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftArmorStand;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.util.EulerAngle;
+import org.bukkit.util.Vector;
+
+import java.util.Collection;
+
+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) {}
+ @Override public void addEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) {}
+ @Override public void removeEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) {}
+
+ // 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 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) {}
+ @Override public void setInvisible(boolean invisible) {}
+
+ // 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 setLastDamageCause(EntityDamageEvent event) {}
+ @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) {}
+ @Override public boolean addPassenger(Entity passenger) { return false; }
+ @Override public boolean removePassenger(Entity passenger) { return false; }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSItem.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSItem.java
new file mode 100644
index 00000000..7c87c3e7
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSItem.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import org.bukkit.EntityEffect;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftItem;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.entity.EntityDamageEvent;
+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 setLastDamageCause(EntityDamageEvent event) {}
+ @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) {}
+ @Override public boolean addPassenger(Entity passenger) { return false; }
+ @Override public boolean removePassenger(Entity passenger) { return false; }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSSlime.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSSlime.java
new file mode 100644
index 00000000..124cb22d
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/CraftNMSSlime.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import org.bukkit.EntityEffect;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSlime;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.bukkit.loot.LootTable;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.util.Vector;
+
+import java.util.Collection;
+
+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 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) {}
+ @Override public void setInvisible(boolean invisible) {}
+
+ // 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 setLastDamageCause(EntityDamageEvent event) {}
+ @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) {}
+ @Override public boolean addPassenger(Entity passenger) { return false; }
+ @Override public boolean removePassenger(Entity passenger) { return false; }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSArmorStand.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSArmorStand.java
new file mode 100644
index 00000000..c192edaa
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSArmorStand.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import com.google.common.collect.ImmutableList;
+import me.filoghost.fcommons.Preconditions;
+import me.filoghost.fcommons.Strings;
+import me.filoghost.fcommons.reflection.ReflectField;
+import me.filoghost.holographicdisplays.common.DebugLogger;
+import me.filoghost.holographicdisplays.common.hologram.StandardHologramLine;
+import me.filoghost.holographicdisplays.common.nms.ProtocolPacketSettings;
+import me.filoghost.holographicdisplays.common.nms.entity.NMSArmorStand;
+import me.filoghost.holographicdisplays.common.nms.entity.NMSEntity;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.chat.IChatBaseComponent;
+import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport;
+import net.minecraft.sounds.SoundEffect;
+import net.minecraft.world.EnumHand;
+import net.minecraft.world.EnumInteractionResult;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.entity.EnumItemSlot;
+import net.minecraft.world.entity.decoration.EntityArmorStand;
+import net.minecraft.world.entity.player.EntityHuman;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.World;
+import net.minecraft.world.phys.AxisAlignedBB;
+import net.minecraft.world.phys.Vec3D;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_17_R1.util.CraftChatMessage;
+import org.bukkit.entity.Player;
+
+import java.util.Objects;
+
+public class EntityNMSArmorStand extends EntityArmorStand implements NMSArmorStand {
+
+ private static final ReflectField VEHICLE_FIELD = ReflectField.lookup(Entity.class, Entity.class, "au");
+
+ private final StandardHologramLine parentHologramLine;
+ private final ProtocolPacketSettings protocolPacketSettings;
+ private final VersionNMSEntityHelper helper;
+ private CraftEntity customBukkitEntity;
+ private String customName;
+
+ public EntityNMSArmorStand(World world, StandardHologramLine parentHologramLine, ProtocolPacketSettings protocolPacketSettings) {
+ super(EntityTypes.c /* ARMOR_STAND */, world);
+ this.parentHologramLine = parentHologramLine;
+ this.protocolPacketSettings = protocolPacketSettings;
+ this.helper = new VersionNMSEntityHelper(this);
+
+ super.setInvisible(true);
+ super.setSmall(true);
+ super.setArms(false);
+ super.setNoGravity(true);
+ super.setBasePlate(true);
+ super.setMarker(true);
+ super.collides = false;
+ super.z /* onGround */ = true; // Workaround to force EntityTrackerEntry to send a teleport packet
+ forceSetBoundingBox(new NullBoundingBox());
+ }
+
+ @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 (super.z /* onGround */) {
+ super.z = 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 (super.z /* onGround */) {
+ super.z = false;
+ }
+ }
+
+ @Override
+ public void setPosition(double d0, double d1, double d2) {
+ // Do not change it!
+ }
+
+ @Override
+ public void saveData(NBTTagCompound nbttagcompound) {
+ // Do not save NBT
+ }
+
+ @Override
+ public boolean d(NBTTagCompound nbttagcompound) {
+ // Do not save NBT
+ return false;
+ }
+
+ @Override
+ public boolean e(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) {
+ // Prevents changes to custom name
+ }
+
+ @Override
+ public void setCustomNameVisible(boolean visible) {
+ // Prevents changes to custom name visibility
+ }
+
+ @Override
+ public EnumInteractionResult a(EntityHuman human, Vec3D vec3d, EnumHand enumhand) {
+ // Prevent armor stand from being equipped
+ return EnumInteractionResult.d /* PASS */;
+ }
+
+ @Override
+ public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) {
+ // Prevent armor stand from being equipped
+ }
+
+ @Override
+ public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack, boolean silent) {
+ // Prevent armor stand from being equipped
+ }
+
+ 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 customName) {
+ if (Objects.equals(this.customName, customName)) {
+ return;
+ }
+ this.customName = customName;
+ super.setCustomName(createCustomNameNMSObject(customName));
+ super.setCustomNameVisible(customName != null && !customName.isEmpty());
+ }
+
+ protected static IChatBaseComponent createCustomNameNMSObject(String customName) {
+ return CraftChatMessage.fromStringOrNull(Strings.truncate(customName, 300));
+ }
+
+ @Override
+ public String getCustomNameStringNMS() {
+ return this.customName;
+ }
+
+ @Override
+ public IChatBaseComponent getCustomNameObjectNMS() {
+ return super.getCustomName();
+ }
+
+ @Override
+ public void killEntity() {
+ // Prevent entity from dying
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (customBukkitEntity == null) {
+ customBukkitEntity = new CraftNMSArmorStand(super.getWorld().getCraftServer(), this);
+ }
+ return customBukkitEntity;
+ }
+
+ @Override
+ public void killEntityNMS() {
+ super.setRemoved(RemovalReason.b /* DISCARDED */);
+ }
+
+ @Override
+ public void setLocationNMS(double x, double y, double z) {
+ super.setPosition(x, y, z);
+ if (protocolPacketSettings.sendAccurateLocationPackets()) {
+ helper.broadcastPacket(new PacketPlayOutEntityTeleport(this));
+ }
+ }
+
+ @Override
+ public void setPassengerNMS(NMSEntity passenger) {
+ Preconditions.checkArgument(passenger instanceof Entity);
+ Entity passengerEntity = (Entity) passenger;
+ Preconditions.checkArgument(passengerEntity.getVehicle() == null);
+ Preconditions.checkState(super.getPassengers().isEmpty());
+
+ try {
+ VEHICLE_FIELD.set(passenger, this);
+ ((Entity) this).at /* passengers */ = ImmutableList.of(this);
+ } catch (ReflectiveOperationException e) {
+ DebugLogger.cannotSetPassenger(e);
+ }
+ }
+
+ @Override
+ public boolean isDeadNMS() {
+ return super.isRemoved();
+ }
+
+ @Override
+ public int getIdNMS() {
+ return super.getId();
+ }
+
+ @Override
+ public StandardHologramLine getHologramLine() {
+ return parentHologramLine;
+ }
+
+ @Override
+ public org.bukkit.entity.Entity getBukkitEntityNMS() {
+ return getBukkitEntity();
+ }
+
+ @Override
+ public boolean isTrackedBy(Player bukkitPlayer) {
+ return helper.isTrackedBy(bukkitPlayer);
+ }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSItem.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSItem.java
new file mode 100644
index 00000000..9d54594f
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSItem.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import me.filoghost.holographicdisplays.common.hologram.StandardHologramLine;
+import me.filoghost.holographicdisplays.common.hologram.StandardItemLine;
+import me.filoghost.holographicdisplays.common.nms.NMSCommons;
+import me.filoghost.holographicdisplays.common.nms.entity.NMSItem;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagString;
+import net.minecraft.server.level.EntityPlayer;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.entity.item.EntityItem;
+import net.minecraft.world.entity.player.EntityHuman;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.World;
+import net.minecraft.world.level.block.Blocks;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+
+public class EntityNMSItem extends EntityItem implements NMSItem {
+
+ private final StandardItemLine parentHologramLine;
+ private final VersionNMSEntityHelper helper;
+ private CraftEntity customBukkitEntity;
+
+ public EntityNMSItem(World world, StandardItemLine parentHologramLine) {
+ super(EntityTypes.Q, world);
+ this.parentHologramLine = parentHologramLine;
+ this.helper = new VersionNMSEntityHelper(this);
+
+ super.ap /* pickupDelay */ = 32767; // Lock the item pickup delay, also prevents entities from picking up the item
+ }
+
+ @Override
+ public void tick() {
+ // Disable normal ticking for this entity
+
+ // So it won't get removed
+ super.R /* tickCount */ = 0;
+ }
+
+ @Override
+ public void inactiveTick() {
+ // Disable normal ticking for this entity
+
+ // So it won't get removed
+ super.R /* tickCount */ = 0;
+ }
+
+ @Override
+ public void setPosition(double d0, double d1, double d2) {
+ // Do not change it!
+ }
+
+ // 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 (human instanceof EntityPlayer) {
+ parentHologramLine.onPickup(((EntityPlayer) human).getBukkitEntity());
+ // It is never added to the inventory
+ }
+ }
+
+ @Override
+ public void saveData(NBTTagCompound nbttagcompound) {
+ // Do not save NBT
+ }
+
+ @Override
+ public boolean d(NBTTagCompound nbttagcompound) {
+ // Do not save NBT
+ return false;
+ }
+
+ @Override
+ public boolean e(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 killEntity() {
+ // Prevent entity from dying
+ }
+
+ @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.getWorld().getCraftServer(), this);
+ }
+ return customBukkitEntity;
+ }
+
+ @Override
+ public boolean isDeadNMS() {
+ return super.isRemoved();
+ }
+
+ @Override
+ public void killEntityNMS() {
+ super.setRemoved(RemovalReason.b /* DISCARDED */);
+ }
+
+ @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);
+
+ if (newItem == null || newItem == ItemStack.b /* EMPTY */) {
+ newItem = new ItemStack(Blocks.z /* 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(NMSCommons.ANTI_STACK_LORE));
+ display.set("Lore", tagList);
+
+ super.setItemStack(newItem);
+ }
+
+ @Override
+ public int getIdNMS() {
+ return super.getId();
+ }
+
+ @Override
+ public StandardHologramLine getHologramLine() {
+ return parentHologramLine;
+ }
+
+ @Override
+ public org.bukkit.entity.Entity getBukkitEntityNMS() {
+ return getBukkitEntity();
+ }
+
+ @Override
+ public boolean isTrackedBy(Player bukkitPlayer) {
+ return helper.isTrackedBy(bukkitPlayer);
+ }
+
+ @Override
+ public Object getRawItemStack() {
+ return super.getItemStack();
+ }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSSlime.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSSlime.java
new file mode 100644
index 00000000..9701fb60
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/EntityNMSSlime.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import me.filoghost.holographicdisplays.common.hologram.StandardHologramLine;
+import me.filoghost.holographicdisplays.common.nms.entity.NMSSlime;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.chat.IChatBaseComponent;
+import net.minecraft.server.level.EntityPlayer;
+import net.minecraft.sounds.SoundEffect;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.damagesource.EntityDamageSource;
+import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.entity.monster.EntitySlime;
+import net.minecraft.world.level.World;
+import net.minecraft.world.phys.AxisAlignedBB;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerInteractEntityEvent;
+
+public class EntityNMSSlime extends EntitySlime implements NMSSlime {
+
+ private final StandardHologramLine parentHologramLine;
+ private final VersionNMSEntityHelper helper;
+ private CraftEntity customBukkitEntity;
+
+ public EntityNMSSlime(World world, StandardHologramLine parentHologramLine) {
+ super(EntityTypes.aD /* SLIME */, world);
+ this.parentHologramLine = parentHologramLine;
+ this.helper = new VersionNMSEntityHelper(this);
+
+ super.collides = false;
+ super.setPersistent();
+ super.a(0.0F, 0.0F);
+ super.setSize(1, false);
+ super.setInvisible(true);
+ forceSetBoundingBox(new NullBoundingBox());
+ }
+
+ @Override
+ public void tick() {
+ // Disable normal ticking for this entity
+
+ // So it won't get removed
+ super.R /* tickCount */ = 0;
+ }
+
+ @Override
+ public void inactiveTick() {
+ // Disable normal ticking for this entity
+
+ // So it won't get removed
+ super.R /* tickCount */ = 0;
+ }
+
+ @Override
+ public void setPosition(double d0, double d1, double d2) {
+ // 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 d(NBTTagCompound nbttagcompound) {
+ // Do not save NBT
+ return false;
+ }
+
+ @Override
+ public boolean e(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) {
+ Player player = ((EntityPlayer) entityDamageSource.getEntity()).getBukkitEntity();
+ PlayerInteractEntityEvent event = new PlayerInteractEntityEvent(player, getBukkitEntity());
+ Bukkit.getPluginManager().callEvent(event); // 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) {
+ // Prevents changes to custom name
+ }
+
+ @Override
+ public void setCustomNameVisible(boolean visible) {
+ // Prevents changes to custom name visibility
+ }
+
+ @Override
+ public void playSound(SoundEffect soundeffect, float f, float f1) {
+ // Remove sounds
+ }
+
+ @Override
+ public void killEntity() {
+ // Prevent entity from dying
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (customBukkitEntity == null) {
+ customBukkitEntity = new CraftNMSSlime(super.getWorld().getCraftServer(), this);
+ }
+ return customBukkitEntity;
+ }
+
+ @Override
+ public boolean isDeadNMS() {
+ return super.isRemoved();
+ }
+
+ @Override
+ public void killEntityNMS() {
+ super.setRemoved(RemovalReason.b /* DISCARDED */);
+ }
+
+ @Override
+ public void setLocationNMS(double x, double y, double z) {
+ super.setPosition(x, y, z);
+ }
+
+ @Override
+ public int getIdNMS() {
+ return super.getId();
+ }
+
+ @Override
+ public StandardHologramLine getHologramLine() {
+ return parentHologramLine;
+ }
+
+ @Override
+ public org.bukkit.entity.Entity getBukkitEntityNMS() {
+ return getBukkitEntity();
+ }
+
+ @Override
+ public boolean isTrackedBy(Player bukkitPlayer) {
+ return helper.isTrackedBy(bukkitPlayer);
+ }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/NullBoundingBox.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/NullBoundingBox.java
new file mode 100644
index 00000000..54df1b9e
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/NullBoundingBox.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import net.minecraft.core.BlockPosition;
+import net.minecraft.core.EnumDirection.EnumAxis;
+import net.minecraft.world.phys.AxisAlignedBB;
+import net.minecraft.world.phys.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.a /* ZERO */;
+ }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/VersionNMSEntityHelper.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/VersionNMSEntityHelper.java
new file mode 100644
index 00000000..ee04fc01
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/VersionNMSEntityHelper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import me.filoghost.holographicdisplays.common.nms.entity.NMSEntityHelper;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.server.level.PlayerChunkMap.EntityTracker;
+import net.minecraft.server.level.WorldServer;
+import net.minecraft.server.network.PlayerConnection;
+import net.minecraft.world.entity.Entity;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+public class VersionNMSEntityHelper extends NMSEntityHelper {
+
+ private final Entity entity;
+
+ public VersionNMSEntityHelper(Entity entity) {
+ this.entity = entity;
+ }
+
+ @Override
+ protected EntityTracker getTracker0() {
+ return ((WorldServer) entity.getWorld()).getChunkProvider().a /* playerChunkMap */.G /* trackedEntities */.get(entity.getId());
+ }
+
+ @Override
+ public boolean isTrackedBy(Player bukkitPlayer) {
+ EntityTracker tracker = getTracker();
+ if (tracker != null) {
+ PlayerConnection playerConnection = ((CraftPlayer) bukkitPlayer).getHandle().b /* playerConnection */;
+ return tracker.f /* trackedPlayerConnections */.contains(playerConnection);
+ } else {
+ return false;
+ }
+ }
+
+ public void broadcastPacket(Packet> packet) {
+ EntityTracker tracker = getTracker();
+ if (tracker != null) {
+ tracker.broadcast(packet);
+ }
+ }
+
+}
diff --git a/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/VersionNMSManager.java b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/VersionNMSManager.java
new file mode 100644
index 00000000..3f59f29a
--- /dev/null
+++ b/nms/v1_17_r1/src/main/java/me/filoghost/holographicdisplays/nms/v1_17_R1/VersionNMSManager.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) filoghost and contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package me.filoghost.holographicdisplays.nms.v1_17_R1;
+
+import me.filoghost.fcommons.Preconditions;
+import me.filoghost.holographicdisplays.common.hologram.StandardHologramLine;
+import me.filoghost.holographicdisplays.common.hologram.StandardItemLine;
+import me.filoghost.holographicdisplays.common.nms.NMSManager;
+import me.filoghost.holographicdisplays.common.nms.ProtocolPacketSettings;
+import me.filoghost.holographicdisplays.common.nms.SpawnFailedException;
+import me.filoghost.holographicdisplays.common.nms.entity.NMSArmorStand;
+import me.filoghost.holographicdisplays.common.nms.entity.NMSEntity;
+import me.filoghost.holographicdisplays.common.nms.entity.NMSItem;
+import net.minecraft.server.level.WorldServer;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.Entity.RemovalReason;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
+import org.bukkit.inventory.ItemStack;
+
+public class VersionNMSManager implements NMSManager {
+
+ private final ProtocolPacketSettings protocolPacketSettings;
+
+ public VersionNMSManager(ProtocolPacketSettings protocolPacketSettings) {
+ this.protocolPacketSettings = protocolPacketSettings;
+ }
+
+ @Override
+ public void setup() {}
+
+ @Override
+ public NMSItem spawnNMSItem(
+ World bukkitWorld, double x, double y, double z,
+ StandardItemLine parentHologramLine,
+ ItemStack stack) throws SpawnFailedException {
+ WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle();
+ EntityNMSItem item = new EntityNMSItem(nmsWorld, parentHologramLine);
+ item.setLocationNMS(x, y, z);
+ item.setItemStackNMS(stack);
+ addEntityToWorld(nmsWorld, item);
+ return item;
+ }
+
+ @Override
+ public EntityNMSSlime spawnNMSSlime(
+ World bukkitWorld, double x, double y, double z,
+ StandardHologramLine parentHologramLine) throws SpawnFailedException {
+ WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle();
+ EntityNMSSlime slime = new EntityNMSSlime(nmsWorld, parentHologramLine);
+ slime.setLocationNMS(x, y, z);
+ addEntityToWorld(nmsWorld, slime);
+ return slime;
+ }
+
+ @Override
+ public NMSArmorStand spawnNMSArmorStand(
+ World world, double x, double y, double z,
+ StandardHologramLine parentHologramLine) throws SpawnFailedException {
+ WorldServer nmsWorld = ((CraftWorld) world).getHandle();
+ EntityNMSArmorStand armorStand = new EntityNMSArmorStand(nmsWorld, parentHologramLine, protocolPacketSettings);
+ armorStand.setLocationNMS(x, y, z);
+ addEntityToWorld(nmsWorld, armorStand);
+ return armorStand;
+ }
+
+ private void addEntityToWorld(WorldServer nmsWorld, Entity nmsEntity) throws SpawnFailedException {
+ Preconditions.checkState(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.setRemoved(RemovalReason.b /* DISCARDED */);
+ throw new SpawnFailedException(SpawnFailedException.CHUNK_NOT_LOADED);
+ }
+
+ try {
+ nmsWorld.G.a(nmsEntity) /* entityManager.addNewEntity() */;
+ } catch (Exception e) {
+ nmsEntity.setRemoved(RemovalReason.b /* DISCARDED */);
+ throw new SpawnFailedException(SpawnFailedException.REGISTER_ENTITY_FAIL, e);
+ }
+ }
+
+ @Override
+ public boolean isNMSEntityBase(org.bukkit.entity.Entity bukkitEntity) {
+ return ((CraftEntity) bukkitEntity).getHandle() instanceof NMSEntity;
+ }
+
+ @Override
+ public NMSEntity getNMSEntityBase(org.bukkit.entity.Entity bukkitEntity) {
+ Entity nmsEntity = ((CraftEntity) bukkitEntity).getHandle();
+
+ if (nmsEntity instanceof NMSEntity) {
+ return (NMSEntity) nmsEntity;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public NMSEntity getNMSEntityBaseFromID(org.bukkit.World bukkitWorld, int entityID) {
+ WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle();
+ Entity nmsEntity = nmsWorld.getEntity(entityID);
+
+ if (nmsEntity instanceof NMSEntity) {
+ return (NMSEntity) nmsEntity;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Object createCustomNameNMSObject(String customName) {
+ return EntityNMSArmorStand.createCustomNameNMSObject(customName);
+ }
+
+}
diff --git a/plugin/pom.xml b/plugin/pom.xml
index c83a3fa8..b30eef9d 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -104,6 +104,11 @@
holographicdisplays-nms-v1_16_r3
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_17_r1
+
+
org.spigotmc
spigot-api
diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java
index 98549599..cf53a933 100644
--- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java
+++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java
@@ -81,7 +81,7 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
if (!NMSVersion.isValid()) {
throw new PluginEnableException(
"Holographic Displays does not support this server version.",
- "Supported Spigot versions: from 1.8.3 to 1.16.4.");
+ "Supported Spigot versions: from 1.8.3 to 1.17.");
}
if (getCommand("holograms") == null) {
diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/util/NMSVersion.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/util/NMSVersion.java
index 4a944f5f..0b0a98d8 100644
--- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/util/NMSVersion.java
+++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/util/NMSVersion.java
@@ -32,7 +32,8 @@ public enum NMSVersion {
v1_15_R1(packetSettings -> new me.filoghost.holographicdisplays.nms.v1_15_R1.VersionNMSManager(packetSettings)),
v1_16_R1(packetSettings -> new me.filoghost.holographicdisplays.nms.v1_16_R1.VersionNMSManager(packetSettings)),
v1_16_R2(packetSettings -> new me.filoghost.holographicdisplays.nms.v1_16_R2.VersionNMSManager(packetSettings)),
- v1_16_R3(packetSettings -> new me.filoghost.holographicdisplays.nms.v1_16_R3.VersionNMSManager(packetSettings));
+ v1_16_R3(packetSettings -> new me.filoghost.holographicdisplays.nms.v1_16_R3.VersionNMSManager(packetSettings)),
+ v1_17_R1(packetSettings -> new me.filoghost.holographicdisplays.nms.v1_17_R1.VersionNMSManager(packetSettings));
private static final NMSVersion CURRENT_VERSION = extractCurrentVersion();
diff --git a/pom.xml b/pom.xml
index 75cd6d66..3f387398 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,409 +1,415 @@
-
-
- 4.0.0
-
- me.filoghost.holographicdisplays
- holographicdisplays-parent
- HolographicDisplays Parent
- 3.0.0-SNAPSHOT
- pom
-
-
- UTF-8
- 1.8
- 1.8
- 1.8-R0.1-SNAPSHOT
-
-
-
-
- codemc-snapshots
- https://repo.codemc.io/repository/maven-snapshots/
-
-
- codemc-releases
- https://repo.codemc.io/repository/maven-releases/
-
-
-
-
- common
- api
- legacy-api
- nms
- plugin
- example
-
-
-
-
- spigot-repo
- https://hub.spigotmc.org/nexus/content/repositories/snapshots/
-
-
-
- codemc-repo
- https://repo.codemc.io/repository/maven-public/
-
-
-
- nms-repo
- https://repo.codemc.io/repository/nms/
-
-
-
- dmulloy2-repo
- https://repo.dmulloy2.net/repository/public/
-
-
-
- placeholderapi-repo
- https://repo.extendedclip.com/content/repositories/placeholderapi/
-
-
-
-
-
-
- ${project.groupId}
- holographicdisplays-api
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-common
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-legacy-api-v1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-legacy-api-v2
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-config
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-interfaces
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_8_r2
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_8_r3
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_9_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_9_r2
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_10_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_11_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_12_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_13_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_13_r2
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_14_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_15_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_16_r1
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_16_r2
- ${project.version}
-
-
-
- ${project.groupId}
- holographicdisplays-nms-v1_16_r3
- ${project.version}
-
-
-
- org.spigotmc
- spigot-api
- ${spigot-api.version}
- provided
-
-
- junit
- junit
-
-
-
-
-
- com.comphenix.protocol
- ProtocolLib
- 4.5.0
- provided
-
-
-
- me.clip
- placeholderapi
- 2.8.1
- provided
-
-
-
- org.bstats
- bstats-bukkit-lite
- 1.7
-
-
-
- me.filoghost.updatechecker
- updatechecker
- 1.0.0
-
-
-
- me.filoghost.fcommons
- fcommons
- 1.2.8-SNAPSHOT
-
-
-
-
-
-
- org.jetbrains
- annotations
- 20.1.0
- provided
-
-
-
- org.junit.jupiter
- junit-jupiter
- 5.6.2
- test
-
-
-
- org.assertj
- assertj-core
- 3.17.0
- test
-
-
-
- org.mockito
- mockito-core
- 3.5.13
- test
-
-
-
-
- clean package
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.2.0
-
-
- false
-
- false
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 3.2.0
-
-
- **/holographicdisplays/api/**/*.java
-
-
- **/holographicdisplays/api/internal/**/*.java
-
-
-
-
-
- org.codehaus.mojo
- build-helper-maven-plugin
- 3.2.0
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 3.2.3
-
-
-
- org.apache.maven.plugins
- maven-enforcer-plugin
- 3.0.0-M3
-
-
-
- org.commonjava.maven.plugins
- directory-maven-plugin
- 0.3.1
-
-
-
- org.apache.maven.plugins
- maven-checkstyle-plugin
- 3.1.2
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.22.2
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-enforcer-plugin
-
-
-
- enforce
-
-
-
-
-
- [3.6.0,)
-
-
- [1.8,)
-
-
-
-
-
-
-
-
- org.commonjava.maven.plugins
- directory-maven-plugin
- true
-
-
- set-root-dir
- validate
-
- highest-basedir
-
-
- rootDir
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-checkstyle-plugin
-
-
- com.puppycrawl.tools
- checkstyle
- 8.42
-
-
-
- true
- ${rootDir}/checkstyle/checkstyle.xml
- samedir=${rootDir}/checkstyle
-
- ${project.basedir}
-
- checkstyle/**/*, pom.xml, src/main/java/**/*.java
-
-
-
- checkstyle-check
- validate
-
- check
-
-
-
-
-
-
-
+
+
+ 4.0.0
+
+ me.filoghost.holographicdisplays
+ holographicdisplays-parent
+ HolographicDisplays Parent
+ 3.0.0-SNAPSHOT
+ pom
+
+
+ UTF-8
+ 1.8
+ 1.8
+ 1.8-R0.1-SNAPSHOT
+
+
+
+
+ codemc-snapshots
+ https://repo.codemc.io/repository/maven-snapshots/
+
+
+ codemc-releases
+ https://repo.codemc.io/repository/maven-releases/
+
+
+
+
+ common
+ api
+ legacy-api
+ nms
+ plugin
+ example
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+
+ codemc-repo
+ https://repo.codemc.io/repository/maven-public/
+
+
+
+ nms-repo
+ https://repo.codemc.io/repository/nms/
+
+
+
+ dmulloy2-repo
+ https://repo.dmulloy2.net/repository/public/
+
+
+
+ placeholderapi-repo
+ https://repo.extendedclip.com/content/repositories/placeholderapi/
+
+
+
+
+
+
+ ${project.groupId}
+ holographicdisplays-api
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-common
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-legacy-api-v1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-legacy-api-v2
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-config
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-interfaces
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_8_r2
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_8_r3
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_9_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_9_r2
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_10_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_11_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_12_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_13_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_13_r2
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_14_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_15_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_16_r1
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_16_r2
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_16_r3
+ ${project.version}
+
+
+
+ ${project.groupId}
+ holographicdisplays-nms-v1_17_r1
+ ${project.version}
+
+
+
+ org.spigotmc
+ spigot-api
+ ${spigot-api.version}
+ provided
+
+
+ junit
+ junit
+
+
+
+
+
+ com.comphenix.protocol
+ ProtocolLib
+ 4.5.0
+ provided
+
+
+
+ me.clip
+ placeholderapi
+ 2.8.1
+ provided
+
+
+
+ org.bstats
+ bstats-bukkit-lite
+ 1.7
+
+
+
+ me.filoghost.updatechecker
+ updatechecker
+ 1.0.0
+
+
+
+ me.filoghost.fcommons
+ fcommons
+ 1.2.8-SNAPSHOT
+
+
+
+
+
+
+ org.jetbrains
+ annotations
+ 20.1.0
+ provided
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.6.2
+ test
+
+
+
+ org.assertj
+ assertj-core
+ 3.17.0
+ test
+
+
+
+ org.mockito
+ mockito-core
+ 3.5.13
+ test
+
+
+
+
+ clean package
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.2.0
+
+
+ false
+
+ false
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.2.0
+
+
+ **/holographicdisplays/api/**/*.java
+
+
+ **/holographicdisplays/api/internal/**/*.java
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.2.0
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.3
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 3.0.0-M3
+
+
+
+ org.commonjava.maven.plugins
+ directory-maven-plugin
+ 0.3.1
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.1.2
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+
+
+
+ enforce
+
+
+
+
+
+ [3.6.0,)
+
+
+ [1.8,)
+
+
+
+
+
+
+
+
+ org.commonjava.maven.plugins
+ directory-maven-plugin
+ true
+
+
+ set-root-dir
+ validate
+
+ highest-basedir
+
+
+ rootDir
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+ com.puppycrawl.tools
+ checkstyle
+ 8.42
+
+
+
+ true
+ ${rootDir}/checkstyle/checkstyle.xml
+ samedir=${rootDir}/checkstyle
+
+ ${project.basedir}
+
+ checkstyle/**/*, pom.xml, src/main/java/**/*.java
+
+
+
+ checkstyle-check
+ validate
+
+ check
+
+
+
+
+
+
+