Skip to content

Instantly share code, notes, and snippets.

@MrPowerGamerBR
Last active April 8, 2021 23:01
Show Gist options
  • Save MrPowerGamerBR/4aad85fa20df17b5a016933937d68bb2 to your computer and use it in GitHub Desktop.
Save MrPowerGamerBR/4aad85fa20df17b5a016933937d68bb2 to your computer and use it in GitHub Desktop.
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.entity.Entity;
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.WrapperPlayServerSpawnEntityLiving;
import lombok.*;
import me.mrpowergamerbr.sparklycore.utils.collections.WeakArrayList;
/**
* Class to spawn holograms in 1.8
* @author Leonardo
*
*/
public class Hologram {
int horseId = 0; // Also used as the Armor Stand ID
String line;
@Getter
Location location;
@Getter
@Setter
WeakArrayList<Player> viewers = new WeakArrayList<Player>();
@Getter
@Setter
ViewHandler vh;
static WrappedDataWatcher wdw = null; // This is static because we don't need to regenerate this every time
static {
wdw.setObject(0, (byte) 0x20); // Invisible
wdw.setObject(3, (byte) 1); // Always show nametag
int bitmask = 0x02; // No gravity
bitmask = bitmask | 0x16; // Zero Bounding Box (Marker)
wdw.setObject(10, (byte) bitmask); // Set our metadatas
}
public Hologram(Location location, String line) {
this.location = location;
this.line = line;
horseId = 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) {
List<AbstractPacket> packets = null;
packets = generateMetadataPackets18(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> generateMetadataPackets18(Player p) {
WrapperPlayServerEntityMetadata metadata = new WrapperPlayServerEntityMetadata();
metadata.setEntityID(horseId);
WrappedWatchableObject wwo = new WrappedWatchableObject(2, getLineForPlayer(p));
metadata.setMetadata(Arrays.asList(wwo));
return Arrays.asList(metadata);
}
public void addEveryoneAsViewer() {
for (Player p : Bukkit.getOnlinePlayers()) {
addViewer(p);
}
}
public void removeEveryoneFromViewers() {
for (WeakReference<Player> p : getViewers().getItems()) {
if (p.get() != null) {
despawnForPlayer(p.get());
viewers.remove(p.get());
}
}
}
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;
}
List<AbstractPacket> packets = null;
packets = generateSpawnPackets18(p);
for (AbstractPacket packet : packets) {
packet.sendPacket(p);
}
}
private List<AbstractPacket> generateSpawnPackets18(Player p) {
// Because Armor Stand is a living entity...
WrapperPlayServerSpawnEntityLiving armorStand = new WrapperPlayServerSpawnEntityLiving();
armorStand.setEntityID(horseId);
armorStand.setX(location.getX());
armorStand.setY(location.getY() + 1.52);
armorStand.setZ(location.getZ());
armorStand.setType(EntityType.ARMOR_STAND); // Armor Stand ID
WrappedDataWatcher wdw = Hologram.wdw.deepClone();
wdw.setObject(2, getLineForPlayer(p));
armorStand.setMetadata(wdw);
List<AbstractPacket> packets = Arrays.asList(armorStand);
return packets;
}
public void despawnForPlayer(Player p) {
WrapperPlayServerEntityDestroy remove = new WrapperPlayServerEntityDestroy();
remove.setEntityIds(new int[] { horseId });
remove.sendPacket(p);
}
public void despawnForAll() {
WrapperPlayServerEntityDestroy remove = new WrapperPlayServerEntityDestroy();
remove.setEntityIds(new int[] { horseId });
for (WeakReference<Player> p : viewers.getItems()) {
if (p.get() != null) {
remove.sendPacket(p.get());
}
}
}
public void teleport(Location l) {
this.location = l;
// Optimizing teleport: Create only one packet and then send to everyone
WrapperPlayServerEntityTeleport teleport = new WrapperPlayServerEntityTeleport();
teleport.setEntityID(horseId);
teleport.setX(l.getX());
teleport.setY(l.getY());
teleport.setZ(l.getZ());
for (WeakReference<Player> p : viewers.getItems()) {
if (p.get() != null) {
teleport.sendPacket(p.get());
}
}
}
public void teleport(Player p, Location l) {
this.location = l;
// Not so optimized: Do not use for (Player p : Bukkit.getOnlinePlayers()) { teleport(p, l); } for this! Use teleport(l);
WrapperPlayServerEntityTeleport teleport = new WrapperPlayServerEntityTeleport();
teleport.setEntityID(horseId);
teleport.setX(l.getX());
teleport.setY(l.getY());
teleport.setZ(l.getZ());
teleport.sendPacket(p);
}
public void teleport(List<Player> players, Location l) {
this.location = l;
// Optimizing teleport: Create only one packet and then send to everyone
WrapperPlayServerEntityTeleport teleport = new WrapperPlayServerEntityTeleport();
teleport.setEntityID(horseId);
teleport.setX(l.getX());
teleport.setY(l.getY());
teleport.setZ(l.getZ());
for (Player p : players) {
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;
}
public void attachTo(Entity entity) {
WrapperPlayServerAttachEntity wpsae = new WrapperPlayServerAttachEntity();
wpsae.setVehicleId(entity.getEntityId());
wpsae.setEntityID(horseId);
for (WeakReference<Player> p : getViewers().getItems()) {
if (p.get() != null) {
wpsae.sendPacket(p.get());
}
}
}
public void unattach() {
WrapperPlayServerAttachEntity wpsae = new WrapperPlayServerAttachEntity();
wpsae.setVehicleId(-1);
wpsae.setEntityID(horseId);
for (WeakReference<Player> p : getViewers().getItems()) {
if (p.get() != null) {
wpsae.sendPacket(p.get());
}
}
}
}
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