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