Delete old template code

This commit is contained in:
fullwall 2024-03-04 20:46:36 +08:00
parent 249fa6675d
commit 903ba91b4c
9 changed files with 83 additions and 301 deletions

View File

@ -52,9 +52,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCDataStore;
import net.citizensnpcs.api.npc.NPCRegistry;
import net.citizensnpcs.api.npc.SimpleNPCDataStore;
import net.citizensnpcs.api.scripting.EventRegistrar;
import net.citizensnpcs.api.scripting.ObjectProvider;
import net.citizensnpcs.api.scripting.ScriptCompiler;
import net.citizensnpcs.api.npc.templates.TemplateRegistry;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitFactory;
import net.citizensnpcs.api.trait.TraitInfo;
@ -74,10 +72,10 @@ import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.npc.CitizensNPCRegistry;
import net.citizensnpcs.npc.CitizensTraitFactory;
import net.citizensnpcs.npc.NPCSelector;
import net.citizensnpcs.npc.Template;
import net.citizensnpcs.npc.profile.ProfileFetcher;
import net.citizensnpcs.npc.skin.Skin;
import net.citizensnpcs.trait.ShopTrait;
import net.citizensnpcs.trait.shop.StoredShops;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.PlayerUpdateTask;
@ -149,6 +147,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
private NPCSelector selector;
private StoredShops shops;
private final Map<String, NPCRegistry> storedRegistries = Maps.newHashMap();
private TemplateRegistry templateRegistry;
private CitizensTraitFactory traitFactory;
@Override
@ -272,6 +271,10 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
return shops;
}
public TemplateRegistry getTemplateRegistry() {
return templateRegistry;
}
@Override
public TraitFactory getTraitFactory() {
return traitFactory;
@ -346,13 +349,14 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
Editor.leaveAll();
despawnNPCs(saveOnDisable);
HandlerList.unregisterAll(this);
templateRegistry = null;
npcRegistry = null;
locationLookup = null;
enabled = false;
saveOnDisable = true;
ProfileFetcher.shutdown();
Skin.clearCache();
Template.shutdown();
NMS.shutdown();
CitizensAPI.shutdown();
}
@ -378,8 +382,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
registerScriptHelpers();
saves = createStorage(getDataFolder());
shops = new StoredShops(new YamlStorage(new File(getDataFolder(), "shops.yml")));
if (saves == null || !shops.loadFromDisk()) {
@ -394,6 +396,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
traitFactory = new CitizensTraitFactory(this);
traitFactory.registerTrait(TraitInfo.create(ShopTrait.class).withSupplier(() -> new ShopTrait(shops)));
selector = new NPCSelector(this);
templateRegistry = new TemplateRegistry(new File(this.getDataFolder(), "templates").toPath());
Bukkit.getPluginManager().registerEvents(new EventListen(), this);
Bukkit.getPluginManager().registerEvents(new Placeholders(), this);
@ -406,7 +409,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
registerCommands();
NMS.load(commands);
Template.migrate();
Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
commands.registerTabCompletion(this);
commands.setTranslationPrefixProvider(cmd -> "citizens.commands." + cmd.aliases()[0]
@ -446,12 +448,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
commands.register(WaypointCommands.class);
}
private void registerScriptHelpers() {
ScriptCompiler compiler = CitizensAPI.getScriptCompiler();
compiler.registerGlobalContextProvider(new EventRegistrar(this));
compiler.registerGlobalContextProvider(new ObjectProvider("plugin", this));
}
public void reload() throws NPCLoadException {
Editor.leaveAll();
config.reload();
@ -461,14 +457,14 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
getServer().getPluginManager().callEvent(new CitizensPreReloadEvent());
templateRegistry = new TemplateRegistry(new File(this.getDataFolder(), "templates").toPath());
saves.reloadFromSource();
saves.loadInto(npcRegistry);
shops.loadFromDisk();
shops.load();
Template.shutdown();
getServer().getPluginManager().callEvent(new CitizensReloadEvent());
}

View File

@ -9,6 +9,7 @@ import java.nio.file.Files;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@ -56,7 +57,6 @@ import com.google.common.io.BaseEncoding;
import net.citizensnpcs.Citizens;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.StoredShops;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.speech.SpeechContext;
import net.citizensnpcs.api.ai.tree.StatusMapper;
@ -85,6 +85,8 @@ import net.citizensnpcs.api.npc.MemoryNPCDataStore;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPC.NPCUpdate;
import net.citizensnpcs.api.npc.NPCRegistry;
import net.citizensnpcs.api.npc.templates.Template;
import net.citizensnpcs.api.npc.templates.TemplateRegistry;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.trait.Equipment;
import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot;
@ -105,7 +107,6 @@ import net.citizensnpcs.commands.history.RemoveNPCHistoryItem;
import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.npc.EntityControllers;
import net.citizensnpcs.npc.NPCSelector;
import net.citizensnpcs.npc.Template;
import net.citizensnpcs.trait.Age;
import net.citizensnpcs.trait.Anchors;
import net.citizensnpcs.trait.ArmorStandTrait;
@ -150,6 +151,7 @@ import net.citizensnpcs.trait.SlimeSize;
import net.citizensnpcs.trait.VillagerProfession;
import net.citizensnpcs.trait.WitherTrait;
import net.citizensnpcs.trait.WolfModifiers;
import net.citizensnpcs.trait.shop.StoredShops;
import net.citizensnpcs.trait.waypoint.Waypoints;
import net.citizensnpcs.util.Anchor;
import net.citizensnpcs.util.Messages;
@ -164,11 +166,13 @@ public class NPCCommands {
private final CommandHistory history;
private final NPCSelector selector;
private final StoredShops shops;
private final TemplateRegistry templateRegistry;
private final NPCRegistry temporaryRegistry;
public NPCCommands(Citizens plugin) {
selector = plugin.getNPCSelector();
shops = plugin.getShops();
templateRegistry = plugin.getTemplateRegistry();
temporaryRegistry = CitizensAPI.createCitizensBackedNPCRegistry(new MemoryNPCDataStore());
history = new CommandHistory(selector);
}
@ -840,11 +844,18 @@ public class NPCCommands {
Iterable<String> parts = Splitter.on(',').trimResults().split(templateName);
StringBuilder builder = new StringBuilder();
for (String part : parts) {
Template template = Template.byName(part);
if (template == null) {
if (part.contains(":")) {
Template template = templateRegistry.getTemplateByNamespacedKey(part);
if (template == null)
continue;
template.apply(npc);
builder.append(StringHelper.wrap(part) + ", ");
continue;
}
template.apply(npc);
Collection<Template> templates = templateRegistry.getTemplates(part);
if (templates.size() != 1)
continue;
templates.iterator().next().apply(npc);
builder.append(StringHelper.wrap(part) + ", ");
}
if (builder.length() > 0) {

View File

@ -1,101 +1,60 @@
package net.citizensnpcs.commands;
import java.io.IOException;
import java.util.List;
import java.util.Collection;
import java.util.stream.Collectors;
import org.bukkit.command.CommandSender;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.google.common.base.Joiner;
import net.citizensnpcs.Citizens;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.command.Arg;
import net.citizensnpcs.api.command.Arg.CompletionsProvider;
import net.citizensnpcs.api.command.Command;
import net.citizensnpcs.api.command.CommandContext;
import net.citizensnpcs.api.command.CommandMessages;
import net.citizensnpcs.api.command.Requirements;
import net.citizensnpcs.api.command.exception.CommandException;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.templates.Template;
import net.citizensnpcs.api.npc.templates.TemplateRegistry;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.Template;
import net.citizensnpcs.util.Messages;
@Requirements(selected = true, ownership = true)
public class TemplateCommands {
private final TemplateRegistry registry;
public TemplateCommands(Citizens plugin) {
this.registry = plugin.getTemplateRegistry();
}
@Command(
aliases = { "template", "tpl" },
usage = "apply [template name] (id id2...)",
usage = "apply (template namespace:)[template name]",
desc = "",
modifiers = { "apply" },
min = 2,
permission = "citizens.templates.apply")
@Requirements
public void apply(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
Template template = Template.byName(args.getString(1));
public void apply(CommandContext args, CommandSender sender, NPC npc,
@Arg(value = 1, completionsProvider = TemplateCompletions.class) String templateName)
throws CommandException {
Template template = null;
if (templateName.contains(":")) {
template = registry.getTemplateByNamespacedKey(templateName);
} else {
Collection<Template> templates = registry.getTemplates(templateName);
if (templates.isEmpty())
throw new CommandException(Messages.TEMPLATE_MISSING);
if (templates.size() > 1)
throw new CommandException(Messages.TEMPLATE_PICKER, templateName, Joiner.on(", ").join(templates
.stream().map(t -> t.getNamespace() + ":" + t.getName()).collect(Collectors.toList())));
template = templates.iterator().next();
}
if (template == null)
throw new CommandException(Messages.TEMPLATE_MISSING);
int appliedCount = 0;
if (args.argsLength() == 2) {
if (npc == null)
throw new CommandException(Messaging.tr(CommandMessages.MUST_HAVE_SELECTED));
template.apply(npc);
appliedCount++;
} else {
String joined = args.getJoinedStrings(2, ',');
List<Integer> ids = Lists.newArrayList();
for (String id : Splitter.on(',').trimResults().split(joined)) {
ids.add(Ints.tryParse(id));
}
Iterable<NPC> transformed = Iterables.transform(ids, id -> CitizensAPI.getNPCRegistry().getById(id));
for (NPC toApply : transformed) {
template.apply(toApply);
appliedCount++;
}
}
Messaging.sendTr(sender, Messages.TEMPLATE_APPLIED, appliedCount);
}
@Command(
aliases = { "template", "tpl" },
usage = "create [template name] (-k)",
desc = "",
modifiers = { "create" },
min = 2,
max = 2,
flags = "o",
permission = "citizens.templates.create")
public void create(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
String name = args.getString(1);
if (Template.byName(name) != null)
throw new CommandException(Messages.TEMPLATE_CONFLICT);
try {
Template.Builder.create(name).from(npc).override(!args.hasFlag('k')).buildAndSave();
Messaging.sendTr(sender, Messages.TEMPLATE_CREATED);
} catch (IOException e) {
Messaging.sendError(sender, "Invalid template filename");
}
}
@Command(
aliases = { "template", "tpl" },
usage = "delete [template name]",
desc = "",
modifiers = { "delete" },
min = 2,
max = 2,
permission = "citizens.templates.delete")
public void delete(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
String name = args.getString(1);
if (Template.byName(name) == null)
throw new CommandException(Messages.TEMPLATE_MISSING);
Template.byName(name).delete();
Messaging.sendTr(sender, Messages.TEMPLATE_DELETED, name);
template.apply(npc);
Messaging.sendTr(sender, Messages.TEMPLATE_APPLIED, template.getName(), npc.getName());
}
@Command(
@ -108,8 +67,22 @@ public class TemplateCommands {
permission = "citizens.templates.list")
public void list(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
Messaging.sendTr(sender, Messages.TEMPLATE_LIST_HEADER);
for (Template template : Template.getTemplates()) {
Messaging.send(sender, "[[-]] " + template.getName());
for (Template template : registry.getAllTemplates()) {
Messaging.send(sender, "[[-]] " + template.getNamespace() + ":" + template.getName());
}
}
public static class TemplateCompletions implements CompletionsProvider {
private final TemplateRegistry templateRegistry;
public TemplateCompletions(Citizens plugin) {
templateRegistry = plugin.getTemplateRegistry();
}
@Override
public Collection<String> getCompletions(CommandContext args, CommandSender sender, NPC npc) {
return templateRegistry.getAllTemplates().stream().map(t -> t.getNamespace() + ":" + t.getName())
.collect(Collectors.toList());
}
}
}

View File

@ -1,191 +0,0 @@
package net.citizensnpcs.npc;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.event.DespawnReason;
import net.citizensnpcs.api.event.SpawnReason;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.MemoryDataKey;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.YamlStorage;
import net.citizensnpcs.api.util.YamlStorage.YamlKey;
public class Template {
private final String name;
private final boolean override;
private final Map<String, Object> replacements;
private Template(String name, Map<String, Object> replacements, boolean override) {
this.replacements = replacements;
this.override = override;
this.name = name;
}
@SuppressWarnings("unchecked")
public void apply(NPC npc) {
MemoryDataKey memoryKey = new MemoryDataKey();
boolean wasSpawned = npc.isSpawned();
if (wasSpawned) {
npc.despawn(DespawnReason.PENDING_RESPAWN);
}
npc.save(memoryKey);
List<Node> queue = Lists.newArrayList(new Node("", replacements));
for (int i = 0; i < queue.size(); i++) {
Node node = queue.get(i);
for (Entry<String, Object> entry : node.map.entrySet()) {
String fullKey = node.headKey.isEmpty() ? entry.getKey() : node.headKey + '.' + entry.getKey();
if (entry.getValue() instanceof Map<?, ?>) {
queue.add(new Node(fullKey, (Map<String, Object>) entry.getValue()));
continue;
}
boolean overwrite = memoryKey.keyExists(fullKey) || override;
if (!overwrite || fullKey.equals("uuid")) {
continue;
}
memoryKey.setRaw(fullKey, entry.getValue());
}
}
npc.load(memoryKey);
if (wasSpawned && npc.getStoredLocation() != null) {
npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN);
}
}
public void delete() {
new File(getDirectory(), name + ".yml").delete();
}
public String getName() {
return name;
}
public void save() throws IOException {
File file = new File(getDirectory(), name + ".yml");
if (!file.getParentFile().equals(getDirectory()))
throw new IOException();
try {
file.createNewFile();
} catch (IOException e) {
throw e;
}
YamlStorage storage = new YamlStorage(file);
DataKey root = storage.getKey("");
root.setBoolean("override", override);
root.setRaw("replacements", replacements);
storage.save();
}
public static class Builder {
private final String name;
private boolean override = true;
private final Map<String, Object> replacements = Maps.newHashMap();
private Builder(String name) {
this.name = name;
}
public Template buildAndSave() throws IOException {
Template tpl = new Template(name, replacements, override);
tpl.save();
return tpl;
}
public Builder from(NPC npc) {
replacements.clear();
MemoryDataKey key = new MemoryDataKey();
((CitizensNPC) npc).save(key);
replacements.putAll(key.getValuesDeep());
return this;
}
public Builder override(boolean override) {
this.override = override;
return this;
}
public static Builder create(String name) {
return new Builder(name);
}
}
private static class Node {
String headKey;
Map<String, Object> map;
private Node(String headKey, Map<String, Object> map) {
this.headKey = headKey;
this.map = map;
}
}
public static Template byName(String name) {
if (TEMPLATES.containsKey(name))
return TEMPLATES.get(name);
File file = new File(getDirectory(), name + ".yml");
if (!file.exists() || !file.getParentFile().equals(getDirectory()))
return null;
YamlStorage storage = new YamlStorage(file);
storage.load();
YamlKey key = storage.getKey("");
boolean override = key.getBoolean("override", true);
Map<String, Object> replacements = key.getRelative("replacements").getValuesDeep();
Template res = new Template(name, replacements, override);
TEMPLATES.put(name, res);
return res;
}
private static File getDirectory() {
return new File(CitizensAPI.getDataFolder(), "templates");
}
public static Iterable<Template> getTemplates() {
return Arrays.asList(getDirectory().list()).stream().map(f -> new File(getDirectory(), f))
.filter(f -> !f.isDirectory() && Files.getFileExtension(f.getName()).equals("yml"))
.map(f -> byName(Files.getNameWithoutExtension(f.getName()))).collect(Collectors.toList());
}
public static void migrate() {
File folder = getDirectory();
if (!folder.exists()) {
folder.mkdir();
}
File from = new File(CitizensAPI.getDataFolder(), "templates.yml");
if (from.exists()) {
YamlStorage storage = new YamlStorage(from);
storage.load();
for (DataKey key : storage.getKey("").getSubKeys()) {
String name = key.name();
Map<String, Object> replacements = key.getRelative("replacements").getValuesDeep();
boolean override = key.getBoolean("override", true);
try {
new Template(name, replacements, override).save();
} catch (IOException e) {
Messaging.severe("Unable to migrate template", name, "due to invalid filename");
}
}
try {
Files.move(from, new File(CitizensAPI.getDataFolder(), "templates_migrated.yml"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void shutdown() {
TEMPLATES.clear();
}
private static Map<String, Template> TEMPLATES = Maps.newHashMap();
}

View File

@ -35,7 +35,6 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.StoredShops;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.gui.CitizensInventoryClickEvent;
import net.citizensnpcs.api.gui.ClickHandler;
@ -70,6 +69,7 @@ import net.citizensnpcs.trait.shop.NPCShopAction;
import net.citizensnpcs.trait.shop.NPCShopAction.GUI;
import net.citizensnpcs.trait.shop.NPCShopAction.Transaction;
import net.citizensnpcs.trait.shop.PermissionAction;
import net.citizensnpcs.trait.shop.StoredShops;
import net.citizensnpcs.trait.shop.PermissionAction.PermissionActionGUI;
import net.citizensnpcs.util.InventoryMultiplexer;
import net.citizensnpcs.util.Util;

View File

@ -1,4 +1,4 @@
package net.citizensnpcs;
package net.citizensnpcs.trait.shop;
import java.util.Map;
@ -44,22 +44,18 @@ public class StoredShops {
}
public void load() {
Messaging.debug("Loading shops...", globalShops.size(), npcShops.size());
PersistenceLoader.load(this, storage.getKey(""));
}
public boolean loadFromDisk() {
Messaging.debug("Loading shops from disk...");
return storage.load();
}
public void saveToDisk() {
Messaging.debug("Saving shops to disk...");
storage.save();
}
public void storeShops() {
Messaging.debug("Saving shops...", globalShops.size(), npcShops.size());
PersistenceLoader.save(this, storage.getKey(""));
}
}

View File

@ -398,10 +398,12 @@ public class Messages {
public static final String TELEPORTED_TO_NPC = "citizens.commands.npc.tp.teleported";
public static final String TEMPLATE_APPLIED = "citizens.commands.template.applied";
public static final String TEMPLATE_CONFLICT = "citizens.commands.template.conflict";
public static final String TEMPLATE_CREATED = "citizens.commands.template.created";
public static final String TEMPLATE_DELETED = "citizens.commands.template.delete.deleted";
public static final String TEMPLATE_LIST_HEADER = "citizens.commands.template.list.header";
public static final String TEMPLATE_MISSING = "citizens.commands.template.missing";
public static final String TEMPLATE_NAMESPACE_EXISTS = "citizens.commands.template.namespace-already-exists";
public static final String TEMPLATE_PICKER = "citizens.commands.template.qualified-template-required";
public static final String TEMPLATE_SCAFFOLD_CREATED = "citizens.commands.template.scaffold.created";
public static final String TEXT_EDITOR_ADD_PROMPT = "citizens.editors.text.add-prompt";
public static final String TEXT_EDITOR_ADDED_ENTRY = "citizens.editors.text.added-entry";
public static final String TEXT_EDITOR_BEGIN = "citizens.editors.text.begin";

View File

@ -600,18 +600,14 @@
"citizens.commands.requirements.must-have-selected" : "You must have an NPC selected to execute that command.",
"citizens.commands.requirements.too-few-arguments" : "Too few arguments.",
"citizens.commands.requirements.too-many-arguments" : "Too many arguments. ",
"citizens.commands.template.applied" : "Template applied to [[{0}]] NPCs.",
"citizens.commands.template.applied" : "Applied [[{0}]] to [[{1}]].",
"citizens.commands.template.qualified-template-required" : "Duplicate template name [[{0}]]. Pick from the following options: [[{1}]].",
"citizens.commands.template.namespace-already-exists" : "Namespace [[{0}]] already exists",
"citizens.commands.template.apply.description" : "Applies a template to the selected NPC",
"citizens.commands.template.apply.help" : "",
"citizens.commands.template.conflict" : "A template by that name already exists.",
"citizens.commands.template.create.description" : "Creates a template from the selected NPC",
"citizens.commands.template.create.help" : "",
"citizens.commands.template.created" : "Template created. Check your Citizens plugin folder.",
"citizens.commands.template.delete.deleted" : "Deleted template [[{0}]].",
"citizens.commands.template.delete.description" : "Deletes a template",
"citizens.commands.template.delete.help" : "",
"citizens.commands.template.conflict" : "A template by that name already exists.",
"citizens.commands.template.list.description" : "Lists available templates",
"citizens.commands.template.list.header" : "]]Available templates[[:]]",
"citizens.commands.template.list.header" : "]]Available templates:",
"citizens.commands.template.list.help" : "",
"citizens.commands.template.missing" : "Template not found.",
"citizens.commands.trait.add.description" : "Adds traits to the NPC",

View File

@ -16,8 +16,7 @@ commands:
citizens:
description: Administration commands
permission: citizens.citizens.help
npc:
aliases: [npc2]
npc:
description: Basic commands for all NPC-related things
permission: citizens.npc.help
template: