Last active
April 8, 2021 23:01
-
-
Save MrPowerGamerBR/4aad85fa20df17b5a016933937d68bb2 to your computer and use it in GitHub Desktop.
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.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