diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java index 82762237..a9613301 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java @@ -125,12 +125,15 @@ public class HolographicDisplays extends JavaPlugin { } else if ("v1_8_R2".equals(version)) { is1_8 = true; nmsManager = new com.gmail.filoghost.holographicdisplays.nms.v1_8_R2.NmsManagerImpl(); + } else if ("v1_8_R3".equals(version)) { + is1_8 = true; + nmsManager = new com.gmail.filoghost.holographicdisplays.nms.v1_8_R3.NmsManagerImpl(); } else { printWarnAndDisable( "******************************************************", " This version of HolographicDisplays can", " only work on these server versions:", - " from 1.6.4 to 1.8.3.", + " from 1.6.4 to 1.8.4.", " The plugin will be disabled.", "******************************************************" ); diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSArmorStand.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSArmorStand.java new file mode 100644 index 00000000..fdb487be --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSArmorStand.java @@ -0,0 +1,67 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import java.util.Collection; + +import org.bukkit.EntityEffect; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.CraftServer; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.util.EulerAngle; +import org.bukkit.util.Vector; + +public class CraftNMSArmorStand extends CraftArmorStand { + + public CraftNMSArmorStand(CraftServer server, EntityNMSArmorStand entity) { + super(server, entity); + } + + // Disallow all the bukkit methods. + + @Override + public void remove() { + // Cannot be removed, this is the most important to override. + } + + // Methods from Armor stand 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 setGravity(boolean gravity) { } + @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) { } + + // 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) { } + + // Methods from Entity + @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) { } + +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSItem.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSItem.java new file mode 100644 index 00000000..80b8fded --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSItem.java @@ -0,0 +1,42 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import org.bukkit.EntityEffect; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.CraftServer; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftItem; +import org.bukkit.entity.Entity; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +public class CraftNMSItem extends CraftItem { + + public CraftNMSItem(CraftServer server, EntityNMSItem entity) { + super(server, entity); + } + + // Disallow all the bukkit methods. + + @Override + public void remove() { + // Cannot be removed, this is the most important to override. + } + + // Methods from Entity + @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) { } + + // Methods from Item + @Override public void setItemStack(ItemStack stack) { } + @Override public void setPickupDelay(int delay) { } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSSlime.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSSlime.java new file mode 100644 index 00000000..ddfd5d6c --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/CraftNMSSlime.java @@ -0,0 +1,49 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import java.util.Collection; + +import org.bukkit.EntityEffect; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.CraftServer; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftSlime; +import org.bukkit.entity.Entity; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.potion.PotionEffect; +import org.bukkit.util.Vector; + +public class CraftNMSSlime extends CraftSlime { + + public CraftNMSSlime(CraftServer server, EntityNMSSlime entity) { + super(server, entity); + } + + // Disallow all the bukkit methods. + + @Override + public void remove() { + // Cannot be removed, this is the most important to override. + } + + // Methods from 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) { } + + // Methods from Entity + @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) { } + + // Methods from Slime + @Override public void setSize(int size) { } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSArmorStand.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSArmorStand.java new file mode 100644 index 00000000..22f8fc4a --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSArmorStand.java @@ -0,0 +1,218 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.DamageSource; +import net.minecraft.server.v1_8_R3.EntityArmorStand; +import net.minecraft.server.v1_8_R3.EntityHuman; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.ItemStack; +import net.minecraft.server.v1_8_R3.NBTTagCompound; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_8_R3.Vec3D; +import net.minecraft.server.v1_8_R3.World; + +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; + +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSArmorStand; +import com.gmail.filoghost.holographicdisplays.object.line.CraftHologramLine; +import com.gmail.filoghost.holographicdisplays.util.ReflectionUtils; +import com.gmail.filoghost.holographicdisplays.util.Utils; + +public class EntityNMSArmorStand extends EntityArmorStand implements NMSArmorStand { + + private boolean lockTick; + private CraftHologramLine parentPiece; + + public EntityNMSArmorStand(World world, CraftHologramLine parentPiece) { + super(world); + setInvisible(true); + setSmall(true); + setArms(false); + setGravity(true); + setBasePlate(true); + this.parentPiece = parentPiece; + try { + ReflectionUtils.setPrivateField(EntityArmorStand.class, this, "bi", Integer.MAX_VALUE); + } catch (Exception e) { + // There's still the overridden method. + } + forceSetBoundingBox(new NullBoundingBox()); + } + + + @Override + public void b(NBTTagCompound nbttagcompound) { + // Do not save NBT. + } + + @Override + public boolean c(NBTTagCompound nbttagcompound) { + // Do not save NBT. + return false; + } + + @Override + public boolean d(NBTTagCompound nbttagcompound) { + // Do not save NBT. + return false; + } + + @Override + public void e(NBTTagCompound nbttagcompound) { + // Do not save 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 void setCustomName(String customName) { + // Locks the custom name. + } + + @Override + public void setCustomNameVisible(boolean visible) { + // Locks the custom name. + } + + @Override + public boolean a(EntityHuman human, Vec3D vec3d) { + // Prevent stand being equipped + return true; + } + + @Override + public boolean d(int i, ItemStack item) { + // Prevent stand being equipped + return false; + } + + @Override + public void setEquipment(int i, ItemStack item) { + // Prevent stand being equipped + } + + @Override + public void a(AxisAlignedBB boundingBox) { + // Do not change it! + } + + public void forceSetBoundingBox(AxisAlignedBB boundingBox) { + super.a(boundingBox); + } + + @Override + public int getId() { + + StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + if (elements.length > 2 && elements[2] != null && elements[2].getFileName().equals("EntityTrackerEntry.java") && elements[2].getLineNumber() > 137 && elements[2].getLineNumber() < 147) { + // Then this method is being called when creating a new packet, we return a fake ID! + return -1; + } + + return super.getId(); + } + + @Override + public void t_() { + if (!lockTick) { + super.t_(); + } + } + + @Override + public void makeSound(String sound, float f1, float f2) { + // Remove sounds. + } + + @Override + public void setCustomNameNMS(String name) { + if (name != null && name.length() > 300) { + name = name.substring(0, 300); + } + super.setCustomName(name); + super.setCustomNameVisible(name != null && !name.isEmpty()); + } + + @Override + public String getCustomNameNMS() { + return super.getCustomName(); + } + + + public void callSuperTick() { + super.h(); + } + + @Override + public void setLockTick(boolean lock) { + lockTick = lock; + } + + @Override + public void die() { + setLockTick(false); + super.die(); + } + + @Override + public CraftEntity getBukkitEntity() { + if (super.bukkitEntity == null) { + this.bukkitEntity = new CraftNMSArmorStand(this.world.getServer(), this); + } + return this.bukkitEntity; + } + + @Override + public void killEntityNMS() { + die(); + } + + @Override + public void setLocationNMS(double x, double y, double z) { + super.setPosition(x, y, z); + + + // Send a packet near to update the position. + PacketPlayOutEntityTeleport teleportPacket = new PacketPlayOutEntityTeleport(this); + + for (Object obj : this.world.players) { + if (obj instanceof EntityPlayer) { + EntityPlayer nmsPlayer = (EntityPlayer) obj; + + double distanceSquared = Utils.square(nmsPlayer.locX - this.locX) + Utils.square(nmsPlayer.locZ - this.locZ); + if (distanceSquared < 8192 && nmsPlayer.playerConnection != null) { + nmsPlayer.playerConnection.sendPacket(teleportPacket); + } + } + } + } + + @Override + public boolean isDeadNMS() { + return this.dead; + } + + @Override + public int getIdNMS() { + return this.getId(); + } + + @Override + public CraftHologramLine getHologramLine() { + return parentPiece; + } + + @Override + public org.bukkit.entity.Entity getBukkitEntityNMS() { + return getBukkitEntity(); + } +} \ No newline at end of file diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSItem.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSItem.java new file mode 100644 index 00000000..402ff339 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSItem.java @@ -0,0 +1,222 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.Blocks; +import net.minecraft.server.v1_8_R3.DamageSource; +import net.minecraft.server.v1_8_R3.EntityHuman; +import net.minecraft.server.v1_8_R3.EntityItem; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.ItemStack; +import net.minecraft.server.v1_8_R3.NBTTagCompound; +import net.minecraft.server.v1_8_R3.NBTTagList; +import net.minecraft.server.v1_8_R3.NBTTagString; +import net.minecraft.server.v1_8_R3.World; + +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.entity.Player; + +import com.gmail.filoghost.holographicdisplays.listener.MainListener; +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSEntityBase; +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSItem; +import com.gmail.filoghost.holographicdisplays.object.line.CraftItemLine; +import com.gmail.filoghost.holographicdisplays.util.DebugHandler; +import com.gmail.filoghost.holographicdisplays.util.ItemUtils; +import com.gmail.filoghost.holographicdisplays.util.ReflectionUtils; + +public class EntityNMSItem extends EntityItem implements NMSItem { + + private boolean lockTick; + private CraftItemLine parentPiece; + + public EntityNMSItem(World world, CraftItemLine piece) { + super(world); + super.pickupDelay = Integer.MAX_VALUE; + this.parentPiece = piece; + } + + @Override + public void t_() { + + // So it won't get removed. + ticksLived = 0; + + if (!lockTick) { + super.t_(); + } + } + + @Override + public ItemStack getItemStack() { + // Dirty method to check if the icon is being picked up + StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); + if (stacktrace.length > 2 && stacktrace[2].getClassName().contains("EntityInsentient")) { + return null; // Try to pickup this, dear entity ignoring the pickupDelay! + } + + return super.getItemStack(); + } + + // Method called when a player is near. + @Override + public void d(EntityHuman human) { + + if (human.locY < this.locY - 1.5 || human.locY > this.locY + 1.0) { + // Too low or too high, it's a bit weird. + return; + } + + if (parentPiece.getPickupHandler() != null && human instanceof EntityPlayer) { + MainListener.handleItemLinePickup((Player) human.getBukkitEntity(), parentPiece.getPickupHandler(), parentPiece.getParent()); + // It is never added to the inventory. + } + } + + @Override + public void b(NBTTagCompound nbttagcompound) { + // Do not save NBT. + } + + @Override + public boolean c(NBTTagCompound nbttagcompound) { + // Do not save NBT. + return false; + } + + @Override + public boolean d(NBTTagCompound nbttagcompound) { + // Do not save NBT. + return false; + } + + @Override + public void e(NBTTagCompound nbttagcompound) { + // Do not save 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 void inactiveTick() { + // Check inactive ticks. + + if (!lockTick) { + super.inactiveTick(); + } + } + + @Override + public void setLockTick(boolean lock) { + lockTick = lock; + } + + @Override + public void die() { + setLockTick(false); + super.die(); + } + + @Override + public CraftEntity getBukkitEntity() { + if (super.bukkitEntity == null) { + this.bukkitEntity = new CraftNMSItem(this.world.getServer(), this); + } + return this.bukkitEntity; + } + + @Override + public boolean isDeadNMS() { + return this.dead; + } + + @Override + public void killEntityNMS() { + die(); + } + + @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 = new ItemStack(Blocks.BEDROCK); + } + + if (newItem.getTag() == null) { + newItem.setTag(new NBTTagCompound()); + } + NBTTagCompound display = newItem.getTag().getCompound("display"); + + if (!newItem.getTag().hasKey("display")) { + newItem.getTag().set("display", display); + } + + NBTTagList tagList = new NBTTagList(); + tagList.add(new NBTTagString(ItemUtils.ANTISTACK_LORE)); // Antistack lore + + display.set("Lore", tagList); + newItem.count = 0; + setItemStack(newItem); + } + + @Override + public int getIdNMS() { + return this.getId(); + } + + @Override + public CraftItemLine getHologramLine() { + return parentPiece; + } + + @Override + public void allowPickup(boolean pickup) { + if (pickup) { + super.pickupDelay = 0; + } else { + super.pickupDelay = Integer.MAX_VALUE; + } + } + + @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 { + ReflectionUtils.setPrivateField(Entity.class, this, "ar", (double) 0.0); + ReflectionUtils.setPrivateField(Entity.class, this, "as", (double) 0.0); + } catch (Exception ex) { + DebugHandler.handleDebugException(ex); + } + + if (this.vehicle != null) { + this.vehicle.passenger = null; + } + + this.vehicle = entity; + entity.passenger = this; + } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSSlime.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSSlime.java new file mode 100644 index 00000000..eb4ca686 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/EntityNMSSlime.java @@ -0,0 +1,192 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import net.minecraft.server.v1_8_R3.EntityDamageSource; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.DamageSource; +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.EntitySlime; +import net.minecraft.server.v1_8_R3.NBTTagCompound; +import net.minecraft.server.v1_8_R3.World; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.event.player.PlayerInteractEntityEvent; + +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSEntityBase; +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSSlime; +import com.gmail.filoghost.holographicdisplays.object.line.CraftHologramLine; +import com.gmail.filoghost.holographicdisplays.object.line.CraftTouchSlimeLine; +import com.gmail.filoghost.holographicdisplays.util.DebugHandler; +import com.gmail.filoghost.holographicdisplays.util.ReflectionUtils; + +public class EntityNMSSlime extends EntitySlime implements NMSSlime { + + private boolean lockTick; + private CraftTouchSlimeLine parentPiece; + + public EntityNMSSlime(World world, CraftTouchSlimeLine parentPiece) { + super(world); + super.persistent = true; + a(0.0F, 0.0F); + setSize(1); + setInvisible(true); + this.parentPiece = parentPiece; + forceSetBoundingBox(new NullBoundingBox()); + } + + @Override + public void a(AxisAlignedBB boundingBox) { + // Do not change it! + } + + public void forceSetBoundingBox(AxisAlignedBB boundingBox) { + super.a(boundingBox); + } + + @Override + public void t_() { + // Checks every 20 ticks. + if (ticksLived % 20 == 0) { + // The slime dies without a vehicle. + if (this.vehicle == null) { + die(); + } + } + + if (!lockTick) { + super.t_(); + } + } + + @Override + public void b(NBTTagCompound nbttagcompound) { + // Do not save NBT. + } + + @Override + public boolean c(NBTTagCompound nbttagcompound) { + // Do not save NBT. + return false; + } + + @Override + public boolean d(NBTTagCompound nbttagcompound) { + // Do not save NBT. + return false; + } + + @Override + public void e(NBTTagCompound nbttagcompound) { + // Do not save 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())); + } + } + 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 void setCustomName(String customName) { + // Locks the custom name. + } + + @Override + public void setCustomNameVisible(boolean visible) { + // Locks the custom name. + } + + @Override + public void makeSound(String sound, float volume, float pitch) { + // Remove sounds. + } + + @Override + public void setLockTick(boolean lock) { + lockTick = lock; + } + + @Override + public void die() { + setLockTick(false); + super.die(); + } + + @Override + public CraftEntity getBukkitEntity() { + if (super.bukkitEntity == null) { + this.bukkitEntity = new CraftNMSSlime(this.world.getServer(), this); + } + return this.bukkitEntity; + } + + @Override + public boolean isDeadNMS() { + return super.dead; + } + + @Override + public void killEntityNMS() { + die(); + } + + @Override + public void setLocationNMS(double x, double y, double z) { + super.setPosition(x, y, z); + } + + @Override + public int getIdNMS() { + return this.getId(); + } + + @Override + public CraftHologramLine 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 { + ReflectionUtils.setPrivateField(Entity.class, this, "ar", (double) 0.0); + ReflectionUtils.setPrivateField(Entity.class, this, "as", (double) 0.0); + } catch (Exception ex) { + DebugHandler.handleDebugException(ex); + } + + if (this.vehicle != null) { + this.vehicle.passenger = null; + } + + this.vehicle = entity; + entity.passenger = this; + } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/FancyMessageImpl.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/FancyMessageImpl.java new file mode 100644 index 00000000..dcd35196 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/FancyMessageImpl.java @@ -0,0 +1,170 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.server.v1_8_R3.IChatBaseComponent; +import net.minecraft.server.v1_8_R3.PacketPlayOutChat; + +import org.bukkit.ChatColor; + +import com.google.gson.stream.JsonWriter; + +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import com.gmail.filoghost.holographicdisplays.nms.interfaces.FancyMessage; + +public class FancyMessageImpl implements FancyMessage { + + private List messageParts; + + public FancyMessageImpl(String firstPartText) { + messageParts = new ArrayList(); + messageParts.add(new MessagePart(firstPartText)); + } + + @Override + public FancyMessageImpl color(ChatColor color) { + if (!color.isColor()) { + throw new IllegalArgumentException(color.name() + " is not a color"); + } + latest().color = color; + return this; + } + + @Override + public FancyMessageImpl style(ChatColor... styles) { + for (ChatColor style : styles) { + if (!style.isFormat()) { + throw new IllegalArgumentException(style.name() + " is not a style"); + } + } + latest().styles = styles; + return this; + } + + @Override + public FancyMessageImpl file(String path) { + onClick("open_file", path); + return this; + } + + @Override + public FancyMessageImpl link(String url) { + onClick("open_url", url); + return this; + } + + @Override + public FancyMessageImpl suggest(String command) { + onClick("suggest_command", command); + return this; + } + + @Override + public FancyMessageImpl command(String command) { + onClick("run_command", command); + return this; + } + + @Override + public FancyMessageImpl tooltip(String text) { + onHover("show_text", text); + return this; + } + + @Override + public FancyMessageImpl then(Object obj) { + messageParts.add(new MessagePart(obj.toString())); + return this; + } + + @Override + public String toJSONString() { + StringWriter stringWriter = new StringWriter(); + JsonWriter json = new JsonWriter(stringWriter); + + try { + if (messageParts.size() == 1) { + latest().writeJson(json); + } else { + json.beginObject().name("text").value("").name("extra").beginArray(); + for (MessagePart part : messageParts) { + part.writeJson(json); + } + json.endArray().endObject(); + } + + } catch (IOException e) { + throw new RuntimeException("invalid message"); + } + return stringWriter.toString(); + } + + @Override + public void send(Player player) { + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutChat(IChatBaseComponent.ChatSerializer.a(toJSONString()))); + } + + private MessagePart latest() { + return messageParts.get(messageParts.size() - 1); + } + + private void onClick(String name, String data) { + MessagePart latest = latest(); + latest.clickActionName = name; + latest.clickActionData = data; + } + + private void onHover(String name, String data) { + MessagePart latest = latest(); + latest.hoverActionName = name; + latest.hoverActionData = data; + } + + static class MessagePart { + + public ChatColor color = null; + public ChatColor[] styles = null; + public String clickActionName = null; + public String clickActionData = null; + public String hoverActionName = null; + public String hoverActionData = null; + public final String text; + + public MessagePart(final String text) { + this.text = text; + } + + public JsonWriter writeJson(final JsonWriter json) throws IOException { + json.beginObject().name("text").value(text); + if (color != null) { + json.name("color").value(color.name().toLowerCase()); + } + if (styles != null) { + for (final ChatColor style : styles) { + json.name(style == ChatColor.UNDERLINE ? "underlined" : style.name().toLowerCase()).value(true); + } + } + if (clickActionName != null && clickActionData != null) { + json.name("clickEvent") + .beginObject() + .name("action").value(clickActionName) + .name("value").value(clickActionData) + .endObject(); + } + if (hoverActionName != null && hoverActionData != null) { + json.name("hoverEvent") + .beginObject() + .name("action").value(hoverActionName) + .name("value").value(hoverActionData) + .endObject(); + } + return json.endObject(); + } + + } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/NmsManagerImpl.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/NmsManagerImpl.java new file mode 100644 index 00000000..422dde47 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/NmsManagerImpl.java @@ -0,0 +1,161 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import java.lang.reflect.Method; + +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.EntityTypes; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.World; +import net.minecraft.server.v1_8_R3.WorldServer; + +import org.apache.commons.lang.NotImplementedException; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.ItemStack; + +import com.gmail.filoghost.holographicdisplays.nms.interfaces.FancyMessage; +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.NMSHorse; +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSItem; +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSWitherSkull; +import com.gmail.filoghost.holographicdisplays.object.line.CraftHologramLine; +import com.gmail.filoghost.holographicdisplays.object.line.CraftItemLine; +import com.gmail.filoghost.holographicdisplays.object.line.CraftTouchSlimeLine; +import com.gmail.filoghost.holographicdisplays.util.DebugHandler; +import com.gmail.filoghost.holographicdisplays.util.ReflectionUtils; +import com.gmail.filoghost.holographicdisplays.util.Validator; +import com.gmail.filoghost.holographicdisplays.util.VersionUtils; + +public class NmsManagerImpl implements NMSManager { + + private Method validateEntityMethod; + + @Override + public void setup() throws Exception { + registerCustomEntity(EntityNMSArmorStand.class, "ArmorStand", 30); + registerCustomEntity(EntityNMSItem.class, "Item", 1); + registerCustomEntity(EntityNMSSlime.class, "Slime", 55); + + if (!VersionUtils.isMCPCOrCauldron()) { + validateEntityMethod = World.class.getDeclaredMethod("a", Entity.class); + validateEntityMethod.setAccessible(true); + } + } + + @SuppressWarnings("rawtypes") + public void registerCustomEntity(Class entityClass, String name, int id) throws Exception { + if (VersionUtils.isMCPCOrCauldron()) { + // MCPC+ / Cauldron entity registration. + Class entityTypesClass = Class.forName("net.minecraft.server.v1_8_R3.EntityTypes"); + ReflectionUtils.putInPrivateStaticMap(entityTypesClass, "field_75626_c", entityClass, name); + ReflectionUtils.putInPrivateStaticMap(entityTypesClass, "field_75624_e", entityClass, Integer.valueOf(id)); + } else { + // Normal entity registration. + ReflectionUtils.putInPrivateStaticMap(EntityTypes.class, "d", entityClass, name); + ReflectionUtils.putInPrivateStaticMap(EntityTypes.class, "f", entityClass, Integer.valueOf(id)); + } + } + + @Override + public NMSHorse spawnNMSHorse(org.bukkit.World world, double x, double y, double z, CraftHologramLine parentPiece) { + throw new NotImplementedException("Method can only be used on 1.7 or lower"); + } + + @Override + public NMSWitherSkull spawnNMSWitherSkull(org.bukkit.World bukkitWorld, double x, double y, double z, CraftHologramLine parentPiece) { + throw new NotImplementedException("Method can only be used on 1.7 or lower"); + } + + @Override + public NMSItem spawnNMSItem(org.bukkit.World bukkitWorld, double x, double y, double z, CraftItemLine parentPiece, ItemStack stack) { + WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle(); + EntityNMSItem customItem = new EntityNMSItem(nmsWorld, parentPiece); + customItem.setLocationNMS(x, y, z); + customItem.setItemStackNMS(stack); + if (!addEntityToWorld(nmsWorld, customItem)) { + DebugHandler.handleSpawnFail(parentPiece); + } + return customItem; + } + + @Override + public EntityNMSSlime spawnNMSSlime(org.bukkit.World bukkitWorld, double x, double y, double z, CraftTouchSlimeLine parentPiece) { + WorldServer nmsWorld = ((CraftWorld) bukkitWorld).getHandle(); + EntityNMSSlime touchSlime = new EntityNMSSlime(nmsWorld, parentPiece); + touchSlime.setLocationNMS(x, y, z); + if (!addEntityToWorld(nmsWorld, touchSlime)) { + DebugHandler.handleSpawnFail(parentPiece); + } + return touchSlime; + } + + @Override + public NMSArmorStand spawnNMSArmorStand(org.bukkit.World world, double x, double y, double z, CraftHologramLine parentPiece) { + WorldServer nmsWorld = ((CraftWorld) world).getHandle(); + EntityNMSArmorStand invisibleArmorStand = new EntityNMSArmorStand(nmsWorld, parentPiece); + invisibleArmorStand.setLocationNMS(x, y, z); + if (!addEntityToWorld(nmsWorld, invisibleArmorStand)) { + DebugHandler.handleSpawnFail(parentPiece); + } + return invisibleArmorStand; + } + + private boolean addEntityToWorld(WorldServer nmsWorld, Entity nmsEntity) { + Validator.isTrue(Bukkit.isPrimaryThread(), "Async entity add"); + + if (validateEntityMethod == null) { + return nmsWorld.addEntity(nmsEntity, SpawnReason.CUSTOM); + } + + final int chunkX = MathHelper.floor(nmsEntity.locX / 16.0); + final int chunkZ = MathHelper.floor(nmsEntity.locZ / 16.0); + + if (!nmsWorld.chunkProviderServer.isChunkLoaded(chunkX, chunkZ)) { + // This should never happen + nmsEntity.dead = true; + return false; + } + + nmsWorld.getChunkAt(chunkX, chunkZ).a(nmsEntity); + nmsWorld.entityList.add(nmsEntity); + + try { + validateEntityMethod.invoke(nmsWorld, nmsEntity); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + @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); + } + + return null; + } + + @Override + public FancyMessage newFancyMessage(String text) { + return new FancyMessageImpl(text); + } + + @Override + public boolean hasChatHoverFeature() { + return true; + } + +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/NullBoundingBox.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/NullBoundingBox.java new file mode 100644 index 00000000..178a94ba --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_8_R3/NullBoundingBox.java @@ -0,0 +1,75 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_8_R3; + +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class NullBoundingBox extends AxisAlignedBB { + + public NullBoundingBox() { + super(0, 0, 0, 0, 0, 0); + } + + @Override + public double a() { + return 0.0; + } + + @Override + public double a(AxisAlignedBB arg0, double arg1) { + 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 MovingObjectPosition a(Vec3D arg0, Vec3D arg1) { + return super.a(arg0, arg1); + } + + @Override + public boolean a(Vec3D arg0) { + return false; + } + + @Override + public double b(AxisAlignedBB arg0, double arg1) { + return 0.0; + } + + @Override + public boolean b(AxisAlignedBB arg0) { + return false; + } + + @Override + public double c(AxisAlignedBB arg0, double arg1) { + return 0.0; + } + + @Override + public AxisAlignedBB c(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, double arg1, double arg2) { + return this; + } + + + +} \ No newline at end of file diff --git a/HolographicDisplays/plugin.yml b/HolographicDisplays/plugin.yml index 8ca268c8..15e5bbdc 100644 --- a/HolographicDisplays/plugin.yml +++ b/HolographicDisplays/plugin.yml @@ -1,6 +1,6 @@ name: HolographicDisplays main: com.gmail.filoghost.holographicdisplays.HolographicDisplays -version: 2.1.9 +version: 2.1.10 softdepend: [Multiverse-Core, MultiWorld, My Worlds, My_Worlds, ProtocolLib]