Implemented citizen importer

This commit is contained in:
D3v1s0m 2023-08-01 19:46:29 +05:30
parent 769eed2f46
commit ca8aa4ba16
No known key found for this signature in database
GPG Key ID: FA1F770C7B1D40C1
15 changed files with 382 additions and 4 deletions

@ -1,6 +1,7 @@
package lol.pyr.znpcsplus.conversion; package lol.pyr.znpcsplus.conversion;
import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.config.ConfigManager;
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.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
@ -30,8 +31,8 @@ public class DataImporterRegistry {
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"))));
} }
private void register(String id, LazyLoader<DataImporter> loader) { private void register(String id, LazyLoader<DataImporter> loader) {

@ -1,21 +1,30 @@
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.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.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;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
import lol.pyr.znpcsplus.util.BungeeConnector; import lol.pyr.znpcsplus.util.BungeeConnector;
import lol.pyr.znpcsplus.util.NpcLocation;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.UUID;
@SuppressWarnings("FieldCanBeLocal") @SuppressWarnings("FieldCanBeLocal")
public class CitizensImporter implements DataImporter { public class CitizensImporter implements DataImporter {
@ -29,6 +38,7 @@ public class CitizensImporter implements DataImporter {
private final EntityPropertyRegistryImpl propertyRegistry; private final EntityPropertyRegistryImpl propertyRegistry;
private final MojangSkinCache skinCache; private final MojangSkinCache skinCache;
private final File dataFile; private final File dataFile;
private final CitizensTraitsRegistry traitsRegistry;
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,
@ -44,14 +54,56 @@ public class CitizensImporter implements DataImporter {
this.propertyRegistry = propertyRegistry; this.propertyRegistry = propertyRegistry;
this.skinCache = skinCache; this.skinCache = skinCache;
this.dataFile = dataFile; this.dataFile = dataFile;
this.traitsRegistry = new CitizensTraitsRegistry(typeRegistry, propertyRegistry, skinCache);
} }
@Override @Override
public Collection<NpcEntryImpl> importData() { public Collection<NpcEntryImpl> importData() {
YamlConfiguration config = YamlConfiguration.loadConfiguration(dataFile); YamlConfiguration config = YamlConfiguration.loadConfiguration(dataFile);
// TODO ConfigurationSection npcsSection = config.getConfigurationSection("npc");
// use guard clause to avoid nested if statements
if (npcsSection == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
ArrayList<NpcEntryImpl> entries = new ArrayList<>();
npcsSection.getKeys(false).forEach(key -> {
ConfigurationSection npcSection = npcsSection.getConfigurationSection(key);
if (npcSection == null) {
return;
}
String name = npcSection.getString("name", "Citizens NPC");
UUID uuid;
try {
uuid = UUID.fromString(npcSection.getString("uuid"));
} catch (IllegalArgumentException e) {
uuid = UUID.randomUUID();
}
String world = npcSection.getString("traits.location.world");
if (world == null) {
world = Bukkit.getWorlds().get(0).getName();
}
NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, world, typeRegistry.getByName("armor_stand"), new NpcLocation(0, 0, 0, 0, 0));
npc.getHologram().addLineComponent(textSerializer.deserialize(name));
ConfigurationSection traits = npcSection.getConfigurationSection("traits");
if (traits != null) {
for (String traitName : traits.getKeys(false)) {
Object trait = traits.get(traitName);
CitizensTrait citizensTrait = traitsRegistry.getByName(traitName);
if (citizensTrait != null) {
npc = citizensTrait.apply(npc, trait);
}
}
}
String id = key.toLowerCase();
while (NpcApiProvider.get().getNpcRegistry().getById(id) != null) {
id += "_";
}
NpcEntryImpl entry = new NpcEntryImpl(id, npc);
entry.enableEverything();
entries.add(entry);
});
return entries;
}
@Override @Override
public boolean isValid() { public boolean isValid() {

@ -0,0 +1,19 @@
package lol.pyr.znpcsplus.conversion.citizens.model;
import lol.pyr.znpcsplus.npc.NpcImpl;
import org.jetbrains.annotations.NotNull;
public abstract class CitizensTrait {
private final String identifier;
public CitizensTrait(String identifier) {
this.identifier = identifier;
}
public String getIdentifier() {
return identifier;
}
public abstract @NotNull NpcImpl apply(NpcImpl npc, Object value);
}

@ -0,0 +1,31 @@
package lol.pyr.znpcsplus.conversion.citizens.model;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry;
import lol.pyr.znpcsplus.conversion.citizens.model.traits.*;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
import java.util.HashMap;
public class CitizensTraitsRegistry {
private final HashMap<String, CitizensTrait> traitMap = new HashMap<>();
public CitizensTraitsRegistry(NpcTypeRegistry typeRegistry, EntityPropertyRegistry propertyRegistry, MojangSkinCache skinCache) {
register(new LocationTrait());
register(new TypeTrait(typeRegistry));
register(new ProfessionTrait(propertyRegistry));
register(new VillagerTrait(propertyRegistry));
register(new SkinTrait(propertyRegistry));
register(new MirrorTrait(propertyRegistry, skinCache));
register(new SkinLayersTrait(propertyRegistry));
register(new LookTrait(propertyRegistry));
}
public CitizensTrait getByName(String name) {
return traitMap.get(name);
}
public void register(CitizensTrait trait) {
traitMap.put(trait.getIdentifier(), trait);
}
}

@ -0,0 +1,19 @@
package lol.pyr.znpcsplus.conversion.citizens.model;
import lol.pyr.znpcsplus.npc.NpcImpl;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public abstract class SectionCitizensTrait extends CitizensTrait {
public SectionCitizensTrait(String identifier) {
super(identifier);
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, Object value) {
if (!(value instanceof ConfigurationSection)) return npc;
return apply(npc, (ConfigurationSection) value);
}
public abstract @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section);
}

@ -0,0 +1,18 @@
package lol.pyr.znpcsplus.conversion.citizens.model;
import lol.pyr.znpcsplus.npc.NpcImpl;
import org.jetbrains.annotations.NotNull;
public abstract class StringCitizensTrait extends CitizensTrait {
public StringCitizensTrait(String identifier) {
super(identifier);
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, Object value) {
if (!(value instanceof String)) return npc;
return apply(npc, (String) value);
}
public abstract @NotNull NpcImpl apply(NpcImpl npc, String string);
}

@ -0,0 +1,25 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.util.NpcLocation;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class LocationTrait extends SectionCitizensTrait {
public LocationTrait() {
super("location");
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
double x = Double.parseDouble(section.getString("x"));
double y = Double.parseDouble(section.getString("y"));
double z = Double.parseDouble(section.getString("z"));
float yaw = Float.parseFloat(section.getString("yaw"));
float pitch = Float.parseFloat(section.getString("pitch"));
NpcLocation location = new NpcLocation(x, y, z, yaw, pitch);
npc.setLocation(location);
return npc;
}
}

@ -0,0 +1,22 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class LookTrait extends SectionCitizensTrait {
private final EntityPropertyRegistry registry;
public LookTrait(EntityPropertyRegistry registry) {
super("lookclose");
this.registry = registry;
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
if (section.getBoolean("enabled")) npc.setProperty(registry.getByName("look", Boolean.class), true);
return npc;
}
}

@ -0,0 +1,27 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class MirrorTrait extends SectionCitizensTrait {
private final EntityPropertyRegistry registry;
private final MojangSkinCache skinCache;
public MirrorTrait(EntityPropertyRegistry registry, MojangSkinCache skinCache) {
super("mirrortrait");
this.registry = registry;
this.skinCache = skinCache;
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
if (section.getBoolean("enabled")) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new MirrorDescriptor(skinCache));
return npc;
}
}

@ -0,0 +1,28 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.conversion.citizens.model.StringCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.util.VillagerProfession;
import org.jetbrains.annotations.NotNull;
public class ProfessionTrait extends StringCitizensTrait {
private final EntityPropertyRegistry registry;
public ProfessionTrait(EntityPropertyRegistry registry) {
super("profession");
this.registry = registry;
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, String string) {
VillagerProfession profession;
try {
profession = VillagerProfession.valueOf(string.toUpperCase());
} catch (IllegalArgumentException ignored) {
profession = VillagerProfession.NONE;
}
npc.setProperty(registry.getByName("villager_profession", VillagerProfession.class), profession);
return npc;
}
}

@ -0,0 +1,38 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class SkinLayersTrait extends SectionCitizensTrait {
private final EntityPropertyRegistry registry;
private final Map<String, String> skinLayers;
public SkinLayersTrait(EntityPropertyRegistry registry) {
super("skinlayers");
this.registry = registry;
this.skinLayers = new HashMap<>();
this.skinLayers.put("cape", "skin_cape");
this.skinLayers.put("hat", "skin_hat");
this.skinLayers.put("jacket", "skin_jacket");
this.skinLayers.put("left_sleeve", "skin_left_sleeve");
this.skinLayers.put("left_pants", "skin_left_leg");
this.skinLayers.put("right_sleeve", "skin_right_sleeve");
this.skinLayers.put("right_pants", "skin_right_leg");
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
for (Map.Entry<String, String> entry : this.skinLayers.entrySet()) {
String key = entry.getKey();
String property = entry.getValue();
if (section.contains(key)) npc.setProperty(registry.getByName(property, Boolean.class), section.getBoolean(key));
}
return npc;
}
}

@ -0,0 +1,27 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.skin.Skin;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class SkinTrait extends SectionCitizensTrait {
private final EntityPropertyRegistry registry;
public SkinTrait(EntityPropertyRegistry registry) {
super("skintrait");
this.registry = registry;
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
String texture = section.getString("textureRaw");
String signature = section.getString("signature");
if (texture != null && signature != null) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new Skin(texture, signature)));
return npc;
}
}

@ -0,0 +1,31 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry;
import lol.pyr.znpcsplus.conversion.citizens.model.StringCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcTypeImpl;
import org.jetbrains.annotations.NotNull;
public class TypeTrait extends StringCitizensTrait {
private final NpcTypeRegistry registry;
public TypeTrait(NpcTypeRegistry registry) {
super("type");
this.registry = registry;
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, String string) {
NpcTypeImpl type = warpNpcType(string);
if (type == null) return npc;
npc.setType(type);
return npc;
}
private NpcTypeImpl warpNpcType(String name) {
name = name.toLowerCase();
// if (name.equals("player")) name = "human";
// else if (name.equals("zombievillager")) name = "zombie_villager";
return (NpcTypeImpl) registry.getByName(name);
}
}

@ -0,0 +1,39 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.util.VillagerLevel;
import lol.pyr.znpcsplus.util.VillagerType;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class VillagerTrait extends SectionCitizensTrait {
private final EntityPropertyRegistry registry;
public VillagerTrait(EntityPropertyRegistry registry) {
super("villagertrait");
this.registry = registry;
}
@Override
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
int level = section.getInt("level");
String type = section.getString("type", "plains");
VillagerLevel villagerLevel;
try {
villagerLevel = VillagerLevel.values()[level];
} catch (ArrayIndexOutOfBoundsException ignored) {
villagerLevel = VillagerLevel.STONE;
}
VillagerType villagerType;
try {
villagerType = VillagerType.valueOf(type.toUpperCase());
} catch (IllegalArgumentException ignored) {
villagerType = VillagerType.PLAINS;
}
npc.setProperty(registry.getByName("villager_level", VillagerLevel.class), villagerLevel);
npc.setProperty(registry.getByName("villager_type", VillagerType.class), villagerType);
return npc;
}
}

@ -142,6 +142,7 @@ public class NpcImpl extends Viewable implements Npc {
} }
public <T> void setProperty(EntityPropertyImpl<T> key, T value) { public <T> void setProperty(EntityPropertyImpl<T> key, T value) {
if (key == null) return;
if (value == null || value.equals(key.getDefaultValue())) propertyMap.remove(key); if (value == null || value.equals(key.getDefaultValue())) propertyMap.remove(key);
else propertyMap.put(key, value); else propertyMap.put(key, value);
UNSAFE_refreshProperty(key); UNSAFE_refreshProperty(key);