Citizens2/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java

180 lines
8.2 KiB
Java
Raw Normal View History

package net.citizensnpcs;
2022-12-24 18:37:54 +01:00
import java.util.Collection;
import java.util.List;
2022-11-28 16:10:50 +01:00
import java.util.Set;
import org.bukkit.entity.Entity;
2022-12-20 14:27:01 +01:00
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.PacketType.Play.Server;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
2022-11-28 16:10:50 +01:00
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
2022-12-20 14:27:01 +01:00
import com.comphenix.protocol.reflect.FieldAccessException;
2022-11-28 16:10:50 +01:00
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.PlayerInfoData;
2023-02-11 15:52:53 +01:00
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
2022-12-24 18:37:54 +01:00
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.google.common.collect.Iterables;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.ai.NPCHolder;
2022-12-24 18:37:54 +01:00
import net.citizensnpcs.trait.MirrorTrait;
2022-11-29 23:13:55 +01:00
import net.citizensnpcs.trait.RotationTrait;
import net.citizensnpcs.trait.RotationTrait.PacketRotationSession;
2022-12-24 18:37:54 +01:00
import net.citizensnpcs.util.NMS;
public class ProtocolLibListener {
2022-11-28 16:10:50 +01:00
private final Class<?> flagsClass;
private final ProtocolManager manager;
private final Citizens plugin;
public ProtocolLibListener(Citizens plugin) {
this.plugin = plugin;
this.manager = ProtocolLibrary.getProtocolManager();
2023-03-17 18:36:53 +01:00
flagsClass = MinecraftReflection.getMinecraftClass("RelativeMovement", "world.entity.RelativeMovement",
"EnumPlayerTeleportFlags", "PacketPlayOutPosition$EnumPlayerTeleportFlags",
2022-11-28 16:10:50 +01:00
"network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags");
manager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.HIGHEST, Server.PLAYER_INFO) {
@Override
public void onPacketSending(PacketEvent event) {
int version = manager.getProtocolVersion(event.getPlayer());
if (version >= 761) {
NMS.onPlayerInfoAdd(event.getPlayer(), event.getPacket().getHandle());
return;
}
List<PlayerInfoData> list = event.getPacket().getPlayerInfoDataLists().readSafely(0);
if (list == null)
return;
2022-12-24 18:37:54 +01:00
boolean changed = false;
for (int i = 0; i < list.size(); i++) {
2023-02-11 15:52:53 +01:00
PlayerInfoData info = list.get(i);
if (info == null)
continue;
2023-02-11 15:52:53 +01:00
NPC npc = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(info.getProfile().getUUID());
2022-12-24 18:37:54 +01:00
if (npc == null || !npc.isSpawned())
continue;
MirrorTrait trait = npc.getTraitNullable(MirrorTrait.class);
if (trait == null || !trait.isMirroring(event.getPlayer()))
continue;
2022-12-24 18:37:54 +01:00
GameProfile profile = NMS.getProfile(event.getPlayer());
2023-02-11 15:52:53 +01:00
if (trait.mirrorName()) {
list.set(i,
new PlayerInfoData(
WrappedGameProfile.fromPlayer(event.getPlayer()).withId(
info.getProfile().getId()),
info.getLatency(), info.getGameMode(),
WrappedChatComponent.fromText(event.getPlayer().getDisplayName())));
continue;
}
2022-12-24 18:37:54 +01:00
Collection<Property> textures = profile.getProperties().get("textures");
if (textures == null || textures.size() == 0)
continue;
2023-02-11 15:52:53 +01:00
info.getProfile().getProperties().clear();
2022-12-24 18:37:54 +01:00
for (String key : profile.getProperties().keySet()) {
2023-02-11 15:52:53 +01:00
info.getProfile().getProperties().putAll(key,
2022-12-24 18:37:54 +01:00
Iterables.transform(profile.getProperties().get(key),
skin -> new WrappedSignedProperty(skin.getName(), skin.getValue(),
skin.getSignature())));
}
changed = true;
}
if (changed) {
event.getPacket().getPlayerInfoDataLists().write(0, list);
}
}
});
manager.addPacketListener(
new PacketAdapter(plugin, ListenerPriority.MONITOR, Server.ENTITY_HEAD_ROTATION, Server.ENTITY_LOOK) {
@Override
public void onPacketSending(PacketEvent event) {
NPC npc = getNPCFromPacket(event);
if (npc == null)
return;
2022-11-28 16:10:50 +01:00
2022-11-29 23:13:55 +01:00
RotationTrait trait = npc.getTraitNullable(RotationTrait.class);
if (trait == null)
return;
PacketRotationSession session = trait.getPacketSession(event.getPlayer());
2022-11-28 16:10:50 +01:00
if (session == null || !session.isActive())
return;
PacketContainer packet = event.getPacket();
2022-12-20 14:27:01 +01:00
PacketType type = event.getPacketType();
if (type == Server.ENTITY_HEAD_ROTATION) {
2022-11-28 16:10:50 +01:00
packet.getBytes().write(0, degToByte(session.getHeadYaw()));
2022-12-20 14:27:01 +01:00
} else if (type == Server.ENTITY_LOOK) {
2022-11-28 16:10:50 +01:00
packet.getBytes().write(0, degToByte(session.getBodyYaw()));
packet.getBytes().write(1, degToByte(session.getPitch()));
2022-12-20 14:27:01 +01:00
} else if (type == Server.ENTITY_MOVE_LOOK || type == Server.REL_ENTITY_MOVE_LOOK) {
2022-11-28 16:10:50 +01:00
packet.getBytes().write(0, degToByte(session.getBodyYaw()));
packet.getBytes().write(1, degToByte(session.getPitch()));
2022-12-20 14:27:01 +01:00
} else if (type == Server.POSITION) {
2022-11-28 16:10:50 +01:00
Set<PlayerTeleportFlag> rel = getFlagsModifier(packet).read(0);
rel.remove(PlayerTeleportFlag.ZYAW);
rel.remove(PlayerTeleportFlag.ZPITCH);
getFlagsModifier(packet).write(0, rel);
packet.getFloat().write(0, session.getBodyYaw());
packet.getFloat().write(1, session.getPitch());
}
2023-01-01 11:43:41 +01:00
session.onPacketOverwritten();
}
});
2023-03-26 07:28:23 +02:00
}
2022-11-28 16:10:50 +01:00
private StructureModifier<Set<PlayerTeleportFlag>> getFlagsModifier(PacketContainer handle) {
return handle.getSets(EnumWrappers.getGenericConverter(flagsClass, PlayerTeleportFlag.class));
}
private NPC getNPCFromPacket(PacketEvent event) {
PacketContainer packet = event.getPacket();
Entity entity = null;
try {
Integer id = packet.getIntegers().readSafely(0);
if (id == null)
return null;
entity = manager.getEntityFromID(event.getPlayer().getWorld(), id);
} catch (FieldAccessException | IllegalArgumentException ex) {
if (!LOGGED_ERROR) {
Messaging.severe(
"Error retrieving entity from ID: ProtocolLib error? Suppressing further exceptions unless debugging.");
ex.printStackTrace();
LOGGED_ERROR = true;
} else if (Messaging.isDebugging()) {
ex.printStackTrace();
}
return null;
}
return entity instanceof NPCHolder ? ((NPCHolder) entity).getNPC() : null;
}
2022-11-28 16:10:50 +01:00
public enum PlayerTeleportFlag {
X,
Y,
Z,
ZPITCH,
ZYAW,
}
private static byte degToByte(float in) {
return (byte) (in * 256.0F / 360.0F);
}
private static boolean LOGGED_ERROR = false;
}