From e23867f0ef8c8fbe7ebc9c6ae915a11ebeffd365 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 19:10:55 +0100 Subject: [PATCH] stuff --- .../commands/list/DefaultCommand.java | 4 +- .../znetworkw/znpcservers/npc/NPCSkin.java | 9 ++- .../znpcservers/reflection/Reflections.java | 3 + .../reflection/types/FieldReflection.java | 23 +++++--- .../znpcservers/skin/SkinFetcher.java | 4 +- .../znpcservers/skin/SkinFetcherResult.java | 2 +- .../pyr/znpcsplus/entity/PacketEntity.java | 8 +++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 14 +++++ .../pyr/znpcsplus/packets/PacketFactory.java | 4 ++ .../pyr/znpcsplus/packets/V1_14Factory.java | 17 ++++++ .../pyr/znpcsplus/packets/V1_19Factory.java | 30 ++++++++++ .../pyr/znpcsplus/packets/V1_8Factory.java | 58 +++++++++++++++---- .../znpcsplus/properties/NPCPropertyKey.java | 7 +++ 13 files changed, 156 insertions(+), 27 deletions(-) create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java index 442d078..2c9d8e1 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java @@ -39,14 +39,14 @@ public class DefaultCommand extends Command { private static final Joiner SPACE_JOINER = Joiner.on(" "); - private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (values, ex) -> { + private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (value, signature, ex) -> { if (ex != null) { Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.CANT_GET_SKIN, skin); ZNPCsPlus.LOGGER.warning("Failed to fetch skin:"); ex.printStackTrace(); return; } - npc.changeSkin(NPCSkin.forValues(values)); + npc.changeSkin(NPCSkin.forValues(value, signature)); Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.GET_SKIN); }); diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java index c1807a4..94baaa9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java @@ -9,14 +9,13 @@ public class NPCSkin { private final String texture; private final String signature; - protected NPCSkin(String... values) { - if (values.length < 1) throw new IllegalArgumentException("Invalid arguments for NPC skin constructor"); - this.texture = values[0]; - this.signature = values[1]; + protected NPCSkin(String texture, String signature) { + this.texture = texture; + this.signature = signature; } public static NPCSkin forValues(String... values) { - return new NPCSkin((values.length > 0) ? values : new String[0]); + return new NPCSkin(values[0], (values.length > 1) ? values[1] : null); } public static void forName(String skin, SkinFetcherResult skinFetcherResult) { diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index 1615ab1..1ea090f 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -667,5 +667,8 @@ public final class Reflections { public static final ReflectionLazyLoader ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withClassName(ENTITY_CLASS) .withFieldName("entityCount") + .withFieldName("d") + .withFieldName("c") + .withExpectResult(AtomicInteger.class) .setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java index 0dbd720..b222326 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java @@ -18,26 +18,35 @@ public class FieldReflection extends ReflectionLazyLoader { } protected Field load() throws NoSuchFieldException { - for (Class clazz : this.reflectionClasses) { - Field field = load(clazz); + if (fieldName != null && fieldName.length() > 0) for (Class clazz : this.reflectionClasses) { + Field field = loadByName(clazz); + if (field != null) return field; + } + if (expectType != null) for (Class clazz : this.reflectionClasses) { + Field field = loadByType(clazz); if (field != null) return field; } return null; } - private Field load(Class clazz) { - if (expectType != null) for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) { - field.setAccessible(true); - return field; - } + private Field loadByName(Class clazz) { try { Field field = clazz.getDeclaredField(fieldName); + if (expectType != null && !field.getType().equals(expectType)) return null; field.setAccessible(true); return field; } catch (NoSuchFieldException ignored) {} return null; } + private Field loadByType(Class clazz) { + for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) { + field.setAccessible(true); + return field; + } + return null; + } + @Override protected void printDebugInfo(Consumer logger) { logger.accept("Field Name: " + fieldName); diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java index 096ede8..0421af9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java @@ -46,11 +46,11 @@ public class SkinFetcher { }); completableFuture.whenComplete((response, throwable) -> { if (completableFuture.isCompletedExceptionally()) { - skinFetcherResult.onDone(null, throwable); + skinFetcherResult.onDone(null, null, throwable); } else { JsonObject jsonObject = response.getAsJsonObject(this.builder.getAPIServer().getValueKey()); JsonObject properties = jsonObject.getAsJsonObject(this.builder.getAPIServer().getSignatureKey()); - skinFetcherResult.onDone(new String[]{properties.get("value").getAsString(), properties.get("signature").getAsString()}, null); + skinFetcherResult.onDone(properties.get("value").getAsString(), properties.get("signature").getAsString(), null); } }); return completableFuture; diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java index 59db73e..ec55efa 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java @@ -1,5 +1,5 @@ package io.github.znetworkw.znpcservers.skin; public interface SkinFetcherResult { - void onDone(String[] paramArrayOfString, Throwable paramThrowable); + void onDone(String value, String signature, Throwable paramThrowable); } diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 09354c4..93d9dcb 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -6,14 +6,18 @@ import lol.pyr.znpcsplus.packets.PacketFactory; import org.bukkit.entity.Player; import java.util.Set; +import java.util.UUID; public class PacketEntity { private final int entityId; + private final UUID uuid; + private final EntityType type; private PacketLocation location; public PacketEntity(EntityType type, PacketLocation location) { this.entityId = EntityIDProvider.reserve(); + this.uuid = UUID.randomUUID(); this.type = type; this.location = location; } @@ -26,6 +30,10 @@ public class PacketEntity { return location; } + public UUID getUuid() { + return uuid; + } + public EntityType getType() { return type; } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 100279b..9283a5e 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -2,11 +2,15 @@ package lol.pyr.znpcsplus.npc; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.properties.NPCProperty; +import lol.pyr.znpcsplus.properties.NPCPropertyKey; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; public class NPC { @@ -16,6 +20,8 @@ public class NPC { private PacketLocation location; private NPCType type; + private final Map propertyMap = new HashMap<>(); + public NPC(World world, NPCType type, PacketLocation location) { this.worldName = world.getName(); this.type = type; @@ -83,4 +89,12 @@ public class NPC { public boolean isShown(Player player) { return viewers.contains(player); } + + public NPCProperty getProperty(NPCPropertyKey key) { + return propertyMap.get(key); + } + + public boolean hasProperty(NPCPropertyKey key) { + return propertyMap.containsKey(key); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index d57b4fb..3baf573 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -16,6 +16,8 @@ public interface PacketFactory { void teleportEntity(Player player, PacketEntity entity); void addTabPlayer(Player player, PacketEntity entity); void removeTabPlayer(Player player, PacketEntity entity); + void createTeam(Player player, PacketEntity entity); + void removeTeam(Player player, PacketEntity entity); PacketFactory factory = get(); @@ -35,6 +37,8 @@ public interface PacketFactory { private static Map> buildFactoryMap() { HashMap> map = new HashMap<>(); map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); + map.put(ServerVersion.V_1_14, LazyLoader.of(V1_14Factory::new)); + map.put(ServerVersion.V_1_19, LazyLoader.of(V1_19Factory::new)); return map; } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java new file mode 100644 index 0000000..07c8a7e --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java @@ -0,0 +1,17 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import org.bukkit.entity.Player; + +import java.util.Optional; + +public class V1_14Factory extends V1_8Factory { + @Override + public void spawnEntity(Player player, PacketEntity entity) { + PacketLocation location = entity.getLocation(); + sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), + location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java new file mode 100644 index 0000000..98aaee1 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java @@ -0,0 +1,30 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate; +import lol.pyr.znpcsplus.entity.PacketEntity; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; + +import java.util.EnumSet; + +public class V1_19Factory extends V1_14Factory { + @Override + public void addTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return; + WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( + new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), false, 1, GameMode.CREATIVE, + Component.empty(), null); + sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, + WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); + } + + @Override + public void removeTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfoRemove(entity.getUuid())); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 3a31083..26e7d4b 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -2,24 +2,32 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.GameMode; import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.*; +import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; import java.util.List; import java.util.Optional; -import java.util.UUID; public class V1_8Factory implements PacketFactory { @Override public void spawnPlayer(Player player, PacketEntity entity) { addTabPlayer(player, entity); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer()); - // TODO + createTeam(player, entity); + PacketLocation location = entity.getLocation(); + sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), + entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); + ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> removeTabPlayer(player, entity), 60); } @Override @@ -27,32 +35,62 @@ public class V1_8Factory implements PacketFactory { PacketLocation location = entity.getLocation(); EntityType type = entity.getType(); ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, type.getLegacyId(clientVersion) == -1 ? - new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), new UUID(0, 0), type, location.toVector3d(), + sendPacket(player, type.getLegacyId(clientVersion) == -1 ? + new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), entity.getUuid(), type, location.toVector3d(), location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : - new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.empty(), entity.getType(), location.toVector3d(), + new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); } @Override public void destroyEntity(Player player, PacketEntity entity) { - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, entity); } @Override public void teleportEntity(Player player, PacketEntity entity) { PacketLocation location = entity.getLocation(); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), + sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), location.toVector3d(), location.getYaw(), location.getPitch(), true)); } @Override public void addTabPlayer(Player player, PacketEntity entity) { - + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfo( + WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), + new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), GameMode.CREATIVE, 1))); } @Override public void removeTabPlayer(Player player, PacketEntity entity) { - new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, new UserProfile(gameProfile.getId(), gameProfile.getName()), null, 1)) + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfo( + WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, + new UserProfile(entity.getUuid(), null), null, -1))); + } + + @Override + public void createTeam(Player player, PacketEntity entity) { + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo( + Component.empty(), + Component.empty(), + Component.empty(), + WrapperPlayServerTeams.NameTagVisibility.NEVER, + WrapperPlayServerTeams.CollisionRule.NEVER, + NamedTextColor.WHITE, + WrapperPlayServerTeams.OptionData.NONE + ))); + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, Integer.toString(entity.getEntityId()))); + } + + @Override + public void removeTeam(Player player, PacketEntity entity) { + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null)); + } + + protected void sendPacket(Player player, PacketWrapper packet) { + PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet); } } diff --git a/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java b/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java new file mode 100644 index 0000000..9f87d74 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java @@ -0,0 +1,7 @@ +package lol.pyr.znpcsplus.properties; + +public class NPCPropertyKey { + public NPCPropertyKey() {} + + public static NPCPropertyKey<> +}