Add support for Minecraft 1.17

This commit is contained in:
filoghost 2021-06-14 23:37:41 +02:00
parent fb68b946d2
commit 464c5804e6
12 changed files with 1352 additions and 1 deletions

41
NMS/v1_17_R1/pom.xml Normal file
View File

@ -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.7-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_17_r1</artifactId>
<name>HolographicDisplays NMS v1_17_R1</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.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,101 @@
/*
* 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_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.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<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) { }
@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 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; }
}

View File

@ -0,0 +1,67 @@
/*
* 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_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.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) { }
@Override public boolean addPassenger(Entity passenger) { return false; }
@Override public boolean removePassenger(Entity passenger) { return false; }
}

View File

@ -0,0 +1,88 @@
/*
* 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_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.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<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) { }
@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 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; }
}

View File

@ -0,0 +1,245 @@
/*
* 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_17_R1;
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.nbt.NBTTagCompound;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport;
import net.minecraft.server.level.EntityPlayer;
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.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;
public class EntityNMSArmorStand extends EntityArmorStand implements NMSArmorStand {
private HologramLine parentPiece;
private CraftEntity customBukkitEntity;
private String customName;
public EntityNMSArmorStand(World world, HologramLine parentPiece) {
super(EntityTypes.c, 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.z /* 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.z /* onGround */) {
this.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 (this.z /* onGround */) {
this.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) {
// 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.d /* PASS */;
}
@Override
public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) {
// Prevent stand being equipped
}
@Override
public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack, boolean silent) {
// Prevent stand 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 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 killEntity() {
// Prevent being killed.
}
@Override
public CraftEntity getBukkitEntity() {
if (customBukkitEntity == null) {
customBukkitEntity = new CraftNMSArmorStand(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, boolean broadcastLocationPacket) {
super.setPosition(x, y, z);
if (broadcastLocationPacket) {
broadcastLocationPacketNMS();
}
}
private void broadcastLocationPacketNMS() {
PacketPlayOutEntityTeleport teleportPacket = new PacketPlayOutEntityTeleport(this);
for (Object obj : super.getWorld().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.b /* playerConnection */ != null) {
nmsPlayer.b.sendPacket(teleportPacket);
}
}
}
}
@Override
public int getIdNMS() {
return super.getId();
}
@Override
public HologramLine getHologramLine() {
return parentPiece;
}
@Override
public org.bukkit.entity.Entity getBukkitEntityNMS() {
return getBukkitEntity();
}
}

View File

@ -0,0 +1,252 @@
/*
* 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_17_R1;
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 com.google.common.collect.ImmutableList;
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.Entity;
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;
import java.util.logging.Level;
public class EntityNMSItem extends EntityItem implements NMSItem {
private static final ReflectField<Entity> VEHICLE_FIELD = new ReflectField<>(Entity.class, "au");
private ItemLine parentPiece;
private ItemPickupManager itemPickupManager;
private CraftEntity customBukkitEntity;
public EntityNMSItem(World world, ItemLine piece, ItemPickupManager itemPickupManager) {
super(EntityTypes.Q /* ITEM */, world);
super.ap /* 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.
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 (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 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 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.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); // ItemStack.a is returned if the stack is null, invalid or the material is not an Item
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(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.ap /* pickupDelay */ = 0;
} else {
super.ap /* 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.at /* passengers */ = ImmutableList.of();
}
VEHICLE_FIELD.set(this, entity);
entity.at /* passengers */ = ImmutableList.of(this);
} catch (Throwable t) {
ConsoleLogger.logDebug(Level.SEVERE, "Couldn't set passenger", t);
}
}
@Override
public Object getRawItemStack() {
return super.getItemStack();
}
}

View File

@ -0,0 +1,223 @@
/*
* 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_17_R1;
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 com.google.common.collect.ImmutableList;
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.Entity;
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.event.player.PlayerInteractEntityEvent;
import java.util.logging.Level;
public class EntityNMSSlime extends EntitySlime implements NMSSlime {
private static final ReflectField<Entity> VEHICLE_FIELD = new ReflectField<>(Entity.class, "au");
private HologramLine parentPiece;
private CraftEntity customBukkitEntity;
public EntityNMSSlime(World world, HologramLine parentPiece) {
super(EntityTypes.aD, world);
super.setPersistent();
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.
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) {
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 killEntity() {
// Prevent being killed.
}
@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 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.at /* passengers */ = ImmutableList.of();
}
VEHICLE_FIELD.set(this, entity);
entity.at /* passengers */ = ImmutableList.of(this);
} catch (Throwable t) {
ConsoleLogger.logDebug(Level.SEVERE, "Couldn't set passenger", t);
}
}
}

View File

@ -0,0 +1,188 @@
/*
* 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_17_R1;
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.CustomNameHelper;
import com.gmail.filoghost.holographicdisplays.nms.interfaces.ItemPickupManager;
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 net.minecraft.core.IRegistry;
import net.minecraft.core.RegistryMaterials;
import net.minecraft.network.chat.ChatComponentText;
import net.minecraft.network.chat.IChatBaseComponent;
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 net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumCreatureType;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.Map;
public class NmsManagerImpl implements NMSManager {
private static final ReflectField<Map<EntityTypes<?>, Integer>> REGISTRY_TO_ID_FIELD = new ReflectField<>(RegistryMaterials.class, "bw");
@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.Y /* ENTITY_TYPES */);
EntityTypes<?> customEntityTypes = EntityTypes.Builder.a(EnumCreatureType.a /* 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.getBukkitEntity().remove();
nmsEntity.setRemoved(RemovalReason.b /* DISCARDED */);
return false;
}
nmsWorld.getChunkAt(chunkX, chunkZ).a(nmsEntity);
try {
nmsWorld.G /* entityManager */ .a /* addNewEntity */ (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;
}
}
}
}

View File

@ -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_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 */;
}
}

View File

@ -125,6 +125,11 @@
<artifactId>holographicdisplays-nms-v1_16_r3</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_17_r1</artifactId>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>

View File

@ -32,7 +32,8 @@ public enum NMSVersion {
v1_15_R1,
v1_16_R1,
v1_16_R2,
v1_16_R3;
v1_16_R3,
v1_17_R1;
private static final NMSVersion CURRENT_VERSION = extractCurrentVersion();

View File

@ -153,6 +153,12 @@
<artifactId>holographicdisplays-nms-v1_16_r3</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_17_r1</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>