From 812a1b1b218e772cb23188bf156852c8aa42e4c2 Mon Sep 17 00:00:00 2001 From: kento2 Date: Sat, 29 Aug 2026 19:22:55 +0200 Subject: [PATCH] configurator works so far --- buildserver/configurator/BUILD | 4 -- .../configurator/{node => }/ConfigNode.java | 8 ++- .../configurator/ConfiguratorPlugin.java | 21 ++++-- .../configurator/action/ConfigAction.java | 11 ++-- .../configurator/action/GlobalShowAction.java | 6 +- .../scrow/configurator/action/PickAction.java | 8 +-- .../configurator/command/CheckLiteral.java | 38 +++++++++++ .../configurator/command/ConfigCommand.java | 34 +++++++--- .../configurator/command/ConfigLiteral.java | 18 +++++ .../configurator/command/KeyLiteral.java | 32 ++++----- .../configurator/command/ShowLiteral.java | 36 ++++++++++ .../{ConfigApi.java => config/Config.java} | 12 +++- .../ConfigImpl.java} | 32 +++++++-- .../configurator/config/ConfigRegistry.java | 28 ++++++++ .../configurator/type/ConfigComplexType.java | 17 +++-- .../configurator/type/ConfigListType.java | 51 -------------- .../scrow/configurator/type/ConfigType.java | 11 +++- .../type/list/ConfigListType.java | 66 +++++++++++++++++++ .../configurator/type/list/ListAddAction.java | 42 ++++++++++++ .../type/list/ListDeleteAction.java | 49 ++++++++++++++ .../location/LocationPickCurrentAction.java | 3 +- .../type/location/LocationTeleportAction.java | 7 +- .../type/world/SetWorldAction.java | 6 +- core/common/BUILD | 1 + .../de/kentoj/scrowlib/utils/Serializer.java | 7 +- 25 files changed, 424 insertions(+), 124 deletions(-) rename buildserver/configurator/main/java/site/lab0x13/scrow/configurator/{node => }/ConfigNode.java (83%) create mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/CheckLiteral.java create mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigLiteral.java create mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ShowLiteral.java rename buildserver/configurator/main/java/site/lab0x13/scrow/configurator/{ConfigApi.java => config/Config.java} (68%) rename buildserver/configurator/main/java/site/lab0x13/scrow/configurator/{ConfigApiImpl.java => config/ConfigImpl.java} (70%) create mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/ConfigRegistry.java delete mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigListType.java create mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ConfigListType.java create mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListAddAction.java create mode 100644 buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListDeleteAction.java rename buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/Serializable.java => core/common/src/main/java/de/kentoj/scrowlib/utils/Serializer.java (76%) diff --git a/buildserver/configurator/BUILD b/buildserver/configurator/BUILD index 21b9853..1914f4e 100644 --- a/buildserver/configurator/BUILD +++ b/buildserver/configurator/BUILD @@ -9,12 +9,8 @@ java_binary( resource_strip_prefix = "buildserver/configurator/main/resources", deps = [ "//core/bukkit:api", - artifact("com.google.code.gson:gson"), artifact("io.papermc.paper:paper-api"), ], - add_exports = [ - artifact("com.google.code.gson:gson"), - ], ) genrule( diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/node/ConfigNode.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigNode.java similarity index 83% rename from buildserver/configurator/main/java/site/lab0x13/scrow/configurator/node/ConfigNode.java rename to buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigNode.java index 94a838a..171c8e4 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/node/ConfigNode.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigNode.java @@ -1,4 +1,4 @@ -package site.lab0x13.scrow.configurator.node; +package site.lab0x13.scrow.configurator; import org.jetbrains.annotations.Nullable; import site.lab0x13.scrow.configurator.type.ConfigType; @@ -18,6 +18,12 @@ public final class ConfigNode { reset(); } + // TODO requirements + + public boolean required() { + return defaultValue == null; + } + public void reset() { this.value(defaultValue); } diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfiguratorPlugin.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfiguratorPlugin.java index fee292e..29828b1 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfiguratorPlugin.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfiguratorPlugin.java @@ -3,16 +3,27 @@ package site.lab0x13.scrow.configurator; import de.kentoj.scrow.bukkit.ScrowAPI; import org.bukkit.plugin.java.JavaPlugin; import site.lab0x13.scrow.configurator.command.ConfigCommand; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.config.Config; +import site.lab0x13.scrow.configurator.config.ConfigImpl; +import site.lab0x13.scrow.configurator.config.ConfigRegistry; +import site.lab0x13.scrow.configurator.type.list.ConfigListType; import site.lab0x13.scrow.configurator.type.location.LocationConfigType; +import java.util.ArrayList; + public class ConfiguratorPlugin extends JavaPlugin { @Override public void onEnable() { - ConfigApi api = new ConfigApiImpl(); - var spawnLocation = new ConfigKey<>("spawnLocation", new LocationConfigType()); - api.register(spawnLocation); - ScrowAPI.commands().register(new ConfigCommand(api).rootLiteral()); + ConfigRegistry configRegistry = new ConfigRegistry(); + + Config hotPotatoConfig = new ConfigImpl(); + configRegistry.register("hot-potato", hotPotatoConfig); + var centerLocation = new ConfigKey<>("centerLocation", new LocationConfigType()); + var spawnLocations = new ConfigKey<>("spawnLocations", new ConfigListType<>(new LocationConfigType())); + hotPotatoConfig.register(centerLocation); + hotPotatoConfig.register(spawnLocations, new ArrayList<>()); + + ScrowAPI.commands().register(new ConfigCommand(configRegistry).rootLiteral()); } } \ No newline at end of file diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/ConfigAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/ConfigAction.java index d90736f..6f60a0f 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/ConfigAction.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/ConfigAction.java @@ -2,19 +2,20 @@ package site.lab0x13.scrow.configurator.action; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; import site.lab0x13.scrow.commands.model.argument.Argument; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.ConfigNode; import java.util.List; /** - * @param type of ConfigNode + * @param type of node value */ -public interface ConfigAction> { +public interface ConfigAction { + String name(); - List> arguments(); + List> arguments(ConfigNode node); boolean requiresValue(); - void execute(N node, ScrowBukkitCC ctx); + void execute(ConfigNode node, ScrowBukkitCC ctx); } diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/GlobalShowAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/GlobalShowAction.java index 2f872c6..9aa75c4 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/GlobalShowAction.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/GlobalShowAction.java @@ -7,11 +7,11 @@ import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import site.lab0x13.scrow.commands.model.argument.Argument; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.ConfigNode; import java.util.List; -public final class GlobalShowAction implements ConfigAction> { +public final class GlobalShowAction implements ConfigAction { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); @@ -21,7 +21,7 @@ public final class GlobalShowAction implements ConfigAction> } @Override - public List> arguments() { + public List> arguments(ConfigNode __) { return List.of(); } diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/PickAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/PickAction.java index 5b4cdfc..8173fba 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/PickAction.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/action/PickAction.java @@ -4,7 +4,7 @@ import site.lab0x13.scrow.commands.model.argument.Argument; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; import org.bukkit.Sound; import org.bukkit.entity.Player; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.ConfigNode; import java.util.Collections; import java.util.List; @@ -12,7 +12,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -public abstract class PickAction> implements ConfigAction { +public abstract class PickAction implements ConfigAction { protected abstract CompletableFuture pick(Player player); @@ -22,7 +22,7 @@ public abstract class PickAction> implements ConfigAc } @Override - public List> arguments() { + public List> arguments(ConfigNode __) { return Collections.emptyList(); } @@ -32,7 +32,7 @@ public abstract class PickAction> implements ConfigAc } @Override - public void execute(N node, ScrowBukkitCC ctx) { + public void execute(ConfigNode node, ScrowBukkitCC ctx) { pick(ctx.player()) .orTimeout(10, TimeUnit.MINUTES) .whenComplete((picked, ex) -> { diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/CheckLiteral.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/CheckLiteral.java new file mode 100644 index 0000000..2a6e6fb --- /dev/null +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/CheckLiteral.java @@ -0,0 +1,38 @@ +package site.lab0x13.scrow.configurator.command; + +import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; +import site.lab0x13.scrow.commands.model.literal.Literal; +import site.lab0x13.scrow.configurator.config.Config; + +import java.util.concurrent.atomic.AtomicInteger; + +final class CheckLiteral { + + private final Literal literal; + private final Config cfg; + + public CheckLiteral(Config cfg) { + this.cfg = cfg; + this.literal = Literal.builder("check") + .withSyncExecutor(this::execute) + .build(); + } + + private void execute(ScrowBukkitCC ctx) { + var badNodes = new AtomicInteger(); + cfg.allNodes().forEach((key, node) -> { + if (!node.required() || node.value() != null) return; + ctx.sender().sendMessage(ctx.style().ok("Missing value for " + key + ".")); + badNodes.getAndIncrement(); + }); + + if (badNodes.get() > 0) + ctx.sender().sendMessage(ctx.style().err("Missing " + badNodes + " values.")); + else + ctx.sender().sendMessage(ctx.style().ok("No missing values.")); + } + + public Literal literal() { + return literal; + } +} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigCommand.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigCommand.java index 3b9dfb4..28c539e 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigCommand.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigCommand.java @@ -3,19 +3,37 @@ package site.lab0x13.scrow.configurator.command; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; import de.kentoj.scrowlib.convention.ScrowMessageStyle; import net.kyori.adventure.text.format.TextColor; +import org.jetbrains.annotations.Nullable; import site.lab0x13.scrow.commands.model.literal.Literal; +import site.lab0x13.scrow.commands.model.literal.LiteralMeta; import site.lab0x13.scrow.commands.model.literal.RootLiteral; -import site.lab0x13.scrow.configurator.ConfigApi; +import site.lab0x13.scrow.configurator.config.ConfigRegistry; + +import java.util.List; public final class ConfigCommand { - private final RootLiteral rootLiteral; - public ConfigCommand(ConfigApi configApi) { - var style = new ScrowMessageStyle("config", TextColor.color(0x28B088)); - rootLiteral = Literal.builder("config", "cfg") - .withPermission("command.config") - .withSubLiteral(new KeyLiteral(configApi).literal()) - .asRootLiteral(style); + private final RootLiteral rootLiteral; + private final ConfigRegistry configRegistry; + + public ConfigCommand(ConfigRegistry configRegistry) { + this.configRegistry = configRegistry; + this.rootLiteral = Literal.dynamic("cfg") + .withSubLiteralMetas(this::subLiteralMetas) + .withSubLiteralProvider(this::configLiteral) + .asRootLiteral(new ScrowMessageStyle("Configurator", TextColor.color(0x9070C0))); + } + + private List subLiteralMetas() { + return configRegistry.allConfigs().keySet().stream() + .map(LiteralMeta::of) + .toList(); + } + + private @Nullable Literal configLiteral(String name) { + var cfg = configRegistry.getConfig(name); + if (cfg == null) return null; + return ConfigLiteral.literal(name, cfg); } public RootLiteral rootLiteral() { diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigLiteral.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigLiteral.java new file mode 100644 index 0000000..08644e8 --- /dev/null +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ConfigLiteral.java @@ -0,0 +1,18 @@ +package site.lab0x13.scrow.configurator.command; + +import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; +import site.lab0x13.scrow.commands.model.literal.Literal; +import site.lab0x13.scrow.configurator.config.Config; + +final class ConfigLiteral { + private ConfigLiteral() { + } + + public static Literal literal(String configName, Config cfg) { + return Literal.builder(configName) + .withSubLiteral(new KeyLiteral(cfg).literal()) + .withSubLiteral(new ShowLiteral(cfg).literal()) + .withSubLiteral(new CheckLiteral(cfg).literal()) + .build(); + } +} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/KeyLiteral.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/KeyLiteral.java index fe7c013..810d4be 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/KeyLiteral.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/KeyLiteral.java @@ -1,44 +1,46 @@ package site.lab0x13.scrow.configurator.command; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; -import de.kentoj.scrowlib.convention.ScrowMessageStyle; import org.jetbrains.annotations.Nullable; import site.lab0x13.scrow.commands.model.literal.Literal; import site.lab0x13.scrow.commands.model.literal.LiteralMeta; -import site.lab0x13.scrow.configurator.ConfigApi; +import site.lab0x13.scrow.configurator.config.Config; +import site.lab0x13.scrow.configurator.ConfigNode; import site.lab0x13.scrow.configurator.action.ConfigAction; -import site.lab0x13.scrow.configurator.node.ConfigNode; -import java.util.ArrayList; - -class KeyLiteral { +final class KeyLiteral { private final Literal literal; - private final ConfigApi api; + private final Config cfg; - KeyLiteral(ConfigApi api) { - this.api = api; + KeyLiteral(Config cfg) { + this.cfg = cfg; literal = Literal.dynamic("key") - .withSubLiteralMetas(() -> api.allNodes().keySet().stream().map(LiteralMeta::of).toList()) + .withSubLiteralMetas(() -> cfg.allNodes().keySet().stream().map(LiteralMeta::of).toList()) .withSubLiteralProvider(this::keyLiteral) .build(); } private @Nullable Literal keyLiteral(String name) { - var node = api.getNode(name); - if (node == null) + ConfigNode node; + try { + node = (ConfigNode) cfg.getNode(name); + } catch (Exception ex) { return null; + } + if (node == null) return null; var literalBuilder = Literal.builder(name); - for (var action : node.type().actions()) { + for (var _action : node.type().actions()) { + var action = (ConfigAction) _action; var actionLiteralBuilder = Literal.builder(action.name()); - action.arguments().forEach(actionLiteralBuilder::withArgument); + action.arguments(node).forEach(actionLiteralBuilder::withArgument); actionLiteralBuilder.withSyncExecutor(ctx -> { if (action.requiresValue() && node.value() == null) { ctx.sender().sendMessage(ctx.style().err("No value set.")); return; } - ((ConfigAction>) action).execute(node, ctx); + action.execute(node, ctx); }); literalBuilder.withSubLiteral(actionLiteralBuilder.build()); } diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ShowLiteral.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ShowLiteral.java new file mode 100644 index 0000000..c078dff --- /dev/null +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/command/ShowLiteral.java @@ -0,0 +1,36 @@ +package site.lab0x13.scrow.configurator.command; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import site.lab0x13.scrow.commands.model.literal.Literal; +import site.lab0x13.scrow.configurator.config.Config; + +final class ShowLiteral { + + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + private final Literal literal; + private final Config cfg; + + ShowLiteral(Config cfg) { + this.cfg = cfg; + this.literal = Literal.builder("show") + .withSyncExecutor(this::execute) + .build(); + } + + private void execute(ScrowBukkitCC ctx) { + var prettyJson = GSON.toJson(cfg.toJson(), JsonElement.class); + var component = Component.text(prettyJson + " [click to copy]") + .clickEvent(ClickEvent.copyToClipboard(prettyJson)); + ctx.sender().sendMessage(ctx.style().ok(component)); + } + + public Literal literal() { + return literal; + } +} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigApi.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/Config.java similarity index 68% rename from buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigApi.java rename to buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/Config.java index 024c3fe..1396178 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigApi.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/Config.java @@ -1,11 +1,13 @@ -package site.lab0x13.scrow.configurator; +package site.lab0x13.scrow.configurator.config; +import com.google.gson.JsonElement; import org.jetbrains.annotations.Nullable; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.ConfigKey; +import site.lab0x13.scrow.configurator.ConfigNode; import java.util.Map; -public interface ConfigApi { +public interface Config { void register(ConfigKey key, @Nullable V defaultValue); @@ -26,4 +28,8 @@ public interface ConfigApi { } Map> allNodes(); + + JsonElement toJson(); + + void loadJson(JsonElement json); } diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigApiImpl.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/ConfigImpl.java similarity index 70% rename from buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigApiImpl.java rename to buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/ConfigImpl.java index 9974b03..6498235 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/ConfigApiImpl.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/ConfigImpl.java @@ -1,17 +1,20 @@ -package site.lab0x13.scrow.configurator; +package site.lab0x13.scrow.configurator.config; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.ConfigKey; +import site.lab0x13.scrow.configurator.ConfigNode; import java.util.ArrayDeque; import java.util.HashMap; import java.util.Map; -public class ConfigApiImpl implements ConfigApi { +public class ConfigImpl implements Config { - private final Logger log = LoggerFactory.getLogger(ConfigApiImpl.class); + private final Logger log = LoggerFactory.getLogger(ConfigImpl.class); private final Map> nodes = new HashMap<>(); @@ -71,4 +74,25 @@ public class ConfigApiImpl implements ConfigApi { addNodeRecursively(result, nodeId + "." + fieldName, subNode); } } + + @Override + public void loadJson(JsonElement json) { + var obj = json.getAsJsonObject(); + allNodes().forEach((key, _node) -> { + var node = (ConfigNode)_node; + var nodeValue = obj.get(key); + node.value(node.type().deserialize(nodeValue)); + }); + } + + @Override + public JsonElement toJson() { + var obj = new JsonObject(); + allNodes().forEach((key, _node) -> { + var node = (ConfigNode)_node; + var nodeValue = node.type().serialize(node.value()); + obj.add(key, nodeValue); + }); + return obj; + } } diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/ConfigRegistry.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/ConfigRegistry.java new file mode 100644 index 0000000..664e9b3 --- /dev/null +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/config/ConfigRegistry.java @@ -0,0 +1,28 @@ +package site.lab0x13.scrow.configurator.config; + +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public class ConfigRegistry { + + private static final Logger log = LoggerFactory.getLogger(ConfigRegistry.class); + private final Map configs = new HashMap<>(); + + public void register(String name, Config config) { + var oldValue = configs.put(name, config); + if (oldValue != null) + log.warn("Overwriting old config with same name '{}'", name); + } + + public Map allConfigs() { + return new HashMap<>(configs); + } + + public @Nullable Config getConfig(String name) { + return configs.get(name); + } +} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigComplexType.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigComplexType.java index f01abf6..35a4d6c 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigComplexType.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigComplexType.java @@ -7,13 +7,13 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Function; -public abstract class ConfigComplexType implements ConfigType { +public abstract class ConfigComplexType implements ConfigType { - private final Map> fields = new HashMap<>(); + private final Map> fields = new HashMap<>(); - protected abstract T deserialize(JsonObject obj); + protected abstract V deserialize(JsonObject obj); - protected void addField(String name, ConfigType type, Function getter) { + protected void addField(String name, ConfigType type, Function getter) { fields.put(name, new Field<>(type, getter)); } @@ -23,18 +23,21 @@ public abstract class ConfigComplexType implements ConfigType { } @Override - public T deserialize(JsonElement json) { + public V deserialize(JsonElement json) { + if (json.getAsJsonObject().isEmpty()) + return null; return deserialize(json.getAsJsonObject()); } @Override - public JsonElement serialize(T value) { + public JsonElement serialize(V value) { + if (value == null) return new JsonObject(); var obj = new JsonObject(); fields.forEach((name, field) -> writeNode(obj, name, field, value)); return obj; } - private void writeNode(JsonObject object, String name, Field field, T value) { + private void writeNode(JsonObject object, String name, Field field, V value) { var fieldValue = field.getter.apply(value); var serializedFieldValue = field.type().serialize(fieldValue); object.add(name, serializedFieldValue); diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigListType.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigListType.java deleted file mode 100644 index dcd7265..0000000 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigListType.java +++ /dev/null @@ -1,51 +0,0 @@ -package site.lab0x13.scrow.configurator.type; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import org.jetbrains.annotations.Nullable; -import site.lab0x13.scrow.configurator.node.ConfigNode; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.IntStream; - -public record ConfigListType( - ConfigType elementType -) implements ConfigType>> { - - @Override - public List> deserialize(JsonElement json) { - var result = new ArrayList>(); - var obj = json.getAsJsonObject(); - obj.asMap().forEach((k, v) -> { - var subNode = new ConfigNode<>(elementType, null); - subNode.value(elementType.deserialize(v)); - result.set(Integer.parseInt(k), subNode); - }); - return result; - } - - @Override - public JsonElement serialize(List> value) { - var res = new JsonObject(); - for (int i = 0; i < value.size(); i++) { - var subNodeValue = value.get(i).value(); - if (subNodeValue == null) continue; - var element = elementType.serialize(subNodeValue); - res.add(Integer.toString(i), element); - } - return res; - } - - @Override - public List getSubNodeNames(List> value) { - return IntStream.range(0, value.size()) - .mapToObj(Integer::toString) - .toList(); - } - - @Override - public @Nullable ConfigNode getSubNode(List> value, String name) { - return value.get(Integer.parseInt(name)); - } -} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigType.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigType.java index a8e2e3d..49b3851 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigType.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/ConfigType.java @@ -1,19 +1,24 @@ package site.lab0x13.scrow.configurator.type; +import de.kentoj.scrowlib.utils.Serializer; import org.jetbrains.annotations.Nullable; import site.lab0x13.scrow.configurator.action.ConfigAction; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.action.GlobalShowAction; +import site.lab0x13.scrow.configurator.ConfigNode; +import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @param type of the stored value */ -public interface ConfigType extends Serializable { +public interface ConfigType extends Serializer { default List> actions() { - return Collections.emptyList(); + return new ArrayList<>(List.of( + new GlobalShowAction() + )); } default List getSubNodeNames(V value) { diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ConfigListType.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ConfigListType.java new file mode 100644 index 0000000..8bfbdf7 --- /dev/null +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ConfigListType.java @@ -0,0 +1,66 @@ +package site.lab0x13.scrow.configurator.type.list; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import org.jetbrains.annotations.Nullable; +import site.lab0x13.scrow.configurator.ConfigNode; +import site.lab0x13.scrow.configurator.action.ConfigAction; +import site.lab0x13.scrow.configurator.type.ConfigType; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +public final class ConfigListType implements ConfigType>> { + + private final ConfigType elementType; + private final List> actions; + + public ConfigListType(ConfigType elementType) { + this.elementType = elementType; + actions = ConfigType.super.actions(); + actions.add(new ListDeleteAction<>()); + actions.add(new ListAddAction<>(() -> new ConfigNode<>(elementType, null))); + } + + @Override + public List> actions() { + return this.actions; + } + + @Override + public List> deserialize(JsonElement json) { + var result = new ArrayList>(); + var array = json.getAsJsonArray(); + for (int i = 0; i < array.asList().size(); i++) { + var subNode = new ConfigNode<>(elementType, null); + subNode.value(elementType.deserialize(array.get(i))); + result.set(i, subNode); + } + return result; + } + + @Override + public JsonElement serialize(List> value) { + var res = new JsonArray(); + for (var subNode : value) { + var subNodeValue = subNode.value(); + if (subNodeValue == null) continue; + var element = elementType.serialize(subNodeValue); + res.add(element); + } + return res; + } + + @Override + public List getSubNodeNames(List> value) { + return IntStream.range(0, value.size()) + .mapToObj(Integer::toString) + .toList(); + } + + @Override + public @Nullable ConfigNode getSubNode(List> value, String name) { + return value.get(Integer.parseInt(name)); + } +} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListAddAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListAddAction.java new file mode 100644 index 0000000..90cc6b4 --- /dev/null +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListAddAction.java @@ -0,0 +1,42 @@ +package site.lab0x13.scrow.configurator.type.list; + +import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; +import site.lab0x13.scrow.commands.model.argument.Argument; +import site.lab0x13.scrow.configurator.action.ConfigAction; +import site.lab0x13.scrow.configurator.ConfigNode; + +import java.util.Collections; +import java.util.List; +import java.util.function.Supplier; + +class ListAddAction implements ConfigAction>> { + + private final Supplier> newElement; + + ListAddAction(Supplier> newElement) { + this.newElement = newElement; + } + + @Override + public String name() { + return "add"; + } + + @Override + public List> arguments(ConfigNode>> __) { + return Collections.emptyList(); + } + + @Override + public boolean requiresValue() { + return true; + } + + @Override + public void execute(ConfigNode>> node, ScrowBukkitCC ctx) { + assert node.value() != null; + var element = newElement.get(); + node.value().add(element); + ctx.sender().sendMessage(ctx.style().ok("Extended list-node by one with null value.")); + } +} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListDeleteAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListDeleteAction.java new file mode 100644 index 0000000..718e81c --- /dev/null +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/list/ListDeleteAction.java @@ -0,0 +1,49 @@ +package site.lab0x13.scrow.configurator.type.list; + +import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; +import site.lab0x13.scrow.commands.model.argument.Argument; +import site.lab0x13.scrow.commands.model.argument.types.IntegerArgumentType; +import site.lab0x13.scrow.configurator.action.ConfigAction; +import site.lab0x13.scrow.configurator.ConfigNode; + +import java.util.Collections; +import java.util.List; +import java.util.stream.IntStream; + +class ListDeleteAction implements ConfigAction>> { + + @Override + public String name() { + return "delete"; + } + + @Override + public List> arguments(ConfigNode>> node) { + return List.of(Argument.builder("index", new IntegerArgumentType()) + .withRequirement((_, index) -> { + assert node.value() != null; + return index >= 0 && index < node.value().size(); + }, "index out of range") + .withSuggestionProvider((_, _) -> { + if (node.value() == null) + return Collections.emptyList(); + return IntStream.range(0, node.value().size()) + .mapToObj(Integer::toString).toList(); + }) + .build()); + } + + @Override + public boolean requiresValue() { + return true; + } + + @Override + public void execute(ConfigNode>> node, ScrowBukkitCC ctx) { + assert node.value() != null; + int index = ctx.getArg("index"); + var oldValue = node.value().remove(index); + var msg = oldValue == null ? "Deleted empty element." : "Deleted element."; + ctx.sender().sendMessage(ctx.style().ok(msg)); + } +} diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationPickCurrentAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationPickCurrentAction.java index 5f058a8..e1e00b4 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationPickCurrentAction.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationPickCurrentAction.java @@ -3,11 +3,10 @@ package site.lab0x13.scrow.configurator.type.location; import org.bukkit.Location; import org.bukkit.entity.Player; import site.lab0x13.scrow.configurator.action.PickAction; -import site.lab0x13.scrow.configurator.node.ConfigNode; import java.util.concurrent.CompletableFuture; -class LocationPickCurrentAction extends PickAction> { +class LocationPickCurrentAction extends PickAction { @Override public String name() { return "pick-current"; diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationTeleportAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationTeleportAction.java index 0c0c973..3850a34 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationTeleportAction.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/location/LocationTeleportAction.java @@ -3,14 +3,13 @@ package site.lab0x13.scrow.configurator.type.location; import site.lab0x13.scrow.commands.model.argument.Argument; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; import org.bukkit.Location; -import org.bukkit.entity.Player; import site.lab0x13.scrow.configurator.action.ConfigAction; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.ConfigNode; import java.util.Collections; import java.util.List; -class LocationTeleportAction implements ConfigAction> { +class LocationTeleportAction implements ConfigAction { @Override public String name() { @@ -18,7 +17,7 @@ class LocationTeleportAction implements ConfigAction> { } @Override - public List> arguments() { + public List> arguments(ConfigNode __) { return Collections.emptyList(); } diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/world/SetWorldAction.java b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/world/SetWorldAction.java index bde1f1a..71b58bc 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/world/SetWorldAction.java +++ b/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/world/SetWorldAction.java @@ -5,11 +5,11 @@ import site.lab0x13.scrow.commands.model.argument.Argument; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; import org.bukkit.World; import site.lab0x13.scrow.configurator.action.ConfigAction; -import site.lab0x13.scrow.configurator.node.ConfigNode; +import site.lab0x13.scrow.configurator.ConfigNode; import java.util.List; -class SetWorldAction implements ConfigAction> { +class SetWorldAction implements ConfigAction { private final Argument arg = Argument.builder("world", new WorldArgumentType()).build(); @@ -20,7 +20,7 @@ class SetWorldAction implements ConfigAction> { } @Override - public List> arguments() { + public List> arguments(ConfigNode __) { return List.of(arg); } diff --git a/core/common/BUILD b/core/common/BUILD index a7e4b0e..d60ab54 100644 --- a/core/common/BUILD +++ b/core/common/BUILD @@ -12,6 +12,7 @@ shared_deps = [ artifact("net.kyori:adventure-text-minimessage"), artifact("org.jdbi:jdbi3-core"), artifact("org.mongodb:bson"), + artifact("com.google.code.gson:gson"), ] java_library( diff --git a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/Serializable.java b/core/common/src/main/java/de/kentoj/scrowlib/utils/Serializer.java similarity index 76% rename from buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/Serializable.java rename to core/common/src/main/java/de/kentoj/scrowlib/utils/Serializer.java index 561ed63..ee5c57d 100644 --- a/buildserver/configurator/main/java/site/lab0x13/scrow/configurator/type/Serializable.java +++ b/core/common/src/main/java/de/kentoj/scrowlib/utils/Serializer.java @@ -1,9 +1,12 @@ -package site.lab0x13.scrow.configurator.type; +package de.kentoj.scrowlib.utils; import com.google.gson.JsonElement; import com.google.gson.JsonParser; -public interface Serializable { +/** + * @param type of data + */ +public interface Serializer { JsonElement serialize(V value);