Last active
November 18, 2016 00:02
-
-
Save MrPowerGamerBR/fab8698da506d9e6f338ce88346f04fb to your computer and use it in GitHub Desktop.
RetroHolograms - A quick and simple Hologram API for Spigot 1.7.10 Protocol Hack (supports 1.7 and 1.8)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.mrpowergamerbr.sparklycore.utils.hologram; | |
| import java.lang.ref.WeakReference; | |
| import java.lang.reflect.Field; | |
| import java.util.Arrays; | |
| import java.util.List; | |
| import org.bukkit.Bukkit; | |
| import org.bukkit.Location; | |
| import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; | |
| import org.bukkit.entity.EntityType; | |
| import org.bukkit.entity.Player; | |
| import com.comphenix.protocol.wrappers.WrappedDataWatcher; | |
| import com.comphenix.protocol.wrappers.WrappedWatchableObject; | |
| import com.mrpowergamerbr.packetwrapper.AbstractPacket; | |
| import com.mrpowergamerbr.packetwrapper.WrapperPlayServerAttachEntity; | |
| import com.mrpowergamerbr.packetwrapper.WrapperPlayServerEntityDestroy; | |
| import com.mrpowergamerbr.packetwrapper.WrapperPlayServerEntityMetadata; | |
| import com.mrpowergamerbr.packetwrapper.WrapperPlayServerEntityTeleport; | |
| import com.mrpowergamerbr.packetwrapper.WrapperPlayServerSpawnEntity; | |
| import com.mrpowergamerbr.packetwrapper.WrapperPlayServerSpawnEntityLiving; | |
| import lombok.*; | |
| import me.mrpowergamerbr.sparklycore.utils.collections.WeakArrayList; | |
| /** | |
| * Class to spawn holograms in 1.7.10 Protocol Hack | |
| * @author Leonardo | |
| * | |
| */ | |
| public class Hologram { | |
| int horseId = 0; // Also used as the Armor Stand ID | |
| int witherSkullId = 0; | |
| String line; | |
| @Getter | |
| Location location; | |
| @Getter | |
| @Setter | |
| WeakArrayList<Player> viewers = new WeakArrayList<Player>(); | |
| @Getter | |
| @Setter | |
| ViewHandler vh; | |
| public Hologram(Location location, String line) { | |
| this.location = location; | |
| this.line = line; | |
| horseId = getId(); | |
| witherSkullId = getId(); | |
| } | |
| public void setViewHandler(ViewHandler vh) { | |
| this.vh = vh; | |
| } | |
| private static int getId() { | |
| try { | |
| Field field = Class.forName( | |
| "net.minecraft.server." + Bukkit.getServer().getClass().getName().split("\\.")[3] + ".Entity") | |
| .getDeclaredField("entityCount"); | |
| field.setAccessible(true); | |
| int id = field.getInt(null); | |
| field.set(null, id + 1); | |
| return id; | |
| } catch (Exception ex) { | |
| ex.printStackTrace(); | |
| } | |
| return -1; | |
| } | |
| public void setLine(String line) { | |
| this.line = line; | |
| for (WeakReference<Player> p : viewers.getItems()) { | |
| if (p.get() != null) { | |
| CraftPlayer craftPlayer = (CraftPlayer) p.get(); | |
| int protocol = craftPlayer.getHandle().playerConnection.networkManager.getVersion(); | |
| List<AbstractPacket> packets = null; | |
| if (protocol >= 47) { | |
| packets = generateMetadataPackets18(p.get()); | |
| } else { | |
| packets = generateMetadataPackets17(p.get()); | |
| } | |
| for (AbstractPacket packet : packets) { | |
| packet.sendPacket(p.get()); | |
| } | |
| } | |
| } | |
| } | |
| public String getLineForPlayer(Player p) { | |
| if (vh != null) { | |
| return vh.onView(this, p, line); | |
| } | |
| return line; | |
| } | |
| private List<AbstractPacket> generateMetadataPackets17(Player p) { | |
| WrapperPlayServerEntityMetadata metadata = new WrapperPlayServerEntityMetadata(); | |
| metadata.setEntityId(horseId); | |
| WrappedWatchableObject wwo = new WrappedWatchableObject(10, getLineForPlayer(p)); | |
| metadata.setEntityMetadata(Arrays.asList(wwo)); | |
| return Arrays.asList(metadata); | |
| } | |
| private List<AbstractPacket> generateMetadataPackets18(Player p) { | |
| WrapperPlayServerEntityMetadata metadata = new WrapperPlayServerEntityMetadata(); | |
| metadata.setEntityId(horseId); | |
| WrappedWatchableObject wwo = new WrappedWatchableObject(2, getLineForPlayer(p)); | |
| metadata.setEntityMetadata(Arrays.asList(wwo)); | |
| return Arrays.asList(metadata); | |
| } | |
| public void addEveryoneAsViewer() { | |
| for (Player p : Bukkit.getOnlinePlayers()) { | |
| viewers.add(p); | |
| } | |
| } | |
| public void addViewer(Player p) { | |
| viewers.add(p); | |
| spawnForPlayer(p); | |
| } | |
| public void removeViewer(Player p) { | |
| viewers.remove(p); | |
| despawnForPlayer(p); | |
| } | |
| public void spawnForAll() { | |
| if (line == null) { | |
| throw new RuntimeException("Line is null!"); | |
| } | |
| for (WeakReference<Player> p : viewers.getItems()) { | |
| if (p.get() != null) { | |
| spawnForPlayer(p.get()); | |
| } | |
| } | |
| } | |
| public void spawnForPlayer(Player p) { | |
| if (!p.getLocation().getWorld().equals(location.getWorld())) { | |
| return; | |
| } | |
| CraftPlayer craftPlayer = (CraftPlayer) p; | |
| int protocol = craftPlayer.getHandle().playerConnection.networkManager.getVersion(); | |
| List<AbstractPacket> packets = null; | |
| if (protocol >= 47) { | |
| packets = generateSpawnPackets18(p); | |
| } else { | |
| packets = generateSpawnPackets17(p); | |
| } | |
| for (AbstractPacket packet : packets) { | |
| packet.sendPacket(p); | |
| } | |
| } | |
| private List<AbstractPacket> generateSpawnPackets17(Player p) { | |
| // Create the wither skull packet first | |
| WrapperPlayServerSpawnEntity skull = new WrapperPlayServerSpawnEntity(); | |
| skull.setEntityID(witherSkullId); | |
| skull.setX(location.getX()); | |
| skull.setY(location.getY() + 56.28); | |
| skull.setZ(location.getZ()); | |
| skull.setType(66); // Wither skull type | |
| // Now the horse packet | |
| WrapperPlayServerSpawnEntityLiving horse = new WrapperPlayServerSpawnEntityLiving(); | |
| horse.setEntityID(horseId); | |
| horse.setType(EntityType.HORSE); | |
| horse.setX(location.getX()); | |
| horse.setY(location.getY()); | |
| horse.setZ(location.getZ()); | |
| WrappedDataWatcher wdw = new WrappedDataWatcher(); // Create the data watcher | |
| wdw.setObject(10, line); // And set the horse name to the hologram text | |
| wdw.setObject(11, (byte) 1); // Always show nametag | |
| wdw.setObject(12, -1700000); | |
| horse.setMetadata(wdw); | |
| // And, finally, the mount | |
| WrapperPlayServerAttachEntity attach = new WrapperPlayServerAttachEntity(); | |
| attach.setVehicleId(witherSkullId); | |
| attach.setEntityId(horseId); | |
| List<AbstractPacket> packets = Arrays.asList(skull, horse, attach); | |
| return packets; | |
| } | |
| private List<AbstractPacket> generateSpawnPackets18(Player p) { | |
| // Because Armor Stand is a living entity... | |
| WrapperPlayServerSpawnEntityLivingWorkaround armorStand = new WrapperPlayServerSpawnEntityLivingWorkaround(); | |
| armorStand.setEntityID(horseId); | |
| armorStand.setX(location.getX()); | |
| armorStand.setY(location.getY() + 1.52); | |
| armorStand.setZ(location.getZ()); | |
| armorStand.setType(30); // Armor Stand ID | |
| WrappedDataWatcher wdw = new WrappedDataWatcher(); // Create the data watcher | |
| wdw.setObject(0, (byte) 0x20); // Invisible | |
| wdw.setObject(2, line); // And set the armor stand name to the hologram text | |
| wdw.setObject(3, (byte) 1); // Always show nametag | |
| wdw.setObject(10, (byte) 0x16); // Zero Bounding Box (Marker) | |
| armorStand.setMetadata(wdw); | |
| List<AbstractPacket> packets = Arrays.asList(armorStand); | |
| return packets; | |
| } | |
| public void despawnForPlayer(Player p) { | |
| WrapperPlayServerEntityDestroy remove = new WrapperPlayServerEntityDestroy(); | |
| remove.setEntities(new int[] { horseId }); // Do we need to add the witherSkullId too? | |
| remove.sendPacket(p); | |
| } | |
| public void despawnForAll() { | |
| WrapperPlayServerEntityDestroy remove = new WrapperPlayServerEntityDestroy(); | |
| remove.setEntities(new int[] { horseId }); // Do we need to add the witherSkullId too? | |
| for (WeakReference<Player> p : viewers.getItems()) { | |
| if (p.get() != null) { | |
| remove.sendPacket(p.get()); | |
| } | |
| } | |
| } | |
| public void teleport(Location l) { | |
| for (WeakReference<Player> p : viewers.getItems()) { | |
| if (p.get() != null) { | |
| teleport(p.get(), l); | |
| } | |
| } | |
| } | |
| public void teleport(Player p, Location l) { | |
| this.location = l; | |
| CraftPlayer craftPlayer = (CraftPlayer) p; | |
| int protocol = craftPlayer.getHandle().playerConnection.networkManager.getVersion(); | |
| WrapperPlayServerEntityTeleport teleport = new WrapperPlayServerEntityTeleport(); | |
| teleport.setEntityID(protocol >= 47 ? horseId : witherSkullId); | |
| teleport.setX(l.getX()); | |
| teleport.setY(l.getY() + (protocol >= 47 ? 1.42 : 56.28)); | |
| teleport.setZ(l.getZ()); | |
| teleport.sendPacket(p); | |
| } | |
| public Hologram addLineBelow(String line) { | |
| Hologram hologram = new Hologram(getLocation().clone().add(0, -0.285, 0), line); | |
| return hologram; | |
| } | |
| public Hologram addLineAbove(String line) { | |
| Hologram hologram = new Hologram(getLocation().clone().add(0, 0.285, 0), line); | |
| return hologram; | |
| } | |
| } | |
| class ViewHandler { | |
| public String onView(Hologram hologram, Player player, String string) { | |
| return string; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment