From a7bf542eb34d08de32377a08f0d01515a3a8d81f Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Tue, 10 Dec 2024 10:56:20 +0400 Subject: [PATCH 01/56] Added entity_sitting property to allow player and some other entities to sit --- .../entity/ArmorStandVehicleEntity.java | 72 +++++++++++++++++++ .../entity/EntityPropertyRegistryImpl.java | 2 + .../pyr/znpcsplus/entity/PacketEntity.java | 41 +++++++++++ .../properties/EntitySittingProperty.java | 53 ++++++++++++++ .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 4 ++ .../lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 2 +- 6 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java new file mode 100644 index 0000000..0bc3886 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java @@ -0,0 +1,72 @@ +package lol.pyr.znpcsplus.entity; + +import io.github.retrooper.packetevents.util.SpigotConversionUtil; +import lol.pyr.znpcsplus.api.entity.EntityProperty; +import lol.pyr.znpcsplus.api.entity.PropertyHolder; +import org.bukkit.inventory.ItemStack; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Represents an armor stand vehicle entity. + *

+ * This entity is used to make the NPC sit on an invisible armor stand. + *

+ */ +public class ArmorStandVehicleEntity implements PropertyHolder { + + private final Map, Object> propertyMap = new HashMap<>(); + + public ArmorStandVehicleEntity(EntityPropertyRegistryImpl propertyRegistry) { + setProperty(propertyRegistry.getByName("small", Boolean.class), true); + setProperty(propertyRegistry.getByName("invisible", Boolean.class), true); + setProperty(propertyRegistry.getByName("base_plate", Boolean.class), false); + } + + @SuppressWarnings("unchecked") + public T getProperty(EntityProperty key) { + return hasProperty(key) ? (T) propertyMap.get((EntityPropertyImpl) key) : key.getDefaultValue(); + } + + @Override + public boolean hasProperty(EntityProperty key) { + return propertyMap.containsKey((EntityPropertyImpl) key); + } + + @SuppressWarnings("unchecked") + @Override + public void setProperty(EntityProperty key, T value) { + Object val = value; + if (val instanceof ItemStack) val = SpigotConversionUtil.fromBukkitItemStack((ItemStack) val); + + setProperty((EntityPropertyImpl) key, (T) val); + } + + @Override + public void setItemProperty(EntityProperty key, ItemStack value) { + throw new UnsupportedOperationException("Cannot set item properties on armor stands"); + } + + @Override + public ItemStack getItemProperty(EntityProperty key) { + throw new UnsupportedOperationException("Cannot get item properties on armor stands"); + } + + public void setProperty(EntityPropertyImpl key, T value) { + if (key == null) return; + if (value == null || value.equals(key.getDefaultValue())) propertyMap.remove(key); + else propertyMap.put(key, value); + } + + public Set> getAllProperties() { + return Collections.unmodifiableSet(propertyMap.keySet()); + } + + @Override + public Set> getAppliedProperties() { + return Collections.unmodifiableSet(propertyMap.keySet()); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 6bb9b3c..f097962 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -182,6 +182,8 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { register(new BooleanProperty("baby", babyIndex, false, legacyBooleans)); } + register(new EntitySittingProperty(packetFactory, this)); + // Player register(new DummyProperty<>("skin", SkinDescriptor.class, false)); final int skinLayersIndex; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 4418152..5687adc 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -4,6 +4,7 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import lol.pyr.znpcsplus.ZNpcsPlusBootstrap; import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.packets.PacketFactory; @@ -13,6 +14,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.Collection; +import java.util.HashMap; import java.util.Set; import java.util.UUID; @@ -26,6 +28,8 @@ public class PacketEntity implements PropertyHolder { private final EntityType type; private NpcLocation location; + private final HashMap metadata = new HashMap<>(); + public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, EntityType type, NpcLocation location) { this.packetFactory = packetFactory; this.properties = properties; @@ -67,6 +71,15 @@ public class PacketEntity implements PropertyHolder { public void despawn(Player player) { packetFactory.destroyEntity(player, this, properties); + if (hasMetadata("ridingVehicle")) { + try { + PacketEntity armorStand = (PacketEntity) getMetadata("ridingVehicle"); + armorStand.despawn(player); + } catch (Exception e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + } } public void refreshMeta(Player player) { @@ -116,4 +129,32 @@ public class PacketEntity implements PropertyHolder { public Set> getAppliedProperties() { return properties.getAppliedProperties(); } + + public void setMetadata(String key, Object value) { + metadata.put(key, value); + } + + public Object getMetadata(String key) { + return metadata.get(key); + } + + public T getMetadata(String key, Class type) { + try { + return type.cast(metadata.get(key)); + } catch (ClassCastException e) { + return null; + } + } + + public void removeMetadata(String key) { + metadata.remove(key); + } + + public boolean hasMetadata(String key) { + return metadata.containsKey(key); + } + + public void clearMetadata() { + metadata.clear(); + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java new file mode 100644 index 0000000..fb8fc2c --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java @@ -0,0 +1,53 @@ +package lol.pyr.znpcsplus.entity.properties; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers; +import lol.pyr.znpcsplus.entity.ArmorStandVehicleEntity; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.packets.PacketFactory; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class EntitySittingProperty extends EntityPropertyImpl { + private final PacketFactory packetFactory; + private final EntityPropertyRegistryImpl propertyRegistry; + + public EntitySittingProperty(PacketFactory packetFactory, EntityPropertyRegistryImpl propertyRegistry) { + super("entity_sitting", false, Boolean.class); + this.packetFactory = packetFactory; + this.propertyRegistry = propertyRegistry; + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + boolean sitting = entity.getProperty(this); + if (sitting) { + ArmorStandVehicleEntity vehicleEntity = new ArmorStandVehicleEntity(propertyRegistry); + PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, vehicleEntity, EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); + vehiclePacketEntity.spawn(player); + entity.setMetadata("ridingVehicle", vehiclePacketEntity); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSetPassengers( + vehiclePacketEntity.getEntityId(), + new int[]{entity.getEntityId()} + )); + } else { + if (entity.hasMetadata("ridingVehicle")) { + PacketEntity vehicleEntity = (PacketEntity) entity.getMetadata("ridingVehicle"); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSetPassengers( + vehicleEntity.getEntityId(), + new int[]{} + )); + vehicleEntity.despawn(player); + entity.removeMetadata("ridingVehicle"); + // Send a packet to reset the npc's position + packetFactory.teleportEntity(player, entity); + } + } + } + +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index 4fa6b67..0a5695a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -86,6 +86,10 @@ public class NpcImpl extends Viewable implements Npc { public void setLocation(NpcLocation location) { this.location = location; entity.setLocation(location, getViewers()); + if (entity.hasMetadata("ridingVehicle")) { + PacketEntity armorStand = (PacketEntity) entity.getMetadata("ridingVehicle"); + armorStand.setLocation(location.withY(location.getY() - 0.9), getViewers()); + } hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index d072740..1e6a26d 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -118,7 +118,7 @@ public class NpcTypeImpl implements NpcType { "potion_color", "potion_ambient", "display_name", "permission_required", "player_knockback", "player_knockback_exempt_permission", "player_knockback_distance", "player_knockback_vertical", "player_knockback_horizontal", "player_knockback_cooldown", "player_knockback_sound", "player_knockback_sound_name", - "player_knockback_sound_volume", "player_knockback_sound_pitch"); + "player_knockback_sound_volume", "player_knockback_sound_pitch", "entity_sitting"); if (!type.equals(EntityTypes.PLAYER)) addProperties("dinnerbone"); // TODO: make this look nicer after completing the rest of the properties if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow"); -- 2.45.2 From 8aed2ba5dc36c9650d7c00fbd65bee6862d6e993 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Thu, 12 Dec 2024 14:27:29 +0400 Subject: [PATCH 02/56] chore: bump packetevents version --- plugin/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/build.gradle b/plugin/build.gradle index 35783cc..7cbf95f 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -19,7 +19,7 @@ dependencies { compileOnly "me.clip:placeholderapi:2.11.6" // Placeholder support implementation "com.google.code.gson:gson:2.10.1" // JSON parsing implementation "org.bstats:bstats-bukkit:3.0.2" // Plugin stats - implementation "com.github.retrooper:packetevents-spigot:2.6.0" // Packets + implementation "com.github.retrooper:packetevents-spigot:2.7.0" // Packets implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" // Configs implementation "lol.pyr:director-adventure:2.1.2" // Commands -- 2.45.2 From 7fbe42e2078d13012aa077724e722bb84dd8a1cc Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Thu, 12 Dec 2024 14:30:22 +0400 Subject: [PATCH 03/56] feat: Creaking NPC Type and its properties --- .../znpcsplus/entity/EntityPropertyRegistryImpl.java | 10 ++++++++++ .../main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 5 +++++ .../lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java | 6 ++++++ 3 files changed, 21 insertions(+) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index f097962..6e02d58 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -667,6 +667,16 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { // Bogged register(new BooleanProperty("bogged_sheared", 16, false, legacyBooleans)); + + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_21_2)) return; + + // Creaking + register(new BooleanProperty("creaking_active", 17, false, legacyBooleans)); + + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_21_4)) return; + + // Creaking + register(new BooleanProperty("creaking_crumbling", 18, false, legacyBooleans)); } private void registerSerializer(PropertySerializer serializer) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index 1e6a26d..1a9bb9c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -176,6 +176,11 @@ public class NpcTypeImpl implements NpcType { addProperties("wolf_variant"); } } + if (version.isNewerThanOrEquals(ServerVersion.V_1_21_4)) { + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.CREAKING)) { + addProperties("creaking_crumbling"); + } + } return new NpcTypeImpl(name, type, hologramOffset, new HashSet<>(allowedProperties), defaultProperties); } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 39f52b7..78c217e 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -386,6 +386,12 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "breeze", EntityTypes.BREEZE) .setHologramOffset(-0.205)); + + if (!version.isNewerThanOrEquals(ServerVersion.V_1_21_2)) return; + + register(builder(p, "creaking", EntityTypes.CREAKING) + .setHologramOffset(0.725) + .addProperties("creaking_active")); } public Collection getAll() { -- 2.45.2 From e20bd9ba57a0b6722206d1bcb12b936649ba211c Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Thu, 12 Dec 2024 16:12:52 +0400 Subject: [PATCH 04/56] fix: multiple polar bear npc type registrations --- .../main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 78c217e..ebc12e0 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -205,9 +205,6 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { .setHologramOffset(-0.025) .addEquipmentProperties()); - register(builder(p, "polar_bear", EntityTypes.POLAR_BEAR) - .setHologramOffset(-0.575)); - register(builder(p, "stray", EntityTypes.STRAY) .setHologramOffset(0.015) .addEquipmentProperties()); -- 2.45.2 From f8d5700b9a188a870689faad6a762927a3e92c08 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Fri, 13 Dec 2024 00:57:36 +0100 Subject: [PATCH 05/56] make set property private on ArmorStandVehicleEntity --- .../znpcsplus/entity/ArmorStandVehicleEntity.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java index 0bc3886..ff53417 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java @@ -21,9 +21,9 @@ public class ArmorStandVehicleEntity implements PropertyHolder { private final Map, Object> propertyMap = new HashMap<>(); public ArmorStandVehicleEntity(EntityPropertyRegistryImpl propertyRegistry) { - setProperty(propertyRegistry.getByName("small", Boolean.class), true); - setProperty(propertyRegistry.getByName("invisible", Boolean.class), true); - setProperty(propertyRegistry.getByName("base_plate", Boolean.class), false); + _setProperty(propertyRegistry.getByName("small", Boolean.class), true); + _setProperty(propertyRegistry.getByName("invisible", Boolean.class), true); + _setProperty(propertyRegistry.getByName("base_plate", Boolean.class), false); } @SuppressWarnings("unchecked") @@ -37,14 +37,18 @@ public class ArmorStandVehicleEntity implements PropertyHolder { } @SuppressWarnings("unchecked") - @Override - public void setProperty(EntityProperty key, T value) { + private void _setProperty(EntityProperty key, T value) { Object val = value; if (val instanceof ItemStack) val = SpigotConversionUtil.fromBukkitItemStack((ItemStack) val); setProperty((EntityPropertyImpl) key, (T) val); } + @Override + public void setProperty(EntityProperty key, T value) { + throw new UnsupportedOperationException("Cannot set properties on armor stands"); + } + @Override public void setItemProperty(EntityProperty key, ItemStack value) { throw new UnsupportedOperationException("Cannot set item properties on armor stands"); -- 2.45.2 From aed6ee178c38ba8730e802f97ddf2b9fea4d6c45 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Fri, 13 Dec 2024 01:37:53 +0100 Subject: [PATCH 06/56] remove metadata and add direct vehicle support to PacketEntity --- ....java => ArmorStandVehicleProperties.java} | 4 +- .../pyr/znpcsplus/entity/PacketEntity.java | 88 +++++++++---------- .../properties/EntitySittingProperty.java | 32 ++----- .../pyr/znpcsplus/hologram/HologramImpl.java | 22 ++--- .../pyr/znpcsplus/hologram/HologramItem.java | 12 ++- .../pyr/znpcsplus/hologram/HologramLine.java | 10 +-- .../pyr/znpcsplus/hologram/HologramText.java | 5 +- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 10 +-- .../pyr/znpcsplus/packets/PacketFactory.java | 1 + .../znpcsplus/packets/V1_8PacketFactory.java | 6 ++ 10 files changed, 85 insertions(+), 105 deletions(-) rename plugin/src/main/java/lol/pyr/znpcsplus/entity/{ArmorStandVehicleEntity.java => ArmorStandVehicleProperties.java} (94%) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleProperties.java similarity index 94% rename from plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java rename to plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleProperties.java index ff53417..4e4605a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleProperties.java @@ -16,11 +16,11 @@ import java.util.Set; * This entity is used to make the NPC sit on an invisible armor stand. *

*/ -public class ArmorStandVehicleEntity implements PropertyHolder { +public class ArmorStandVehicleProperties implements PropertyHolder { private final Map, Object> propertyMap = new HashMap<>(); - public ArmorStandVehicleEntity(EntityPropertyRegistryImpl propertyRegistry) { + public ArmorStandVehicleProperties(EntityPropertyRegistryImpl propertyRegistry) { _setProperty(propertyRegistry.getByName("small", Boolean.class), true); _setProperty(propertyRegistry.getByName("invisible", Boolean.class), true); _setProperty(propertyRegistry.getByName("base_plate", Boolean.class), false); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 5687adc..255a201 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -4,17 +4,15 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import lol.pyr.znpcsplus.ZNpcsPlusBootstrap; import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.reflection.Reflections; import lol.pyr.znpcsplus.util.NpcLocation; +import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.Collection; -import java.util.HashMap; import java.util.Set; import java.util.UUID; @@ -22,17 +20,19 @@ public class PacketEntity implements PropertyHolder { private final PacketFactory packetFactory; private final PropertyHolder properties; + private final Viewable viewable; private final int entityId; private final UUID uuid; private final EntityType type; private NpcLocation location; - private final HashMap metadata = new HashMap<>(); + private PacketEntity vehicle; - public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, EntityType type, NpcLocation location) { + public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, Viewable viewable, EntityType type, NpcLocation location) { this.packetFactory = packetFactory; this.properties = properties; + this.viewable = viewable; this.entityId = reserveEntityID(); this.uuid = UUID.randomUUID(); this.type = type; @@ -55,31 +55,59 @@ public class PacketEntity implements PropertyHolder { return type; } - public void setLocation(NpcLocation location, Collection viewers) { + public void setLocation(NpcLocation location) { this.location = location; - for (Player viewer : viewers) packetFactory.teleportEntity(viewer, this); + if (vehicle != null) { + vehicle.setLocation(location.withY(location.getY() - 0.9)); + return; + } + for (Player viewer : viewable.getViewers()) packetFactory.teleportEntity(viewer, this); } public void spawn(Player player) { if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties); else packetFactory.spawnEntity(player, this, properties); + if (vehicle != null) { + vehicle.spawn(player); + packetFactory.setPassenger(player, vehicle, this); + } } public void setHeadRotation(Player player, float yaw, float pitch) { packetFactory.sendHeadRotation(player, this, yaw, pitch); } - public void despawn(Player player) { - packetFactory.destroyEntity(player, this, properties); - if (hasMetadata("ridingVehicle")) { - try { - PacketEntity armorStand = (PacketEntity) getMetadata("ridingVehicle"); - armorStand.despawn(player); - } catch (Exception e) { - //noinspection CallToPrintStackTrace - e.printStackTrace(); + public PacketEntity getVehicle() { + return vehicle; + } + + public Viewable getViewable() { + return viewable; + } + + public void setVehicle(PacketEntity vehicle) { + // remove old vehicle + if (this.vehicle != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassenger(player, this.vehicle, null); + this.vehicle.despawn(player); + packetFactory.teleportEntity(player, this); } } + + this.vehicle = vehicle; + if (this.vehicle == null) return; + + vehicle.setLocation(location.withY(location.getY() - 0.9)); + for (Player player : viewable.getViewers()) { + vehicle.spawn(player); + packetFactory.setPassenger(player, vehicle, this); + } + } + + public void despawn(Player player) { + packetFactory.destroyEntity(player, this, properties); + if (vehicle != null) vehicle.despawn(player); } public void refreshMeta(Player player) { @@ -129,32 +157,4 @@ public class PacketEntity implements PropertyHolder { public Set> getAppliedProperties() { return properties.getAppliedProperties(); } - - public void setMetadata(String key, Object value) { - metadata.put(key, value); - } - - public Object getMetadata(String key) { - return metadata.get(key); - } - - public T getMetadata(String key, Class type) { - try { - return type.cast(metadata.get(key)); - } catch (ClassCastException e) { - return null; - } - } - - public void removeMetadata(String key) { - metadata.remove(key); - } - - public boolean hasMetadata(String key) { - return metadata.containsKey(key); - } - - public void clearMetadata() { - metadata.clear(); - } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java index fb8fc2c..e9b66c5 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java @@ -1,10 +1,8 @@ package lol.pyr.znpcsplus.entity.properties; -import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers; -import lol.pyr.znpcsplus.entity.ArmorStandVehicleEntity; +import lol.pyr.znpcsplus.entity.ArmorStandVehicleProperties; import lol.pyr.znpcsplus.entity.EntityPropertyImpl; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.entity.PacketEntity; @@ -26,28 +24,12 @@ public class EntitySittingProperty extends EntityPropertyImpl { @Override public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { boolean sitting = entity.getProperty(this); - if (sitting) { - ArmorStandVehicleEntity vehicleEntity = new ArmorStandVehicleEntity(propertyRegistry); - PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, vehicleEntity, EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); - vehiclePacketEntity.spawn(player); - entity.setMetadata("ridingVehicle", vehiclePacketEntity); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSetPassengers( - vehiclePacketEntity.getEntityId(), - new int[]{entity.getEntityId()} - )); - } else { - if (entity.hasMetadata("ridingVehicle")) { - PacketEntity vehicleEntity = (PacketEntity) entity.getMetadata("ridingVehicle"); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSetPassengers( - vehicleEntity.getEntityId(), - new int[]{} - )); - vehicleEntity.despawn(player); - entity.removeMetadata("ridingVehicle"); - // Send a packet to reset the npc's position - packetFactory.teleportEntity(player, entity); - } + if (sitting) if (entity.getVehicle() == null) { + PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, new ArmorStandVehicleProperties(propertyRegistry), + entity.getViewable(), EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); + entity.setVehicle(vehiclePacketEntity); + } else if (entity.getVehicle() != null) { + entity.setVehicle(null); } } - } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java index 4092e92..c1a4556 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java @@ -38,9 +38,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void addTextLineComponent(Component line) { - HologramText newLine = new HologramText(propertyRegistry, packetFactory, null, line); + HologramText newLine = new HologramText(this, propertyRegistry, packetFactory, null, line); lines.add(newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -57,9 +57,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void addItemLinePEStack(ItemStack item) { - HologramItem newLine = new HologramItem(propertyRegistry, packetFactory, null, item); + HologramItem newLine = new HologramItem(this, propertyRegistry, packetFactory, null, item); lines.add(newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -99,9 +99,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void insertTextLineComponent(int index, Component line) { - HologramText newLine = new HologramText(propertyRegistry, packetFactory, null, line); + HologramText newLine = new HologramText(this, propertyRegistry, packetFactory, null, line); lines.add(index, newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -114,9 +114,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void insertItemLinePEStack(int index, ItemStack item) { - HologramItem newLine = new HologramItem(propertyRegistry, packetFactory, null, item); + HologramItem newLine = new HologramItem(this, propertyRegistry, packetFactory, null, item); lines.add(index, newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -172,14 +172,10 @@ public class HologramImpl extends Viewable implements Hologram { } private void relocateLines() { - relocateLines(null); - } - - private void relocateLines(HologramLine newLine) { final double lineSpacing = configManager.getConfig().lineSpacing(); double height = location.getY() + (lines.size() - 1) * lineSpacing + getOffset(); for (HologramLine line : lines) { - line.setLocation(location.withY(height), line == newLine ? Collections.emptySet() : getViewers()); + line.setLocation(location.withY(height)); height -= lineSpacing; } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java index c25e434..da17da4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java @@ -15,13 +15,11 @@ import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.util.NpcLocation; -import org.bukkit.entity.Player; - -import java.util.Collection; +import lol.pyr.znpcsplus.util.Viewable; public class HologramItem extends HologramLine { - public HologramItem(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, ItemStack item) { - super(item, packetFactory, EntityTypes.ITEM, location); + public HologramItem(Viewable viewable, EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, ItemStack item) { + super(viewable, item, packetFactory, EntityTypes.ITEM, location); addProperty(propertyRegistry.getByName("holo_item")); } @@ -33,8 +31,8 @@ public class HologramItem extends HologramLine { } @Override - public void setLocation(NpcLocation location, Collection viewers) { - super.setLocation(location.withY(location.getY() + 2.05), viewers); + public void setLocation(NpcLocation location) { + super.setLocation(location.withY(location.getY() + 2.05)); } public static boolean ensureValidItemInput(String in) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java index 3b572e5..79e45c1 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java @@ -7,10 +7,10 @@ import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.util.NpcLocation; +import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -19,9 +19,9 @@ public class HologramLine implements PropertyHolder { private final PacketEntity entity; private final Set> properties; - public HologramLine(M value, PacketFactory packetFactory, EntityType type, NpcLocation location) { + public HologramLine(Viewable viewable, M value, PacketFactory packetFactory, EntityType type, NpcLocation location) { this.value = value; - this.entity = new PacketEntity(packetFactory, this, type, location); + this.entity = new PacketEntity(packetFactory, this, viewable, type, location); this.properties = new HashSet<>(); } @@ -45,8 +45,8 @@ public class HologramLine implements PropertyHolder { entity.despawn(player); } - public void setLocation(NpcLocation location, Collection viewers) { - entity.setLocation(location, viewers); + public void setLocation(NpcLocation location) { + entity.setLocation(location); } public int getEntityId() { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java index 47e5e91..40c8995 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java @@ -5,6 +5,7 @@ import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.util.NpcLocation; +import lol.pyr.znpcsplus.util.Viewable; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @@ -12,8 +13,8 @@ public class HologramText extends HologramLine { private static final Component BLANK = Component.text("%blank%"); - public HologramText(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) { - super(text, packetFactory, EntityTypes.ARMOR_STAND, location); + public HologramText(Viewable viewable, EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) { + super(viewable, text, packetFactory, EntityTypes.ARMOR_STAND, location); addProperty(propertyRegistry.getByName("name")); addProperty(propertyRegistry.getByName("invisible")); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index 0a5695a..e29948a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -48,14 +48,14 @@ public class NpcImpl extends Viewable implements Npc { this.type = type; this.location = location; this.uuid = uuid; - entity = new PacketEntity(packetFactory, this, type.getType(), location); + entity = new PacketEntity(packetFactory, this, this, type.getType(), location); hologram = new HologramImpl(propertyRegistry, configManager, packetFactory, textSerializer, location.withY(location.getY() + type.getHologramOffset())); } public void setType(NpcTypeImpl type) { UNSAFE_hideAll(); this.type = type; - entity = new PacketEntity(packetFactory, this, type.getType(), entity.getLocation()); + entity = new PacketEntity(packetFactory, this, this, type.getType(), entity.getLocation()); hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); UNSAFE_showAll(); } @@ -85,11 +85,7 @@ public class NpcImpl extends Viewable implements Npc { public void setLocation(NpcLocation location) { this.location = location; - entity.setLocation(location, getViewers()); - if (entity.hasMetadata("ridingVehicle")) { - PacketEntity armorStand = (PacketEntity) entity.getMetadata("ridingVehicle"); - armorStand.setLocation(location.withY(location.getY() - 0.9), getViewers()); - } + entity.setLocation(location); hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 98cc382..824ef31 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -24,4 +24,5 @@ public interface PacketFactory { void sendMetadata(Player player, PacketEntity entity, List data); void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); void sendHandSwing(Player player, PacketEntity entity, boolean offHand); + void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index 74490ce..e1134f8 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -153,6 +153,12 @@ public class V1_8PacketFactory implements PacketFactory { sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), Collections.singletonList(equipment))); } + @Override + public void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger) { + sendPacket(player, new WrapperPlayServerSetPassengers(vehicle.getEntityId(), + passenger == null ? new int[] {} : new int[] {passenger.getEntityId()})); + } + protected void sendPacket(Player player, PacketWrapper packet) { packetEvents.getPlayerManager().sendPacket(player, packet); } -- 2.45.2 From 670bc9623b3a48ceae9fe344f13aed6f5cf5c1b2 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Fri, 13 Dec 2024 01:38:19 +0100 Subject: [PATCH 07/56] make entity_sitting only available to player since it doesn't really do anything for any other npc type --- plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 2 +- .../main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index 1a9bb9c..bfb259e 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -118,7 +118,7 @@ public class NpcTypeImpl implements NpcType { "potion_color", "potion_ambient", "display_name", "permission_required", "player_knockback", "player_knockback_exempt_permission", "player_knockback_distance", "player_knockback_vertical", "player_knockback_horizontal", "player_knockback_cooldown", "player_knockback_sound", "player_knockback_sound_name", - "player_knockback_sound_volume", "player_knockback_sound_pitch", "entity_sitting"); + "player_knockback_sound_volume", "player_knockback_sound_pitch"); if (!type.equals(EntityTypes.PLAYER)) addProperties("dinnerbone"); // TODO: make this look nicer after completing the rest of the properties if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow"); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 78c217e..742ea0a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -36,7 +36,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "player", EntityTypes.PLAYER) .setHologramOffset(-0.15D) .addEquipmentProperties() - .addProperties("skin_cape", "skin_jacket", "skin_left_sleeve", "skin_right_sleeve", "skin_left_leg", "skin_right_leg", "skin_hat", "shoulder_entity_left", "shoulder_entity_right", "force_body_rotation") + .addProperties("skin_cape", "skin_jacket", "skin_left_sleeve", "skin_right_sleeve", "skin_left_leg", "skin_right_leg", "skin_hat", "shoulder_entity_left", "shoulder_entity_right", "force_body_rotation", "entity_sitting") .addDefaultProperty("skin_cape", true) .addDefaultProperty("skin_jacket", true) .addDefaultProperty("skin_left_sleeve", true) -- 2.45.2 From f5d1a1914aaf7aa55d2bec4c86d8eac655294d52 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 13 Dec 2024 10:54:29 +0400 Subject: [PATCH 08/56] chore: added entity_sitting property to more npc types --- .../znpcsplus/npc/NpcTypeRegistryImpl.java | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 2878880..2a9e775 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -82,7 +82,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "enderman", EntityTypes.ENDERMAN) .setHologramOffset(0.925) - .addProperties("enderman_held_block", "enderman_screaming", "enderman_staring")); + .addProperties("enderman_held_block", "enderman_screaming", "enderman_staring", "entity_sitting")); register(builder(p, "endermite", EntityTypes.ENDERMITE) .setHologramOffset(-1.675)); @@ -93,7 +93,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "giant", EntityTypes.GIANT) .setHologramOffset(10.025) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "guardian", EntityTypes.GUARDIAN) .setHologramOffset(-1.125) @@ -133,7 +134,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "skeleton", EntityTypes.SKELETON) .setHologramOffset(0.015) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "skeleton_horse", EntityTypes.SKELETON_HORSE) .setHologramOffset(-0.375)); @@ -169,14 +171,16 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "zombie", EntityTypes.ZOMBIE) .setHologramOffset(-0.025) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "zombie_horse", EntityTypes.ZOMBIE_HORSE) .setHologramOffset(-0.375)); register(builder(p, "zombified_piglin", EntityTypes.ZOMBIFIED_PIGLIN) .setHologramOffset(-0.025) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); if (!version.isNewerThanOrEquals(ServerVersion.V_1_9)) return; @@ -203,14 +207,17 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "husk", EntityTypes.HUSK) .setHologramOffset(-0.025) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "stray", EntityTypes.STRAY) .setHologramOffset(0.015) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "evoker", EntityTypes.EVOKER) - .setHologramOffset(-0.025)); + .setHologramOffset(-0.025) + .addProperties("entity_sitting")); register(builder(p, "llama", EntityTypes.LLAMA) .setHologramOffset(-0.105) @@ -222,20 +229,23 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "vindicator", EntityTypes.VINDICATOR) .setHologramOffset(-0.025) - .addProperties("celebrating")); + .addProperties("celebrating", "entity_sitting")); register(builder(p, "wither_skeleton", EntityTypes.WITHER_SKELETON) .setHologramOffset(0.425) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "zombie_villager", EntityTypes.ZOMBIE_VILLAGER) .setHologramOffset(-0.025) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); if (!version.isNewerThanOrEquals(ServerVersion.V_1_12)) return; register(builder(p, "illusioner", EntityTypes.ILLUSIONER) - .setHologramOffset(-0.025)); + .setHologramOffset(-0.025) + .addProperties("entity_sitting")); register(builder(p, "parrot", EntityTypes.PARROT) .setHologramOffset(-1.075) @@ -252,7 +262,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "drowned", EntityTypes.DROWNED) .setHologramOffset(-0.025) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "phantom", EntityTypes.PHANTOM) .setHologramOffset(-1.475)); @@ -288,7 +299,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "pillager", EntityTypes.PILLAGER) .setHologramOffset(-0.025) .addHandProperties() - .addProperties("pillager_charging")); + .addProperties("pillager_charging", "entity_sitting")); register(builder(p, "ravager", EntityTypes.RAVAGER) .setHologramOffset(0.225)); @@ -316,11 +327,12 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "piglin", EntityTypes.PIGLIN) .setHologramOffset(-0.025) .addEquipmentProperties() - .addProperties("piglin_baby", "piglin_charging_crossbow", "piglin_dancing")); + .addProperties("piglin_baby", "piglin_charging_crossbow", "piglin_dancing", "entity_sitting")); register(builder(p, "piglin_brute", EntityTypes.PIGLIN_BRUTE) .setHologramOffset(-0.025) - .addEquipmentProperties()); + .addEquipmentProperties() + .addProperties("entity_sitting")); register(builder(p, "strider", EntityTypes.STRIDER) .setHologramOffset(-0.275) @@ -379,7 +391,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "bogged", EntityTypes.BOGGED) .setHologramOffset(0.015) - .addProperties("bogged_sheared")); + .addProperties("bogged_sheared", "entity_sitting")); register(builder(p, "breeze", EntityTypes.BREEZE) .setHologramOffset(-0.205)); @@ -388,7 +400,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "creaking", EntityTypes.CREAKING) .setHologramOffset(0.725) - .addProperties("creaking_active")); + .addProperties("creaking_active", "entity_sitting")); } public Collection getAll() { -- 2.45.2 From 41244fb86bb679dece30c95993b438a349662841 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 13 Dec 2024 10:58:52 +0400 Subject: [PATCH 09/56] fix: disabling entity_sitting property --- .../entity/properties/EntitySittingProperty.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java index e9b66c5..5e59221 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java @@ -24,10 +24,12 @@ public class EntitySittingProperty extends EntityPropertyImpl { @Override public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { boolean sitting = entity.getProperty(this); - if (sitting) if (entity.getVehicle() == null) { - PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, new ArmorStandVehicleProperties(propertyRegistry), - entity.getViewable(), EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); - entity.setVehicle(vehiclePacketEntity); + if (sitting) { + if (entity.getVehicle() == null) { + PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, new ArmorStandVehicleProperties(propertyRegistry), + entity.getViewable(), EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); + entity.setVehicle(vehiclePacketEntity); + } } else if (entity.getVehicle() != null) { entity.setVehicle(null); } -- 2.45.2 From 79c0897de9b435cfd670b14c57ad52ccf3f4b6fb Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 13 Dec 2024 11:02:56 +0400 Subject: [PATCH 10/56] fix: remove entity_sitting property from creaking --- .../main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 2a9e775..5a23efc 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -400,7 +400,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "creaking", EntityTypes.CREAKING) .setHologramOffset(0.725) - .addProperties("creaking_active", "entity_sitting")); + .addProperties("creaking_active")); } public Collection getAll() { -- 2.45.2 From b107a3b011d84c5e350184b6ef88487d629fb8d2 Mon Sep 17 00:00:00 2001 From: Dablakbandit Date: Sat, 14 Dec 2024 21:49:21 +1300 Subject: [PATCH 11/56] Add passengers to npc api Add passengers to npc api & implementation Add jetbrains annotations to api to tag with nullables --- api/build.gradle | 4 ++ .../java/lol/pyr/znpcsplus/api/npc/Npc.java | 22 +++++++++++ .../pyr/znpcsplus/entity/PacketEntity.java | 38 +++++++++++++++++-- .../switchserver/SwitchServerAction.java | 2 +- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 15 ++++++++ .../pyr/znpcsplus/packets/PacketFactory.java | 2 +- .../znpcsplus/packets/V1_8PacketFactory.java | 5 +-- 7 files changed, 80 insertions(+), 8 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 349cf17..381069e 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,6 +8,10 @@ java { withJavadocJar() } +dependencies { + compileOnly 'org.jetbrains:annotations:26.0.1' +} + publishing { publications { mavenJava(MavenPublication) { diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java index 6081060..9302b4b 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java @@ -6,6 +6,7 @@ import lol.pyr.znpcsplus.api.interaction.InteractionAction; import lol.pyr.znpcsplus.util.NpcLocation; import org.bukkit.World; import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Set; @@ -174,4 +175,25 @@ public interface Npc extends PropertyHolder { * @param offHand Should the hand be the offhand */ void swingHand(boolean offHand); + + /** + * Gets the passengers of this npc + * @return The list of entity ids of the passengers + */ + + @Nullable List getPassengers(); + + /** + * Adds a passenger to this npc + * @param entityId The entity id of the passenger to add + */ + void addPassenger(int entityId); + + /** + * Removes a passenger from this npc + * @param entityId The entity id of the passenger to remove + */ + void removePassenger(int entityId); + + } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 255a201..8b2fe03 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -13,8 +13,11 @@ import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.UUID; +import java.util.stream.IntStream; public class PacketEntity implements PropertyHolder { private final PacketFactory packetFactory; @@ -28,6 +31,7 @@ public class PacketEntity implements PropertyHolder { private NpcLocation location; private PacketEntity vehicle; + private List passengers; public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, Viewable viewable, EntityType type, NpcLocation location) { this.packetFactory = packetFactory; @@ -69,7 +73,10 @@ public class PacketEntity implements PropertyHolder { else packetFactory.spawnEntity(player, this, properties); if (vehicle != null) { vehicle.spawn(player); - packetFactory.setPassenger(player, vehicle, this); + packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + } + if(passengers != null) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } } @@ -89,7 +96,7 @@ public class PacketEntity implements PropertyHolder { // remove old vehicle if (this.vehicle != null) { for (Player player : viewable.getViewers()) { - packetFactory.setPassenger(player, this.vehicle, null); + packetFactory.setPassengers(player, this.vehicle.getEntityId()); this.vehicle.despawn(player); packetFactory.teleportEntity(player, this); } @@ -101,7 +108,32 @@ public class PacketEntity implements PropertyHolder { vehicle.setLocation(location.withY(location.getY() - 0.9)); for (Player player : viewable.getViewers()) { vehicle.spawn(player); - packetFactory.setPassenger(player, vehicle, this); + packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + } + } + + public List getPassengers() { + return passengers; + } + + public void addPassenger(int entityId) { + if (passengers == null) { + passengers = new ArrayList<>(); + } + passengers.add(entityId); + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + } + } + + public void removePassenger(int entityId) { + if (passengers == null) return; + passengers.remove(entityId); + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + } + if (passengers.isEmpty()) { + passengers = null; } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java index 94fc807..ca89839 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java @@ -32,7 +32,7 @@ public class SwitchServerAction extends InteractionActionImpl { .hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("Click to edit this action", NamedTextColor.GRAY))) .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND, - "/" + context.getLabel() + " action edit " + id + " " + index + " switcserver " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + server)) + "/" + context.getLabel() + " action edit " + id + " " + index + " switchserver " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + server)) .append(Component.text(" | ", NamedTextColor.GRAY)) .append(Component.text("[DELETE]", NamedTextColor.RED) .hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index e29948a..39c4c4a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -246,4 +246,19 @@ public class NpcImpl extends Viewable implements Npc { public void swingHand(boolean offHand) { for (Player viewer : getViewers()) entity.swingHand(viewer, offHand); } + + @Override + public @Nullable List getPassengers() { + return entity.getPassengers(); + } + + @Override + public void addPassenger(int entityId) { + entity.addPassenger(entityId); + } + + @Override + public void removePassenger(int entityId) { + entity.removePassenger(entityId); + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 824ef31..aaea42a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -24,5 +24,5 @@ public interface PacketFactory { void sendMetadata(Player player, PacketEntity entity, List data); void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); void sendHandSwing(Player player, PacketEntity entity, boolean offHand); - void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger); + void setPassengers(Player player, int vehicle, int... passengers); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index e1134f8..2637b83 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -154,9 +154,8 @@ public class V1_8PacketFactory implements PacketFactory { } @Override - public void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger) { - sendPacket(player, new WrapperPlayServerSetPassengers(vehicle.getEntityId(), - passenger == null ? new int[] {} : new int[] {passenger.getEntityId()})); + public void setPassengers(Player player, int vehicleEntityId, int... passengers) { + sendPacket(player, new WrapperPlayServerSetPassengers(vehicleEntityId, passengers)); } protected void sendPacket(Player player, PacketWrapper packet) { -- 2.45.2 From a49c43c04ec350067d98e3e5288110291fff2416 Mon Sep 17 00:00:00 2001 From: Dablakbandit Date: Sat, 14 Dec 2024 23:24:26 +1300 Subject: [PATCH 12/56] Update wiki.vg links --- README.md | 2 +- .../entity/EntityPropertyRegistryImpl.java | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0d0eeb0..49b1a42 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Open an issue in the GitHub [issue tracker](https://github.com/Pyrbu/ZNPCsPlus/i ## Credits - [PacketEvents 2.0](https://github.com/retrooper/packetevents) - Packet library -- [wiki.vg](https://wiki.vg/Main_Page) - Minecraft protocol documentation +- [Minecraft Wiki Protocol (formally wiki.vg)](https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Main_Page) - Minecraft protocol documentation - [gson](https://github.com/google/gson) - JSON parsing library made by Google - [Mineskin.org](https://mineskin.org/) - Website for raw skin file uploads - [adventure](https://docs.advntr.dev/) - Minecraft text api diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 6e02d58..a10ce9f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -32,18 +32,19 @@ import java.util.*; import java.util.stream.Collectors; /** - * 1.8 ... - * 1.9 ... - * 1.10 ... - * 1.11 ... - * 1.12 ... - * 1.13 ... - * 1.14 ... - * 1.15 ... - * 1.16 ... - * 1.17 ... - * 1.18-1.19 ... - * 1.20 ... + * 1.8 ... + * 1.9 ... + * 1.10 ... + * 1.11 ... + * 1.12 ... + * 1.13 ... + * 1.14 ... + * 1.15 ... + * 1.16 ... + * 1.17 ... + * 1.18-1.19 ... + * 1.20 ... + * 1.21 ... */ @SuppressWarnings("unchecked") public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { -- 2.45.2 From cea0ffb8ac694e527c730c6b3e8367130937450c Mon Sep 17 00:00:00 2001 From: Dablakbandit Date: Sun, 15 Dec 2024 01:06:09 +1300 Subject: [PATCH 13/56] Add vehicles by entity id Add vehicles by entity id for cases where the entity is an existing server npc --- .../java/lol/pyr/znpcsplus/api/npc/Npc.java | 12 +++++++ .../pyr/znpcsplus/entity/PacketEntity.java | 34 +++++++++++++++++-- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 12 +++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java index 9302b4b..9546ed4 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java @@ -196,4 +196,16 @@ public interface Npc extends PropertyHolder { void removePassenger(int entityId); + /** + * Gets the vehicle entity id of this npc + * @return The entity id of the vehicle + */ + @Nullable Integer getVehicleId(); + + /** + * Sets the vehicle id of this npc + * @param vehicleId The entity id of the vehicle + */ + void setVehicleId(Integer vehicleId); + } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 8b2fe03..cdee0e8 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -31,6 +31,7 @@ public class PacketEntity implements PropertyHolder { private NpcLocation location; private PacketEntity vehicle; + private Integer vehicleId; private List passengers; public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, Viewable viewable, EntityType type, NpcLocation location) { @@ -71,9 +72,8 @@ public class PacketEntity implements PropertyHolder { public void spawn(Player player) { if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties); else packetFactory.spawnEntity(player, this, properties); - if (vehicle != null) { - vehicle.spawn(player); - packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + if (vehicleId != null) { + packetFactory.setPassengers(player, vehicleId, this.getEntityId()); } if(passengers != null) { packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); @@ -92,6 +92,26 @@ public class PacketEntity implements PropertyHolder { return viewable; } + public void setVehicleId(Integer vehicleId) { + if (this.vehicle != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.vehicle.getEntityId()); + this.vehicle.despawn(player); + packetFactory.teleportEntity(player, this); + } + } else if (this.vehicleId != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.vehicleId); + } + } + this.vehicleId = vehicleId; + if (vehicleId == null) return; + + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.getEntityId(), vehicleId); + } + } + public void setVehicle(PacketEntity vehicle) { // remove old vehicle if (this.vehicle != null) { @@ -100,6 +120,10 @@ public class PacketEntity implements PropertyHolder { this.vehicle.despawn(player); packetFactory.teleportEntity(player, this); } + } else if (this.vehicleId != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.vehicleId); + } } this.vehicle = vehicle; @@ -112,6 +136,10 @@ public class PacketEntity implements PropertyHolder { } } + public Integer getVehicleId() { + return vehicleId; + } + public List getPassengers() { return passengers; } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index 39c4c4a..fafe780 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -261,4 +261,16 @@ public class NpcImpl extends Viewable implements Npc { public void removePassenger(int entityId) { entity.removePassenger(entityId); } + + @Override + public @Nullable Integer getVehicleId() { + return entity.getVehicleId(); + } + + @Override + public void setVehicleId(Integer vehicleId) { + entity.setVehicleId(vehicleId); + } + + } -- 2.45.2 From ad50d311940035bdcfad7793c38b0f900bc99f59 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 15 Dec 2024 10:36:33 +0100 Subject: [PATCH 14/56] move annotations dependency to main gradle file because both subprojects use it --- api/build.gradle | 4 ---- build.gradle | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 381069e..349cf17 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,10 +8,6 @@ java { withJavadocJar() } -dependencies { - compileOnly 'org.jetbrains:annotations:26.0.1' -} - publishing { publications { mavenJava(MavenPublication) { diff --git a/build.gradle b/build.gradle index f3ef9f5..1ec5bfc 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,7 @@ subprojects { } dependencies { + compileOnly "org.jetbrains:annotations:26.0.1" compileOnly "org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT" } -- 2.45.2 From aa5e62ab0d63c83ab8b73e7b329b7dd416427616 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 15 Dec 2024 10:40:28 +0100 Subject: [PATCH 15/56] make passenger list not null because its more clean to use the api that way --- .../lol/pyr/znpcsplus/entity/PacketEntity.java | 18 +++++++----------- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 5 ++--- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index cdee0e8..dc06d00 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -13,11 +13,7 @@ import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.stream.IntStream; +import java.util.*; public class PacketEntity implements PropertyHolder { private final PacketFactory packetFactory; @@ -75,8 +71,8 @@ public class PacketEntity implements PropertyHolder { if (vehicleId != null) { packetFactory.setPassengers(player, vehicleId, this.getEntityId()); } - if(passengers != null) { - packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + if (passengers != null) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } } @@ -108,7 +104,7 @@ public class PacketEntity implements PropertyHolder { if (vehicleId == null) return; for (Player player : viewable.getViewers()) { - packetFactory.setPassengers(player, this.getEntityId(), vehicleId); + packetFactory.setPassengers(player, this.getEntityId(), vehicleId); } } @@ -141,7 +137,7 @@ public class PacketEntity implements PropertyHolder { } public List getPassengers() { - return passengers; + return passengers == null ? Collections.emptyList() : passengers; } public void addPassenger(int entityId) { @@ -150,7 +146,7 @@ public class PacketEntity implements PropertyHolder { } passengers.add(entityId); for (Player player : viewable.getViewers()) { - packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } } @@ -158,7 +154,7 @@ public class PacketEntity implements PropertyHolder { if (passengers == null) return; passengers.remove(entityId); for (Player player : viewable.getViewers()) { - packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } if (passengers.isEmpty()) { passengers = null; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index fafe780..ad0061f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -20,6 +20,7 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -248,7 +249,7 @@ public class NpcImpl extends Viewable implements Npc { } @Override - public @Nullable List getPassengers() { + public @NotNull List getPassengers() { return entity.getPassengers(); } @@ -271,6 +272,4 @@ public class NpcImpl extends Viewable implements Npc { public void setVehicleId(Integer vehicleId) { entity.setVehicleId(vehicleId); } - - } -- 2.45.2 From 31518c213632e5a351b745135b86582a6eb7db9d Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 15 Dec 2024 10:45:25 +0100 Subject: [PATCH 16/56] remove whitespace --- api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java index 9546ed4..d5e70bb 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java @@ -195,7 +195,6 @@ public interface Npc extends PropertyHolder { */ void removePassenger(int entityId); - /** * Gets the vehicle entity id of this npc * @return The entity id of the vehicle @@ -207,5 +206,4 @@ public interface Npc extends PropertyHolder { * @param vehicleId The entity id of the vehicle */ void setVehicleId(Integer vehicleId); - } -- 2.45.2 From c5bf8dea0b0cb77349311a64162c8cdd7583d844 Mon Sep 17 00:00:00 2001 From: Dablakbandit Date: Sat, 14 Dec 2024 21:49:21 +1300 Subject: [PATCH 17/56] Add passengers to npc api Add passengers to npc api & implementation Add jetbrains annotations to api to tag with nullables --- api/build.gradle | 4 ++ .../java/lol/pyr/znpcsplus/api/npc/Npc.java | 22 +++++++++++ .../pyr/znpcsplus/entity/PacketEntity.java | 38 +++++++++++++++++-- .../switchserver/SwitchServerAction.java | 2 +- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 15 ++++++++ .../pyr/znpcsplus/packets/PacketFactory.java | 2 +- .../znpcsplus/packets/V1_8PacketFactory.java | 5 +-- 7 files changed, 80 insertions(+), 8 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 349cf17..381069e 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,6 +8,10 @@ java { withJavadocJar() } +dependencies { + compileOnly 'org.jetbrains:annotations:26.0.1' +} + publishing { publications { mavenJava(MavenPublication) { diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java index 6081060..9302b4b 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java @@ -6,6 +6,7 @@ import lol.pyr.znpcsplus.api.interaction.InteractionAction; import lol.pyr.znpcsplus.util.NpcLocation; import org.bukkit.World; import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Set; @@ -174,4 +175,25 @@ public interface Npc extends PropertyHolder { * @param offHand Should the hand be the offhand */ void swingHand(boolean offHand); + + /** + * Gets the passengers of this npc + * @return The list of entity ids of the passengers + */ + + @Nullable List getPassengers(); + + /** + * Adds a passenger to this npc + * @param entityId The entity id of the passenger to add + */ + void addPassenger(int entityId); + + /** + * Removes a passenger from this npc + * @param entityId The entity id of the passenger to remove + */ + void removePassenger(int entityId); + + } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 255a201..8b2fe03 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -13,8 +13,11 @@ import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.UUID; +import java.util.stream.IntStream; public class PacketEntity implements PropertyHolder { private final PacketFactory packetFactory; @@ -28,6 +31,7 @@ public class PacketEntity implements PropertyHolder { private NpcLocation location; private PacketEntity vehicle; + private List passengers; public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, Viewable viewable, EntityType type, NpcLocation location) { this.packetFactory = packetFactory; @@ -69,7 +73,10 @@ public class PacketEntity implements PropertyHolder { else packetFactory.spawnEntity(player, this, properties); if (vehicle != null) { vehicle.spawn(player); - packetFactory.setPassenger(player, vehicle, this); + packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + } + if(passengers != null) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } } @@ -89,7 +96,7 @@ public class PacketEntity implements PropertyHolder { // remove old vehicle if (this.vehicle != null) { for (Player player : viewable.getViewers()) { - packetFactory.setPassenger(player, this.vehicle, null); + packetFactory.setPassengers(player, this.vehicle.getEntityId()); this.vehicle.despawn(player); packetFactory.teleportEntity(player, this); } @@ -101,7 +108,32 @@ public class PacketEntity implements PropertyHolder { vehicle.setLocation(location.withY(location.getY() - 0.9)); for (Player player : viewable.getViewers()) { vehicle.spawn(player); - packetFactory.setPassenger(player, vehicle, this); + packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + } + } + + public List getPassengers() { + return passengers; + } + + public void addPassenger(int entityId) { + if (passengers == null) { + passengers = new ArrayList<>(); + } + passengers.add(entityId); + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + } + } + + public void removePassenger(int entityId) { + if (passengers == null) return; + passengers.remove(entityId); + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + } + if (passengers.isEmpty()) { + passengers = null; } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java index 94fc807..ca89839 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/switchserver/SwitchServerAction.java @@ -32,7 +32,7 @@ public class SwitchServerAction extends InteractionActionImpl { .hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("Click to edit this action", NamedTextColor.GRAY))) .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND, - "/" + context.getLabel() + " action edit " + id + " " + index + " switcserver " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + server)) + "/" + context.getLabel() + " action edit " + id + " " + index + " switchserver " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + server)) .append(Component.text(" | ", NamedTextColor.GRAY)) .append(Component.text("[DELETE]", NamedTextColor.RED) .hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index e29948a..39c4c4a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -246,4 +246,19 @@ public class NpcImpl extends Viewable implements Npc { public void swingHand(boolean offHand) { for (Player viewer : getViewers()) entity.swingHand(viewer, offHand); } + + @Override + public @Nullable List getPassengers() { + return entity.getPassengers(); + } + + @Override + public void addPassenger(int entityId) { + entity.addPassenger(entityId); + } + + @Override + public void removePassenger(int entityId) { + entity.removePassenger(entityId); + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 824ef31..aaea42a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -24,5 +24,5 @@ public interface PacketFactory { void sendMetadata(Player player, PacketEntity entity, List data); void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); void sendHandSwing(Player player, PacketEntity entity, boolean offHand); - void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger); + void setPassengers(Player player, int vehicle, int... passengers); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index e1134f8..2637b83 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -154,9 +154,8 @@ public class V1_8PacketFactory implements PacketFactory { } @Override - public void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger) { - sendPacket(player, new WrapperPlayServerSetPassengers(vehicle.getEntityId(), - passenger == null ? new int[] {} : new int[] {passenger.getEntityId()})); + public void setPassengers(Player player, int vehicleEntityId, int... passengers) { + sendPacket(player, new WrapperPlayServerSetPassengers(vehicleEntityId, passengers)); } protected void sendPacket(Player player, PacketWrapper packet) { -- 2.45.2 From 238a1fe2242f917c2a4152d92e4bc914f490abbb Mon Sep 17 00:00:00 2001 From: Dablakbandit Date: Sun, 15 Dec 2024 01:06:09 +1300 Subject: [PATCH 18/56] Add vehicles by entity id Add vehicles by entity id for cases where the entity is an existing server npc --- .../java/lol/pyr/znpcsplus/api/npc/Npc.java | 12 +++++++ .../pyr/znpcsplus/entity/PacketEntity.java | 34 +++++++++++++++++-- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 12 +++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java index 9302b4b..9546ed4 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java @@ -196,4 +196,16 @@ public interface Npc extends PropertyHolder { void removePassenger(int entityId); + /** + * Gets the vehicle entity id of this npc + * @return The entity id of the vehicle + */ + @Nullable Integer getVehicleId(); + + /** + * Sets the vehicle id of this npc + * @param vehicleId The entity id of the vehicle + */ + void setVehicleId(Integer vehicleId); + } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 8b2fe03..cdee0e8 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -31,6 +31,7 @@ public class PacketEntity implements PropertyHolder { private NpcLocation location; private PacketEntity vehicle; + private Integer vehicleId; private List passengers; public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, Viewable viewable, EntityType type, NpcLocation location) { @@ -71,9 +72,8 @@ public class PacketEntity implements PropertyHolder { public void spawn(Player player) { if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties); else packetFactory.spawnEntity(player, this, properties); - if (vehicle != null) { - vehicle.spawn(player); - packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + if (vehicleId != null) { + packetFactory.setPassengers(player, vehicleId, this.getEntityId()); } if(passengers != null) { packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); @@ -92,6 +92,26 @@ public class PacketEntity implements PropertyHolder { return viewable; } + public void setVehicleId(Integer vehicleId) { + if (this.vehicle != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.vehicle.getEntityId()); + this.vehicle.despawn(player); + packetFactory.teleportEntity(player, this); + } + } else if (this.vehicleId != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.vehicleId); + } + } + this.vehicleId = vehicleId; + if (vehicleId == null) return; + + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.getEntityId(), vehicleId); + } + } + public void setVehicle(PacketEntity vehicle) { // remove old vehicle if (this.vehicle != null) { @@ -100,6 +120,10 @@ public class PacketEntity implements PropertyHolder { this.vehicle.despawn(player); packetFactory.teleportEntity(player, this); } + } else if (this.vehicleId != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassengers(player, this.vehicleId); + } } this.vehicle = vehicle; @@ -112,6 +136,10 @@ public class PacketEntity implements PropertyHolder { } } + public Integer getVehicleId() { + return vehicleId; + } + public List getPassengers() { return passengers; } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index 39c4c4a..fafe780 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -261,4 +261,16 @@ public class NpcImpl extends Viewable implements Npc { public void removePassenger(int entityId) { entity.removePassenger(entityId); } + + @Override + public @Nullable Integer getVehicleId() { + return entity.getVehicleId(); + } + + @Override + public void setVehicleId(Integer vehicleId) { + entity.setVehicleId(vehicleId); + } + + } -- 2.45.2 From ca89bfe32d738c8e03c3eafde3315238ab89082f Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 15 Dec 2024 10:36:33 +0100 Subject: [PATCH 19/56] move annotations dependency to main gradle file because both subprojects use it --- api/build.gradle | 4 ---- build.gradle | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 381069e..349cf17 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,10 +8,6 @@ java { withJavadocJar() } -dependencies { - compileOnly 'org.jetbrains:annotations:26.0.1' -} - publishing { publications { mavenJava(MavenPublication) { diff --git a/build.gradle b/build.gradle index f3ef9f5..1ec5bfc 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,7 @@ subprojects { } dependencies { + compileOnly "org.jetbrains:annotations:26.0.1" compileOnly "org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT" } -- 2.45.2 From 9477d4b500fa92bb1282f7b9eebd7a608fc7df86 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 15 Dec 2024 10:40:28 +0100 Subject: [PATCH 20/56] make passenger list not null because its more clean to use the api that way --- .../lol/pyr/znpcsplus/entity/PacketEntity.java | 18 +++++++----------- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 5 ++--- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index cdee0e8..dc06d00 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -13,11 +13,7 @@ import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.stream.IntStream; +import java.util.*; public class PacketEntity implements PropertyHolder { private final PacketFactory packetFactory; @@ -75,8 +71,8 @@ public class PacketEntity implements PropertyHolder { if (vehicleId != null) { packetFactory.setPassengers(player, vehicleId, this.getEntityId()); } - if(passengers != null) { - packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + if (passengers != null) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } } @@ -108,7 +104,7 @@ public class PacketEntity implements PropertyHolder { if (vehicleId == null) return; for (Player player : viewable.getViewers()) { - packetFactory.setPassengers(player, this.getEntityId(), vehicleId); + packetFactory.setPassengers(player, this.getEntityId(), vehicleId); } } @@ -141,7 +137,7 @@ public class PacketEntity implements PropertyHolder { } public List getPassengers() { - return passengers; + return passengers == null ? Collections.emptyList() : passengers; } public void addPassenger(int entityId) { @@ -150,7 +146,7 @@ public class PacketEntity implements PropertyHolder { } passengers.add(entityId); for (Player player : viewable.getViewers()) { - packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } } @@ -158,7 +154,7 @@ public class PacketEntity implements PropertyHolder { if (passengers == null) return; passengers.remove(entityId); for (Player player : viewable.getViewers()) { - packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); } if (passengers.isEmpty()) { passengers = null; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index fafe780..ad0061f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -20,6 +20,7 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -248,7 +249,7 @@ public class NpcImpl extends Viewable implements Npc { } @Override - public @Nullable List getPassengers() { + public @NotNull List getPassengers() { return entity.getPassengers(); } @@ -271,6 +272,4 @@ public class NpcImpl extends Viewable implements Npc { public void setVehicleId(Integer vehicleId) { entity.setVehicleId(vehicleId); } - - } -- 2.45.2 From 9303d74f8f313948d681dd67f7465ea690f290b6 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 15 Dec 2024 10:45:25 +0100 Subject: [PATCH 21/56] remove whitespace --- api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java index 9546ed4..d5e70bb 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java @@ -195,7 +195,6 @@ public interface Npc extends PropertyHolder { */ void removePassenger(int entityId); - /** * Gets the vehicle entity id of this npc * @return The entity id of the vehicle @@ -207,5 +206,4 @@ public interface Npc extends PropertyHolder { * @param vehicleId The entity id of the vehicle */ void setVehicleId(Integer vehicleId); - } -- 2.45.2 From 255a938dda2bb86f2123f5695102c6d346ac83f5 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Mon, 16 Dec 2024 22:42:27 +0400 Subject: [PATCH 22/56] feat: file skin type to use files for npc skin --- .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 2 +- .../pyr/znpcsplus/commands/SkinCommand.java | 38 +++++++++++- .../znpcsplus/skin/cache/MojangSkinCache.java | 62 ++++++++++++++++++- .../skin/descriptor/PrefetchedDescriptor.java | 11 ++++ 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index c4d1f9a..42d7624 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -93,7 +93,7 @@ public class ZNpcsPlus { packetEvents.load(); configManager = new ConfigManager(getDataFolder()); - skinCache = new MojangSkinCache(configManager); + skinCache = new MojangSkinCache(configManager, new File(getDataFolder(), "skins")); propertyRegistry = new EntityPropertyRegistryImpl(skinCache, configManager); NpcPropertyRegistryProvider.register(propertyRegistry); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/SkinCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/SkinCommand.java index dc9832f..485b866 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/SkinCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/SkinCommand.java @@ -17,10 +17,14 @@ import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import java.io.File; +import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; public class SkinCommand implements CommandHandler { private final MojangSkinCache skinCache; @@ -90,6 +94,30 @@ public class SkinCommand implements CommandHandler { context.send(Component.text("Invalid url!", NamedTextColor.RED)); } return; + } else if (type.equalsIgnoreCase("file")) { + context.ensureArgsNotEmpty(); + String path = context.dumpAllArgs(); + context.send(Component.text("Fetching skin from file \"" + path + "\"...", NamedTextColor.GREEN)); + PrefetchedDescriptor.fromFile(skinCache, path).exceptionally(e -> { + if (e instanceof FileNotFoundException || e.getCause() instanceof FileNotFoundException) { + context.send(Component.text("A file at the specified path could not be found!", NamedTextColor.RED)); + } else { + context.send(Component.text("An error occurred while fetching the skin from file! Check the console for more details.", NamedTextColor.RED)); + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + return null; + }).thenAccept(skin -> { + if (skin == null) return; + if (skin.getSkin() == null) { + context.send(Component.text("Failed to fetch skin, are you sure the file path is valid?", NamedTextColor.RED)); + return; + } + npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), skin); + npc.respawn(); + context.send(Component.text("The NPC's skin has been set.", NamedTextColor.GREEN)); + }); + return; } context.send(Component.text("Unknown skin type! Please use one of the following: mirror, static, dynamic, url")); } @@ -97,11 +125,19 @@ public class SkinCommand implements CommandHandler { @Override public List suggest(CommandContext context) throws CommandExecutionException { if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); - if (context.argSize() == 2) return context.suggestLiteral("mirror", "static", "dynamic", "url"); + if (context.argSize() == 2) return context.suggestLiteral("mirror", "static", "dynamic", "url", "file"); if (context.matchSuggestion("*", "static")) return context.suggestPlayers(); if (context.argSize() == 3 && context.matchSuggestion("*", "url")) { return context.suggestLiteral("slim", "classic"); } + if (context.argSize() == 3 && context.matchSuggestion("*", "file")) { + if (skinCache.getSkinsFolder().exists()) { + File[] files = skinCache.getSkinsFolder().listFiles(); + if (files != null) { + return Arrays.stream(files).map(File::getName).collect(Collectors.toList()); + } + } + } return Collections.emptyList(); } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java index 2a54509..faef8f5 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java @@ -14,6 +14,7 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; @@ -26,9 +27,12 @@ public class MojangSkinCache { private final Map cache = new ConcurrentHashMap<>(); private final Map idCache = new ConcurrentHashMap<>(); + private final File skinsFolder; - public MojangSkinCache(ConfigManager configManager) { + public MojangSkinCache(ConfigManager configManager, File skinsFolder) { this.configManager = configManager; + this.skinsFolder = skinsFolder; + if (!skinsFolder.exists()) skinsFolder.mkdirs(); } public void cleanCache() { @@ -142,6 +146,58 @@ public class MojangSkinCache { }); } + public CompletableFuture fetchFromFile(String path) throws FileNotFoundException { + File file = new File(skinsFolder, path); + if (!file.exists()) throw new FileNotFoundException("File not found: " + path); + return CompletableFuture.supplyAsync(() -> { + URL apiUrl = parseUrl("https://api.mineskin.org/generate/upload"); + HttpURLConnection connection = null; + try { + String boundary = "*****"; + String CRLF = "\r\n"; + + connection = (HttpURLConnection) apiUrl.openConnection(); + connection.setRequestMethod("POST"); + connection.setReadTimeout(10000); + connection.setConnectTimeout(15000); + connection.setUseCaches(false); + connection.setRequestProperty("Cache-Control", "no-cache"); + connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); + connection.setDoInput(true); + connection.setDoOutput(true); + OutputStream outputStream = connection.getOutputStream(); + DataOutputStream out = new DataOutputStream(outputStream); + out.writeBytes("--" + boundary + CRLF); + out.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"" + CRLF); + out.writeBytes("Content-Type: image/png" + CRLF); + out.writeBytes(CRLF); + out.write(Files.readAllBytes(file.toPath())); + out.writeBytes(CRLF); + out.writeBytes("--" + boundary + "--" + CRLF); + out.flush(); + out.close(); + outputStream.close(); + + try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) { + JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject(); + if (obj.has("error")) return null; + if (!obj.has("data")) return null; + JsonObject texture = obj.get("data").getAsJsonObject().get("texture").getAsJsonObject(); + return new SkinImpl(texture.get("value").getAsString(), texture.get("signature").getAsString()); + } + + } catch (IOException exception) { + if (!configManager.getConfig().disableSkinFetcherWarnings()) { + logger.warning("Failed to get skin from file:"); + exception.printStackTrace(); + } + } finally { + if (connection != null) connection.disconnect(); + } + return null; + }); + } + public boolean isNameFullyCached(String s) { String name = s.toLowerCase(); if (!idCache.containsKey(name)) return false; @@ -213,4 +269,8 @@ public class MojangSkinCache { throw new RuntimeException(exception); } } + + public File getSkinsFolder() { + return skinsFolder; + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java index c852080..24cd80c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java @@ -7,6 +7,7 @@ import lol.pyr.znpcsplus.skin.SkinImpl; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; import org.bukkit.entity.Player; +import java.io.FileNotFoundException; import java.net.URL; import java.util.concurrent.CompletableFuture; @@ -25,6 +26,16 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor return CompletableFuture.supplyAsync(() -> new PrefetchedDescriptor(cache.fetchByUrl(url, variant).join())); } + public static CompletableFuture fromFile(MojangSkinCache cache, String path) { + return CompletableFuture.supplyAsync(() -> { + try { + return new PrefetchedDescriptor(cache.fetchFromFile(path).join()); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + }); + } + @Override public CompletableFuture fetch(Player player) { return CompletableFuture.completedFuture(skin); -- 2.45.2 From 8cd7282bb5a8e952aada0e6f68b41e94c04596cc Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Tue, 17 Dec 2024 23:55:05 +0400 Subject: [PATCH 23/56] feat: added skeleton_type property --- .../java/lol/pyr/znpcsplus/util/SkeletonType.java | 11 +++++++++++ plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java | 1 + .../znpcsplus/entity/EntityPropertyRegistryImpl.java | 7 +++++++ .../main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 3 +++ 4 files changed, 22 insertions(+) create mode 100644 api/src/main/java/lol/pyr/znpcsplus/util/SkeletonType.java diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/SkeletonType.java b/api/src/main/java/lol/pyr/znpcsplus/util/SkeletonType.java new file mode 100644 index 0000000..ba3f05f --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/util/SkeletonType.java @@ -0,0 +1,11 @@ +package lol.pyr.znpcsplus.util; + +public enum SkeletonType { + NORMAL, + WITHER, + STRAY; + + public byte getLegacyId() { + return (byte) ordinal(); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index c4d1f9a..383d84f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -296,6 +296,7 @@ public class ZNpcsPlus { registerEnumParser(manager, ArmadilloState.class, incorrectUsageMessage); registerEnumParser(manager, WoldVariant.class, incorrectUsageMessage); registerEnumParser(manager, NpcStorageType.class, incorrectUsageMessage); + registerEnumParser(manager, SkeletonType.class, incorrectUsageMessage); manager.registerCommand("npc", new MultiCommand(bootstrap.loadHelpMessage("root")) .addSubcommand("center", new CenterCommand(npcRegistry)) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index a10ce9f..024a28a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -91,6 +91,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { registerEnumSerializer(Sound.class); registerEnumSerializer(ArmadilloState.class); registerEnumSerializer(WoldVariant.class); + registerEnumSerializer(SkeletonType.class); registerPrimitiveSerializers(Integer.class, Boolean.class, Double.class, Float.class, Long.class, Short.class, Byte.class, String.class); @@ -439,6 +440,12 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { witherIndex += 3; // skip the first 3 indexes, will be used for the other properties later register(new IntegerProperty("invulnerable_time", witherIndex, 0, false)); + // Skeleton + if (ver.isOlderThan(ServerVersion.V_1_11)) { + if (legacyBooleans) register(new EncodedByteProperty<>("skeleton_type", SkeletonType.NORMAL, 13, SkeletonType::getLegacyId)); + else register(new EncodedIntegerProperty<>("skeleton_type", SkeletonType.NORMAL, ver.isOlderThan(ServerVersion.V_1_10) ? 11 : 12, Enum::ordinal)); + } + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_9)) return; // Shulker int shulkerIndex; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index bfb259e..f62adb8 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -143,6 +143,9 @@ public class NpcTypeImpl implements NpcType { } else if (version.isOlderThan(ServerVersion.V_1_11) && type.equals(EntityTypes.HORSE)) { addProperties("has_chest"); } + if (version.isOlderThan(ServerVersion.V_1_11) && EntityTypes.isTypeInstanceOf(type, EntityTypes.SKELETON)) { + addProperties("skeleton_type"); + } if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_EVO_ILLU_ILLAGER)) { addProperties("spell"); } -- 2.45.2 From 33c27e903ce05cd3c39cbec35f89665bb827a1db Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 18 Dec 2024 05:22:12 +0100 Subject: [PATCH 24/56] fix duplicate team creation with glow property --- .../lol/pyr/znpcsplus/entity/properties/GlowProperty.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/GlowProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/GlowProperty.java index e32f61d..b20d2e5 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/GlowProperty.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/GlowProperty.java @@ -24,7 +24,10 @@ public class GlowProperty extends EntityPropertyImpl { EntityData oldData = properties.get(0); byte oldValue = oldData == null ? 0 : (byte) oldData.getValue(); properties.put(0, newEntityData(0, EntityDataTypes.BYTE, (byte) (oldValue | (value == null ? 0 : 0x40)))); - if (isSpawned) packetFactory.removeTeam(player, entity); - packetFactory.createTeam(player, entity, value); + // the team is already created with the right glow color in the packet factory if the npc isnt spawned yet + if (isSpawned) { + packetFactory.removeTeam(player, entity); + packetFactory.createTeam(player, entity, value); + } } } -- 2.45.2 From e30d6a57823a7c27a11854d0cc6d3652703467cb Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 18 Dec 2024 07:05:46 +0100 Subject: [PATCH 25/56] fix concurrency issues in Viewable by making all view tasks execute one by one through a queue --- .../java/lol/pyr/znpcsplus/api/npc/Npc.java | 7 +- .../pyr/znpcsplus/entity/PacketEntity.java | 26 +++--- .../pyr/znpcsplus/hologram/HologramImpl.java | 9 +- .../pyr/znpcsplus/hologram/HologramLine.java | 5 +- .../pyr/znpcsplus/hologram/HologramText.java | 9 +- .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 6 +- .../pyr/znpcsplus/packets/PacketFactory.java | 2 +- .../packets/V1_20_2PacketFactory.java | 5 +- .../znpcsplus/packets/V1_8PacketFactory.java | 4 +- .../lol/pyr/znpcsplus/util/FutureUtil.java | 12 +++ .../java/lol/pyr/znpcsplus/util/Viewable.java | 87 +++++++++++++------ 11 files changed, 118 insertions(+), 54 deletions(-) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java index d5e70bb..79872ba 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/Npc.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CompletableFuture; /** * Base class for all NPCs @@ -136,14 +137,16 @@ public interface Npc extends PropertyHolder { /** * Shows this NPC to a player * @param player The {@link Player} to show to + * @return A future that completes when the npc is fully shown to the player */ - void show(Player player); + CompletableFuture show(Player player); /** * Respawns this NPC for a player * @param player The {@link Player} to respawn for + * @return A future that completes when the npc is fully respawned */ - void respawn(Player player); + CompletableFuture respawn(Player player); /** * Sets the head rotation of this NPC for a player diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index dc06d00..a46c9d4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -14,6 +14,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.*; +import java.util.concurrent.CompletableFuture; public class PacketEntity implements PropertyHolder { private final PacketFactory packetFactory; @@ -65,15 +66,17 @@ public class PacketEntity implements PropertyHolder { for (Player viewer : viewable.getViewers()) packetFactory.teleportEntity(viewer, this); } - public void spawn(Player player) { - if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties); - else packetFactory.spawnEntity(player, this, properties); - if (vehicleId != null) { - packetFactory.setPassengers(player, vehicleId, this.getEntityId()); - } - if (passengers != null) { - packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); - } + public CompletableFuture spawn(Player player) { + return CompletableFuture.runAsync(() -> { + if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties).join(); + else packetFactory.spawnEntity(player, this, properties); + if (vehicleId != null) { + packetFactory.setPassengers(player, vehicleId, this.getEntityId()); + } + if (passengers != null) { + packetFactory.setPassengers(player, this.getEntityId(), passengers.stream().mapToInt(Integer::intValue).toArray()); + } + }); } public void setHeadRotation(Player player, float yaw, float pitch) { @@ -127,8 +130,9 @@ public class PacketEntity implements PropertyHolder { vehicle.setLocation(location.withY(location.getY() - 0.9)); for (Player player : viewable.getViewers()) { - vehicle.spawn(player); - packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + vehicle.spawn(player).thenRun(() -> { + packetFactory.setPassengers(player, vehicle.getEntityId(), this.getEntityId()); + }); } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java index c1a4556..6605515 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java @@ -6,6 +6,7 @@ import lol.pyr.znpcsplus.api.hologram.Hologram; import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.util.FutureUtil; import lol.pyr.znpcsplus.util.NpcLocation; import lol.pyr.znpcsplus.util.Viewable; import net.kyori.adventure.text.Component; @@ -16,6 +17,8 @@ import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; public class HologramImpl extends Viewable implements Hologram { private final ConfigManager configManager; @@ -138,8 +141,10 @@ public class HologramImpl extends Viewable implements Hologram { } @Override - protected void UNSAFE_show(Player player) { - for (HologramLine line : lines) line.show(player); + protected CompletableFuture UNSAFE_show(Player player) { + return FutureUtil.allOf(lines.stream() + .map(line -> line.show(player)) + .collect(Collectors.toList())); } @Override diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java index 79e45c1..553a5e2 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java @@ -13,6 +13,7 @@ import org.bukkit.inventory.ItemStack; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.CompletableFuture; public class HologramLine implements PropertyHolder { private M value; @@ -37,8 +38,8 @@ public class HologramLine implements PropertyHolder { entity.refreshMeta(player); } - protected void show(Player player) { - entity.spawn(player); + protected CompletableFuture show(Player player) { + return entity.spawn(player); } protected void hide(Player player) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java index 40c8995..23f3428 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java @@ -9,6 +9,8 @@ import lol.pyr.znpcsplus.util.Viewable; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import java.util.concurrent.CompletableFuture; + public class HologramText extends HologramLine { private static final Component BLANK = Component.text("%blank%"); @@ -20,10 +22,9 @@ public class HologramText extends HologramLine { } @Override - public void show(Player player) { - if (!getValue().equals(BLANK)) { - super.show(player); - } + public CompletableFuture show(Player player) { + if (getValue().equals(BLANK)) return CompletableFuture.completedFuture(null); + return super.show(player); } @SuppressWarnings("unchecked") diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index ad0061f..d340f32 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; public class NpcImpl extends Viewable implements Npc { @@ -126,9 +127,8 @@ public class NpcImpl extends Viewable implements Npc { } @Override - protected void UNSAFE_show(Player player) { - entity.spawn(player); - hologram.show(player); + protected CompletableFuture UNSAFE_show(Player player) { + return CompletableFuture.allOf(entity.spawn(player), hologram.show(player)); } @Override diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index aaea42a..f2b58c1 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; public interface PacketFactory { - void spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties); + CompletableFuture spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties); void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties); void destroyEntity(Player player, PacketEntity entity, PropertyHolder properties); void teleportEntity(Player player, PacketEntity entity); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java index fd9e126..9d5de17 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java @@ -16,6 +16,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import java.util.Optional; +import java.util.concurrent.CompletableFuture; public class V1_20_2PacketFactory extends V1_19_3PacketFactory { @@ -27,8 +28,8 @@ public class V1_20_2PacketFactory extends V1_19_3PacketFactory { } @Override - public void spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties) { - addTabPlayer(player, entity, properties).thenAccept(ignored -> { + public CompletableFuture spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties) { + return addTabPlayer(player, entity, properties).thenAccept(ignored -> { createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); NpcLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index 2637b83..3fe0504 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -47,8 +47,8 @@ public class V1_8PacketFactory implements PacketFactory { } @Override - public void spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties) { - addTabPlayer(player, entity, properties).thenAccept(ignored -> { + public CompletableFuture spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties) { + return addTabPlayer(player, entity, properties).thenAccept(ignored -> { createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); NpcLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java new file mode 100644 index 0000000..3b0c31c --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java @@ -0,0 +1,12 @@ +package lol.pyr.znpcsplus.util; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +public class FutureUtil { + public static CompletableFuture allOf(Collection> futures) { + return CompletableFuture.runAsync(() -> { + for (CompletableFuture future : futures) future.join(); + }); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java index 27e4bad..19637d8 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java @@ -4,11 +4,9 @@ import org.bukkit.entity.Player; import java.lang.ref.Reference; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Collectors; public abstract class Viewable { @@ -21,38 +19,74 @@ public abstract class Viewable { .collect(Collectors.toList()); } - private final Set viewers = ConcurrentHashMap.newKeySet(); + private boolean queueRunning = false; + private final Queue visibilityTaskQueue = new ConcurrentLinkedQueue<>(); + private final Set viewers = new HashSet<>(); public Viewable() { all.add(new WeakReference<>(this)); } + private void tryRunQueue() { + if (visibilityTaskQueue.isEmpty() || queueRunning) return; + queueRunning = true; + CompletableFuture.runAsync(() -> { + while (!visibilityTaskQueue.isEmpty()) try { + visibilityTaskQueue.remove().run(); + } catch (Exception e) { + e.printStackTrace(); + } + queueRunning = false; + }); + } + + private void queueVisibilityTask(Runnable runnable) { + visibilityTaskQueue.add(runnable); + tryRunQueue(); + } + public void delete() { - UNSAFE_hideAll(); - viewers.clear(); + queueVisibilityTask(() -> { + UNSAFE_hideAll(); + viewers.clear(); + }); } - public void respawn() { - UNSAFE_hideAll(); - UNSAFE_showAll(); + public CompletableFuture respawn() { + CompletableFuture future = new CompletableFuture<>(); + queueVisibilityTask(() -> { + UNSAFE_hideAll(); + UNSAFE_showAll().join(); + future.complete(null); + }); + return future; } - public void respawn(Player player) { - if (!viewers.contains(player)) return; - UNSAFE_hide(player); - UNSAFE_show(player); + public CompletableFuture respawn(Player player) { + hide(player); + return show(player); } - public void show(Player player) { - if (viewers.contains(player)) return; - viewers.add(player); - UNSAFE_show(player); + public CompletableFuture show(Player player) { + CompletableFuture future = new CompletableFuture<>(); + queueVisibilityTask(() -> { + if (viewers.contains(player)) { + future.complete(null); + return; + } + viewers.add(player); + UNSAFE_show(player).join(); + future.complete(null); + }); + return future; } public void hide(Player player) { - if (!viewers.contains(player)) return; - viewers.remove(player); - UNSAFE_hide(player); + queueVisibilityTask(() -> { + if (!viewers.contains(player)) return; + viewers.remove(player); + UNSAFE_hide(player); + }); } public void UNSAFE_removeViewer(Player player) { @@ -63,8 +97,11 @@ public abstract class Viewable { for (Player viewer : viewers) UNSAFE_hide(viewer); } - protected void UNSAFE_showAll() { - for (Player viewer : viewers) UNSAFE_show(viewer); + protected CompletableFuture UNSAFE_showAll() { + return FutureUtil.allOf(viewers.stream() + .map(this::UNSAFE_show) + .collect(Collectors.toList())); + // for (Player viewer : viewers) UNSAFE_show(viewer); } public Set getViewers() { @@ -75,7 +112,7 @@ public abstract class Viewable { return viewers.contains(player); } - protected abstract void UNSAFE_show(Player player); + protected abstract CompletableFuture UNSAFE_show(Player player); protected abstract void UNSAFE_hide(Player player); } -- 2.45.2 From e621ac69085cd5fe500e812f6090e977b523fbb8 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 18 Dec 2024 07:08:46 +0100 Subject: [PATCH 26/56] add exception printing by default to all futures --- .../commands/storage/ImportCommand.java | 4 ++-- .../commands/storage/LoadAllCommand.java | 3 ++- .../commands/storage/SaveAllCommand.java | 3 ++- .../pyr/znpcsplus/entity/PacketEntity.java | 3 ++- .../znpcsplus/skin/cache/MojangSkinCache.java | 9 +++---- .../skin/descriptor/PrefetchedDescriptor.java | 5 ++-- .../lol/pyr/znpcsplus/util/FutureUtil.java | 24 ++++++++++++++++++- .../java/lol/pyr/znpcsplus/util/Viewable.java | 2 +- 8 files changed, 40 insertions(+), 13 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/ImportCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/ImportCommand.java index 39b492c..c6c598e 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/ImportCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/ImportCommand.java @@ -7,13 +7,13 @@ import lol.pyr.znpcsplus.conversion.DataImporter; import lol.pyr.znpcsplus.conversion.DataImporterRegistry; import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; +import lol.pyr.znpcsplus.util.FutureUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.concurrent.CompletableFuture; public class ImportCommand implements CommandHandler { private final NpcRegistryImpl npcRegistry; @@ -33,7 +33,7 @@ public class ImportCommand implements CommandHandler { if (importer == null) context.halt(Component.text("Importer not found! Possible importers: " + String.join(", ", importerRegistry.getIds()), NamedTextColor.RED)); - CompletableFuture.runAsync(() -> { + FutureUtil.exceptionPrintingRunAsync(() -> { if (!importer.isValid()) { context.send(Component.text("There is no data to import from this importer!", NamedTextColor.RED)); return; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java index 1402816..e007656 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java @@ -4,6 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext; import lol.pyr.director.adventure.command.CommandHandler; import lol.pyr.director.common.command.CommandExecutionException; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; +import lol.pyr.znpcsplus.util.FutureUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -20,7 +21,7 @@ public class LoadAllCommand implements CommandHandler { @Override public void run(CommandContext context) throws CommandExecutionException { - CompletableFuture.runAsync(() -> { + FutureUtil.exceptionPrintingRunAsync(() -> { npcRegistry.reload(); context.send(Component.text("All NPCs have been re-loaded from storage", NamedTextColor.GREEN)); }); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java index d995f30..4188a38 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java @@ -4,6 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext; import lol.pyr.director.adventure.command.CommandHandler; import lol.pyr.director.common.command.CommandExecutionException; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; +import lol.pyr.znpcsplus.util.FutureUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -20,7 +21,7 @@ public class SaveAllCommand implements CommandHandler { @Override public void run(CommandContext context) throws CommandExecutionException { - CompletableFuture.runAsync(() -> { + FutureUtil.exceptionPrintingRunAsync(() -> { npcRegistry.save(); context.send(Component.text("All NPCs have been saved to storage", NamedTextColor.GREEN)); }); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index a46c9d4..4e51020 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -8,6 +8,7 @@ import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.reflection.Reflections; +import lol.pyr.znpcsplus.util.FutureUtil; import lol.pyr.znpcsplus.util.NpcLocation; import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; @@ -67,7 +68,7 @@ public class PacketEntity implements PropertyHolder { } public CompletableFuture spawn(Player player) { - return CompletableFuture.runAsync(() -> { + return FutureUtil.exceptionPrintingRunAsync(() -> { if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties).join(); else packetFactory.spawnEntity(player, this, properties); if (vehicleId != null) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java index 2a54509..3b0a982 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/MojangSkinCache.java @@ -5,6 +5,7 @@ import com.google.gson.JsonParser; import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.reflection.Reflections; import lol.pyr.znpcsplus.skin.SkinImpl; +import lol.pyr.znpcsplus.util.FutureUtil; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -42,7 +43,7 @@ public class MojangSkinCache { if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId()); - return CompletableFuture.supplyAsync(() -> { + return FutureUtil.exceptionPrintingSupplyAsync(() -> { URL url = parseUrl("https://api.mojang.com/users/profiles/minecraft/" + name); HttpURLConnection connection = null; try { @@ -75,7 +76,7 @@ public class MojangSkinCache { if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId()); - return CompletableFuture.supplyAsync(() -> { + return FutureUtil.exceptionPrintingSupplyAsync(() -> { URL url = parseUrl("https://api.ashcon.app/mojang/v2/user/" + name); HttpURLConnection connection = null; try { @@ -106,7 +107,7 @@ public class MojangSkinCache { } public CompletableFuture fetchByUrl(URL url, String variant) { - return CompletableFuture.supplyAsync(() -> { + return FutureUtil.exceptionPrintingSupplyAsync(() -> { URL apiUrl = parseUrl("https://api.mineskin.org/generate/url"); HttpURLConnection connection = null; try { @@ -170,7 +171,7 @@ public class MojangSkinCache { if (!skin.isExpired()) return CompletableFuture.completedFuture(skin); } - return CompletableFuture.supplyAsync(() -> { + return FutureUtil.exceptionPrintingSupplyAsync(() -> { URL url = parseUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false"); HttpURLConnection connection = null; try { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java index c852080..3e62802 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java @@ -5,6 +5,7 @@ import lol.pyr.znpcsplus.api.skin.SkinDescriptor; import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; import lol.pyr.znpcsplus.skin.SkinImpl; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; +import lol.pyr.znpcsplus.util.FutureUtil; import org.bukkit.entity.Player; import java.net.URL; @@ -18,11 +19,11 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor } public static CompletableFuture forPlayer(MojangSkinCache cache, String name) { - return CompletableFuture.supplyAsync(() -> new PrefetchedDescriptor(cache.fetchByName(name).join())); + return FutureUtil.exceptionPrintingSupplyAsync(() -> new PrefetchedDescriptor(cache.fetchByName(name).join())); } public static CompletableFuture fromUrl(MojangSkinCache cache, URL url, String variant) { - return CompletableFuture.supplyAsync(() -> new PrefetchedDescriptor(cache.fetchByUrl(url, variant).join())); + return FutureUtil.exceptionPrintingSupplyAsync(() -> new PrefetchedDescriptor(cache.fetchByUrl(url, variant).join())); } @Override diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java index 3b0c31c..18ca6e4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java @@ -2,11 +2,33 @@ package lol.pyr.znpcsplus.util; import java.util.Collection; import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; public class FutureUtil { public static CompletableFuture allOf(Collection> futures) { - return CompletableFuture.runAsync(() -> { + return exceptionPrintingRunAsync(() -> { for (CompletableFuture future : futures) future.join(); }); } + + public static CompletableFuture newExceptionPrintingFuture() { + return new CompletableFuture().exceptionally(throwable -> { + throwable.printStackTrace(); + return null; + }); + } + + public static CompletableFuture exceptionPrintingRunAsync(Runnable runnable) { + return CompletableFuture.runAsync(runnable).exceptionally(throwable -> { + throwable.printStackTrace(); + return null; + }); + } + + public static CompletableFuture exceptionPrintingSupplyAsync(Supplier supplier) { + return CompletableFuture.supplyAsync(supplier).exceptionally(throwable -> { + throwable.printStackTrace(); + return null; + }); + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java index 19637d8..9dd4160 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java @@ -30,7 +30,7 @@ public abstract class Viewable { private void tryRunQueue() { if (visibilityTaskQueue.isEmpty() || queueRunning) return; queueRunning = true; - CompletableFuture.runAsync(() -> { + FutureUtil.exceptionPrintingRunAsync(() -> { while (!visibilityTaskQueue.isEmpty()) try { visibilityTaskQueue.remove().run(); } catch (Exception e) { -- 2.45.2 From 27096e532b33965d0afa579063b6c74774811740 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 18 Dec 2024 07:29:37 +0100 Subject: [PATCH 27/56] remove comment and unused imports --- .../java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java | 1 - .../java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java | 1 - plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java | 1 - 3 files changed, 3 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java index e007656..93cc3de 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java @@ -10,7 +10,6 @@ import net.kyori.adventure.text.format.NamedTextColor; import java.util.Collections; import java.util.List; -import java.util.concurrent.CompletableFuture; public class LoadAllCommand implements CommandHandler { private final NpcRegistryImpl npcRegistry; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java index 4188a38..4445cf1 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java @@ -10,7 +10,6 @@ import net.kyori.adventure.text.format.NamedTextColor; import java.util.Collections; import java.util.List; -import java.util.concurrent.CompletableFuture; public class SaveAllCommand implements CommandHandler { private final NpcRegistryImpl npcRegistry; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java index 9dd4160..190f13e 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java @@ -101,7 +101,6 @@ public abstract class Viewable { return FutureUtil.allOf(viewers.stream() .map(this::UNSAFE_show) .collect(Collectors.toList())); - // for (Player viewer : viewers) UNSAFE_show(viewer); } public Set getViewers() { -- 2.45.2 From c780c0ec78c8ea422cecbe9da9d16e52c46a368d Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 24 Dec 2024 16:11:13 +0100 Subject: [PATCH 28/56] add npc serialization methods to the api --- .../java/lol/pyr/znpcsplus/api/NpcApi.java | 7 + .../pyr/znpcsplus/api/npc/NpcRegistry.java | 7 + .../api/serialization/NpcSerializer.java | 20 +++ .../serialization/NpcSerializerRegistry.java | 19 +++ .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 12 +- .../java/lol/pyr/znpcsplus/ZNpcsPlusApi.java | 10 +- .../commands/storage/MigrateCommand.java | 9 +- .../pyr/znpcsplus/npc/NpcRegistryImpl.java | 13 +- .../NpcSerializerRegistryImpl.java | 33 ++++ .../serialization/YamlSerializer.java | 154 ++++++++++++++++++ .../pyr/znpcsplus/storage/NpcStorageType.java | 11 +- .../znpcsplus/storage/yaml/YamlStorage.java | 115 ++----------- 12 files changed, 289 insertions(+), 121 deletions(-) create mode 100644 api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java create mode 100644 api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java b/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java index b32c050..2faf2c8 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java @@ -5,6 +5,7 @@ import lol.pyr.znpcsplus.api.interaction.ActionFactory; import lol.pyr.znpcsplus.api.interaction.ActionRegistry; import lol.pyr.znpcsplus.api.npc.NpcRegistry; import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry; +import lol.pyr.znpcsplus.api.serialization.NpcSerializerRegistry; import lol.pyr.znpcsplus.api.skin.SkinDescriptorFactory; /** @@ -46,4 +47,10 @@ public interface NpcApi { * @return the skin descriptor factory */ SkinDescriptorFactory getSkinDescriptorFactory(); + + /** + * Gets the npc serializer registry. + * @return the npc serializer registry + */ + NpcSerializerRegistry getNpcSerializerRegistry(); } diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java index 4722e0b..b822354 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java @@ -64,4 +64,11 @@ public interface NpcRegistry { * @param id The ID of the NPC entry */ void delete(String id); + + /** + * Register an NPC to this registry + * NpcEntry instances can be obtained through the NpcSerializer classes + * @param entry The npc to be registered + */ + void register(NpcEntry entry); } diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java new file mode 100644 index 0000000..f35cbed --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java @@ -0,0 +1,20 @@ +package lol.pyr.znpcsplus.api.serialization; + +import lol.pyr.znpcsplus.api.npc.NpcEntry; + +public interface NpcSerializer { + /** + * Serialize an npc into the type of this serializer + * @param entry The npc entry + * @return The serialized class + */ + T serialize(NpcEntry entry); + + /** + * Deserialize an npc from a serialized class + * Note: This npc will not be registered, you need to also register it using the NpcRegistry#register(NpcEntry) method + * @param model The serialized class + * @return The deserialized NpcEntry + */ + NpcEntry deserialize(T model); +} diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java new file mode 100644 index 0000000..74e8d89 --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java @@ -0,0 +1,19 @@ +package lol.pyr.znpcsplus.api.serialization; + +public interface NpcSerializerRegistry { + /** + * Get an NpcSerializer that serializes npcs into the provided class + * @param clazz The class to serialize into + * @return The npc serializer instance + * @param The type of the class that the serializer serializes into + */ + NpcSerializer getSerializer(Class clazz); + + /** + * Register an NpcSerializer to be used by other plugins + * @param clazz The class that the serializer serializes into + * @param serializer The serializer itself + * @param The type of the class that the serializer serializes into + */ + void registerSerializer(Class clazz, NpcSerializer serializer); +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index 07aadf3..2a0d64f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -38,6 +38,7 @@ import lol.pyr.znpcsplus.parsers.*; import lol.pyr.znpcsplus.scheduling.FoliaScheduler; import lol.pyr.znpcsplus.scheduling.SpigotScheduler; import lol.pyr.znpcsplus.scheduling.TaskScheduler; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; import lol.pyr.znpcsplus.skin.cache.SkinCacheCleanTask; import lol.pyr.znpcsplus.storage.NpcStorageType; @@ -135,8 +136,9 @@ public class ZNpcsPlus { ActionRegistryImpl actionRegistry = new ActionRegistryImpl(); ActionFactoryImpl actionFactory = new ActionFactoryImpl(scheduler, adventure, textSerializer, bungeeConnector); NpcTypeRegistryImpl typeRegistry = new NpcTypeRegistryImpl(); + NpcSerializerRegistryImpl serializerRegistry = new NpcSerializerRegistryImpl(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer); NpcRegistryImpl npcRegistry = new NpcRegistryImpl(configManager, this, packetFactory, actionRegistry, - scheduler, typeRegistry, propertyRegistry, textSerializer); + scheduler, typeRegistry, propertyRegistry, serializerRegistry, textSerializer); shutdownTasks.add(npcRegistry::unload); UserManager userManager = new UserManager(); @@ -159,7 +161,7 @@ public class ZNpcsPlus { pluginManager.registerEvents(new UserListener(userManager), bootstrap); registerCommands(npcRegistry, skinCache, adventure, actionRegistry, - typeRegistry, propertyRegistry, importerRegistry, configManager, packetFactory); + typeRegistry, propertyRegistry, importerRegistry, configManager, packetFactory, serializerRegistry); log(ChatColor.WHITE + " * Starting tasks..."); if (configManager.getConfig().checkForUpdates()) { @@ -193,7 +195,7 @@ public class ZNpcsPlus { } } - NpcApiProvider.register(bootstrap, new ZNpcsPlusApi(npcRegistry, typeRegistry, propertyRegistry, actionRegistry, actionFactory, skinCache)); + NpcApiProvider.register(bootstrap, new ZNpcsPlusApi(npcRegistry, typeRegistry, propertyRegistry, actionRegistry, actionFactory, skinCache, serializerRegistry)); log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)"); log(""); @@ -246,7 +248,7 @@ public class ZNpcsPlus { private void registerCommands(NpcRegistryImpl npcRegistry, MojangSkinCache skinCache, BukkitAudiences adventure, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, DataImporterRegistry importerRegistry, - ConfigManager configManager, PacketFactory packetFactory) { + ConfigManager configManager, PacketFactory packetFactory, NpcSerializerRegistryImpl serializerRegistry) { Message incorrectUsageMessage = context -> context.send(Component.text("Incorrect usage: /" + context.getUsage(), NamedTextColor.RED)); CommandManager manager = new CommandManager(bootstrap, adventure, incorrectUsageMessage); @@ -322,7 +324,7 @@ public class ZNpcsPlus { .addSubcommand("save", new SaveAllCommand(npcRegistry)) .addSubcommand("reload", new LoadAllCommand(npcRegistry)) .addSubcommand("import", new ImportCommand(npcRegistry, importerRegistry)) - .addSubcommand("migrate", new MigrateCommand(configManager, this, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, npcRegistry.getStorage(), configManager.getConfig().storageType(), npcRegistry))) + .addSubcommand("migrate", new MigrateCommand(configManager, this, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, npcRegistry.getStorage(), configManager.getConfig().storageType(), npcRegistry, serializerRegistry))) .addSubcommand("holo", new MultiCommand(bootstrap.loadHelpMessage("holo")) .addSubcommand("add", new HoloAddCommand(npcRegistry)) .addSubcommand("additem", new HoloAddItemCommand(npcRegistry)) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java index ef9c8ee..7d272da 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java @@ -12,6 +12,7 @@ import lol.pyr.znpcsplus.interaction.ActionFactoryImpl; import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.skin.SkinDescriptorFactoryImpl; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; @@ -22,14 +23,16 @@ public class ZNpcsPlusApi implements NpcApi { private final ActionRegistryImpl actionRegistry; private final ActionFactoryImpl actionFactory; private final SkinDescriptorFactoryImpl skinDescriptorFactory; + private final NpcSerializerRegistryImpl npcSerializerRegistry; - public ZNpcsPlusApi(NpcRegistryImpl npcRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, ActionRegistryImpl actionRegistry, ActionFactoryImpl actionFactory, MojangSkinCache skinCache) { + public ZNpcsPlusApi(NpcRegistryImpl npcRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, ActionRegistryImpl actionRegistry, ActionFactoryImpl actionFactory, MojangSkinCache skinCache, NpcSerializerRegistryImpl npcSerializerRegistry) { this.npcRegistry = npcRegistry; this.typeRegistry = typeRegistry; this.propertyRegistry = propertyRegistry; this.actionRegistry = actionRegistry; this.actionFactory = actionFactory; this.skinDescriptorFactory = new SkinDescriptorFactoryImpl(skinCache); + this.npcSerializerRegistry = npcSerializerRegistry; } @Override @@ -62,4 +65,9 @@ public class ZNpcsPlusApi implements NpcApi { public SkinDescriptorFactory getSkinDescriptorFactory() { return skinDescriptorFactory; } + + @Override + public NpcSerializerRegistryImpl getNpcSerializerRegistry() { + return npcSerializerRegistry; + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java index cda3b3c..063b98a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java @@ -11,6 +11,7 @@ import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.NpcStorage; import lol.pyr.znpcsplus.storage.NpcStorageType; import net.kyori.adventure.text.Component; @@ -35,8 +36,9 @@ public class MigrateCommand implements CommandHandler { private final NpcStorage currentStorage; private final NpcStorageType currentStorageType; private final NpcRegistryImpl npcRegistry; + private final NpcSerializerRegistryImpl serializerRegistry; - public MigrateCommand(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcStorage currentStorage, NpcStorageType currentStorageType, NpcRegistryImpl npcRegistry) { + public MigrateCommand(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcStorage currentStorage, NpcStorageType currentStorageType, NpcRegistryImpl npcRegistry, NpcSerializerRegistryImpl serializerRegistry) { this.configManager = configManager; this.plugin = plugin; this.packetFactory = packetFactory; @@ -47,6 +49,7 @@ public class MigrateCommand implements CommandHandler { this.currentStorage = currentStorage; this.currentStorageType = currentStorageType; this.npcRegistry = npcRegistry; + this.serializerRegistry = serializerRegistry; } @Override @@ -63,7 +66,7 @@ public class MigrateCommand implements CommandHandler { if (currentStorageType == from) { fromStorage = currentStorage; } else { - fromStorage = from.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + fromStorage = from.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); if (fromStorage == null) { context.halt(Component.text("Failed to initialize the source storage. Please check the console for more information.", NamedTextColor.RED)); return; @@ -84,7 +87,7 @@ public class MigrateCommand implements CommandHandler { if (currentStorageType == to) { toStorage = currentStorage; } else { - toStorage = to.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + toStorage = to.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); if (toStorage == null) { context.halt(Component.text("Failed to initialize the destination storage. Please check the console for more information.", NamedTextColor.RED)); return; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java index e95cecd..0dc8a1a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java @@ -14,6 +14,7 @@ import lol.pyr.znpcsplus.hologram.HologramText; import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.scheduling.TaskScheduler; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.NpcStorage; import lol.pyr.znpcsplus.storage.NpcStorageType; import lol.pyr.znpcsplus.util.NpcLocation; @@ -35,13 +36,13 @@ public class NpcRegistryImpl implements NpcRegistry { private final Map npcIdLookupMap = new HashMap<>(); private final Map npcUuidLookupMap = new HashMap<>(); - public NpcRegistryImpl(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, TaskScheduler scheduler, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + public NpcRegistryImpl(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, TaskScheduler scheduler, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, NpcSerializerRegistryImpl serializerRegistry, LegacyComponentSerializer textSerializer) { this.textSerializer = textSerializer; this.propertyRegistry = propertyRegistry; - storage = configManager.getConfig().storageType().create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + storage = configManager.getConfig().storageType().create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); if (storage == null) { Bukkit.getLogger().warning("Failed to initialize storage, falling back to YAML"); - storage = NpcStorageType.YAML.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + storage = NpcStorageType.YAML.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); } this.packetFactory = packetFactory; this.configManager = configManager; @@ -52,7 +53,13 @@ public class NpcRegistryImpl implements NpcRegistry { } } + @Override + public void register(NpcEntry entry) { + register((NpcEntryImpl) entry); + } + private void register(NpcEntryImpl entry) { + if (entry == null) throw new NullPointerException(); unregister(npcIdLookupMap.put(entry.getId(), entry)); unregister(npcUuidLookupMap.put(entry.getNpc().getUuid(), entry)); npcList.add(entry); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java new file mode 100644 index 0000000..71a7a95 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java @@ -0,0 +1,33 @@ +package lol.pyr.znpcsplus.serialization; + +import lol.pyr.znpcsplus.api.serialization.NpcSerializer; +import lol.pyr.znpcsplus.api.serialization.NpcSerializerRegistry; +import lol.pyr.znpcsplus.config.ConfigManager; +import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; +import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; +import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; +import lol.pyr.znpcsplus.packets.PacketFactory; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.util.HashMap; +import java.util.Map; + +public class NpcSerializerRegistryImpl implements NpcSerializerRegistry { + private final Map, NpcSerializer> serializerMap = new HashMap<>(); + + public NpcSerializerRegistryImpl(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + registerSerializer(YamlConfiguration.class, new YamlSerializer(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer)); + } + + @SuppressWarnings("unchecked") + @Override + public NpcSerializer getSerializer(Class clazz) { + return (NpcSerializer) serializerMap.get(clazz); + } + + @Override + public void registerSerializer(Class clazz, NpcSerializer serializer) { + serializerMap.put(clazz, serializer); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java new file mode 100644 index 0000000..6a87564 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java @@ -0,0 +1,154 @@ +package lol.pyr.znpcsplus.serialization; + +import lol.pyr.znpcsplus.api.entity.EntityProperty; +import lol.pyr.znpcsplus.api.npc.NpcEntry; +import lol.pyr.znpcsplus.api.serialization.NpcSerializer; +import lol.pyr.znpcsplus.config.ConfigManager; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; +import lol.pyr.znpcsplus.entity.PropertySerializer; +import lol.pyr.znpcsplus.hologram.HologramImpl; +import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; +import lol.pyr.znpcsplus.npc.NpcEntryImpl; +import lol.pyr.znpcsplus.npc.NpcImpl; +import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; +import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.util.NpcLocation; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class YamlSerializer implements NpcSerializer { + private final static Logger logger = Logger.getLogger("YamlSerializer"); + + private final PacketFactory packetFactory; + private final ConfigManager configManager; + private final ActionRegistryImpl actionRegistry; + private final NpcTypeRegistryImpl typeRegistry; + private final EntityPropertyRegistryImpl propertyRegistry; + private final LegacyComponentSerializer textSerializer; + + public YamlSerializer(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + this.packetFactory = packetFactory; + this.configManager = configManager; + this.actionRegistry = actionRegistry; + this.typeRegistry = typeRegistry; + this.propertyRegistry = propertyRegistry; + this.textSerializer = textSerializer; + } + + @Override + public YamlConfiguration serialize(NpcEntry entry) { + YamlConfiguration config = new YamlConfiguration(); + config.set("id", entry.getId()); + config.set("is-processed", entry.isProcessed()); + config.set("allow-commands", entry.isAllowCommandModification()); + config.set("save", entry.isSave()); + + NpcImpl npc = (NpcImpl) entry.getNpc(); + config.set("enabled", npc.isEnabled()); + config.set("uuid", npc.getUuid().toString()); + config.set("world", npc.getWorldName()); + config.set("location", serializeLocation(npc.getLocation())); + config.set("type", npc.getType().getName()); + + for (EntityProperty property : npc.getAllProperties()) try { + PropertySerializer serializer = propertyRegistry.getSerializer(((EntityPropertyImpl) property).getType()); + if (serializer == null) { + Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + property.getName() + "' for npc '" + entry.getId() + "'. skipping ..."); + continue; + } + config.set("properties." + property.getName(), serializer.UNSAFE_serialize(npc.getProperty(property))); + } catch (Exception exception) { + logger.severe("Failed to serialize property " + property.getName() + " for npc with id " + entry.getId()); + exception.printStackTrace(); + } + + HologramImpl hologram = npc.getHologram(); + if (hologram.getOffset() != 0.0) config.set("hologram.offset", hologram.getOffset()); + if (hologram.getRefreshDelay() != -1) config.set("hologram.refresh-delay", hologram.getRefreshDelay()); + List lines = new ArrayList<>(npc.getHologram().getLines().size()); + for (int i = 0; i < hologram.getLines().size(); i++) { + lines.add(hologram.getLine(i)); + } + config.set("hologram.lines", lines); + config.set("actions", npc.getActions().stream() + .map(actionRegistry::serialize) + .filter(Objects::nonNull) + .collect(Collectors.toList())); + + return config; + } + + @Override + public NpcEntry deserialize(YamlConfiguration config) { + UUID uuid = config.contains("uuid") ? UUID.fromString(config.getString("uuid")) : UUID.randomUUID(); + NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, config.getString("world"), + typeRegistry.getByName(config.getString("type")), deserializeLocation(config.getConfigurationSection("location"))); + + if (config.isBoolean("enabled")) npc.setEnabled(config.getBoolean("enabled")); + + ConfigurationSection properties = config.getConfigurationSection("properties"); + if (properties != null) { + for (String key : properties.getKeys(false)) { + EntityPropertyImpl property = propertyRegistry.getByName(key); + if (property == null) { + Bukkit.getLogger().log(Level.WARNING, "Unknown property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); + continue; + } + PropertySerializer serializer = propertyRegistry.getSerializer(property.getType()); + if (serializer == null) { + Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); + continue; + } + Object value = serializer.deserialize(properties.getString(key)); + if (value == null) { + Bukkit.getLogger().log(Level.WARNING, "Failed to deserialize property '" + key + "' for npc '" + config.getString("id") + "'. Resetting to default ..."); + value = property.getDefaultValue(); + } + npc.UNSAFE_setProperty(property, value); + } + } + HologramImpl hologram = npc.getHologram(); + hologram.setOffset(config.getDouble("hologram.offset", 0.0)); + hologram.setRefreshDelay(config.getLong("hologram.refresh-delay", -1)); + for (String line : config.getStringList("hologram.lines")) hologram.addLine(line); + for (String s : config.getStringList("actions")) npc.addAction(actionRegistry.deserialize(s)); + + NpcEntryImpl entry = new NpcEntryImpl(config.getString("id"), npc); + entry.setProcessed(config.getBoolean("is-processed")); + entry.setAllowCommandModification(config.getBoolean("allow-commands")); + entry.setSave(config.getBoolean("save")); + + return entry; + } + + public NpcLocation deserializeLocation(ConfigurationSection section) { + return new NpcLocation( + section.getDouble("x"), + section.getDouble("y"), + section.getDouble("z"), + (float) section.getDouble("yaw"), + (float) section.getDouble("pitch") + ); + } + + public YamlConfiguration serializeLocation(NpcLocation location) { + YamlConfiguration config = new YamlConfiguration(); + config.set("x", location.getX()); + config.set("y", location.getY()); + config.set("z", location.getZ()); + config.set("yaw", location.getYaw()); + config.set("pitch", location.getPitch()); + return config; + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java index 5205dfc..b4139cc 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java @@ -6,6 +6,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.mysql.MySQLStorage; import lol.pyr.znpcsplus.storage.sqlite.SQLiteStorage; import lol.pyr.znpcsplus.storage.yaml.YamlStorage; @@ -16,13 +17,13 @@ import java.io.File; public enum NpcStorageType { YAML { @Override - public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { - return new YamlStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer, new File(plugin.getDataFolder(), "data")); + public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry) { + return new YamlStorage(serializerRegistry, new File(plugin.getDataFolder(), "data")); } }, SQLITE { @Override - public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry) { try { return new SQLiteStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer, new File(plugin.getDataFolder(), "znpcsplus.sqlite")); } catch (Exception e) { @@ -33,7 +34,7 @@ public enum NpcStorageType { }, MYSQL { @Override - public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry) { try { return new MySQLStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer); } catch (Exception e) { @@ -43,5 +44,5 @@ public enum NpcStorageType { } }; - public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer); + public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java index 55e46dd..b985fa7 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java @@ -1,47 +1,28 @@ package lol.pyr.znpcsplus.storage.yaml; -import lol.pyr.znpcsplus.api.entity.EntityProperty; -import lol.pyr.znpcsplus.config.ConfigManager; -import lol.pyr.znpcsplus.entity.EntityPropertyImpl; -import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; -import lol.pyr.znpcsplus.entity.PropertySerializer; -import lol.pyr.znpcsplus.hologram.HologramImpl; -import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; +import lol.pyr.znpcsplus.api.serialization.NpcSerializer; import lol.pyr.znpcsplus.npc.NpcEntryImpl; -import lol.pyr.znpcsplus.npc.NpcImpl; -import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; -import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.NpcStorage; import lol.pyr.znpcsplus.util.NpcLocation; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; -import java.util.*; -import java.util.logging.Level; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.logging.Logger; -import java.util.stream.Collectors; public class YamlStorage implements NpcStorage { private final static Logger logger = Logger.getLogger("YamlStorage"); - private final PacketFactory packetFactory; - private final ConfigManager configManager; - private final ActionRegistryImpl actionRegistry; - private final NpcTypeRegistryImpl typeRegistry; - private final EntityPropertyRegistryImpl propertyRegistry; - private final LegacyComponentSerializer textSerializer; private final File folder; + private final NpcSerializer yamlSerializer; - public YamlStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, File folder) { - this.packetFactory = packetFactory; - this.configManager = configManager; - this.actionRegistry = actionRegistry; - this.typeRegistry = typeRegistry; - this.propertyRegistry = propertyRegistry; - this.textSerializer = textSerializer; + public YamlStorage(NpcSerializerRegistryImpl serializerRegistry, File folder) { + this.yamlSerializer = serializerRegistry.getSerializer(YamlConfiguration.class); this.folder = folder; if (!this.folder.exists()) this.folder.mkdirs(); } @@ -53,45 +34,7 @@ public class YamlStorage implements NpcStorage { List npcs = new ArrayList<>(files.length); for (File file : files) if (file.isFile() && file.getName().toLowerCase().endsWith(".yml")) try { YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - UUID uuid = config.contains("uuid") ? UUID.fromString(config.getString("uuid")) : UUID.randomUUID(); - NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, config.getString("world"), - typeRegistry.getByName(config.getString("type")), deserializeLocation(config.getConfigurationSection("location"))); - - if (config.isBoolean("enabled")) npc.setEnabled(config.getBoolean("enabled")); - - ConfigurationSection properties = config.getConfigurationSection("properties"); - if (properties != null) { - for (String key : properties.getKeys(false)) { - EntityPropertyImpl property = propertyRegistry.getByName(key); - if (property == null) { - Bukkit.getLogger().log(Level.WARNING, "Unknown property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); - continue; - } - PropertySerializer serializer = propertyRegistry.getSerializer(property.getType()); - if (serializer == null) { - Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); - continue; - } - Object value = serializer.deserialize(properties.getString(key)); - if (value == null) { - Bukkit.getLogger().log(Level.WARNING, "Failed to deserialize property '" + key + "' for npc '" + config.getString("id") + "'. Resetting to default ..."); - value = property.getDefaultValue(); - } - npc.UNSAFE_setProperty(property, value); - } - } - HologramImpl hologram = npc.getHologram(); - hologram.setOffset(config.getDouble("hologram.offset", 0.0)); - hologram.setRefreshDelay(config.getLong("hologram.refresh-delay", -1)); - for (String line : config.getStringList("hologram.lines")) hologram.addLine(line); - for (String s : config.getStringList("actions")) npc.addAction(actionRegistry.deserialize(s)); - - NpcEntryImpl entry = new NpcEntryImpl(config.getString("id"), npc); - entry.setProcessed(config.getBoolean("is-processed")); - entry.setAllowCommandModification(config.getBoolean("allow-commands")); - entry.setSave(true); - - npcs.add(entry); + npcs.add((NpcEntryImpl) yamlSerializer.deserialize(config)); } catch (Throwable t) { logger.severe("Failed to load npc file: " + file.getName()); t.printStackTrace(); @@ -102,43 +45,7 @@ public class YamlStorage implements NpcStorage { @Override public void saveNpcs(Collection npcs) { for (NpcEntryImpl entry : npcs) try { - YamlConfiguration config = new YamlConfiguration(); - config.set("id", entry.getId()); - config.set("is-processed", entry.isProcessed()); - config.set("allow-commands", entry.isAllowCommandModification()); - - NpcImpl npc = entry.getNpc(); - config.set("enabled", npc.isEnabled()); - config.set("uuid", npc.getUuid().toString()); - config.set("world", npc.getWorldName()); - config.set("location", serializeLocation(npc.getLocation())); - config.set("type", npc.getType().getName()); - - for (EntityProperty property : npc.getAllProperties()) try { - PropertySerializer serializer = propertyRegistry.getSerializer(((EntityPropertyImpl) property).getType()); - if (serializer == null) { - Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + property.getName() + "' for npc '" + entry.getId() + "'. skipping ..."); - continue; - } - config.set("properties." + property.getName(), serializer.UNSAFE_serialize(npc.getProperty(property))); - } catch (Exception exception) { - logger.severe("Failed to serialize property " + property.getName() + " for npc with id " + entry.getId()); - exception.printStackTrace(); - } - - HologramImpl hologram = npc.getHologram(); - if (hologram.getOffset() != 0.0) config.set("hologram.offset", hologram.getOffset()); - if (hologram.getRefreshDelay() != -1) config.set("hologram.refresh-delay", hologram.getRefreshDelay()); - List lines = new ArrayList<>(npc.getHologram().getLines().size()); - for (int i = 0; i < hologram.getLines().size(); i++) { - lines.add(hologram.getLine(i)); - } - config.set("hologram.lines", lines); - config.set("actions", npc.getActions().stream() - .map(actionRegistry::serialize) - .filter(Objects::nonNull) - .collect(Collectors.toList())); - + YamlConfiguration config = yamlSerializer.serialize(entry); config.save(fileFor(entry)); } catch (Exception exception) { logger.severe("Failed to save npc with id " + entry.getId()); -- 2.45.2 From b3b8635477bc43c65bbb33f682935666fd1003bd Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 24 Dec 2024 16:14:00 +0100 Subject: [PATCH 29/56] expose save and reload in npc registry to the api --- .../java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java index b822354..8a39418 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java @@ -71,4 +71,14 @@ public interface NpcRegistry { * @param entry The npc to be registered */ void register(NpcEntry entry); + + /** + * Reload all saveable npcs from storage + */ + void reload(); + + /** + * Save all saveable npcs to storage + */ + void save(); } -- 2.45.2 From 55104b56f39ff799d1fd477dd88c8ecf96be37bc Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Fri, 27 Dec 2024 11:58:38 +0100 Subject: [PATCH 30/56] make save true by default in yaml deserializer --- .../java/lol/pyr/znpcsplus/serialization/YamlSerializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java index 6a87564..094a493 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java @@ -127,7 +127,7 @@ public class YamlSerializer implements NpcSerializer { NpcEntryImpl entry = new NpcEntryImpl(config.getString("id"), npc); entry.setProcessed(config.getBoolean("is-processed")); entry.setAllowCommandModification(config.getBoolean("allow-commands")); - entry.setSave(config.getBoolean("save")); + entry.setSave(config.getBoolean("save", true)); return entry; } -- 2.45.2 From 9d1d8f9bb093fc6d34b4907b8a1c57880ba51171 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Fri, 27 Dec 2024 12:02:36 +0100 Subject: [PATCH 31/56] bump version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1ec5bfc..39cfcbd 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ subprojects { apply plugin: "java" group "lol.pyr" - version "2.0.0" + (System.getenv().containsKey("BUILD_ID") ? "-SNAPSHOT" : "") + version "2.1.0" + (System.getenv().containsKey("BUILD_ID") ? "-SNAPSHOT" : "") java { toolchain.languageVersion.set(JavaLanguageVersion.of(8)) -- 2.45.2 From b8dda22154a1fa49752ae5b215c8dee85b06ba50 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 18:25:22 +0530 Subject: [PATCH 32/56] feat: added look_return property --- .../entity/EntityPropertyRegistryImpl.java | 1 + .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 19 +++++++++++++++++++ .../lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 2 +- .../pyr/znpcsplus/tasks/NpcProcessorTask.java | 17 ++++++++++++++--- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 024a28a..8105e76 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -126,6 +126,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { register(new DummyProperty<>("look", LookType.FIXED)); register(new DummyProperty<>("look_distance", configManager.getConfig().lookPropertyDistance())); + register(new DummyProperty<>("look_return", false)); register(new DummyProperty<>("view_distance", configManager.getConfig().viewDistance())); register(new DummyProperty<>("permission_required", false)); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index d340f32..2be57a3 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class NpcImpl extends Viewable implements Npc { @@ -40,6 +41,8 @@ public class NpcImpl extends Viewable implements Npc { private final Map, Object> propertyMap = new HashMap<>(); private final List actions = new ArrayList<>(); + private final Map playerLookMap = new ConcurrentHashMap<>(); + protected NpcImpl(UUID uuid, EntityPropertyRegistryImpl propertyRegistry, ConfigManager configManager, LegacyComponentSerializer textSerializer, World world, NpcTypeImpl type, NpcLocation location, PacketFactory packetFactory) { this(uuid, propertyRegistry, configManager, packetFactory, textSerializer, world.getName(), type, location); } @@ -87,20 +90,34 @@ public class NpcImpl extends Viewable implements Npc { public void setLocation(NpcLocation location) { this.location = location; + playerLookMap.clear(); + playerLookMap.putAll(getViewers().stream().collect(Collectors.toMap(Player::getUniqueId, player -> new float[]{location.getYaw(), location.getPitch()}))); entity.setLocation(location); hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); } public void setHeadRotation(Player player, float yaw, float pitch) { + if (getHeadYaw(player) == yaw && getHeadPitch(player) == pitch) return; + playerLookMap.put(player.getUniqueId(), new float[]{yaw, pitch}); entity.setHeadRotation(player, yaw, pitch); } public void setHeadRotation(float yaw, float pitch) { for (Player player : getViewers()) { + if (getHeadYaw(player) == yaw && getHeadPitch(player) == pitch) continue; + playerLookMap.put(player.getUniqueId(), new float[]{yaw, pitch}); entity.setHeadRotation(player, yaw, pitch); } } + public float getHeadYaw(Player player) { + return playerLookMap.getOrDefault(player.getUniqueId(), new float[]{location.getYaw(), location.getPitch()})[0]; + } + + public float getHeadPitch(Player player) { + return playerLookMap.getOrDefault(player.getUniqueId(), new float[]{location.getYaw(), location.getPitch()})[1]; + } + public HologramImpl getHologram() { return hologram; } @@ -128,11 +145,13 @@ public class NpcImpl extends Viewable implements Npc { @Override protected CompletableFuture UNSAFE_show(Player player) { + playerLookMap.put(player.getUniqueId(), new float[]{location.getYaw(), location.getPitch()}); return CompletableFuture.allOf(entity.spawn(player), hologram.show(player)); } @Override protected void UNSAFE_hide(Player player) { + playerLookMap.remove(player.getUniqueId()); entity.despawn(player); hologram.hide(player); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index f62adb8..207e75c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -114,7 +114,7 @@ public class NpcTypeImpl implements NpcType { public NpcTypeImpl build() { ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); - addProperties("fire", "invisible", "silent", "look", "look_distance", "view_distance", + addProperties("fire", "invisible", "silent", "look", "look_distance", "look_return", "view_distance", "potion_color", "potion_ambient", "display_name", "permission_required", "player_knockback", "player_knockback_exempt_permission", "player_knockback_distance", "player_knockback_vertical", "player_knockback_horizontal", "player_knockback_cooldown", "player_knockback_sound", "player_knockback_sound_name", diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java b/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java index e0cdcf1..a975546 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java @@ -33,6 +33,7 @@ public class NpcProcessorTask extends BukkitRunnable { EntityPropertyImpl viewDistanceProperty = propertyRegistry.getByName("view_distance", Integer.class); // Not sure why this is an Integer, but it is EntityPropertyImpl lookProperty = propertyRegistry.getByName("look", LookType.class); EntityPropertyImpl lookDistanceProperty = propertyRegistry.getByName("look_distance", Double.class); + EntityPropertyImpl lookReturnProperty = propertyRegistry.getByName("look_return", Boolean.class); EntityPropertyImpl permissionRequiredProperty = propertyRegistry.getByName("permission_required", Boolean.class); EntityPropertyImpl playerKnockbackProperty = propertyRegistry.getByName("player_knockback", Boolean.class); EntityPropertyImpl playerKnockbackExemptPermissionProperty = propertyRegistry.getByName("player_knockback_exempt_permission", String.class); @@ -45,6 +46,7 @@ public class NpcProcessorTask extends BukkitRunnable { EntityPropertyImpl playerKnockbackSoundVolumeProperty = propertyRegistry.getByName("player_knockback_sound_volume", Float.class); EntityPropertyImpl playerKnockbackSoundPitchProperty = propertyRegistry.getByName("player_knockback_sound_pitch", Float.class); double lookDistance; + boolean lookReturn; boolean permissionRequired; boolean playerKnockback; String playerKnockbackExemptPermission = null; @@ -64,6 +66,7 @@ public class NpcProcessorTask extends BukkitRunnable { Player closest = null; LookType lookType = npc.getProperty(lookProperty); lookDistance = NumberConversions.square(npc.getProperty(lookDistanceProperty)); + lookReturn = npc.getProperty(lookReturnProperty); permissionRequired = npc.getProperty(permissionRequiredProperty); playerKnockback = npc.getProperty(playerKnockbackProperty); if (playerKnockback) { @@ -106,9 +109,13 @@ public class NpcProcessorTask extends BukkitRunnable { closestDist = distance; closest = player; } - if (lookType.equals(LookType.PER_PLAYER) && lookDistance >= distance) { - NpcLocation expected = npc.getLocation().lookingAt(player.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); - if (!expected.equals(npc.getLocation())) npc.setHeadRotation(player, expected.getYaw(), expected.getPitch()); + if (lookType.equals(LookType.PER_PLAYER)) { + if (lookDistance >= distance) { + NpcLocation expected = npc.getLocation().lookingAt(player.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); + npc.setHeadRotation(player, expected.getYaw(), expected.getPitch()); + } else if (lookReturn) { + npc.setHeadRotation(player, npc.getLocation().getYaw(), npc.getLocation().getPitch()); + } } // player knockback @@ -132,7 +139,11 @@ public class NpcProcessorTask extends BukkitRunnable { if (closest != null && lookDistance >= closestDist) { NpcLocation expected = npc.getLocation().lookingAt(closest.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); if (!expected.equals(npc.getLocation())) npc.setHeadRotation(expected.getYaw(), expected.getPitch()); + } else if (lookReturn) { + npc.setHeadRotation(npc.getLocation().getYaw(), npc.getLocation().getPitch()); } + } else if (lookType.equals(LookType.FIXED)) { + npc.setHeadRotation(npc.getLocation().getYaw(), npc.getLocation().getPitch()); } } } -- 2.45.2 From 218c4e48cc083dd30f4c574795703bb558d17ac4 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 18:26:45 +0530 Subject: [PATCH 33/56] fix: glow import for znpcs --- .../znpcsplus/conversion/znpcs/ZNpcImporter.java | 13 ++++++++----- .../conversion/znpcs/model/ZNpcsModel.java | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java index dccf704..604347f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java @@ -189,12 +189,15 @@ public class ZNpcImporter implements DataImporter { if (toggleValues.containsKey("mirror")) { npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new MirrorDescriptor(skinCache)); } - if (toggleValues.containsKey("glow")) { - try { - npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.valueOf((String) toggleValues.get("glow"))); - } catch (IllegalArgumentException e) { + if (toggleValues.containsKey("glow") && (boolean) toggleValues.get("glow")) { + if (!model.getGlowName().isEmpty()) + try { + npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.valueOf(model.getGlowName())); + } catch (IllegalArgumentException e) { + npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.WHITE); + } + else npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.WHITE); - } } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java index 67ecfa0..987a9b4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java @@ -84,4 +84,8 @@ public class ZNpcsModel { public String getSignature() { return signature; } + + public String getGlowName() { + return glowName; + } } \ No newline at end of file -- 2.45.2 From 97fd7bfd762e2f9788b92bdd0ce33ec69dfd39b8 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 19:15:36 +0530 Subject: [PATCH 34/56] feat: added attribute_max_health and health properties --- .../commands/property/PropertySetCommand.java | 10 +++ .../entity/EntityPropertyRegistryImpl.java | 12 ++++ .../entity/properties/HealthProperty.java | 27 ++++++++ .../attributes/AttributeProperty.java | 63 +++++++++++++++++++ .../lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 3 + .../pyr/znpcsplus/packets/PacketFactory.java | 3 + .../znpcsplus/packets/V1_17PacketFactory.java | 2 + .../packets/V1_20_2PacketFactory.java | 1 + .../znpcsplus/packets/V1_8PacketFactory.java | 18 ++++++ 9 files changed, 139 insertions(+) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java index 334d7f6..53a5e25 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java @@ -11,6 +11,7 @@ import lol.pyr.director.adventure.command.CommandHandler; import lol.pyr.director.common.command.CommandExecutionException; import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.properties.attributes.AttributeProperty; import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; @@ -124,6 +125,15 @@ public class PropertySetCommand implements CommandHandler { value = context.parse(type); valueName = value == null ? "NONE" : ((Vector3i) value).toPrettyString(); } + else if (property instanceof AttributeProperty) { + value = context.parse(type); + if ((double) value < ((AttributeProperty) property).getMinValue() || (double) value > ((AttributeProperty) property).getMaxValue()) { + double sanitizedValue = ((AttributeProperty) property).sanitizeValue((double) value); + context.send(Component.text("WARNING: Value " + value + " is out of range for property " + property.getName() + ", setting to " + sanitizedValue, NamedTextColor.YELLOW)); + value = sanitizedValue; + } + valueName = String.valueOf(value); + } else { try { value = context.parse(type); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 8105e76..b4ba5b2 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -2,6 +2,7 @@ package lol.pyr.znpcsplus.entity; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.attribute.Attributes; import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -15,6 +16,7 @@ import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; import lol.pyr.znpcsplus.api.skin.SkinDescriptor; import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.entity.properties.*; +import lol.pyr.znpcsplus.entity.properties.attributes.AttributeProperty; import lol.pyr.znpcsplus.entity.properties.villager.VillagerLevelProperty; import lol.pyr.znpcsplus.entity.properties.villager.VillagerProfessionProperty; import lol.pyr.znpcsplus.entity.properties.villager.VillagerTypeProperty; @@ -154,6 +156,16 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { linkProperties("glow", "fire", "invisible"); register(new BooleanProperty("silent", 4, false, legacyBooleans)); + // Attribute Max Health + register(new AttributeProperty(packetFactory, "attribute_max_health", Attributes.MAX_HEALTH)); + + // Health - LivingEntity + int healthIndex = 6; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) healthIndex = 9; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) healthIndex = 8; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) healthIndex = 7; + register(new HealthProperty(healthIndex)); + final int tameableIndex; if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) tameableIndex = 17; else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) tameableIndex = 16; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java new file mode 100644 index 0000000..82615c5 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java @@ -0,0 +1,27 @@ +package lol.pyr.znpcsplus.entity.properties; + +import com.github.retrooper.packetevents.protocol.attribute.Attributes; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class HealthProperty extends EntityPropertyImpl { + private final int index; + + public HealthProperty(int index) { + super("health", 20f, Float.class); + this.index = index; + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + float health = entity.getProperty(this); + health = (float) Attributes.MAX_HEALTH.sanitizeValue(health); + properties.put(index, new EntityData(index, EntityDataTypes.FLOAT, health)); + + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java new file mode 100644 index 0000000..30ae5af --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java @@ -0,0 +1,63 @@ +package lol.pyr.znpcsplus.entity.properties.attributes; + +import com.github.retrooper.packetevents.protocol.attribute.Attribute; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.packets.PacketFactory; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class AttributeProperty extends EntityPropertyImpl { + private final PacketFactory packetFactory; + private final Attribute attribute; + + public AttributeProperty(PacketFactory packetFactory, String name, Attribute attribute) { + super(name, attribute.getDefaultValue(), Double.class); + this.packetFactory = packetFactory; + this.attribute = attribute; + } + + public double getMinValue() { + return attribute.getMinValue(); + } + + public double getMaxValue() { + return attribute.getMaxValue(); + } + + public double sanitizeValue(double value) { + return attribute.sanitizeValue(value); + } + + @Override + public List applyStandalone(Player player, PacketEntity packetEntity, boolean isSpawned) { + apply(player, packetEntity, isSpawned, Collections.emptyList()); + return Collections.emptyList(); + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + } + + public void apply(Player player, PacketEntity entity, boolean isSpawned, List properties) { + Double value = entity.getProperty(this); + if (value == null) { + return; + } + value = attribute.sanitizeValue(value); + if (isSpawned) { + packetFactory.sendAttribute(player, entity, new WrapperPlayServerUpdateAttributes.Property(attribute, value, Collections.emptyList())); + } else { + properties.add(new WrapperPlayServerUpdateAttributes.Property(attribute, value, Collections.emptyList())); + } + } + + public Attribute getAttribute() { + return attribute; + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index 207e75c..b2eae03 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -120,6 +120,9 @@ public class NpcTypeImpl implements NpcType { "player_knockback_horizontal", "player_knockback_cooldown", "player_knockback_sound", "player_knockback_sound_name", "player_knockback_sound_volume", "player_knockback_sound_pitch"); if (!type.equals(EntityTypes.PLAYER)) addProperties("dinnerbone"); + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.LIVINGENTITY)) { + addProperties("health", "attribute_max_health"); + } // TODO: make this look nicer after completing the rest of the properties if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow"); if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index f2b58c1..1d3ba41 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -2,6 +2,7 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.player.Equipment; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.util.NamedColor; @@ -25,4 +26,6 @@ public interface PacketFactory { void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); void sendHandSwing(Player player, PacketEntity entity, boolean offHand); void setPassengers(Player player, int vehicle, int... passengers); + void sendAllAttributes(Player player, PacketEntity entity, PropertyHolder properties); + void sendAttribute(Player player, PacketEntity entity, WrapperPlayServerUpdateAttributes.Property property); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java index 45b6e41..5a97fbf 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java @@ -1,6 +1,7 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEventsAPI; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; import lol.pyr.znpcsplus.api.entity.PropertyHolder; @@ -27,6 +28,7 @@ public class V1_17PacketFactory extends V1_8PacketFactory { sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d()))); sendAllMetadata(player, entity, properties); + if (EntityTypes.isTypeInstanceOf(entity.getType(), EntityTypes.LIVINGENTITY)) sendAllAttributes(player, entity, properties); createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java index 9d5de17..4a760e4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java @@ -36,6 +36,7 @@ public class V1_20_2PacketFactory extends V1_19_3PacketFactory { npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d()))); sendPacket(player, new WrapperPlayServerEntityHeadLook(entity.getEntityId(), location.getYaw())); sendAllMetadata(player, entity, properties); + sendAllAttributes(player, entity, properties); scheduler.runLaterAsync(() -> removeTabPlayer(player, entity), configManager.getConfig().tabHideDelay()); }); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index 3fe0504..e288aa2 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -18,6 +18,7 @@ import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.entity.EntityPropertyImpl; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.properties.attributes.AttributeProperty; import lol.pyr.znpcsplus.scheduling.TaskScheduler; import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; import lol.pyr.znpcsplus.util.NamedColor; @@ -55,6 +56,7 @@ public class V1_8PacketFactory implements PacketFactory { entity.getUuid(), npcLocationToVector(location), location.getYaw(), location.getPitch(), Collections.emptyList())); sendPacket(player, new WrapperPlayServerEntityHeadLook(entity.getEntityId(), location.getYaw())); sendAllMetadata(player, entity, properties); + sendAllAttributes(player, entity, properties); scheduler.runLaterAsync(() -> removeTabPlayer(player, entity), configManager.getConfig().tabHideDelay()); }); } @@ -70,6 +72,7 @@ public class V1_8PacketFactory implements PacketFactory { new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); sendAllMetadata(player, entity, properties); + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.LIVINGENTITY)) sendAllAttributes(player, entity, properties); createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); } @@ -187,4 +190,19 @@ public class V1_8PacketFactory implements PacketFactory { WrapperPlayServerEntityAnimation.EntityAnimationType.SWING_OFF_HAND : WrapperPlayServerEntityAnimation.EntityAnimationType.SWING_MAIN_ARM)); } + + @Override + public void sendAllAttributes(Player player, PacketEntity entity, PropertyHolder properties) { + List attributesList = new ArrayList<>(); + properties.getAppliedProperties() + .stream() + .filter(property -> property instanceof AttributeProperty) + .forEach(property -> ((AttributeProperty) property).apply(player, entity, false, attributesList)); + sendPacket(player, new WrapperPlayServerUpdateAttributes(entity.getEntityId(), attributesList)); + } + + @Override + public void sendAttribute(Player player, PacketEntity entity, WrapperPlayServerUpdateAttributes.Property property) { + sendPacket(player, new WrapperPlayServerUpdateAttributes(entity.getEntityId(), Collections.singletonList(property))); + } } -- 2.45.2 From ba75abcebcfbdc35e5e0cd6ca55ea9168d628ead Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 19:30:50 +0530 Subject: [PATCH 35/56] feat: added version command --- plugin/build.gradle | 18 ++++++ .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 1 + .../znpcsplus/commands/VersionCommand.java | 64 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java diff --git a/plugin/build.gradle b/plugin/build.gradle index 7cbf95f..ac8ee3d 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -30,10 +30,28 @@ dependencies { implementation project(":api") } +ext { + gitBranch = System.getenv('GIT_BRANCH') ?: '' + gitCommitHash = System.getenv('GIT_COMMIT') ?: '' + buildId = System.getenv('BUILD_ID') ?: '' +} + shadowJar { archivesBaseName = "ZNPCsPlus" archiveClassifier.set "" + manifest { + if (gitBranch?.trim()) { + attributes('Git-Branch': gitBranch) + } + if (gitCommitHash?.trim()) { + attributes('Git-Commit': gitCommitHash) + } + if (buildId?.trim()) { + attributes('Build-Id': buildId) + } + } + relocate "org.objectweb.asm", "lol.pyr.znpcsplus.libraries.asm" relocate "me.lucko.jarrelocator", "lol.pyr.znpcsplus.libraries.jarrelocator" diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index 2a0d64f..2a12c2d 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -342,6 +342,7 @@ public class ZNpcsPlus { .addSubcommand("delete", new ActionDeleteCommand(npcRegistry)) .addSubcommand("edit", new ActionEditCommand(npcRegistry, actionRegistry)) .addSubcommand("list", new ActionListCommand(npcRegistry))) + .addSubcommand("version", new VersionCommand(this)) ); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java new file mode 100644 index 0000000..f59bf17 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java @@ -0,0 +1,64 @@ +package lol.pyr.znpcsplus.commands; + +import lol.pyr.director.adventure.command.CommandContext; +import lol.pyr.director.adventure.command.CommandHandler; +import lol.pyr.director.common.command.CommandExecutionException; +import lol.pyr.znpcsplus.ZNpcsPlus; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.jar.Attributes; +import java.util.jar.JarFile; + +public class VersionCommand implements CommandHandler { + + private final String pluginVersion; + private final String gitBranch; + private final String gitCommitHash; + private final String buildId; + + public VersionCommand(ZNpcsPlus plugin) { + pluginVersion = plugin.getDescription().getVersion(); + String gitBranch = ""; + String gitCommitHash = ""; + String buildId = ""; + try { + URL jarUrl = getClass().getProtectionDomain().getCodeSource().getLocation(); + JarFile jarFile = new JarFile(jarUrl.toURI().getPath()); + Attributes attributes = jarFile.getManifest().getMainAttributes(); + gitBranch = attributes.getValue("Git-Branch"); + gitCommitHash = attributes.getValue("Git-Commit-Hash"); + buildId = attributes.getValue("Build-Id"); + } catch (IOException | URISyntaxException e) { + e.printStackTrace(); + } + this.gitBranch = gitBranch; + this.gitCommitHash = gitCommitHash; + this.buildId = buildId; + } + + @Override + public void run(CommandContext context) throws CommandExecutionException { + + StringBuilder versionBuilder = new StringBuilder("This server is running ZNPCsPlus version ").append(pluginVersion); + if (gitBranch != null && !gitBranch.isEmpty()) { + versionBuilder.append("-").append(gitBranch); + } + if (gitCommitHash != null && !gitCommitHash.isEmpty()) { + versionBuilder.append("@").append(gitCommitHash); + } + if (buildId != null && !buildId.isEmpty()) { + versionBuilder.append(" (Build #").append(buildId).append(")"); + } + + String version = versionBuilder.toString(); + + context.send(Component.text(version, NamedTextColor.GREEN) + .hoverEvent(Component.text("Click to copy version to clipboard")) + .clickEvent(ClickEvent.copyToClipboard(version))); + } +} -- 2.45.2 From d1b890a9126632e988b3ac86d75f40928822ef91 Mon Sep 17 00:00:00 2001 From: envizar Date: Sun, 29 Dec 2024 14:13:37 +0300 Subject: [PATCH 36/56] toggle command with arg --- .../lol/pyr/znpcsplus/commands/ToggleCommand.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java index c6d1c06..764f771 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java @@ -11,6 +11,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import java.util.Collections; import java.util.List; +import java.util.Set; public class ToggleCommand implements CommandHandler { private final NpcRegistryImpl npcRegistry; @@ -21,9 +22,14 @@ public class ToggleCommand implements CommandHandler { @Override public void run(CommandContext context) throws CommandExecutionException { - context.setUsage(context.getLabel() + " toggle "); + context.setUsage(context.getLabel() + " toggle []"); NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); - boolean enabled = !npc.isEnabled(); + boolean enabled; + if (context.argSize() == 1) { + enabled = context.popString().equals("enable"); + } else { + enabled = !npc.isEnabled(); + } npc.setEnabled(enabled); context.send(Component.text("NPC has been " + (enabled ? "enabled" : "disabled"), NamedTextColor.GREEN)); } @@ -31,6 +37,7 @@ public class ToggleCommand implements CommandHandler { @Override public List suggest(CommandContext context) throws CommandExecutionException { if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); + if (context.argSize() == 2) return context.suggestLiteral("enable", "disable"); return Collections.emptyList(); } } -- 2.45.2 From dfdcc54313639e0a190e5581dc44368550b18c94 Mon Sep 17 00:00:00 2001 From: envizar Date: Sun, 29 Dec 2024 14:29:17 +0300 Subject: [PATCH 37/56] default type = player in create command --- .../java/lol/pyr/znpcsplus/commands/CreateCommand.java | 10 ++++++++-- .../java/lol/pyr/znpcsplus/commands/ToggleCommand.java | 1 - 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java index 1c3c1e9..341edca 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java @@ -26,12 +26,18 @@ public class CreateCommand implements CommandHandler { @Override public void run(CommandContext context) throws CommandExecutionException { - context.setUsage(context.getLabel() + " create "); + context.setUsage(context.getLabel() + " create []"); Player player = context.ensureSenderIsPlayer(); String id = context.popString(); if (npcRegistry.getById(id) != null) context.halt(Component.text("NPC with that ID already exists.", NamedTextColor.RED)); - NpcTypeImpl type = context.parse(NpcTypeImpl.class); + + NpcTypeImpl type; + if (context.argSize() == 1) { + type = context.parse(NpcTypeImpl.class); + } else { + type = typeRegistry.getByName("player"); + } NpcEntryImpl entry = npcRegistry.create(id, player.getWorld(), type, new NpcLocation(player.getLocation())); entry.enableEverything(); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java index 764f771..4b122d6 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java @@ -11,7 +11,6 @@ import net.kyori.adventure.text.format.NamedTextColor; import java.util.Collections; import java.util.List; -import java.util.Set; public class ToggleCommand implements CommandHandler { private final NpcRegistryImpl npcRegistry; -- 2.45.2 From ec60af7186b43ea8da0c662646ecbc5f04e31815 Mon Sep 17 00:00:00 2001 From: envizar Date: Sun, 29 Dec 2024 14:43:19 +0300 Subject: [PATCH 38/56] This should be equalsIgnoreCase --- .../src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java index 4b122d6..60a09c8 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java @@ -25,7 +25,7 @@ public class ToggleCommand implements CommandHandler { NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); boolean enabled; if (context.argSize() == 1) { - enabled = context.popString().equals("enable"); + enabled = context.popString().equalsIgnoreCase("enable"); } else { enabled = !npc.isEnabled(); } -- 2.45.2 From c0bcbcf7a3491dd69c42debd78c969a60889071a Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 29 Dec 2024 13:49:52 +0100 Subject: [PATCH 39/56] expose file descriptor in api --- .../lol/pyr/znpcsplus/api/skin/SkinDescriptorFactory.java | 1 + .../lol/pyr/znpcsplus/skin/SkinDescriptorFactoryImpl.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/skin/SkinDescriptorFactory.java b/api/src/main/java/lol/pyr/znpcsplus/api/skin/SkinDescriptorFactory.java index 41313c1..c5573e7 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/skin/SkinDescriptorFactory.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/skin/SkinDescriptorFactory.java @@ -12,4 +12,5 @@ public interface SkinDescriptorFactory { SkinDescriptor createStaticDescriptor(String texture, String signature); SkinDescriptor createUrlDescriptor(String url, String variant); SkinDescriptor createUrlDescriptor(URL url, String variant); + SkinDescriptor createFileDescriptor(String path); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptorFactoryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptorFactoryImpl.java index 0eeb491..b4557e6 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptorFactoryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptorFactoryImpl.java @@ -52,4 +52,9 @@ public class SkinDescriptorFactoryImpl implements SkinDescriptorFactory { public SkinDescriptor createUrlDescriptor(URL url, String variant) { return PrefetchedDescriptor.fromUrl(skinCache, url, variant).join(); } + + @Override + public SkinDescriptor createFileDescriptor(String path) { + return PrefetchedDescriptor.fromFile(skinCache, path).join(); + } } -- 2.45.2 From ad8138f9833685914fa159199000aba2efc8fbba Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 29 Dec 2024 13:51:33 +0100 Subject: [PATCH 40/56] fix llama properties on 1.20+ --- plugin/build.gradle | 2 +- .../pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java | 6 +++++- .../java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugin/build.gradle b/plugin/build.gradle index 7cbf95f..3101f47 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -8,7 +8,7 @@ runServer { javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(21) } - minecraftVersion "1.21.3" + minecraftVersion "1.21.4" } processResources { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 024a28a..a54ff96 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -493,7 +493,9 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) llamaIndex = 20; else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) llamaIndex = 19; else llamaIndex = 17; - register(new EncodedIntegerProperty("carpet_color", DyeColor.class, llamaIndex++, obj -> obj == null ? -1 : obj.ordinal())); + + // Removed in 1.20 + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_20)) register(new EncodedIntegerProperty("carpet_color", DyeColor.class, llamaIndex++, obj -> obj == null ? -1 : obj.ordinal())); register(new EncodedIntegerProperty<>("llama_variant", LlamaVariant.CREAMY, llamaIndex, Enum::ordinal)); if (!ver.isNewerThanOrEquals(ServerVersion.V_1_12)) return; @@ -655,6 +657,8 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { if (!ver.isNewerThanOrEquals(ServerVersion.V_1_20)) return; + register(new EquipmentProperty(packetFactory, "body", EquipmentSlot.BODY)); + // Camel int camelIndex = 18; register(new BooleanProperty("bashing", camelIndex++, false, legacyBooleans)); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 5a23efc..7c480a7 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -221,7 +221,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { register(builder(p, "llama", EntityTypes.LLAMA) .setHologramOffset(-0.105) - .addProperties("carpet_color", "llama_variant")); + .addProperties("carpet_color", "llama_variant", "body")); register(builder(p, "vex", EntityTypes.VEX) .setHologramOffset(-1.175) -- 2.45.2 From dd8899163cd9bdc09f645711103b58ba2ebd26c4 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 29 Dec 2024 14:00:35 +0100 Subject: [PATCH 41/56] move body property to the right place --- .../lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 93b0259..d0f0e22 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -670,8 +670,6 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { if (!ver.isNewerThanOrEquals(ServerVersion.V_1_20)) return; - register(new EquipmentProperty(packetFactory, "body", EquipmentSlot.BODY)); - // Camel int camelIndex = 18; register(new BooleanProperty("bashing", camelIndex++, false, legacyBooleans)); @@ -690,6 +688,8 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { if (!ver.isNewerThanOrEquals(ServerVersion.V_1_21)) return; + register(new EquipmentProperty(packetFactory, "body", EquipmentSlot.BODY)); + // Bogged register(new BooleanProperty("bogged_sheared", 16, false, legacyBooleans)); -- 2.45.2 From 86c5b9c3259a98025845225dd0a523f229fe6f54 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 29 Dec 2024 17:18:59 +0100 Subject: [PATCH 42/56] fix carpet_color on 1.20-1.20.4 --- .../lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index d0f0e22..4a43cd4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -507,8 +507,8 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) llamaIndex = 19; else llamaIndex = 17; - // Removed in 1.20 - if (!ver.isNewerThanOrEquals(ServerVersion.V_1_20)) register(new EncodedIntegerProperty("carpet_color", DyeColor.class, llamaIndex++, obj -> obj == null ? -1 : obj.ordinal())); + // Removed in 1.21 + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_21)) register(new EncodedIntegerProperty("carpet_color", DyeColor.class, llamaIndex++, obj -> obj == null ? -1 : obj.ordinal())); register(new EncodedIntegerProperty<>("llama_variant", LlamaVariant.CREAMY, llamaIndex, Enum::ordinal)); if (!ver.isNewerThanOrEquals(ServerVersion.V_1_12)) return; -- 2.45.2 From ca8a1d649950ea5ac03538c3a30b7b9c12cb33a8 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 8 Jan 2025 02:22:28 +0100 Subject: [PATCH 43/56] switch viewers list back to a concurrent set --- plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java index 190f13e..9001b1e 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java @@ -6,6 +6,7 @@ import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Collectors; @@ -21,7 +22,7 @@ public abstract class Viewable { private boolean queueRunning = false; private final Queue visibilityTaskQueue = new ConcurrentLinkedQueue<>(); - private final Set viewers = new HashSet<>(); + private final Set viewers = ConcurrentHashMap.newKeySet(); public Viewable() { all.add(new WeakReference<>(this)); -- 2.45.2 From c521eb9a51a5b5da06d687b5e854ff81b5d83688 Mon Sep 17 00:00:00 2001 From: that-apex Date: Wed, 20 Dec 2023 18:27:25 +0100 Subject: [PATCH 44/56] feat(ci): add drone # Conflicts: # build.gradle --- .drone.yml | 18 ++++++++++++++++++ api/build.gradle | 12 ------------ build.gradle | 20 +++++++++++++++++++- gradlew | 0 plugin/build.gradle | 15 +++++++++++++++ 5 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 .drone.yml mode change 100644 => 100755 gradlew diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..7c6f5d3 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,18 @@ +kind: pipeline +type: docker +name: default + +trigger: + event: + - push + - custom + +steps: + - name: publish + pull: if-not-exists + image: openjdk:8-jdk + environment: + PACKAGESKEY: + from_secret: GITEA_PACKAGE_PUBLIC_RW + commands: + - ./gradlew --no-daemon --parallel -Pnetherite.git.packages.token=$PACKAGESKEY build publish diff --git a/api/build.gradle b/api/build.gradle index 349cf17..98f5894 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1,6 +1,5 @@ plugins { id "java" - id "maven-publish" } java { @@ -21,15 +20,4 @@ publishing { } } } - repositories { - maven { - Map systemProperties = System.getenv() - credentials { - if (systemProperties.containsKey("DIST_USERNAME")) username systemProperties.get("DIST_USERNAME") - if (systemProperties.containsKey("DIST_PASSWORD")) password systemProperties.get("DIST_PASSWORD") - } - // If the BUILD_ID enviroment variable is present that means its a Jenkins build & that it should go into the snapshots repo - url = systemProperties.containsKey("BUILD_ID") ? uri("https://repo.pyr.lol/snapshots/") : uri("https://repo.pyr.lol/releases/") - } - } } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 39cfcbd..64712e0 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ subprojects { apply plugin: "java" group "lol.pyr" - version "2.1.0" + (System.getenv().containsKey("BUILD_ID") ? "-SNAPSHOT" : "") + version "2.1.0-netherite-SNAPSHOT" java { toolchain.languageVersion.set(JavaLanguageVersion.of(8)) @@ -33,5 +33,23 @@ subprojects { maven { url "https://repo.pyr.lol/releases" } + maven { + url "https://jitpack.io/" + } + } + + publishing { + repositories { + maven { + url = uri("https://git.netherite.gg/api/packages/Netherite-Public/maven") + credentials(HttpHeaderCredentials) { + name "Authorization" + value "token ${project.properties["netherite.git.packages.token"]}" + } + authentication { + header(HttpHeaderAuthentication) + } + } + } } } diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/plugin/build.gradle b/plugin/build.gradle index b778a35..99fe7c4 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -15,6 +15,21 @@ processResources { expand("version": version) } +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifactId = "znpcsplus-plugin" + + pom { + name.set("znpcsplus-plugin") + description.set("The ZNPCsPlus plugin") + url.set("https://github.com/Pyrbu/ZNPCsPlus") + } + } + } +} + dependencies { compileOnly "me.clip:placeholderapi:2.11.6" // Placeholder support implementation "com.google.code.gson:gson:2.10.1" // JSON parsing -- 2.45.2 From 77093109971269c6bda770e0eacfde701a96534d Mon Sep 17 00:00:00 2001 From: bridge Date: Sat, 30 Mar 2024 20:13:09 +0100 Subject: [PATCH 45/56] chore: bump up to java 17 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 64712e0..08376ab 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ subprojects { version "2.1.0-netherite-SNAPSHOT" java { - toolchain.languageVersion.set(JavaLanguageVersion.of(8)) + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) } dependencies { -- 2.45.2 From c0789c8630a682f372573bd572289f584f689863 Mon Sep 17 00:00:00 2001 From: bridge Date: Mon, 1 Apr 2024 19:53:12 +0200 Subject: [PATCH 46/56] chore: update jdk image --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 7c6f5d3..0bd7598 100644 --- a/.drone.yml +++ b/.drone.yml @@ -10,7 +10,7 @@ trigger: steps: - name: publish pull: if-not-exists - image: openjdk:8-jdk + image: openjdk:17-jdk environment: PACKAGESKEY: from_secret: GITEA_PACKAGE_PUBLIC_RW -- 2.45.2 From 33bd65f7663ca865ef3fa6e2e163d1f02a36aeae Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Mon, 24 Jun 2024 16:24:21 +0530 Subject: [PATCH 47/56] small action command(s) fix --- .../java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java index b08ae1c..15bdb01 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java @@ -38,6 +38,7 @@ public class ActionRegistryImpl implements ActionRegistry { public List getCommands() { return serializerMap.values().stream() + .filter(type -> type instanceof InteractionActionImpl) .filter(type -> type instanceof InteractionCommandHandler) .map(type -> (InteractionCommandHandler) type) .collect(Collectors.toList()); -- 2.45.2 From cdda0f0e47edd0eb70143e6b78e6abcba44e0265 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Tue, 25 Jun 2024 01:16:03 +0530 Subject: [PATCH 48/56] fix action commands, ughh --- .../java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java index 15bdb01..b08ae1c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/interaction/ActionRegistryImpl.java @@ -38,7 +38,6 @@ public class ActionRegistryImpl implements ActionRegistry { public List getCommands() { return serializerMap.values().stream() - .filter(type -> type instanceof InteractionActionImpl) .filter(type -> type instanceof InteractionCommandHandler) .map(type -> (InteractionCommandHandler) type) .collect(Collectors.toList()); -- 2.45.2 From c68585868cf2e5b76d307257fafb8ad6bc2570b3 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Tue, 30 Apr 2024 19:21:12 +0530 Subject: [PATCH 49/56] added camel_sitting property --- .../src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 7c480a7..3bd2071 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -381,6 +381,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { .setHologramOffset(0.4) .addProperties("bashing", "camel_sitting")); + if (!version.isNewerThanOrEquals(ServerVersion.V_1_20_5)) return; register(builder(p, "armadillo", EntityTypes.ARMADILLO) -- 2.45.2 From 2248f3530c1d84412d29f959dc4db74e3ba6419d Mon Sep 17 00:00:00 2001 From: bridge Date: Mon, 24 Jun 2024 23:43:15 +0200 Subject: [PATCH 50/56] chore: update packetevents properly --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 08376ab..69f154e 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,9 @@ subprojects { maven { url "https://repo.codemc.io/repository/maven-releases/" } + maven { + url "https://repo.codemc.io/repository/maven-snapshots/" + } maven { url "https://libraries.minecraft.net" } -- 2.45.2 From 92682ea60f007b9f6b24b99a63260d5563ffffd2 Mon Sep 17 00:00:00 2001 From: bridge Date: Tue, 25 Jun 2024 01:07:11 +0200 Subject: [PATCH 51/56] chore: expose api methods we need --- .../java/lol/pyr/znpcsplus/api/interaction/ActionRegistry.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/interaction/ActionRegistry.java b/api/src/main/java/lol/pyr/znpcsplus/api/interaction/ActionRegistry.java index 6f5cedb..6dc61fa 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/interaction/ActionRegistry.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/interaction/ActionRegistry.java @@ -2,6 +2,7 @@ package lol.pyr.znpcsplus.api.interaction; public interface ActionRegistry { void register(InteractionActionType type); - void unregister(Class clazz); + T deserialize(String str); + String serialize(T action); } -- 2.45.2 From db2f14369d566598bc2d636ac6a4bad8c97b0227 Mon Sep 17 00:00:00 2001 From: bridge Date: Tue, 26 Nov 2024 16:13:50 +0100 Subject: [PATCH 52/56] refactor: do not shade packetevents --- plugin/src/main/resources/plugin.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugin/src/main/resources/plugin.yml b/plugin/src/main/resources/plugin.yml index 44dc2d4..91f6ca7 100644 --- a/plugin/src/main/resources/plugin.yml +++ b/plugin/src/main/resources/plugin.yml @@ -11,6 +11,9 @@ api-version: 1.13 folia-supported: true +depend: + - packetevents + softdepend: - PlaceholderAPI - ServersNPC -- 2.45.2 From f07acc0e778bfb3f3c81b8bfdc0f502e801646de Mon Sep 17 00:00:00 2001 From: bridge Date: Thu, 28 Nov 2024 18:37:52 +0100 Subject: [PATCH 53/56] feat: HoloRemoveDuplicateCommand --- .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 3 +- .../hologram/HoloRemoveDuplicateCommand.java | 58 +++++++++++++++++++ .../pyr/znpcsplus/hologram/HologramImpl.java | 6 ++ .../pyr/znpcsplus/hologram/HologramText.java | 8 +++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloRemoveDuplicateCommand.java diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index 2a12c2d..d04832a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -335,7 +335,8 @@ public class ZNpcsPlus { .addSubcommand("set", new HoloSetCommand(npcRegistry)) .addSubcommand("setitem", new HoloSetItemCommand(npcRegistry)) .addSubcommand("offset", new HoloOffsetCommand(npcRegistry)) - .addSubcommand("refreshdelay", new HoloRefreshDelayCommand(npcRegistry))) + .addSubcommand("refreshdelay", new HoloRefreshDelayCommand(npcRegistry)) + .addSubcommand("removeduplicate", new HoloRemoveDuplicateCommand(npcRegistry))) .addSubcommand("action", new MultiCommand(bootstrap.loadHelpMessage("action")) .addSubcommand("add", new ActionAddCommand(npcRegistry, actionRegistry)) .addSubcommand("clear", new ActionClearCommand(npcRegistry)) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloRemoveDuplicateCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloRemoveDuplicateCommand.java new file mode 100644 index 0000000..96c0ab2 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloRemoveDuplicateCommand.java @@ -0,0 +1,58 @@ +package lol.pyr.znpcsplus.commands.hologram; + +import lol.pyr.director.adventure.command.CommandContext; +import lol.pyr.director.adventure.command.CommandHandler; +import lol.pyr.director.common.command.CommandExecutionException; +import lol.pyr.znpcsplus.hologram.HologramImpl; +import lol.pyr.znpcsplus.hologram.HologramLine; +import lol.pyr.znpcsplus.hologram.HologramText; +import lol.pyr.znpcsplus.npc.NpcEntryImpl; +import lol.pyr.znpcsplus.npc.NpcRegistryImpl; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class HoloRemoveDuplicateCommand implements CommandHandler { + private final NpcRegistryImpl registry; + + public HoloRemoveDuplicateCommand(NpcRegistryImpl registry) { + this.registry = registry; + } + + @Override + public void run(CommandContext context) throws CommandExecutionException { + context.setUsage(context.getLabel() + " holo removeduplicates "); + HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); + List> lines = new ArrayList<>(hologram.getLines()); + List textLines = new ArrayList<>(); + + Iterator> iterator = lines.iterator(); + while (iterator.hasNext()) { + HologramLine line = iterator.next(); + if (line instanceof HologramText textLine + && !textLine.getValue().equals(Component.empty()) + && textLines.contains(textLine)) { + iterator.remove(); + continue; + } + + if (line instanceof HologramText textLine) { + textLines.add(textLine); + } + } + + hologram.clearLines(); + hologram.addLines(lines); + context.send(Component.text("NPC lines fixed!", NamedTextColor.GREEN)); + } + + @Override + public List suggest(CommandContext context) throws CommandExecutionException { + if (context.argSize() == 1) return context.suggestCollection(registry.getModifiableIds()); + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java index 6605515..5d55d06 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java @@ -101,6 +101,12 @@ public class HologramImpl extends Viewable implements Hologram { lines.clear(); } + public void addLines(List> lines) { + this.lines.addAll(lines); + relocateLines(); + for (Player viewer : getViewers()) for (HologramLine line : lines) line.show(viewer); + } + public void insertTextLineComponent(int index, Component line) { HologramText newLine = new HologramText(this, propertyRegistry, packetFactory, null, line); lines.add(index, newLine); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java index 23f3428..c552194 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java @@ -39,4 +39,12 @@ public class HologramText extends HologramLine { public boolean hasProperty(EntityProperty key) { return key.getName().equalsIgnoreCase("name") || key.getName().equalsIgnoreCase("invisible"); } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + HologramText that = (HologramText) obj; + return getValue().equals(that.getValue()); + } } -- 2.45.2 From 5c9ac03615edbd6640743162c14154fc94f9d2c1 Mon Sep 17 00:00:00 2001 From: bridge Date: Thu, 28 Nov 2024 18:47:56 +0100 Subject: [PATCH 54/56] feat: HoloRemoveAllDuplicatesCommand --- .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 3 +- .../holoRemoveAllDuplicatesCommand.java | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/holoRemoveAllDuplicatesCommand.java diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index d04832a..ea8b11b 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -336,7 +336,8 @@ public class ZNpcsPlus { .addSubcommand("setitem", new HoloSetItemCommand(npcRegistry)) .addSubcommand("offset", new HoloOffsetCommand(npcRegistry)) .addSubcommand("refreshdelay", new HoloRefreshDelayCommand(npcRegistry)) - .addSubcommand("removeduplicate", new HoloRemoveDuplicateCommand(npcRegistry))) + .addSubcommand("removeduplicate", new HoloRemoveDuplicateCommand(npcRegistry)) + .addSubcommand("removeallduplicates", new holoRemoveAllDuplicatesCommand(npcRegistry))) .addSubcommand("action", new MultiCommand(bootstrap.loadHelpMessage("action")) .addSubcommand("add", new ActionAddCommand(npcRegistry, actionRegistry)) .addSubcommand("clear", new ActionClearCommand(npcRegistry)) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/holoRemoveAllDuplicatesCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/holoRemoveAllDuplicatesCommand.java new file mode 100644 index 0000000..0343f29 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/holoRemoveAllDuplicatesCommand.java @@ -0,0 +1,62 @@ +package lol.pyr.znpcsplus.commands.hologram; + +import lol.pyr.director.adventure.command.CommandContext; +import lol.pyr.director.adventure.command.CommandHandler; +import lol.pyr.director.common.command.CommandExecutionException; +import lol.pyr.znpcsplus.hologram.HologramImpl; +import lol.pyr.znpcsplus.hologram.HologramLine; +import lol.pyr.znpcsplus.hologram.HologramText; +import lol.pyr.znpcsplus.npc.NpcEntryImpl; +import lol.pyr.znpcsplus.npc.NpcRegistryImpl; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class holoRemoveAllDuplicatesCommand implements CommandHandler { + private final NpcRegistryImpl registry; + + public holoRemoveAllDuplicatesCommand(NpcRegistryImpl registry) { + this.registry = registry; + } + + @Override + public void run(CommandContext context) throws CommandExecutionException { + context.setUsage(context.getLabel() + " holo removeallduplicates "); + + for (NpcEntryImpl npcEntry : registry.getAll()) { + HologramImpl hologram = npcEntry.getNpc().getHologram(); + List> lines = new ArrayList<>(hologram.getLines()); + List textLines = new ArrayList<>(); + + Iterator> iterator = lines.iterator(); + while (iterator.hasNext()) { + HologramLine line = iterator.next(); + if (line instanceof HologramText textLine + && !textLine.getValue().equals(Component.empty()) + && textLines.contains(textLine)) { + iterator.remove(); + continue; + } + + if (line instanceof HologramText textLine) { + textLines.add(textLine); + } + } + + hologram.clearLines(); + hologram.addLines(lines); + } + + context.send(Component.text("NPCs fixed!", NamedTextColor.GREEN)); + } + + @Override + public List suggest(CommandContext context) throws CommandExecutionException { + if (context.argSize() == 1) return context.suggestCollection(registry.getModifiableIds()); + return Collections.emptyList(); + } +} \ No newline at end of file -- 2.45.2 From 7825d92b2aac079a2394f4713a5819f413fb4e29 Mon Sep 17 00:00:00 2001 From: bridge Date: Tue, 4 Mar 2025 20:33:49 +0100 Subject: [PATCH 55/56] 21 --- .drone.yml | 2 +- build.gradle | 2 +- plugin/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index 0bd7598..a3da061 100644 --- a/.drone.yml +++ b/.drone.yml @@ -10,7 +10,7 @@ trigger: steps: - name: publish pull: if-not-exists - image: openjdk:17-jdk + image: openjdk:21-jdk environment: PACKAGESKEY: from_secret: GITEA_PACKAGE_PUBLIC_RW diff --git a/build.gradle b/build.gradle index 69f154e..92ed89d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ subprojects { version "2.1.0-netherite-SNAPSHOT" java { - toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } dependencies { diff --git a/plugin/build.gradle b/plugin/build.gradle index 99fe7c4..ee15fcf 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -40,7 +40,7 @@ dependencies { // Fancy text library implementation "net.kyori:adventure-platform-bukkit:4.3.4" - implementation "net.kyori:adventure-text-minimessage:4.17.0" + implementation "net.kyori:adventure-text-minimessage:4.18.0" implementation project(":api") } -- 2.45.2 From 49330e51b15c042929e0842bda456289b206dad0 Mon Sep 17 00:00:00 2001 From: bridge Date: Tue, 4 Mar 2025 20:34:37 +0100 Subject: [PATCH 56/56] ver --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 92ed89d..e6d7913 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ subprojects { apply plugin: "java" group "lol.pyr" - version "2.1.0-netherite-SNAPSHOT" + version "2.0.0-netherite-SNAPSHOT" java { toolchain.languageVersion.set(JavaLanguageVersion.of(21)) -- 2.45.2