Merge pull request #89 from D3v1s0m/modular-property-system

Properties
This commit is contained in:
Pyr 2023-09-12 22:09:33 +02:00 committed by GitHub
commit fb3a22a355
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 481 additions and 86 deletions

View file

@ -0,0 +1,8 @@
package lol.pyr.znpcsplus.util;
public enum LlamaVariant {
CREAMY,
WHITE,
BROWN,
GRAY
}

View file

@ -0,0 +1,10 @@
package lol.pyr.znpcsplus.util;
public enum MooshroomVariant {
RED,
BROWN;
public static String getVariantName(MooshroomVariant variant) {
return variant.name().toLowerCase();
}
}

View file

@ -0,0 +1,8 @@
package lol.pyr.znpcsplus.util;
public enum OcelotType {
OCELOT,
TUXEDO,
TABBY,
SIAMESE,
}

View file

@ -0,0 +1,11 @@
package lol.pyr.znpcsplus.util;
public enum PandaGene {
NORMAL,
LAZY,
WORRIED,
PLAYFUL,
BROWN,
WEAK,
AGGRESSIVE
}

View file

@ -5,6 +5,5 @@ public enum ParrotVariant {
BLUE, BLUE,
GREEN, GREEN,
YELLOW_BLUE, YELLOW_BLUE,
GRAY, GRAY
NONE // only used to set empty nbt compound
} }

View file

@ -0,0 +1,7 @@
package lol.pyr.znpcsplus.util;
public enum PuffState {
DEFLATED,
HALF_INFLATED,
FULLY_INFLATED,
}

View file

@ -145,7 +145,7 @@ public class ZNpcsPlus extends JavaPlugin {
DataImporterRegistry importerRegistry = new DataImporterRegistry(configManager, adventure, bungeeConnector, DataImporterRegistry importerRegistry = new DataImporterRegistry(configManager, adventure, bungeeConnector,
scheduler, packetFactory, textSerializer, typeRegistry, getDataFolder().getParentFile(), scheduler, packetFactory, textSerializer, typeRegistry, getDataFolder().getParentFile(),
propertyRegistry, skinCache); propertyRegistry, skinCache, npcRegistry);
log(ChatColor.WHITE + " * Registerring components..."); log(ChatColor.WHITE + " * Registerring components...");
@ -270,6 +270,11 @@ public class ZNpcsPlus extends JavaPlugin {
registerEnumParser(manager, HorseStyle.class, incorrectUsageMessage); registerEnumParser(manager, HorseStyle.class, incorrectUsageMessage);
registerEnumParser(manager, HorseColor.class, incorrectUsageMessage); registerEnumParser(manager, HorseColor.class, incorrectUsageMessage);
registerEnumParser(manager, HorseArmor.class, incorrectUsageMessage); registerEnumParser(manager, HorseArmor.class, incorrectUsageMessage);
registerEnumParser(manager, LlamaVariant.class, incorrectUsageMessage);
registerEnumParser(manager, MooshroomVariant.class, incorrectUsageMessage);
registerEnumParser(manager, OcelotType.class, incorrectUsageMessage);
registerEnumParser(manager, PandaGene.class, incorrectUsageMessage);
registerEnumParser(manager, PuffState.class, incorrectUsageMessage);
manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root")) manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root"))
.addSubcommand("create", new CreateCommand(npcRegistry, typeRegistry)) .addSubcommand("create", new CreateCommand(npcRegistry, typeRegistry))

View file

@ -1,5 +1,7 @@
package lol.pyr.znpcsplus.commands.property; package lol.pyr.znpcsplus.commands.property;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType; import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
@ -18,6 +20,7 @@ import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Color; import org.bukkit.Color;
import com.github.retrooper.packetevents.protocol.item.ItemStack; import com.github.retrooper.packetevents.protocol.item.ItemStack;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -60,7 +63,7 @@ public class PropertySetCommand implements CommandHandler {
valueName = "NONE"; valueName = "NONE";
} }
else if (type == ParrotVariant.class && context.argSize() < 1 && npc.getProperty(property) != null) { else if (type == ParrotVariant.class && context.argSize() < 1 && npc.getProperty(property) != null) {
value = ParrotVariant.NONE; value = null;
valueName = "NONE"; valueName = "NONE";
} }
else if (type == BlockState.class) { else if (type == BlockState.class) {
@ -96,6 +99,24 @@ public class PropertySetCommand implements CommandHandler {
return; return;
} }
} }
else if (type == SpellType.class) {
if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_13)) {
value = context.parse(type);
valueName = String.valueOf(value);
if (((SpellType) value).ordinal() > 3) {
context.send(Component.text("Spell type " + valueName + " is not supported on this version", NamedTextColor.RED));
return;
}
}
else {
value = context.parse(type);
valueName = String.valueOf(value);
}
}
else if (type == NpcEntryImpl.class) {
value = context.parse(type);
valueName = value == null ? "NONE" : ((NpcEntryImpl) value).getId();
}
else { else {
value = context.parse(type); value = context.parse(type);
valueName = String.valueOf(value); valueName = String.valueOf(value);
@ -119,6 +140,9 @@ public class PropertySetCommand implements CommandHandler {
if (type == NamedTextColor.class) return context.suggestCollection(NamedTextColor.NAMES.keys()); if (type == NamedTextColor.class) return context.suggestCollection(NamedTextColor.NAMES.keys());
if (type == Color.class) return context.suggestLiteral("0x0F00FF", "#FFFFFF"); if (type == Color.class) return context.suggestLiteral("0x0F00FF", "#FFFFFF");
if (type == BlockState.class) return context.suggestLiteral("hand", "looking_at", "block"); if (type == BlockState.class) return context.suggestLiteral("hand", "looking_at", "block");
if (type == SpellType.class) return PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_13) ?
context.suggestEnum(Arrays.stream(SpellType.values()).filter(spellType -> spellType.ordinal() <= 3).toArray(SpellType[]::new)) :
context.suggestEnum(SpellType.values());
// Suggest enum values directly // Suggest enum values directly
if (type.isEnum()) { if (type.isEnum()) {

View file

@ -4,6 +4,7 @@ import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.conversion.citizens.CitizensImporter; import lol.pyr.znpcsplus.conversion.citizens.CitizensImporter;
import lol.pyr.znpcsplus.conversion.znpcs.ZNpcImporter; import lol.pyr.znpcsplus.conversion.znpcs.ZNpcImporter;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler; import lol.pyr.znpcsplus.scheduling.TaskScheduler;
@ -25,14 +26,14 @@ public class DataImporterRegistry {
public DataImporterRegistry(ConfigManager configManager, BukkitAudiences adventure, BungeeConnector bungeeConnector, public DataImporterRegistry(ConfigManager configManager, BukkitAudiences adventure, BungeeConnector bungeeConnector,
TaskScheduler taskScheduler, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, TaskScheduler taskScheduler, PacketFactory packetFactory, LegacyComponentSerializer textSerializer,
NpcTypeRegistryImpl typeRegistry, File pluginsFolder, EntityPropertyRegistryImpl propertyRegistry, NpcTypeRegistryImpl typeRegistry, File pluginsFolder, EntityPropertyRegistryImpl propertyRegistry,
MojangSkinCache skinCache) { MojangSkinCache skinCache, NpcRegistryImpl npcRegistry) {
register("znpcs", LazyLoader.of(() -> new ZNpcImporter(configManager, adventure, bungeeConnector, taskScheduler, register("znpcs", LazyLoader.of(() -> new ZNpcImporter(configManager, adventure, bungeeConnector, taskScheduler,
packetFactory, textSerializer, typeRegistry, propertyRegistry, skinCache, new File(pluginsFolder, "ServersNPC/data.json")))); packetFactory, textSerializer, typeRegistry, propertyRegistry, skinCache, new File(pluginsFolder, "ServersNPC/data.json"))));
register("znpcsplus_legacy", LazyLoader.of(() -> new ZNpcImporter(configManager, adventure, bungeeConnector, taskScheduler, register("znpcsplus_legacy", LazyLoader.of(() -> new ZNpcImporter(configManager, adventure, bungeeConnector, taskScheduler,
packetFactory, textSerializer, typeRegistry, propertyRegistry, skinCache, new File(pluginsFolder, "ZNPCsPlusLegacy/data.json")))); packetFactory, textSerializer, typeRegistry, propertyRegistry, skinCache, new File(pluginsFolder, "ZNPCsPlusLegacy/data.json"))));
register("citizens", LazyLoader.of(() -> new CitizensImporter(configManager, adventure, bungeeConnector, taskScheduler, register("citizens", LazyLoader.of(() -> new CitizensImporter(configManager, adventure, bungeeConnector, taskScheduler,
packetFactory, textSerializer, typeRegistry, propertyRegistry, skinCache, new File(pluginsFolder, "Citizens/saves.yml")))); packetFactory, textSerializer, typeRegistry, propertyRegistry, skinCache, new File(pluginsFolder, "Citizens/saves.yml"), npcRegistry)));
} }
private void register(String id, LazyLoader<DataImporter> loader) { private void register(String id, LazyLoader<DataImporter> loader) {

View file

@ -1,6 +1,5 @@
package lol.pyr.znpcsplus.conversion.citizens; package lol.pyr.znpcsplus.conversion.citizens;
import lol.pyr.znpcsplus.api.NpcApiProvider;
import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.conversion.DataImporter; import lol.pyr.znpcsplus.conversion.DataImporter;
import lol.pyr.znpcsplus.conversion.citizens.model.CitizensTrait; import lol.pyr.znpcsplus.conversion.citizens.model.CitizensTrait;
@ -8,6 +7,7 @@ import lol.pyr.znpcsplus.conversion.citizens.model.CitizensTraitsRegistry;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl; import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler; import lol.pyr.znpcsplus.scheduling.TaskScheduler;
@ -39,11 +39,12 @@ public class CitizensImporter implements DataImporter {
private final MojangSkinCache skinCache; private final MojangSkinCache skinCache;
private final File dataFile; private final File dataFile;
private final CitizensTraitsRegistry traitsRegistry; private final CitizensTraitsRegistry traitsRegistry;
private final NpcRegistryImpl npcRegistry;
public CitizensImporter(ConfigManager configManager, BukkitAudiences adventure, BungeeConnector bungeeConnector, public CitizensImporter(ConfigManager configManager, BukkitAudiences adventure, BungeeConnector bungeeConnector,
TaskScheduler taskScheduler, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, TaskScheduler taskScheduler, PacketFactory packetFactory, LegacyComponentSerializer textSerializer,
NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, MojangSkinCache skinCache, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, MojangSkinCache skinCache,
File dataFile) { File dataFile, NpcRegistryImpl npcRegistry) {
this.configManager = configManager; this.configManager = configManager;
this.adventure = adventure; this.adventure = adventure;
this.bungeeConnector = bungeeConnector; this.bungeeConnector = bungeeConnector;
@ -55,6 +56,7 @@ public class CitizensImporter implements DataImporter {
this.skinCache = skinCache; this.skinCache = skinCache;
this.dataFile = dataFile; this.dataFile = dataFile;
this.traitsRegistry = new CitizensTraitsRegistry(typeRegistry, propertyRegistry, skinCache); this.traitsRegistry = new CitizensTraitsRegistry(typeRegistry, propertyRegistry, skinCache);
this.npcRegistry = npcRegistry;
} }
@Override @Override
@ -96,8 +98,8 @@ public class CitizensImporter implements DataImporter {
} }
} }
String id = key.toLowerCase(); String id = key.toLowerCase();
while (NpcApiProvider.get().getNpcRegistry().getById(id) != null) { while (npcRegistry.getById(id) != null) {
id += "_"; id += "_"; // TODO: make a backup of the old npc instead
} }
NpcEntryImpl entry = new NpcEntryImpl(id, npc); NpcEntryImpl entry = new NpcEntryImpl(id, npc);
entry.enableEverything(); entry.enableEverything();

View file

@ -3,6 +3,9 @@ package lol.pyr.znpcsplus.entity;
import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot; import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
@ -46,6 +49,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
registerSerializer(new ColorPropertySerializer()); registerSerializer(new ColorPropertySerializer());
registerSerializer(new Vector3fPropertySerializer()); registerSerializer(new Vector3fPropertySerializer());
registerSerializer(new BlockStatePropertySerializer()); registerSerializer(new BlockStatePropertySerializer());
registerSerializer(new IntegerPropertySerializer());
registerEnumSerializer(NpcPose.class); registerEnumSerializer(NpcPose.class);
registerEnumSerializer(DyeColor.class); registerEnumSerializer(DyeColor.class);
@ -63,64 +67,36 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
registerEnumSerializer(HorseColor.class); registerEnumSerializer(HorseColor.class);
registerEnumSerializer(HorseStyle.class); registerEnumSerializer(HorseStyle.class);
registerEnumSerializer(HorseArmor.class); registerEnumSerializer(HorseArmor.class);
registerEnumSerializer(LlamaVariant.class);
registerEnumSerializer(MooshroomVariant.class);
registerEnumSerializer(OcelotType.class);
registerEnumSerializer(PandaGene.class);
registerEnumSerializer(PuffState.class);
/* /*
registerType("using_item", false); // TODO: fix it for 1.8 and add new property to use offhand item and riptide animation registerType("using_item", false); // TODO: fix it for 1.8 and add new property to use offhand item and riptide animation
// Player
registerType("shoulder_entity_left", ParrotVariant.NONE);
registerType("shoulder_entity_right", ParrotVariant.NONE);
// End Crystal // End Crystal
registerType("beam_target", null); // TODO: Make a block pos class for this registerType("beam_target", null); // TODO: Make a block pos class for this
registerType("show_base", true); // TODO registerType("show_base", true); // TODO
// Creeper
registerType("creeper_state", CreeperState.IDLE);
registerType("creeper_charged", false);
// Enderman // Enderman
registerType("enderman_held_block", new BlockState(0)); // TODO: figure out the type on this registerType("enderman_held_block", new BlockState(0)); // TODO: figure out the type on this
registerType("enderman_screaming", false); // TODO registerType("enderman_screaming", false); // TODO
registerType("enderman_staring", false); // TODO registerType("enderman_staring", false); // TODO
// Evoker
registerType("evoker_spell", SpellType.NONE);
// Frog
registerType("frog_variant", FrogVariant.TEMPERATE);
// Guardian // Guardian
registerType("is_elder", false); // TODO: ensure it only works till 1.10. Note: index is wrong on wiki.vg registerType("is_elder", false); // TODO: ensure it only works till 1.10. Note: index is wrong on wiki.vg
// Pufferfish
registerType("puff_state", null); // TODO: Make a puff state enum class
// Tropical Fish // Tropical Fish
registerType("tropical_fish_variant", null); // TODO: Maybe make an enum class for this? its just an int on wiki.vg registerType("tropical_fish_variant", null); // TODO: Maybe make an enum class for this? its just an int on wiki.vg
// Sniffer // Sniffer
registerType("sniffer_state", null); // TODO: Nothing on wiki.vg, look in mc source registerType("sniffer_state", null); // TODO: Nothing on wiki.vg, look in mc source
// LLama
registerType("carpet_color", DyeColor.class); // TODO
registerType("llama_variant", 0); // TODO
// Panda
registerType("panda_sneezing", false); // TODO
registerType("panda_rolling", false); // TODO
registerType("panda_sitting", false); // TODO
registerType("panda_on_back", false); // TODO
// Pig
registerType("pig_saddle", false); // TODO
// Rabbit // Rabbit
registerType("rabbit_type", 0); // TODO: Figure this out registerType("rabbit_type", 0); // TODO: Figure this out
// Polar Bear
registerType("polar_bear_standing", false); // TODO
// Sheep // Sheep
registerType("sheep_color", DyeColor.WHITE); // TODO: Figure this out registerType("sheep_color", DyeColor.WHITE); // TODO: Figure this out
registerType("sheep_sheared", false); // TODO registerType("sheep_sheared", false); // TODO
@ -133,9 +109,6 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
registerType("wolf_collar_color", DyeColor.RED); // TODO registerType("wolf_collar_color", DyeColor.RED); // TODO
registerType("wolf_angry", false); // TODO registerType("wolf_angry", false); // TODO
// Parrot
registerType("parrot_variant", 0); // TODO
// Villager // Villager
registerType("villager_type", VillagerType.PLAINS); registerType("villager_type", VillagerType.PLAINS);
registerType("villager_profession", VillagerProfession.NONE); registerType("villager_profession", VillagerProfession.NONE);
@ -149,21 +122,9 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
registerType("shield_height", 0); // TODO: figure this out registerType("shield_height", 0); // TODO: figure this out
registerType("shulker_color", DyeColor.RED); // TODO registerType("shulker_color", DyeColor.RED); // TODO
// Piglin
registerType("piglin_dancing", false); // TODO
registerType("piglin_charging_crossbow", false); // TODO
// Vindicator
registerType("celebrating", false); // TODO
// Wither // Wither
registerType("invulnerable_time", 0); // TODO registerType("invulnerable_time", 0); // TODO
// Phantom
registerType("phantom_size", 0); // TODO
// Slime
registerType("slime_size", 0); // TODO
*/ */
} }
@ -271,7 +232,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) batIndex = 12; else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) batIndex = 12;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) batIndex = 11; else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) batIndex = 11;
else batIndex = 16; else batIndex = 16;
register(new BooleanProperty("hanging", batIndex, false, true /* This isnt a mistake */)); register(new BooleanProperty("hanging", batIndex, false, true /* This isn't a mistake */));
// Blaze // Blaze
final int blazeIndex; final int blazeIndex;
@ -303,12 +264,11 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) horseIndex = 12; else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) horseIndex = 12;
else horseIndex = 16; else horseIndex = 16;
int horseEating = ver.isNewerThanOrEquals(ServerVersion.V_1_12) ? 0x10 : 0x20; int horseEating = ver.isNewerThanOrEquals(ServerVersion.V_1_12) ? 0x10 : 0x20;
boolean v1_8 = ver.isOlderThan(ServerVersion.V_1_9); register(new BitsetProperty("is_tame", horseIndex, 0x02, false, legacyBooleans));
register(new BitsetProperty("is_tame", horseIndex, 0x02, false, v1_8)); register(new BitsetProperty("is_saddled", horseIndex, 0x04, false, legacyBooleans));
register(new BitsetProperty("is_saddled", horseIndex, 0x04, false, v1_8)); register(new BitsetProperty("is_eating", horseIndex, horseEating, false, legacyBooleans));
register(new BitsetProperty("is_eating", horseIndex, horseEating, false, v1_8)); register(new BitsetProperty("is_rearing", horseIndex, horseEating << 1, false, legacyBooleans));
register(new BitsetProperty("is_rearing", horseIndex, horseEating << 1, false, v1_8)); register(new BitsetProperty("has_mouth_open", horseIndex, horseEating << 2, false, legacyBooleans));
register(new BitsetProperty("has_mouth_open", horseIndex, horseEating << 2, false, v1_8));
// Horse // Horse
if (ver.isNewerThanOrEquals(ServerVersion.V_1_8) && ver.isOlderThan(ServerVersion.V_1_9)) { if (ver.isNewerThanOrEquals(ServerVersion.V_1_8) && ver.isOlderThan(ServerVersion.V_1_9)) {
@ -337,13 +297,100 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
// Chested Horse // Chested Horse
if (ver.isOlderThan(ServerVersion.V_1_11)) { if (ver.isOlderThan(ServerVersion.V_1_11)) {
register(new BitsetProperty("has_chest", horseIndex, 0x08, false, v1_8)); register(new BitsetProperty("has_chest", horseIndex, 0x08, false, legacyBooleans));
linkProperties("is_saddled", "has_chest", "is_eating", "is_rearing", "has_mouth_open"); linkProperties("is_saddled", "has_chest", "is_eating", "is_rearing", "has_mouth_open");
} else { } else {
register(new BooleanProperty("has_chest", horseVariantIndex, false, legacyBooleans)); register(new BooleanProperty("has_chest", horseVariantIndex, false, legacyBooleans));
linkProperties("is_saddled", "is_eating", "is_rearing", "has_mouth_open"); linkProperties("is_saddled", "is_eating", "is_rearing", "has_mouth_open");
} }
// Slime, Magma Cube and Phantom
int sizeIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) sizeIndex = 16;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) sizeIndex = 15;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) sizeIndex = 14;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) sizeIndex = 12;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) sizeIndex = 11;
else sizeIndex = 16;
register(new IntegerProperty("size", sizeIndex, 1, legacyBooleans));
// Ocelot
if (ver.isOlderThan(ServerVersion.V_1_14)) {
int ocelotIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) ocelotIndex = 15;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) ocelotIndex = 14;
else ocelotIndex = 18;
if (legacyBooleans) register(new EncodedByteProperty<>("ocelot_type", OcelotType.OCELOT, ocelotIndex, obj -> (byte) obj.ordinal()));
else register(new EncodedIntegerProperty<>("ocelot_type", OcelotType.OCELOT, ocelotIndex, Enum::ordinal));
}
// Pig
int pigIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) pigIndex = 17;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) pigIndex = 16;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) pigIndex = 15;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) pigIndex = 13;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) pigIndex = 12;
else pigIndex = 16;
register(new BooleanProperty("pig_saddled", pigIndex, false, legacyBooleans));
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_10)) return;
// Polar Bear
int polarBearIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) polarBearIndex = 17;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) polarBearIndex = 16;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) polarBearIndex = 15;
else polarBearIndex = 13;
register(new BooleanProperty("polar_bear_standing", polarBearIndex, false, false));
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_11)) return;
// Spellcaster Illager
int spellIndex = 12;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) spellIndex = 17;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) spellIndex = 16;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) spellIndex = 15;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_12)) spellIndex = 13;
register(new EncodedByteProperty<>("spell", SpellType.NONE, spellIndex, obj -> (byte) Math.min(obj.ordinal(), ver.isOlderThan(ServerVersion.V_1_13) ? 3 : 5)));
// Llama
int llamaIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_18)) llamaIndex = 20;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) llamaIndex = 21;
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<DyeColor>("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;
// Parrot
int parrotIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) parrotIndex = 19;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) parrotIndex = 18;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) parrotIndex = 17;
else parrotIndex = 15;
register(new EncodedIntegerProperty<>("parrot_variant", ParrotVariant.RED_BLUE, parrotIndex, Enum::ordinal));
// Player
NBTProperty.NBTDecoder<ParrotVariant> parrotVariantDecoder = (variant) -> {
NBTCompound compound = new NBTCompound();
compound.setTag("id", new NBTString("minecraft:parrot"));
compound.setTag("Variant", new NBTInt(variant.ordinal()));
return compound;
};
int shoulderIndex = skinLayersIndex+2;
register(new NBTProperty<>("shoulder_entity_left", ParrotVariant.class, shoulderIndex++, parrotVariantDecoder));
register(new NBTProperty<>("shoulder_entity_right", ParrotVariant.class, shoulderIndex, parrotVariantDecoder));
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_13)) return;
// Pufferfish
int pufferfishIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) pufferfishIndex = 17;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) pufferfishIndex = 16;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) pufferfishIndex = 15;
else pufferfishIndex = 13;
register(new EncodedIntegerProperty<>("puff_state", PuffState.DEFLATED, pufferfishIndex, Enum::ordinal));
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_14)) return; if (!ver.isNewerThanOrEquals(ServerVersion.V_1_14)) return;
// Pose // Pose
register(new NpcPoseProperty()); register(new NpcPoseProperty());
@ -369,6 +416,32 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
register(new BitsetProperty("fox_sleeping", foxIndex, 0x20)); register(new BitsetProperty("fox_sleeping", foxIndex, 0x20));
linkProperties("fox_sitting", "fox_crouching", "fox_sleeping"); linkProperties("fox_sitting", "fox_crouching", "fox_sleeping");
int mooshroomIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) mooshroomIndex = 17;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) mooshroomIndex = 16;
else mooshroomIndex = 15;
register(new EncodedStringProperty<>("mooshroom_variant", MooshroomVariant.RED, mooshroomIndex, MooshroomVariant::getVariantName));
// Panda
int pandaIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) pandaIndex = 20;
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) pandaIndex = 19;
else pandaIndex = 18;
register(new EncodedByteProperty<>("panda_main_gene", PandaGene.NORMAL, pandaIndex++, obj -> (byte) obj.ordinal()));
register(new EncodedByteProperty<>("panda_hidden_gene", PandaGene.NORMAL, pandaIndex++, obj -> (byte) obj.ordinal()));
if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) {
register(new BitsetProperty("panda_sneezing", pandaIndex, 0x02));
register(new BitsetProperty("panda_rolling", pandaIndex, 0x04));
register(new BitsetProperty("panda_sitting", pandaIndex, 0x08));
register(new BitsetProperty("panda_on_back", pandaIndex, 0x10));
linkProperties("panda_sneezing", "panda_rolling", "panda_sitting", "panda_on_back");
} else {
register(new BitsetProperty("panda_sneezing", pandaIndex, 0x02));
register(new BitsetProperty("panda_eating", pandaIndex, 0x04));
linkProperties("panda_sneezing", "panda_eating");
}
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_15)) return; if (!ver.isNewerThanOrEquals(ServerVersion.V_1_15)) return;
register(new BitsetProperty("fox_faceplanted", foxIndex, 0x40)); register(new BitsetProperty("fox_faceplanted", foxIndex, 0x40));
@ -383,10 +456,26 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_16)) return; if (!ver.isNewerThanOrEquals(ServerVersion.V_1_16)) return;
// Hoglin and Piglin Zombification
final int zombificationIndex; final int zombificationIndex;
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) zombificationIndex = 17; if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) zombificationIndex = 17; // Change piglinIndex and pillagerIndex if you change this
else zombificationIndex = 16; else zombificationIndex = 16;
register(new BooleanProperty("immune_to_zombification", zombificationIndex, false, legacyBooleans)); register(new BooleanProperty("hoglin_immune_to_zombification", zombificationIndex, false, legacyBooleans));
register(new BooleanProperty("piglin_immune_to_zombification", zombificationIndex-1, false, legacyBooleans));
// Piglin
int piglinIndex = zombificationIndex;
register(new BooleanProperty("piglin_baby", piglinIndex++, false, legacyBooleans));
register(new BooleanProperty("piglin_charging_crossbow", piglinIndex++, false, legacyBooleans));
register(new BooleanProperty("piglin_dancing", piglinIndex, false, legacyBooleans));
// Pillager
int pillagerIndex = zombificationIndex;
register(new BooleanProperty("pillager_charging", pillagerIndex, false, legacyBooleans));
// Vindicator
int vindicatorIndex = pillagerIndex-1;
register(new BooleanProperty("celebrating", vindicatorIndex, false, legacyBooleans));
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_17)) return; if (!ver.isNewerThanOrEquals(ServerVersion.V_1_17)) return;
// Axolotl // Axolotl
@ -398,6 +487,9 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
register(new BooleanProperty("has_right_horn", 19, true, legacyBooleans)); register(new BooleanProperty("has_right_horn", 19, true, legacyBooleans));
register(new EncodedIntegerProperty<>("shaking", false,7, enabled -> enabled ? 140 : 0)); register(new EncodedIntegerProperty<>("shaking", false,7, enabled -> enabled ? 140 : 0));
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_19)) return;
// Frog
register(new EncodedIntegerProperty<>("frog_variant", FrogVariant.TEMPERATE, 17, Enum::ordinal, EntityDataTypes.FROG_VARIANT));
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_20)) return; if (!ver.isNewerThanOrEquals(ServerVersion.V_1_20)) return;

View file

@ -15,7 +15,11 @@ public class EnumPropertySerializer<T extends Enum<T>> implements PropertySerial
@Override @Override
public T deserialize(String property) { public T deserialize(String property) {
return Enum.valueOf(enumClass, property.toUpperCase()); try {
return Enum.valueOf(enumClass, property.toUpperCase());
} catch (IllegalArgumentException e) {
return null;
}
} }
@Override @Override

View file

@ -0,0 +1,48 @@
package lol.pyr.znpcsplus.entity.properties;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import org.bukkit.entity.Player;
import java.util.Map;
public class EncodedStringProperty<T> extends EntityPropertyImpl<T> {
private final EntityDataType<String> type;
private final EncodedStringProperty.StringDecoder<T> decoder;
private final int index;
public EncodedStringProperty(String name, T defaultValue, Class<T> clazz, int index, StringDecoder<T> decoder, EntityDataType<String> type) {
super(name, defaultValue, clazz);
this.decoder = decoder;
this.index = index;
this.type = type;
}
@SuppressWarnings("unchecked")
public EncodedStringProperty(String name, T defaultValue, int index, StringDecoder<T> decoder) {
this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, EntityDataTypes.STRING);
}
@SuppressWarnings("unchecked")
public EncodedStringProperty(String name, T defaultValue, int index, StringDecoder<T> decoder, EntityDataType<String> type) {
this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, type);
}
public EncodedStringProperty(String name, Class<T> clazz, int index, StringDecoder<T> decoder) {
this(name, null, clazz, index, decoder, EntityDataTypes.STRING);
}
@Override
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
T value = entity.getProperty(this);
if (value == null) return;
properties.put(index, newEntityData(index, type, decoder.decode(value)));
}
public interface StringDecoder<T> {
String decode(T obj);
}
}

View file

@ -10,14 +10,22 @@ import java.util.Map;
public class IntegerProperty extends EntityPropertyImpl<Integer> { public class IntegerProperty extends EntityPropertyImpl<Integer> {
private final int index; private final int index;
private final boolean legacy;
protected IntegerProperty(String name, int index, Integer defaultValue) { public IntegerProperty(String name, int index, Integer defaultValue) {
this(name, index, defaultValue, false);
}
public IntegerProperty(String name, int index, Integer defaultValue, boolean legacy) {
super(name, defaultValue, Integer.class); super(name, defaultValue, Integer.class);
this.index = index; this.index = index;
this.legacy = legacy;
} }
@Override @Override
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) { public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
properties.put(index, newEntityData(index, EntityDataTypes.INT, entity.getProperty(this))); properties.put(index, legacy ?
newEntityData(index, EntityDataTypes.BYTE, (byte) entity.getProperty(this).intValue()) :
newEntityData(index, EntityDataTypes.INT, entity.getProperty(this)));
} }
} }

View file

@ -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.EntityDataType;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import org.bukkit.entity.Player;
import java.util.Map;
public class NBTProperty<T> extends EntityPropertyImpl<T> {
private final EntityDataType<NBTCompound> type;
private final NBTDecoder<T> decoder;
private final int index;
public NBTProperty(String name, T defaultValue, Class<T> clazz, int index, NBTDecoder<T> decoder, EntityDataType<NBTCompound> type) {
super(name, defaultValue, clazz);
this.decoder = decoder;
this.index = index;
this.type = type;
}
@SuppressWarnings("unchecked")
public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder) {
this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, EntityDataTypes.NBT);
}
@SuppressWarnings("unchecked")
public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder, EntityDataType<NBTCompound> type) {
this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, type);
}
public NBTProperty(String name, Class<T> clazz, int index, NBTDecoder<T> decoder) {
this(name, null, clazz, index, decoder, EntityDataTypes.NBT);
}
@Override
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
T value = entity.getProperty(this);
if (value == null) return;
properties.put(index, newEntityData(index, type, decoder.decode(value)));
}
public interface NBTDecoder<T> {
NBTCompound decode(T obj);
}
}

View file

@ -5,6 +5,7 @@ import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl; import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.util.PapiUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -29,6 +30,7 @@ public class NameProperty extends EntityPropertyImpl<Component> {
String serialized = legacy ? String serialized = legacy ?
AdventureSerializer.getLegacyGsonSerializer().serialize(value) : AdventureSerializer.getLegacyGsonSerializer().serialize(value) :
AdventureSerializer.getGsonSerializer().serialize(value); AdventureSerializer.getGsonSerializer().serialize(value);
serialized = PapiUtil.set(player, serialized);
if (optional) properties.put(2, newEntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.of(serialized))); if (optional) properties.put(2, newEntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.of(serialized)));
else properties.put(2, newEntityData(2, EntityDataTypes.STRING, serialized)); else properties.put(2, newEntityData(2, EntityDataTypes.STRING, serialized));
} }

View file

@ -0,0 +1,29 @@
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.npc.NpcEntryImpl;
import org.bukkit.entity.Player;
import java.util.Map;
public class TargetNpcProperty extends EntityPropertyImpl<NpcEntryImpl> {
private final int index;
public TargetNpcProperty(String name, int index, NpcEntryImpl defaultValue) {
super(name, defaultValue, NpcEntryImpl.class);
this.index = index;
}
@Override
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
NpcEntryImpl value = entity.getProperty(this);
if (value == null) return;
if (value.getNpc().getEntity().getEntityId() == entity.getEntityId()) return;
if (value.getNpc().isVisibleTo(player)) {
properties.put(index, newEntityData(index, EntityDataTypes.INT, value.getNpc().getEntity().getEntityId()));
}
}
}

View file

@ -0,0 +1,25 @@
package lol.pyr.znpcsplus.entity.serializers;
import lol.pyr.znpcsplus.entity.PropertySerializer;
public class IntegerPropertySerializer implements PropertySerializer<Integer> {
@Override
public String serialize(Integer property) {
return String.valueOf(property);
}
@Override
public Integer deserialize(String property) {
try {
return Integer.parseInt(property);
} catch (NumberFormatException e) {
e.printStackTrace();
}
return null;
}
@Override
public Class<Integer> getTypeClass() {
return Integer.class;
}
}

View file

@ -0,0 +1,21 @@
package lol.pyr.znpcsplus.entity.serializers;
import lol.pyr.znpcsplus.entity.PropertySerializer;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
public class TargetNpcPropertySerializer implements PropertySerializer<NpcEntryImpl> {
@Override
public String serialize(NpcEntryImpl property) {
return property.getId();
}
@Override
public NpcEntryImpl deserialize(String property) {
return null; // TODO: find a way to do this
}
@Override
public Class<NpcEntryImpl> getTypeClass() {
return NpcEntryImpl.class;
}
}

View file

@ -110,6 +110,7 @@ public class NpcTypeImpl implements NpcType {
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
addProperties("fire", "invisible", "silent", "look", addProperties("fire", "invisible", "silent", "look",
"potion_color", "potion_ambient", "dinnerbone"); "potion_color", "potion_ambient", "dinnerbone");
// 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_9)) addProperties("glow");
if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) { if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) {
addProperties("pose"); addProperties("pose");
@ -118,7 +119,7 @@ public class NpcTypeImpl implements NpcType {
} }
} }
if (version.isNewerThanOrEquals(ServerVersion.V_1_17)) addProperties("shaking"); if (version.isNewerThanOrEquals(ServerVersion.V_1_17)) addProperties("shaking");
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_AGEABLE)) { if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_AGEABLE) || EntityTypes.isTypeInstanceOf(type, EntityTypes.ZOMBIE) || EntityTypes.isTypeInstanceOf(type, EntityTypes.ZOGLIN)) {
addProperties("baby"); addProperties("baby");
} }
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_HORSE)) { if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_HORSE)) {
@ -129,6 +130,27 @@ public class NpcTypeImpl implements NpcType {
} else if (version.isOlderThan(ServerVersion.V_1_11) && type.equals(EntityTypes.HORSE)) { } else if (version.isOlderThan(ServerVersion.V_1_11) && type.equals(EntityTypes.HORSE)) {
addProperties("has_chest"); addProperties("has_chest");
} }
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_EVO_ILLU_ILLAGER)) {
addProperties("spell");
}
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_PIGLIN)) {
addProperties("piglin_immune_to_zombification");
}
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.SLIME) || EntityTypes.isTypeInstanceOf(type, EntityTypes.PHANTOM)) {
addProperties("size");
}
if (version.isOlderThan(ServerVersion.V_1_14)) {
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.OCELOT)) {
addProperties("ocelot_type");
}
}
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.PANDA)) {
if (version.isNewerThanOrEquals(ServerVersion.V_1_15)) {
addProperties("panda_rolling", "panda_sitting", "panda_on_back");
} else {
addProperties("panda_eating");
}
}
return new NpcTypeImpl(name, type, hologramOffset, new HashSet<>(allowedProperties), defaultProperties); return new NpcTypeImpl(name, type, hologramOffset, new HashSet<>(allowedProperties), defaultProperties);
} }
} }

View file

@ -104,13 +104,15 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
register(builder(p, "magma_cube", EntityTypes.MAGMA_CUBE)); // TODO: Hologram offset scaling with size property register(builder(p, "magma_cube", EntityTypes.MAGMA_CUBE)); // TODO: Hologram offset scaling with size property
register(builder(p, "mooshroom", EntityTypes.MOOSHROOM) register(builder(p, "mooshroom", EntityTypes.MOOSHROOM)
.setHologramOffset(-0.575)); .setHologramOffset(-0.575)
.addProperties("mooshroom_variant"));
register(builder(p, "ocelot", EntityTypes.OCELOT) register(builder(p, "ocelot", EntityTypes.OCELOT)
.setHologramOffset(-1.275)); .setHologramOffset(-1.275));
register(builder(p, "pig", EntityTypes.PIG) register(builder(p, "pig", EntityTypes.PIG)
.setHologramOffset(-1.075)); .setHologramOffset(-1.075)
.addProperties("pig_saddled"));
register(builder(p, "rabbit", EntityTypes.RABBIT) register(builder(p, "rabbit", EntityTypes.RABBIT)
.setHologramOffset(-1.475)); .setHologramOffset(-1.475));
@ -173,7 +175,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
if (!version.isNewerThanOrEquals(ServerVersion.V_1_10)) return; if (!version.isNewerThanOrEquals(ServerVersion.V_1_10)) return;
register(builder(p, "polar_bear", EntityTypes.POLAR_BEAR) register(builder(p, "polar_bear", EntityTypes.POLAR_BEAR)
.setHologramOffset(-0.575)); .setHologramOffset(-0.575)
.addProperties("polar_bear_standing"));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_11)) return; if (!version.isNewerThanOrEquals(ServerVersion.V_1_11)) return;
@ -202,14 +205,16 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
.addProperties("evoker_spell")); .addProperties("evoker_spell"));
register(builder(p, "llama", EntityTypes.LLAMA) register(builder(p, "llama", EntityTypes.LLAMA)
.setHologramOffset(-0.105)); .setHologramOffset(-0.105)
.addProperties("carpet_color", "llama_variant"));
register(builder(p, "vex", EntityTypes.VEX) register(builder(p, "vex", EntityTypes.VEX)
.setHologramOffset(-1.175) .setHologramOffset(-1.175)
.addHandProperties()); .addHandProperties());
register(builder(p, "vindicator", EntityTypes.VINDICATOR) register(builder(p, "vindicator", EntityTypes.VINDICATOR)
.setHologramOffset(-0.025)); .setHologramOffset(-0.025)
.addProperties("celebrating"));
register(builder(p, "wither_skeleton", EntityTypes.WITHER_SKELETON) register(builder(p, "wither_skeleton", EntityTypes.WITHER_SKELETON)
.setHologramOffset(0.425) .setHologramOffset(0.425)
@ -225,7 +230,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
.setHologramOffset(-0.025)); .setHologramOffset(-0.025));
register(builder(p, "parrot", EntityTypes.PARROT) register(builder(p, "parrot", EntityTypes.PARROT)
.setHologramOffset(-1.075)); .setHologramOffset(-1.075)
.addProperties("parrot_variant"));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_13)) return; if (!version.isNewerThanOrEquals(ServerVersion.V_1_13)) return;
@ -244,7 +250,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
.setHologramOffset(-1.475)); .setHologramOffset(-1.475));
register(builder(p, "pufferfish", EntityTypes.PUFFERFISH) register(builder(p, "pufferfish", EntityTypes.PUFFERFISH)
.setHologramOffset(-1.625)); .setHologramOffset(-1.625)
.addProperties("puff_state"));
register(builder(p, "salmon", EntityTypes.SALMON) register(builder(p, "salmon", EntityTypes.SALMON)
.setHologramOffset(-1.575)); .setHologramOffset(-1.575));
@ -266,17 +273,20 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
.addProperties("hand", "fox_variant", "fox_sitting", "fox_crouching", "fox_sleeping", "fox_faceplanted")); .addProperties("hand", "fox_variant", "fox_sitting", "fox_crouching", "fox_sleeping", "fox_faceplanted"));
register(builder(p, "panda", EntityTypes.PANDA) register(builder(p, "panda", EntityTypes.PANDA)
.setHologramOffset(-0.725)); .setHologramOffset(-0.725)
.addProperties("panda_main_gene", "panda_hidden_gene", "panda_sneezing"));
register(builder(p, "pillager", EntityTypes.PILLAGER) register(builder(p, "pillager", EntityTypes.PILLAGER)
.setHologramOffset(-0.025) .setHologramOffset(-0.025)
.addHandProperties()); .addHandProperties()
.addProperties("pillager_charging"));
register(builder(p, "ravager", EntityTypes.RAVAGER) register(builder(p, "ravager", EntityTypes.RAVAGER)
.setHologramOffset(0.225)); .setHologramOffset(0.225));
register(builder(p, "trader_llama", EntityTypes.TRADER_LLAMA) register(builder(p, "trader_llama", EntityTypes.TRADER_LLAMA)
.setHologramOffset(-0.105)); .setHologramOffset(-0.105)
.addProperties("llama_variant"));
register(builder(p, "wandering_trader", EntityTypes.WANDERING_TRADER) register(builder(p, "wandering_trader", EntityTypes.WANDERING_TRADER)
.setHologramOffset(-0.025) .setHologramOffset(-0.025)
@ -292,11 +302,12 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
register(builder(p, "hoglin", EntityTypes.HOGLIN) register(builder(p, "hoglin", EntityTypes.HOGLIN)
.setHologramOffset(-0.575) .setHologramOffset(-0.575)
.addProperties("immune_to_zombification")); .addProperties("hoglin_immune_to_zombification"));
register(builder(p, "piglin", EntityTypes.PIGLIN) register(builder(p, "piglin", EntityTypes.PIGLIN)
.setHologramOffset(-1.0) .setHologramOffset(-1.0)
.addEquipmentProperties()); .addEquipmentProperties()
.addProperties("piglin_baby", "piglin_charging_crossbow", "piglin_dancing"));
register(builder(p, "piglin_brute", EntityTypes.PIGLIN_BRUTE) register(builder(p, "piglin_brute", EntityTypes.PIGLIN_BRUTE)
.setHologramOffset(-0.025) .setHologramOffset(-0.025)
@ -329,7 +340,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
register(builder(p, "frog", EntityTypes.FROG) register(builder(p, "frog", EntityTypes.FROG)
.setHologramOffset(-1.475) .setHologramOffset(-1.475)
.addProperties("frog_variant")); .addProperties("frog_variant", "frog_target_npc"));
register(builder(p, "tadpole", EntityTypes.TADPOLE) register(builder(p, "tadpole", EntityTypes.TADPOLE)
.setHologramOffset(-1.675)); .setHologramOffset(-1.675));

View file

@ -70,7 +70,12 @@ public class YamlStorage implements NpcStorage {
Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + key + "' for npc '" + config.getString("id") + "'. skipping ...");
continue; continue;
} }
npc.UNSAFE_setProperty(property, serializer.deserialize(properties.getString(key))); 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(); HologramImpl hologram = npc.getHologram();
@ -108,6 +113,10 @@ public class YamlStorage implements NpcStorage {
for (EntityProperty<?> property : npc.getAppliedProperties()) { for (EntityProperty<?> property : npc.getAppliedProperties()) {
PropertySerializer<?> serializer = propertyRegistry.getSerializer(((EntityPropertyImpl<?>) property).getType()); 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))); config.set("properties." + property.getName(), serializer.UNSAFE_serialize(npc.getProperty(property)));
} }