diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java index 78897146..f34fe6a1 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/HolographicDisplays.java @@ -7,7 +7,6 @@ import org.bukkit.plugin.java.JavaPlugin; import com.gmail.filoghost.holographicdisplays.SimpleUpdater.ResponseHandler; import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker; -import com.gmail.filoghost.holographicdisplays.bridge.protocollib.ProtocolLibHook; import com.gmail.filoghost.holographicdisplays.commands.main.HologramsCommandHandler; import com.gmail.filoghost.holographicdisplays.disk.Configuration; import com.gmail.filoghost.holographicdisplays.disk.HologramDatabase; @@ -39,7 +38,10 @@ public class HolographicDisplays extends JavaPlugin { private HologramsCommandHandler commandHandler; // Since 1.8 we use armor stands instead of wither skulls. - private static boolean is1_8; + private static boolean is18orGreater; + + // Since 1.9 there is a different offset for the nametag. + private static boolean is19orGreater; // Used for the server pinger. private static boolean isPreNetty; @@ -120,20 +122,24 @@ public class HolographicDisplays extends JavaPlugin { } else if ("v1_7_R4".equals(version)) { nmsManager = new com.gmail.filoghost.holographicdisplays.nms.v1_7_R4.NmsManagerImpl(); } else if ("v1_8_R1".equals(version)) { - is1_8 = true; + is18orGreater = true; nmsManager = new com.gmail.filoghost.holographicdisplays.nms.v1_8_R1.NmsManagerImpl(); } else if ("v1_8_R2".equals(version)) { - is1_8 = true; + is18orGreater = true; nmsManager = new com.gmail.filoghost.holographicdisplays.nms.v1_8_R2.NmsManagerImpl(); } else if ("v1_8_R3".equals(version)) { - is1_8 = true; + is18orGreater = true; nmsManager = new com.gmail.filoghost.holographicdisplays.nms.v1_8_R3.NmsManagerImpl(); + } else if ("v1_9_R1".equals(version)) { + is18orGreater = true; + is19orGreater = true; + nmsManager = new com.gmail.filoghost.holographicdisplays.nms.v1_9_R1.NmsManagerImpl(); } else { printWarnAndDisable( "******************************************************", " This version of HolographicDisplays can", " only work on these server versions:", - " from 1.6.4 to 1.8.8.", + " from 1.6.4 to 1.9.", " The plugin will be disabled.", "******************************************************" ); @@ -157,7 +163,7 @@ public class HolographicDisplays extends JavaPlugin { "******************************************************", " HolographicDisplays was unable to register", " custom entities, the plugin will be disabled.", - " Are you using the correct Bukkit version?", + " Are you using the correct Bukkit/Spigot version?", "******************************************************" ); return; @@ -166,7 +172,11 @@ public class HolographicDisplays extends JavaPlugin { // ProtocolLib check. try { if (Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) { - useProtocolLib = ProtocolLibHook.load(nmsManager, this, is1_8); + if (is19orGreater) { + useProtocolLib = com.gmail.filoghost.holographicdisplays.bridge.protocollib.current.ProtocolLibHook.load(nmsManager, this); + } else { + useProtocolLib = com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9.ProtocolLibHook.load(nmsManager, this, is18orGreater); + } } } catch (Exception ex) { ex.printStackTrace(); @@ -214,8 +224,8 @@ public class HolographicDisplays extends JavaPlugin { "******************************************************", " HolographicDisplays was unable to register", " the command \"holograms\". Do not modify", - " plugin.yml removing commands, if you're", - " doing so.", + " plugin.yml removing commands, if this is", + " the case.", "******************************************************" ); return; @@ -249,8 +259,12 @@ public class HolographicDisplays extends JavaPlugin { return commandHandler; } - public static boolean is1_8() { - return is1_8; + public static boolean is18orGreater() { + return is18orGreater; + } + + public static boolean is19orGreater() { + return is19orGreater; } public static boolean isPreNetty() { diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/bungeecord/BungeeChannel.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/bungeecord/BungeeChannel.java index 13bae5d2..a00e5b2c 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/bungeecord/BungeeChannel.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/bungeecord/BungeeChannel.java @@ -6,6 +6,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; +import java.util.Collection; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -14,6 +15,7 @@ import org.bukkit.plugin.messaging.PluginMessageListener; import com.gmail.filoghost.holographicdisplays.HolographicDisplays; import com.gmail.filoghost.holographicdisplays.disk.Configuration; +import com.gmail.filoghost.holographicdisplays.util.VersionUtils; public class BungeeChannel implements PluginMessageListener { @@ -80,7 +82,7 @@ public class BungeeChannel implements PluginMessageListener { } } - @SuppressWarnings("deprecation") + public void askPlayerCount(String server) { ByteArrayOutputStream b = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(b); @@ -95,9 +97,9 @@ public class BungeeChannel implements PluginMessageListener { } // OR, if you don't need to send it to a specific player - Player[] players = Bukkit.getOnlinePlayers(); - if (players.length > 0) { - players[0].sendPluginMessage(HolographicDisplays.getInstance(), Configuration.useRedisBungee ? "RedisBungee" : "BungeeCord", b.toByteArray()); + Collection players = VersionUtils.getOnlinePlayers(); + if (players.size() > 0) { + players.iterator().next().sendPluginMessage(HolographicDisplays.getInstance(), Configuration.useRedisBungee ? "RedisBungee" : "BungeeCord", b.toByteArray()); } } } diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/AbstractPacket.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/AbstractPacket.java new file mode 100644 index 00000000..385b29c9 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/AbstractPacket.java @@ -0,0 +1,82 @@ +/* + * PacketWrapper - Contains wrappers for each packet in Minecraft. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; + +import java.lang.reflect.InvocationTargetException; + +import org.bukkit.entity.Player; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.google.common.base.Objects; + +public abstract class AbstractPacket { + // The packet we will be modifying + protected PacketContainer handle; + + /** + * Constructs a new strongly typed wrapper for the given packet. + * @param handle - handle to the raw packet data. + * @param type - the packet type. + */ + protected AbstractPacket(PacketContainer handle, PacketType type) { + // Make sure we're given a valid packet + if (handle == null) + throw new IllegalArgumentException("Packet handle cannot be NULL."); + if (!Objects.equal(handle.getType(), type)) + throw new IllegalArgumentException( + handle.getHandle() + " is not a packet of type " + type); + + this.handle = handle; + } + + /** + * Retrieve a handle to the raw packet data. + * @return Raw packet data. + */ + public PacketContainer getHandle() { + return handle; + } + + /** + * Send the current packet to the given receiver. + * @param receiver - the receiver. + * @throws RuntimeException If the packet cannot be sent. + */ + public void sendPacket(Player receiver) { + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(receiver, getHandle()); + } catch (InvocationTargetException e) { + throw new RuntimeException("Cannot send packet.", e); + } + } + + /** + * Simulate receiving the current packet from the given sender. + * @param sender - the sender. + * @throws RuntimeException If the packet cannot be received. + */ + public void recievePacket(Player sender) { + try { + ProtocolLibrary.getProtocolManager().recieveClientPacket(sender, getHandle()); + } catch (Exception e) { + throw new RuntimeException("Cannot recieve packet.", e); + } + } +} \ No newline at end of file diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/ProtocolLibHook.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/ProtocolLibHook.java new file mode 100644 index 00000000..4d5f7396 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/ProtocolLibHook.java @@ -0,0 +1,287 @@ +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; + +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; +import com.comphenix.protocol.wrappers.WrappedWatchableObject; +import com.gmail.filoghost.holographicdisplays.bridge.protocollib.current.WrapperPlayServerSpawnEntity.ObjectTypes; +import com.gmail.filoghost.holographicdisplays.nms.interfaces.NMSManager; +import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSEntityBase; +import com.gmail.filoghost.holographicdisplays.object.CraftHologram; +import com.gmail.filoghost.holographicdisplays.object.line.CraftHologramLine; +import com.gmail.filoghost.holographicdisplays.object.line.CraftItemLine; +import com.gmail.filoghost.holographicdisplays.object.line.CraftTextLine; +import com.gmail.filoghost.holographicdisplays.object.line.CraftTouchSlimeLine; +import com.gmail.filoghost.holographicdisplays.object.line.CraftTouchableLine; +import com.gmail.filoghost.holographicdisplays.util.Utils; + +public class ProtocolLibHook { + + private static boolean hasProtocolLib; + private static NMSManager nmsManager; + + public static boolean load(NMSManager nmsManager, Plugin plugin) { + ProtocolLibHook.nmsManager = nmsManager; + + if (Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) { + + //TODO + Bukkit.getConsoleSender().sendMessage( + ChatColor.RED + "[Holographic Displays] Detected development version of ProtocolLib, support disabled. " + + "Related functions (the placeholders {player} {displayname} and the visibility API) will not work.\n" + + "The reason is that this version of ProtocolLib is unstable and partly broken. " + + "A new version of Holographic Displays will be out when ProtocolLib gets fixed."); + return false; + + /* + hasProtocolLib = true; + + plugin.getLogger().info("Found ProtocolLib, adding support for player relative variables."); + + ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.SPAWN_ENTITY_LIVING, PacketType.Play.Server.SPAWN_ENTITY, PacketType.Play.Server.ENTITY_METADATA) { + + @Override + public void onPacketSending(PacketEvent event) { + + PacketContainer packet = event.getPacket(); + + // Spawn entity packet + if (packet.getType() == PacketType.Play.Server.SPAWN_ENTITY_LIVING) { + + WrapperPlayServerSpawnEntityLiving spawnEntityPacket = new WrapperPlayServerSpawnEntityLiving(packet); + Entity entity = spawnEntityPacket.getEntity(event); + + if (entity == null || !isHologramType(entity.getType())) { + return; + } + + CraftHologram hologram = getHologram(entity); + if (hologram == null) { + return; + } + + Player player = event.getPlayer(); + if (!hologram.getVisibilityManager().isVisibleTo(player)) { + event.setCancelled(true); + return; + } + + WrappedDataWatcher dataWatcher = spawnEntityPacket.getMetadata(); + String customName = dataWatcher.getString(2); + + if (customName == null) { + return; + } + + if (customName.contains("{player}") || customName.contains("{displayname}")) { + + WrappedDataWatcher dataWatcherClone = dataWatcher.deepClone(); + dataWatcherClone.setObject(2, customName.replace("{player}", player.getName()).replace("{displayname}", player.getDisplayName())); + spawnEntityPacket.setMetadata(dataWatcherClone); + event.setPacket(spawnEntityPacket.getHandle()); + + } + + } else if (packet.getType() == PacketType.Play.Server.SPAWN_ENTITY) { + + WrapperPlayServerSpawnEntity spawnEntityPacket = new WrapperPlayServerSpawnEntity(packet); + int objectId = spawnEntityPacket.getType(); + if (objectId != ObjectTypes.ITEM_STACK && objectId != ObjectTypes.ARMOR_STAND) { + return; + } + + Entity entity = spawnEntityPacket.getEntity(event); + if (entity == null) { + return; + } + + CraftHologram hologram = getHologram(entity); + if (hologram == null) { + return; + } + + Player player = event.getPlayer(); + if (!hologram.getVisibilityManager().isVisibleTo(player)) { + event.setCancelled(true); + return; + } + + } else if (packet.getType() == PacketType.Play.Server.ENTITY_METADATA) { + + WrapperPlayServerEntityMetadata entityMetadataPacket = new WrapperPlayServerEntityMetadata(packet); + Entity entity = entityMetadataPacket.getEntity(event); + + if (entity == null) { + return; + } + + if (entity.getType() != EntityType.ARMOR_STAND) { + // Enough, only armorstands are used with custom names. + return; + } + + CraftHologram hologram = getHologram(entity); + if (hologram == null) { + return; + } + + Player player = event.getPlayer(); + if (!hologram.getVisibilityManager().isVisibleTo(player)) { + event.setCancelled(true); + return; + } + + List dataWatcherValues = entityMetadataPacket.getEntityMetadata(); + + for (int i = 0; i < dataWatcherValues.size(); i++) { + + if (dataWatcherValues.get(i).getIndex() == 2 && dataWatcherValues.get(i).getValue() != null) { + + Object customNameObject = dataWatcherValues.get(i).deepClone().getValue(); + if (customNameObject == null || customNameObject instanceof String == false) { + return; + } + + String customName = (String) customNameObject; + + if (customName.contains("{player}") || customName.contains("{displayname}")) { + + entityMetadataPacket = new WrapperPlayServerEntityMetadata(packet.deepClone()); + List clonedList = entityMetadataPacket.getEntityMetadata(); + WrappedWatchableObject clonedElement = clonedList.get(i); + clonedElement.setValue(customName.replace("{player}", player.getName()).replace("{displayname}", player.getDisplayName())); + entityMetadataPacket.setEntityMetadata(clonedList); + event.setPacket(entityMetadataPacket.getHandle()); + return; + + } + } + } + } + } + }); + + return true; + */ + } + + return false; + } + + public static void sendDestroyEntitiesPacket(Player player, CraftHologram hologram) { + if (!hasProtocolLib) { + return; + } + + List ids = Utils.newList(); + for (CraftHologramLine line : hologram.getLinesUnsafe()) { + if (line.isSpawned()) { + for (int id : line.getEntitiesIDs()) { + ids.add(id); + } + } + } + + if (!ids.isEmpty()) { + WrapperPlayServerEntityDestroy packet = new WrapperPlayServerEntityDestroy(); + packet.setEntities(ids); + packet.sendPacket(player); + } + } + + public static void sendCreateEntitiesPacket(Player player, CraftHologram hologram) { + if (!hasProtocolLib) { + return; + } + + for (CraftHologramLine line : hologram.getLinesUnsafe()) { + if (line.isSpawned()) { + + if (line instanceof CraftTextLine) { + CraftTextLine textLine = (CraftTextLine) line; + + if (textLine.isSpawned()) { + + AbstractPacket nameablePacket = new WrapperPlayServerSpawnEntityLiving(textLine.getNmsNameble().getBukkitEntityNMS()); + nameablePacket.sendPacket(player); + + } + + } else if (line instanceof CraftItemLine) { + CraftItemLine itemLine = (CraftItemLine) line; + + if (itemLine.isSpawned()) { + AbstractPacket itemPacket = new WrapperPlayServerSpawnEntity(itemLine.getNmsItem().getBukkitEntityNMS(), ObjectTypes.ITEM_STACK, 1); + itemPacket.sendPacket(player); + + AbstractPacket vehiclePacket = new WrapperPlayServerSpawnEntityLiving(itemLine.getNmsVehicle().getBukkitEntityNMS()); + + vehiclePacket.sendPacket(player); + + WrapperPlayServerMount attachPacket = new WrapperPlayServerMount(); + attachPacket.setVehicleId(itemLine.getNmsVehicle().getIdNMS()); + attachPacket.setPassengers(new int[] {itemLine.getNmsItem().getIdNMS()}); + attachPacket.sendPacket(player); + + WrapperPlayServerEntityMetadata itemDataPacket = new WrapperPlayServerEntityMetadata(); + + List metadata = Utils.newList(); + metadata.add(new WrappedWatchableObject(10, itemLine.getItemStack())); + metadata.add(new WrappedWatchableObject(1, (short) 300)); + metadata.add(new WrappedWatchableObject(0, (byte) 0)); + itemDataPacket.setEntityMetadata(metadata); + itemDataPacket.setEntityId(itemLine.getNmsItem().getIdNMS()); + itemDataPacket.sendPacket(player); + } + } + + // Unsafe cast, however both CraftTextLine and CraftItemLine are touchable. + CraftTouchableLine touchableLine = (CraftTouchableLine) line; + + if (touchableLine.isSpawned() && touchableLine.getTouchSlime() != null) { + + CraftTouchSlimeLine touchSlime = touchableLine.getTouchSlime(); + + if (touchSlime.isSpawned()) { + AbstractPacket vehiclePacket = new WrapperPlayServerSpawnEntityLiving(touchSlime.getNmsVehicle().getBukkitEntityNMS()); + vehiclePacket.sendPacket(player); + + AbstractPacket slimePacket = new WrapperPlayServerSpawnEntityLiving(touchSlime.getNmsSlime().getBukkitEntityNMS()); + slimePacket.sendPacket(player); + + WrapperPlayServerMount attachPacket = new WrapperPlayServerMount(); + attachPacket.setVehicleId(touchSlime.getNmsVehicle().getIdNMS()); + attachPacket.setPassengers(new int[] {touchSlime.getNmsSlime().getIdNMS()}); + attachPacket.sendPacket(player); + } + } + } + } + } + + private static boolean isHologramType(EntityType type) { + return type == EntityType.ARMOR_STAND || type == EntityType.DROPPED_ITEM || type == EntityType.SLIME; + } + + private static CraftHologram getHologram(Entity bukkitEntity) { + NMSEntityBase entity = nmsManager.getNMSEntityBase(bukkitEntity); + if (entity != null) { + return entity.getHologramLine().getParent(); + } + + return null; + } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerEntityDestroy.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerEntityDestroy.java new file mode 100644 index 00000000..05095015 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerEntityDestroy.java @@ -0,0 +1,61 @@ +/* + * PacketWrapper - Contains wrappers for each packet in Minecraft. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; + +import java.util.List; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.google.common.primitives.Ints; + +public class WrapperPlayServerEntityDestroy extends AbstractPacket { + public static final PacketType TYPE = PacketType.Play.Server.ENTITY_DESTROY; + + public WrapperPlayServerEntityDestroy() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerEntityDestroy(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve the IDs of the entities that will be destroyed. + * @return The current entities. + */ + public List getEntities() { + return Ints.asList(handle.getIntegerArrays().read(0)); + } + + /** + * Set the entities that will be destroyed. + * @param value - new value. + */ + public void setEntities(int[] entities) { + handle.getIntegerArrays().write(0, entities); + } + + /** + * Set the entities that will be destroyed. + * @param value - new value. + */ + public void setEntities(List entities) { + setEntities(Ints.toArray(entities)); + } +} \ No newline at end of file diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerEntityMetadata.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerEntityMetadata.java new file mode 100644 index 00000000..1f05c005 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerEntityMetadata.java @@ -0,0 +1,94 @@ +/* + * PacketWrapper - Contains wrappers for each packet in Minecraft. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; + +import java.util.List; + +import org.bukkit.World; +import org.bukkit.entity.Entity; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; +import com.comphenix.protocol.wrappers.WrappedWatchableObject; + +public class WrapperPlayServerEntityMetadata extends AbstractPacket { + public static final PacketType TYPE = PacketType.Play.Server.ENTITY_METADATA; + + public WrapperPlayServerEntityMetadata() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerEntityMetadata(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve unique entity ID to update. + * @return The current Entity ID + */ + public int getEntityId() { + return handle.getIntegers().read(0); + } + + /** + * Set unique entity ID to update. + * @param value - new value. + */ + public void setEntityId(int value) { + handle.getIntegers().write(0, value); + } + + /** + * Retrieve the entity. + * @param world - the current world of the entity. + * @return The entity. + */ + public Entity getEntity(World world) { + return handle.getEntityModifier(world).read(0); + } + + /** + * Retrieve the entity. + * @param event - the packet event. + * @return The entity. + */ + public Entity getEntity(PacketEvent event) { + return getEntity(event.getPlayer().getWorld()); + } + + /** + * Retrieve a list of all the watchable objects. + *

+ * This can be converted to a data watcher using {@link WrappedDataWatcher#WrappedDataWatcher(List) WrappedDataWatcher(List)} + * @return The current metadata + */ + public List getEntityMetadata() { + return handle.getWatchableCollectionModifier().read(0); + } + + /** + * Set the list of the watchable objects (meta data). + * @param value - new value. + */ + public void setEntityMetadata(List value) { + handle.getWatchableCollectionModifier().write(0, value); + } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerMount.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerMount.java new file mode 100644 index 00000000..36fcb9a9 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerMount.java @@ -0,0 +1,78 @@ +/* + * PacketWrapper - Contains wrappers for each packet in Minecraft. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; + +import java.util.List; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.google.common.primitives.Ints; + +public class WrapperPlayServerMount extends AbstractPacket { + + public static final PacketType TYPE = PacketType.Play.Server.MOUNT; + + public WrapperPlayServerMount() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerMount(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve the player entity ID being attached. + * @return The current Entity ID + */ + public int getVehicleId() { + return handle.getIntegers().read(0); + } + + /** + * Set the player entity ID being attached. + * @param value - new value. + */ + public void setVehicleId(int value) { + handle.getIntegers().write(0, value); + } + + /** + * Retrieve the IDs of the entities that will be destroyed. + * @return The current entities. + */ + public List getPassengers() { + return Ints.asList(handle.getIntegerArrays().read(0)); + } + + /** + * Set the entities that will be destroyed. + * @param value - new value. + */ + public void setPassengers(int[] entities) { + handle.getIntegerArrays().write(0, entities); + } + + /** + * Set the entities that will be destroyed. + * @param value - new value. + */ + public void setPassengers(List entities) { + setPassengers(Ints.toArray(entities)); + } +} \ No newline at end of file diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerSpawnEntity.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerSpawnEntity.java new file mode 100644 index 00000000..9b4887fe --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerSpawnEntity.java @@ -0,0 +1,148 @@ +/* + * PacketWrapper - Contains wrappers for each packet in Minecraft. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; +import org.bukkit.World; +import org.bukkit.entity.Entity; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.injector.PacketConstructor; +import com.comphenix.protocol.reflect.IntEnum; + +public class WrapperPlayServerSpawnEntity extends AbstractPacket { + public static final PacketType TYPE = PacketType.Play.Server.SPAWN_ENTITY; + + private static PacketConstructor entityConstructor; + + /** + * Represents the different object types. + * + * @author Kristian + */ + public static class ObjectTypes extends IntEnum { + public static final int BOAT = 1; + public static final int ITEM_STACK = 2; + public static final int MINECART = 10; + public static final int MINECART_STORAGE = 11; + public static final int MINECART_POWERED = 12; + public static final int ACTIVATED_TNT = 50; + public static final int ENDER_CRYSTAL = 51; + public static final int ARROW_PROJECTILE = 60; + public static final int SNOWBALL_PROJECTILE = 61; + public static final int EGG_PROJECTILE = 62; + public static final int FIRE_BALL_GHAST = 63; + public static final int FIRE_BALL_BLAZE = 64; + public static final int THROWN_ENDERPEARL = 65; + public static final int WITHER_SKULL = 66; + public static final int FALLING_BLOCK = 70; + public static final int ITEM_FRAME = 71; + public static final int EYE_OF_ENDER = 72; + public static final int THROWN_POTION = 73; + public static final int FALLING_DRAGON_EGG = 74; + public static final int THROWN_EXP_BOTTLE = 75; + public static final int FIREWORK = 76; + public static final int ARMOR_STAND = 78; + public static final int FISHING_FLOAT = 90; + + /** + * The singleton instance. Can also be retrieved from the parent class. + */ + private static ObjectTypes INSTANCE = new ObjectTypes(); + + /** + * Retrieve an instance of the object types enum. + * @return Object type enum. + */ + public static ObjectTypes getInstance() { + return INSTANCE; + } + } + + public WrapperPlayServerSpawnEntity() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerSpawnEntity(PacketContainer packet) { + super(packet, TYPE); + } + + public WrapperPlayServerSpawnEntity(Entity entity, int type, int objectData) { + super(fromEntity(entity, type, objectData), TYPE); + } + + // Useful constructor + private static PacketContainer fromEntity(Entity entity, int type, int objectData) { + if (entityConstructor == null) + entityConstructor = ProtocolLibrary.getProtocolManager().createPacketConstructor(TYPE, entity, type, objectData); + return entityConstructor.createPacket(entity, type, objectData); + } + + /** + * Retrieve entity ID of the Object. + * @return The current EID + */ + public int getEntityID() { + return handle.getIntegers().read(0); + } + + /** + * Retrieve the entity that will be spawned. + * @param world - the current world of the entity. + * @return The spawned entity. + */ + public Entity getEntity(World world) { + return handle.getEntityModifier(world).read(0); + } + + /** + * Retrieve the entity that will be spawned. + * @param event - the packet event. + * @return The spawned entity. + */ + public Entity getEntity(PacketEvent event) { + return getEntity(event.getPlayer().getWorld()); + } + + /** + * Set entity ID of the Object. + * @param value - new value. + */ + public void setEntityID(int value) { + handle.getIntegers().write(0, value); + } + + /** + * Retrieve the type of object. See {@link ObjectTypes} + * @return The current Type + */ + public int getType() { + return handle.getIntegers().read(6); + } + + /** + * Set the type of object. See {@link ObjectTypes}. + * @param value - new value. + */ + public void setType(int value) { + handle.getIntegers().write(6, value); + } + +} \ No newline at end of file diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerSpawnEntityLiving.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerSpawnEntityLiving.java new file mode 100644 index 00000000..2a9f30db --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/WrapperPlayServerSpawnEntityLiving.java @@ -0,0 +1,125 @@ +/* + * PacketWrapper - Contains wrappers for each packet in Minecraft. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; + +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.injector.PacketConstructor; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; + +public class WrapperPlayServerSpawnEntityLiving extends AbstractPacket { + public static final PacketType TYPE = PacketType.Play.Server.SPAWN_ENTITY_LIVING; + + private static PacketConstructor entityConstructor; + + public WrapperPlayServerSpawnEntityLiving() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerSpawnEntityLiving(PacketContainer packet) { + super(packet, TYPE); + } + + public WrapperPlayServerSpawnEntityLiving(Entity entity) { + super(fromEntity(entity), TYPE); + } + + // Useful constructor + private static PacketContainer fromEntity(Entity entity) { + if (entityConstructor == null) + entityConstructor = ProtocolLibrary.getProtocolManager().createPacketConstructor(TYPE, entity); + return entityConstructor.createPacket(entity); + } + + /** + * Retrieve entity ID. + * @return The current EID + */ + public int getEntityID() { + return handle.getIntegers().read(0); + } + + /** + * Retrieve the entity that will be spawned. + * @param world - the current world of the entity. + * @return The spawned entity. + */ + public Entity getEntity(World world) { + return handle.getEntityModifier(world).read(0); + } + + /** + * Retrieve the entity that will be spawned. + * @param event - the packet event. + * @return The spawned entity. + */ + public Entity getEntity(PacketEvent event) { + return getEntity(event.getPlayer().getWorld()); + } + + /** + * Set entity ID. + * @param value - new value. + */ + public void setEntityID(int value) { + handle.getIntegers().write(0, value); + } + + /** + * Retrieve the type of mob. + * @return The current Type + */ + @SuppressWarnings("deprecation") + public EntityType getType() { + return EntityType.fromId(handle.getIntegers().read(1)); + } + + /** + * Set the type of mob. + * @param value - new value. + */ + @SuppressWarnings("deprecation") + public void setType(EntityType value) { + handle.getIntegers().write(1, (int) value.getTypeId()); + } + + /** + * Retrieve the data watcher. + *

+ * Content varies by mob, see Entities. + * @return The current Metadata + */ + public WrappedDataWatcher getMetadata() { + return handle.getDataWatcherModifier().read(0); + } + + /** + * Set the data watcher. + * @param value - new value. + */ + public void setMetadata(WrappedDataWatcher value) { + handle.getDataWatcherModifier().write(0, value); + } +} \ No newline at end of file diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/AbstractPacket.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/AbstractPacket.java similarity index 96% rename from HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/AbstractPacket.java rename to HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/AbstractPacket.java index 5dd4aaa4..a3120592 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/AbstractPacket.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/AbstractPacket.java @@ -15,7 +15,7 @@ * 02111-1307 USA */ -package com.gmail.filoghost.holographicdisplays.bridge.protocollib; +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9; import java.lang.reflect.InvocationTargetException; diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/ProtocolLibHook.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/ProtocolLibHook.java similarity index 96% rename from HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/ProtocolLibHook.java rename to HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/ProtocolLibHook.java index c0fb38a9..f0b29723 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/ProtocolLibHook.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/ProtocolLibHook.java @@ -1,4 +1,4 @@ -package com.gmail.filoghost.holographicdisplays.bridge.protocollib; +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9; import java.util.List; @@ -17,7 +17,7 @@ import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.wrappers.WrappedDataWatcher; import com.comphenix.protocol.wrappers.WrappedWatchableObject; import com.gmail.filoghost.holographicdisplays.HolographicDisplays; -import com.gmail.filoghost.holographicdisplays.bridge.protocollib.WrapperPlayServerSpawnEntity.ObjectTypes; +import com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9.WrapperPlayServerSpawnEntity.ObjectTypes; import com.gmail.filoghost.holographicdisplays.nms.interfaces.NMSManager; import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSEntityBase; import com.gmail.filoghost.holographicdisplays.object.CraftHologram; @@ -236,7 +236,7 @@ public class ProtocolLibHook { itemPacket.sendPacket(player); AbstractPacket vehiclePacket; - if (HolographicDisplays.is1_8()) { + if (HolographicDisplays.is18orGreater()) { // In 1.8 we have armor stands, that are living entities. vehiclePacket = new WrapperPlayServerSpawnEntityLiving(itemLine.getNmsVehicle().getBukkitEntityNMS()); } else { @@ -272,7 +272,7 @@ public class ProtocolLibHook { if (touchSlime.isSpawned()) { AbstractPacket vehiclePacket; - if (HolographicDisplays.is1_8()) { + if (HolographicDisplays.is18orGreater()) { // Armor stand vehicle vehiclePacket = new WrapperPlayServerSpawnEntityLiving(touchSlime.getNmsVehicle().getBukkitEntityNMS()); } else { diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerAttachEntity.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerAttachEntity.java similarity index 96% rename from HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerAttachEntity.java rename to HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerAttachEntity.java index df3fff6a..6ba97f09 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerAttachEntity.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerAttachEntity.java @@ -15,7 +15,7 @@ * 02111-1307 USA */ -package com.gmail.filoghost.holographicdisplays.bridge.protocollib; +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9; import org.bukkit.World; import org.bukkit.entity.Entity; diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerEntityDestroy.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerEntityDestroy.java similarity index 96% rename from HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerEntityDestroy.java rename to HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerEntityDestroy.java index 82383eec..551cf773 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerEntityDestroy.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerEntityDestroy.java @@ -15,7 +15,7 @@ * 02111-1307 USA */ -package com.gmail.filoghost.holographicdisplays.bridge.protocollib; +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9; import java.util.List; diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerEntityMetadata.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerEntityMetadata.java similarity index 96% rename from HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerEntityMetadata.java rename to HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerEntityMetadata.java index e3eef964..46ce52bc 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerEntityMetadata.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerEntityMetadata.java @@ -15,7 +15,7 @@ * 02111-1307 USA */ -package com.gmail.filoghost.holographicdisplays.bridge.protocollib; +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9; import java.util.List; diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerSpawnEntity.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerSpawnEntity.java similarity index 96% rename from HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerSpawnEntity.java rename to HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerSpawnEntity.java index 9feae7ae..e99c3a98 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerSpawnEntity.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerSpawnEntity.java @@ -15,7 +15,7 @@ * 02111-1307 USA */ -package com.gmail.filoghost.holographicdisplays.bridge.protocollib; +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9; import org.bukkit.World; import org.bukkit.entity.Entity; diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerSpawnEntityLiving.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerSpawnEntityLiving.java similarity index 96% rename from HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerSpawnEntityLiving.java rename to HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerSpawnEntityLiving.java index c4df9b58..0d473218 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/WrapperPlayServerSpawnEntityLiving.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/bridge/protocollib/pre1_9/WrapperPlayServerSpawnEntityLiving.java @@ -15,7 +15,7 @@ * 02111-1307 USA */ -package com.gmail.filoghost.holographicdisplays.bridge.protocollib; +package com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9; import org.bukkit.World; import org.bukkit.entity.Entity; diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/commands/main/subs/FixCommand.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/commands/main/subs/FixCommand.java index 1f88f0bd..a22986b6 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/commands/main/subs/FixCommand.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/commands/main/subs/FixCommand.java @@ -37,7 +37,7 @@ public class FixCommand extends HologramSubCommand { @Override public void execute(CommandSender sender, String label, String[] args) throws CommandException { - CommandValidator.isTrue(!HolographicDisplays.is1_8(), "This command is no longer necessary in 1.8+. The holograms already use the correct ambient light."); + CommandValidator.isTrue(!HolographicDisplays.is18orGreater(), "This command is no longer necessary in 1.8+. The holograms already use the correct ambient light."); NamedHologram hologram = NamedHologramManager.getHologram(args[0].toLowerCase()); CommandValidator.notNull(hologram, Strings.noSuchHologram(args[0].toLowerCase())); @@ -70,7 +70,11 @@ public class FixCommand extends HologramSubCommand { @Override public SubCommandType getType() { - return SubCommandType.GENERIC; + if (HolographicDisplays.is18orGreater()) { + return SubCommandType.HIDDEN; + } else { + return SubCommandType.GENERIC; + } } } diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/listener/MainListener.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/listener/MainListener.java index 8cf78979..0fbbe84d 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/listener/MainListener.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/listener/MainListener.java @@ -95,16 +95,16 @@ public class MainListener implements Listener { public void onSlimeInteract(PlayerInteractEntityEvent event) { if (event.getRightClicked().getType() == EntityType.SLIME) { + Player clicker = event.getPlayer(); NMSEntityBase entityBase = nmsManager.getNMSEntityBase(event.getRightClicked()); - if (entityBase == null) return; - if (entityBase.getHologramLine() instanceof CraftTouchSlimeLine) { + if (entityBase != null && entityBase.getHologramLine() instanceof CraftTouchSlimeLine && !isSpectatorMode(clicker)) { CraftTouchSlimeLine touchSlime = (CraftTouchSlimeLine) entityBase.getHologramLine(); - if (touchSlime.getTouchablePiece().getTouchHandler() != null && touchSlime.getParent().getVisibilityManager().isVisibleTo(event.getPlayer())) { + if (touchSlime.getTouchablePiece().getTouchHandler() != null && touchSlime.getParent().getVisibilityManager().isVisibleTo(clicker)) { - Long lastClick = anticlickSpam.get(event.getPlayer()); + Long lastClick = anticlickSpam.get(clicker); if (lastClick != null && System.currentTimeMillis() - lastClick.longValue() < 100) { return; } @@ -117,11 +117,15 @@ public class MainListener implements Listener { Plugin plugin = touchSlime.getParent() instanceof PluginHologram ? ((PluginHologram) touchSlime.getParent()).getOwner() : HolographicDisplays.getInstance(); HolographicDisplays.getInstance().getLogger().log(Level.WARNING, "The plugin " + plugin.getName() + " generated an exception when the player " + event.getPlayer().getName() + " touched a hologram.", ex); } - } + } } } } + public static boolean isSpectatorMode(Player player) { + return player.getGameMode().toString().equals("SPECTATOR"); + } + public static void handleItemLinePickup(Player player, PickupHandler pickupHandler, CraftHologram hologram) { try { if (hologram.getVisibilityManager().isVisibleTo(player)) { diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/metrics/MetricsLite.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/metrics/MetricsLite.java index 4a6b7727..d7541ed4 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/metrics/MetricsLite.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/metrics/MetricsLite.java @@ -35,6 +35,8 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.scheduler.BukkitTask; +import com.gmail.filoghost.holographicdisplays.util.VersionUtils; + import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; @@ -277,7 +279,6 @@ public class MetricsLite { /** * Generic method that posts a plugin to the metrics website */ - @SuppressWarnings("deprecation") private void postPlugin(boolean isPing) throws IOException { // Server software specific section PluginDescriptionFile description = plugin.getDescription(); @@ -285,7 +286,7 @@ public class MetricsLite { boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled String pluginVersion = description.getVersion(); String serverVersion = Bukkit.getVersion(); - int playersOnline = Bukkit.getServer().getOnlinePlayers().length; + int playersOnline = VersionUtils.getOnlinePlayers().size(); // END server software specific section -- all code below does not use any code outside of this class / Java diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/CraftNMSArmorStand.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/CraftNMSArmorStand.java new file mode 100644 index 00000000..780d0a88 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/CraftNMSArmorStand.java @@ -0,0 +1,68 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import java.util.Collection; + +import org.bukkit.EntityEffect; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_9_R1.CraftServer; +import org.bukkit.craftbukkit.v1_9_R1.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) { } + @Override public void setMarker(boolean marker) { } + + // Methods from LivingEntity class + @Override public boolean addPotionEffect(PotionEffect effect) { return false; } + @Override public boolean addPotionEffect(PotionEffect effect, boolean param) { return false; } + @Override public boolean addPotionEffects(Collection 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_9_R1/CraftNMSItem.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/CraftNMSItem.java new file mode 100644 index 00000000..d921439a --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/CraftNMSItem.java @@ -0,0 +1,43 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import org.bukkit.EntityEffect; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_9_R1.CraftServer; +import org.bukkit.craftbukkit.v1_9_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 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_9_R1/CraftNMSSlime.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/CraftNMSSlime.java new file mode 100644 index 00000000..d2d2a0d5 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/CraftNMSSlime.java @@ -0,0 +1,50 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import java.util.Collection; + +import org.bukkit.EntityEffect; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_9_R1.CraftServer; +import org.bukkit.craftbukkit.v1_9_R1.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_9_R1/EntityNMSArmorStand.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/EntityNMSArmorStand.java new file mode 100644 index 00000000..7268da0d --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/EntityNMSArmorStand.java @@ -0,0 +1,236 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import net.minecraft.server.v1_9_R1.AxisAlignedBB; +import net.minecraft.server.v1_9_R1.DamageSource; +import net.minecraft.server.v1_9_R1.EntityArmorStand; +import net.minecraft.server.v1_9_R1.EntityHuman; +import net.minecraft.server.v1_9_R1.EntityPlayer; +import net.minecraft.server.v1_9_R1.EnumHand; +import net.minecraft.server.v1_9_R1.EnumInteractionResult; +import net.minecraft.server.v1_9_R1.EnumItemSlot; +import net.minecraft.server.v1_9_R1.ItemStack; +import net.minecraft.server.v1_9_R1.NBTTagCompound; +import net.minecraft.server.v1_9_R1.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_9_R1.SoundEffect; +import net.minecraft.server.v1_9_R1.Vec3D; +import net.minecraft.server.v1_9_R1.World; + +import org.bukkit.craftbukkit.v1_9_R1.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); + super.setInvisible(true); + super.setSmall(true); + super.setArms(false); + super.setGravity(true); + super.setBasePlate(true); + super.setMarker(true); + this.parentPiece = parentPiece; + try { + ReflectionUtils.setPrivateField(EntityArmorStand.class, this, "bz", 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 void f(NBTTagCompound nbttagcompound) { + // Do not load NBT. + } + + @Override + public void a(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(String customName) { + // Locks the custom name. + } + + @Override + public void setCustomNameVisible(boolean visible) { + // Locks the custom name. + } + + @Override + public EnumInteractionResult a(EntityHuman human, Vec3D vec3d, ItemStack itemstack, EnumHand enumhand) { + // Prevent stand being equipped + return EnumInteractionResult.PASS; + } + + @Override + public boolean c(int i, ItemStack item) { + // Prevent stand being equipped + return false; + } + + @Override + public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) { + // Prevent stand being equipped + } + + @Override + public void a(AxisAlignedBB boundingBox) { + // Do not change it! + } + + public void forceSetBoundingBox(AxisAlignedBB boundingBox) { + super.a(boundingBox); + } + + @Override + public int getId() { + + StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + if (elements.length > 2 && elements[2] != null && elements[2].getFileName().equals("EntityTrackerEntry.java") && elements[2].getLineNumber() > 142 && elements[2].getLineNumber() < 152) { + // Then this method is being called when creating a new packet, we return a fake ID! + return -1; + } + + return super.getId(); + } + + @Override + public void m() { + if (!lockTick) { + super.m(); + } + } + + @Override + public void a(SoundEffect soundeffect, float f, float f1) { + // 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() { + // Prevent being killed. + } + + @Override + public CraftEntity getBukkitEntity() { + if (super.bukkitEntity == null) { + super.bukkitEntity = new CraftNMSArmorStand(super.world.getServer(), this); + } + return super.bukkitEntity; + } + + @Override + public void killEntityNMS() { + super.dead = true; + } + + @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 : super.world.players) { + if (obj instanceof EntityPlayer) { + EntityPlayer nmsPlayer = (EntityPlayer) obj; + + double distanceSquared = Utils.square(nmsPlayer.locX - super.locX) + Utils.square(nmsPlayer.locZ - super.locZ); + if (distanceSquared < 8192 && nmsPlayer.playerConnection != null) { + nmsPlayer.playerConnection.sendPacket(teleportPacket); + } + } + } + } + + @Override + public boolean isDeadNMS() { + return super.dead; + } + + @Override + public int getIdNMS() { + return super.getId(); // Return the real ID without checking the stack trace. + } + + @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_9_R1/EntityNMSItem.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/EntityNMSItem.java new file mode 100644 index 00000000..ac2aea51 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/EntityNMSItem.java @@ -0,0 +1,261 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import net.minecraft.server.v1_9_R1.Entity; +import net.minecraft.server.v1_9_R1.Blocks; +import net.minecraft.server.v1_9_R1.DamageSource; +import net.minecraft.server.v1_9_R1.EntityHuman; +import net.minecraft.server.v1_9_R1.EntityItem; +import net.minecraft.server.v1_9_R1.EntityPlayer; +import net.minecraft.server.v1_9_R1.ItemStack; +import net.minecraft.server.v1_9_R1.NBTTagCompound; +import net.minecraft.server.v1_9_R1.NBTTagList; +import net.minecraft.server.v1_9_R1.NBTTagString; +import net.minecraft.server.v1_9_R1.PacketPlayOutMount; +import net.minecraft.server.v1_9_R1.World; + +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_9_R1.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; +import com.gmail.filoghost.holographicdisplays.util.Utils; + +public class EntityNMSItem extends EntityItem implements NMSItem { + + private boolean lockTick; + private CraftItemLine parentPiece; + + private int resendMountPacketTicks; + + public EntityNMSItem(World world, CraftItemLine piece) { + super(world); + super.pickupDelay = Integer.MAX_VALUE; + this.parentPiece = piece; + } + + @Override + public void m() { + + // So it won't get removed. + ticksLived = 0; + + if (resendMountPacketTicks++ > 20) { + resendMountPacketTicks = 0; + + if (by() != null) { + // Send a packet near to "remind" players that the item is riding the armor stand (Spigot bug or client bug) + PacketPlayOutMount mountPacket = new PacketPlayOutMount(by()); + + for (Object obj : super.world.players) { + if (obj instanceof EntityPlayer) { + EntityPlayer nmsPlayer = (EntityPlayer) obj; + + double distanceSquared = Utils.square(nmsPlayer.locX - super.locX) + Utils.square(nmsPlayer.locZ - super.locZ); + if (distanceSquared < 1024 && nmsPlayer.playerConnection != null) { + nmsPlayer.playerConnection.sendPacket(mountPacket); + } + } + } + } + } + + if (!lockTick) { + super.m(); + } + } + + @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 < 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) { + 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 void f(NBTTagCompound nbttagcompound) { + // Do not load NBT. + } + + @Override + public void a(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 inactiveTick() { + // Check inactive ticks. + + if (!lockTick) { + super.inactiveTick(); + } + } + + @Override + public void setLockTick(boolean lock) { + lockTick = lock; + } + + @Override + public void die() { + // Prevent being killed. + } + + @Override + public CraftEntity getBukkitEntity() { + if (super.bukkitEntity == null) { + super.bukkitEntity = new CraftNMSItem(super.world.getServer(), this); + } + return super.bukkitEntity; + } + + @Override + public boolean isDeadNMS() { + return super.dead; + } + + @Override + public void killEntityNMS() { + super.dead = true; + } + + @Override + public void setLocationNMS(double x, double y, double z) { + super.setPosition(x, y, z); + } + + @Override + public void setItemStackNMS(org.bukkit.inventory.ItemStack stack) { + ItemStack newItem = CraftItemStack.asNMSCopy(stack); + + 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 super.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 { + if (super.by() != null) { + Entity oldVehicle = super.by(); + ReflectionUtils.setPrivateField(Entity.class, this, "as", null); + oldVehicle.passengers.remove(this); + } + + ReflectionUtils.setPrivateField(Entity.class, this, "as", entity); + entity.passengers.clear(); + entity.passengers.add(this); + + } catch (Exception ex) { + DebugHandler.handleDebugException(ex); + } + } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/EntityNMSSlime.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/EntityNMSSlime.java new file mode 100644 index 00000000..ff48bd3b --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/EntityNMSSlime.java @@ -0,0 +1,228 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import net.minecraft.server.v1_9_R1.EntityDamageSource; +import net.minecraft.server.v1_9_R1.EntityPlayer; +import net.minecraft.server.v1_9_R1.AxisAlignedBB; +import net.minecraft.server.v1_9_R1.DamageSource; +import net.minecraft.server.v1_9_R1.Entity; +import net.minecraft.server.v1_9_R1.EntitySlime; +import net.minecraft.server.v1_9_R1.NBTTagCompound; +import net.minecraft.server.v1_9_R1.PacketPlayOutMount; +import net.minecraft.server.v1_9_R1.SoundEffect; +import net.minecraft.server.v1_9_R1.World; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_9_R1.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; +import com.gmail.filoghost.holographicdisplays.util.Utils; + +public class EntityNMSSlime extends EntitySlime implements NMSSlime { + + private boolean lockTick; + private CraftTouchSlimeLine parentPiece; + + private int resendMountPacketTicks; + + 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 m() { + + // So it won't get removed. + ticksLived = 0; + + if (resendMountPacketTicks++ > 20) { + resendMountPacketTicks = 0; + + if (by() != null) { + // Send a packet near to "remind" players that the slime is riding the armor stand (Spigot bug or client bug) + PacketPlayOutMount mountPacket = new PacketPlayOutMount(by()); + + for (Object obj : super.world.players) { + if (obj instanceof EntityPlayer) { + EntityPlayer nmsPlayer = (EntityPlayer) obj; + + double distanceSquared = Utils.square(nmsPlayer.locX - super.locX) + Utils.square(nmsPlayer.locZ - super.locZ); + if (distanceSquared < 1024 && nmsPlayer.playerConnection != null) { + nmsPlayer.playerConnection.sendPacket(mountPacket); + } + } + } + } + } + + if (!lockTick) { + super.m(); + } + } + + @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 void f(NBTTagCompound nbttagcompound) { + // Do not load NBT. + } + + @Override + public void a(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(String customName) { + // Locks the custom name. + } + + @Override + public void setCustomNameVisible(boolean visible) { + // Locks the custom name. + } + + @Override + public void a(SoundEffect soundeffect, float f, float f1) { + // Remove sounds. + } + + @Override + public void setLockTick(boolean lock) { + lockTick = lock; + } + + @Override + public void die() { + // Prevent being killed. + } + + @Override + public CraftEntity getBukkitEntity() { + if (super.bukkitEntity == null) { + super.bukkitEntity = new CraftNMSSlime(super.world.getServer(), this); + } + return super.bukkitEntity; + } + + @Override + public boolean isDeadNMS() { + return super.dead; + } + + @Override + public void killEntityNMS() { + super.dead = true; + } + + @Override + public void setLocationNMS(double x, double y, double z) { + super.setPosition(x, y, z); + } + + @Override + public int getIdNMS() { + return super.getId(); + } + + @Override + public 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 { + if (super.by() != null) { + Entity oldVehicle = super.by(); + ReflectionUtils.setPrivateField(Entity.class, this, "as", null); + oldVehicle.passengers.remove(this); + } + + ReflectionUtils.setPrivateField(Entity.class, this, "as", entity); + entity.passengers.clear(); + entity.passengers.add(this); + + } catch (Exception ex) { + DebugHandler.handleDebugException(ex); + } + } +} diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/FancyMessageImpl.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/FancyMessageImpl.java new file mode 100644 index 00000000..c582248f --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/FancyMessageImpl.java @@ -0,0 +1,170 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.server.v1_9_R1.IChatBaseComponent; +import net.minecraft.server.v1_9_R1.PacketPlayOutChat; + +import org.bukkit.ChatColor; + +import com.google.gson.stream.JsonWriter; + +import org.bukkit.craftbukkit.v1_9_R1.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_9_R1/NmsManagerImpl.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/NmsManagerImpl.java new file mode 100644 index 00000000..86727269 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/NmsManagerImpl.java @@ -0,0 +1,152 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import java.lang.reflect.Method; + +import net.minecraft.server.v1_9_R1.Entity; +import net.minecraft.server.v1_9_R1.EntityTypes; +import net.minecraft.server.v1_9_R1.MathHelper; +import net.minecraft.server.v1_9_R1.World; +import net.minecraft.server.v1_9_R1.WorldServer; + +import org.apache.commons.lang.NotImplementedException; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_9_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; +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); + + validateEntityMethod = World.class.getDeclaredMethod("b", 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. + throw new UnsupportedOperationException("MCPC, Cauldron and similar softwares are not supported"); + } 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"); + + final int chunkX = MathHelper.floor(nmsEntity.locX / 16.0); + final int chunkZ = MathHelper.floor(nmsEntity.locZ / 16.0); + + if (!nmsWorld.getChunkProviderServer().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_9_R1/NullBoundingBox.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/NullBoundingBox.java new file mode 100644 index 00000000..f15da196 --- /dev/null +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/nms/v1_9_R1/NullBoundingBox.java @@ -0,0 +1,111 @@ +package com.gmail.filoghost.holographicdisplays.nms.v1_9_R1; + +import net.minecraft.server.v1_9_R1.AxisAlignedBB; +import net.minecraft.server.v1_9_R1.BlockPosition; +import net.minecraft.server.v1_9_R1.MovingObjectPosition; +import net.minecraft.server.v1_9_R1.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) { + 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 boolean b(Vec3D arg0) { + return false; + } + + @Override + public boolean c(Vec3D arg0) { + return false; + } + + @Override + public boolean d(Vec3D arg0) { + return false; + } + + @Override + public AxisAlignedBB e(double arg0) { + return this; + } + + @Override + public AxisAlignedBB g(double arg0) { + return this; + } + + + +} \ No newline at end of file diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/CraftVisibilityManager.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/CraftVisibilityManager.java index 514b60dd..01c9ee1c 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/CraftVisibilityManager.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/CraftVisibilityManager.java @@ -10,8 +10,9 @@ import org.bukkit.entity.Player; import com.gmail.filoghost.holographicdisplays.HolographicDisplays; import com.gmail.filoghost.holographicdisplays.api.VisibilityManager; -import com.gmail.filoghost.holographicdisplays.bridge.protocollib.ProtocolLibHook; +import com.gmail.filoghost.holographicdisplays.bridge.protocollib.pre1_9.ProtocolLibHook; import com.gmail.filoghost.holographicdisplays.util.Validator; +import com.gmail.filoghost.holographicdisplays.util.VersionUtils; public class CraftVisibilityManager implements VisibilityManager { @@ -32,7 +33,6 @@ public class CraftVisibilityManager implements VisibilityManager { return visibleByDefault; } - @SuppressWarnings("deprecation") @Override public void setVisibleByDefault(boolean visibleByDefault) { if (this.visibleByDefault != visibleByDefault) { @@ -40,7 +40,7 @@ public class CraftVisibilityManager implements VisibilityManager { boolean oldVisibleByDefault = this.visibleByDefault; this.visibleByDefault = visibleByDefault; - for (Player player : Bukkit.getOnlinePlayers()) { + for (Player player : VersionUtils.getOnlinePlayers()) { if (playersVisibilityMap != null && playersVisibilityMap.containsKey(player.getName().toLowerCase())) { // Has a specific value set diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftItemLine.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftItemLine.java index 3f6d2c67..28185cb3 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftItemLine.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftItemLine.java @@ -61,10 +61,12 @@ public class CraftItemLine extends CraftTouchableLine implements ItemLine { Location loc = nmsItem.getBukkitEntityNMS().getLocation(); - if (HolographicDisplays.is1_8()) { - super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - Offsets.ARMOR_STAND_WITH_ITEM, loc.getZ()); + if (HolographicDisplays.is19orGreater()) { + super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - getItemOffset(), loc.getZ()); + } else if (HolographicDisplays.is18orGreater()) { + super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - getItemOffset(), loc.getZ()); } else { - super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - Offsets.WITHER_SKULL_WITH_ITEM, loc.getZ()); + super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - getItemOffset(), loc.getZ()); } } else { @@ -78,11 +80,11 @@ public class CraftItemLine extends CraftTouchableLine implements ItemLine { if (itemStack != null && itemStack.getType() != Material.AIR) { - double offset = HolographicDisplays.is1_8() ? Offsets.ARMOR_STAND_WITH_ITEM : Offsets.WITHER_SKULL_WITH_ITEM; + double offset = getItemOffset(); nmsItem = HolographicDisplays.getNMSManager().spawnNMSItem(world, x, y + offset, z, this, itemStack); - if (HolographicDisplays.is1_8()) { + if (HolographicDisplays.is18orGreater()) { nmsVehicle = HolographicDisplays.getNMSManager().spawnNMSArmorStand(world, x, y + offset, z, this); } else { nmsVehicle = HolographicDisplays.getNMSManager().spawnNMSWitherSkull(world, x, y + offset, z, this); @@ -115,7 +117,7 @@ public class CraftItemLine extends CraftTouchableLine implements ItemLine { public void teleport(double x, double y, double z) { super.teleport(x, y, z); - double offset = HolographicDisplays.is1_8() ? Offsets.ARMOR_STAND_WITH_ITEM : Offsets.WITHER_SKULL_WITH_ITEM; + double offset = getItemOffset(); if (nmsVehicle != null) { nmsVehicle.setLocationNMS(x, y + offset, z); @@ -146,6 +148,16 @@ public class CraftItemLine extends CraftTouchableLine implements ItemLine { public NMSEntityBase getNmsVehicle() { return nmsVehicle; } + + private double getItemOffset() { + if (HolographicDisplays.is19orGreater()) { + return Offsets.ARMOR_STAND_WITH_ITEM_1_9; + } else if (HolographicDisplays.is18orGreater()) { + return Offsets.ARMOR_STAND_WITH_ITEM; + } else { + return Offsets.WITHER_SKULL_WITH_ITEM; + } + } @Override public String toString() { diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java index f7f91df3..6a84b7c1 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java @@ -59,12 +59,7 @@ public class CraftTextLine extends CraftTouchableLine implements TextLine { if (nmsNameble != null) { Location loc = nmsNameble.getBukkitEntityNMS().getLocation(); - - if (HolographicDisplays.is1_8()) { - super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - Offsets.ARMOR_STAND_ALONE, loc.getZ()); - } else { - super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - Offsets.WITHER_SKULL_WITH_HORSE, loc.getZ()); - } + super.setTouchHandler(touchHandler, loc.getWorld(), loc.getX(), loc.getY() - getTextOffset(), loc.getZ()); } else { super.setTouchHandler(touchHandler, null, 0, 0, 0); @@ -75,8 +70,8 @@ public class CraftTextLine extends CraftTouchableLine implements TextLine { public void spawn(World world, double x, double y, double z) { super.spawn(world, x, y, z); - if (HolographicDisplays.is1_8()) { - nmsNameble = HolographicDisplays.getNMSManager().spawnNMSArmorStand(world, x, y + Offsets.ARMOR_STAND_ALONE, z, this); + if (HolographicDisplays.is18orGreater()) { + nmsNameble = HolographicDisplays.getNMSManager().spawnNMSArmorStand(world, x, y + getTextOffset(), z, this); } else { nmsNameble = HolographicDisplays.getNMSManager().spawnNMSHorse(world, x, y + Offsets.WITHER_SKULL_WITH_HORSE, z, this); nmsSkullVehicle = HolographicDisplays.getNMSManager().spawnNMSWitherSkull(world, x, y + Offsets.WITHER_SKULL_WITH_HORSE, z, this); @@ -119,7 +114,7 @@ public class CraftTextLine extends CraftTouchableLine implements TextLine { } if (nmsNameble != null) { - nmsNameble.setLocationNMS(x, y + (HolographicDisplays.is1_8() ? Offsets.ARMOR_STAND_ALONE : Offsets.WITHER_SKULL_WITH_HORSE), z); + nmsNameble.setLocationNMS(x, y + getTextOffset(), z); } } @@ -152,6 +147,15 @@ public class CraftTextLine extends CraftTouchableLine implements TextLine { return nmsSkullVehicle; } + private double getTextOffset() { + if (HolographicDisplays.is19orGreater()) { + return Offsets.ARMOR_STAND_ALONE_1_9; + } else if (HolographicDisplays.is18orGreater()) { + return Offsets.ARMOR_STAND_ALONE; + } else { + return Offsets.WITHER_SKULL_WITH_HORSE; + } + } @Override public String toString() { diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTouchSlimeLine.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTouchSlimeLine.java index 3597e98c..a14ee26c 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTouchSlimeLine.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/object/line/CraftTouchSlimeLine.java @@ -34,11 +34,11 @@ public class CraftTouchSlimeLine extends CraftHologramLine { public void spawn(World world, double x, double y, double z) { super.spawn(world, x, y, z); - double offset = HolographicDisplays.is1_8() ? Offsets.ARMOR_STAND_WITH_SLIME : Offsets.WITHER_SKULL_WITH_SLIME; + double offset = getSlimeOffset(); nmsSlime = HolographicDisplays.getNMSManager().spawnNMSSlime(world, x, y + offset, z, this); - if (HolographicDisplays.is1_8()) { + if (HolographicDisplays.is18orGreater()) { nmsVehicle = HolographicDisplays.getNMSManager().spawnNMSArmorStand(world, x, y + offset, z, this); } else { nmsVehicle = HolographicDisplays.getNMSManager().spawnNMSWitherSkull(world, x, y + offset, z, this); @@ -70,7 +70,7 @@ public class CraftTouchSlimeLine extends CraftHologramLine { @Override public void teleport(double x, double y, double z) { - double offset = HolographicDisplays.is1_8() ? Offsets.ARMOR_STAND_WITH_SLIME : Offsets.WITHER_SKULL_WITH_SLIME; + double offset = getSlimeOffset(); if (nmsVehicle != null) { nmsVehicle.setLocationNMS(x, y + offset, z); @@ -97,6 +97,16 @@ public class CraftTouchSlimeLine extends CraftHologramLine { public NMSEntityBase getNmsVehicle() { return nmsVehicle; } + + private double getSlimeOffset() { + if (HolographicDisplays.is19orGreater()) { + return Offsets.ARMOR_STAND_WITH_SLIME_1_9; + } else if (HolographicDisplays.is18orGreater()) { + return Offsets.ARMOR_STAND_WITH_SLIME; + } else { + return Offsets.WITHER_SKULL_WITH_SLIME; + } + } @Override public String toString() { diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/placeholder/PlaceholdersRegister.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/placeholder/PlaceholdersRegister.java index d9113b08..557263aa 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/placeholder/PlaceholdersRegister.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/placeholder/PlaceholdersRegister.java @@ -12,6 +12,7 @@ import com.gmail.filoghost.holographicdisplays.HolographicDisplays; import com.gmail.filoghost.holographicdisplays.api.placeholder.PlaceholderReplacer; import com.gmail.filoghost.holographicdisplays.disk.Configuration; import com.gmail.filoghost.holographicdisplays.util.Utils; +import com.gmail.filoghost.holographicdisplays.util.VersionUtils; public class PlaceholdersRegister { @@ -22,10 +23,9 @@ public class PlaceholdersRegister { register(new Placeholder(HolographicDisplays.getInstance(), "{online}", 1.0, new PlaceholderReplacer() { - @SuppressWarnings("deprecation") @Override public String update() { - return String.valueOf(Bukkit.getOnlinePlayers().length); + return String.valueOf(VersionUtils.getOnlinePlayers().size()); } })); diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/Offsets.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/Offsets.java index 2df7cbcd..7fcc5a2a 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/Offsets.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/Offsets.java @@ -18,6 +18,16 @@ public class Offsets { ARMOR_STAND_WITH_ITEM = -1.48, // For 1.8+, an armor stand holding a slime. - ARMOR_STAND_WITH_SLIME = -1.49; + ARMOR_STAND_WITH_SLIME = -1.49, + + + // For 1.9+, a single armor stand. As with wither skulls and horses, the bottom part of the nametag should be on the surface of the block. + ARMOR_STAND_ALONE_1_9 = -0.29, + + // For 1.9+, an armor stand holding an item. + ARMOR_STAND_WITH_ITEM_1_9 = -0.0, + + // For 1.9+, an armor stand holding a slime. + ARMOR_STAND_WITH_SLIME_1_9 = -0.01; } diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/ReflectionUtils.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/ReflectionUtils.java index 4d3ddb92..bf2c6c1b 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/ReflectionUtils.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/ReflectionUtils.java @@ -18,4 +18,10 @@ public class ReflectionUtils { field.setAccessible(true); field.set(handle, value); } + + public static Object getPrivateField(Class clazz, Object handle, String fieldName) throws Exception { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(handle); + } } diff --git a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/VersionUtils.java b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/VersionUtils.java index 6f9e41fa..99147d9c 100644 --- a/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/VersionUtils.java +++ b/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/VersionUtils.java @@ -1,15 +1,22 @@ package com.gmail.filoghost.holographicdisplays.util; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bukkit.Bukkit; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import com.gmail.filoghost.holographicdisplays.HolographicDisplays; +import com.google.common.collect.ImmutableList; public class VersionUtils { + private static Method oldGetOnlinePlayersMethod; + /** * This method uses a regex to get the NMS package part that changes with every update. * Example: v1_8_R1 @@ -47,10 +54,29 @@ public class VersionUtils { } public static boolean isArmorstand(EntityType type) { - if (!HolographicDisplays.is1_8()) { + if (!HolographicDisplays.is18orGreater()) { return false; } return type == EntityType.ARMOR_STAND; } + + + public static Collection getOnlinePlayers() { + if (HolographicDisplays.is18orGreater()) { + return Bukkit.getOnlinePlayers(); + } else { + try { + if (oldGetOnlinePlayersMethod == null) { + oldGetOnlinePlayersMethod = Bukkit.class.getDeclaredMethod("getOnlinePlayers"); + } + + Player[] playersArray = (Player[]) oldGetOnlinePlayersMethod.invoke(null); + return ImmutableList.copyOf(playersArray); + } catch (Exception e) { + e.printStackTrace(); + return Collections.emptyList(); + } + } + } } diff --git a/HolographicDisplays/plugin.yml b/HolographicDisplays/plugin.yml index 15e5bbdc..3623ec1a 100644 --- a/HolographicDisplays/plugin.yml +++ b/HolographicDisplays/plugin.yml @@ -1,6 +1,6 @@ name: HolographicDisplays main: com.gmail.filoghost.holographicdisplays.HolographicDisplays -version: 2.1.10 +version: 2.1.11 softdepend: [Multiverse-Core, MultiWorld, My Worlds, My_Worlds, ProtocolLib] diff --git a/README.md b/README.md index 56863156..5273923b 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,4 @@ HolographicDisplays Bukkit Dev Page: http://dev.bukkit.org/bukkit-plugins/holographic-displays -API tutorial: https://github.com/filoghost/HolographicDisplays/wiki - -Old source (deprecated): https://github.com/filoghost/HolographicDisplays/tree/1.x \ No newline at end of file +API tutorial: https://github.com/filoghost/HolographicDisplays/wiki \ No newline at end of file