Skip to content

Commit

Permalink
fix(commands): update command registration and improve error handling
Browse files Browse the repository at this point in the history
Signed-off-by: TimMayr <[email protected]>
  • Loading branch information
TimMayr committed Feb 9, 2025
1 parent 8edefad commit 4cf8431
Show file tree
Hide file tree
Showing 15 changed files with 211 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,13 @@ public class Schematica {
public static void init() {
if (Platform.getEnv() == EnvType.CLIENT) {
Schematica.clientInit();
} else {
Schematica.serverInit();
}

CommandRegistrationEvent.EVENT.register(
(dispatcher, context, selection) -> CommandSchematicaBase.register(dispatcher));

if (Platform.getEnv() == EnvType.SERVER) {
LifecycleEvent.SERVER_STARTING.register(
(server) -> ServerProxy.serverWeakReference = new WeakReference<>(server));
}

Reference.proxy = EnvExecutor.getEnvSpecific(() -> ClientProxy::new, () -> ServerProxy::new);
Reference.proxy.init();
PacketHandler.init();
Expand All @@ -48,7 +45,11 @@ public static void init() {
}

private static void clientInit() {
ClientCommandRegistrationEvent.EVENT.register(
((dispatcher, context) -> CommandSchematicaBase.registerClient(context)));
ClientCommandRegistrationEvent.EVENT.register(CommandSchematicaBase::registerClient);
}

private static void serverInit() {
LifecycleEvent.SERVER_STARTING.register(
(server) -> ServerProxy.serverWeakReference = new WeakReference<>(server));
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.github.lunatrius.schematica.command;

import com.github.lunatrius.schematica.command.client.CommandSchematicaReplace;
import com.github.lunatrius.schematica.reference.Names;
import com.github.lunatrius.schematica.reference.Reference;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.CommandNode;
import dev.architectury.event.events.client.ClientCommandRegistrationEvent;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
Expand All @@ -27,7 +29,7 @@
import java.util.concurrent.CompletableFuture;

public abstract class CommandSchematicaBase {
private static LiteralCommandNode<CommandSourceStack> mainNode;
private static CommandNode<CommandSourceStack> rootNode;

protected static @NotNull MutableComponent withStyle(MutableComponent component, ChatFormatting formatting,
@Nullable String command) {
Expand All @@ -41,15 +43,15 @@ public abstract class CommandSchematicaBase {
}

public static void register(@NotNull CommandDispatcher<CommandSourceStack> dispatcher) {
mainNode = dispatcher.register(Commands.literal("schematica")
.then(CommandSchematicaDownload.register())
.then(CommandSchematicaList.register())
.then(CommandSchematicaSave.register())
.then(CommandSchematicaRemove.register()));
rootNode = dispatcher.register(Commands.literal(Names.Command.BASE)
.then(CommandSchematicaDownload.register())
.then(CommandSchematicaList.register())
.then(CommandSchematicaSave.register())
.then(CommandSchematicaRemove.register()));
}

public static void registerClient(CommandBuildContext context) {
mainNode.addChild(CommandSchematicaReplace.register(context).build());
public static void registerClient(@NotNull CommandDispatcher<ClientCommandRegistrationEvent.ClientCommandSourceStack> dispatcher, CommandBuildContext context) {
dispatcher.register(CommandSchematicaReplace.register(context));
}

public static CompletableFuture<Suggestions> getSchematicNamesSuggestions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,43 @@ public class CommandSchematicaDownload extends CommandSchematicaBase {

public static ArgumentBuilder<CommandSourceStack, ?> register() {
return Commands.literal(Names.Command.Download.NAME)
.then(Commands.argument("filename", StringArgumentType.string())
.suggests(
((context, builder) -> CommandSchematicaBase.getSchematicNamesSuggestions(
context, builder, FILE_FILTER_SCHEMATIC)))
.executes((commandContext) -> {
CommandSourceStack source = commandContext.getSource();
ServerPlayer player = source.getPlayerOrException();
.then(Commands.argument("filename", StringArgumentType.string())
.suggests(
((context, builder) -> CommandSchematicaBase.getSchematicNamesSuggestions(
context, builder, FILE_FILTER_SCHEMATIC)))
.executes((commandContext) -> {
CommandSourceStack source = commandContext.getSource();
ServerPlayer player = source.getPlayerOrException();

String filename = StringArgumentType.getString(commandContext, "filename");
File directory = Reference.proxy.getPlayerSchematicDirectory(player, true);
String filename = StringArgumentType.getString(commandContext, "filename");
File directory = Reference.proxy.getPlayerSchematicDirectory(player, true);

if (!FileUtils.contains(directory, filename)) {
Reference.logger.error("{} has tried to download" + " the file " + "{}",
player.getName(), filename);
if (!FileUtils.contains(directory, filename)) {
Reference.logger.error("{} has tried to download" + " the file " + "{}",
player.getName(), filename);

source.sendFailure(Component.translatable(
Names.Command.Download.Message.DOWNLOAD_FAILED));
return -1;
}
source.sendFailure(Component.translatable(
Names.Command.Download.Message.DOWNLOAD_FAILED));
return -1;
}

ISchematic schematic = SchematicFormat.readFromFile(directory, filename,
Reference.proxy.getLevel(
player));
ISchematic schematic = SchematicFormat.readFromFile(directory, filename,
Reference.proxy.getLevel(
player));

if (schematic != null) {
DownloadHandler.INSTANCE.transferMap.put(player.getScoreboardName(),
new SchematicTransfer(schematic,
filename));
source.sendSuccess(() -> Component.translatable(
Names.Command.Download.Message.DOWNLOAD_STARTED, filename), true);
} else {
source.sendFailure(Component.translatable(
Names.Command.Download.Message.DOWNLOAD_FAILED));
return -1;
}
if (schematic != null) {
DownloadHandler.INSTANCE.transferMap.put(player.getScoreboardName(),
new SchematicTransfer(schematic,
filename));
source.sendSuccess(() -> Component.translatable(
Names.Command.Download.Message.DOWNLOAD_STARTED, filename), true);
} else {
source.sendFailure(Component.translatable(
Names.Command.Download.Message.DOWNLOAD_FAILED));
return -1;
}

return 0;
}));
return 0;
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public class CommandSchematicaList extends CommandSchematicaBase {

public static ArgumentBuilder<CommandSourceStack, ?> register() {
return Commands.literal(Names.Command.List.NAME)
.executes(CommandSchematicaList::printList)
.then(Commands.argument("page", IntegerArgumentType.integer(1))
.executes(CommandSchematicaList::printList));
.executes(CommandSchematicaList::printList)
.then(Commands.argument("page", IntegerArgumentType.integer(1))
.executes(CommandSchematicaList::printList));
}

private static int printList(@NotNull CommandContext<CommandSourceStack> commandContext)
Expand Down Expand Up @@ -60,7 +60,7 @@ private static int printList(@NotNull CommandContext<CommandSourceStack> command
if (!schematicDirectory.exists()) {
if (!schematicDirectory.mkdirs()) {
Reference.logger.warn("Could not create player schematic directory {}",
schematicDirectory.getAbsolutePath());
schematicDirectory.getAbsolutePath());

source.sendFailure(Component.translatable(Names.Command.Save.Message.PLAYER_SCHEMATIC_DIR_UNAVAILABLE));
return -1;
Expand All @@ -74,23 +74,23 @@ private static int printList(@NotNull CommandContext<CommandSourceStack> command
String fileName = path.getName();

Component chatComponent = Component.literal(String.format("%2d (%s): %s [", currentFile + 1,
FileUtils.humanReadableByteCount(
path.length()),
FilenameUtils.removeExtension(fileName)));
FileUtils.humanReadableByteCount(
path.length()),
FilenameUtils.removeExtension(fileName)));

String removeCommand =
String.format("/%s %s", Reference.MOD_ID + " " + Names.Command.Remove.NAME, fileName);
Component removeLink =
withStyle(Component.translatable(Names.Command.List.Message.REMOVE), ChatFormatting.RED,
removeCommand);
removeCommand);
chatComponent = chatComponent.copy().append(removeLink).append("][");

String downloadCommand =
String.format("/%s %s", Reference.MOD_ID + " " + Names.Command.Download.NAME, fileName);
Component downloadLink =
withStyle(Component.translatable(Names.Command.List.Message.DOWNLOAD),
ChatFormatting.GREEN,
downloadCommand);
ChatFormatting.GREEN,
downloadCommand);
chatComponent = chatComponent.copy().append(downloadLink).append("]");

componentsToSend.add(chatComponent);
Expand All @@ -112,7 +112,7 @@ private static int printList(@NotNull CommandContext<CommandSourceStack> command

source.sendSystemMessage(
withStyle(Component.translatable(Names.Command.List.Message.PAGE_HEADER, page + 1, totalPages + 1),
ChatFormatting.DARK_GREEN, null));
ChatFormatting.DARK_GREEN, null));
for (Component chatComponent : componentsToSend) {
source.sendSystemMessage(chatComponent);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,20 @@
public class CommandSchematicaSave extends CommandSchematicaBase {
public static ArgumentBuilder<CommandSourceStack, ?> register() {
return Commands.literal(Names.Command.Save.NAME)
.then(Commands.argument("from", BlockPosArgument.blockPos())
.then(Commands.argument("to", BlockPosArgument.blockPos())
.then(Commands.argument("name", StringArgumentType.string())
.executes(CommandSchematicaSave::execute)
.then(Commands.argument("format",
StringArgumentType.string())
.suggests(((context, builder) -> {
for (String s :
SchematicFormat.FORMATS.keySet()) {
builder.suggest(s);
}
return builder.buildFuture();
}))
.executes(
CommandSchematicaSave::execute)))));
.then(Commands.argument("from", BlockPosArgument.blockPos())
.then(Commands.argument("to", BlockPosArgument.blockPos())
.then(Commands.argument("name", StringArgumentType.string())
.executes(CommandSchematicaSave::execute)
.then(Commands.argument("format",
StringArgumentType.string())
.suggests(((context, builder) -> {
for (String s :
SchematicFormat.FORMATS.keySet()) {
builder.suggest(s);
}
return builder.buildFuture();
}))
.executes(CommandSchematicaSave::execute)))));
}

private static int execute(@NotNull CommandContext<CommandSourceStack> commandContext)
Expand Down Expand Up @@ -67,7 +66,7 @@ private static int execute(@NotNull CommandContext<CommandSourceStack> commandCo

String filename = name + SchematicFormat.getExtension(format);

Reference.logger.debug("Saving " + "schematic from {} to {} to {}", from, to, filename);
Reference.logger.debug("Saving schematic from {} to {} to {}", from, to, filename);
File schematicDirectory = Reference.proxy.getPlayerSchematicDirectory(player, true);
if (schematicDirectory == null) {
//Chances are that if this is null, we could not retrieve their UUID.
Expand All @@ -79,15 +78,15 @@ private static int execute(@NotNull CommandContext<CommandSourceStack> commandCo
if (!schematicDirectory.exists()) {
if (!schematicDirectory.mkdirs()) {
Reference.logger.warn("Could not create " + "player " + "schematic " + "directory " + "{}",
schematicDirectory.getAbsolutePath());
schematicDirectory.getAbsolutePath());
source.sendFailure(Component.translatable(Names.Command.Save.Message.PLAYER_SCHEMATIC_DIR_UNAVAILABLE));
return -1;
}
}

try {
Reference.proxy.saveSchematic(player, schematicDirectory, filename, player.getCommandSenderWorld(), format,
from, to);
from, to);
} catch (Exception e) {
source.sendFailure(Component.translatable(Names.Command.Save.Message.SAVE_FAILED));
return -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,53 @@
import com.github.lunatrius.schematica.reference.Names;
import com.github.lunatrius.schematica.reference.Reference;
import com.github.lunatrius.schematica.world.FakeLevel;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import dev.architectury.event.events.client.ClientCommandRegistrationEvent;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.blocks.BlockInput;
import net.minecraft.commands.arguments.blocks.BlockStateArgument;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockStateMatchTest;

public class CommandSchematicaReplace extends CommandSchematicaBase {
public static ArgumentBuilder<CommandSourceStack, ?> register(CommandBuildContext context) {
return Commands.literal(Names.Command.Replace.NAME)
.then(Commands.argument("toReplace", BlockStateArgument.block(context))
.then(Commands.argument("with", BlockStateArgument.block(context)))
.executes((commandContext) -> {
CommandSourceStack source = commandContext.getSource();
BlockState toReplace =
BlockStateArgument.getBlock(commandContext, "toReplace").getState();
BlockState with =
BlockStateArgument.getBlock(commandContext, "with").getState();
public static LiteralArgumentBuilder<ClientCommandRegistrationEvent.ClientCommandSourceStack> register(CommandBuildContext context) {
return ClientCommandRegistrationEvent.literal(Names.Command.BASE).then(
ClientCommandRegistrationEvent.literal(Names.Command.Replace.NAME)
.then(ClientCommandRegistrationEvent.argument("toReplace", BlockStateArgument.block(context))
.then(ClientCommandRegistrationEvent.argument("with",
BlockStateArgument.block(context))
.executes((commandContext) -> {
ClientCommandRegistrationEvent.ClientCommandSourceStack source =
commandContext.getSource();

FakeLevel schematic = ClientProxy.schematic;
BlockState toReplace = commandContext.getArgument("toReplace",
BlockInput.class).getState();
BlockState with =
commandContext.getArgument("with", BlockInput.class).getState();

if (schematic == null) {
source.sendFailure(Component.translatable(
Names.Command.Replace.Message.NO_SCHEMATIC));
return -1;
}
FakeLevel schematic = ClientProxy.schematic;

try {
BlockStateMatchTest matcher = new BlockStateMatchTest(toReplace);
BlockStateReplacer replacer = BlockStateReplacer.forBlockState(with);
int count = schematic.replaceBlock(matcher, replacer);
if (schematic == null) {
source.arch$sendFailure(Component.translatable(
Names.Command.Replace.Message.NO_SCHEMATIC));
return -1;
}

source.sendSuccess(
() -> Component.translatable(Names.Command.Replace.Message.SUCCESS,
count), true);
} catch (Exception e) {
Reference.logger.error("Something went wrong!", e);
source.sendFailure(Component.literal(e.getMessage()));
return -1;
}
return 0;
}));
try {
BlockStateMatchTest matcher = new BlockStateMatchTest(toReplace);
BlockStateReplacer replacer = BlockStateReplacer.forBlockState(with);
int count = schematic.replaceBlock(matcher, replacer);

source.arch$sendSuccess(
() -> Component.translatable(Names.Command.Replace.Message.SUCCESS,
count), true);
} catch (Exception e) {
Reference.logger.error("Something went wrong!", e);
source.arch$sendFailure(Component.literal(e.getMessage()));
return -1;
}
return 0;
}))));
}
}
Loading

0 comments on commit 4cf8431

Please sign in to comment.