configurator works so far
This commit is contained in:
parent
0cf84f5419
commit
812a1b1b21
25 changed files with 424 additions and 124 deletions
|
|
@ -9,12 +9,8 @@ java_binary(
|
||||||
resource_strip_prefix = "buildserver/configurator/main/resources",
|
resource_strip_prefix = "buildserver/configurator/main/resources",
|
||||||
deps = [
|
deps = [
|
||||||
"//core/bukkit:api",
|
"//core/bukkit:api",
|
||||||
artifact("com.google.code.gson:gson"),
|
|
||||||
artifact("io.papermc.paper:paper-api"),
|
artifact("io.papermc.paper:paper-api"),
|
||||||
],
|
],
|
||||||
add_exports = [
|
|
||||||
artifact("com.google.code.gson:gson"),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
genrule(
|
genrule(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package site.lab0x13.scrow.configurator.node;
|
package site.lab0x13.scrow.configurator;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import site.lab0x13.scrow.configurator.type.ConfigType;
|
import site.lab0x13.scrow.configurator.type.ConfigType;
|
||||||
|
|
@ -18,6 +18,12 @@ public final class ConfigNode<V> {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO requirements
|
||||||
|
|
||||||
|
public boolean required() {
|
||||||
|
return defaultValue == null;
|
||||||
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
this.value(defaultValue);
|
this.value(defaultValue);
|
||||||
}
|
}
|
||||||
|
|
@ -3,16 +3,27 @@ package site.lab0x13.scrow.configurator;
|
||||||
import de.kentoj.scrow.bukkit.ScrowAPI;
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import site.lab0x13.scrow.configurator.command.ConfigCommand;
|
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 site.lab0x13.scrow.configurator.type.location.LocationConfigType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class ConfiguratorPlugin extends JavaPlugin {
|
public class ConfiguratorPlugin extends JavaPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
ConfigApi api = new ConfigApiImpl();
|
ConfigRegistry configRegistry = new ConfigRegistry();
|
||||||
var spawnLocation = new ConfigKey<>("spawnLocation", new LocationConfigType());
|
|
||||||
api.register(spawnLocation);
|
Config hotPotatoConfig = new ConfigImpl();
|
||||||
ScrowAPI.commands().register(new ConfigCommand(api).rootLiteral());
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,19 +2,20 @@ package site.lab0x13.scrow.configurator.action;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
||||||
import site.lab0x13.scrow.commands.model.argument.Argument;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param <N> type of ConfigNode
|
* @param <V> type of node value
|
||||||
*/
|
*/
|
||||||
public interface ConfigAction<N extends ConfigNode<?>> {
|
public interface ConfigAction<V> {
|
||||||
|
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
List<Argument<ScrowBukkitCC, ?>> arguments();
|
List<Argument<ScrowBukkitCC, ?>> arguments(ConfigNode<V> node);
|
||||||
|
|
||||||
boolean requiresValue();
|
boolean requiresValue();
|
||||||
|
|
||||||
void execute(N node, ScrowBukkitCC ctx);
|
void execute(ConfigNode<V> node, ScrowBukkitCC ctx);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import site.lab0x13.scrow.commands.model.argument.Argument;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
public final class GlobalShowAction implements ConfigAction<ConfigNode<Object>> {
|
public final class GlobalShowAction implements ConfigAction<Object> {
|
||||||
|
|
||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ public final class GlobalShowAction implements ConfigAction<ConfigNode<Object>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Argument<ScrowBukkitCC, ?>> arguments() {
|
public List<Argument<ScrowBukkitCC, ?>> arguments(ConfigNode<Object> __) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import site.lab0x13.scrow.commands.model.argument.Argument;
|
||||||
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.Player;
|
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.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -12,7 +12,7 @@ import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public abstract class PickAction<V, N extends ConfigNode<V>> implements ConfigAction<N> {
|
public abstract class PickAction<V> implements ConfigAction<V> {
|
||||||
|
|
||||||
protected abstract CompletableFuture<V> pick(Player player);
|
protected abstract CompletableFuture<V> pick(Player player);
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ public abstract class PickAction<V, N extends ConfigNode<V>> implements ConfigAc
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Argument<ScrowBukkitCC, ?>> arguments() {
|
public List<Argument<ScrowBukkitCC, ?>> arguments(ConfigNode<V> __) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ public abstract class PickAction<V, N extends ConfigNode<V>> implements ConfigAc
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(N node, ScrowBukkitCC ctx) {
|
public void execute(ConfigNode<V> node, ScrowBukkitCC ctx) {
|
||||||
pick(ctx.player())
|
pick(ctx.player())
|
||||||
.orTimeout(10, TimeUnit.MINUTES)
|
.orTimeout(10, TimeUnit.MINUTES)
|
||||||
.whenComplete((picked, ex) -> {
|
.whenComplete((picked, ex) -> {
|
||||||
|
|
|
||||||
|
|
@ -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<ScrowBukkitCC> literal;
|
||||||
|
private final Config cfg;
|
||||||
|
|
||||||
|
public CheckLiteral(Config cfg) {
|
||||||
|
this.cfg = cfg;
|
||||||
|
this.literal = Literal.<ScrowBukkitCC>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<ScrowBukkitCC> literal() {
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,19 +3,37 @@ package site.lab0x13.scrow.configurator.command;
|
||||||
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
||||||
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
|
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
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.Literal;
|
||||||
|
import site.lab0x13.scrow.commands.model.literal.LiteralMeta;
|
||||||
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
|
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 {
|
public final class ConfigCommand {
|
||||||
private final RootLiteral<ScrowBukkitCC> rootLiteral;
|
|
||||||
|
|
||||||
public ConfigCommand(ConfigApi configApi) {
|
private final RootLiteral<ScrowBukkitCC> rootLiteral;
|
||||||
var style = new ScrowMessageStyle("config", TextColor.color(0x28B088));
|
private final ConfigRegistry configRegistry;
|
||||||
rootLiteral = Literal.<ScrowBukkitCC>builder("config", "cfg")
|
|
||||||
.withPermission("command.config")
|
public ConfigCommand(ConfigRegistry configRegistry) {
|
||||||
.withSubLiteral(new KeyLiteral(configApi).literal())
|
this.configRegistry = configRegistry;
|
||||||
.asRootLiteral(style);
|
this.rootLiteral = Literal.<ScrowBukkitCC>dynamic("cfg")
|
||||||
|
.withSubLiteralMetas(this::subLiteralMetas)
|
||||||
|
.withSubLiteralProvider(this::configLiteral)
|
||||||
|
.asRootLiteral(new ScrowMessageStyle("Configurator", TextColor.color(0x9070C0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<LiteralMeta> subLiteralMetas() {
|
||||||
|
return configRegistry.allConfigs().keySet().stream()
|
||||||
|
.map(LiteralMeta::of)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nullable Literal<ScrowBukkitCC> configLiteral(String name) {
|
||||||
|
var cfg = configRegistry.getConfig(name);
|
||||||
|
if (cfg == null) return null;
|
||||||
|
return ConfigLiteral.literal(name, cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RootLiteral<ScrowBukkitCC> rootLiteral() {
|
public RootLiteral<ScrowBukkitCC> rootLiteral() {
|
||||||
|
|
|
||||||
|
|
@ -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<ScrowBukkitCC> literal(String configName, Config cfg) {
|
||||||
|
return Literal.<ScrowBukkitCC>builder(configName)
|
||||||
|
.withSubLiteral(new KeyLiteral(cfg).literal())
|
||||||
|
.withSubLiteral(new ShowLiteral(cfg).literal())
|
||||||
|
.withSubLiteral(new CheckLiteral(cfg).literal())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,44 +1,46 @@
|
||||||
package site.lab0x13.scrow.configurator.command;
|
package site.lab0x13.scrow.configurator.command;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
||||||
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import site.lab0x13.scrow.commands.model.literal.Literal;
|
import site.lab0x13.scrow.commands.model.literal.Literal;
|
||||||
import site.lab0x13.scrow.commands.model.literal.LiteralMeta;
|
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.action.ConfigAction;
|
||||||
import site.lab0x13.scrow.configurator.node.ConfigNode;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
final class KeyLiteral {
|
||||||
|
|
||||||
class KeyLiteral {
|
|
||||||
|
|
||||||
private final Literal<ScrowBukkitCC> literal;
|
private final Literal<ScrowBukkitCC> literal;
|
||||||
private final ConfigApi api;
|
private final Config cfg;
|
||||||
|
|
||||||
KeyLiteral(ConfigApi api) {
|
KeyLiteral(Config cfg) {
|
||||||
this.api = api;
|
this.cfg = cfg;
|
||||||
literal = Literal.<ScrowBukkitCC>dynamic("key")
|
literal = Literal.<ScrowBukkitCC>dynamic("key")
|
||||||
.withSubLiteralMetas(() -> api.allNodes().keySet().stream().map(LiteralMeta::of).toList())
|
.withSubLiteralMetas(() -> cfg.allNodes().keySet().stream().map(LiteralMeta::of).toList())
|
||||||
.withSubLiteralProvider(this::keyLiteral)
|
.withSubLiteralProvider(this::keyLiteral)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable Literal<ScrowBukkitCC> keyLiteral(String name) {
|
private @Nullable Literal<ScrowBukkitCC> keyLiteral(String name) {
|
||||||
var node = api.getNode(name);
|
ConfigNode<Object> node;
|
||||||
if (node == null)
|
try {
|
||||||
|
node = (ConfigNode<Object>) cfg.getNode(name);
|
||||||
|
} catch (Exception ex) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
if (node == null) return null;
|
||||||
|
|
||||||
var literalBuilder = Literal.<ScrowBukkitCC>builder(name);
|
var literalBuilder = Literal.<ScrowBukkitCC>builder(name);
|
||||||
for (var action : node.type().actions()) {
|
for (var _action : node.type().actions()) {
|
||||||
|
var action = (ConfigAction<Object>) _action;
|
||||||
var actionLiteralBuilder = Literal.<ScrowBukkitCC>builder(action.name());
|
var actionLiteralBuilder = Literal.<ScrowBukkitCC>builder(action.name());
|
||||||
action.arguments().forEach(actionLiteralBuilder::withArgument);
|
action.arguments(node).forEach(actionLiteralBuilder::withArgument);
|
||||||
actionLiteralBuilder.withSyncExecutor(ctx -> {
|
actionLiteralBuilder.withSyncExecutor(ctx -> {
|
||||||
if (action.requiresValue() && node.value() == null) {
|
if (action.requiresValue() && node.value() == null) {
|
||||||
ctx.sender().sendMessage(ctx.style().err("No value set."));
|
ctx.sender().sendMessage(ctx.style().err("No value set."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
((ConfigAction<ConfigNode<?>>) action).execute(node, ctx);
|
action.execute(node, ctx);
|
||||||
});
|
});
|
||||||
literalBuilder.withSubLiteral(actionLiteralBuilder.build());
|
literalBuilder.withSubLiteral(actionLiteralBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<ScrowBukkitCC> literal;
|
||||||
|
private final Config cfg;
|
||||||
|
|
||||||
|
ShowLiteral(Config cfg) {
|
||||||
|
this.cfg = cfg;
|
||||||
|
this.literal = Literal.<ScrowBukkitCC>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<ScrowBukkitCC> literal() {
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 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;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface ConfigApi {
|
public interface Config {
|
||||||
|
|
||||||
<V> void register(ConfigKey<V> key, @Nullable V defaultValue);
|
<V> void register(ConfigKey<V> key, @Nullable V defaultValue);
|
||||||
|
|
||||||
|
|
@ -26,4 +28,8 @@ public interface ConfigApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, ConfigNode<?>> allNodes();
|
Map<String, ConfigNode<?>> allNodes();
|
||||||
|
|
||||||
|
JsonElement toJson();
|
||||||
|
|
||||||
|
void loadJson(JsonElement json);
|
||||||
}
|
}
|
||||||
|
|
@ -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.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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.ArrayDeque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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<String, ConfigNode<?>> nodes = new HashMap<>();
|
private final Map<String, ConfigNode<?>> nodes = new HashMap<>();
|
||||||
|
|
||||||
|
|
@ -71,4 +74,25 @@ public class ConfigApiImpl implements ConfigApi {
|
||||||
addNodeRecursively(result, nodeId + "." + fieldName, subNode);
|
addNodeRecursively(result, nodeId + "." + fieldName, subNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadJson(JsonElement json) {
|
||||||
|
var obj = json.getAsJsonObject();
|
||||||
|
allNodes().forEach((key, _node) -> {
|
||||||
|
var node = (ConfigNode<Object>)_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<Object>)_node;
|
||||||
|
var nodeValue = node.type().serialize(node.value());
|
||||||
|
obj.add(key, nodeValue);
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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<String, Config> 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<String, Config> allConfigs() {
|
||||||
|
return new HashMap<>(configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable Config getConfig(String name) {
|
||||||
|
return configs.get(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,13 +7,13 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public abstract class ConfigComplexType<T> implements ConfigType<T> {
|
public abstract class ConfigComplexType<V> implements ConfigType<V> {
|
||||||
|
|
||||||
private final Map<String, Field<T, ?>> fields = new HashMap<>();
|
private final Map<String, Field<V, ?>> fields = new HashMap<>();
|
||||||
|
|
||||||
protected abstract T deserialize(JsonObject obj);
|
protected abstract V deserialize(JsonObject obj);
|
||||||
|
|
||||||
protected <S> void addField(String name, ConfigType<S> type, Function<T, S> getter) {
|
protected <S> void addField(String name, ConfigType<S> type, Function<V, S> getter) {
|
||||||
fields.put(name, new Field<>(type, getter));
|
fields.put(name, new Field<>(type, getter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,18 +23,21 @@ public abstract class ConfigComplexType<T> implements ConfigType<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T deserialize(JsonElement json) {
|
public V deserialize(JsonElement json) {
|
||||||
|
if (json.getAsJsonObject().isEmpty())
|
||||||
|
return null;
|
||||||
return deserialize(json.getAsJsonObject());
|
return deserialize(json.getAsJsonObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement serialize(T value) {
|
public JsonElement serialize(V value) {
|
||||||
|
if (value == null) return new JsonObject();
|
||||||
var obj = new JsonObject();
|
var obj = new JsonObject();
|
||||||
fields.forEach((name, field) -> writeNode(obj, name, field, value));
|
fields.forEach((name, field) -> writeNode(obj, name, field, value));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <S> void writeNode(JsonObject object, String name, Field<T, S> field, T value) {
|
private <S> void writeNode(JsonObject object, String name, Field<V, S> field, V value) {
|
||||||
var fieldValue = field.getter.apply(value);
|
var fieldValue = field.getter.apply(value);
|
||||||
var serializedFieldValue = field.type().serialize(fieldValue);
|
var serializedFieldValue = field.type().serialize(fieldValue);
|
||||||
object.add(name, serializedFieldValue);
|
object.add(name, serializedFieldValue);
|
||||||
|
|
|
||||||
|
|
@ -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<V>(
|
|
||||||
ConfigType<V> elementType
|
|
||||||
) implements ConfigType<List<ConfigNode<V>>> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ConfigNode<V>> deserialize(JsonElement json) {
|
|
||||||
var result = new ArrayList<ConfigNode<V>>();
|
|
||||||
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<ConfigNode<V>> 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<String> getSubNodeNames(List<ConfigNode<V>> value) {
|
|
||||||
return IntStream.range(0, value.size())
|
|
||||||
.mapToObj(Integer::toString)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable ConfigNode<V> getSubNode(List<ConfigNode<V>> value, String name) {
|
|
||||||
return value.get(Integer.parseInt(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +1,24 @@
|
||||||
package site.lab0x13.scrow.configurator.type;
|
package site.lab0x13.scrow.configurator.type;
|
||||||
|
|
||||||
|
import de.kentoj.scrowlib.utils.Serializer;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import site.lab0x13.scrow.configurator.action.ConfigAction;
|
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.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param <V> type of the stored value
|
* @param <V> type of the stored value
|
||||||
*/
|
*/
|
||||||
public interface ConfigType<V> extends Serializable<V> {
|
public interface ConfigType<V> extends Serializer<V> {
|
||||||
|
|
||||||
default List<ConfigAction<?>> actions() {
|
default List<ConfigAction<?>> actions() {
|
||||||
return Collections.emptyList();
|
return new ArrayList<>(List.of(
|
||||||
|
new GlobalShowAction()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<String> getSubNodeNames(V value) {
|
default List<String> getSubNodeNames(V value) {
|
||||||
|
|
|
||||||
|
|
@ -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<V> implements ConfigType<List<ConfigNode<V>>> {
|
||||||
|
|
||||||
|
private final ConfigType<V> elementType;
|
||||||
|
private final List<ConfigAction<?>> actions;
|
||||||
|
|
||||||
|
public ConfigListType(ConfigType<V> elementType) {
|
||||||
|
this.elementType = elementType;
|
||||||
|
actions = ConfigType.super.actions();
|
||||||
|
actions.add(new ListDeleteAction<>());
|
||||||
|
actions.add(new ListAddAction<>(() -> new ConfigNode<>(elementType, null)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ConfigAction<?>> actions() {
|
||||||
|
return this.actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ConfigNode<V>> deserialize(JsonElement json) {
|
||||||
|
var result = new ArrayList<ConfigNode<V>>();
|
||||||
|
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<ConfigNode<V>> 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<String> getSubNodeNames(List<ConfigNode<V>> value) {
|
||||||
|
return IntStream.range(0, value.size())
|
||||||
|
.mapToObj(Integer::toString)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ConfigNode<V> getSubNode(List<ConfigNode<V>> value, String name) {
|
||||||
|
return value.get(Integer.parseInt(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<V> implements ConfigAction<List<ConfigNode<V>>> {
|
||||||
|
|
||||||
|
private final Supplier<ConfigNode<V>> newElement;
|
||||||
|
|
||||||
|
ListAddAction(Supplier<ConfigNode<V>> newElement) {
|
||||||
|
this.newElement = newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "add";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Argument<ScrowBukkitCC, ?>> arguments(ConfigNode<List<ConfigNode<V>>> __) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresValue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(ConfigNode<List<ConfigNode<V>>> 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."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<V> implements ConfigAction<List<ConfigNode<V>>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "delete";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Argument<ScrowBukkitCC, ?>> arguments(ConfigNode<List<ConfigNode<V>>> node) {
|
||||||
|
return List.of(Argument.builder("index", new IntegerArgumentType<ScrowBukkitCC>())
|
||||||
|
.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<List<ConfigNode<V>>> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,11 +3,10 @@ package site.lab0x13.scrow.configurator.type.location;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import site.lab0x13.scrow.configurator.action.PickAction;
|
import site.lab0x13.scrow.configurator.action.PickAction;
|
||||||
import site.lab0x13.scrow.configurator.node.ConfigNode;
|
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
class LocationPickCurrentAction extends PickAction<Location, ConfigNode<Location>> {
|
class LocationPickCurrentAction extends PickAction<Location> {
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return "pick-current";
|
return "pick-current";
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@ package site.lab0x13.scrow.configurator.type.location;
|
||||||
import site.lab0x13.scrow.commands.model.argument.Argument;
|
import site.lab0x13.scrow.commands.model.argument.Argument;
|
||||||
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import site.lab0x13.scrow.configurator.action.ConfigAction;
|
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.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class LocationTeleportAction implements ConfigAction<ConfigNode<Location>> {
|
class LocationTeleportAction implements ConfigAction<Location> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
|
|
@ -18,7 +17,7 @@ class LocationTeleportAction implements ConfigAction<ConfigNode<Location>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Argument<ScrowBukkitCC, ?>> arguments() {
|
public List<Argument<ScrowBukkitCC, ?>> arguments(ConfigNode<Location> __) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ import site.lab0x13.scrow.commands.model.argument.Argument;
|
||||||
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import site.lab0x13.scrow.configurator.action.ConfigAction;
|
import site.lab0x13.scrow.configurator.action.ConfigAction;
|
||||||
import site.lab0x13.scrow.configurator.node.ConfigNode;
|
import site.lab0x13.scrow.configurator.ConfigNode;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class SetWorldAction implements ConfigAction<ConfigNode<World>> {
|
class SetWorldAction implements ConfigAction<World> {
|
||||||
|
|
||||||
private final Argument<ScrowBukkitCC, World> arg =
|
private final Argument<ScrowBukkitCC, World> arg =
|
||||||
Argument.builder("world", new WorldArgumentType<ScrowBukkitCC>()).build();
|
Argument.builder("world", new WorldArgumentType<ScrowBukkitCC>()).build();
|
||||||
|
|
@ -20,7 +20,7 @@ class SetWorldAction implements ConfigAction<ConfigNode<World>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Argument<ScrowBukkitCC, ?>> arguments() {
|
public List<Argument<ScrowBukkitCC, ?>> arguments(ConfigNode<World> __) {
|
||||||
return List.of(arg);
|
return List.of(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ shared_deps = [
|
||||||
artifact("net.kyori:adventure-text-minimessage"),
|
artifact("net.kyori:adventure-text-minimessage"),
|
||||||
artifact("org.jdbi:jdbi3-core"),
|
artifact("org.jdbi:jdbi3-core"),
|
||||||
artifact("org.mongodb:bson"),
|
artifact("org.mongodb:bson"),
|
||||||
|
artifact("com.google.code.gson:gson"),
|
||||||
]
|
]
|
||||||
|
|
||||||
java_library(
|
java_library(
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
package site.lab0x13.scrow.configurator.type;
|
package de.kentoj.scrowlib.utils;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
public interface Serializable<V> {
|
/**
|
||||||
|
* @param <V> type of data
|
||||||
|
*/
|
||||||
|
public interface Serializer<V> {
|
||||||
|
|
||||||
JsonElement serialize(V value);
|
JsonElement serialize(V value);
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue