mirror of
https://github.com/libraryaddict/LibsDisguises.git
synced 2024-12-12 15:07:22 +01:00
Add some vehicle support for armorstand names
This commit is contained in:
parent
54c9bfc968
commit
4b8c293c43
@ -110,7 +110,6 @@ public class DisguiseCommand extends DisguiseBaseCommand implements TabCompleter
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] origArgs) {
|
||||
ArrayList<String> tabs = new ArrayList<>();
|
||||
String[] args = getPreviousArgs(origArgs);
|
||||
|
||||
DisguisePermissions perms = getPermissions(sender);
|
||||
|
@ -138,6 +138,7 @@ import org.bukkit.scoreboard.Team;
|
||||
import org.bukkit.scoreboard.Team.Option;
|
||||
import org.bukkit.scoreboard.Team.OptionStatus;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@ -282,7 +283,7 @@ public class DisguiseUtilities {
|
||||
private static final Cache<Integer, Long> velocityTimes = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.SECONDS).build();
|
||||
private static final HashMap<UUID, ArrayList<Integer>> disguiseLoading = new HashMap<>();
|
||||
@Getter
|
||||
private static boolean runningPaper;
|
||||
private static boolean runningPaper, runningGeyser;
|
||||
private static MineSkinAPI mineSkinAPI;
|
||||
@Getter
|
||||
private static boolean invalidFile;
|
||||
@ -337,6 +338,8 @@ public class DisguiseUtilities {
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
runningGeyser = Bukkit.getPluginManager().getPlugin("Geyser-Spigot") != null;
|
||||
|
||||
if (LibsDisguises.getInstance() == null) {
|
||||
profileCache = null;
|
||||
sanitySkinCacheFile = null;
|
||||
@ -506,6 +509,65 @@ public class DisguiseUtilities {
|
||||
return getHexedColors(name);
|
||||
}
|
||||
|
||||
public static void adjustNamePositions(Disguise disguise, LibsPackets<? extends PacketWrapper> packets) {
|
||||
List<PacketWrapper> newPackets = adjustNamePositions(disguise, packets.getPackets());
|
||||
|
||||
if (newPackets == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
packets.getPackets().addAll(newPackets);
|
||||
}
|
||||
|
||||
public static @Nullable List<PacketWrapper> adjustNamePositions(Disguise disguise, List<PacketWrapper> packets) {
|
||||
int len = disguise.getMultiNameLength();
|
||||
|
||||
if (len == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<PacketWrapper> toAdd = new ArrayList<>();
|
||||
double height = (disguise.getHeight() + disguise.getWatcher().getNameYModifier());
|
||||
double heightScale = disguise.getNameHeightScale();
|
||||
height *= heightScale;
|
||||
height += (DisguiseUtilities.getNameSpacing() * (heightScale - 1)) * 0.35;
|
||||
|
||||
for (PacketWrapper packet : packets) {
|
||||
if (packet instanceof WrapperPlayServerEntityRotation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
int standId = disguise.getArmorstandIds()[i];
|
||||
PacketWrapper cloned;
|
||||
|
||||
if (packet instanceof WrapperPlayServerEntityTeleport) {
|
||||
// TODO Handle if this is a vehicle movement
|
||||
WrapperPlayServerEntityTeleport tele = (WrapperPlayServerEntityTeleport) packet;
|
||||
|
||||
cloned = new WrapperPlayServerEntityTeleport(standId,
|
||||
tele.getPosition().add(0, height + (DisguiseUtilities.getNameSpacing() * i), 0), tele.getYaw(), tele.getPitch(),
|
||||
tele.isOnGround());
|
||||
} else if (packet instanceof WrapperPlayServerEntityRelativeMoveAndRotation) {
|
||||
WrapperPlayServerEntityRelativeMoveAndRotation rot = (WrapperPlayServerEntityRelativeMoveAndRotation) packet;
|
||||
cloned = new WrapperPlayServerEntityRelativeMoveAndRotation(standId, rot.getDeltaX(), rot.getDeltaY(), rot.getDeltaZ(),
|
||||
rot.getYaw(), rot.getPitch(), rot.isOnGround());
|
||||
} else if (packet instanceof WrapperPlayServerEntityRelativeMove) {
|
||||
WrapperPlayServerEntityRelativeMove rot = (WrapperPlayServerEntityRelativeMove) packet;
|
||||
cloned = new WrapperPlayServerEntityRelativeMove(standId, rot.getDeltaX(), rot.getDeltaY(), rot.getDeltaZ(),
|
||||
rot.isOnGround());
|
||||
} else {
|
||||
// It seems that EntityStatus packet was being added at some point, probably in some other transformation
|
||||
continue; // throw new IllegalStateException("Unknown packet " + packet.getClass());
|
||||
}
|
||||
|
||||
toAdd.add(cloned);
|
||||
}
|
||||
}
|
||||
|
||||
return toAdd;
|
||||
}
|
||||
|
||||
private static String toMiniMessage(Component component) {
|
||||
// Why do we run this through two serializers? Because the alternative is that we shade 2 versions of minimessage instead of just 1.
|
||||
return getMiniMessage().serialize(internalComponentSerializer.deserialize(externalComponentSerializer.serialize(component)));
|
||||
|
@ -5,6 +5,7 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Ser
|
||||
import lombok.Getter;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.DisguiseConfig;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.packets.packetlisteners.PacketListenerClientCustomPayload;
|
||||
@ -15,6 +16,7 @@ import me.libraryaddict.disguise.utilities.packets.packetlisteners.PacketListene
|
||||
import me.libraryaddict.disguise.utilities.packets.packetlisteners.PacketListenerScoreboardTeam;
|
||||
import me.libraryaddict.disguise.utilities.packets.packetlisteners.PacketListenerSounds;
|
||||
import me.libraryaddict.disguise.utilities.packets.packetlisteners.PacketListenerTabList;
|
||||
import me.libraryaddict.disguise.utilities.packets.packetlisteners.PacketListenerVehicleMovement;
|
||||
import me.libraryaddict.disguise.utilities.packets.packetlisteners.PacketListenerViewSelfDisguise;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -52,6 +54,11 @@ public class PacketsManager {
|
||||
PacketEvents.getAPI().getEventManager().registerListener(customPayload);
|
||||
}
|
||||
|
||||
PacketListenerVehicleMovement vehicleMovement = new PacketListenerVehicleMovement();
|
||||
Bukkit.getPluginManager().registerEvents(vehicleMovement, LibsDisguises.getInstance());
|
||||
|
||||
PacketEvents.getAPI().getEventManager().registerListener(vehicleMovement);
|
||||
|
||||
initialListenersRegistered = true;
|
||||
PacketEvents.getAPI().getSettings().fullStackTrace(true);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
@ -46,54 +45,7 @@ public class PacketHandlerMovement<T extends PacketWrapper<T>> implements IPacke
|
||||
@Override
|
||||
public void handle(Disguise disguise, LibsPackets<T> packets, Player observer, Entity entity) {
|
||||
handleMovement(disguise, packets, observer, entity);
|
||||
addMultiNames(disguise, packets);
|
||||
}
|
||||
|
||||
private void addMultiNames(Disguise disguise, LibsPackets<T> packets) {
|
||||
int len = disguise.getMultiNameLength();
|
||||
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<PacketWrapper> toAdd = new ArrayList<>();
|
||||
double height = (disguise.getHeight() + disguise.getWatcher().getNameYModifier());
|
||||
double heightScale = disguise.getNameHeightScale();
|
||||
height *= heightScale;
|
||||
height += (DisguiseUtilities.getNameSpacing() * (heightScale - 1)) * 0.35;
|
||||
|
||||
for (PacketWrapper packet : packets.getPackets()) {
|
||||
if (packet instanceof WrapperPlayServerEntityRotation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
int standId = disguise.getArmorstandIds()[i];
|
||||
PacketWrapper cloned;
|
||||
|
||||
if (packet instanceof WrapperPlayServerEntityTeleport) {
|
||||
WrapperPlayServerEntityTeleport tele = (WrapperPlayServerEntityTeleport) packet;
|
||||
cloned = new WrapperPlayServerEntityTeleport(standId,
|
||||
tele.getPosition().add(0, height + (DisguiseUtilities.getNameSpacing() * i), 0), tele.getYaw(), tele.getPitch(),
|
||||
tele.isOnGround());
|
||||
} else if (packet instanceof WrapperPlayServerEntityRelativeMoveAndRotation) {
|
||||
WrapperPlayServerEntityRelativeMoveAndRotation rot = (WrapperPlayServerEntityRelativeMoveAndRotation) packet;
|
||||
cloned = new WrapperPlayServerEntityRelativeMoveAndRotation(standId, rot.getDeltaX(), rot.getDeltaY(), rot.getDeltaZ(),
|
||||
rot.getYaw(), rot.getPitch(), rot.isOnGround());
|
||||
} else if (packet instanceof WrapperPlayServerEntityRelativeMove) {
|
||||
WrapperPlayServerEntityRelativeMove rot = (WrapperPlayServerEntityRelativeMove) packet;
|
||||
cloned = new WrapperPlayServerEntityRelativeMove(standId, rot.getDeltaX(), rot.getDeltaY(), rot.getDeltaZ(),
|
||||
rot.isOnGround());
|
||||
} else {
|
||||
// It seems that EntityStatus packet was being added at some point, probably in some other transformation
|
||||
continue; // throw new IllegalStateException("Unknown packet " + packet.getClass());
|
||||
}
|
||||
|
||||
toAdd.add(cloned);
|
||||
}
|
||||
}
|
||||
|
||||
packets.getPackets().addAll(toAdd);
|
||||
DisguiseUtilities.adjustNamePositions(disguise, packets);
|
||||
}
|
||||
|
||||
private void handleMovement(Disguise disguise, LibsPackets<T> packets, Player observer, Entity entity) {
|
||||
|
@ -0,0 +1,289 @@
|
||||
package me.libraryaddict.disguise.utilities.packets.packetlisteners;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
import com.github.retrooper.packetevents.event.SimplePacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.simple.PacketPlaySendEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRelativeMove;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRelativeMoveAndRotation;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Server.ENTITY_RELATIVE_MOVE;
|
||||
import static com.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Server.ENTITY_RELATIVE_MOVE_AND_ROTATION;
|
||||
import static com.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Server.ENTITY_TELEPORT;
|
||||
import static com.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Server.RESPAWN;
|
||||
|
||||
public class PacketListenerVehicleMovement extends SimplePacketListenerAbstract implements Listener {
|
||||
static class PlayerTracker {
|
||||
/**
|
||||
* A vehicle can have multiple passengers
|
||||
*/
|
||||
private final Map<Integer, int[]> vehicleAndPassengersId = new HashMap<>();
|
||||
}
|
||||
|
||||
private final Map<UUID, PlayerTracker> trackerMap = new HashMap<>();
|
||||
|
||||
public PacketListenerVehicleMovement() {
|
||||
super(PacketListenerPriority.LOW);
|
||||
// This handling does not handle packets that were only sent to specific players
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
trackerMap.remove(event.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
private void refreshPosition(Player observer, int entityId) {
|
||||
refreshPosition(observer, entityId, null);
|
||||
}
|
||||
|
||||
private void refreshPosition(Player observer, int entityId, PacketWrapper sentPacket) {
|
||||
Disguise disguise = DisguiseUtilities.getDisguise(observer, entityId);
|
||||
|
||||
if (disguise == null || disguise.getArmorstandIds().length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Entity entity = disguise.getEntity();
|
||||
|
||||
if (entity == null || !entity.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location loc = entity.getLocation();
|
||||
|
||||
if (sentPacket == null) {
|
||||
sentPacket = new WrapperPlayServerEntityTeleport(entityId,
|
||||
new com.github.retrooper.packetevents.protocol.world.Location(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(),
|
||||
loc.getPitch()), true);
|
||||
}
|
||||
|
||||
List<PacketWrapper> wrappers = DisguiseUtilities.adjustNamePositions(disguise, Collections.singletonList(sentPacket));
|
||||
|
||||
if (wrappers == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (PacketWrapper wrapper : wrappers) {
|
||||
PacketEvents.getAPI().getPlayerManager().sendPacketSilently(observer, wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshPassengersRecursive(Map<Integer, int[]> vehicleAndPassengersId, int[] passengers, Map<Integer, Boolean> map) {
|
||||
for (int entityId : passengers) {
|
||||
// If this entity is already handled
|
||||
if (map.containsKey(entityId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Refresh the passenger
|
||||
map.put(entityId, true);
|
||||
|
||||
// Get the passengers on the passenger
|
||||
int[] mounted = vehicleAndPassengersId.get(entityId);
|
||||
|
||||
// If not carrying anyone
|
||||
if (mounted == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Refresh the passengers on the passenger
|
||||
refreshPassengersRecursive(vehicleAndPassengersId, mounted, map);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePassengersRecursive(int depth, Player player, PlayerTracker tracker, int[] passengers, PacketWrapper wrapper) {
|
||||
// Basic sanity check
|
||||
if (depth > 15) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int entityId : passengers) {
|
||||
refreshPosition(player, entityId, wrapper);
|
||||
|
||||
int[] newPassengers = tracker.vehicleAndPassengersId.get(entityId);
|
||||
|
||||
if (newPassengers == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
updatePassengersRecursive(depth++, player, tracker, newPassengers, wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketPlaySend(PacketPlaySendEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.SET_PASSENGERS) {
|
||||
WrapperPlayServerSetPassengers packet;
|
||||
|
||||
if (event.getLastUsedWrapper() != null) {
|
||||
packet = (WrapperPlayServerSetPassengers) event.getLastUsedWrapper();
|
||||
} else {
|
||||
packet = new WrapperPlayServerSetPassengers(event);
|
||||
}
|
||||
|
||||
PlayerTracker tracker = trackerMap.get(player.getUniqueId());
|
||||
int[] mountedNow = packet.getPassengers();
|
||||
|
||||
if (tracker == null) {
|
||||
if (mountedNow.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
trackerMap.put(player.getUniqueId(), tracker = new PlayerTracker());
|
||||
}
|
||||
|
||||
int[] mountedPrevious = tracker.vehicleAndPassengersId.get(packet.getEntityId());
|
||||
|
||||
if (packet.getPassengers().length == 0) {
|
||||
// Dismounted
|
||||
tracker.vehicleAndPassengersId.remove(packet.getEntityId());
|
||||
} else {
|
||||
tracker.vehicleAndPassengersId.put(packet.getEntityId(), mountedNow);
|
||||
}
|
||||
|
||||
// We could do some fancy logic to avoid sending packets when it is not required, but that's making this complicated
|
||||
|
||||
if (mountedPrevious != null) {
|
||||
loop:
|
||||
for (int entityId : mountedPrevious) {
|
||||
boolean stillRiding = false;
|
||||
|
||||
// If the entity is still riding the same vehicle, skip loop
|
||||
for (int ridingId : mountedNow) {
|
||||
if (entityId != ridingId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
continue loop;
|
||||
}
|
||||
|
||||
// This entity has dismounted
|
||||
refreshPosition(player, entityId);
|
||||
}
|
||||
|
||||
loop:
|
||||
for (int ridingId : mountedNow) {
|
||||
// If the entity is still riding the same vehicle, skip loop
|
||||
for (int entityId : mountedNow) {
|
||||
if (entityId != ridingId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
continue loop;
|
||||
}
|
||||
|
||||
// This entity has mounted
|
||||
refreshPosition(player, ridingId);
|
||||
}
|
||||
} else {
|
||||
for (int entityId : mountedNow) {
|
||||
refreshPosition(player, entityId);
|
||||
}
|
||||
}
|
||||
} else if (event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) {
|
||||
PlayerTracker tracker = trackerMap.get(player.getUniqueId());
|
||||
|
||||
if (tracker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int[] ids;
|
||||
|
||||
if (event.getLastUsedWrapper() != null) {
|
||||
ids = ((WrapperPlayServerDestroyEntities) event.getLastUsedWrapper()).getEntityIds();
|
||||
} else {
|
||||
ids = new WrapperPlayServerDestroyEntities(event).getEntityIds();
|
||||
}
|
||||
|
||||
Map<Integer, Boolean> toRefresh = new HashMap<>();
|
||||
|
||||
for (int entityId : ids) {
|
||||
// Don't refresh this entity, it is destroyed
|
||||
toRefresh.put(entityId, false);
|
||||
}
|
||||
|
||||
// Seperate block so the map is prefilled
|
||||
for (int entityId : ids) {
|
||||
int[] passengers = tracker.vehicleAndPassengersId.remove(entityId);
|
||||
|
||||
// If nothing was riding this entity, continue
|
||||
if (passengers == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Refresh the passengers, recursive if there happens to be a pillar of mounted entities
|
||||
refreshPassengersRecursive(tracker.vehicleAndPassengersId, passengers, toRefresh);
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, Boolean> entry : toRefresh.entrySet()) {
|
||||
// If this entity is not one to be refreshed
|
||||
if (!entry.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Refresh the position
|
||||
refreshPosition(player, entry.getKey());
|
||||
}
|
||||
} else if (event.getPacketType() == ENTITY_TELEPORT || event.getPacketType() == ENTITY_RELATIVE_MOVE ||
|
||||
event.getPacketType() == ENTITY_RELATIVE_MOVE_AND_ROTATION) {
|
||||
PlayerTracker tracker = trackerMap.get(player.getUniqueId());
|
||||
|
||||
if (tracker == null || tracker.vehicleAndPassengersId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PacketWrapper wrapper = event.getLastUsedWrapper();
|
||||
int entityId;
|
||||
|
||||
if (wrapper == null) {
|
||||
if (event.getPacketType() == ENTITY_TELEPORT) {
|
||||
wrapper = new WrapperPlayServerEntityTeleport(event);
|
||||
entityId = ((WrapperPlayServerEntityTeleport) wrapper).getEntityId();
|
||||
} else if (event.getPacketType() == ENTITY_RELATIVE_MOVE) {
|
||||
wrapper = new WrapperPlayServerEntityRelativeMove(event);
|
||||
entityId = ((WrapperPlayServerEntityRelativeMove) wrapper).getEntityId();
|
||||
} else {
|
||||
wrapper = new WrapperPlayServerEntityRelativeMoveAndRotation(event);
|
||||
entityId = ((WrapperPlayServerEntityRelativeMoveAndRotation) wrapper).getEntityId();
|
||||
}
|
||||
} else {
|
||||
entityId = DisguiseUtilities.getEntityId(wrapper);
|
||||
}
|
||||
|
||||
int[] passengers = tracker.vehicleAndPassengersId.get(entityId);
|
||||
|
||||
if (passengers == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
updatePassengersRecursive(0, player, tracker, passengers, wrapper);
|
||||
} else if (event.getPacketType() == RESPAWN) {
|
||||
// Respawn will remove entities, not sure if entities are removed in other ways
|
||||
// This might need a perioditic check to ensure that we're not creating a memory leak if a player does not die or switch worlds
|
||||
// Yet the entities just keep being added
|
||||
// Even if it is the case, should be minor as this only tracks ints, and only mounted entities
|
||||
trackerMap.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user