From a7bf542eb34d08de32377a08f0d01515a3a8d81f Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Tue, 10 Dec 2024 10:56:20 +0400
Subject: [PATCH 01/60] 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");
From 8aed2ba5dc36c9650d7c00fbd65bee6862d6e993 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Thu, 12 Dec 2024 14:27:29 +0400
Subject: [PATCH 02/60] 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
From 7fbe42e2078d13012aa077724e722bb84dd8a1cc Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Thu, 12 Dec 2024 14:30:22 +0400
Subject: [PATCH 03/60] 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() {
From e20bd9ba57a0b6722206d1bcb12b936649ba211c Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Thu, 12 Dec 2024 16:12:52 +0400
Subject: [PATCH 04/60] 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());
From f8d5700b9a188a870689faad6a762927a3e92c08 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Fri, 13 Dec 2024 00:57:36 +0100
Subject: [PATCH 05/60] 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");
From aed6ee178c38ba8730e802f97ddf2b9fea4d6c45 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Fri, 13 Dec 2024 01:37:53 +0100
Subject: [PATCH 06/60] 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);
}
From 670bc9623b3a48ceae9fe344f13aed6f5cf5c1b2 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Fri, 13 Dec 2024 01:38:19 +0100
Subject: [PATCH 07/60] 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)
From f5d1a1914aaf7aa55d2bec4c86d8eac655294d52 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 13 Dec 2024 10:54:29 +0400
Subject: [PATCH 08/60] 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() {
From 41244fb86bb679dece30c95993b438a349662841 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 13 Dec 2024 10:58:52 +0400
Subject: [PATCH 09/60] 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);
}
From 79c0897de9b435cfd670b14c57ad52ccf3f4b6fb Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 13 Dec 2024 11:02:56 +0400
Subject: [PATCH 10/60] 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() {
From b107a3b011d84c5e350184b6ef88487d629fb8d2 Mon Sep 17 00:00:00 2001
From: Dablakbandit
Date: Sat, 14 Dec 2024 21:49:21 +1300
Subject: [PATCH 11/60] 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) {
From a49c43c04ec350067d98e3e5288110291fff2416 Mon Sep 17 00:00:00 2001
From: Dablakbandit
Date: Sat, 14 Dec 2024 23:24:26 +1300
Subject: [PATCH 12/60] 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 {
From cea0ffb8ac694e527c730c6b3e8367130937450c Mon Sep 17 00:00:00 2001
From: Dablakbandit
Date: Sun, 15 Dec 2024 01:06:09 +1300
Subject: [PATCH 13/60] 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);
+ }
+
+
}
From ad50d311940035bdcfad7793c38b0f900bc99f59 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 15 Dec 2024 10:36:33 +0100
Subject: [PATCH 14/60] 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"
}
From aa5e62ab0d63c83ab8b73e7b329b7dd416427616 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 15 Dec 2024 10:40:28 +0100
Subject: [PATCH 15/60] 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);
}
-
-
}
From 31518c213632e5a351b745135b86582a6eb7db9d Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 15 Dec 2024 10:45:25 +0100
Subject: [PATCH 16/60] 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);
-
}
From c5bf8dea0b0cb77349311a64162c8cdd7583d844 Mon Sep 17 00:00:00 2001
From: Dablakbandit
Date: Sat, 14 Dec 2024 21:49:21 +1300
Subject: [PATCH 17/60] 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) {
From 238a1fe2242f917c2a4152d92e4bc914f490abbb Mon Sep 17 00:00:00 2001
From: Dablakbandit
Date: Sun, 15 Dec 2024 01:06:09 +1300
Subject: [PATCH 18/60] 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);
+ }
+
+
}
From ca89bfe32d738c8e03c3eafde3315238ab89082f Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 15 Dec 2024 10:36:33 +0100
Subject: [PATCH 19/60] 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"
}
From 9477d4b500fa92bb1282f7b9eebd7a608fc7df86 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 15 Dec 2024 10:40:28 +0100
Subject: [PATCH 20/60] 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);
}
-
-
}
From 9303d74f8f313948d681dd67f7465ea690f290b6 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 15 Dec 2024 10:45:25 +0100
Subject: [PATCH 21/60] 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);
-
}
From 255a938dda2bb86f2123f5695102c6d346ac83f5 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Mon, 16 Dec 2024 22:42:27 +0400
Subject: [PATCH 22/60] 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);
From 8cd7282bb5a8e952aada0e6f68b41e94c04596cc Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Tue, 17 Dec 2024 23:55:05 +0400
Subject: [PATCH 23/60] 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");
}
From 33c27e903ce05cd3c39cbec35f89665bb827a1db Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Wed, 18 Dec 2024 05:22:12 +0100
Subject: [PATCH 24/60] 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);
+ }
}
}
From e30d6a57823a7c27a11854d0cc6d3652703467cb Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Wed, 18 Dec 2024 07:05:46 +0100
Subject: [PATCH 25/60] 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);
}
From e621ac69085cd5fe500e812f6090e977b523fbb8 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Wed, 18 Dec 2024 07:08:46 +0100
Subject: [PATCH 26/60] 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) {
From 27096e532b33965d0afa579063b6c74774811740 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Wed, 18 Dec 2024 07:29:37 +0100
Subject: [PATCH 27/60] 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() {
From c780c0ec78c8ea422cecbe9da9d16e52c46a368d Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Tue, 24 Dec 2024 16:11:13 +0100
Subject: [PATCH 28/60] 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());
From b3b8635477bc43c65bbb33f682935666fd1003bd Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Tue, 24 Dec 2024 16:14:00 +0100
Subject: [PATCH 29/60] 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();
}
From 55104b56f39ff799d1fd477dd88c8ecf96be37bc Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Fri, 27 Dec 2024 11:58:38 +0100
Subject: [PATCH 30/60] 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;
}
From 9d1d8f9bb093fc6d34b4907b8a1c57880ba51171 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Fri, 27 Dec 2024 12:02:36 +0100
Subject: [PATCH 31/60] 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))
From b8dda22154a1fa49752ae5b215c8dee85b06ba50 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 27 Dec 2024 18:25:22 +0530
Subject: [PATCH 32/60] 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());
}
}
}
From 218c4e48cc083dd30f4c574795703bb558d17ac4 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 27 Dec 2024 18:26:45 +0530
Subject: [PATCH 33/60] 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
From 97fd7bfd762e2f9788b92bdd0ce33ec69dfd39b8 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 27 Dec 2024 19:15:36 +0530
Subject: [PATCH 34/60] 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)));
+ }
}
From ba75abcebcfbdc35e5e0cd6ca55ea9168d628ead Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 27 Dec 2024 19:30:50 +0530
Subject: [PATCH 35/60] 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)));
+ }
+}
From d1b890a9126632e988b3ac86d75f40928822ef91 Mon Sep 17 00:00:00 2001
From: envizar
Date: Sun, 29 Dec 2024 14:13:37 +0300
Subject: [PATCH 36/60] 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();
}
}
From dfdcc54313639e0a190e5581dc44368550b18c94 Mon Sep 17 00:00:00 2001
From: envizar
Date: Sun, 29 Dec 2024 14:29:17 +0300
Subject: [PATCH 37/60] 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;
From ec60af7186b43ea8da0c662646ecbc5f04e31815 Mon Sep 17 00:00:00 2001
From: envizar
Date: Sun, 29 Dec 2024 14:43:19 +0300
Subject: [PATCH 38/60] 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();
}
From c0bcbcf7a3491dd69c42debd78c969a60889071a Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 29 Dec 2024 13:49:52 +0100
Subject: [PATCH 39/60] 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();
+ }
}
From ad8138f9833685914fa159199000aba2efc8fbba Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 29 Dec 2024 13:51:33 +0100
Subject: [PATCH 40/60] 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)
From dd8899163cd9bdc09f645711103b58ba2ebd26c4 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 29 Dec 2024 14:00:35 +0100
Subject: [PATCH 41/60] 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));
From 86c5b9c3259a98025845225dd0a523f229fe6f54 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Sun, 29 Dec 2024 17:18:59 +0100
Subject: [PATCH 42/60] 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;
From ca8a1d649950ea5ac03538c3a30b7b9c12cb33a8 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Wed, 8 Jan 2025 02:22:28 +0100
Subject: [PATCH 43/60] 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));
From e663c19254321fc676cd2c02aa510429728da548 Mon Sep 17 00:00:00 2001
From: Rainnny7
Date: Sun, 23 Feb 2025 16:08:03 -0500
Subject: [PATCH 44/60] Support for legacy section symbols in holograms
---
.../src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
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..c0194c7 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java
@@ -48,7 +48,8 @@ public class HologramImpl extends Viewable implements Hologram {
}
public void addTextLine(String line) {
- addTextLineComponent(textSerializer.deserialize(textSerializer.serialize(MiniMessage.miniMessage().deserialize(line))));
+ Component component = line.contains("§") ? Component.text(line) : MiniMessage.miniMessage().deserialize(line);
+ addTextLineComponent(textSerializer.deserialize(textSerializer.serialize(component)));
}
public void addItemLineStack(org.bukkit.inventory.ItemStack item) {
From 02584503837709e6e0d904ea4662c3d4e97fa07c Mon Sep 17 00:00:00 2001
From: Mqzn
Date: Thu, 20 Mar 2025 15:05:58 +0200
Subject: [PATCH 45/60] Added skin descriptor fetching by UUID
---
.../api/skin/SkinDescriptorFactory.java | 2 +
.../pyr/znpcsplus/commands/SkinCommand.java | 4 +-
.../conversion/znpcs/ZNpcImporter.java | 4 +-
.../znpcsplus/skin/BaseSkinDescriptor.java | 4 +-
.../skin/SkinDescriptorFactoryImpl.java | 11 ++++-
...iptor.java => NameFetchingDescriptor.java} | 4 +-
.../descriptor/UUIDFetchingDescriptor.java | 41 +++++++++++++++++++
7 files changed, 60 insertions(+), 10 deletions(-)
rename plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/{FetchingDescriptor.java => NameFetchingDescriptor.java} (87%)
create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
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 c5573e7..46d979a 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
@@ -1,6 +1,7 @@
package lol.pyr.znpcsplus.api.skin;
import java.net.URL;
+import java.util.UUID;
/**
* Factory for creating skin descriptors.
@@ -8,6 +9,7 @@ import java.net.URL;
public interface SkinDescriptorFactory {
SkinDescriptor createMirrorDescriptor();
SkinDescriptor createRefreshingDescriptor(String playerName);
+ SkinDescriptor createRefreshingDescriptor(UUID playerUUID);
SkinDescriptor createStaticDescriptor(String playerName);
SkinDescriptor createStaticDescriptor(String texture, String signature);
SkinDescriptor createUrlDescriptor(String url, String variant);
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 485b866..48fa332 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/SkinCommand.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/SkinCommand.java
@@ -11,7 +11,7 @@ import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
-import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
+import lol.pyr.znpcsplus.skin.descriptor.NameFetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import net.kyori.adventure.text.Component;
@@ -67,7 +67,7 @@ public class SkinCommand implements CommandHandler {
} else if (type.equalsIgnoreCase("dynamic")) {
context.ensureArgsNotEmpty();
String name = context.dumpAllArgs();
- npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new FetchingDescriptor(skinCache, name));
+ npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new NameFetchingDescriptor(skinCache, name));
npc.respawn();
context.halt(Component.text("The NPC's skin will now be resolved per-player from \"" + name + "\""));
} else if (type.equalsIgnoreCase("url")) {
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 604347f..024c66c 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
@@ -25,7 +25,7 @@ import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.skin.SkinImpl;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
-import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
+import lol.pyr.znpcsplus.skin.descriptor.NameFetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import lol.pyr.znpcsplus.util.BungeeConnector;
@@ -175,7 +175,7 @@ public class ZNpcImporter implements DataImporter {
}
if (model.getSkinName() != null) {
- npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new FetchingDescriptor(skinCache, model.getSkinName()));
+ npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new NameFetchingDescriptor(skinCache, model.getSkinName()));
}
else if (model.getSkin() != null && model.getSignature() != null) {
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new SkinImpl(model.getSkin(), model.getSignature())));
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
index 65e6e7d..6d55f62 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
@@ -3,7 +3,7 @@ package lol.pyr.znpcsplus.skin;
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
-import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
+import lol.pyr.znpcsplus.skin.descriptor.NameFetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import org.bukkit.entity.Player;
@@ -22,7 +22,7 @@ public interface BaseSkinDescriptor extends SkinDescriptor {
static BaseSkinDescriptor deserialize(MojangSkinCache skinCache, String str) {
String[] arr = str.split(";");
if (arr[0].equalsIgnoreCase("mirror")) return new MirrorDescriptor(skinCache);
- else if (arr[0].equalsIgnoreCase("fetching")) return new FetchingDescriptor(skinCache, String.join(";", Arrays.copyOfRange(arr, 1, arr.length)));
+ else if (arr[0].equalsIgnoreCase("fetching")) return new NameFetchingDescriptor(skinCache, String.join(";", Arrays.copyOfRange(arr, 1, arr.length)));
else if (arr[0].equalsIgnoreCase("prefetched")) {
List properties = new ArrayList<>();
for (int i = 0; i < (arr.length - 1) / 3; i++) {
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 b4557e6..10a8cea 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptorFactoryImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptorFactoryImpl.java
@@ -3,12 +3,14 @@ package lol.pyr.znpcsplus.skin;
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
import lol.pyr.znpcsplus.api.skin.SkinDescriptorFactory;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
-import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
+import lol.pyr.znpcsplus.skin.descriptor.NameFetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
+import lol.pyr.znpcsplus.skin.descriptor.UUIDFetchingDescriptor;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.UUID;
public class SkinDescriptorFactoryImpl implements SkinDescriptorFactory {
private final MojangSkinCache skinCache;
@@ -26,7 +28,12 @@ public class SkinDescriptorFactoryImpl implements SkinDescriptorFactory {
@Override
public SkinDescriptor createRefreshingDescriptor(String playerName) {
- return new FetchingDescriptor(skinCache, playerName);
+ return new NameFetchingDescriptor(skinCache, playerName);
+ }
+
+ @Override
+ public SkinDescriptor createRefreshingDescriptor(UUID playerUUID) {
+ return new UUIDFetchingDescriptor(skinCache, playerUUID);
}
@Override
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/FetchingDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
similarity index 87%
rename from plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/FetchingDescriptor.java
rename to plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
index d99ad2c..00d4521 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/FetchingDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
@@ -9,11 +9,11 @@ import org.bukkit.entity.Player;
import java.util.concurrent.CompletableFuture;
-public class FetchingDescriptor implements BaseSkinDescriptor, SkinDescriptor {
+public class NameFetchingDescriptor implements BaseSkinDescriptor, SkinDescriptor {
private final MojangSkinCache skinCache;
private final String name;
- public FetchingDescriptor(MojangSkinCache skinCache, String name) {
+ public NameFetchingDescriptor(MojangSkinCache skinCache, String name) {
this.skinCache = skinCache;
this.name = name;
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
new file mode 100644
index 0000000..4406bbd
--- /dev/null
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
@@ -0,0 +1,41 @@
+package lol.pyr.znpcsplus.skin.descriptor;
+
+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 org.bukkit.entity.Player;
+
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+
+public class UUIDFetchingDescriptor implements BaseSkinDescriptor, SkinDescriptor {
+
+ private final MojangSkinCache skinCache;
+ private final UUID uuid;
+
+ public UUIDFetchingDescriptor(MojangSkinCache skinCache, UUID uuid) {
+ this.skinCache = skinCache;
+ this.uuid = uuid;
+ }
+
+ @Override
+ public CompletableFuture fetch(Player player) {
+ return skinCache.fetchByUUID(uuid.toString());
+ }
+
+ @Override
+ public SkinImpl fetchInstant(Player player) {
+ return fetch(player).join();
+ }
+
+ @Override
+ public boolean supportsInstant(Player player) {
+ return false;
+ }
+
+ @Override
+ public String serialize() {
+ return "fetching;" + uuid.toString();
+ }
+}
From 33e79e8543a9d1f6eac5acdfe33c6a4f59b2efda Mon Sep 17 00:00:00 2001
From: Mqzn
Date: Sat, 22 Mar 2025 16:03:11 +0200
Subject: [PATCH 46/60] Adapted the serialization process to the new fetching
descriptors
---
.../java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java | 7 ++++++-
.../znpcsplus/skin/descriptor/NameFetchingDescriptor.java | 2 +-
.../znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java | 3 ++-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
index 6d55f62..59f6a36 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
@@ -6,11 +6,13 @@ import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
import lol.pyr.znpcsplus.skin.descriptor.NameFetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
+import lol.pyr.znpcsplus.skin.descriptor.UUIDFetchingDescriptor;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public interface BaseSkinDescriptor extends SkinDescriptor {
@@ -22,7 +24,10 @@ public interface BaseSkinDescriptor extends SkinDescriptor {
static BaseSkinDescriptor deserialize(MojangSkinCache skinCache, String str) {
String[] arr = str.split(";");
if (arr[0].equalsIgnoreCase("mirror")) return new MirrorDescriptor(skinCache);
- else if (arr[0].equalsIgnoreCase("fetching")) return new NameFetchingDescriptor(skinCache, String.join(";", Arrays.copyOfRange(arr, 1, arr.length)));
+ else if (arr[0].equalsIgnoreCase("fetching-name"))
+ return new NameFetchingDescriptor(skinCache, String.join(";", Arrays.copyOfRange(arr, 1, arr.length)));
+ else if(arr[0].equalsIgnoreCase("fetching-uuid"))
+ return new UUIDFetchingDescriptor(skinCache, UUID.fromString(String.join(";", Arrays.copyOfRange(arr, 1, arr.length))));
else if (arr[0].equalsIgnoreCase("prefetched")) {
List properties = new ArrayList<>();
for (int i = 0; i < (arr.length - 1) / 3; i++) {
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
index 00d4521..48ac7e6 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
@@ -39,6 +39,6 @@ public class NameFetchingDescriptor implements BaseSkinDescriptor, SkinDescripto
@Override
public String serialize() {
- return "fetching;" + name;
+ return "fetching-name;" + name;
}
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
index 4406bbd..685c786 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
@@ -36,6 +36,7 @@ public class UUIDFetchingDescriptor implements BaseSkinDescriptor, SkinDescripto
@Override
public String serialize() {
- return "fetching;" + uuid.toString();
+ return "fetching-uuid;" + uuid.toString();
}
+
}
From d9ed69eecd409d09375d3e57ebe8cd5fe3d87d70 Mon Sep 17 00:00:00 2001
From: Mqzn
Date: Sat, 22 Mar 2025 19:44:32 +0200
Subject: [PATCH 47/60] Made it compatible with old npc files
---
.../pyr/znpcsplus/skin/BaseSkinDescriptor.java | 9 +++++----
.../skin/descriptor/NameFetchingDescriptor.java | 2 +-
.../skin/descriptor/UUIDFetchingDescriptor.java | 2 +-
.../java/lol/pyr/znpcsplus/util/UUIDUtil.java | 16 ++++++++++++++++
4 files changed, 23 insertions(+), 6 deletions(-)
create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
index 59f6a36..66dd9a4 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
@@ -7,6 +7,7 @@ import lol.pyr.znpcsplus.skin.descriptor.NameFetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.UUIDFetchingDescriptor;
+import lol.pyr.znpcsplus.util.UUIDUtil;
import org.bukkit.entity.Player;
import java.util.ArrayList;
@@ -24,10 +25,10 @@ public interface BaseSkinDescriptor extends SkinDescriptor {
static BaseSkinDescriptor deserialize(MojangSkinCache skinCache, String str) {
String[] arr = str.split(";");
if (arr[0].equalsIgnoreCase("mirror")) return new MirrorDescriptor(skinCache);
- else if (arr[0].equalsIgnoreCase("fetching-name"))
- return new NameFetchingDescriptor(skinCache, String.join(";", Arrays.copyOfRange(arr, 1, arr.length)));
- else if(arr[0].equalsIgnoreCase("fetching-uuid"))
- return new UUIDFetchingDescriptor(skinCache, UUID.fromString(String.join(";", Arrays.copyOfRange(arr, 1, arr.length))));
+ else if (arr[0].equalsIgnoreCase("fetching")) {
+ String value = String.join(";", Arrays.copyOfRange(arr, 1, arr.length));
+ return UUIDUtil.isUUID(value) ? new UUIDFetchingDescriptor(skinCache, UUID.fromString(value)) : new NameFetchingDescriptor(skinCache, value);
+ }
else if (arr[0].equalsIgnoreCase("prefetched")) {
List properties = new ArrayList<>();
for (int i = 0; i < (arr.length - 1) / 3; i++) {
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
index 48ac7e6..00d4521 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java
@@ -39,6 +39,6 @@ public class NameFetchingDescriptor implements BaseSkinDescriptor, SkinDescripto
@Override
public String serialize() {
- return "fetching-name;" + name;
+ return "fetching;" + name;
}
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
index 685c786..d4db046 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
@@ -36,7 +36,7 @@ public class UUIDFetchingDescriptor implements BaseSkinDescriptor, SkinDescripto
@Override
public String serialize() {
- return "fetching-uuid;" + uuid.toString();
+ return "fetching;" + uuid.toString();
}
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java
new file mode 100644
index 0000000..c85b73e
--- /dev/null
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java
@@ -0,0 +1,16 @@
+package lol.pyr.znpcsplus.util;
+
+
+import java.util.regex.Pattern;
+
+public final class UUIDUtil {
+
+
+ public final static Pattern UUID_REGEX =
+ Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
+
+ public static boolean isUUID(String uuid) {
+ return UUID_REGEX.matcher(uuid).matches();
+ }
+
+}
From 04b57fc8ea31e8bb232fad6fc27a3e915766a305 Mon Sep 17 00:00:00 2001
From: Mqzn
Date: Thu, 27 Mar 2025 20:31:33 +0200
Subject: [PATCH 48/60] Removed unnecessary code
---
.../pyr/znpcsplus/skin/BaseSkinDescriptor.java | 9 ++++++---
.../skin/descriptor/UUIDFetchingDescriptor.java | 2 +-
.../java/lol/pyr/znpcsplus/util/UUIDUtil.java | 16 ----------------
3 files changed, 7 insertions(+), 20 deletions(-)
delete mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
index 66dd9a4..1fe1623 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/BaseSkinDescriptor.java
@@ -7,7 +7,6 @@ import lol.pyr.znpcsplus.skin.descriptor.NameFetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.UUIDFetchingDescriptor;
-import lol.pyr.znpcsplus.util.UUIDUtil;
import org.bukkit.entity.Player;
import java.util.ArrayList;
@@ -25,9 +24,13 @@ public interface BaseSkinDescriptor extends SkinDescriptor {
static BaseSkinDescriptor deserialize(MojangSkinCache skinCache, String str) {
String[] arr = str.split(";");
if (arr[0].equalsIgnoreCase("mirror")) return new MirrorDescriptor(skinCache);
- else if (arr[0].equalsIgnoreCase("fetching")) {
+ else if (arr[0].equalsIgnoreCase("fetching-uuid")) {
String value = String.join(";", Arrays.copyOfRange(arr, 1, arr.length));
- return UUIDUtil.isUUID(value) ? new UUIDFetchingDescriptor(skinCache, UUID.fromString(value)) : new NameFetchingDescriptor(skinCache, value);
+ return new UUIDFetchingDescriptor(skinCache, UUID.fromString(value));
+ }
+ else if(arr[0].equalsIgnoreCase("fetching")) {
+ String value = String.join(";", Arrays.copyOfRange(arr, 1, arr.length));
+ return new NameFetchingDescriptor(skinCache, value);
}
else if (arr[0].equalsIgnoreCase("prefetched")) {
List properties = new ArrayList<>();
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
index d4db046..685c786 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java
@@ -36,7 +36,7 @@ public class UUIDFetchingDescriptor implements BaseSkinDescriptor, SkinDescripto
@Override
public String serialize() {
- return "fetching;" + uuid.toString();
+ return "fetching-uuid;" + uuid.toString();
}
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java b/plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java
deleted file mode 100644
index c85b73e..0000000
--- a/plugin/src/main/java/lol/pyr/znpcsplus/util/UUIDUtil.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package lol.pyr.znpcsplus.util;
-
-
-import java.util.regex.Pattern;
-
-public final class UUIDUtil {
-
-
- public final static Pattern UUID_REGEX =
- Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
-
- public static boolean isUUID(String uuid) {
- return UUID_REGEX.matcher(uuid).matches();
- }
-
-}
From affa0f4c8476b94d82b86bcfc5c11e0725ae9824 Mon Sep 17 00:00:00 2001
From: Pyrbu
Date: Wed, 2 Apr 2025 23:35:14 +0200
Subject: [PATCH 49/60] fix viewable thread-safety
---
.../main/java/lol/pyr/znpcsplus/util/Viewable.java | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
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 9001b1e..08b62fe 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/util/Viewable.java
@@ -11,13 +11,15 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;
public abstract class Viewable {
- private final static List> all = new ArrayList<>();
+ private final static List> all = Collections.synchronizedList(new ArrayList<>());
public static List all() {
- all.removeIf(reference -> reference.get() == null);
- return all.stream()
- .map(Reference::get)
- .collect(Collectors.toList());
+ synchronized (all) {
+ all.removeIf(reference -> reference.get() == null);
+ return all.stream()
+ .map(Reference::get)
+ .collect(Collectors.toList());
+ }
}
private boolean queueRunning = false;
From c34a665692217b2beb20596c133919939e8beb6d Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 18 Apr 2025 12:26:23 +0530
Subject: [PATCH 50/60] chore: Add method to delete npc using UUID
---
.../main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java | 6 ++++++
.../main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java | 8 ++++++++
2 files changed, 14 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 8a39418..2d41981 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
@@ -65,6 +65,12 @@ public interface NpcRegistry {
*/
void delete(String id);
+ /**
+ * Deletes an NPC entry by its UUID
+ * @param uuid The UUID of the NPC entry
+ */
+ void delete(UUID uuid);
+
/**
* Register an NPC to this registry
* NpcEntry instances can be obtained through the NpcSerializer classes
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 0dc8a1a..43f0a9f 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java
@@ -202,6 +202,14 @@ public class NpcRegistryImpl implements NpcRegistry {
storage.deleteNpc(entry);
}
+ @Override
+ public void delete(UUID uuid) {
+ NpcEntryImpl entry = npcUuidLookupMap.get(uuid);
+ if (entry == null) return;
+ unregister(entry);
+ storage.deleteNpc(entry);
+ }
+
public void switchIds(String oldId, String newId) {
NpcEntryImpl entry = getById(oldId);
delete(oldId);
From 643b1438685f7f9369e131e38991f94779de6511 Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 18 Apr 2025 12:27:21 +0530
Subject: [PATCH 51/60] fix: citizens hologram import
---
.../conversion/citizens/model/traits/HologramTrait.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/HologramTrait.java b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/HologramTrait.java
index 670e48a..48c850d 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/HologramTrait.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/HologramTrait.java
@@ -24,7 +24,7 @@ public class HologramTrait extends SectionCitizensTrait {
if (linesSection != null) {
List keys = new ArrayList<>(linesSection.getKeys(false));
for (int i = keys.size() - 1; i >= 0; i--) {
- String line = linesSection.getConfigurationSection(keys.get(i)).getString("text");
+ String line = linesSection.isConfigurationSection(keys.get(i)) ? linesSection.getConfigurationSection(keys.get(i)).getString("text") : linesSection.getString(keys.get(i));
if (line != null) {
Component component = textSerializer.deserialize(line);
npc.getHologram().addTextLineComponent(component);
From a87f1657ccec55987ff1cd8e2cdc1cad62d26f8f Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Fri, 18 Apr 2025 12:28:26 +0530
Subject: [PATCH 52/60] chore: add development build in version command
---
.../main/java/lol/pyr/znpcsplus/commands/VersionCommand.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java
index f59bf17..77ce2c0 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java
@@ -53,6 +53,8 @@ public class VersionCommand implements CommandHandler {
}
if (buildId != null && !buildId.isEmpty()) {
versionBuilder.append(" (Build #").append(buildId).append(")");
+ } else {
+ versionBuilder.append(" (Development Build)");
}
String version = versionBuilder.toString();
From fe70e7ca9cc188b8345bf35dadc8e851c929c00d Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Thu, 8 May 2025 22:25:18 +0530
Subject: [PATCH 53/60] fix: entity_sitting property when npc respawns
---
.../src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java | 3 +++
1 file changed, 3 insertions(+)
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 4e51020..e1cf15c 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java
@@ -71,6 +71,9 @@ public class PacketEntity implements PropertyHolder {
return FutureUtil.exceptionPrintingRunAsync(() -> {
if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties).join();
else packetFactory.spawnEntity(player, this, properties);
+ if (vehicle != null) {
+ setVehicle(vehicle);
+ }
if (vehicleId != null) {
packetFactory.setPassengers(player, vehicleId, this.getEntityId());
}
From 95432d438e89db28db04b4770e91e4ee0c932aff Mon Sep 17 00:00:00 2001
From: D3v1s0m
Date: Thu, 15 May 2025 23:33:06 +0530
Subject: [PATCH 54/60] chore: bump PacketEvents to 2.8.0 fix: baby property
and a mem leak add: zombie related properties
---
.../api/NpcPropertyRegistryProvider.java | 6 ++-
.../api/entity/EntityPropertyRegistry.java | 16 +++++-
.../lol/pyr/znpcsplus/util/ZombieType.java | 11 ++++
plugin/build.gradle | 2 +-
.../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 4 +-
.../commands/property/PropertySetCommand.java | 1 +
.../znpcsplus/entity/EntityPropertyImpl.java | 10 ++--
.../entity/EntityPropertyRegistryImpl.java | 50 +++++++++++++++----
.../entity/properties/BitsetProperty.java | 21 +++++---
.../entity/properties/BooleanProperty.java | 2 +-
.../properties/CamelSittingProperty.java | 2 +-
.../entity/properties/CustomTypeProperty.java | 2 +-
.../entity/properties/DinnerboneProperty.java | 14 +++---
.../entity/properties/DummyProperty.java | 2 +-
.../properties/EncodedByteProperty.java | 2 +-
.../properties/EncodedIntegerProperty.java | 2 +-
.../properties/EncodedStringProperty.java | 2 +-
.../properties/EntitySittingProperty.java | 2 +-
.../entity/properties/EquipmentProperty.java | 2 +-
.../properties/ForceBodyRotationProperty.java | 7 +--
.../entity/properties/GlowProperty.java | 10 ++--
.../entity/properties/HealthProperty.java | 4 +-
.../properties/HologramItemProperty.java | 2 +-
.../entity/properties/HorseColorProperty.java | 10 ++--
.../entity/properties/HorseStyleProperty.java | 10 ++--
.../entity/properties/IntegerProperty.java | 2 +-
.../entity/properties/LegacyBabyProperty.java | 29 +++++++++++
.../entity/properties/NBTProperty.java | 2 +-
.../entity/properties/NameProperty.java | 13 +++--
.../properties/OptionalBlockPosProperty.java | 6 +--
.../entity/properties/RabbitTypeProperty.java | 22 +++++---
.../entity/properties/RotationProperty.java | 2 +-
.../entity/properties/TargetNpcProperty.java | 2 +-
.../TropicalFishVariantProperty.java | 13 +++--
.../attributes/AttributeProperty.java | 4 +-
.../villager/VillagerDataProperty.java | 4 +-
.../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 8 +--
.../lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 24 +++++++++
.../znpcsplus/npc/NpcTypeRegistryImpl.java | 2 +-
.../pyr/znpcsplus/packets/PacketFactory.java | 2 +-
.../znpcsplus/packets/V1_8PacketFactory.java | 6 +--
.../java/lol/pyr/znpcsplus/util/Viewable.java | 3 ++
42 files changed, 243 insertions(+), 97 deletions(-)
create mode 100644 api/src/main/java/lol/pyr/znpcsplus/util/ZombieType.java
create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/LegacyBabyProperty.java
diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/NpcPropertyRegistryProvider.java b/api/src/main/java/lol/pyr/znpcsplus/api/NpcPropertyRegistryProvider.java
index 83b3e2c..bcfd0b5 100644
--- a/api/src/main/java/lol/pyr/znpcsplus/api/NpcPropertyRegistryProvider.java
+++ b/api/src/main/java/lol/pyr/znpcsplus/api/NpcPropertyRegistryProvider.java
@@ -2,6 +2,8 @@ package lol.pyr.znpcsplus.api;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.ServicePriority;
/**
* Provider for the registered entity property registry instance
@@ -30,10 +32,12 @@ public class NpcPropertyRegistryProvider {
* Internal method used to register the main instance of the plugin as the entity property registry provider
* You probably shouldn't call this method under any circumstances
*
+ * @param plugin Instance of the ZNPCsPlus plugin
* @param api Instance of the ZNPCsPlus entity property registry
*/
- public static void register(EntityPropertyRegistry api) {
+ public static void register(Plugin plugin, EntityPropertyRegistry api) {
NpcPropertyRegistryProvider.registry = api;
+ Bukkit.getServicesManager().register(EntityPropertyRegistry.class, registry, plugin, ServicePriority.Normal);
}
/**
diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/entity/EntityPropertyRegistry.java b/api/src/main/java/lol/pyr/znpcsplus/api/entity/EntityPropertyRegistry.java
index 69e7adf..13c094f 100644
--- a/api/src/main/java/lol/pyr/znpcsplus/api/entity/EntityPropertyRegistry.java
+++ b/api/src/main/java/lol/pyr/znpcsplus/api/entity/EntityPropertyRegistry.java
@@ -31,11 +31,25 @@ public interface EntityPropertyRegistry {
*/
EntityProperty getByName(String name, Class type);
+ /**
+ * Register a dummy property that can be used to store unique information per npc
+ * Note: Properties registered this way will be player-modifiable by default
+ *
+ * @param name The name of the new property
+ * @param type The type of the new property
+ * @deprecated Use {@link #registerDummy(String, Class, boolean)} instead
+ */
+ @Deprecated
+ default void registerDummy(String name, Class> type) {
+ registerDummy(name, type, true);
+ }
+
/**
* Register a dummy property that can be used to store unique information per npc
*
* @param name The name of the new property
* @param type The type of the new property
+ * @param playerModifiable Whether this property can be modified by players using commands
*/
- void registerDummy(String name, Class> type);
+ void registerDummy(String name, Class> type, boolean playerModifiable);
}
diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/ZombieType.java b/api/src/main/java/lol/pyr/znpcsplus/util/ZombieType.java
new file mode 100644
index 0000000..8751b82
--- /dev/null
+++ b/api/src/main/java/lol/pyr/znpcsplus/util/ZombieType.java
@@ -0,0 +1,11 @@
+package lol.pyr.znpcsplus.util;
+
+public enum ZombieType {
+ ZOMBIE,
+ FARMER,
+ LIBRARIAN,
+ PRIEST,
+ BLACKSMITH,
+ BUTCHER,
+ HUSK
+}
diff --git a/plugin/build.gradle b/plugin/build.gradle
index b778a35..e7af00f 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.7.0" // Packets
+ implementation "com.github.retrooper:packetevents-spigot:2.8.0" // Packets
implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" // Configs
implementation "lol.pyr:director-adventure:2.1.2" // Commands
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java
index 2a12c2d..ed39bb4 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java
@@ -97,7 +97,7 @@ public class ZNpcsPlus {
skinCache = new MojangSkinCache(configManager, new File(getDataFolder(), "skins"));
propertyRegistry = new EntityPropertyRegistryImpl(skinCache, configManager);
- NpcPropertyRegistryProvider.register(propertyRegistry);
+ NpcPropertyRegistryProvider.register(bootstrap, propertyRegistry);
shutdownTasks.add(NpcPropertyRegistryProvider::unregister);
}
@@ -130,7 +130,7 @@ public class ZNpcsPlus {
PacketFactory packetFactory = setupPacketFactory(scheduler, propertyRegistry, configManager);
- propertyRegistry.registerTypes(bootstrap, packetFactory, textSerializer, scheduler);
+ propertyRegistry.registerTypes(packetFactory, textSerializer, scheduler);
BungeeConnector bungeeConnector = new BungeeConnector(bootstrap);
ActionRegistryImpl actionRegistry = new ActionRegistryImpl();
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 53a5e25..3d9b228 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
@@ -45,6 +45,7 @@ public class PropertySetCommand implements CommandHandler {
// TODO: find a way to do this better & rewrite this mess
if (!npc.getType().getAllowedProperties().contains(property)) context.halt(Component.text("Property " + property.getName() + " not allowed for npc type " + npc.getType().getName(), NamedTextColor.RED));
+ if (!property.isPlayerModifiable()) context.halt(Component.text("This property is not modifiable by players", NamedTextColor.RED));
Class> type = property.getType();
Object value;
String valueName;
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyImpl.java
index 25786d4..dcfdf5f 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyImpl.java
@@ -47,16 +47,16 @@ public abstract class EntityPropertyImpl implements EntityProperty {
dependencies.add(property);
}
- protected static EntityData newEntityData(int index, EntityDataType type, V value) {
- return new EntityData(index, type, value);
+ protected static EntityData newEntityData(int index, EntityDataType type, V value) {
+ return new EntityData<>(index, type, value);
}
- public List applyStandalone(Player player, PacketEntity packetEntity, boolean isSpawned) {
- Map map = new HashMap<>();
+ public List> applyStandalone(Player player, PacketEntity packetEntity, boolean isSpawned) {
+ Map> map = new HashMap<>();
apply(player, packetEntity, isSpawned, map);
for (EntityPropertyImpl> property : dependencies) property.apply(player, packetEntity, isSpawned, map);
return new ArrayList<>(map.values());
}
- abstract public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties);
+ abstract public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties);
}
\ No newline at end of file
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 4a43cd4..28053e6 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java
@@ -10,7 +10,6 @@ import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
-import lol.pyr.znpcsplus.ZNpcsPlusBootstrap;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
@@ -109,7 +108,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
*/
}
- public void registerTypes(ZNpcsPlusBootstrap plugin, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, TaskScheduler taskScheduler) {
+ public void registerTypes(PacketFactory packetFactory, LegacyComponentSerializer textSerializer, TaskScheduler taskScheduler) {
ServerVersion ver = PacketEvents.getAPI().getServerManager().getVersion();
boolean legacyBooleans = ver.isOlderThan(ServerVersion.V_1_9);
boolean legacyNames = ver.isOlderThan(ServerVersion.V_1_9);
@@ -133,7 +132,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
register(new DummyProperty<>("permission_required", false));
- register(new ForceBodyRotationProperty(plugin, taskScheduler));
+ register(new ForceBodyRotationProperty(taskScheduler));
register(new DummyProperty<>("player_knockback", false));
register(new DummyProperty<>("player_knockback_exempt_permission", String.class));
@@ -192,7 +191,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) babyIndex = 11;
else babyIndex = 12;
if (ver.isOlderThan(ServerVersion.V_1_9)) {
- register(new EncodedByteProperty<>("baby", false, babyIndex, obj -> (byte) (obj ? -1 : 0)));
+ register(new LegacyBabyProperty(babyIndex));
} else {
register(new BooleanProperty("baby", babyIndex, false, legacyBooleans));
}
@@ -286,7 +285,9 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
else horseIndex = 16;
int horseEating = ver.isNewerThanOrEquals(ServerVersion.V_1_12) ? 0x10 : 0x20;
register(new BitsetProperty("is_tame", horseIndex, 0x02, false, legacyBooleans));
- register(new BitsetProperty("is_saddled", horseIndex, 0x04, false, legacyBooleans));
+ if (ver.isOlderThan(ServerVersion.V_1_21)) {
+ register(new BitsetProperty("is_saddled", horseIndex, 0x04, false, legacyBooleans));
+ }
register(new BitsetProperty("is_eating", horseIndex, horseEating, false, legacyBooleans));
register(new BitsetProperty("is_rearing", horseIndex, horseEating << 1, false, legacyBooleans));
register(new BitsetProperty("has_mouth_open", horseIndex, horseEating << 2, false, legacyBooleans));
@@ -354,10 +355,14 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
// Chested Horse
if (ver.isOlderThan(ServerVersion.V_1_11)) {
register(new BitsetProperty("has_chest", horseIndex, 0x08, false, legacyBooleans));
- linkProperties("is_saddled", "has_chest", "is_eating", "is_rearing", "has_mouth_open");
+ linkProperties("is_tame", "is_saddled", "has_chest", "is_eating", "is_rearing", "has_mouth_open");
} else {
register(new BooleanProperty("has_chest", horseVariantIndex, false, legacyBooleans));
- linkProperties("is_saddled", "is_eating", "is_rearing", "has_mouth_open");
+ if (ver.isOlderThan(ServerVersion.V_1_21)){
+ linkProperties("is_tame", "is_saddled", "is_eating", "is_rearing", "has_mouth_open");
+ } else {
+ linkProperties("is_tame", "is_eating", "is_rearing", "has_mouth_open");
+ }
}
// Slime, Magma Cube and Phantom
@@ -459,6 +464,33 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
else register(new EncodedIntegerProperty<>("skeleton_type", SkeletonType.NORMAL, ver.isOlderThan(ServerVersion.V_1_10) ? 11 : 12, Enum::ordinal));
}
+ // Zombie
+ int zombieIndex;
+ if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) zombieIndex = 17;
+ else if (ver.isNewerThanOrEquals(ServerVersion.V_1_16)) zombieIndex = 16;
+ else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) zombieIndex = 13;
+ else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) zombieIndex = 12;
+ else zombieIndex = 13;
+
+ if (ver.isOlderThan(ServerVersion.V_1_9)) {
+ register(new EncodedByteProperty<>("zombie_is_villager", false, zombieIndex++, b -> (byte) (b ? 1 : 0)));
+ } else if (ver.isOlderThan(ServerVersion.V_1_11)) {
+ register(new EncodedIntegerProperty<>("zombie_type", ZombieType.ZOMBIE, zombieIndex++, Enum::ordinal));
+ } else {
+ zombieIndex++; // Not a mistake, this is field unused in 1.11+
+ }
+ if (ver.isOlderThan(ServerVersion.V_1_9)) {
+ register(new EncodedByteProperty<>("is_converting", false, zombieIndex++, b -> (byte) (b ? 1 : 0)));
+ } else if (ver.isOlderThan(ServerVersion.V_1_11)) {
+ register(new BooleanProperty("is_converting", zombieIndex++, false, legacyBooleans));
+ }
+ if (ver.isNewerThanOrEquals(ServerVersion.V_1_9) && ver.isOlderThan(ServerVersion.V_1_14)) {
+ register(new BooleanProperty("zombie_hands_held_up", zombieIndex++, false, legacyBooleans));
+ }
+ if (ver.isNewerThanOrEquals(ServerVersion.V_1_13)) {
+ register(new BooleanProperty("zombie_becoming_drowned", zombieIndex++, false, legacyBooleans));
+ }
+
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_9)) return;
// Shulker
int shulkerIndex;
@@ -758,8 +790,8 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
}
@Override
- public void registerDummy(String name, Class> type) {
- register(new DummyProperty<>(name, type));
+ public void registerDummy(String name, Class> type, boolean playerModifiable) {
+ register(new DummyProperty<>(name, type, playerModifiable));
}
public EntityPropertyImpl> getByName(String name) {
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java
index 1a1e5f2..eb01483 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java
@@ -31,13 +31,22 @@ public class BitsetProperty extends EntityPropertyImpl {
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
- EntityData oldData = properties.get(index);
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
+ EntityData> oldData = properties.get(index);
boolean enabled = entity.getProperty(this);
if (inverted) enabled = !enabled;
- properties.put(index,
- integer ? newEntityData(index, EntityDataTypes.INT, (oldData == null ? 0 : (int) oldData.getValue()) | (enabled ? bitmask : 0)) :
- newEntityData(index, EntityDataTypes.BYTE, (byte) ((oldData == null ? 0 : (byte) oldData.getValue()) | (enabled ? bitmask : 0))));
-
+ if (integer) {
+ int oldValue = 0;
+ if (oldData != null && oldData.getValue() instanceof Number) {
+ oldValue = ((Number) oldData.getValue()).intValue();
+ }
+ properties.put(index, newEntityData(index, EntityDataTypes.INT, oldValue | (enabled ? bitmask : 0)));
+ } else {
+ byte oldValue = 0;
+ if (oldData != null && oldData.getValue() instanceof Number) {
+ oldValue = ((Number) oldData.getValue()).byteValue();
+ }
+ properties.put(index, newEntityData(index, EntityDataTypes.BYTE, (byte) (oldValue | (enabled ? bitmask : 0))));
+ }
}
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BooleanProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BooleanProperty.java
index 5cdb880..bddc0bf 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BooleanProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BooleanProperty.java
@@ -25,7 +25,7 @@ public class BooleanProperty extends EntityPropertyImpl {
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
boolean enabled = entity.getProperty(this);
if (inverted) enabled = !enabled;
if (legacy) properties.put(index, newEntityData(index, EntityDataTypes.BYTE, (byte) (enabled ? 1 : 0)));
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CamelSittingProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CamelSittingProperty.java
index 2732c21..0afa31d 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CamelSittingProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CamelSittingProperty.java
@@ -20,7 +20,7 @@ public class CamelSittingProperty extends EntityPropertyImpl {
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
boolean value = entity.getProperty(this);
if (value) {
properties.put(poseIndex, newEntityData(poseIndex, EntityDataTypes.ENTITY_POSE, EntityPose.SITTING));
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CustomTypeProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CustomTypeProperty.java
index 9946778..0d142d2 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CustomTypeProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CustomTypeProperty.java
@@ -22,7 +22,7 @@ public class CustomTypeProperty extends EntityPropertyImpl {
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
properties.put(index, newEntityData(index, type, decoder.decode(entity.getProperty(this))));
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DinnerboneProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DinnerboneProperty.java
index dab1770..9df06f1 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DinnerboneProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DinnerboneProperty.java
@@ -1,7 +1,6 @@
package lol.pyr.znpcsplus.entity.properties;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
-import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
@@ -16,20 +15,21 @@ import java.util.Optional;
public class DinnerboneProperty extends EntityPropertyImpl {
private final boolean optional;
private final Object serialized;
- private final EntityDataType> type;
public DinnerboneProperty(boolean legacy, boolean optional) {
super("dinnerbone", false, Boolean.class);
this.optional = optional;
Component name = Component.text("Dinnerbone");
- Object serialized = legacy ? AdventureSerializer.getLegacyGsonSerializer().serialize(name) :
+ this.serialized = legacy ? AdventureSerializer.serializer().legacy().serialize(name) :
optional ? name : LegacyComponentSerializer.legacySection().serialize(name);
- this.serialized = optional ? Optional.of(serialized) : serialized;
- this.type = optional ? EntityDataTypes.OPTIONAL_ADV_COMPONENT : EntityDataTypes.STRING;
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
- properties.put(2, new EntityData(2, type, entity.getProperty(this) ? serialized : optional ? null : ""));
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
+ if (optional) {
+ properties.put(2, new EntityData<>(2, EntityDataTypes.OPTIONAL_ADV_COMPONENT, entity.getProperty(this) ? Optional.of((Component) serialized) : Optional.empty()));
+ } else {
+ properties.put(2, new EntityData<>(2, EntityDataTypes.STRING, entity.getProperty(this) ? (String) serialized : ""));
+ }
}
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DummyProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DummyProperty.java
index eba69a5..78d3308 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DummyProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DummyProperty.java
@@ -28,6 +28,6 @@ public class DummyProperty extends EntityPropertyImpl {
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
}
}
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedByteProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedByteProperty.java
index af64b11..19fa125 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedByteProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedByteProperty.java
@@ -36,7 +36,7 @@ public class EncodedByteProperty extends EntityPropertyImpl {
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
T value = entity.getProperty(this);
if (value == null) return;
properties.put(index, newEntityData(index, type, decoder.decode(value)));
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedIntegerProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedIntegerProperty.java
index d089547..896faa1 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedIntegerProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedIntegerProperty.java
@@ -36,7 +36,7 @@ public class EncodedIntegerProperty extends EntityPropertyImpl {
}
@Override
- public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) {
+ public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) {
T value = entity.getProperty(this);
if (value == null) return;
properties.put(index, newEntityData(index, type, decoder.decode(value)));
diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedStringProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedStringProperty.java
index 84e0cd1..2ebc088 100644
--- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedStringProperty.java
+++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedStringProperty.java
@@ -36,7 +36,7 @@ public class EncodedStringProperty extends EntityPropertyImpl