Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee1bf8216e | ||
|
|
362d871ab8 | ||
|
|
738101d5d4 | ||
|
|
782d58fcac | ||
|
|
94b1e77a98 |
No files matched your search
@@ -0,0 +1,76 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Optional;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
@Service
|
||||
@CommandAlias("mv")
|
||||
class ModifyCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
ModifyCommand(@NotNull MVCommandManager commandManager, WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
/* /mv modify [world] <set|add|remove|reset> <property> <value> */
|
||||
@Subcommand("modify")
|
||||
@CommandPermission("multiverse.core.modify")
|
||||
@CommandCompletion("@mvworlds:scope=both @configmodifytype @mvworldpropsname @mvworldpropsvalue")
|
||||
@Syntax("[world] <set|add|remove|reset> <property> <value>")
|
||||
@Description("")
|
||||
void onModifyCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware")
|
||||
@Syntax("[world]")
|
||||
@Description("")
|
||||
MultiverseWorld world,
|
||||
|
||||
@Syntax("<set|add|remove|reset>")
|
||||
@Description("")
|
||||
ConfigModifyType configModifyType,
|
||||
|
||||
@Syntax("<property>")
|
||||
@Description("")
|
||||
String propertyName,
|
||||
|
||||
@Optional
|
||||
@Single
|
||||
@Syntax("[value]")
|
||||
@Description("")
|
||||
String propertyValue) {
|
||||
Logging.fine("ModifyCommand.onModifyCommand: world=%s, configModifyType=%s, propertyName=%s, propertyValue=%s",
|
||||
world, configModifyType, propertyName, propertyValue);
|
||||
|
||||
world.modifyProperty(configModifyType, propertyName, propertyValue).onSuccess(ignore -> {
|
||||
issuer.sendMessage("Property " + propertyName + " set to " + world.getProperty(propertyName).getOrNull()
|
||||
+ " for world " + world.getName() + ".");
|
||||
worldManager.saveWorldsConfig();
|
||||
}).onFailure(exception -> {
|
||||
issuer.sendMessage("Failed to " + configModifyType.name().toLowerCase() + " property " + propertyName
|
||||
+ " to " + propertyValue + " for world " + world.getName() + ".");
|
||||
issuer.sendMessage(exception.getMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package org.mvplugins.multiverse.core.commandtools;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -19,10 +20,12 @@ import com.google.common.collect.Sets;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.config.MVCoreConfig;
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
|
||||
import org.mvplugins.multiverse.core.destination.ParsedDestination;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
@@ -37,27 +40,32 @@ public class MVCommandCompletions extends PaperCommandCompletions {
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
|
||||
@Inject
|
||||
public MVCommandCompletions(
|
||||
MVCommandCompletions(
|
||||
@NotNull MVCommandManager mvCommandManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull DestinationsProvider destinationsProvider,
|
||||
@NotNull MVCoreConfig config
|
||||
) {
|
||||
@NotNull MVCoreConfig config) {
|
||||
super(mvCommandManager);
|
||||
this.commandManager = mvCommandManager;
|
||||
this.worldManager = worldManager;
|
||||
this.destinationsProvider = destinationsProvider;
|
||||
|
||||
registerAsyncCompletion("commands", this::suggestCommands);
|
||||
registerStaticCompletion("configmodifytype", suggestEnums(ConfigModifyType.class));
|
||||
registerAsyncCompletion("destinations", this::suggestDestinations);
|
||||
registerStaticCompletion("environments", suggestEnums(World.Environment.class));
|
||||
registerAsyncCompletion("flags", this::suggestFlags);
|
||||
registerStaticCompletion("gamerules", this::suggestGamerules);
|
||||
registerStaticCompletion("mvconfigs", config.getNodes().getNames());
|
||||
registerAsyncCompletion("mvworlds", this::suggestMVWorlds);
|
||||
registerAsyncCompletion("mvworldpropsname", this::suggestMVWorldPropsName);
|
||||
registerAsyncCompletion("mvworldpropsvalue", this::suggestMVWorldPropsValue);
|
||||
|
||||
setDefaultCompletion("configmodifytype", ConfigModifyType.class);
|
||||
setDefaultCompletion("destinations", ParsedDestination.class);
|
||||
setDefaultCompletion("flags", String[].class);
|
||||
setDefaultCompletion("environments", World.Environment.class);
|
||||
setDefaultCompletion("gamerules", GameRule.class);
|
||||
setDefaultCompletion("mvworlds", MultiverseWorld.class);
|
||||
setDefaultCompletion("mvworlds", LoadedMultiverseWorld.class);
|
||||
}
|
||||
|
||||
@@ -152,4 +160,28 @@ public class MVCommandCompletions extends PaperCommandCompletions {
|
||||
Logging.severe("Invalid MVWorld scope: " + scope);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Collection<String> suggestMVWorldPropsName(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> {
|
||||
MultiverseWorld mvWorld = context.getContextValue(MultiverseWorld.class);
|
||||
ConfigModifyType modifyType = context.getContextValue(ConfigModifyType.class);
|
||||
return mvWorld.getConfigurablePropertyNames(modifyType);
|
||||
}).getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestMVWorldPropsValue(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> {
|
||||
MultiverseWorld mvWorld = context.getContextValue(MultiverseWorld.class);
|
||||
ConfigModifyType modifyType = context.getContextValue(ConfigModifyType.class);
|
||||
String propertyName = context.getContextValue(String.class);
|
||||
return mvWorld.suggestPropertyValues(modifyType, propertyName, context.getInput());
|
||||
}).getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private <T extends Enum<T>> Collection<String> suggestEnums(Class<T> enumClass) {
|
||||
return EnumSet.allOf(enumClass).stream()
|
||||
.map(Enum::name)
|
||||
.map(String::toLowerCase)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,11 @@ import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.RegexContentFilter;
|
||||
import org.mvplugins.multiverse.core.utils.PlayerFinder;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
@Service
|
||||
public class MVCommandContexts extends PaperCommandContexts {
|
||||
class MVCommandContexts extends PaperCommandContexts {
|
||||
|
||||
private final MVCommandManager mvCommandManager;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
@@ -38,12 +39,11 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
private final MVCoreConfig config;
|
||||
|
||||
@Inject
|
||||
public MVCommandContexts(
|
||||
MVCommandContexts(
|
||||
MVCommandManager mvCommandManager,
|
||||
DestinationsProvider destinationsProvider,
|
||||
WorldManager worldManager,
|
||||
MVCoreConfig config
|
||||
) {
|
||||
MVCoreConfig config) {
|
||||
super(mvCommandManager);
|
||||
this.mvCommandManager = mvCommandManager;
|
||||
this.destinationsProvider = destinationsProvider;
|
||||
@@ -57,8 +57,9 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
registerContext(GameRule.class, this::parseGameRule);
|
||||
registerContext(GameRuleValue.class, this::parseGameRuleValue);
|
||||
registerContext(MVConfigValue.class, this::parseMVConfigValue);
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld.class, this::parseMVWorld);
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld[].class, this::parseMVWorldArray);
|
||||
registerIssuerAwareContext(MultiverseWorld.class, this::parseWorld);
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld.class, this::parseLoadedWorld);
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld[].class, this::parseLoadedWorldArray);
|
||||
registerIssuerAwareContext(Player.class, this::parsePlayer);
|
||||
registerIssuerAwareContext(Player[].class, this::parsePlayerArray);
|
||||
}
|
||||
@@ -162,13 +163,14 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
return new MVConfigValue(resolvedValue);
|
||||
}
|
||||
|
||||
private LoadedMultiverseWorld parseMVWorld(BukkitCommandExecutionContext context) {
|
||||
private MultiverseWorld parseWorld(BukkitCommandExecutionContext context) {
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
// Get world based on sender only
|
||||
if (resolve.equals("issuerOnly")) {
|
||||
if (context.getIssuer().isPlayer()) {
|
||||
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
|
||||
return worldManager.getWorld(context.getIssuer().getPlayer().getWorld())
|
||||
.getOrElseThrow(() -> new InvalidCommandArgument("Player is not in a Multiverse World."));
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
@@ -177,7 +179,7 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
}
|
||||
|
||||
String worldName = context.getFirstArg();
|
||||
LoadedMultiverseWorld world = worldManager.getLoadedWorld(worldName).getOrNull();
|
||||
MultiverseWorld world = worldManager.getWorld(worldName).getOrNull();
|
||||
|
||||
// Get world based on input, fallback to sender if input is not a world
|
||||
if (resolve.equals("issuerAware")) {
|
||||
@@ -186,7 +188,8 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
return world;
|
||||
}
|
||||
if (context.getIssuer().isPlayer()) {
|
||||
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
|
||||
return worldManager.getWorld(context.getIssuer().getPlayer().getWorld())
|
||||
.getOrElseThrow(() -> new InvalidCommandArgument("Player is not in a Multiverse World."));
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
@@ -205,7 +208,53 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
|
||||
}
|
||||
|
||||
private LoadedMultiverseWorld[] parseMVWorldArray(BukkitCommandExecutionContext context) {
|
||||
|
||||
private LoadedMultiverseWorld parseLoadedWorld(BukkitCommandExecutionContext context) {
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
// Get world based on sender only
|
||||
if (resolve.equals("issuerOnly")) {
|
||||
if (context.getIssuer().isPlayer()) {
|
||||
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld())
|
||||
.getOrElseThrow(() -> new InvalidCommandArgument("Player is not in a Multiverse World."));
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
}
|
||||
throw new InvalidCommandArgument("This command can only be used by a player in a Multiverse World.");
|
||||
}
|
||||
|
||||
String worldName = context.getFirstArg();
|
||||
LoadedMultiverseWorld world = worldManager.getLoadedWorld(worldName).getOrNull();
|
||||
|
||||
// Get world based on input, fallback to sender if input is not a world
|
||||
if (resolve.equals("issuerAware")) {
|
||||
if (world != null) {
|
||||
context.popFirstArg();
|
||||
return world;
|
||||
}
|
||||
if (context.getIssuer().isPlayer()) {
|
||||
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld())
|
||||
.getOrElseThrow(() -> new InvalidCommandArgument("Player is not in a Multiverse World."));
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
}
|
||||
throw new InvalidCommandArgument("Player is not in a Multiverse World.");
|
||||
}
|
||||
|
||||
// Get world based on input only
|
||||
if (world != null) {
|
||||
context.popFirstArg();
|
||||
return world;
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
}
|
||||
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
|
||||
}
|
||||
|
||||
private LoadedMultiverseWorld[] parseLoadedWorldArray(BukkitCommandExecutionContext context) {
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
LoadedMultiverseWorld playerWorld = null;
|
||||
@@ -309,7 +358,6 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
throw new InvalidCommandArgument("Player " + playerIdentifier + " not found.");
|
||||
}
|
||||
|
||||
|
||||
private Player[] parsePlayerArray(BukkitCommandExecutionContext context) {
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.mvplugins.multiverse.core.commandtools.flags.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
|
||||
@Contract
|
||||
public abstract class MultiverseCommand extends BaseCommand {
|
||||
public abstract class MultiverseCommand extends BaseCommand {
|
||||
|
||||
protected final MVCommandManager commandManager;
|
||||
private String flagGroupName;
|
||||
|
||||
@@ -114,12 +114,12 @@ public class MVCoreConfig implements MVConfig {
|
||||
|
||||
@Override
|
||||
public Try<Object> getProperty(String name) {
|
||||
return configHandle.get(name);
|
||||
return configHandle.getProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Try<Void> setProperty(String name, Object value) {
|
||||
return configHandle.set(name, value);
|
||||
return configHandle.setProperty(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package org.mvplugins.multiverse.core.configuration.functions;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class DefaultSerializerProvider {
|
||||
|
||||
private static final Map<Class<?>, NodeSerializer<?>> SERIALIZERS = new HashMap<>();
|
||||
|
||||
public static <T> void addDefaultSerializer(@NotNull Class<T> type, @NotNull NodeSerializer<T> serializer) {
|
||||
SERIALIZERS.put(type, serializer);
|
||||
}
|
||||
|
||||
public static <T> @Nullable NodeSerializer<T> getDefaultSerializer(Class<T> type) {
|
||||
if (type.isEnum()) {
|
||||
// Special case for enums
|
||||
return (NodeSerializer<T>) ENUM_SERIALIZER;
|
||||
}
|
||||
return (NodeSerializer<T>) SERIALIZERS.get(type);
|
||||
}
|
||||
|
||||
private static final NodeSerializer<Enum> ENUM_SERIALIZER = new NodeSerializer<>() {
|
||||
@Override
|
||||
public Enum<?> deserialize(Object object, Class<Enum> type) {
|
||||
return Enum.valueOf(type, String.valueOf(object).toUpperCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object serialize(Enum object, Class<Enum> type) {
|
||||
return object.name();
|
||||
}
|
||||
};
|
||||
|
||||
private static final NodeSerializer<Boolean> BOOLEAN_SERIALIZER = new NodeSerializer<>() {
|
||||
@Override
|
||||
public Boolean deserialize(Object object, Class<Boolean> type) {
|
||||
if (object instanceof Boolean) {
|
||||
return (Boolean) object;
|
||||
}
|
||||
return ACFUtil.isTruthy(String.valueOf(object));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object serialize(Boolean object, Class<Boolean> type) {
|
||||
return object;
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
addDefaultSerializer(Boolean.class, BOOLEAN_SERIALIZER);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package org.mvplugins.multiverse.core.configuration.functions;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import io.vavr.control.Try;
|
||||
|
||||
public class DefaultStringParserProvider {
|
||||
|
||||
private static final Map<Class<?>, NodeStringParser<?>> PARSERS = new HashMap<>();
|
||||
|
||||
public static void addDefaultStringParser(Class<?> clazz, NodeStringParser<?> parser) {
|
||||
PARSERS.put(clazz, parser);
|
||||
}
|
||||
|
||||
public static <T> NodeStringParser<T> getDefaultStringParser(Class<T> clazz) {
|
||||
if (clazz.isEnum()) {
|
||||
// Special case for enums
|
||||
return (NodeStringParser<T>) ENUM_STRING_PARSER;
|
||||
}
|
||||
return (NodeStringParser<T>) PARSERS.get(clazz);
|
||||
}
|
||||
|
||||
private static final NodeStringParser<Enum> ENUM_STRING_PARSER = (input, type) -> Try.of(
|
||||
() -> Enum.valueOf(type, input.toUpperCase()));
|
||||
|
||||
private static final NodeStringParser<String> STRING_STRING_PARSER = (input, type) -> Try.of(
|
||||
() -> input);
|
||||
|
||||
private static final NodeStringParser<Boolean> BOOLEAN_STRING_PARSER = (input, type) -> Try.of(
|
||||
() -> ACFUtil.isTruthy(String.valueOf(input).toLowerCase()));
|
||||
|
||||
private static final NodeStringParser<Integer> INTEGER_STRING_PARSER = (input, type) -> Try.of(
|
||||
() -> ACFUtil.parseInt(input));
|
||||
|
||||
private static final NodeStringParser<Double> DOUBLE_STRING_PARSER = (input, type) -> Try.of(
|
||||
() -> ACFUtil.parseDouble(input));
|
||||
|
||||
private static final NodeStringParser<Float> FLOAT_STRING_PARSER = (input, type) -> Try.of(
|
||||
() -> ACFUtil.parseFloat(input));
|
||||
|
||||
private static final NodeStringParser<Long> LONG_STRING_PARSER = (input, type) -> Try.of(
|
||||
() -> ACFUtil.parseLong(input));
|
||||
|
||||
static {
|
||||
addDefaultStringParser(String.class, STRING_STRING_PARSER);
|
||||
addDefaultStringParser(Boolean.class, BOOLEAN_STRING_PARSER);
|
||||
addDefaultStringParser(Integer.class, INTEGER_STRING_PARSER);
|
||||
addDefaultStringParser(Double.class, DOUBLE_STRING_PARSER);
|
||||
addDefaultStringParser(Float.class, FLOAT_STRING_PARSER);
|
||||
addDefaultStringParser(Long.class, LONG_STRING_PARSER);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package org.mvplugins.multiverse.core.configuration.functions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DefaultSuggesterProvider {
|
||||
|
||||
private static final Map<Class<?>, NodeSuggester> SUGGESTERS = new HashMap<>();
|
||||
|
||||
public static void addDefaultSuggester(Class<?> clazz, NodeSuggester suggester) {
|
||||
SUGGESTERS.put(clazz, suggester);
|
||||
}
|
||||
|
||||
public static @Nullable NodeSuggester getDefaultSuggester(Class<?> clazz) {
|
||||
if (clazz.isEnum()) {
|
||||
// Special case for enums
|
||||
return enumSuggester(clazz);
|
||||
}
|
||||
return SUGGESTERS.get(clazz);
|
||||
}
|
||||
|
||||
private static NodeSuggester enumSuggester(Class<?> clazz) {
|
||||
return input -> Arrays.stream(clazz.getEnumConstants())
|
||||
.map(Object::toString)
|
||||
.map(String::toLowerCase)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static final NodeSuggester BOOLEAN_SUGGESTER = input -> List.of("true", "false");
|
||||
|
||||
private static final NodeSuggester INTEGER_SUGGESTER = input -> IntStream.range(1, 10)
|
||||
.boxed()
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
static {
|
||||
addDefaultSuggester(Boolean.class, BOOLEAN_SUGGESTER);
|
||||
addDefaultSuggester(Integer.class, INTEGER_SUGGESTER);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
package org.mvplugins.multiverse.core.configuration.functions;
|
||||
|
||||
public interface NodeSerializer<T> {
|
||||
T deserialize(Object object, Class<T> type);
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.mvplugins.multiverse.core.configuration.functions;
|
||||
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface NodeStringParser<T> {
|
||||
Try<T> parse(@Nullable String string, @NotNull Class<T> type);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.mvplugins.multiverse.core.configuration.functions;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface NodeSuggester {
|
||||
Collection<String> suggest(String input);
|
||||
}
|
||||
+1
-1
@@ -76,7 +76,7 @@ public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfigu
|
||||
valueNode.getDefaultValue())).onFailure(e -> {
|
||||
Logging.warning("Failed to set node " + valueNode.getPath()
|
||||
+ " to " + valueNode.getDefaultValue());
|
||||
setDefault(valueNode);
|
||||
reset(valueNode);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.mvplugins.multiverse.core.configuration.handle;
|
||||
|
||||
public enum ConfigModifyType {
|
||||
SET,
|
||||
ADD,
|
||||
REMOVE,
|
||||
RESET
|
||||
}
|
||||
+171
-26
@@ -1,7 +1,12 @@
|
||||
package org.mvplugins.multiverse.core.configuration.handle;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@@ -10,6 +15,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.migration.ConfigMigrator;
|
||||
import org.mvplugins.multiverse.core.configuration.node.ConfigNodeNotFoundException;
|
||||
import org.mvplugins.multiverse.core.configuration.node.ListValueNode;
|
||||
import org.mvplugins.multiverse.core.configuration.node.NodeGroup;
|
||||
import org.mvplugins.multiverse.core.configuration.node.ValueNode;
|
||||
|
||||
@@ -18,12 +24,12 @@ import org.mvplugins.multiverse.core.configuration.node.ValueNode;
|
||||
*/
|
||||
public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
protected final @Nullable Logger logger;
|
||||
protected final @Nullable NodeGroup nodes;
|
||||
protected final @NotNull NodeGroup nodes;
|
||||
protected final @Nullable ConfigMigrator migrator;
|
||||
|
||||
protected C config;
|
||||
|
||||
protected GenericConfigHandle(@Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
|
||||
protected GenericConfigHandle(@Nullable Logger logger, @NotNull NodeGroup nodes, @Nullable ConfigMigrator migrator) {
|
||||
this.logger = logger;
|
||||
this.nodes = nodes;
|
||||
this.migrator = migrator;
|
||||
@@ -67,21 +73,140 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
});
|
||||
}
|
||||
|
||||
public Collection<String> getPropertyNames() {
|
||||
return nodes.getNames();
|
||||
}
|
||||
|
||||
public Collection<String> getPropertyNames(ConfigModifyType configModifyType) {
|
||||
return switch (configModifyType) {
|
||||
case SET, RESET -> nodes.getNames();
|
||||
case ADD, REMOVE -> nodes.stream()
|
||||
.filter(node -> node instanceof ListValueNode)
|
||||
.map(node -> ((ValueNode<?>) node).getName())
|
||||
.filter(Option::isDefined)
|
||||
.map(Option::get)
|
||||
.toList();
|
||||
};
|
||||
}
|
||||
|
||||
public Try<Class> getPropertyType(@Nullable String name) {
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.map(valueNode -> {
|
||||
if (valueNode instanceof ListValueNode listValueNode) {
|
||||
return listValueNode.getItemType();
|
||||
}
|
||||
return valueNode.getType();
|
||||
})
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name));
|
||||
}
|
||||
|
||||
public Collection<String> suggestPropertyValues(
|
||||
@NotNull ConfigModifyType type, @Nullable String name, @Nullable String input) {
|
||||
return switch (type) {
|
||||
case RESET -> Collections.emptyList();
|
||||
case SET -> nodes.findNode(name, ValueNode.class)
|
||||
.map(node -> node.suggest(input))
|
||||
.getOrElse(Collections.emptyList());
|
||||
case ADD -> nodes.findNode(name, ListValueNode.class)
|
||||
.map(node -> node.suggestItem(input))
|
||||
.getOrElse(Collections.emptyList());
|
||||
case REMOVE -> nodes.findNode(name, ListValueNode.class)
|
||||
.toTry()
|
||||
.map(node -> Option.of(get((ValueNode<List>) node))
|
||||
.map(list -> list.stream().map(Object::toString).toList())
|
||||
.getOrElse(Collections.emptyList()))
|
||||
.getOrElse(Collections.emptyList());
|
||||
default -> Collections.emptyList();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
|
||||
*
|
||||
* @param name The name of the node.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public Try<Object> get(@Nullable String name) {
|
||||
public Try<Object> getProperty(@Nullable String name) {
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.map(node -> get((ValueNode<Object>) node));
|
||||
}
|
||||
|
||||
public Try<Void> modifyProperty(@NotNull ConfigModifyType type, @Nullable String name, @Nullable String value) {
|
||||
return switch (type) {
|
||||
case SET -> setProperty(name, value);
|
||||
case RESET -> resetProperty(name);
|
||||
case ADD -> addProperty(name, value);
|
||||
case REMOVE -> removeProperty(name, value);
|
||||
default -> Try.failure(new IllegalArgumentException("Unknown config modify type: " + type));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param name The name of the node.
|
||||
* @param value The value to set.
|
||||
* @return True if the value was set, false otherwise.
|
||||
*/
|
||||
public Try<Void> setProperty(@Nullable String name, @Nullable String value) {
|
||||
//noinspection unchecked
|
||||
return propertyAction(name, ValueNode.class, node ->
|
||||
node.parseFromString(value).flatMapTry(parsedValue -> set(node, parsedValue)));
|
||||
}
|
||||
|
||||
public Try<Void> addProperty(@Nullable String name, @Nullable String value) {
|
||||
//noinspection unchecked
|
||||
return propertyAction(name, ListValueNode.class, node ->
|
||||
node.parseItemFromString(value).flatMapTry(item -> add(node, item)));
|
||||
}
|
||||
|
||||
public Try<Void> removeProperty(@Nullable String name, @Nullable String value) {
|
||||
//noinspection unchecked
|
||||
return propertyAction(name, ListValueNode.class, node ->
|
||||
node.parseItemFromString(value).flatMapTry(item -> remove(node, item)));
|
||||
}
|
||||
|
||||
public Try<Void> resetProperty(@Nullable String name) {
|
||||
return propertyAction(name, ValueNode.class, this::reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param name The name of the node.
|
||||
* @param value The value to set.
|
||||
* @return True if the value was set, false otherwise.
|
||||
*/
|
||||
public Try<Void> setProperty(@Nullable String name, @Nullable Object value) {
|
||||
//noinspection unchecked
|
||||
return propertyAction(name, ValueNode.class, node -> set(node, value));
|
||||
}
|
||||
|
||||
public Try<Void> addProperty(@Nullable String name, @Nullable Object value) {
|
||||
//noinspection unchecked
|
||||
return propertyAction(name, ListValueNode.class, node -> add(node, value));
|
||||
}
|
||||
|
||||
public Try<Void> removeProperty(@Nullable String name, @Nullable Object value) {
|
||||
//noinspection unchecked
|
||||
return propertyAction(name, ListValueNode.class, node -> remove(node, value));
|
||||
}
|
||||
|
||||
private <T extends ValueNode<?>> Try<Void> propertyAction(
|
||||
@Nullable String name,
|
||||
@NotNull Class<T> nodeClass,
|
||||
@NotNull Function<T, Try<Void>> action) {
|
||||
return nodes.findNode(name, nodeClass)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.flatMapTry(action::apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
|
||||
*
|
||||
* @param node The node to get the value of.
|
||||
* @param <T> The type of the node value.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public <T> T get(@NotNull ValueNode<T> node) {
|
||||
@@ -91,48 +216,67 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
return node.getSerializer().deserialize(config.get(node.getPath(), node.getDefaultValue()), node.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param name The name of the node.
|
||||
* @param value The value to set.
|
||||
* @return True if the value was set, false otherwise.
|
||||
*/
|
||||
public Try<Void> set(@Nullable String name, Object value) {
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.flatMap(node -> set(node, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param node The node to set the value of.
|
||||
* @param value The value to set.
|
||||
* @return True if the value was set, false otherwise.
|
||||
* @param <T> The type of the node value.
|
||||
* @return Empty try if the value was set, try containing an error otherwise.
|
||||
*/
|
||||
public <T> Try<Void> set(@NotNull ValueNode<T> node, T value) {
|
||||
return node.validate(value).map(ignore -> {
|
||||
T oldValue = get(node);
|
||||
if (node.getSerializer() != null) {
|
||||
var serialized = node.getSerializer().serialize(value, node.getType());
|
||||
config.set(node.getPath(), serialized);
|
||||
} else {
|
||||
config.set(node.getPath(), value);
|
||||
}
|
||||
var serialized = node.getSerializer() != null
|
||||
? node.getSerializer().serialize(value, node.getType())
|
||||
: value;
|
||||
config.set(node.getPath(), serialized);
|
||||
node.onSetValue(oldValue, get(node));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public <I> Try<Void> add(@NotNull ListValueNode<I> node, I value) {
|
||||
// TODO: Serialize value, Validate value
|
||||
return Try.run(() -> {
|
||||
var serialized = node.getItemSerializer() != null
|
||||
? node.getItemSerializer().serialize(value, node.getItemType())
|
||||
: value;
|
||||
List list = get(node);
|
||||
if (list == null) {
|
||||
throw new IllegalArgumentException("List is null");
|
||||
}
|
||||
list.add(serialized);
|
||||
config.set(node.getPath(), list);
|
||||
node.onSetValue(list, get(node));
|
||||
});
|
||||
}
|
||||
|
||||
public <I> Try<Void> remove(@NotNull ListValueNode<I> node, I value) {
|
||||
return Try.run(() -> {
|
||||
var serialized = node.getItemSerializer() != null
|
||||
? node.getItemSerializer().serialize(value, node.getItemType())
|
||||
: value;
|
||||
List list = get(node);
|
||||
if (list == null) {
|
||||
throw new IllegalArgumentException("List is null");
|
||||
}
|
||||
if (!list.remove(serialized)) {
|
||||
throw new IllegalArgumentException("Value not found in list");
|
||||
}
|
||||
config.set(node.getPath(), list);
|
||||
node.onSetItemValue(value, null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value of a node.
|
||||
*
|
||||
* @param node The node to set the default value of.
|
||||
* @return Empty try if the value was set, try containing an error otherwise.
|
||||
*/
|
||||
public void setDefault(@NotNull ValueNode node) {
|
||||
config.set(node.getPath(), node.getDefaultValue());
|
||||
public <T> Try<Void> reset(@NotNull ValueNode<T> node) {
|
||||
return Try.run(() -> config.set(node.getPath(), node.getDefaultValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,7 +291,8 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
protected @Nullable NodeGroup nodes;
|
||||
protected @Nullable ConfigMigrator migrator;
|
||||
|
||||
protected Builder() {}
|
||||
protected Builder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger.
|
||||
|
||||
+6
-1
@@ -66,7 +66,7 @@ public class ConfigHeaderNode implements CommentedNode {
|
||||
comment = "# " + comment;
|
||||
}
|
||||
comments.add(comment);
|
||||
return (B) this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,5 +77,10 @@ public class ConfigHeaderNode implements CommentedNode {
|
||||
public @NotNull ConfigHeaderNode build() {
|
||||
return new ConfigHeaderNode(path, comments.toArray(new String[0]));
|
||||
}
|
||||
|
||||
protected B self() {
|
||||
//noinspection unchecked
|
||||
return (B) this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,26 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.functions.DefaultSerializerProvider;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.DefaultStringParserProvider;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.DefaultSuggesterProvider;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeSerializer;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeStringParser;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeSuggester;
|
||||
|
||||
/**
|
||||
* A node that contains a value.
|
||||
*
|
||||
* @param <T> The type of the value.
|
||||
*/
|
||||
public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
@@ -19,38 +30,48 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
*
|
||||
* @param path The path of the node.
|
||||
* @param type The type of the value.
|
||||
* @return The new builder.
|
||||
* @param <T> The type of the value.
|
||||
* @return The new builder.
|
||||
*/
|
||||
public static @NotNull <T> ConfigNode.Builder<T, ? extends ConfigNode.Builder<T, ?>> builder(
|
||||
@NotNull String path,
|
||||
@NotNull Class<T> type
|
||||
) {
|
||||
@NotNull Class<T> type) {
|
||||
return new ConfigNode.Builder<>(path, type);
|
||||
}
|
||||
|
||||
protected final @Nullable String name;
|
||||
protected final @NotNull Class<T> type;
|
||||
protected final @Nullable T defaultValue;
|
||||
protected final @Nullable NodeSerializer<T> serializer;
|
||||
protected final @Nullable Function<T, Try<Void>> validator;
|
||||
protected final @Nullable BiConsumer<T, T> onSetValue;
|
||||
protected final @Nullable Supplier<T> defaultValueSupplier;
|
||||
protected @Nullable NodeSuggester suggester;
|
||||
protected @Nullable NodeStringParser<T> stringParser;
|
||||
protected @Nullable NodeSerializer<T> serializer;
|
||||
protected @Nullable Function<T, Try<Void>> validator;
|
||||
protected @Nullable BiConsumer<T, T> onSetValue;
|
||||
|
||||
protected ConfigNode(
|
||||
@NotNull String path,
|
||||
@NotNull String[] comments,
|
||||
@Nullable String name,
|
||||
@NotNull Class<T> type,
|
||||
@Nullable T defaultValue,
|
||||
@Nullable Supplier<T> defaultValueSupplier,
|
||||
@Nullable NodeSuggester suggester,
|
||||
@Nullable NodeStringParser<T> stringParser,
|
||||
@Nullable NodeSerializer<T> serializer,
|
||||
@Nullable Function<T, Try<Void>> validator,
|
||||
@Nullable BiConsumer<T, T> onSetValue
|
||||
) {
|
||||
@Nullable BiConsumer<T, T> onSetValue) {
|
||||
super(path, comments);
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.defaultValue = defaultValue;
|
||||
this.serializer = serializer;
|
||||
this.defaultValueSupplier = defaultValueSupplier;
|
||||
this.suggester = suggester != null
|
||||
? suggester
|
||||
: DefaultSuggesterProvider.getDefaultSuggester(type);
|
||||
this.stringParser = stringParser != null
|
||||
? stringParser
|
||||
: DefaultStringParserProvider.getDefaultStringParser(type);
|
||||
this.serializer = serializer != null
|
||||
? serializer
|
||||
: DefaultSerializerProvider.getDefaultSerializer(type);
|
||||
this.validator = validator;
|
||||
this.onSetValue = onSetValue;
|
||||
}
|
||||
@@ -76,7 +97,29 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
*/
|
||||
@Override
|
||||
public @Nullable T getDefaultValue() {
|
||||
return defaultValue;
|
||||
return defaultValueSupplier != null ? defaultValueSupplier.get() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Collection<String> suggest(@Nullable String input) {
|
||||
if (suggester != null) {
|
||||
return suggester.suggest(input);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Try<T> parseFromString(@Nullable String input) {
|
||||
if (stringParser != null) {
|
||||
return stringParser.parse(input, type);
|
||||
}
|
||||
return Try.failure(new UnsupportedOperationException("No string parser for type " + type.getName()));
|
||||
}
|
||||
|
||||
public @Nullable NodeSerializer<T> getSerializer() {
|
||||
@@ -111,11 +154,12 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
* @param <B> The type of the builder.
|
||||
*/
|
||||
public static class Builder<T, B extends ConfigNode.Builder<T, B>> extends ConfigHeaderNode.Builder<B> {
|
||||
private static final NodeSerializer<?> ENUM_NODE_SERIALIZER = new EnumNodeSerializer<>();
|
||||
|
||||
protected @Nullable String name;
|
||||
protected @NotNull final Class<T> type;
|
||||
protected @Nullable T defaultValue;
|
||||
protected @Nullable Supplier<T> defaultValueSupplier;
|
||||
protected @Nullable NodeSuggester suggester;
|
||||
protected @Nullable NodeStringParser<T> stringParser;
|
||||
protected @Nullable NodeSerializer<T> serializer;
|
||||
protected @Nullable Function<T, Try<Void>> validator;
|
||||
protected @Nullable BiConsumer<T, T> onSetValue;
|
||||
@@ -130,9 +174,6 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
super(path);
|
||||
this.name = path;
|
||||
this.type = type;
|
||||
if (type.isEnum()) {
|
||||
this.serializer = (NodeSerializer<T>) ENUM_NODE_SERIALIZER;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,8 +183,19 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B defaultValue(@NotNull T defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
return (B) this;
|
||||
this.defaultValueSupplier = () -> defaultValue;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value for this node.
|
||||
*
|
||||
* @param defaultValueSupplier The supplier for the default value.
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B defaultValue(@NotNull Supplier<T> defaultValueSupplier) {
|
||||
this.defaultValueSupplier = defaultValueSupplier;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,17 +206,27 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
*/
|
||||
public @NotNull B name(@Nullable String name) {
|
||||
this.name = name;
|
||||
return (B) this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull B suggester(@NotNull NodeSuggester suggester) {
|
||||
this.suggester = suggester;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull B stringParser(@NotNull NodeStringParser<T> stringParser) {
|
||||
this.stringParser = stringParser;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull B serializer(@NotNull NodeSerializer<T> serializer) {
|
||||
this.serializer = serializer;
|
||||
return (B) this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull B validator(@NotNull Function<T, Try<Void>> validator) {
|
||||
this.validator = validator;
|
||||
return (B) this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,7 +237,7 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
*/
|
||||
public @NotNull B onSetValue(@NotNull BiConsumer<T, T> onSetValue) {
|
||||
this.onSetValue = onSetValue;
|
||||
return (B) this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,7 +245,17 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
*/
|
||||
@Override
|
||||
public @NotNull ConfigNode<T> build() {
|
||||
return new ConfigNode<>(path, comments.toArray(new String[0]), name, type, defaultValue, serializer, validator, onSetValue);
|
||||
return new ConfigNode<>(
|
||||
path,
|
||||
comments.toArray(new String[0]),
|
||||
name,
|
||||
type,
|
||||
defaultValueSupplier,
|
||||
suggester,
|
||||
stringParser,
|
||||
serializer,
|
||||
validator,
|
||||
onSetValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
public class EnumNodeSerializer<T extends Enum<T>> implements NodeSerializer<T> {
|
||||
|
||||
@Override
|
||||
public T deserialize(Object object, Class<T> type) {
|
||||
return Enum.valueOf(type, object.toString().toUpperCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object serialize(T object, Class<T> type) {
|
||||
return object.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import io.vavr.Value;
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.functions.DefaultStringParserProvider;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.DefaultSuggesterProvider;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeSerializer;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeStringParser;
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeSuggester;
|
||||
|
||||
public class ListConfigNode<I> extends ConfigNode<List<I>> implements ListValueNode<I> {
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link ConfigNode}.
|
||||
*
|
||||
* @param path The path of the node.
|
||||
* @param type The type of the value.
|
||||
* @param <I> The type of the value.
|
||||
* @return The new builder.
|
||||
*/
|
||||
public static @NotNull <I> Builder<I, ? extends Builder<I, ?>> listBuilder(
|
||||
@NotNull String path,
|
||||
@NotNull Class<I> type) {
|
||||
return new Builder<>(path, type);
|
||||
}
|
||||
|
||||
protected final Class<I> itemType;
|
||||
protected final NodeSuggester itemSuggester;
|
||||
protected final NodeStringParser<I> itemStringParser;
|
||||
protected final NodeSerializer<I> itemSerializer;
|
||||
protected final Function<I, Try<Void>> itemValidator;
|
||||
protected final BiConsumer<I, I> onSetItemValue;
|
||||
|
||||
protected ListConfigNode(
|
||||
@NotNull String path,
|
||||
@NotNull String[] comments,
|
||||
@Nullable String name,
|
||||
@NotNull Class<List<I>> type,
|
||||
@Nullable Supplier<List<I>> defaultValueSupplier,
|
||||
@Nullable NodeSuggester suggester,
|
||||
@Nullable NodeStringParser<List<I>> stringParser,
|
||||
@Nullable NodeSerializer<List<I>> serializer,
|
||||
@Nullable Function<List<I>, Try<Void>> validator,
|
||||
@Nullable BiConsumer<List<I>, List<I>> onSetValue,
|
||||
@NotNull Class<I> itemType,
|
||||
@Nullable NodeSuggester itemSuggester,
|
||||
@Nullable NodeStringParser<I> itemStringParser,
|
||||
@Nullable NodeSerializer<I> itemSerializer,
|
||||
@Nullable Function<I, Try<Void>> itemValidator,
|
||||
@Nullable BiConsumer<I, I> onSetItemValue) {
|
||||
super(path, comments, name, type, defaultValueSupplier, suggester, stringParser, serializer,
|
||||
validator, onSetValue);
|
||||
this.itemType = itemType;
|
||||
this.itemSuggester = itemSuggester != null
|
||||
? itemSuggester
|
||||
: DefaultSuggesterProvider.getDefaultSuggester(itemType);
|
||||
this.itemStringParser = itemStringParser != null
|
||||
? itemStringParser
|
||||
: DefaultStringParserProvider.getDefaultStringParser(itemType);
|
||||
this.itemSerializer = itemSerializer;
|
||||
this.itemValidator = itemValidator;
|
||||
this.onSetItemValue = onSetItemValue;
|
||||
|
||||
if (this.itemSuggester != null && this.suggester == null) {
|
||||
setDefaultSuggester();
|
||||
}
|
||||
if (this.itemStringParser != null && this.stringParser == null) {
|
||||
Logging.fine("Setting default string parser for list node " + path);
|
||||
setDefaultStringParser();
|
||||
}
|
||||
if (this.itemValidator != null && this.validator == null) {
|
||||
setDefaultValidator();
|
||||
}
|
||||
if (this.itemSerializer != null && this.serializer == null) {
|
||||
setDefaultSerialiser();
|
||||
}
|
||||
if (this.onSetItemValue != null && this.onSetValue == null) {
|
||||
setDefaultOnSetValue();
|
||||
}
|
||||
}
|
||||
|
||||
private void setDefaultSuggester() {
|
||||
this.suggester = input -> {
|
||||
int lastIndexOf = input.lastIndexOf(',');
|
||||
if (lastIndexOf == -1) {
|
||||
return itemSuggester.suggest(input);
|
||||
}
|
||||
|
||||
String lastInput = input.substring(lastIndexOf + 1);
|
||||
String inputBeforeLast = input.substring(0, lastIndexOf + 1);
|
||||
Set<String> inputs = Set.of(inputBeforeLast.split(","));
|
||||
return itemSuggester.suggest(lastInput).stream()
|
||||
.filter(item -> !inputs.contains(item))
|
||||
.map(item -> inputBeforeLast + item)
|
||||
.toList();
|
||||
};
|
||||
}
|
||||
|
||||
private void setDefaultStringParser() {
|
||||
this.stringParser = (input, type) -> {
|
||||
if (input == null) {
|
||||
return Try.failure(new IllegalArgumentException("Input cannot be null"));
|
||||
}
|
||||
return Try.sequence(Arrays.stream(input.split(","))
|
||||
.map(inputItem -> itemStringParser.parse(inputItem, itemType))
|
||||
.toList()).map(Value::toJavaList);
|
||||
};
|
||||
}
|
||||
|
||||
private void setDefaultValidator() {
|
||||
this.validator = value -> {
|
||||
if (value != null) {
|
||||
return Try.sequence(value.stream().map(itemValidator).toList()).map(v -> null);
|
||||
}
|
||||
return Try.success(null);
|
||||
};
|
||||
}
|
||||
|
||||
private void setDefaultSerialiser() {
|
||||
this.serializer = new NodeSerializer<>() {
|
||||
@Override
|
||||
public List<I> deserialize(Object object, Class<List<I>> type) {
|
||||
if (object instanceof List list) {
|
||||
return list.stream().map(item -> itemSerializer.deserialize(item, itemType)).toList();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object serialize(List<I> object, Class<List<I>> type) {
|
||||
if (object != null) {
|
||||
return object.stream().map(item -> itemSerializer.serialize(item, itemType)).toList();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setDefaultOnSetValue() {
|
||||
this.onSetValue = (oldValue, newValue) -> {
|
||||
if (oldValue != null) {
|
||||
oldValue.stream()
|
||||
.filter(value -> !newValue.contains(value))
|
||||
.forEach(item -> onSetItemValue.accept(item, null));
|
||||
}
|
||||
newValue.forEach(item -> onSetItemValue.accept(null, item));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Class<I> getItemType() {
|
||||
return itemType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Collection<String> suggestItem(@Nullable String input) {
|
||||
if (itemSuggester != null) {
|
||||
return itemSuggester.suggest(input);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Try<I> parseItemFromString(@Nullable String input) {
|
||||
if (itemStringParser != null) {
|
||||
return itemStringParser.parse(input, itemType);
|
||||
}
|
||||
return Try.failure(new UnsupportedOperationException("No item string parser for type " + itemType));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @Nullable NodeSerializer<I> getItemSerializer() {
|
||||
return itemSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Try<Void> validateItem(@Nullable I value) {
|
||||
if (itemValidator != null) {
|
||||
return itemValidator.apply(value);
|
||||
}
|
||||
return Try.success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onSetItemValue(@Nullable I oldValue, @Nullable I newValue) {
|
||||
if (onSetItemValue != null) {
|
||||
onSetItemValue.accept(oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder<I, B extends ListConfigNode.Builder<I, B>> extends ConfigNode.Builder<List<I>, B> {
|
||||
|
||||
protected final @NotNull Class<I> itemType;
|
||||
protected @Nullable NodeSuggester itemSuggester;
|
||||
protected @Nullable NodeStringParser<I> itemStringParser;
|
||||
protected @Nullable NodeSerializer<I> itemSerializer;
|
||||
protected @Nullable Function<I, Try<Void>> itemValidator;
|
||||
protected @Nullable BiConsumer<I, I> onSetItemValue;
|
||||
|
||||
/**
|
||||
* Creates a new builder.
|
||||
*
|
||||
* @param path The path of the node.
|
||||
* @param itemType The type of the item value in list.
|
||||
*/
|
||||
protected Builder(@NotNull String path, @NotNull Class<I> itemType) {
|
||||
//noinspection unchecked
|
||||
super(path, (Class<List<I>>) (Object) List.class);
|
||||
this.itemType = itemType;
|
||||
this.defaultValueSupplier = () -> (List<I>) new ArrayList<Object>();
|
||||
}
|
||||
|
||||
public @NotNull B itemSuggester(@NotNull NodeSuggester itemSuggester) {
|
||||
this.itemSuggester = itemSuggester;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull B itemStringParser(@NotNull NodeStringParser<I> itemStringParser) {
|
||||
this.itemStringParser = itemStringParser;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializer for the node.
|
||||
*
|
||||
* @param serializer The serializer for the node.
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B itemSerializer(@NotNull NodeSerializer<I> serializer) {
|
||||
this.itemSerializer = serializer;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the validator for the node.
|
||||
*
|
||||
* @param itemValidator The validator for the node.
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B itemValidator(@NotNull Function<I, Try<Void>> itemValidator) {
|
||||
this.itemValidator = itemValidator;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the onSetValue for the node.
|
||||
*
|
||||
* @param onSetItemValue The onSetValue for the node.
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B onSetItemValue(@Nullable BiConsumer<I, I> onSetItemValue) {
|
||||
this.onSetItemValue = onSetItemValue;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull ListConfigNode<I> build() {
|
||||
return new ListConfigNode<>(
|
||||
path,
|
||||
comments.toArray(new String[0]),
|
||||
name,
|
||||
type,
|
||||
defaultValueSupplier,
|
||||
suggester,
|
||||
stringParser,
|
||||
serializer,
|
||||
validator,
|
||||
onSetValue,
|
||||
itemType,
|
||||
itemSuggester, itemStringParser, itemSerializer,
|
||||
itemValidator,
|
||||
onSetItemValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeSerializer;
|
||||
|
||||
public interface ListValueNode<I> extends ValueNode<List<I>> {
|
||||
|
||||
/**
|
||||
* Gets the class type of list item.
|
||||
*
|
||||
* @return The class type of list item.
|
||||
*/
|
||||
@NotNull Class<I> getItemType();
|
||||
|
||||
/**
|
||||
* Suggests possible string values for this node.
|
||||
*
|
||||
* @param input The input string.
|
||||
* @return A collection of possible string values.
|
||||
*/
|
||||
@NotNull Collection<String> suggestItem(@Nullable String input);
|
||||
|
||||
/**
|
||||
* Parses the given string into a value of type {@link I}. Used for property set by user input.
|
||||
*
|
||||
* @param input The string to parse.
|
||||
* @return The parsed value, or given exception if parsing failed.
|
||||
*/
|
||||
@NotNull Try<I> parseItemFromString(@Nullable String input);
|
||||
|
||||
/**
|
||||
* Gets the serializer for this node.
|
||||
*
|
||||
* @return The serializer for this node.
|
||||
*/
|
||||
@Nullable NodeSerializer<I> getItemSerializer();
|
||||
|
||||
/**
|
||||
* Validates the value of this node.
|
||||
*
|
||||
* @param value The value to validate.
|
||||
* @return True if the value is valid, false otherwise.
|
||||
*/
|
||||
Try<Void> validateItem(@Nullable I value);
|
||||
|
||||
/**
|
||||
* Called when the value of this node is set.
|
||||
*
|
||||
* @param oldValue The old value.
|
||||
* @param newValue The new value.
|
||||
*/
|
||||
void onSetItemValue(@Nullable I oldValue, @Nullable I newValue);
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
|
||||
import io.vavr.control.Option;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A collection of {@link CommentedNode}s, with mappings to nodes by name.
|
||||
@@ -49,10 +50,6 @@ public class NodeGroup implements Collection<Node> {
|
||||
return nodesMap.keySet();
|
||||
}
|
||||
|
||||
public Map<String, Node> getNodesMap() {
|
||||
return nodesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node with the given name.
|
||||
*
|
||||
@@ -68,9 +65,10 @@ public class NodeGroup implements Collection<Node> {
|
||||
*
|
||||
* @param name The name of the node to get.
|
||||
* @param type The type of the node to get.
|
||||
* @param <T> The type of the node.
|
||||
* @return The node with the given name, or {@link Option.None} if no node with the given name exists.
|
||||
*/
|
||||
public <T extends Node> Option<T> findNode(String name, Class<T> type) {
|
||||
public <T extends Node> @NotNull Option<T> findNode(@Nullable String name, @NotNull Class<T> type) {
|
||||
return Option.of(nodesMap.get(name)).map(node -> type.isAssignableFrom(node.getClass()) ? (T) node : null);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.functions.NodeSerializer;
|
||||
|
||||
public interface ValueNode<T> extends Node {
|
||||
|
||||
/**
|
||||
@@ -28,6 +32,22 @@ public interface ValueNode<T> extends Node {
|
||||
*/
|
||||
@Nullable T getDefaultValue();
|
||||
|
||||
/**
|
||||
* Suggests possible string values for this node.
|
||||
*
|
||||
* @param input The input string.
|
||||
* @return A collection of possible string values.
|
||||
*/
|
||||
@NotNull Collection<String> suggest(@Nullable String input);
|
||||
|
||||
/**
|
||||
* Parses the given string into a value of type {@link T}. Used for property set by user input.
|
||||
*
|
||||
* @param input The string to parse.
|
||||
* @return The parsed value, or given exception if parsing failed.
|
||||
*/
|
||||
@NotNull Try<T> parseFromString(@Nullable String input);
|
||||
|
||||
/**
|
||||
* Gets the serializer for this node.
|
||||
*
|
||||
|
||||
@@ -11,8 +11,10 @@ import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.world.config.AllowedPortalType;
|
||||
import org.mvplugins.multiverse.core.world.config.WorldConfig;
|
||||
|
||||
@@ -66,6 +68,15 @@ public class MultiverseWorld {
|
||||
return worldConfig.getConfigurablePropertyNames();
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames(ConfigModifyType configModifyType) {
|
||||
return worldConfig.getConfigurablePropertyNames(configModifyType);
|
||||
}
|
||||
|
||||
public Collection<String> suggestPropertyValues(
|
||||
@NotNull ConfigModifyType type, @Nullable String name, @Nullable String input) {
|
||||
return worldConfig.suggestPropertyValues(type, name, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property on this world.
|
||||
*
|
||||
@@ -76,6 +87,10 @@ public class MultiverseWorld {
|
||||
return worldConfig.getProperty(name);
|
||||
}
|
||||
|
||||
public Try<Void> modifyProperty(ConfigModifyType type, String name, String value) {
|
||||
return worldConfig.modifyProperty(type, name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a property on this world.
|
||||
*
|
||||
|
||||
@@ -737,6 +737,17 @@ public class WorldManager {
|
||||
return !isLoadedWorld(worldName) && isWorld(worldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a world that may or may not be loaded. It will an {@link LoadedMultiverseWorld} if the world is loaded,
|
||||
* otherwise returns an {@link MultiverseWorld} instance.
|
||||
*
|
||||
* @param world The bukkit world to get.
|
||||
* @return The world if it exists.
|
||||
*/
|
||||
public Option<MultiverseWorld> getWorld(@Nullable World world) {
|
||||
return world == null ? Option.none() : getWorld(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a world that may or may not be loaded. It will an {@link LoadedMultiverseWorld} if the world is loaded,
|
||||
* otherwise returns an {@link MultiverseWorld} instance.
|
||||
|
||||
@@ -14,6 +14,8 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.MultiverseCore;
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigurationSectionHandle;
|
||||
import org.mvplugins.multiverse.core.configuration.migration.BooleanMigratorAction;
|
||||
import org.mvplugins.multiverse.core.configuration.migration.ConfigMigrator;
|
||||
@@ -23,7 +25,6 @@ import org.mvplugins.multiverse.core.configuration.migration.MoveMigratorAction;
|
||||
import org.mvplugins.multiverse.core.configuration.migration.NullStringMigratorAction;
|
||||
import org.mvplugins.multiverse.core.configuration.migration.VersionMigrator;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.helpers.EnforcementHandler;
|
||||
|
||||
/**
|
||||
* Represents a world configuration.
|
||||
@@ -37,9 +38,9 @@ public final class WorldConfig {
|
||||
WorldConfig(
|
||||
@NotNull String worldName,
|
||||
@NotNull ConfigurationSection configSection,
|
||||
@NotNull EnforcementHandler enforcementHandler) {
|
||||
@NotNull MultiverseCore multiverseCore) {
|
||||
this.worldName = worldName;
|
||||
this.configNodes = new WorldConfigNodes(enforcementHandler);
|
||||
this.configNodes = new WorldConfigNodes(multiverseCore);
|
||||
this.configHandle = ConfigurationSectionHandle.builder(configSection)
|
||||
.logger(Logging.getLogger())
|
||||
.nodes(configNodes.getNodes())
|
||||
@@ -115,15 +116,32 @@ public final class WorldConfig {
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames() {
|
||||
return configNodes.getNodes().getNames();
|
||||
return configHandle.getPropertyNames();
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames(ConfigModifyType configModifyType) {
|
||||
return configHandle.getPropertyNames(configModifyType);
|
||||
}
|
||||
|
||||
public Try<Class> getPropertyType(String name) {
|
||||
return configHandle.getPropertyType(name);
|
||||
}
|
||||
|
||||
public Collection<String> suggestPropertyValues(
|
||||
@NotNull ConfigModifyType type, @Nullable String name, @Nullable String input) {
|
||||
return configHandle.suggestPropertyValues(type, name, input);
|
||||
}
|
||||
|
||||
public Try<Object> getProperty(String name) {
|
||||
return configHandle.get(name);
|
||||
return configHandle.getProperty(name);
|
||||
}
|
||||
|
||||
public Try<Void> modifyProperty(ConfigModifyType type, String name, String value) {
|
||||
return configHandle.modifyProperty(type, name, value);
|
||||
}
|
||||
|
||||
public Try<Void> setProperty(String name, Object value) {
|
||||
return configHandle.set(name, value);
|
||||
return configHandle.setProperty(name, value);
|
||||
}
|
||||
|
||||
public boolean getAdjustSpawn() {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package org.mvplugins.multiverse.core.world.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
@@ -10,11 +7,14 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.mvplugins.multiverse.core.MultiverseCore;
|
||||
import org.mvplugins.multiverse.core.configuration.node.ConfigNode;
|
||||
import org.mvplugins.multiverse.core.configuration.node.ListConfigNode;
|
||||
import org.mvplugins.multiverse.core.configuration.node.Node;
|
||||
import org.mvplugins.multiverse.core.configuration.node.NodeGroup;
|
||||
import org.mvplugins.multiverse.core.world.config.AllowedPortalType;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.helpers.EnforcementHandler;
|
||||
|
||||
/**
|
||||
@@ -25,10 +25,12 @@ public class WorldConfigNodes {
|
||||
|
||||
private final NodeGroup nodes = new NodeGroup();
|
||||
private EnforcementHandler enforcementHandler;
|
||||
private WorldManager worldManager;
|
||||
private LoadedMultiverseWorld world = null;
|
||||
|
||||
WorldConfigNodes(@NotNull EnforcementHandler enforcementHandler) {
|
||||
this.enforcementHandler = enforcementHandler;
|
||||
WorldConfigNodes(@NotNull MultiverseCore multiverseCore) {
|
||||
this.enforcementHandler = multiverseCore.getService(EnforcementHandler.class);
|
||||
this.worldManager = multiverseCore.getService(WorldManager.class);
|
||||
}
|
||||
|
||||
LoadedMultiverseWorld getWorld() {
|
||||
@@ -212,9 +214,8 @@ public class WorldConfigNodes {
|
||||
})
|
||||
.build());
|
||||
|
||||
final ConfigNode<List> SPAWNING_ANIMALS_EXCEPTIONS = node(ConfigNode
|
||||
.builder("spawning.animals.exceptions", List.class)
|
||||
.defaultValue(new ArrayList<>())
|
||||
final ListConfigNode<String> SPAWNING_ANIMALS_EXCEPTIONS = node(ListConfigNode
|
||||
.listBuilder("spawning.animals.exceptions", String.class)
|
||||
.name("spawning-animals-exceptions")
|
||||
.build());
|
||||
|
||||
@@ -238,14 +239,14 @@ public class WorldConfigNodes {
|
||||
})
|
||||
.build());
|
||||
|
||||
final ConfigNode<List> SPAWNING_MONSTERS_EXCEPTIONS = node(ConfigNode
|
||||
.builder("spawning.monsters.exceptions", List.class)
|
||||
.defaultValue(new ArrayList<>())
|
||||
final ListConfigNode<String> SPAWNING_MONSTERS_EXCEPTIONS = node(ListConfigNode
|
||||
.listBuilder("spawning.monsters.exceptions", String.class)
|
||||
.name("spawning-monsters-exceptions")
|
||||
.build());
|
||||
|
||||
final ConfigNode<List> WORLD_BLACKLIST = node(ConfigNode.builder("world-blacklist", List.class)
|
||||
.defaultValue(new ArrayList<>())
|
||||
final ListConfigNode<String> WORLD_BLACKLIST = node(ListConfigNode
|
||||
.listBuilder("world-blacklist", String.class)
|
||||
.itemSuggester(input -> worldManager.getWorlds().stream().map(MultiverseWorld::getName).toList())
|
||||
.build());
|
||||
|
||||
final ConfigNode<Double> VERSION = node(ConfigNode.builder("version", Double.class)
|
||||
|
||||
@@ -33,16 +33,14 @@ public final class WorldsConfigManager {
|
||||
|
||||
private final Map<String, WorldConfig> worldConfigMap;
|
||||
private final File worldConfigFile;
|
||||
private final MultiverseCore multiverseCore;
|
||||
private YamlConfiguration worldsConfig;
|
||||
|
||||
private final EnforcementHandler enforcementHandler;
|
||||
|
||||
@Inject
|
||||
WorldsConfigManager(@NotNull MultiverseCore core, @NotNull EnforcementHandler enforcementHandler) {
|
||||
WorldsConfigManager(@NotNull MultiverseCore multiverseCore) {
|
||||
worldConfigMap = new HashMap<>();
|
||||
worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
|
||||
|
||||
this.enforcementHandler = enforcementHandler;
|
||||
worldConfigFile = multiverseCore.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
|
||||
this.multiverseCore = multiverseCore;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +126,7 @@ public final class WorldsConfigManager {
|
||||
WorldConfig newWorldConfig = new WorldConfig(
|
||||
worldName,
|
||||
getWorldConfigSection(worldName),
|
||||
enforcementHandler);
|
||||
multiverseCore);
|
||||
worldConfigMap.put(worldName, newWorldConfig);
|
||||
newWorldsAdded.add(newWorldConfig);
|
||||
});
|
||||
@@ -183,7 +181,7 @@ public final class WorldsConfigManager {
|
||||
if (worldConfigMap.containsKey(worldName)) {
|
||||
throw new IllegalArgumentException("WorldConfig for world " + worldName + " already exists.");
|
||||
}
|
||||
WorldConfig worldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName), enforcementHandler);
|
||||
WorldConfig worldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName), multiverseCore);
|
||||
worldConfigMap.put(worldName, worldConfig);
|
||||
return worldConfig;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user