Add /iris language and /iris debugdump on both platforms

/iris language opens a locale menu and sets the language for the caller
or, for a gamemaster, the server default; /iris debugdump writes a
diagnostic report and optionally uploads it. Neither needs iris.all, so
a plain player can reach them. Every modded command now executes inside
a language audience scope, and the Bukkit dispatcher opens one around
execution, tab completion and help. Permissions, message keys and the
shipped locales follow.
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-03 05:03:28 -04:00
1 parent b25937f986
commit 657aaeaccf
39 files changed
+654 -226

No files matched your search

@@ -18,6 +18,7 @@
package art.arcane.iris;
import art.arcane.volmlib.util.diagnostics.BukkitDebugDump;
import art.arcane.iris.engine.IrisEngineEffects;
import art.arcane.iris.engine.IrisWorldManager;
@@ -50,6 +51,8 @@ import art.arcane.iris.core.link.IrisPapiInstaller;
import art.arcane.iris.core.link.IrisPapiListener;
import art.arcane.iris.core.link.IrisPapiState;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.volmlib.util.director.help.DirectorMiniMenu;
import art.arcane.volmlib.util.localization.BukkitLanguageSwitcher;
import art.arcane.iris.core.link.MultiverseCoreLink;
import art.arcane.iris.core.nms.INMS;
import art.arcane.iris.core.gui.BukkitGuiHost;
@@ -199,6 +202,8 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
private final BukkitWorldReconciler worldReconciler = new BukkitWorldReconciler(this);
private final PendingWorldDeleteQueue pendingWorldDeletes = new PendingWorldDeleteQueue(this);
private final PendingWorldReplacementManager pendingWorldReplacements = new PendingWorldReplacementManager(this);
private BukkitLanguageSwitcher languageSwitcher;
private BukkitDebugDump debugDump;
private volatile SettingsHotloadWatch settingsHotloadWatch;
private volatile Thread serverLifecycleThread;
@@ -602,6 +607,10 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
MultiBurst.burst.reopen();
MultiBurst.ioBurst.reopen();
IrisLanguage.initialize();
debugDump = BukkitDebugDump.create(this);
languageSwitcher = BukkitLanguageSwitcher.register(this, IrisLanguage.selections(),
new BukkitLanguageSwitcher.Options("iris", "iris.all",
DirectorMiniMenu.Theme.irisGreen(), IrisLanguage.directorResolver(), IrisLanguage.editorOptions()));
PaperLibBootstrap.install();
SimdSupport.install();
services = new KMap<>();
@@ -861,7 +870,32 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
}
}
public BukkitDebugDump debugDump() {
return debugDump;
}
public void selectLanguage(CommandSender sender, String[] arguments) {
BukkitLanguageSwitcher current = languageSwitcher;
if (current != null) {
current.command(sender, arguments);
}
}
public List<String> completeLanguage(CommandSender sender, String[] arguments) {
BukkitLanguageSwitcher current = languageSwitcher;
return current == null ? List.of() : current.complete(sender, arguments);
}
public void onDisable() {
if (debugDump != null) {
debugDump.close();
debugDump = null;
}
if (languageSwitcher != null) {
languageSwitcher.close();
languageSwitcher = null;
}
IrisLanguage.shutdown();
teardownPapi();
boolean serverStopping = IrisToolbelt.isServerStopping();
boolean restartingAtStartupBoundary = startupBoundaryRestart.get();
@@ -50,6 +50,7 @@ import art.arcane.iris.util.common.format.C;
import art.arcane.iris.util.common.plugin.VolmitSender;
import art.arcane.iris.util.common.scheduling.J;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
@@ -95,6 +96,19 @@ public class CommandIris implements DirectorExecutor {
private CommandDatapack datapack;
VolmitSender sender = Iris.getSender();
@Director(name = "debugdump", sync = true, description = "Create and optionally upload a diagnostic report", descriptionKey = "iris.director.commandiris.director.debugdump")
public void debugdump(
@Param(name = "upload", defaultValue = "true", description = "Upload the report to mclo.gs", descriptionKey = "iris.director.commandiris.param.debugdump_upload") boolean upload,
@Param(name = "sender", contextual = true) CommandSender sender
) {
Iris.instance.debugDump().request(sender, upload);
}
@Director(description = "Choose your language or the server default")
public void language() {
Iris.instance.selectLanguage(sender().getS(), new String[0]);
}
@Director(description = "Create a new world", descriptionKey = "iris.director.commandiris.director.create_new_world", aliases = {"c"})
public void create(
@Param(aliases = "world-name", description = "The name of the world to create", descriptionKey = "iris.director.commandiris.param.name_world_create")
@@ -55,6 +55,8 @@ import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -62,11 +64,14 @@ import java.util.Optional;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.IrisMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
import art.arcane.volmlib.util.localization.LanguageAudience;
import art.arcane.volmlib.util.plugin.ComponentMessenger;
public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, DirectorInvocationHook {
private static final String ROOT_COMMAND = "iris";
private static final String ROOT_PERMISSION = "iris.all";
private final ThreadLocal<Deque<LanguageAudience.Scope>> languageScopes = ThreadLocal.withInitial(ArrayDeque::new);
private final transient AtomicCache<DirectorRuntimeEngine> directorCache = new AtomicCache<>();
private final transient ThreadLocal<CommandSender> dispatchSenders = new ThreadLocal<>();
@@ -102,6 +107,12 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
private DirectorContextRegistry buildDirectorContexts() {
DirectorContextRegistry contexts = new DirectorContextRegistry();
contexts.register(CommandSender.class, (invocation, map) -> {
if (invocation.getSender() instanceof BukkitDirectorSender sender) {
return sender.sender();
}
return null;
});
for (Map.Entry<Class<?>, DirectorContextHandler<?>> entry : DirectorContextHandler.contextHandlers.entrySet()) {
registerContextHandler(contexts, entry.getKey(), entry.getValue());
@@ -139,6 +150,7 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
@Override
public void beforeInvoke(DirectorInvocation invocation, DirectorRuntimeNode node) {
if (invocation.getSender() instanceof BukkitDirectorSender sender) {
languageScopes.get().push(LanguageAudience.open(sender.sender() instanceof Player player ? player.getUniqueId() : null));
DirectorContext.touch(new VolmitSender(sender.sender()));
}
}
@@ -146,6 +158,13 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
@Override
public void afterInvoke(DirectorInvocation invocation, DirectorRuntimeNode node) {
DirectorContext.remove();
Deque<LanguageAudience.Scope> scopes = languageScopes.get();
if (!scopes.isEmpty()) {
scopes.pop().close();
}
if (scopes.isEmpty()) {
languageScopes.remove();
}
}
@Nullable
@@ -169,7 +188,12 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
}
public void executeRoot(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission(ROOT_PERMISSION)) {
if (args.length > 0 && args[0].equalsIgnoreCase("language")) {
Iris.instance.selectLanguage(sender, Arrays.copyOfRange(args, 1, args.length));
return;
}
if (!(args.length > 0 && args[0].equalsIgnoreCase("debugdump"))
&& !sender.hasPermission(ROOT_PERMISSION)) {
ComponentMessenger.sendSection(sender, IrisLanguage.text(
IrisMessages.COMMAND_PERMISSION_DENIED,
MessageArgument.trusted("permission", ROOT_PERMISSION)
@@ -181,7 +205,9 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
}
public List<String> tabCompleteRoot(CommandSender sender, String alias, String[] args) {
List<String> suggestions = runDirectorTab(sender, alias, args);
List<String> suggestions = args.length > 0 && args[0].equalsIgnoreCase("language")
? Iris.instance.completeLanguage(sender, Arrays.copyOfRange(args, 1, args.length))
: runDirectorTab(sender, alias, args);
if (sender instanceof Player player && IrisSettings.get().getGeneral().isCommandSounds()) {
player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 0.25f, RNG.r.f(0.125f, 1.95f));
}
@@ -235,23 +261,25 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
}
private boolean sendHelpIfRequested(CommandSender sender, String[] args) {
Optional<DirectorHelpPage> request = DirectorMiniMenu.resolveHelp(getDirector(), Arrays.asList(args));
if (request.isEmpty()) {
return false;
}
try (LanguageAudience.Scope audience = LanguageAudience.open(sender instanceof Player player ? player.getUniqueId() : null)) {
Optional<DirectorHelpPage> request = DirectorMiniMenu.resolveHelp(getDirector(), Arrays.asList(args));
if (request.isEmpty()) {
return false;
}
DirectorMiniMenu.deliver(
sender,
request.get(),
DirectorMiniMenu.Theme.irisGreen(),
IrisLanguage.directorResolver()
);
return true;
DirectorMiniMenu.deliver(
sender,
request.get(),
DirectorMiniMenu.Theme.irisGreen(),
IrisLanguage.directorResolver()
);
return true;
}
}
private DirectorExecutionResult runDirector(CommandSender sender, String label, String[] args) {
dispatchSenders.set(sender);
try {
try (LanguageAudience.Scope audience = LanguageAudience.open(sender instanceof Player player ? player.getUniqueId() : null)) {
return getDirector().execute(new DirectorInvocation(new BukkitDirectorSender(sender), label, Arrays.asList(args)));
} catch (Throwable e) {
Iris.warn("Director command execution failed: " + e.getClass().getSimpleName() + " " + e.getMessage());
@@ -263,7 +291,7 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
private List<String> runDirectorTab(CommandSender sender, String alias, String[] args) {
DirectorContext.touch(new VolmitSender(sender));
try {
try (LanguageAudience.Scope audience = LanguageAudience.open(sender instanceof Player player ? player.getUniqueId() : null)) {
return getDirector().tabComplete(new DirectorInvocation(new BukkitDirectorSender(sender), alias, Arrays.asList(args)));
} catch (Throwable e) {
Iris.warn("Director tab completion failed: " + e.getClass().getSimpleName() + " " + e.getMessage());
@@ -10,6 +10,12 @@ authors: [ cyberpwn, NextdoorPsycho, Vatuu ]
website: VolmitSoftware.com
description: More than a Dimension!
permissions:
iris.debugdump:
description: Allows creating and optionally uploading diagnostic reports.
default: op
iris.language.self:
description: Allows choosing your own language for this plugin.
default: true
iris.all:
description: Allows use of the full /iris command tree (worlds, studio, pregen, packs, developer tools).
default: op
@@ -26,6 +26,12 @@ commands:
iris:
aliases: [ ir, irs ]
permissions:
iris.debugdump:
description: Allows creating and optionally uploading diagnostic reports.
default: op
iris.language.self:
description: Allows choosing your own language for this plugin.
default: true
iris.all:
description: Allows use of the full /iris command tree (worlds, studio, pregen, packs, developer tools).
default: op
@@ -57,7 +57,14 @@ public class PaperPluginMetadataTest {
assertTrue(metadata.contains("folia-supported: true"));
assertTrue(metadata.contains("load: STARTUP"));
assertFalse(metadata.contains("commands:"));
assertTrue(metadata.contains("permissions:\n iris.all:\n"
assertTrue(metadata.contains("permissions:\n"));
assertTrue(metadata.contains(" iris.debugdump:\n"
+ " description: Allows creating and optionally uploading diagnostic reports.\n"
+ " default: op"));
assertTrue(metadata.contains(" iris.language.self:\n"
+ " description: Allows choosing your own language for this plugin.\n"
+ " default: true"));
assertTrue(metadata.contains(" iris.all:\n"
+ " description: Allows use of the full /iris command tree (worlds, studio, pregen, packs, developer tools).\n"
+ " default: op\n"
+ " iris.treefeller:\n"
@@ -0,0 +1,56 @@
package art.arcane.iris.core.commands;
import art.arcane.iris.Iris;
import art.arcane.iris.core.service.CommandSVC;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class CommandLanguageRoutingTest {
private Iris previousPlugin;
private Iris plugin;
@Before
public void installPlugin() {
previousPlugin = Iris.instance;
plugin = mock(Iris.class);
Iris.instance = plugin;
}
@After
public void restorePlugin() {
Iris.instance = previousPlugin;
}
@Test
public void forwardsEveryLanguageArgumentBeforeCheckingTheAdminRootPermission() {
Player player = mock(Player.class);
String[] arguments = {"language", "self", "de_DE"};
new CommandSVC().executeRoot(player, "iris", arguments);
verify(plugin).selectLanguage(player, new String[]{"self", "de_DE"});
verify(player, never()).hasPermission("iris.all");
}
@Test
public void forwardsLanguageTabArgumentsToTheSharedCompletionService() {
CommandSender sender = mock(CommandSender.class);
String[] arguments = {"language", "self", "de"};
String[] languageArguments = {"self", "de"};
when(plugin.completeLanguage(sender, languageArguments)).thenReturn(List.of("de_DE"));
assertEquals(List.of("de_DE"), new CommandSVC().tabCompleteRoot(sender, "iris", arguments));
verify(plugin).completeLanguage(sender, languageArguments);
}
}
@@ -82,12 +82,15 @@ public class IrisPapiLifecycleTest {
@Test
public void bothDisablePathsTearThePlaceholderSurfaceDown() throws Exception {
String source = source();
String disable = body("public void onDisable() {");
String preUnload = body("public void onPreUnload(ReloadAware.PreUnloadReason reason) {");
int disableTeardown = disable.indexOf("teardownPapi();");
int preUnloadTeardown = preUnload.indexOf("teardownPapi();");
assertTrue("onDisable must tear the expansion down",
source.contains("public void onDisable() {\n teardownPapi();"));
assertTrue("the BileTools pre-unload hook must tear the expansion down",
source.contains("public void onPreUnload(ReloadAware.PreUnloadReason reason) {\n teardownPapi();"));
assertTrue("onDisable must tear the expansion down before branching into runtime shutdown",
disableTeardown >= 0 && disableTeardown < disable.indexOf("IrisToolbelt.isServerStopping()"));
assertTrue("the BileTools pre-unload hook must tear the expansion down before any shutdown branch",
preUnloadTeardown >= 0 && preUnloadTeardown < preUnload.indexOf("IrisToolbelt.isServerStopping()"));
}
@Test
@@ -435,6 +435,7 @@ public final class ModdedEngineBootstrap {
}
private static void restorePlatform(IrisPlatform platform) {
IrisLanguage.shutdown();
IrisPlatforms.unbind();
if (platform != null) {
IrisPlatforms.bind(platform);
@@ -18,7 +18,10 @@
package art.arcane.iris.modded.command;
import art.arcane.volmlib.util.localization.LanguageAudience;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import net.minecraft.server.level.ServerPlayer;
import com.mojang.brigadier.arguments.LongArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
@@ -66,16 +69,17 @@ final class ModdedCommandTree {
static LiteralArgumentBuilder<CommandSourceStack> rootTree() {
LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal("iris");
root.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), ""));
root.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "")));
root.then(helpTree());
root.then(ModdedLanguageCommands.tree());
root.then(Commands.literal("version").requires(READ_ONLY)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.version(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.version(context.getSource()))));
root.then(Commands.literal("info").requires(READ_ONLY)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), null)))
.then(Commands.argument("dimension", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.DIMENSION_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), StringArgumentType.getString(context, "dimension")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), StringArgumentType.getString(context, "dimension"))))));
// ModdedWhatCommands.tree() gates itself at LEVEL_GAMEMASTERS and keeps that gate:
// "what markers" drives lease-gated 9x9 mantle scans, and the Bukkit twin puts the
@@ -86,27 +90,27 @@ final class ModdedCommandTree {
root.then(teleportTree("tp"));
root.then(Commands.literal("evacuate").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.evacuate(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.evacuate(context.getSource(), null)))
.then(Commands.argument("dimension", DimensionArgument.dimension()).suggests(ModdedCommandSuggestions.DIMENSION_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.evacuate(context.getSource(), DimensionArgument.getDimension(context, "dimension")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.evacuate(context.getSource(), DimensionArgument.getDimension(context, "dimension"))))));
root.then(Commands.literal("debug").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.debug(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.debug(context.getSource()))));
root.then(Commands.literal("reload").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.reload(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.reload(context.getSource()))));
root.then(Commands.literal("height").requires(READ_ONLY)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.height(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.height(context.getSource()))));
root.then(Commands.literal("worlds").requires(READ_ONLY)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), null)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), null))));
root.then(Commands.literal("accesslist").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), null)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.info(context.getSource(), null))));
root.then(gotoTree("goto"));
root.then(gotoTree("find"));
root.then(Commands.literal("seed").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.seed(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.seed(context.getSource()))));
root.then(goldenhashTree("goldenhash"));
root.then(goldenhashTree("gold"));
@@ -124,11 +128,11 @@ final class ModdedCommandTree {
root.then(pregenTree("pregenerate"));
root.then(Commands.literal("wand").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedObjectCommands.giveWand(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedObjectCommands.giveWand(context.getSource()))));
root.then(Commands.literal("dust").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedObjectCommands.giveDust(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedObjectCommands.giveDust(context.getSource()))));
root.then(Commands.literal("d").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedObjectCommands.giveDust(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedObjectCommands.giveDust(context.getSource()))));
root.then(ModdedObjectCommands.tree("object"));
root.then(ModdedObjectCommands.tree("o"));
root.then(editTree());
@@ -155,122 +159,131 @@ final class ModdedCommandTree {
return root;
}
static Command<CommandSourceStack> localized(Command<CommandSourceStack> command) {
return context -> {
ServerPlayer player = context.getSource().getPlayer();
try (LanguageAudience.Scope audience = LanguageAudience.open(player == null ? null : player.getUUID())) {
return command.run(context);
}
};
}
private static LiteralArgumentBuilder<CommandSourceStack> createTree(String name) {
return Commands.literal(name).requires(GATE)
.then(Commands.argument("name", StringArgumentType.word())
.executes((CommandContext<CommandSourceStack> context) ->
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
ModdedWorldCommands.createWorld(
context.getSource(),
StringArgumentType.getString(context, "name"),
"overworld",
1337L))
1337L)))
.then(Commands.argument("pack", StringArgumentType.string()).suggests(ModdedCommandSuggestions.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> ModdedWorldCommands.createWorld(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedWorldCommands.createWorld(context.getSource(),
StringArgumentType.getString(context, "name"),
StringArgumentType.getString(context, "pack"),
1337L))
1337L)))
.then(Commands.argument("seed", LongArgumentType.longArg())
.executes((CommandContext<CommandSourceStack> context) -> ModdedWorldCommands.createWorld(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedWorldCommands.createWorld(context.getSource(),
StringArgumentType.getString(context, "name"),
StringArgumentType.getString(context, "pack"),
LongArgumentType.getLong(context, "seed"))))));
LongArgumentType.getLong(context, "seed")))))));
}
private static LiteralArgumentBuilder<CommandSourceStack> teleportTree(String name) {
return Commands.literal(name).requires(GATE)
.then(Commands.argument("dimension", DimensionArgument.dimension()).suggests(ModdedCommandSuggestions.DIMENSION_NAMES)
.executes((CommandContext<CommandSourceStack> context) ->
IrisModdedCommands.tp(context.getSource(), DimensionArgument.getDimension(context, "dimension"), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
IrisModdedCommands.tp(context.getSource(), DimensionArgument.getDimension(context, "dimension"), null)))
.then(Commands.argument("player", EntityArgument.player())
.executes((CommandContext<CommandSourceStack> context) ->
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
IrisModdedCommands.tp(context.getSource(), DimensionArgument.getDimension(context, "dimension"),
EntityArgument.getPlayer(context, "player")))));
EntityArgument.getPlayer(context, "player"))))));
}
private static LiteralArgumentBuilder<CommandSourceStack> helpTree() {
return Commands.literal("help").requires(READ_ONLY)
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), ""))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "")))
.then(Commands.argument("section", StringArgumentType.greedyString())
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), StringArgumentType.getString(context, "section"))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), StringArgumentType.getString(context, "section")))));
}
private static LiteralArgumentBuilder<CommandSourceStack> downloadTree(String name) {
return Commands.literal(name).requires(GATE)
.then(Commands.argument("source", StringArgumentType.greedyString()).suggests(DOWNLOAD_SOURCES)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.download(
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.download(
context.getSource(),
StringArgumentType.getString(context, "source")
)));
))));
}
private static LiteralArgumentBuilder<CommandSourceStack> metricsTree(String name) {
return Commands.literal(name).requires(READ_ONLY)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.metrics(context.getSource()));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.metrics(context.getSource())));
}
private static LiteralArgumentBuilder<CommandSourceStack> regenTree(String name) {
return Commands.literal(name).requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.regen(context.getSource(), 0))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.regen(context.getSource(), 0)))
.then(Commands.argument("radius", IntegerArgumentType.integer(0, 64))
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.regen(context.getSource(), IntegerArgumentType.getInteger(context, "radius"))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.regen(context.getSource(), IntegerArgumentType.getInteger(context, "radius")))));
}
private static LiteralArgumentBuilder<CommandSourceStack> gotoTree(String name) {
return Commands.literal(name).requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)))
.then(Commands.literal("biome")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.BIOME_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoBiome(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoBiome(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("region")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.REGION_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoRegion(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoRegion(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("object")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoObject(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoObject(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("river")
.then(Commands.argument("type", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.HYDROLOGY_TYPES)
.executes((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoRiver(context.getSource(), StringArgumentType.getString(context, "type")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoRiver(context.getSource(), StringArgumentType.getString(context, "type"))))))
.then(Commands.literal("unregistered")
.executes((CommandContext<CommandSourceStack> context) ->
ModdedUnregisteredStructures.print(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
ModdedUnregisteredStructures.print(context.getSource()))))
.then(Commands.literal("structure")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.STRUCTURE_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoStructure(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoStructure(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("poi")
.then(Commands.argument("type", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.POI_TYPES)
.executes((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoPoi(context.getSource(), StringArgumentType.getString(context, "type")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedLocateCommands.gotoPoi(context.getSource(), StringArgumentType.getString(context, "type"))))));
}
private static LiteralArgumentBuilder<CommandSourceStack> pregenTree(String name) {
RequiredArgumentBuilder<CommandSourceStack, Integer> radius = Commands.argument("radius", IntegerArgumentType.integer(1, 100000))
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, false, false, false, false, false));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, false, false, false, false, false)));
attachPregenCenter(radius, false);
attachPregenFlags(radius, false, false, false, false, false);
RequiredArgumentBuilder<CommandSourceStack, Identifier> dimension = Commands.argument("dimension", DimensionArgument.dimension()).suggests(ModdedCommandSuggestions.DIMENSION_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, true, false, false, false, false));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, true, false, false, false, false)));
attachPregenCenter(dimension, true);
attachPregenFlags(dimension, true, false, false, false, false);
radius.then(dimension);
return Commands.literal(name).requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)))
.then(Commands.literal("start")
.then(radius))
.then(Commands.literal("stop")
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStop(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStop(context.getSource()))))
.then(Commands.literal("x")
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStop(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStop(context.getSource()))))
.then(Commands.literal("pause")
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenPause(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenPause(context.getSource()))))
.then(Commands.literal("resume")
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenPause(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenPause(context.getSource()))))
.then(Commands.literal("status")
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStatus(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStatus(context.getSource()))));
}
private static void attachPregenCenter(ArgumentBuilder<CommandSourceStack, ?> node, boolean withDimension) {
RequiredArgumentBuilder<CommandSourceStack, Integer> z = Commands.argument("z", IntegerArgumentType.integer())
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, withDimension, true, false, false, false));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, withDimension, true, false, false, false)));
attachPregenFlags(z, withDimension, true, false, false, false);
node.then(Commands.literal("at")
.then(Commands.argument("x", IntegerArgumentType.integer())
@@ -291,22 +304,22 @@ final class ModdedCommandTree {
private static LiteralArgumentBuilder<CommandSourceStack> pregenFlagNode(String name, boolean withDimension, boolean withCenter, boolean gui, boolean sync, boolean nocache) {
LiteralArgumentBuilder<CommandSourceStack> flag = Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, withDimension, withCenter, gui, sync, nocache));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedPregenCommands.pregenStart(context, withDimension, withCenter, gui, sync, nocache)));
attachPregenFlags(flag, withDimension, withCenter, gui, sync, nocache);
return flag;
}
private static LiteralArgumentBuilder<CommandSourceStack> goldenhashTree(String name) {
LiteralArgumentBuilder<CommandSourceStack> radiusAndThreads = Commands.literal(name).requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), 8, 8, ModdedGoldenHash.Mode.AUTO));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), 8, 8, ModdedGoldenHash.Mode.AUTO)));
attachModes(radiusAndThreads, (CommandContext<CommandSourceStack> context) -> 8, (CommandContext<CommandSourceStack> context) -> 8);
com.mojang.brigadier.builder.RequiredArgumentBuilder<CommandSourceStack, Integer> radius = Commands.argument("radius", IntegerArgumentType.integer(0, 256))
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), IntegerArgumentType.getInteger(context, "radius"), 8, ModdedGoldenHash.Mode.AUTO));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), IntegerArgumentType.getInteger(context, "radius"), 8, ModdedGoldenHash.Mode.AUTO)));
attachModes(radius, (CommandContext<CommandSourceStack> context) -> IntegerArgumentType.getInteger(context, "radius"), (CommandContext<CommandSourceStack> context) -> 8);
com.mojang.brigadier.builder.RequiredArgumentBuilder<CommandSourceStack, Integer> threads = Commands.argument("threads", IntegerArgumentType.integer(1, 64))
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), IntegerArgumentType.getInteger(context, "radius"), IntegerArgumentType.getInteger(context, "threads"), ModdedGoldenHash.Mode.AUTO));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), IntegerArgumentType.getInteger(context, "radius"), IntegerArgumentType.getInteger(context, "threads"), ModdedGoldenHash.Mode.AUTO)));
attachModes(threads, (CommandContext<CommandSourceStack> context) -> IntegerArgumentType.getInteger(context, "radius"), (CommandContext<CommandSourceStack> context) -> IntegerArgumentType.getInteger(context, "threads"));
radius.then(threads);
@@ -320,33 +333,33 @@ final class ModdedCommandTree {
private static void attachModes(com.mojang.brigadier.builder.ArgumentBuilder<CommandSourceStack, ?> node, IntExtractor radius, IntExtractor threads) {
node.then(Commands.literal("capture")
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), radius.extract(context), threads.extract(context), ModdedGoldenHash.Mode.CAPTURE)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), radius.extract(context), threads.extract(context), ModdedGoldenHash.Mode.CAPTURE))));
node.then(Commands.literal("verify")
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), radius.extract(context), threads.extract(context), ModdedGoldenHash.Mode.VERIFY)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.goldenhash(context.getSource(), radius.extract(context), threads.extract(context), ModdedGoldenHash.Mode.VERIFY))));
}
private static LiteralArgumentBuilder<CommandSourceStack> editTree() {
return Commands.literal("edit").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "edit"))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "edit")))
.then(Commands.literal("biome")
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), null)))
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.BIOME_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("b")
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), null)))
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.BIOME_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editBiome(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("region")
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), null)))
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.REGION_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("r")
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), null)))
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ModdedCommandSuggestions.REGION_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), StringArgumentType.getString(context, "key")))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editRegion(context.getSource(), StringArgumentType.getString(context, "key"))))))
.then(Commands.literal("dimension")
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editDimension(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editDimension(context.getSource()))))
.then(Commands.literal("d")
.executes((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editDimension(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedEditCommands.editDimension(context.getSource()))));
}
}
@@ -64,18 +64,18 @@ public final class ModdedDatapackCommands {
public static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal(name).requires(GATE);
root.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name));
root.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)));
root.then(Commands.literal("status")
.executes((CommandContext<CommandSourceStack> context) -> status(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> status(context.getSource()))));
root.then(Commands.literal("install")
.executes((CommandContext<CommandSourceStack> context) -> install(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> install(context.getSource()))));
root.then(Commands.literal("list")
.executes((CommandContext<CommandSourceStack> context) -> list(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> list(context.getSource()))));
root.then(Commands.literal("ls")
.executes((CommandContext<CommandSourceStack> context) -> list(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> list(context.getSource()))));
root.then(message("ingest", "Managed Modrinth datapack ingest is Bukkit-only. On modded servers install the datapack folder or zip in world/datapacks, enable it, restart, then use /iris datapack list to confirm it is enabled. Registered structures generate natively in Iris dimensions."));
root.then(message("pull", "Managed Modrinth datapack ingest is Bukkit-only. On modded servers install the datapack folder or zip in world/datapacks, enable it, restart, then use /iris datapack list to confirm it is enabled. Registered structures generate natively in Iris dimensions."));
@@ -88,15 +88,15 @@ public final class ModdedDatapackCommands {
private static LiteralArgumentBuilder<CommandSourceStack> message(String name, String text) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> {
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> {
IrisModdedCommands.fail(context.getSource(), text);
return 0;
})
}))
.then(Commands.argument("args", StringArgumentType.greedyString())
.executes((CommandContext<CommandSourceStack> context) -> {
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> {
IrisModdedCommands.fail(context.getSource(), text);
return 0;
}));
})));
}
private static File worldDatapacksFolder(MinecraftServer server) {
@@ -42,11 +42,11 @@ final class ModdedDeveloperCommands {
static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
return Commands.literal(name).requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "developer"))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "developer")))
.then(Commands.literal("network")
.executes((CommandContext<CommandSourceStack> context) -> network(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> network(context.getSource()))))
.then(Commands.literal("ip")
.executes((CommandContext<CommandSourceStack> context) -> network(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> network(context.getSource()))));
}
private static int network(CommandSourceStack source) {
@@ -0,0 +1,92 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.volmlib.util.director.help.DirectorHelpMessages;
import art.arcane.volmlib.util.localization.PluginLanguageService;
import art.arcane.volmlib.util.localization.VolmitLocales;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
final class ModdedLanguageCommands {
private ModdedLanguageCommands() {
}
static LiteralArgumentBuilder<CommandSourceStack> tree() {
return Commands.literal("language")
.executes(ModdedCommandTree.localized(context -> open(context.getSource())))
.then(scope("self", false))
.then(scope("server", true).requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS)));
}
private static LiteralArgumentBuilder<CommandSourceStack> scope(String name, boolean server) {
return Commands.literal(name)
.then(Commands.argument("locale", StringArgumentType.word())
.suggests((context, builder) -> SharedSuggestionProvider.suggest(IrisLanguage.availableLocales(), builder))
.executes(ModdedCommandTree.localized(context -> select(context.getSource(), server, StringArgumentType.getString(context, "locale")))));
}
private static int open(CommandSourceStack source) {
ModdedCommandFeedback.clear(source);
ModdedCommandFeedback.send(source, ModdedCommandFeedback.banner("/iris language"));
ModdedCommandFeedback.send(source, ModdedCommandFeedback.button(
"〈 " + IrisLanguage.plain(DirectorHelpMessages.BACK), "/iris", "Iris", true));
ModdedCommandFeedback.send(source, ModdedCommandFeedback.text(
"Iris language: " + IrisLanguage.activeLocale(), ModdedCommandFeedback.DESCRIPTION));
for (String locale : IrisLanguage.availableLocales()) {
String name = VolmitLocales.displayName(locale).orElse(locale);
ModdedCommandFeedback.send(source, ModdedCommandFeedback.text("⇀ ", ModdedCommandFeedback.DARK_GREEN)
.append(ModdedCommandFeedback.button(name + " [me]", "/iris language self " + locale, "Use " + name, true))
.append(ModdedCommandTree.isGamemaster(source)
? ModdedCommandFeedback.button(" [server]", "/iris language server " + locale, "Set the server default", true)
: Component.empty()));
}
ModdedCommandFeedback.send(source, ModdedCommandFeedback.button(
"Use server default", "/iris language self reset", "Clear your personal language", true));
ModdedCommandFeedback.ok(source, ModdedCommandFeedback.footer());
return 1;
}
private static int select(CommandSourceStack source, boolean server, String locale) {
PluginLanguageService service = IrisLanguage.selections();
if (service == null) {
source.sendFailure(Component.literal("Iris language service is unavailable."));
return 0;
}
CompletableFuture<String> selection;
if (server) {
selection = service.selectDefault(locale).thenApply(ignored -> service.defaultLocale());
} else {
ServerPlayer player = source.getPlayer();
if (player == null) {
source.sendFailure(Component.literal("Personal language selection requires a player."));
return 0;
}
UUID playerId = player.getUUID();
CompletableFuture<Void> personal = locale.equals("reset")
? service.clearPlayer(playerId) : service.selectPlayer(playerId, locale);
selection = personal.thenApply(ignored -> service.effectiveLocale(playerId));
}
selection.whenComplete((activeLocale, failure) -> source.getServer().execute(() -> {
if (failure != null) {
IrisLogging.reportError(failure);
source.sendFailure(Component.literal("Language selection failed. See the server log."));
} else if (!locale.equals("reset")
&& !locale.replace('-', '_').equalsIgnoreCase(activeLocale.replace('-', '_'))) {
source.sendSuccess(() -> Component.literal("Iris: " + locale
+ " unavailable; using English (" + activeLocale + ")."), false);
} else {
source.sendSuccess(() -> Component.literal("Language updated: " + activeLocale), false);
}
}));
return 1;
}
}
@@ -107,21 +107,21 @@ public final class ModdedObjectCommands {
ModdedObjectUndo.init();
LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal(name).requires(GATE);
root.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name));
root.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)));
root.then(Commands.literal("wand")
.executes((CommandContext<CommandSourceStack> context) -> giveWand(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> giveWand(context.getSource()))));
root.then(Commands.literal("dust")
.executes((CommandContext<CommandSourceStack> context) -> giveDust(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> giveDust(context.getSource()))));
root.then(Commands.literal("d")
.executes((CommandContext<CommandSourceStack> context) -> giveDust(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> giveDust(context.getSource()))));
root.then(Commands.literal("save")
.then(Commands.literal("overwrite")
.then(Commands.argument("name", StringArgumentType.greedyString())
.executes((CommandContext<CommandSourceStack> context) -> save(context.getSource(), StringArgumentType.getString(context, "name"), true))))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> save(context.getSource(), StringArgumentType.getString(context, "name"), true)))))
.then(Commands.argument("name", StringArgumentType.greedyString())
.executes((CommandContext<CommandSourceStack> context) -> save(context.getSource(), StringArgumentType.getString(context, "name"), false))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> save(context.getSource(), StringArgumentType.getString(context, "name"), false)))));
root.then(pasteTree());
@@ -131,13 +131,13 @@ public final class ModdedObjectCommands {
root.then(resizeTree("shift", ResizeOp.SHIFT));
root.then(Commands.literal("xpy")
.executes((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), false)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), false))));
root.then(Commands.literal("x+y")
.executes((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), false)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), false))));
root.then(Commands.literal("xay")
.executes((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), true)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), true))));
root.then(Commands.literal("x&y")
.executes((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), true)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> autoSelect(context.getSource(), true))));
root.then(positionTree("position1", true));
root.then(positionTree("p1", true));
@@ -146,27 +146,27 @@ public final class ModdedObjectCommands {
root.then(Commands.literal("analyze")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> analyze(context.getSource(), StringArgumentType.getString(context, "key")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> analyze(context.getSource(), StringArgumentType.getString(context, "key"))))));
root.then(Commands.literal("shrink")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> shrink(context.getSource(), StringArgumentType.getString(context, "key")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> shrink(context.getSource(), StringArgumentType.getString(context, "key"))))));
root.then(Commands.literal("undo")
.executes((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), 1))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), 1)))
.then(Commands.argument("amount", IntegerArgumentType.integer(1, 32))
.executes((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), IntegerArgumentType.getInteger(context, "amount")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), IntegerArgumentType.getInteger(context, "amount"))))));
root.then(Commands.literal("u")
.executes((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), 1))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), 1)))
.then(Commands.argument("amount", IntegerArgumentType.integer(1, 32))
.executes((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), IntegerArgumentType.getInteger(context, "amount")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> undo(context.getSource(), IntegerArgumentType.getInteger(context, "amount"))))));
root.then(bukkitOnly("we", "WorldEdit selection import requires the Bukkit plugin with WorldEdit installed."));
root.then(bukkitOnly("studio", "The object studio world requires the Bukkit studio toolchain; it is not available on modded servers."));
root.then(bukkitOnly("convert", "Schematic conversion (.schem -> .iob) requires the Bukkit plugin."));
root.then(Commands.literal("plausibilize")
.then(Commands.argument("args", StringArgumentType.greedyString()).suggests(OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> plausibilize(context.getSource(), StringArgumentType.getString(context, "args")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> plausibilize(context.getSource(), StringArgumentType.getString(context, "args"))))));
return root;
}
@@ -174,12 +174,12 @@ public final class ModdedObjectCommands {
private static LiteralArgumentBuilder<CommandSourceStack> pasteTree() {
LiteralArgumentBuilder<CommandSourceStack> paste = Commands.literal("paste");
paste.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"), 0, null)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"), 0, null))));
paste.then(Commands.literal("rotate")
.then(Commands.argument("degrees", IntegerArgumentType.integer(-270, 270)).suggests(ROTATIONS)
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"),
IntegerArgumentType.getInteger(context, "degrees"), null)))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"),
IntegerArgumentType.getInteger(context, "degrees"), null))))));
paste.then(Commands.literal("at")
.then(Commands.argument("x", IntegerArgumentType.integer())
.then(Commands.argument("y", IntegerArgumentType.integer())
@@ -187,35 +187,35 @@ public final class ModdedObjectCommands {
.then(Commands.literal("rotate")
.then(Commands.argument("degrees", IntegerArgumentType.integer(-270, 270)).suggests(ROTATIONS)
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"),
IntegerArgumentType.getInteger(context, "degrees"),
new BlockPos(IntegerArgumentType.getInteger(context, "x"), IntegerArgumentType.getInteger(context, "y"), IntegerArgumentType.getInteger(context, "z")))))))
new BlockPos(IntegerArgumentType.getInteger(context, "x"), IntegerArgumentType.getInteger(context, "y"), IntegerArgumentType.getInteger(context, "z"))))))))
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(OBJECT_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"), 0,
new BlockPos(IntegerArgumentType.getInteger(context, "x"), IntegerArgumentType.getInteger(context, "y"), IntegerArgumentType.getInteger(context, "z")))))))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> paste(context.getSource(), StringArgumentType.getString(context, "key"), 0,
new BlockPos(IntegerArgumentType.getInteger(context, "x"), IntegerArgumentType.getInteger(context, "y"), IntegerArgumentType.getInteger(context, "z"))))))))));
return paste;
}
private static LiteralArgumentBuilder<CommandSourceStack> resizeTree(String name, ResizeOp op) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> resize(context.getSource(), 1, op))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> resize(context.getSource(), 1, op)))
.then(Commands.argument("amount", IntegerArgumentType.integer(1, 256))
.executes((CommandContext<CommandSourceStack> context) -> resize(context.getSource(), IntegerArgumentType.getInteger(context, "amount"), op)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> resize(context.getSource(), IntegerArgumentType.getInteger(context, "amount"), op))));
}
private static LiteralArgumentBuilder<CommandSourceStack> positionTree(String name, boolean first) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> position(context.getSource(), first, false))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> position(context.getSource(), first, false)))
.then(Commands.literal("look")
.executes((CommandContext<CommandSourceStack> context) -> position(context.getSource(), first, true)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> position(context.getSource(), first, true))));
}
private static LiteralArgumentBuilder<CommandSourceStack> bukkitOnly(String name, String message) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> {
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> {
IrisModdedCommands.fail(context.getSource(), message);
return 0;
});
}));
}
public static int giveWand(CommandSourceStack source) {
@@ -51,47 +51,47 @@ public final class ModdedPackCommands {
public static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal(name).requires(GATE);
root.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name));
root.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)));
root.then(Commands.literal("validate")
.executes((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), null)))
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), StringArgumentType.getString(context, "pack")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), StringArgumentType.getString(context, "pack"))))));
root.then(Commands.literal("v")
.executes((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), null)))
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), StringArgumentType.getString(context, "pack")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> validate(context.getSource(), StringArgumentType.getString(context, "pack"))))));
root.then(Commands.literal("cleanup")
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), false))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), false)))
.then(Commands.literal("apply")
.executes((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), true)))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), true))))));
root.then(Commands.literal("c")
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), false))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), false)))
.then(Commands.literal("apply")
.executes((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), true)))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> cleanup(context.getSource(), StringArgumentType.getString(context, "pack"), true))))));
root.then(Commands.literal("restore")
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), false))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), false)))
.then(Commands.literal("apply")
.executes((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), true)))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), true))))));
root.then(Commands.literal("r")
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), false))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), false)))
.then(Commands.literal("apply")
.executes((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), true)))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> restore(context.getSource(), StringArgumentType.getString(context, "pack"), true))))));
root.then(Commands.literal("status")
.executes((CommandContext<CommandSourceStack> context) -> status(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> status(context.getSource(), null)))
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> status(context.getSource(), StringArgumentType.getString(context, "pack")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> status(context.getSource(), StringArgumentType.getString(context, "pack"))))));
root.then(Commands.literal("s")
.executes((CommandContext<CommandSourceStack> context) -> status(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> status(context.getSource(), null)))
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> status(context.getSource(), StringArgumentType.getString(context, "pack")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> status(context.getSource(), StringArgumentType.getString(context, "pack"))))));
return root;
}
@@ -63,23 +63,23 @@ public final class ModdedStructureCommands {
public static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal(name).requires(GATE);
root.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name));
root.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)));
root.then(Commands.literal("list")
.executes((CommandContext<CommandSourceStack> context) -> list(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> list(context.getSource()))));
root.then(Commands.literal("ls")
.executes((CommandContext<CommandSourceStack> context) -> list(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> list(context.getSource()))));
root.then(Commands.literal("info")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(IRIS_STRUCTURE_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> info(context.getSource(), StringArgumentType.getString(context, "key")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> info(context.getSource(), StringArgumentType.getString(context, "key"))))));
root.then(Commands.literal("place")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(IRIS_STRUCTURE_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> place(context.getSource(), StringArgumentType.getString(context, "key")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> place(context.getSource(), StringArgumentType.getString(context, "key"))))));
root.then(Commands.literal("p")
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(IRIS_STRUCTURE_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> place(context.getSource(), StringArgumentType.getString(context, "key")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> place(context.getSource(), StringArgumentType.getString(context, "key"))))));
root.then(message("import", "Structure import rebuilds vanilla & datapack structures as editable Iris resources through Bukkit/NMS template managers; run /iris structure import on a Bukkit server against this pack, then copy the pack folder over."));
root.then(message("import-all", "Structure import rebuilds vanilla & datapack structures as editable Iris resources through Bukkit/NMS template managers; run /iris structure import on a Bukkit server against this pack, then copy the pack folder over."));
@@ -96,23 +96,23 @@ public final class ModdedStructureCommands {
private static LiteralArgumentBuilder<CommandSourceStack> verifyTree(String name) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.verifyStructures(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.verifyStructures(context.getSource(), null)))
.then(Commands.argument("key", StringArgumentType.greedyString()).suggests(ALL_STRUCTURE_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.verifyStructures(
context.getSource(), StringArgumentType.getString(context, "key"))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.verifyStructures(
context.getSource(), StringArgumentType.getString(context, "key")))));
}
private static LiteralArgumentBuilder<CommandSourceStack> message(String name, String text) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> {
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> {
IrisModdedCommands.fail(context.getSource(), text);
return 0;
})
}))
.then(Commands.argument("args", StringArgumentType.greedyString())
.executes((CommandContext<CommandSourceStack> context) -> {
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> {
IrisModdedCommands.fail(context.getSource(), text);
return 0;
}));
})));
}
private static IrisData dataFor(CommandSourceStack source) {
@@ -118,7 +118,7 @@ public final class ModdedStudioCommands {
public static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal(name).requires(GATE);
root.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name));
root.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)));
root.then(createTree("create"));
root.then(createTree("+"));
@@ -127,27 +127,27 @@ public final class ModdedStudioCommands {
root.then(packageTree("pkg"));
root.then(Commands.literal("version")
.executes((CommandContext<CommandSourceStack> context) -> version(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> version(context.getSource(), null)))
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> version(context.getSource(), StringArgumentType.getString(context, "pack")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> version(context.getSource(), StringArgumentType.getString(context, "pack"))))));
root.then(Commands.literal("regions")
.executes((CommandContext<CommandSourceStack> context) -> regions(context.getSource(), 500))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> regions(context.getSource(), 500)))
.then(Commands.argument("radius", IntegerArgumentType.integer(8, 1000))
.executes((CommandContext<CommandSourceStack> context) -> regions(context.getSource(), IntegerArgumentType.getInteger(context, "radius")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> regions(context.getSource(), IntegerArgumentType.getInteger(context, "radius"))))));
root.then(openTree("open"));
root.then(openTree("o"));
root.then(Commands.literal("close")
.executes((CommandContext<CommandSourceStack> context) -> close(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> close(context.getSource()))));
root.then(Commands.literal("x")
.executes((CommandContext<CommandSourceStack> context) -> close(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> close(context.getSource()))));
root.then(Commands.literal("tpstudio")
.executes((CommandContext<CommandSourceStack> context) -> tpStudio(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> tpStudio(context.getSource()))));
root.then(Commands.literal("stp")
.executes((CommandContext<CommandSourceStack> context) -> tpStudio(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> tpStudio(context.getSource()))));
root.then(Commands.literal("status")
.executes((CommandContext<CommandSourceStack> context) -> status(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> status(context.getSource()))));
root.then(workspaceTree("vscode", true));
root.then(workspaceTree("vsc", true));
root.then(workspaceTree("update", false));
@@ -172,26 +172,26 @@ public final class ModdedStudioCommands {
private static LiteralArgumentBuilder<CommandSourceStack> createTree(String name) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) ->
create(context.getSource(), "studio", DEFAULT_TEMPLATE))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
create(context.getSource(), "studio", DEFAULT_TEMPLATE)))
.then(Commands.argument("name", StringArgumentType.word())
.executes((CommandContext<CommandSourceStack> context) ->
create(context.getSource(), StringArgumentType.getString(context, "name"), DEFAULT_TEMPLATE))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
create(context.getSource(), StringArgumentType.getString(context, "name"), DEFAULT_TEMPLATE)))
.then(Commands.argument("template", StringArgumentType.word())
.suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) ->
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
create(context.getSource(),
StringArgumentType.getString(context, "name"),
StringArgumentType.getString(context, "template")))));
StringArgumentType.getString(context, "template"))))));
}
private static LiteralArgumentBuilder<CommandSourceStack> packageTree(String name) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> pkg(context.getSource(), null))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> pkg(context.getSource(), null)))
.then(Commands.argument("pack", StringArgumentType.word())
.suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) ->
pkg(context.getSource(), StringArgumentType.getString(context, "pack"))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
pkg(context.getSource(), StringArgumentType.getString(context, "pack")))));
}
public static void clear() {
@@ -201,11 +201,11 @@ public final class ModdedStudioCommands {
private static LiteralArgumentBuilder<CommandSourceStack> openTree(String name) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> openHelp(context.getSource()))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> openHelp(context.getSource())))
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> open(context.getSource(), StringArgumentType.getString(context, "pack"), 1337L))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> open(context.getSource(), StringArgumentType.getString(context, "pack"), 1337L)))
.then(Commands.argument("seed", LongArgumentType.longArg())
.executes((CommandContext<CommandSourceStack> context) -> open(context.getSource(), StringArgumentType.getString(context, "pack"), LongArgumentType.getLong(context, "seed")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> open(context.getSource(), StringArgumentType.getString(context, "pack"), LongArgumentType.getLong(context, "seed"))))));
}
private static int openHelp(CommandSourceStack source) {
@@ -215,21 +215,21 @@ public final class ModdedStudioCommands {
private static LiteralArgumentBuilder<CommandSourceStack> noiseTree(String name) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> noise(context.getSource(), null, 12345L))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> noise(context.getSource(), null, 12345L)))
.then(Commands.argument("generator", StringArgumentType.word()).suggests(GENERATOR_KEYS)
.executes((CommandContext<CommandSourceStack> context) -> noise(context.getSource(), StringArgumentType.getString(context, "generator"), 12345L))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> noise(context.getSource(), StringArgumentType.getString(context, "generator"), 12345L)))
.then(Commands.argument("seed", LongArgumentType.longArg())
.executes((CommandContext<CommandSourceStack> context) -> noise(context.getSource(), StringArgumentType.getString(context, "generator"), LongArgumentType.getLong(context, "seed")))));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> noise(context.getSource(), StringArgumentType.getString(context, "generator"), LongArgumentType.getLong(context, "seed"))))));
}
private static LiteralArgumentBuilder<CommandSourceStack> mapTree(String name) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> map(context.getSource()));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> map(context.getSource())));
}
private static LiteralArgumentBuilder<CommandSourceStack> imageMapTree(String name) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> imageMap(context.getSource()));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> imageMap(context.getSource())));
}
private static int noise(CommandSourceStack source, String generatorKey, long seed) {
@@ -306,9 +306,9 @@ public final class ModdedStudioCommands {
private static LiteralArgumentBuilder<CommandSourceStack> workspaceTree(String name, boolean open) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> workspace(context.getSource(), null, open))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> workspace(context.getSource(), null, open)))
.then(Commands.argument("pack", StringArgumentType.word()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> workspace(context.getSource(), StringArgumentType.getString(context, "pack"), open)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> workspace(context.getSource(), StringArgumentType.getString(context, "pack"), open))));
}
private static int workspace(CommandSourceStack source, String pack, boolean open) {
@@ -355,15 +355,15 @@ public final class ModdedStudioCommands {
private static LiteralArgumentBuilder<CommandSourceStack> message(String name, String text) {
return Commands.literal(name)
.executes((CommandContext<CommandSourceStack> context) -> {
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> {
IrisModdedCommands.fail(context.getSource(), text);
return 0;
})
}))
.then(Commands.argument("args", StringArgumentType.greedyString())
.executes((CommandContext<CommandSourceStack> context) -> {
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> {
IrisModdedCommands.fail(context.getSource(), text);
return 0;
}));
})));
}
private static File resolvePack(CommandSourceStack source, String pack) {
@@ -905,6 +905,7 @@ public final class ModdedStudioCommands {
lootKeys.addAll(dimension.getLoot().getTables());
spawnerKeys.addAll(dimension.getEntitySpawners());
collectStructureKeys(structureKeys, dimension.getStructures());
objectKeys.addAll(PackExportClosure.collectStaticObjectKeys(dimension.getStaticObjects()));
for (String regionKey : regionKeys) {
IrisRegion region = dm.getRegionLoader().load(regionKey);
@@ -92,30 +92,30 @@ public final class ModdedWhatCommands {
public static LiteralArgumentBuilder<CommandSourceStack> tree() {
return Commands.literal("what").requires(GATE)
.executes((CommandContext<CommandSourceStack> context) ->
inspectHere(context.getSource()))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
inspectHere(context.getSource())))
.then(Commands.literal("here")
.executes((CommandContext<CommandSourceStack> context) ->
inspectHere(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
inspectHere(context.getSource()))))
.then(Commands.literal("biome")
.executes((CommandContext<CommandSourceStack> context) ->
inspectBiome(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
inspectBiome(context.getSource()))))
.then(Commands.literal("region")
.executes((CommandContext<CommandSourceStack> context) ->
inspectRegion(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
inspectRegion(context.getSource()))))
.then(Commands.literal("block")
.executes((CommandContext<CommandSourceStack> context) ->
inspectBlock(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
inspectBlock(context.getSource()))))
.then(Commands.literal("hand")
.executes((CommandContext<CommandSourceStack> context) ->
inspectHand(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
inspectHand(context.getSource()))))
.then(Commands.literal("markers")
.then(Commands.argument("marker", StringArgumentType.greedyString())
.suggests(MARKER_TYPES)
.executes((CommandContext<CommandSourceStack> context) ->
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) ->
inspectMarkers(
context.getSource(),
StringArgumentType.getString(context, "marker")))));
StringArgumentType.getString(context, "marker"))))));
}
static void clear() {
@@ -67,14 +67,14 @@ public final class ModdedWorldCommands {
public static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal(name).requires(GATE);
root.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name));
root.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), name)));
root.then(Commands.literal("status")
.executes((CommandContext<CommandSourceStack> context) -> status(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> status(context.getSource()))));
root.then(Commands.literal("list")
.executes((CommandContext<CommandSourceStack> context) -> list(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> list(context.getSource()))));
root.then(Commands.literal("ls")
.executes((CommandContext<CommandSourceStack> context) -> list(context.getSource())));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> list(context.getSource()))));
root.then(enableTree("enable"));
root.then(enableTree("create"));
@@ -93,53 +93,53 @@ public final class ModdedWorldCommands {
return Commands.literal(name)
.then(Commands.argument("dimension", IdentifierArgument.id())
.then(Commands.argument("pack", StringArgumentType.string()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> enable(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> enable(context.getSource(),
dimensionArgument(context),
StringArgumentType.getString(context, "pack"),
null))
null)))
.then(Commands.argument("seed", StringArgumentType.word())
.executes((CommandContext<CommandSourceStack> context) -> enable(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> enable(context.getSource(),
dimensionArgument(context),
StringArgumentType.getString(context, "pack"),
StringArgumentType.getString(context, "seed"))))));
StringArgumentType.getString(context, "seed")))))));
}
private static LiteralArgumentBuilder<CommandSourceStack> disableTree() {
return Commands.literal("disable")
.then(Commands.argument("dimension", IdentifierArgument.id()).suggests(LOADED_DIMENSIONS)
.executes((CommandContext<CommandSourceStack> context) -> disable(context.getSource(), dimensionArgument(context), false)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> disable(context.getSource(), dimensionArgument(context), false))));
}
private static LiteralArgumentBuilder<CommandSourceStack> deleteTree(String name) {
return Commands.literal(name)
.then(Commands.argument("dimension", IdentifierArgument.id()).suggests(LOADED_DIMENSIONS)
.executes((CommandContext<CommandSourceStack> context) -> disable(context.getSource(), dimensionArgument(context), true)));
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> disable(context.getSource(), dimensionArgument(context), true))));
}
private static LiteralArgumentBuilder<CommandSourceStack> replaceOverworldTree() {
return Commands.literal("replace-overworld")
.then(Commands.argument("pack", StringArgumentType.string()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> replaceOverworld(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> replaceOverworld(context.getSource(),
StringArgumentType.getString(context, "pack"),
null))
null)))
.then(Commands.argument("seed", StringArgumentType.word())
.executes((CommandContext<CommandSourceStack> context) -> replaceOverworld(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> replaceOverworld(context.getSource(),
StringArgumentType.getString(context, "pack"),
StringArgumentType.getString(context, "seed")))));
StringArgumentType.getString(context, "seed"))))));
}
private static LiteralArgumentBuilder<CommandSourceStack> mainWorldTree() {
return Commands.literal("mainworld")
.then(Commands.literal("off")
.executes((CommandContext<CommandSourceStack> context) -> clearMainWorld(context.getSource())))
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> clearMainWorld(context.getSource()))))
.then(Commands.argument("pack", StringArgumentType.string()).suggests(IrisModdedCommands.PACK_NAMES)
.executes((CommandContext<CommandSourceStack> context) -> mainWorld(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> mainWorld(context.getSource(),
StringArgumentType.getString(context, "pack"),
null))
null)))
.then(Commands.argument("seed", StringArgumentType.word())
.executes((CommandContext<CommandSourceStack> context) -> mainWorld(context.getSource(),
.executes(ModdedCommandTree.localized((CommandContext<CommandSourceStack> context) -> mainWorld(context.getSource(),
StringArgumentType.getString(context, "pack"),
StringArgumentType.getString(context, "seed")))));
StringArgumentType.getString(context, "seed"))))));
}
public static int createWorld(CommandSourceStack source, String name, String pack, long seed) {
@@ -30,6 +30,10 @@ public class IrisModdedCommandParityTest {
IrisModdedCommands.register(dispatcher);
CommandNode<CommandSourceStack> iris = child(dispatcher.getRoot(), "iris");
CommandNode<CommandSourceStack> language = child(iris, "language");
assertNotNull(language.getCommand());
child(child(language, "self"), "locale");
child(child(language, "server"), "locale");
CommandNode<CommandSourceStack> what = child(iris, "what");
child(what, "here");
child(what, "biome");
@@ -0,0 +1,125 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.volmlib.util.director.help.DirectorHelpMessages;
import art.arcane.volmlib.util.localization.PluginLanguageService;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.server.Bootstrap;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
public class ModdedLanguageCommandsTest {
@Test
public void personalFailureReportsTheCommittedEnglishFallback() throws Exception {
assertPersonalCompletion("de_DE", "en_US", "Iris: de_DE unavailable; using English (en_US).");
}
@Test
public void personalResetReportsTheInheritedLanguage() throws Exception {
assertPersonalCompletion("reset", "fr_FR", "Language updated: fr_FR");
}
@Test
public void personalSuccessReportsTheSelectedLanguage() throws Exception {
assertPersonalCompletion("de_DE", "de_DE", "Language updated: de_DE");
}
@Test
public void pickerRendersTheNativeHelpFrameAndLanguageActions() throws Exception {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
CommandSourceStack source = mock(CommandSourceStack.class, RETURNS_DEEP_STUBS);
when(source.getPlayer()).thenReturn(null);
List<Component> rendered = new ArrayList<>();
doAnswer(invocation -> {
Supplier<Component> message = invocation.getArgument(0);
rendered.add(message.get());
return null;
}).when(source).sendSuccess(any(), eq(false));
try (MockedStatic<IrisLanguage> language = mockStatic(IrisLanguage.class)) {
language.when(IrisLanguage::activeLocale).thenReturn("en_US");
language.when(IrisLanguage::availableLocales).thenReturn(Set.of("de_DE"));
language.when(() -> IrisLanguage.plain(DirectorHelpMessages.BACK)).thenReturn("Back");
CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
dispatcher.register(Commands.literal("iris").then(ModdedLanguageCommands.tree()));
assertEquals(1, dispatcher.execute("iris language", source));
}
assertEquals(6, rendered.size());
assertEquals(ModdedCommandFeedback.banner("/iris language"), rendered.getFirst());
assertEquals(new ClickEvent.RunCommand("/iris"), rendered.get(1).getStyle().getClickEvent());
assertEquals("Iris language: en_US", rendered.get(2).getString());
Component locale = rendered.get(3);
assertTrue(locale.getString().contains("[me]"));
assertFalse(locale.getString().contains("[server]"));
assertEquals(new ClickEvent.RunCommand("/iris language self de_DE"),
locale.getSiblings().getFirst().getStyle().getClickEvent());
assertEquals(new ClickEvent.RunCommand("/iris language self reset"), rendered.get(4).getStyle().getClickEvent());
assertEquals(ModdedCommandFeedback.footer(), rendered.getLast());
}
private void assertPersonalCompletion(String requested, String selected, String expected) throws Exception {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
CommandSourceStack source = mock(CommandSourceStack.class, RETURNS_DEEP_STUBS);
ServerPlayer player = mock(ServerPlayer.class);
UUID playerId = UUID.randomUUID();
when(source.getPlayer()).thenReturn(player);
when(player.getUUID()).thenReturn(playerId);
MinecraftServer server = source.getServer();
PluginLanguageService service = mock(PluginLanguageService.class);
CompletableFuture<Void> selection = new CompletableFuture<>();
when(service.selectPlayer(playerId, requested)).thenReturn(selection);
when(service.clearPlayer(playerId)).thenReturn(selection);
when(service.effectiveLocale(playerId)).thenReturn(selected);
List<Component> rendered = new ArrayList<>();
doAnswer(invocation -> {
Supplier<Component> message = invocation.getArgument(0);
rendered.add(message.get());
return null;
}).when(source).sendSuccess(any(), eq(false));
doAnswer(invocation -> {
Runnable task = invocation.getArgument(0);
task.run();
return null;
}).when(server).execute(any(Runnable.class));
try (MockedStatic<IrisLanguage> language = mockStatic(IrisLanguage.class)) {
language.when(IrisLanguage::selections).thenReturn(service);
CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
dispatcher.register(Commands.literal("iris").then(ModdedLanguageCommands.tree()));
assertEquals(1, dispatcher.execute("iris language self " + requested, source));
assertTrue(rendered.isEmpty());
selection.complete(null);
}
assertEquals(List.of(expected), rendered.stream().map(Component::getString).toList());
}
}
@@ -6,6 +6,8 @@ import art.arcane.volmlib.util.localization.TextKey;
import java.util.List;
public final class DirectorCommandMessages {
public static final TextKey DEBUG_DUMP_DESCRIPTION = TextKey.of("iris.director.commandiris.director.debugdump", "Create and optionally upload a diagnostic report");
public static final TextKey DEBUG_DUMP_UPLOAD = TextKey.of("iris.director.commandiris.param.debugdump_upload", "Upload the report to mclo.gs");
public static final TextKey COMMAND_DATAPACK_DIRECTOR_DOWNLOAD_MANAGE_EXTERNAL_DATAPACK_IMPORTS_MODRINTH = TextKey.of(
"iris.director.commanddatapack.director.download_manage_external_datapack_imports_modrinth",
"Download & manage external datapack imports"
@@ -864,6 +866,8 @@ public final class DirectorCommandMessages {
);
private static final List<MessageKey> KEYS = List.of(
DEBUG_DUMP_DESCRIPTION,
DEBUG_DUMP_UPLOAD,
COMMAND_DATAPACK_DIRECTOR_DOWNLOAD_MANAGE_EXTERNAL_DATAPACK_IMPORTS_MODRINTH,
COMMAND_DATAPACK_DIRECTOR_DOWNLOAD_UPDATE_EVERY_DATAPACK_LISTED_PACK_DIMENSION_S_DATAPACKIMPORTS_INSTALL_IT_INTO,
COMMAND_DATAPACK_PARAM_RESTART_SERVER_WHEN_NEW_DATAPACKS_ARE_INSTALLED_REQUIRED_NEW_STRUCTURES_REGISTER_GENERATE,
@@ -1,6 +1,8 @@
{
"locale": "de_DE",
"messages": {
"iris.director.commandiris.director.debugdump": "Einen Diagnosebericht erstellen und optional hochladen",
"iris.director.commandiris.param.debugdump_upload": "Den Bericht zu mclo.gs hochladen",
"director.help.navigation.parent.hover": "Zur übergeordneten Befehlsgruppe zurückkehren",
"director.help.navigation.back": "Zurück",
"director.help.no_subcommands": "Auf dieser Seite gibt es keine Unterbefehle.",
@@ -1,6 +1,8 @@
{
"locale": "es_ES",
"messages": {
"iris.director.commandiris.director.debugdump": "Crear y subir opcionalmente un informe de diagnóstico",
"iris.director.commandiris.param.debugdump_upload": "Subir el informe a mclo.gs",
"director.help.navigation.parent.hover": "Volver al grupo de comandos superior",
"director.help.navigation.back": "Atrás",
"director.help.no_subcommands": "No hay subcomandos en esta página.",
@@ -1,6 +1,8 @@
{
"locale": "fi_FI",
"messages": {
"iris.director.commandiris.director.debugdump": "Luo diagnostiikkaraportti ja lähetä se halutessasi",
"iris.director.commandiris.param.debugdump_upload": "Lähetä raportti mclo.gs-palveluun",
"director.help.navigation.parent.hover": "Palaa ylempään komentoryhmään",
"director.help.navigation.back": "Takaisin",
"director.help.no_subcommands": "Tällä sivulla ei ole alikomentoja.",
@@ -1,6 +1,8 @@
{
"locale": "fr_FR",
"messages": {
"iris.director.commandiris.director.debugdump": "Créer un rapport de diagnostic et le publier si souhaité",
"iris.director.commandiris.param.debugdump_upload": "Publier le rapport sur mclo.gs",
"director.help.navigation.parent.hover": "Revenir au groupe de commandes parent",
"director.help.navigation.back": "Retour",
"director.help.no_subcommands": "Aucune sous-commande sur cette page.",
@@ -1,6 +1,8 @@
{
"locale": "he_IL",
"messages": {
"iris.director.commandiris.director.debugdump": "יצירת דוח אבחון והעלאתו לפי בחירה",
"iris.director.commandiris.param.debugdump_upload": "העלאת הדוח אל mclo.gs",
"director.help.navigation.parent.hover": "חזרה לקבוצת פקודות האב",
"director.help.navigation.back": "חזרה",
"director.help.no_subcommands": "אין פקודות משנה בעמוד זה.",
@@ -1,6 +1,8 @@
{
"locale": "it_IT",
"messages": {
"iris.director.commandiris.director.debugdump": "Crea un rapporto diagnostico e caricalo facoltativamente",
"iris.director.commandiris.param.debugdump_upload": "Carica il rapporto su mclo.gs",
"director.help.navigation.parent.hover": "Torna al gruppo di comandi principale",
"director.help.navigation.back": "Indietro",
"director.help.no_subcommands": "Nessun sottocomando in questa pagina.",
@@ -1,6 +1,8 @@
{
"locale": "ja-JP",
"messages": {
"iris.director.commandiris.director.debugdump": "診断レポートを作成し、必要に応じてアップロードする",
"iris.director.commandiris.param.debugdump_upload": "レポートを mclo.gs にアップロードする",
"director.help.navigation.parent.hover": "親コマンドグループに戻る",
"director.help.navigation.back": "戻る",
"director.help.no_subcommands": "このページにサブコマンドはありません。",
@@ -1,6 +1,8 @@
{
"locale": "ko_KR",
"messages": {
"iris.director.commandiris.director.debugdump": "진단 보고서를 생성하고 선택적으로 업로드",
"iris.director.commandiris.param.debugdump_upload": "보고서를 mclo.gs에 업로드",
"director.help.navigation.parent.hover": "상위 명령어 그룹으로 돌아가기",
"director.help.navigation.back": "뒤로",
"director.help.no_subcommands": "이 페이지에는 하위 명령어가 없습니다.",
@@ -1,6 +1,8 @@
{
"locale": "lt_LT",
"messages": {
"iris.director.commandiris.director.debugdump": "Sukurti diagnostikos ataskaitą ir pasirinktinai ją įkelti",
"iris.director.commandiris.param.debugdump_upload": "Įkelti ataskaitą į mclo.gs",
"director.help.navigation.parent.hover": "Grįžti į pirminę komandų grupę",
"director.help.navigation.back": "Atgal",
"director.help.no_subcommands": "Šiame puslapyje nėra antrinių komandų.",
@@ -1,6 +1,8 @@
{
"locale": "nl_NL",
"messages": {
"iris.director.commandiris.director.debugdump": "Maak een diagnostisch rapport en upload het desgewenst",
"iris.director.commandiris.param.debugdump_upload": "Upload het rapport naar mclo.gs",
"director.help.navigation.parent.hover": "Terug naar de bovenliggende opdrachtgroep",
"director.help.navigation.back": "Terug",
"director.help.no_subcommands": "Geen subopdrachten op deze pagina.",
@@ -1,6 +1,8 @@
{
"locale": "pl_PL",
"messages": {
"iris.director.commandiris.director.debugdump": "Utwórz raport diagnostyczny i opcjonalnie go prześlij",
"iris.director.commandiris.param.debugdump_upload": "Prześlij raport do mclo.gs",
"director.help.navigation.parent.hover": "Wróć do nadrzędnej grupy poleceń",
"director.help.navigation.back": "Wstecz",
"director.help.no_subcommands": "Na tej stronie nie ma podpoleceń.",
@@ -1,6 +1,8 @@
{
"locale": "pt_PT",
"messages": {
"iris.director.commandiris.director.debugdump": "Criar um relatório de diagnóstico e carregá-lo opcionalmente",
"iris.director.commandiris.param.debugdump_upload": "Carregar o relatório para mclo.gs",
"director.help.navigation.parent.hover": "Voltar ao grupo de comandos principal",
"director.help.navigation.back": "Voltar",
"director.help.no_subcommands": "Não existem subcomandos nesta página.",
@@ -1,6 +1,8 @@
{
"locale": "ru_RU",
"messages": {
"iris.director.commandiris.director.debugdump": "Создать диагностический отчёт и при желании загрузить его",
"iris.director.commandiris.param.debugdump_upload": "Загрузить отчёт на mclo.gs",
"director.help.navigation.parent.hover": "Вернуться к родительской группе команд",
"director.help.navigation.back": "Назад",
"director.help.no_subcommands": "На этой странице нет подкоманд.",
@@ -1,6 +1,8 @@
{
"locale": "tr_TR",
"messages": {
"iris.director.commandiris.director.debugdump": "Tanılama raporu oluştur ve isteğe bağlı olarak yükle",
"iris.director.commandiris.param.debugdump_upload": "Raporu mclo.gs üzerine yükle",
"director.help.navigation.parent.hover": "Üst komut grubuna dön",
"director.help.navigation.back": "Geri",
"director.help.no_subcommands": "Bu sayfada alt komut yok.",
@@ -1,6 +1,8 @@
{
"locale": "vi_VI",
"messages": {
"iris.director.commandiris.director.debugdump": "Tạo báo cáo chẩn đoán và tải lên nếu muốn",
"iris.director.commandiris.param.debugdump_upload": "Tải báo cáo lên mclo.gs",
"director.help.navigation.parent.hover": "Quay lại nhóm lệnh cha",
"director.help.navigation.back": "Quay lại",
"director.help.no_subcommands": "Không có lệnh con trên trang này.",
@@ -1,6 +1,8 @@
{
"locale": "zh_CN",
"messages": {
"iris.director.commandiris.director.debugdump": "创建诊断报告并选择是否上传",
"iris.director.commandiris.param.debugdump_upload": "将报告上传到 mclo.gs",
"director.help.navigation.parent.hover": "返回上级命令组",
"director.help.navigation.back": "返回",
"director.help.no_subcommands": "此页面没有子命令。",
@@ -1,6 +1,8 @@
{
"locale": "zh_TW",
"messages": {
"iris.director.commandiris.director.debugdump": "建立診斷報告並選擇是否上傳",
"iris.director.commandiris.param.debugdump_upload": "將報告上傳至 mclo.gs",
"director.help.navigation.parent.hover": "返回上層命令群組",
"director.help.navigation.back": "返回",
"director.help.no_subcommands": "此頁面沒有子命令。",