Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ public boolean persist() {
case "generator" -> world.getGenerator();
case "hunger" -> String.valueOf(world.isHunger());
case "isloaded" -> String.valueOf(world.isLoaded());
case "key" -> String.valueOf(world.getKey());
case "meta" -> {
if (placeholderParams.isEmpty()) {
warning("No meta key specified.");
yield null;
}
String metaKey = String.join("_", placeholderParams);
yield world.getMeta(metaKey)
.getOrElse(() -> {
warning("Meta key '" + metaKey + "' not found for world '" + world.getName() + "'.");
return null;
});
}
case "monstersspawn" -> String.valueOf(world.getEntitySpawnConfig()
.getSpawnCategoryConfig(SpawnCategory.MONSTER)
.isSpawn());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public class MVCommandCompletions extends PaperCommandCompletions {
registerStaticCompletion("mvconfigs", config.getStringPropertyHandle().getAllPropertyNames());
registerAsyncCompletion("mvconfigvalues", this::suggestMVConfigValues);
registerAsyncCompletion("mvworlds", this::suggestMVWorlds);
registerAsyncCompletion("mvworldmetakey", this::suggestMVWorldMetaKey);
registerAsyncCompletion("mvworldpropsname", this::suggestMVWorldPropsName);
registerAsyncCompletion("mvworldpropsvalue", this::suggestMVWorldPropsValue);
registerCompletion("playersarray", this::suggestPlayersArray); // getting online players cannot be async
Expand Down Expand Up @@ -308,6 +309,13 @@ private Collection<String> suggestMVWorlds(BukkitCommandCompletionContext contex
return Collections.emptyList();
}

private Collection<String> suggestMVWorldMetaKey(BukkitCommandCompletionContext context) {
return Try.of(() -> context.getContextValue(MultiverseWorld.class))
.map(MultiverseWorld::getAllMeta)
.map(Map::keySet)
.getOrElse(Collections.emptySet());
}

private Collection<String> suggestMVWorldPropsName(BukkitCommandCompletionContext context) {
return Try.of(() -> {
MultiverseWorld world = context.getContextValue(MultiverseWorldValue.class).value();
Expand Down
121 changes: 121 additions & 0 deletions src/main/java/org/mvplugins/multiverse/core/commands/MetaCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package org.mvplugins.multiverse.core.commands;

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.Optional;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import jakarta.inject.Inject;
import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
import org.mvplugins.multiverse.core.command.flags.PageFilterFlags;
import org.mvplugins.multiverse.core.display.ContentDisplay;
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
import org.mvplugins.multiverse.core.display.parsers.MapContentProvider;
import org.mvplugins.multiverse.core.locale.MVCorei18n;
import org.mvplugins.multiverse.core.locale.message.Message;
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
import org.mvplugins.multiverse.core.world.MultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;

import java.util.Locale;

import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;

@Service
@Subcommand("meta")
final class MetaCommand extends CoreCommand {

private final WorldManager worldManager;
private final PageFilterFlags flags;

@Inject
MetaCommand(@NotNull WorldManager worldManager, @NotNull PageFilterFlags flags) {
this.worldManager = worldManager;
this.flags = flags;
}

@Subcommand("info")
@CommandPermission("multiverse.core.meta.info")
@CommandCompletion("@mvworlds:scope=both|@flags:resolveUntil=arg1,groupName=" + PageFilterFlags.NAME + " " +
"@flags:groupName=" + PageFilterFlags.NAME)
@Syntax("[world] [--page <page>] [--filter <filter>]")
@Description("{@@mv-core.meta.info.description}")
void infoCommand(
MVCommandIssuer issuer,

@Flags("resolve=issuerAware,maxArgForAware=0")
@Syntax("[world]")
@Description("{@@mv-core.meta.info.world.description}")
MultiverseWorld world,

@Optional
@Syntax("[--page <page>] [--filter <filter>]")
String[] flagArray
) {
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
ContentDisplay.create()
.addContent(MapContentProvider.forContent(world.getAllMeta())
.withKeyColor(ChatColor.AQUA)
.withValueColor(ChatColor.WHITE))
.withSendHandler(PagedSendHandler.create()
.withHeader(Message.of(MVCorei18n.META_INFO_HEADER, replace("{world}").with(world.getName())))
.noContentMessage(Message.of(MVCorei18n.META_INFO_NOCONTENT, replace("{world}").with(world.getName())))
.withTargetPage(parsedFlags.flagValue(flags.page, 1))
.withFilter(parsedFlags.flagValue(flags.filter, DefaultContentFilter.get())))
.send(issuer);
}

@Subcommand("modify")
@CommandPermission("multiverse.core.meta.modify")
@CommandCompletion("@mvworlds:scope=both set|remove @mvworldmetakey @empty")
@Syntax("[world] <set|remove> <key> [value]")
void modifyCommand(
MVCommandIssuer issuer,

@Flags("resolve=issuerAware,maxArgForAware=4")
@Syntax("[world]")
MultiverseWorld world,

@Syntax("<set|remove>")
String action,

@Syntax("<key>")
String key,

@Optional
@Single
@Syntax("[value]")
String value
) {
switch (action.toLowerCase(Locale.ROOT)) {
case "set" -> world.setMeta(key, value)
.onSuccess(ignore -> issuer.sendInfo(MVCorei18n.META_MODIFY_SET_SUCCESS,
replace("{key}").with(key),

Check failure on line 101 in src/main/java/org/mvplugins/multiverse/core/commands/MetaCommand.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "{key}" 4 times.

See more on https://sonarcloud.io/project/issues?id=Multiverse_Multiverse-Core&issues=AZ4B4FhIsdPLneVpMsNK&open=AZ4B4FhIsdPLneVpMsNK&pullRequest=3469
replace("{value}").with(value),
Replace.WORLD.with(world.getName())))
.onFailure(throwable -> issuer.sendError(MVCorei18n.META_MODIFY_SET_FAILURE,
replace("{key}").with(key),
replace("{value}").with(value),
Replace.WORLD.with(world.getName()),
Replace.ERROR.with(throwable)));
case "remove" -> world.removeMeta(key)
.onSuccess(ignore -> issuer.sendInfo(MVCorei18n.META_MODIFY_REMOVE_SUCCESS,
replace("{key}").with(key),
Replace.WORLD.with(world.getName())))
.onFailure(throwable -> issuer.sendError(MVCorei18n.META_MODIFY_REMOVE_FAILURE,
replace("{key}").with(key),
Replace.WORLD.with(world.getName()),
Replace.ERROR.with(throwable)));
default -> issuer.sendError(MVCorei18n.META_MODIFY_INVALIDACTION, replace("{action}").with(action));
}
worldManager.saveWorldsConfig();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Logger;

import com.dumptruckman.minecraft.util.Logging;
import io.vavr.control.Option;
import io.vavr.control.Try;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
Expand All @@ -19,6 +17,7 @@

import org.mvplugins.multiverse.core.config.migration.ConfigMigrator;
import org.mvplugins.multiverse.core.config.node.ListValueNode;
import org.mvplugins.multiverse.core.config.node.MapValueNode;
import org.mvplugins.multiverse.core.config.node.NodeGroup;
import org.mvplugins.multiverse.core.config.node.ValueNode;

Expand Down Expand Up @@ -93,17 +92,13 @@
}

protected <T> T deserializeNodeFromConfig(ValueNode<T> node) {
if (node.getSerializer() == null) {
return Option.of(config.getObject(node.getPath(), node.getType())).getOrElse(node::getDefaultValue);
}
return Try.of(() -> {
var value = config.get(node.getPath());
if (value == null) {
return node.getDefaultValue();
}
return node.getSerializer().deserialize(value, node.getType());
}).flatMap(value -> node.validate(value).map(ignore -> value))
.onFailure(e -> Logging.warning("Failed to deserialize node %s: %s", node.getPath(), e.getMessage()))
return value == null ? node.getDefaultValue() : node.deserialize(value);

Check warning on line 97 in src/main/java/org/mvplugins/multiverse/core/config/handle/BaseConfigurationHandle.java

View workflow job for this annotation

GitHub Actions / checkstyle / checkstyle

[checkstyle] reported by reviewdog 🐶 'block' child has incorrect indentation level 20, expected level should be 12. Raw Output: /github/workspace/src/main/java/org/mvplugins/multiverse/core/config/handle/BaseConfigurationHandle.java:97:21: warning: 'block' child has incorrect indentation level 20, expected level should be 12. (com.puppycrawl.tools.checkstyle.checks.indentation.IndentationCheck)
})

Check warning on line 98 in src/main/java/org/mvplugins/multiverse/core/config/handle/BaseConfigurationHandle.java

View workflow job for this annotation

GitHub Actions / checkstyle / checkstyle

[checkstyle] reported by reviewdog 🐶 'block rcurly' has incorrect indentation level 16, expected level should be 8. Raw Output: /github/workspace/src/main/java/org/mvplugins/multiverse/core/config/handle/BaseConfigurationHandle.java:98:17: warning: 'block rcurly' has incorrect indentation level 16, expected level should be 8. (com.puppycrawl.tools.checkstyle.checks.indentation.IndentationCheck)
.flatMap(value -> node.validate(value).map(ignore -> value))
.onFailure(e -> Logging.warning("Failed to deserialize node %s: %s",
node.getPath(), e.getMessage()))
.getOrElse(node::getDefaultValue);
}

Expand All @@ -124,12 +119,7 @@
if (value == null) {
value = node.getDefaultValue();
}
if (node.getSerializer() != null) {
var serialized = node.getSerializer().serialize(value, node.getType());
config.set(node.getPath(), serialized);
} else {
config.set(node.getPath(), value);
}
config.set(node.getPath(), node.serialize(value));
}

/**
Expand Down Expand Up @@ -163,6 +153,15 @@
return set(Bukkit.getConsoleSender(), node, value);
}

public <K, V> Try<Void> set(@NotNull MapValueNode<K, V> node, K key, V value) {
return node.validateEntry(key, value).map(ignore -> {
Map<K,V> map = get(node);
map.put(key, value);
// node.onSetEntryValue(null, key, null, value);

Check warning on line 160 in src/main/java/org/mvplugins/multiverse/core/config/handle/BaseConfigurationHandle.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=Multiverse_Multiverse-Core&issues=AZ4B4FbbsdPLneVpMsNE&open=AZ4B4FbbsdPLneVpMsNE&pullRequest=3469
return null;
});
}

/**
* Sets the value of a node, if the validator is not null, it will be tested first.
*
Expand Down Expand Up @@ -221,6 +220,18 @@
});
}

public <K, V> Try<Void> remove(@NotNull MapValueNode<K, V> node, K key) {
return node.validateKey(key).map(ignore -> {
Map<K,V> map = get(node);
V value = map.remove(key);
if (value == null) {
throw new IllegalArgumentException("Cannot remove entry as it is already not in the map!");
}
// node.onSetEntryValue(key, value, null);

Check warning on line 230 in src/main/java/org/mvplugins/multiverse/core/config/handle/BaseConfigurationHandle.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=Multiverse_Multiverse-Core&issues=AZ4B4FbbsdPLneVpMsNF&open=AZ4B4FbbsdPLneVpMsNF&pullRequest=3469
return null;
});
}

/**
* Sets the default value of a node.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,5 @@ protected Builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
* @return The configuration handle.
*/
public abstract @NotNull FileConfigurationHandle<C> build();

@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,24 @@
return serializer;
}

/**
* {@inheritDoc}
*/
@Override
public T deserialize(@Nullable Object object) {
return serializer == null
? (type.isInstance(object)) ? type.cast(object) : getDefaultValue()

Check warning on line 189 in src/main/java/org/mvplugins/multiverse/core/config/node/ConfigNode.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=Multiverse_Multiverse-Core&issues=AZ4B4Fg_sdPLneVpMsNJ&open=AZ4B4Fg_sdPLneVpMsNJ&pullRequest=3469
: serializer.deserialize(object, type);
}

/**
* {@inheritDoc}
*/
@Override
public Object serialize(T value) {
return serializer == null ? value : serializer.serialize(value, type);
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ protected Builder(@NotNull String path, @NotNull Class<I> itemType) {
//noinspection unchecked
super(path, (Class<List<I>>) (Object) List.class);
this.itemType = itemType;
this.defaultValue = () -> (List<I>) new ArrayList<>();
this.defaultValue = ArrayList::new;
}

/**
Expand Down
Loading
Loading