From b8dda22154a1fa49752ae5b215c8dee85b06ba50 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 18:25:22 +0530 Subject: [PATCH 1/7] feat: added look_return property --- .../entity/EntityPropertyRegistryImpl.java | 1 + .../java/lol/pyr/znpcsplus/npc/NpcImpl.java | 19 +++++++++++++++++++ .../lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 2 +- .../pyr/znpcsplus/tasks/NpcProcessorTask.java | 17 ++++++++++++++--- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 024a28a..8105e76 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -126,6 +126,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { register(new DummyProperty<>("look", LookType.FIXED)); register(new DummyProperty<>("look_distance", configManager.getConfig().lookPropertyDistance())); + register(new DummyProperty<>("look_return", false)); register(new DummyProperty<>("view_distance", configManager.getConfig().viewDistance())); register(new DummyProperty<>("permission_required", false)); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index d340f32..2be57a3 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class NpcImpl extends Viewable implements Npc { @@ -40,6 +41,8 @@ public class NpcImpl extends Viewable implements Npc { private final Map, Object> propertyMap = new HashMap<>(); private final List actions = new ArrayList<>(); + private final Map playerLookMap = new ConcurrentHashMap<>(); + protected NpcImpl(UUID uuid, EntityPropertyRegistryImpl propertyRegistry, ConfigManager configManager, LegacyComponentSerializer textSerializer, World world, NpcTypeImpl type, NpcLocation location, PacketFactory packetFactory) { this(uuid, propertyRegistry, configManager, packetFactory, textSerializer, world.getName(), type, location); } @@ -87,20 +90,34 @@ public class NpcImpl extends Viewable implements Npc { public void setLocation(NpcLocation location) { this.location = location; + playerLookMap.clear(); + playerLookMap.putAll(getViewers().stream().collect(Collectors.toMap(Player::getUniqueId, player -> new float[]{location.getYaw(), location.getPitch()}))); entity.setLocation(location); hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); } public void setHeadRotation(Player player, float yaw, float pitch) { + if (getHeadYaw(player) == yaw && getHeadPitch(player) == pitch) return; + playerLookMap.put(player.getUniqueId(), new float[]{yaw, pitch}); entity.setHeadRotation(player, yaw, pitch); } public void setHeadRotation(float yaw, float pitch) { for (Player player : getViewers()) { + if (getHeadYaw(player) == yaw && getHeadPitch(player) == pitch) continue; + playerLookMap.put(player.getUniqueId(), new float[]{yaw, pitch}); entity.setHeadRotation(player, yaw, pitch); } } + public float getHeadYaw(Player player) { + return playerLookMap.getOrDefault(player.getUniqueId(), new float[]{location.getYaw(), location.getPitch()})[0]; + } + + public float getHeadPitch(Player player) { + return playerLookMap.getOrDefault(player.getUniqueId(), new float[]{location.getYaw(), location.getPitch()})[1]; + } + public HologramImpl getHologram() { return hologram; } @@ -128,11 +145,13 @@ public class NpcImpl extends Viewable implements Npc { @Override protected CompletableFuture UNSAFE_show(Player player) { + playerLookMap.put(player.getUniqueId(), new float[]{location.getYaw(), location.getPitch()}); return CompletableFuture.allOf(entity.spawn(player), hologram.show(player)); } @Override protected void UNSAFE_hide(Player player) { + playerLookMap.remove(player.getUniqueId()); entity.despawn(player); hologram.hide(player); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index f62adb8..207e75c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -114,7 +114,7 @@ public class NpcTypeImpl implements NpcType { public NpcTypeImpl build() { ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); - addProperties("fire", "invisible", "silent", "look", "look_distance", "view_distance", + addProperties("fire", "invisible", "silent", "look", "look_distance", "look_return", "view_distance", "potion_color", "potion_ambient", "display_name", "permission_required", "player_knockback", "player_knockback_exempt_permission", "player_knockback_distance", "player_knockback_vertical", "player_knockback_horizontal", "player_knockback_cooldown", "player_knockback_sound", "player_knockback_sound_name", diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java b/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java index e0cdcf1..a975546 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/tasks/NpcProcessorTask.java @@ -33,6 +33,7 @@ public class NpcProcessorTask extends BukkitRunnable { EntityPropertyImpl viewDistanceProperty = propertyRegistry.getByName("view_distance", Integer.class); // Not sure why this is an Integer, but it is EntityPropertyImpl lookProperty = propertyRegistry.getByName("look", LookType.class); EntityPropertyImpl lookDistanceProperty = propertyRegistry.getByName("look_distance", Double.class); + EntityPropertyImpl lookReturnProperty = propertyRegistry.getByName("look_return", Boolean.class); EntityPropertyImpl permissionRequiredProperty = propertyRegistry.getByName("permission_required", Boolean.class); EntityPropertyImpl playerKnockbackProperty = propertyRegistry.getByName("player_knockback", Boolean.class); EntityPropertyImpl playerKnockbackExemptPermissionProperty = propertyRegistry.getByName("player_knockback_exempt_permission", String.class); @@ -45,6 +46,7 @@ public class NpcProcessorTask extends BukkitRunnable { EntityPropertyImpl playerKnockbackSoundVolumeProperty = propertyRegistry.getByName("player_knockback_sound_volume", Float.class); EntityPropertyImpl playerKnockbackSoundPitchProperty = propertyRegistry.getByName("player_knockback_sound_pitch", Float.class); double lookDistance; + boolean lookReturn; boolean permissionRequired; boolean playerKnockback; String playerKnockbackExemptPermission = null; @@ -64,6 +66,7 @@ public class NpcProcessorTask extends BukkitRunnable { Player closest = null; LookType lookType = npc.getProperty(lookProperty); lookDistance = NumberConversions.square(npc.getProperty(lookDistanceProperty)); + lookReturn = npc.getProperty(lookReturnProperty); permissionRequired = npc.getProperty(permissionRequiredProperty); playerKnockback = npc.getProperty(playerKnockbackProperty); if (playerKnockback) { @@ -106,9 +109,13 @@ public class NpcProcessorTask extends BukkitRunnable { closestDist = distance; closest = player; } - if (lookType.equals(LookType.PER_PLAYER) && lookDistance >= distance) { - NpcLocation expected = npc.getLocation().lookingAt(player.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); - if (!expected.equals(npc.getLocation())) npc.setHeadRotation(player, expected.getYaw(), expected.getPitch()); + if (lookType.equals(LookType.PER_PLAYER)) { + if (lookDistance >= distance) { + NpcLocation expected = npc.getLocation().lookingAt(player.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); + npc.setHeadRotation(player, expected.getYaw(), expected.getPitch()); + } else if (lookReturn) { + npc.setHeadRotation(player, npc.getLocation().getYaw(), npc.getLocation().getPitch()); + } } // player knockback @@ -132,7 +139,11 @@ public class NpcProcessorTask extends BukkitRunnable { if (closest != null && lookDistance >= closestDist) { NpcLocation expected = npc.getLocation().lookingAt(closest.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); if (!expected.equals(npc.getLocation())) npc.setHeadRotation(expected.getYaw(), expected.getPitch()); + } else if (lookReturn) { + npc.setHeadRotation(npc.getLocation().getYaw(), npc.getLocation().getPitch()); } + } else if (lookType.equals(LookType.FIXED)) { + npc.setHeadRotation(npc.getLocation().getYaw(), npc.getLocation().getPitch()); } } } From 218c4e48cc083dd30f4c574795703bb558d17ac4 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 18:26:45 +0530 Subject: [PATCH 2/7] fix: glow import for znpcs --- .../znpcsplus/conversion/znpcs/ZNpcImporter.java | 13 ++++++++----- .../conversion/znpcs/model/ZNpcsModel.java | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java index dccf704..604347f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/ZNpcImporter.java @@ -189,12 +189,15 @@ public class ZNpcImporter implements DataImporter { if (toggleValues.containsKey("mirror")) { npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new MirrorDescriptor(skinCache)); } - if (toggleValues.containsKey("glow")) { - try { - npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.valueOf((String) toggleValues.get("glow"))); - } catch (IllegalArgumentException e) { + if (toggleValues.containsKey("glow") && (boolean) toggleValues.get("glow")) { + if (!model.getGlowName().isEmpty()) + try { + npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.valueOf(model.getGlowName())); + } catch (IllegalArgumentException e) { + npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.WHITE); + } + else npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.WHITE); - } } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java index 67ecfa0..987a9b4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsModel.java @@ -84,4 +84,8 @@ public class ZNpcsModel { public String getSignature() { return signature; } + + public String getGlowName() { + return glowName; + } } \ No newline at end of file From 97fd7bfd762e2f9788b92bdd0ce33ec69dfd39b8 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 19:15:36 +0530 Subject: [PATCH 3/7] feat: added attribute_max_health and health properties --- .../commands/property/PropertySetCommand.java | 10 +++ .../entity/EntityPropertyRegistryImpl.java | 12 ++++ .../entity/properties/HealthProperty.java | 27 ++++++++ .../attributes/AttributeProperty.java | 63 +++++++++++++++++++ .../lol/pyr/znpcsplus/npc/NpcTypeImpl.java | 3 + .../pyr/znpcsplus/packets/PacketFactory.java | 3 + .../znpcsplus/packets/V1_17PacketFactory.java | 2 + .../packets/V1_20_2PacketFactory.java | 1 + .../znpcsplus/packets/V1_8PacketFactory.java | 18 ++++++ 9 files changed, 139 insertions(+) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java index 334d7f6..53a5e25 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java @@ -11,6 +11,7 @@ import lol.pyr.director.adventure.command.CommandHandler; import lol.pyr.director.common.command.CommandExecutionException; import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.properties.attributes.AttributeProperty; import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; @@ -124,6 +125,15 @@ public class PropertySetCommand implements CommandHandler { value = context.parse(type); valueName = value == null ? "NONE" : ((Vector3i) value).toPrettyString(); } + else if (property instanceof AttributeProperty) { + value = context.parse(type); + if ((double) value < ((AttributeProperty) property).getMinValue() || (double) value > ((AttributeProperty) property).getMaxValue()) { + double sanitizedValue = ((AttributeProperty) property).sanitizeValue((double) value); + context.send(Component.text("WARNING: Value " + value + " is out of range for property " + property.getName() + ", setting to " + sanitizedValue, NamedTextColor.YELLOW)); + value = sanitizedValue; + } + valueName = String.valueOf(value); + } else { try { value = context.parse(type); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index 8105e76..b4ba5b2 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -2,6 +2,7 @@ package lol.pyr.znpcsplus.entity; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.attribute.Attributes; import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -15,6 +16,7 @@ import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; import lol.pyr.znpcsplus.api.skin.SkinDescriptor; import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.entity.properties.*; +import lol.pyr.znpcsplus.entity.properties.attributes.AttributeProperty; import lol.pyr.znpcsplus.entity.properties.villager.VillagerLevelProperty; import lol.pyr.znpcsplus.entity.properties.villager.VillagerProfessionProperty; import lol.pyr.znpcsplus.entity.properties.villager.VillagerTypeProperty; @@ -154,6 +156,16 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { linkProperties("glow", "fire", "invisible"); register(new BooleanProperty("silent", 4, false, legacyBooleans)); + // Attribute Max Health + register(new AttributeProperty(packetFactory, "attribute_max_health", Attributes.MAX_HEALTH)); + + // Health - LivingEntity + int healthIndex = 6; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) healthIndex = 9; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) healthIndex = 8; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) healthIndex = 7; + register(new HealthProperty(healthIndex)); + final int tameableIndex; if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) tameableIndex = 17; else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) tameableIndex = 16; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java new file mode 100644 index 0000000..82615c5 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java @@ -0,0 +1,27 @@ +package lol.pyr.znpcsplus.entity.properties; + +import com.github.retrooper.packetevents.protocol.attribute.Attributes; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class HealthProperty extends EntityPropertyImpl { + private final int index; + + public HealthProperty(int index) { + super("health", 20f, Float.class); + this.index = index; + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + float health = entity.getProperty(this); + health = (float) Attributes.MAX_HEALTH.sanitizeValue(health); + properties.put(index, new EntityData(index, EntityDataTypes.FLOAT, health)); + + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java new file mode 100644 index 0000000..30ae5af --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/attributes/AttributeProperty.java @@ -0,0 +1,63 @@ +package lol.pyr.znpcsplus.entity.properties.attributes; + +import com.github.retrooper.packetevents.protocol.attribute.Attribute; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.packets.PacketFactory; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class AttributeProperty extends EntityPropertyImpl { + private final PacketFactory packetFactory; + private final Attribute attribute; + + public AttributeProperty(PacketFactory packetFactory, String name, Attribute attribute) { + super(name, attribute.getDefaultValue(), Double.class); + this.packetFactory = packetFactory; + this.attribute = attribute; + } + + public double getMinValue() { + return attribute.getMinValue(); + } + + public double getMaxValue() { + return attribute.getMaxValue(); + } + + public double sanitizeValue(double value) { + return attribute.sanitizeValue(value); + } + + @Override + public List applyStandalone(Player player, PacketEntity packetEntity, boolean isSpawned) { + apply(player, packetEntity, isSpawned, Collections.emptyList()); + return Collections.emptyList(); + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + } + + public void apply(Player player, PacketEntity entity, boolean isSpawned, List properties) { + Double value = entity.getProperty(this); + if (value == null) { + return; + } + value = attribute.sanitizeValue(value); + if (isSpawned) { + packetFactory.sendAttribute(player, entity, new WrapperPlayServerUpdateAttributes.Property(attribute, value, Collections.emptyList())); + } else { + properties.add(new WrapperPlayServerUpdateAttributes.Property(attribute, value, Collections.emptyList())); + } + } + + public Attribute getAttribute() { + return attribute; + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index 207e75c..b2eae03 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -120,6 +120,9 @@ public class NpcTypeImpl implements NpcType { "player_knockback_horizontal", "player_knockback_cooldown", "player_knockback_sound", "player_knockback_sound_name", "player_knockback_sound_volume", "player_knockback_sound_pitch"); if (!type.equals(EntityTypes.PLAYER)) addProperties("dinnerbone"); + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.LIVINGENTITY)) { + addProperties("health", "attribute_max_health"); + } // TODO: make this look nicer after completing the rest of the properties if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow"); if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index f2b58c1..1d3ba41 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -2,6 +2,7 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.player.Equipment; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.util.NamedColor; @@ -25,4 +26,6 @@ public interface PacketFactory { void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); void sendHandSwing(Player player, PacketEntity entity, boolean offHand); void setPassengers(Player player, int vehicle, int... passengers); + void sendAllAttributes(Player player, PacketEntity entity, PropertyHolder properties); + void sendAttribute(Player player, PacketEntity entity, WrapperPlayServerUpdateAttributes.Property property); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java index 45b6e41..5a97fbf 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java @@ -1,6 +1,7 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEventsAPI; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; import lol.pyr.znpcsplus.api.entity.PropertyHolder; @@ -27,6 +28,7 @@ public class V1_17PacketFactory extends V1_8PacketFactory { sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d()))); sendAllMetadata(player, entity, properties); + if (EntityTypes.isTypeInstanceOf(entity.getType(), EntityTypes.LIVINGENTITY)) sendAllAttributes(player, entity, properties); createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java index 9d5de17..4a760e4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java @@ -36,6 +36,7 @@ public class V1_20_2PacketFactory extends V1_19_3PacketFactory { npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d()))); sendPacket(player, new WrapperPlayServerEntityHeadLook(entity.getEntityId(), location.getYaw())); sendAllMetadata(player, entity, properties); + sendAllAttributes(player, entity, properties); scheduler.runLaterAsync(() -> removeTabPlayer(player, entity), configManager.getConfig().tabHideDelay()); }); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index 3fe0504..e288aa2 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -18,6 +18,7 @@ import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.entity.EntityPropertyImpl; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.properties.attributes.AttributeProperty; import lol.pyr.znpcsplus.scheduling.TaskScheduler; import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; import lol.pyr.znpcsplus.util.NamedColor; @@ -55,6 +56,7 @@ public class V1_8PacketFactory implements PacketFactory { entity.getUuid(), npcLocationToVector(location), location.getYaw(), location.getPitch(), Collections.emptyList())); sendPacket(player, new WrapperPlayServerEntityHeadLook(entity.getEntityId(), location.getYaw())); sendAllMetadata(player, entity, properties); + sendAllAttributes(player, entity, properties); scheduler.runLaterAsync(() -> removeTabPlayer(player, entity), configManager.getConfig().tabHideDelay()); }); } @@ -70,6 +72,7 @@ public class V1_8PacketFactory implements PacketFactory { new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); sendAllMetadata(player, entity, properties); + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.LIVINGENTITY)) sendAllAttributes(player, entity, properties); createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); } @@ -187,4 +190,19 @@ public class V1_8PacketFactory implements PacketFactory { WrapperPlayServerEntityAnimation.EntityAnimationType.SWING_OFF_HAND : WrapperPlayServerEntityAnimation.EntityAnimationType.SWING_MAIN_ARM)); } + + @Override + public void sendAllAttributes(Player player, PacketEntity entity, PropertyHolder properties) { + List attributesList = new ArrayList<>(); + properties.getAppliedProperties() + .stream() + .filter(property -> property instanceof AttributeProperty) + .forEach(property -> ((AttributeProperty) property).apply(player, entity, false, attributesList)); + sendPacket(player, new WrapperPlayServerUpdateAttributes(entity.getEntityId(), attributesList)); + } + + @Override + public void sendAttribute(Player player, PacketEntity entity, WrapperPlayServerUpdateAttributes.Property property) { + sendPacket(player, new WrapperPlayServerUpdateAttributes(entity.getEntityId(), Collections.singletonList(property))); + } } From ba75abcebcfbdc35e5e0cd6ca55ea9168d628ead Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Fri, 27 Dec 2024 19:30:50 +0530 Subject: [PATCH 4/7] feat: added version command --- plugin/build.gradle | 18 ++++++ .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 1 + .../znpcsplus/commands/VersionCommand.java | 64 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java diff --git a/plugin/build.gradle b/plugin/build.gradle index 7cbf95f..ac8ee3d 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -30,10 +30,28 @@ dependencies { implementation project(":api") } +ext { + gitBranch = System.getenv('GIT_BRANCH') ?: '' + gitCommitHash = System.getenv('GIT_COMMIT') ?: '' + buildId = System.getenv('BUILD_ID') ?: '' +} + shadowJar { archivesBaseName = "ZNPCsPlus" archiveClassifier.set "" + manifest { + if (gitBranch?.trim()) { + attributes('Git-Branch': gitBranch) + } + if (gitCommitHash?.trim()) { + attributes('Git-Commit': gitCommitHash) + } + if (buildId?.trim()) { + attributes('Build-Id': buildId) + } + } + relocate "org.objectweb.asm", "lol.pyr.znpcsplus.libraries.asm" relocate "me.lucko.jarrelocator", "lol.pyr.znpcsplus.libraries.jarrelocator" diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index 2a0d64f..2a12c2d 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -342,6 +342,7 @@ public class ZNpcsPlus { .addSubcommand("delete", new ActionDeleteCommand(npcRegistry)) .addSubcommand("edit", new ActionEditCommand(npcRegistry, actionRegistry)) .addSubcommand("list", new ActionListCommand(npcRegistry))) + .addSubcommand("version", new VersionCommand(this)) ); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java new file mode 100644 index 0000000..f59bf17 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/VersionCommand.java @@ -0,0 +1,64 @@ +package lol.pyr.znpcsplus.commands; + +import lol.pyr.director.adventure.command.CommandContext; +import lol.pyr.director.adventure.command.CommandHandler; +import lol.pyr.director.common.command.CommandExecutionException; +import lol.pyr.znpcsplus.ZNpcsPlus; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.jar.Attributes; +import java.util.jar.JarFile; + +public class VersionCommand implements CommandHandler { + + private final String pluginVersion; + private final String gitBranch; + private final String gitCommitHash; + private final String buildId; + + public VersionCommand(ZNpcsPlus plugin) { + pluginVersion = plugin.getDescription().getVersion(); + String gitBranch = ""; + String gitCommitHash = ""; + String buildId = ""; + try { + URL jarUrl = getClass().getProtectionDomain().getCodeSource().getLocation(); + JarFile jarFile = new JarFile(jarUrl.toURI().getPath()); + Attributes attributes = jarFile.getManifest().getMainAttributes(); + gitBranch = attributes.getValue("Git-Branch"); + gitCommitHash = attributes.getValue("Git-Commit-Hash"); + buildId = attributes.getValue("Build-Id"); + } catch (IOException | URISyntaxException e) { + e.printStackTrace(); + } + this.gitBranch = gitBranch; + this.gitCommitHash = gitCommitHash; + this.buildId = buildId; + } + + @Override + public void run(CommandContext context) throws CommandExecutionException { + + StringBuilder versionBuilder = new StringBuilder("This server is running ZNPCsPlus version ").append(pluginVersion); + if (gitBranch != null && !gitBranch.isEmpty()) { + versionBuilder.append("-").append(gitBranch); + } + if (gitCommitHash != null && !gitCommitHash.isEmpty()) { + versionBuilder.append("@").append(gitCommitHash); + } + if (buildId != null && !buildId.isEmpty()) { + versionBuilder.append(" (Build #").append(buildId).append(")"); + } + + String version = versionBuilder.toString(); + + context.send(Component.text(version, NamedTextColor.GREEN) + .hoverEvent(Component.text("Click to copy version to clipboard")) + .clickEvent(ClickEvent.copyToClipboard(version))); + } +} From d1b890a9126632e988b3ac86d75f40928822ef91 Mon Sep 17 00:00:00 2001 From: envizar Date: Sun, 29 Dec 2024 14:13:37 +0300 Subject: [PATCH 5/7] toggle command with arg --- .../lol/pyr/znpcsplus/commands/ToggleCommand.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java index c6d1c06..764f771 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java @@ -11,6 +11,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import java.util.Collections; import java.util.List; +import java.util.Set; public class ToggleCommand implements CommandHandler { private final NpcRegistryImpl npcRegistry; @@ -21,9 +22,14 @@ public class ToggleCommand implements CommandHandler { @Override public void run(CommandContext context) throws CommandExecutionException { - context.setUsage(context.getLabel() + " toggle "); + context.setUsage(context.getLabel() + " toggle []"); NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); - boolean enabled = !npc.isEnabled(); + boolean enabled; + if (context.argSize() == 1) { + enabled = context.popString().equals("enable"); + } else { + enabled = !npc.isEnabled(); + } npc.setEnabled(enabled); context.send(Component.text("NPC has been " + (enabled ? "enabled" : "disabled"), NamedTextColor.GREEN)); } @@ -31,6 +37,7 @@ public class ToggleCommand implements CommandHandler { @Override public List suggest(CommandContext context) throws CommandExecutionException { if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); + if (context.argSize() == 2) return context.suggestLiteral("enable", "disable"); return Collections.emptyList(); } } From dfdcc54313639e0a190e5581dc44368550b18c94 Mon Sep 17 00:00:00 2001 From: envizar Date: Sun, 29 Dec 2024 14:29:17 +0300 Subject: [PATCH 6/7] default type = player in create command --- .../java/lol/pyr/znpcsplus/commands/CreateCommand.java | 10 ++++++++-- .../java/lol/pyr/znpcsplus/commands/ToggleCommand.java | 1 - 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java index 1c3c1e9..341edca 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/CreateCommand.java @@ -26,12 +26,18 @@ public class CreateCommand implements CommandHandler { @Override public void run(CommandContext context) throws CommandExecutionException { - context.setUsage(context.getLabel() + " create "); + context.setUsage(context.getLabel() + " create []"); Player player = context.ensureSenderIsPlayer(); String id = context.popString(); if (npcRegistry.getById(id) != null) context.halt(Component.text("NPC with that ID already exists.", NamedTextColor.RED)); - NpcTypeImpl type = context.parse(NpcTypeImpl.class); + + NpcTypeImpl type; + if (context.argSize() == 1) { + type = context.parse(NpcTypeImpl.class); + } else { + type = typeRegistry.getByName("player"); + } NpcEntryImpl entry = npcRegistry.create(id, player.getWorld(), type, new NpcLocation(player.getLocation())); entry.enableEverything(); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java index 764f771..4b122d6 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java @@ -11,7 +11,6 @@ import net.kyori.adventure.text.format.NamedTextColor; import java.util.Collections; import java.util.List; -import java.util.Set; public class ToggleCommand implements CommandHandler { private final NpcRegistryImpl npcRegistry; From ec60af7186b43ea8da0c662646ecbc5f04e31815 Mon Sep 17 00:00:00 2001 From: envizar Date: Sun, 29 Dec 2024 14:43:19 +0300 Subject: [PATCH 7/7] 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(); }