mirror of
https://github.com/Multiverse/Multiverse-Core.git
synced 2024-11-28 13:36:21 +01:00
Implement support for property modification with ConfigModifyType and ListValueNode
This commit is contained in:
parent
6f014838e9
commit
94b1e77a98
@ -0,0 +1,73 @@
|
||||
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.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.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.commandtools.context.WorldConfigValue;
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.worldnew.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.worldnew.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,
|
||||
|
||||
@Syntax("[value]")
|
||||
@Description("")
|
||||
WorldConfigValue propertyValue) {
|
||||
Logging.fine("ModifyCommand.onModifyCommand: world=%s, configModifyType=%s, propertyName=%s, propertyValue=%s",
|
||||
world, configModifyType, propertyName, propertyValue);
|
||||
|
||||
world.modifyProperty(configModifyType, propertyName, propertyValue.getValue()).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.getValue() + " 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.worldnew.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,41 @@ 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) {
|
||||
//noinspection unchecked
|
||||
return Try.of(() -> {
|
||||
MultiverseWorld mvWorld = context.getContextValue(MultiverseWorld.class);
|
||||
String propertyName = context.getContextValue(String.class);
|
||||
Class type = mvWorld.getPropertyType(propertyName).get();
|
||||
if (type.isEnum()) {
|
||||
return suggestEnums(type);
|
||||
}
|
||||
if (type == Boolean.class) {
|
||||
return List.of("true", "false");
|
||||
}
|
||||
if (type == Integer.class) {
|
||||
return List.of("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||
}
|
||||
if (type == Double.class) {
|
||||
return List.of("0.0", "1.0", "2.0", "3.0", "4.0", "5.0");
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}).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();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package org.mvplugins.multiverse.core.commandtools;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import co.aikar.commands.BukkitCommandExecutionContext;
|
||||
@ -8,8 +11,10 @@ import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import co.aikar.commands.PaperCommandContexts;
|
||||
import co.aikar.commands.contexts.ContextResolver;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.google.common.base.Strings;
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -17,7 +22,9 @@ import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.commandtools.context.GameRuleValue;
|
||||
import org.mvplugins.multiverse.core.commandtools.context.MVConfigValue;
|
||||
import org.mvplugins.multiverse.core.commandtools.context.WorldConfigValue;
|
||||
import org.mvplugins.multiverse.core.config.MVCoreConfig;
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.configuration.node.Node;
|
||||
import org.mvplugins.multiverse.core.configuration.node.ValueNode;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
|
||||
@ -27,10 +34,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.worldnew.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.worldnew.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.worldnew.WorldManager;
|
||||
|
||||
@Service
|
||||
public class MVCommandContexts extends PaperCommandContexts {
|
||||
class MVCommandContexts extends PaperCommandContexts {
|
||||
|
||||
private final MVCommandManager mvCommandManager;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
@ -38,12 +46,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,10 +64,12 @@ 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);
|
||||
registerIssuerAwareContext(WorldConfigValue.class, this::parseWorldConfigValue);
|
||||
}
|
||||
|
||||
private MVCommandIssuer parseMVCommandIssuer(BukkitCommandExecutionContext context) {
|
||||
@ -162,13 +171,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 +187,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 +196,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 +216,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 +366,6 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
throw new InvalidCommandArgument("Player " + playerIdentifier + " not found.");
|
||||
}
|
||||
|
||||
|
||||
private Player[] parsePlayerArray(BukkitCommandExecutionContext context) {
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
@ -353,4 +409,50 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
}
|
||||
throw new InvalidCommandArgument("Player " + playerIdentifier + " not found.");
|
||||
}
|
||||
|
||||
private WorldConfigValue parseWorldConfigValue(BukkitCommandExecutionContext context) {
|
||||
MultiverseWorld mvWorld = (MultiverseWorld) context.getResolvedArg(MultiverseWorld.class);
|
||||
ConfigModifyType modifyType = (ConfigModifyType) context.getResolvedArg(ConfigModifyType.class);
|
||||
String propertyName = (String) context.getResolvedArg(String.class);
|
||||
if (mvWorld == null || modifyType == null || propertyName == null) {
|
||||
throw new InvalidCommandArgument("No world or property specified.");
|
||||
}
|
||||
|
||||
if (modifyType == ConfigModifyType.RESET) {
|
||||
if (context.popFirstArg() != null) {
|
||||
throw new InvalidCommandArgument("No value should be specified for reset.");
|
||||
}
|
||||
return new WorldConfigValue(null);
|
||||
}
|
||||
|
||||
Class<?> type = mvWorld.getPropertyType(propertyName)
|
||||
.getOrElseThrow(() -> {
|
||||
return new InvalidCommandArgument("The property " + propertyName + " is not valid for world "
|
||||
+ mvWorld.getName() + ".");
|
||||
});
|
||||
return new WorldConfigValue(parseType(context, type));
|
||||
}
|
||||
|
||||
private Object parseType(BukkitCommandExecutionContext context, Class<?> type) {
|
||||
Object value = context.getFirstArg();
|
||||
if (value == null) {
|
||||
throw new InvalidCommandArgument("No value specified.");
|
||||
}
|
||||
|
||||
// Special case for enums
|
||||
if (type.isEnum()) {
|
||||
return Try.of(() -> Enum.valueOf((Class<? extends Enum>) type, context.popFirstArg().toUpperCase()))
|
||||
.getOrElseThrow(() -> new InvalidCommandArgument(("The value %s is not a valid %s. "
|
||||
+ "Valid values are: %s").formatted(
|
||||
value,
|
||||
type.getSimpleName(),
|
||||
Arrays.stream(((Class<? extends Enum>) type).getEnumConstants())
|
||||
.map(enumValue -> enumValue.name().toLowerCase())
|
||||
.reduce((a, b) -> a + ", " + b)
|
||||
.orElse(""))));
|
||||
}
|
||||
|
||||
ContextResolver<?, BukkitCommandExecutionContext> resolver = getResolver(type);
|
||||
return resolver == null ? value : resolver.getContext(context);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -0,0 +1,20 @@
|
||||
package org.mvplugins.multiverse.core.commandtools.context;
|
||||
|
||||
public class WorldConfigValue {
|
||||
private final Object value;
|
||||
|
||||
public WorldConfigValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WorldConfigValue{"
|
||||
+ "value=" + value
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
package org.mvplugins.multiverse.core.configuration.handle;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
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 +13,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 +22,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,8 +71,36 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
});
|
||||
}
|
||||
|
||||
public Collection<String> getNames() {
|
||||
return nodes.getNames();
|
||||
}
|
||||
|
||||
public Collection<String> getNamesThatSupports(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> getTypeByName(@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));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@ -78,17 +110,10 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
.map(node -> get((ValueNode<Object>) node));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public <T> T get(@NotNull ValueNode<T> node) {
|
||||
if (node.getSerializer() == null) {
|
||||
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
|
||||
}
|
||||
return node.getSerializer().deserialize(config.get(node.getPath(), node.getDefaultValue()), node.getType());
|
||||
public Try<Void> modify(@NotNull ConfigModifyType type, @Nullable String name, @Nullable Object value) {
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.flatMapTry(node -> modify(type, node, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,9 +124,68 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
* @return True if the value was set, false otherwise.
|
||||
*/
|
||||
public Try<Void> set(@Nullable String name, Object value) {
|
||||
//noinspection unchecked
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.flatMap(node -> set(node, value));
|
||||
.flatMapTry(node -> set(node, value));
|
||||
}
|
||||
|
||||
public Try<Void> add(@Nullable String name, Object value) {
|
||||
//noinspection unchecked
|
||||
return nodes.findNode(name, ListValueNode.class)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.flatMapTry(node -> add(node, value));
|
||||
}
|
||||
|
||||
public Try<Void> remove(@Nullable String name, Object value) {
|
||||
//noinspection unchecked
|
||||
return nodes.findNode(name, ListValueNode.class)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.flatMapTry(node -> remove(node, value));
|
||||
}
|
||||
|
||||
public Try<Void> reset(@Nullable String name) {
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.toTry(() -> new ConfigNodeNotFoundException(name))
|
||||
.flatMapTry(this::reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (node.getSerializer() == null) {
|
||||
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
|
||||
}
|
||||
return node.getSerializer().deserialize(config.get(node.getPath(), node.getDefaultValue()), node.getType());
|
||||
}
|
||||
|
||||
public Try<Void> modify(@NotNull ConfigModifyType type, @NotNull ValueNode node, @Nullable Object value) {
|
||||
return switch (type) {
|
||||
case SET -> set(node, value);
|
||||
case REMOVE -> {
|
||||
if (!(node instanceof ListValueNode listNode)) {
|
||||
yield Try.failure(new IllegalArgumentException("Node is not a list"));
|
||||
}
|
||||
yield remove(listNode, value);
|
||||
}
|
||||
case ADD -> {
|
||||
if (!(node instanceof ListValueNode listNode)) {
|
||||
yield Try.failure(new IllegalArgumentException("Node is not a list"));
|
||||
}
|
||||
yield add(listNode, value);
|
||||
}
|
||||
case RESET -> {
|
||||
if (value != null) {
|
||||
yield Try.failure(new IllegalArgumentException("Reset type cannot have a value"));
|
||||
}
|
||||
yield reset(node);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,30 +193,62 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
*
|
||||
* @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 +263,8 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
||||
protected @Nullable NodeGroup nodes;
|
||||
protected @Nullable ConfigMigrator migrator;
|
||||
|
||||
protected Builder() {}
|
||||
protected Builder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
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;
|
||||
@ -10,6 +11,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A node that contains a value.
|
||||
*
|
||||
* @param <T> The type of the value.
|
||||
*/
|
||||
public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
@ -19,19 +21,18 @@ 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 Supplier<T> defaultValueSupplier;
|
||||
protected final @Nullable NodeSerializer<T> serializer;
|
||||
protected final @Nullable Function<T, Try<Void>> validator;
|
||||
protected final @Nullable BiConsumer<T, T> onSetValue;
|
||||
@ -41,15 +42,14 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
@NotNull String[] comments,
|
||||
@Nullable String name,
|
||||
@NotNull Class<T> type,
|
||||
@Nullable T defaultValue,
|
||||
@Nullable Supplier<T> defaultValueSupplier,
|
||||
@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.defaultValueSupplier = defaultValueSupplier;
|
||||
this.serializer = serializer;
|
||||
this.validator = validator;
|
||||
this.onSetValue = onSetValue;
|
||||
@ -76,7 +76,7 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
*/
|
||||
@Override
|
||||
public @Nullable T getDefaultValue() {
|
||||
return defaultValue;
|
||||
return defaultValueSupplier != null ? defaultValueSupplier.get() : null;
|
||||
}
|
||||
|
||||
public @Nullable NodeSerializer<T> getSerializer() {
|
||||
@ -115,7 +115,7 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
|
||||
protected @Nullable String name;
|
||||
protected @NotNull final Class<T> type;
|
||||
protected @Nullable T defaultValue;
|
||||
protected @Nullable Supplier<T> defaultValueSupplier;
|
||||
protected @Nullable NodeSerializer<T> serializer;
|
||||
protected @Nullable Function<T, Try<Void>> validator;
|
||||
protected @Nullable BiConsumer<T, T> onSetValue;
|
||||
@ -142,8 +142,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 +165,17 @@ 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 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 +186,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 +194,15 @@ 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,
|
||||
serializer,
|
||||
validator,
|
||||
onSetValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,190 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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 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 NodeSerializer<List<I>> serializer,
|
||||
@Nullable Function<List<I>, Try<Void>> validator,
|
||||
@Nullable BiConsumer<List<I>, List<I>> onSetValue,
|
||||
@NotNull Class<I> itemType,
|
||||
@Nullable NodeSerializer<I> itemSerializer,
|
||||
@Nullable Function<I, Try<Void>> itemValidator,
|
||||
@Nullable BiConsumer<I, I> onSetItemValue) {
|
||||
super(path, comments, name, type, defaultValueSupplier, serializer, validator, onSetValue);
|
||||
this.itemType = itemType;
|
||||
this.itemSerializer = itemSerializer;
|
||||
this.itemValidator = itemValidator;
|
||||
this.onSetItemValue = onSetItemValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Class<I> getItemType() {
|
||||
return 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 NodeSerializer<I> itemSerializer;
|
||||
protected Function<I, Try<Void>> itemValidator;
|
||||
protected 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>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializer for the node.
|
||||
*
|
||||
* @param serializer The serializer for the node.
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B itemSerializer(@Nullable NodeSerializer<I> serializer) {
|
||||
this.itemSerializer = serializer;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the validator for the node.
|
||||
*
|
||||
* @param validator The validator for the node.
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B itemValidator(@Nullable Function<I, Try<Void>> validator) {
|
||||
this.itemValidator = validator;
|
||||
if (validator == null) {
|
||||
setDefaultValidator();
|
||||
}
|
||||
return self();
|
||||
}
|
||||
|
||||
private void setDefaultValidator() {
|
||||
this.validator = value -> {
|
||||
if (value != null) {
|
||||
return Try.sequence(value.stream().map(itemValidator).toList()).map(v -> null);
|
||||
}
|
||||
return Try.success(null);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the onSetValue for the node.
|
||||
*
|
||||
* @param onSetValue The onSetValue for the node.
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NotNull B onSetItemValue(@Nullable BiConsumer<I, I> onSetValue) {
|
||||
this.onSetItemValue = onSetValue;
|
||||
if (onSetValue == null) {
|
||||
setDefaultOnSetValue();
|
||||
}
|
||||
return self();
|
||||
}
|
||||
|
||||
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 ListConfigNode<I> build() {
|
||||
return new ListConfigNode<>(
|
||||
path,
|
||||
comments.toArray(new String[0]),
|
||||
name,
|
||||
type,
|
||||
defaultValueSupplier,
|
||||
serializer,
|
||||
validator,
|
||||
onSetValue,
|
||||
itemType,
|
||||
itemSerializer,
|
||||
itemValidator,
|
||||
onSetItemValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.mvplugins.multiverse.core.configuration.node;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.world.configuration.AllowedPortalType;
|
||||
import org.mvplugins.multiverse.core.worldnew.config.WorldConfig;
|
||||
|
||||
@ -66,6 +67,14 @@ public class MultiverseWorld {
|
||||
return worldConfig.getConfigurablePropertyNames();
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames(ConfigModifyType configModifyType) {
|
||||
return worldConfig.getConfigurablePropertyNames(configModifyType);
|
||||
}
|
||||
|
||||
public Try<Class> getPropertyType(String name) {
|
||||
return worldConfig.getPropertyType(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property on this world.
|
||||
*
|
||||
@ -87,6 +96,10 @@ public class MultiverseWorld {
|
||||
return worldConfig.setProperty(name, value);
|
||||
}
|
||||
|
||||
public Try<Void> modifyProperty(ConfigModifyType type, String name, Object value) {
|
||||
return worldConfig.modifyProperty(type, name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not Multiverse should auto-adjust the spawn for 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,7 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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;
|
||||
@ -116,7 +117,15 @@ public final class WorldConfig {
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames() {
|
||||
return configNodes.getNodes().getNames();
|
||||
return configHandle.getNames();
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames(ConfigModifyType configModifyType) {
|
||||
return configHandle.getNamesThatSupports(configModifyType);
|
||||
}
|
||||
|
||||
public Try<Class> getPropertyType(String name) {
|
||||
return configHandle.getTypeByName(name);
|
||||
}
|
||||
|
||||
public Try<Object> getProperty(String name) {
|
||||
@ -127,6 +136,10 @@ public final class WorldConfig {
|
||||
return configHandle.set(name, value);
|
||||
}
|
||||
|
||||
public Try<Void> modifyProperty(ConfigModifyType type, String name, Object value) {
|
||||
return configHandle.modify(type, name, value);
|
||||
}
|
||||
|
||||
public boolean getAdjustSpawn() {
|
||||
return configHandle.get(configNodes.ADJUST_SPAWN);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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.configuration.AllowedPortalType;
|
||||
@ -212,9 +213,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 +238,13 @@ 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)
|
||||
.build());
|
||||
|
||||
final ConfigNode<Double> VERSION = node(ConfigNode.builder("version", Double.class)
|
||||
|
Loading…
Reference in New Issue
Block a user