diff --git a/src/main/java/me/youhavetrouble/blockedit/BELocale.java b/src/main/java/me/youhavetrouble/blockedit/BELocale.java index 37bc4fa..b5e1000 100644 --- a/src/main/java/me/youhavetrouble/blockedit/BELocale.java +++ b/src/main/java/me/youhavetrouble/blockedit/BELocale.java @@ -1,7 +1,7 @@ package me.youhavetrouble.blockedit; import com.google.gson.JsonObject; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Locale; @@ -14,32 +14,44 @@ public class BELocale { public final String couldNotFindWandById, selectArea, copiedSelectionToClipboard, selectionReset, firstPositionSet, secondPositionSet, pastingClipboard, clipboardRotated, settingBlocks, replacingBlocks, schematicLoaded, - startedLoadingSchematic, noProviderForSchematicFileExtension, schematicLoadError, schematicNotFound; + startedLoadingSchematic, noProviderForSchematicFileExtension, schematicLoadError, schematicNotFound, + providerNotFound; protected BELocale(JsonObject json) { - couldNotFindWandById = json.get("could_not_find_wand_by_id").getAsString(); - selectArea = json.get("select_area").getAsString(); - copiedSelectionToClipboard = json.get("copied_selection_to_clipboard").getAsString(); - selectionReset = json.get("selection_reset").getAsString(); - firstPositionSet = json.get("first_position_set").getAsString(); - secondPositionSet = json.get("second_position_set").getAsString(); - pastingClipboard = json.get("pasting_clipboard").getAsString(); - clipboardRotated = json.get("clipboard_rotated").getAsString(); - settingBlocks = json.get("setting_blocks").getAsString(); - replacingBlocks = json.get("replacing_blocks").getAsString(); - startedLoadingSchematic = json.get("started_loading_schematic").getAsString(); - schematicLoaded = json.get("schematic_loaded").getAsString(); - noProviderForSchematicFileExtension = json.get("no_provider_for_schematic_file_extension").getAsString(); - schematicLoadError = json.get("schematic_load_error").getAsString(); - schematicNotFound = json.get("schematic_not_found").getAsString(); + couldNotFindWandById = getString(json, "could_not_find_wand_by_id"); + selectArea = getString(json, "select_area"); + copiedSelectionToClipboard = getString(json, "copied_selection_to_clipboard"); + selectionReset = getString(json, "selection_reset"); + firstPositionSet = getString(json, "first_position_set"); + secondPositionSet = getString(json, "second_position_set"); + pastingClipboard = getString(json, "pasting_clipboard"); + clipboardRotated = getString(json, "clipboard_rotated"); + settingBlocks = getString(json, "setting_blocks"); + replacingBlocks = getString(json, "replacing_blocks"); + startedLoadingSchematic = getString(json, "started_loading_schematic"); + schematicLoaded = getString(json, "schematic_loaded"); + noProviderForSchematicFileExtension = getString(json, "no_provider_for_schematic_file_extension"); + schematicLoadError = getString(json, "schematic_load_error"); + schematicNotFound = getString(json, "schematic_not_found"); + providerNotFound = getString(json, "provider_not_found"); + } + + @Nullable + private String getString(JsonObject jsonObject, String key) { + if (jsonObject.has(key)) { + return jsonObject.get(key).getAsString(); + } else { + return null; + } } protected static void registerLocale(Locale locale, BELocale blockEditLocale) { locales.put(locale, blockEditLocale); } - public static BELocale getLocale(@NotNull Locale locale) { + public static BELocale getLocale(@Nullable Locale locale) { + if (locale == null) return locales.get(defaultLocale); BELocale beLocale = locales.get(locale); if (beLocale == null) beLocale = locales.get(defaultLocale); return beLocale; diff --git a/src/main/java/me/youhavetrouble/blockedit/BlockEditCommands.java b/src/main/java/me/youhavetrouble/blockedit/BlockEditCommands.java index 283c09c..5601ff0 100644 --- a/src/main/java/me/youhavetrouble/blockedit/BlockEditCommands.java +++ b/src/main/java/me/youhavetrouble/blockedit/BlockEditCommands.java @@ -12,12 +12,13 @@ import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolv import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import me.youhavetrouble.blockedit.api.BlockEditAPI; -import me.youhavetrouble.blockedit.exception.NoProviderForSchematicFileExtensionException; +import me.youhavetrouble.blockedit.commands.arguments.SchematicProviderArgument; import me.youhavetrouble.blockedit.exception.SchematicLoadException; import me.youhavetrouble.blockedit.operations.PasteOperation; import me.youhavetrouble.blockedit.operations.ReplaceOperation; import me.youhavetrouble.blockedit.operations.SetOperation; import me.youhavetrouble.blockedit.schematic.Schematic; +import me.youhavetrouble.blockedit.schematic.SchematicProvider; import me.youhavetrouble.blockedit.util.Selection; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -28,6 +29,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.concurrent.CompletableFuture; @@ -85,6 +87,11 @@ public class BlockEditCommands { "Replaces the specified block with another block" ); + commands.register( + schematicCommand(), + "Loads a schematic" + ); + }); } @@ -389,37 +396,33 @@ public class BlockEditCommands { .requires(commandSourceStack -> { if (!(commandSourceStack.getSender() instanceof Player player)) return false; - return player.hasPermission("blockedit.command.schematic.load.file"); + return player.hasPermission("blockedit.command.schematic.load"); }) .executes(context -> { - CompletableFuture.runAsync(() -> { - Player player = (Player) context.getSource().getSender(); - String schematicName = context.getArgument("schematic_name", String.class); - - player.sendMessage(Component.text(BELocale.getLocale(player.locale()).startedLoadingSchematic.formatted(schematicName), NamedTextColor.GRAY)); - - Schematic schematic; - try { - schematic = BlockEditAPI.getSchematicHandler().loadSchematic(schematicName); - } catch (NoProviderForSchematicFileExtensionException e) { - player.sendMessage(Component.text(BELocale.getLocale(player.locale()).noProviderForSchematicFileExtension.formatted(e.getExtension()), NamedTextColor.RED)); - return; - } catch (SchematicLoadException e) { - player.sendMessage(Component.text(BELocale.getLocale(player.locale()).schematicLoadError.formatted(schematicName), NamedTextColor.RED)); - BlockEdit.getPlugin().getSLF4JLogger().error("Could not load schematic {} due to provider error ", schematicName, e); - return; - } - - if (schematic == null) { - player.sendMessage(Component.text(BELocale.getLocale(player.locale()).schematicNotFound.formatted(schematicName), NamedTextColor.RED)); - return; - } - - BEPlayer bePlayer = BEPlayer.getByPlayer(player); - bePlayer.setClipboard(schematic.asClipboard()); - player.sendMessage(Component.text(BELocale.getLocale(player.locale()).schematicLoaded.formatted(schematicName), NamedTextColor.GRAY)); - }); - + Player player = (Player) context.getSource().getSender(); + loadSchematic( + player, + null, // file provider + context.getArgument("schematic_name", String.class) + ); + return Command.SINGLE_SUCCESS; + }) + ) + ) + .then(Commands.argument("provider_name", new SchematicProviderArgument(BlockEdit.getSchematicHandler())) + .then(Commands.argument("schematic_name", StringArgumentType.word()) + .requires(commandSourceStack -> { + if (!(commandSourceStack.getSender() instanceof Player player)) + return false; + return player.hasPermission("blockedit.command.schematic.load"); + }) + .executes(context -> { + Player player = (Player) context.getSource().getSender(); + loadSchematic( + player, + context.getArgument("provider_name", SchematicProvider.class), + context.getArgument("schematic_name", String.class) + ); return Command.SINGLE_SUCCESS; }) ) @@ -428,4 +431,38 @@ public class BlockEditCommands { .build(); } + private static void loadSchematic(@NotNull Player player, @Nullable SchematicProvider provider, @NotNull String schematicName) { + CompletableFuture.runAsync(() -> { + player.sendMessage(Component.text(BELocale.getLocale(player.locale()).startedLoadingSchematic.formatted(schematicName), NamedTextColor.GRAY)); + Schematic schematic; + + if (provider == null) { + try { + schematic = BlockEditAPI.getSchematicHandler().loadSchematic(schematicName); + } catch (SchematicLoadException e) { + player.sendMessage(Component.text(BELocale.getLocale(player.locale()).schematicLoadError.formatted(schematicName), NamedTextColor.RED)); + BlockEdit.getPlugin().getSLF4JLogger().error("Could not load schematic {} due to provider error ", schematicName, e); + return; + } + } else { + try { + schematic = provider.load(schematicName); + } catch (SchematicLoadException e) { + player.sendMessage(Component.text(BELocale.getLocale(player.locale()).schematicLoadError.formatted(schematicName), NamedTextColor.RED)); + BlockEdit.getPlugin().getSLF4JLogger().error("Could not load schematic {} due to provider error ", schematicName, e); + return; + } + } + + if (schematic == null) { + player.sendMessage(Component.text(BELocale.getLocale(player.locale()).schematicNotFound.formatted(schematicName), NamedTextColor.RED)); + return; + } + + BEPlayer bePlayer = BEPlayer.getByPlayer(player); + bePlayer.setClipboard(schematic.asClipboard()); + player.sendMessage(Component.text(BELocale.getLocale(player.locale()).schematicLoaded.formatted(schematicName), NamedTextColor.GRAY)); + }); + } + } diff --git a/src/main/java/me/youhavetrouble/blockedit/SchematicHandler.java b/src/main/java/me/youhavetrouble/blockedit/SchematicHandler.java index c464994..9c6649a 100644 --- a/src/main/java/me/youhavetrouble/blockedit/SchematicHandler.java +++ b/src/main/java/me/youhavetrouble/blockedit/SchematicHandler.java @@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.*; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -39,6 +40,14 @@ public class SchematicHandler { } } + public Collection getSchematicProvidersList() { + return schematicProvidersByName.keySet(); + } + + public SchematicProvider getSchematicProviderByName(String name) { + return schematicProvidersByName.get(name); + } + public void registerSchematicProvider( @NotNull SchematicProvider schematicProvider ) throws SchematicHandlerRegistrationException { diff --git a/src/main/java/me/youhavetrouble/blockedit/commands/arguments/SchematicProviderArgument.java b/src/main/java/me/youhavetrouble/blockedit/commands/arguments/SchematicProviderArgument.java new file mode 100644 index 0000000..5201c54 --- /dev/null +++ b/src/main/java/me/youhavetrouble/blockedit/commands/arguments/SchematicProviderArgument.java @@ -0,0 +1,60 @@ +package me.youhavetrouble.blockedit.commands.arguments; + +import com.mojang.brigadier.LiteralMessage; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +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 io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import me.youhavetrouble.blockedit.SchematicHandler; +import me.youhavetrouble.blockedit.commands.exceptiontype.UnknownProviderExceptionType; +import me.youhavetrouble.blockedit.schematic.Schematic; +import me.youhavetrouble.blockedit.schematic.SchematicProvider; +import org.jetbrains.annotations.NotNull; + +import java.util.Locale; +import java.util.concurrent.CompletableFuture; + +@SuppressWarnings("UnstableApiUsage") +public class SchematicProviderArgument implements CustomArgumentType, String> { + + private final SchematicHandler schematicHandler; + + public SchematicProviderArgument(@NotNull SchematicHandler schematicHandler) { + this.schematicHandler = schematicHandler; + } + + @Override + public @NotNull SchematicProvider parse(StringReader reader) throws CommandSyntaxException { + int cursor = reader.getCursor(); + String arg = reader.getString().toLowerCase(Locale.ENGLISH); + + if (!this.schematicHandler.getSchematicProvidersList().contains(arg)) { + throw new CommandSyntaxException( + new UnknownProviderExceptionType(), + new LiteralMessage("Provider not found"), + arg, + cursor + ); + } + + return schematicHandler.getSchematicProviderByName(arg); + } + + @Override + public @NotNull ArgumentType getNativeType() { + return StringArgumentType.word(); + } + + @Override + public @NotNull CompletableFuture listSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + for (String providerName : schematicHandler.getSchematicProvidersList()) { + if (!providerName.startsWith(builder.getRemaining())) continue; + builder.suggest(providerName); + } + return builder.buildFuture(); + } +} diff --git a/src/main/java/me/youhavetrouble/blockedit/commands/exceptiontype/UnknownProviderExceptionType.java b/src/main/java/me/youhavetrouble/blockedit/commands/exceptiontype/UnknownProviderExceptionType.java new file mode 100644 index 0000000..fd73372 --- /dev/null +++ b/src/main/java/me/youhavetrouble/blockedit/commands/exceptiontype/UnknownProviderExceptionType.java @@ -0,0 +1,6 @@ +package me.youhavetrouble.blockedit.commands.exceptiontype; + +import com.mojang.brigadier.exceptions.CommandExceptionType; + +public class UnknownProviderExceptionType implements CommandExceptionType { +} diff --git a/src/main/resources/locale/en_US.json b/src/main/resources/locale/en_US.json index 4b3a64b..cd04b65 100644 --- a/src/main/resources/locale/en_US.json +++ b/src/main/resources/locale/en_US.json @@ -11,6 +11,7 @@ "replacing_blocks": "Replacing blocks...", "started_loading_schematic": "Started loading schematic %s", "schematic_loaded": "Loaded schematic %s", + "provider_not_found": "Provider not found", "no_provider_for_schematic_file": "No provider for schematic file type %s", "schematic_load_error": "Error loading schematic %s: %s", "schematic_not_found": "Schematic %s not found" diff --git a/src/main/resources/locale/pl_PL.json b/src/main/resources/locale/pl_PL.json index 18c019c..acb12a8 100644 --- a/src/main/resources/locale/pl_PL.json +++ b/src/main/resources/locale/pl_PL.json @@ -8,5 +8,11 @@ "pasting_clipboard": "Wklejanie ze schowka...", "clipboard_rotated": "Schowek obrócony o %s stopni", "setting_blocks": "Ustawianie bloków...", - "replacing_blocks": "Zastępowanie bloków..." + "replacing_blocks": "Zastępowanie bloków...", + "started_loading_schematic": "Rozpoczęto ładowanie schematu %s", + "schematic_loaded": "Załadowano schemat %s", + "provider_not_found": "Nie znaleziono dostawcy", + "no_provider_for_schematic_file": "Nie znaleziono dostawcy dla typu pliku %s", + "schematic_load_error": "Błąd podczas ładowania schematu %s: %s", + "schematic_not_found": "Nie znaleziono schematu %s" }