From 8637b5b5c2c7d71b7bbe44e1fae18ee7009435e9 Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Mon, 2 Oct 2023 09:56:52 +0530 Subject: [PATCH] added Tropical Fish properties --- .../znpcsplus/util/TropicalFishVariant.java | 104 ++++++++++++++++++ .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 1 + .../entity/EntityPropertyRegistryImpl.java | 15 ++- .../TropicalFishVariantProperty.java | 49 +++++++++ .../znpcsplus/npc/NpcTypeRegistryImpl.java | 3 +- 5 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 api/src/main/java/lol/pyr/znpcsplus/util/TropicalFishVariant.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/TropicalFishVariantProperty.java diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/TropicalFishVariant.java b/api/src/main/java/lol/pyr/znpcsplus/util/TropicalFishVariant.java new file mode 100644 index 0000000..e201886 --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/util/TropicalFishVariant.java @@ -0,0 +1,104 @@ +package lol.pyr.znpcsplus.util; + +import org.bukkit.DyeColor; + +import java.util.function.IntFunction; + +public class TropicalFishVariant { + + private final TropicalFishPattern pattern; + private final DyeColor bodyColor; + private final DyeColor patternColor; + + public TropicalFishVariant(TropicalFishPattern pattern, DyeColor bodyColor, DyeColor patternColor) { + this.pattern = pattern; + this.bodyColor = bodyColor; + this.patternColor = patternColor; + } + + public int getVariant() { + return pattern.getId() & '\uffff' | (bodyColor.ordinal() & 255) << 16 | (patternColor.ordinal() & 255) << 24; + } + + public enum TropicalFishPattern { + KOB(0, 0), + SUNSTREAK(0, 1), + SNOOPER(0, 2), + DASHER(0, 3), + BRINELY(0, 4), + SPOTTY(0, 5), + FLOPPER(1, 0), + STRIPEY(1, 1), + GLITTER(1, 2), + BLOCKFISH(1, 3), + BETTY(1, 4), + CLAYFISH(1, 5); + + private final int size; + private final int id; + private static final IntFunction BY_ID = (id) -> { + for (TropicalFishPattern pattern : values()) { + if (pattern.id == id) { + return pattern; + } + } + return null; + }; + + TropicalFishPattern(int size, int pattern) { + this.size = size; + this.id = size | pattern << 8; + } + + public int getSize() { + return size; + } + + public int getId() { + return id; + } + + public static TropicalFishPattern fromVariant(int variant) { + return BY_ID.apply(variant & '\uffff'); + } + } + + public static class Builder { + private TropicalFishPattern pattern; + private DyeColor bodyColor; + private DyeColor patternColor; + + public Builder() { + this.pattern = TropicalFishPattern.KOB; + this.bodyColor = DyeColor.WHITE; + this.patternColor = DyeColor.WHITE; + } + + public Builder pattern(TropicalFishPattern pattern) { + this.pattern = pattern; + return this; + } + + public Builder bodyColor(DyeColor bodyColor) { + this.bodyColor = bodyColor; + return this; + } + + public Builder patternColor(DyeColor patternColor) { + this.patternColor = patternColor; + return this; + } + + public static Builder fromInt(int variant) { + Builder builder = new Builder(); + builder.pattern = TropicalFishPattern.fromVariant(variant); + builder.bodyColor = DyeColor.values()[(variant >> 16) & 0xFF]; + builder.patternColor = DyeColor.values()[(variant >> 24) & 0xFF]; + return builder; + } + + public TropicalFishVariant build() { + return new TropicalFishVariant(pattern, bodyColor, patternColor); + } + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index 2013141..f4736d6 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -278,6 +278,7 @@ public class ZNpcsPlus extends JavaPlugin { registerEnumParser(manager, PandaGene.class, incorrectUsageMessage); registerEnumParser(manager, PuffState.class, incorrectUsageMessage); registerEnumParser(manager, LookType.class, incorrectUsageMessage); + registerEnumParser(manager, TropicalFishVariant.TropicalFishPattern.class, incorrectUsageMessage); manager.registerCommand("npc", new MultiCommand(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 f26741f..e97658c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -76,6 +76,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { registerEnumSerializer(OcelotType.class); registerEnumSerializer(PandaGene.class); registerEnumSerializer(PuffState.class); + registerEnumSerializer(TropicalFishVariant.TropicalFishPattern.class); registerPrimitiveSerializers(Integer.class, Boolean.class, Double.class, Float.class, Long.class, Short.class, Byte.class, String.class); @@ -96,9 +97,6 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { // Guardian registerType("is_elder", false); // TODO: ensure it only works till 1.10. Note: index is wrong on wiki.vg - // Tropical Fish - registerType("tropical_fish_variant", null); // TODO: Maybe make an enum class for this? its just an int on wiki.vg - // Sniffer registerType("sniffer_state", null); // TODO: Nothing on wiki.vg, look in mc source @@ -398,6 +396,17 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { else pufferfishIndex = 13; register(new EncodedIntegerProperty<>("puff_state", PuffState.DEFLATED, pufferfishIndex, Enum::ordinal)); + // Tropical Fish + int tropicalFishIndex; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) tropicalFishIndex = 17; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) tropicalFishIndex = 16; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) tropicalFishIndex = 15; + else tropicalFishIndex = 13; + register(new TropicalFishVariantProperty<>("tropical_fish_pattern", TropicalFishVariant.TropicalFishPattern.KOB, tropicalFishIndex, TropicalFishVariant.Builder::pattern)); + register(new TropicalFishVariantProperty<>("tropical_fish_body_color", DyeColor.WHITE, tropicalFishIndex, TropicalFishVariant.Builder::bodyColor)); + register(new TropicalFishVariantProperty<>("tropical_fish_pattern_color", DyeColor.WHITE, tropicalFishIndex, TropicalFishVariant.Builder::patternColor)); + linkProperties("tropical_fish_pattern", "tropical_fish_body_color", "tropical_fish_pattern_color"); + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_14)) return; // Pose register(new NpcPoseProperty()); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/TropicalFishVariantProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/TropicalFishVariantProperty.java new file mode 100644 index 0000000..99c8d68 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/TropicalFishVariantProperty.java @@ -0,0 +1,49 @@ +package lol.pyr.znpcsplus.entity.properties; + +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 lol.pyr.znpcsplus.util.TropicalFishVariant; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class TropicalFishVariantProperty extends EntityPropertyImpl { + private final int index; + private final BuilderDecoder decoder; + + public TropicalFishVariantProperty(String name, T defaultValue, Class type, int index, BuilderDecoder decoder) { + super(name, defaultValue, type); + this.index = index; + this.decoder = decoder; + } + + @SuppressWarnings("unchecked") + public TropicalFishVariantProperty(String name, T defaultValue, int index, BuilderDecoder decoder) { + this(name, defaultValue, (Class) defaultValue.getClass(), index, decoder); + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + T value = entity.getProperty(this); + if (value == null) { + return; + } + EntityData oldData = properties.get(index); + TropicalFishVariant.Builder builder; + if (oldData != null && oldData.getType() == EntityDataTypes.INT && oldData.getValue() != null) { + int oldVal = (int) oldData.getValue(); + builder = TropicalFishVariant.Builder.fromInt(oldVal); + } else { + builder = new TropicalFishVariant.Builder(); + } + builder = decoder.decode(builder, value); + int variant = builder.build().getVariant(); + properties.put(index, newEntityData(index, EntityDataTypes.INT, variant)); + } + + public interface BuilderDecoder { + TropicalFishVariant.Builder decode(TropicalFishVariant.Builder builder, T obj); + } +} 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 e12d9e2..9227d99 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -257,7 +257,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { .setHologramOffset(-1.575)); register(builder(p, "tropical_fish", EntityTypes.TROPICAL_FISH) - .setHologramOffset(-1.575)); + .setHologramOffset(-1.575) + .addProperties("tropical_fish_pattern", "tropical_fish_body_color", "tropical_fish_pattern_color")); register(builder(p, "turtle", EntityTypes.TURTLE) .setHologramOffset(-1.575));