diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 1d3389b09..6fc1cec83 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -53,4 +53,5 @@ dependencies { implementation("net.minecraftforge.gradle:ForgeGradle:3.0.143") implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") + implementation("gradle.plugin.com.mendhak.gradlecrowdin:plugin:0.1.0") } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java index fe5114cb1..e5545a804 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java @@ -32,9 +32,11 @@ import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.BlockCommandSender; +import java.util.Locale; import java.util.UUID; import javax.annotation.Nullable; @@ -91,7 +93,12 @@ public class BukkitBlockCommandSender extends AbstractNonPlayerActor implements @Override public void print(Component component) { - TextAdapter.sendComponent(sender, WorldEditText.format(component)); + TextAdapter.sendComponent(sender, WorldEditText.format(component, getLocale())); + } + + @Override + public Locale getLocale() { + return Locale.US; } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java index de2a5ffa1..a314b4855 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java @@ -30,6 +30,7 @@ import org.enginehub.piston.inject.MapBackedValueStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; import java.util.Optional; import static com.google.common.base.Preconditions.checkNotNull; @@ -52,7 +53,7 @@ class BukkitCommandInspector implements CommandInspector { public String getShortText(Command command) { Optional mapping = dispatcher.getCommand(command.getName()); if (mapping.isPresent()) { - return reduceToText(mapping.get().getDescription()); + return reduceToText(mapping.get().getDescription(), Locale.US); } else { logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); return "Help text not available"; @@ -63,7 +64,7 @@ class BukkitCommandInspector implements CommandInspector { public String getFullText(Command command) { Optional mapping = dispatcher.getCommand(command.getName()); if (mapping.isPresent()) { - return reduceToText(mapping.get().getFullHelp()); + return reduceToText(mapping.get().getFullHelp(), Locale.US); } else { logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); return "Help text not available"; diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java index 75d5aa903..33dc3594c 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java @@ -31,6 +31,7 @@ import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.Locale; import java.util.UUID; import javax.annotation.Nullable; @@ -94,7 +95,7 @@ public class BukkitCommandSender extends AbstractNonPlayerActor { @Override public void print(Component component) { - TextAdapter.sendComponent(sender, WorldEditText.format(component)); + TextAdapter.sendComponent(sender, WorldEditText.format(component, getLocale())); } @Override @@ -111,6 +112,11 @@ public class BukkitCommandSender extends AbstractNonPlayerActor { public void checkPermission(String permission) throws AuthorizationException { } + @Override + public Locale getLocale() { + return Locale.US; + } + @Override public SessionKey getSessionKey() { return new SessionKey() { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 75b9c0ff7..7abaf32be 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.bukkit; import com.sk89q.util.StringUtil; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; @@ -33,13 +34,13 @@ import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.formatting.WorldEditText; import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; -import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -130,7 +131,7 @@ public class BukkitPlayer extends AbstractPlayerActor { @Override public void print(Component component) { - TextAdapter.sendComponent(player, WorldEditText.format(component)); + TextAdapter.sendComponent(player, WorldEditText.format(component, getLocale())); } @Override @@ -216,6 +217,11 @@ public class BukkitPlayer extends AbstractPlayerActor { return player.teleport(BukkitAdapter.adapt(location)); } + @Override + public Locale getLocale() { + return Locale.forLanguageTag(player.getLocale().replace('_', '-')); + } + @Nullable @Override public T getFacet(Class cls) { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index 0fda56974..5a9ca9b93 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -43,6 +43,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -168,8 +169,9 @@ public class BukkitServerInterface implements MultiUserPlatform { Stream.of(command.getName()), command.getAliases().stream() ).toArray(String[]::new); - return new CommandInfo(reduceToText(command.getUsage()), - reduceToText(command.getDescription()), aliases, + // TODO Handle localisation correctly + return new CommandInfo(reduceToText(command.getUsage(), Locale.US), + reduceToText(command.getDescription(), Locale.US), aliases, inspector, permissionsArray); }).collect(Collectors.toList())); } diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLICommandSender.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLICommandSender.java index 970c11df5..2170cf17c 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLICommandSender.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLICommandSender.java @@ -32,6 +32,7 @@ import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentS import org.slf4j.Logger; import java.io.File; +import java.util.Locale; import java.util.UUID; public class CLICommandSender implements Actor { @@ -97,7 +98,7 @@ public class CLICommandSender implements Actor { @Override public void print(Component component) { - print(PlainComponentSerializer.INSTANCE.serialize(WorldEditText.format(component))); + print(PlainComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale()))); } @Override @@ -138,6 +139,11 @@ public class CLICommandSender implements Actor { public void dispatchCUIEvent(CUIEvent event) { } + @Override + public Locale getLocale() { + return Locale.getDefault(); + } + @Override public SessionKey getSessionKey() { return new SessionKey() { diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index 188dc7430..e03d384fb 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -1,11 +1,14 @@ import net.minecrell.gradle.licenser.LicenseExtension import org.gradle.plugins.ide.idea.model.IdeaModel +import com.mendhak.gradlecrowdin.DownloadTranslationsTask +import com.mendhak.gradlecrowdin.UploadSourceFileTask plugins { id("java-library") id("net.ltgt.apt-eclipse") id("net.ltgt.apt-idea") id("antlr") + id("com.mendhak.gradlecrowdin") } applyPlatformAndCoreConfiguration() @@ -84,3 +87,32 @@ sourceSets { } } } + +val crowdinApiKey = "crowdin_apikey" + +fun Project.applyPlatformCrowdInConfig() { + if (!project.hasProperty(crowdinApiKey)) ext[crowdinApiKey] = "" + + apply(plugin = "com.mendhak.gradlecrowdin") + + tasks.named("crowdinUpload") { + apiKey = crowdinApiKey + projectId = "worldedit-core" + files = arrayOf( + object { + var name = "strings.json" + var source = "$projectDir/src/main/resources/lang/strings.json" + } + ) + } + + tasks.named("crowdinDownload") { + apiKey = crowdinApiKey + destination = "$projectDir/src/main/resources/lang" + projectId = "worldedit-core" + } + + tasks.named("processResources").configure { + dependsOn("crowdinDownload") + } +} diff --git a/worldedit-core/doctools/src/main/kotlin/com/sk89q/worldedit/internal/util/RstWorldEditText.kt b/worldedit-core/doctools/src/main/kotlin/com/sk89q/worldedit/internal/util/RstWorldEditText.kt index 2b37700f6..04adb822e 100644 --- a/worldedit-core/doctools/src/main/kotlin/com/sk89q/worldedit/internal/util/RstWorldEditText.kt +++ b/worldedit-core/doctools/src/main/kotlin/com/sk89q/worldedit/internal/util/RstWorldEditText.kt @@ -7,9 +7,10 @@ import com.sk89q.worldedit.util.formatting.text.TranslatableComponent import com.sk89q.worldedit.util.formatting.text.event.ClickEvent import com.sk89q.worldedit.util.formatting.text.format.TextDecoration import org.enginehub.piston.util.TextHelper +import java.util.Locale fun reduceToRst(component: Component): String { - val formatted = WorldEditText.format(component) + val formatted = WorldEditText.format(component, Locale.US) return formatAsRst(formatted).toString() } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java index fade284c4..7c65784d2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -48,12 +48,14 @@ import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors; import com.sk89q.worldedit.util.eventbus.EventBus; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException; import com.sk89q.worldedit.util.io.file.FilenameException; import com.sk89q.worldedit.util.io.file.FilenameResolutionException; import com.sk89q.worldedit.util.io.file.InvalidFilenameException; import com.sk89q.worldedit.util.task.SimpleSupervisor; import com.sk89q.worldedit.util.task.Supervisor; +import com.sk89q.worldedit.util.translation.TranslationManager; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BundledBlockData; @@ -64,6 +66,7 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import javax.script.ScriptException; + import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; @@ -108,6 +111,7 @@ public final class WorldEdit { private final ListeningExecutorService executorService = MoreExecutors.listeningDecorator( EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20, "WorldEdit Task Executor - %s")); private final Supervisor supervisor = new SimpleSupervisor(); + private final TranslationManager translationManager = new TranslationManager(this); private final BlockFactory blockFactory = new BlockFactory(this); private final ItemFactory itemFactory = new ItemFactory(this); @@ -223,6 +227,15 @@ public final class WorldEdit { return sessions; } + /** + * Return the translation manager. + * + * @return the translation manager + */ + public TranslationManager getTranslationManager() { + return translationManager; + } + /** * Gets the path to a file. This method will check to see if the filename * has valid characters and has an extension. It also prevents directory @@ -684,13 +697,13 @@ public final class WorldEdit { engine.evaluate(script, filename, vars); } catch (ScriptException e) { player.printError("Failed to execute:"); - player.printRaw(e.getMessage()); + player.print(TextComponent.of(e.getMessage())); logger.warn("Failed to execute script", e); } catch (NumberFormatException | WorldEditException e) { throw e; } catch (Throwable e) { player.printError("Failed to execute (see console):"); - player.printRaw(e.getClass().getCanonicalName()); + player.print(TextComponent.of(e.getClass().getCanonicalName())); logger.warn("Failed to execute script", e); } finally { for (EditSession editSession : scriptContext.getEditSessions()) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java index 67bb630bd..9715ae8d1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -61,19 +61,19 @@ import static org.enginehub.piston.part.CommandParts.arg; @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ApplyBrushCommands { - private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region")) + private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TranslatableComponent.of("worldedit.brush.apply.shape")) .defaultsTo(ImmutableList.of()) .ofTypes(ImmutableList.of(Key.of(RegionFactory.class))) .build(); - private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TextComponent.of("The size of the brush")) + private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TranslatableComponent.of("worldedit.brush.apply.radius")) .defaultsTo(ImmutableList.of("5")) .ofTypes(ImmutableList.of(Key.of(double.class))) .build(); public static void register(CommandManagerService service, CommandManager commandManager, CommandRegistrationHandler registration) { commandManager.register("apply", builder -> { - builder.description(TextComponent.of("Apply brush, apply a function to every block")); + builder.description(TranslatableComponent.of("worldedit.brush.apply.description")); builder.action(org.enginehub.piston.Command.Action.NULL_ACTION); CommandManager manager = service.newCommandManager(); @@ -86,7 +86,7 @@ public class ApplyBrushCommands { builder.condition(new PermissionCondition(ImmutableSet.of("worldedit.brush.apply"))); builder.addParts(REGION_FACTORY, RADIUS); - builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use")) + builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TranslatableComponent.of("worldedit.brush.apply.type")) .withCommands(manager.getAllCommands().collect(Collectors.toList())) .required() .build()); @@ -125,8 +125,7 @@ public class ApplyBrushCommands { @Direction(includeDiagonals = true) com.sk89q.worldedit.util.Direction direction) throws WorldEditException { player.print(TextComponent.builder().append("WARNING: ", TextColor.RED, TextDecoration.BOLD) - .append("This brush simulates item usages. Its effects may not work on all platforms, may not be undo-able," + - " and may cause strange interactions with other mods/plugins. Use at your own risk.").build()); + .append(TranslatableComponent.of("worldedit.brush.apply.item.warning")).build()); setApplyBrush(parameters, player, localSession, new ItemUseFactory(item, direction)); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index 29747852e..9b40db6a8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -45,6 +45,11 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.component.PaginationBox; +import com.sk89q.worldedit.util.formatting.component.TextUtils; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.biome.BiomeType; @@ -56,10 +61,12 @@ import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.Switch; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; /** * Implements biome-related commands such as "/biomelist". @@ -117,24 +124,24 @@ public class BiomeCommands { BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); Set biomes = new HashSet<>(); - String qualifier; + String messageKey; if (useLineOfSight) { Location blockPosition = player.getBlockTrace(300); if (blockPosition == null) { - player.printError("No block in sight!"); + player.printError(TranslatableComponent.of("worldedit.raytrace.noblock")); return; } BiomeType biome = player.getWorld().getBiome(blockPosition.toVector().toBlockPoint().toBlockVector2()); biomes.add(biome); - qualifier = "at line of sight point"; + messageKey = "worldedit.biomeinfo.lineofsight"; } else if (usePosition) { BiomeType biome = player.getWorld().getBiome(player.getLocation().toVector().toBlockPoint().toBlockVector2()); biomes.add(biome); - qualifier = "at your position"; + messageKey = "worldedit.biomeinfo.position"; } else { World world = player.getWorld(); Region region = session.getSelection(world); @@ -149,18 +156,18 @@ public class BiomeCommands { } } - qualifier = "in your selection"; + messageKey = "worldedit.biomeinfo.selection"; } - player.print(biomes.size() != 1 ? "Biomes " + qualifier + ":" : "Biome " + qualifier + ":"); - for (BiomeType biome : biomes) { + List components = biomes.stream().map(biome -> { BiomeData data = biomeRegistry.getData(biome); if (data != null) { - player.print(" " + data.getName()); + return TextComponent.of(data.getName()).hoverEvent(HoverEvent.showText(TextComponent.of(biome.getId()))); } else { - player.print(" "); + return TextComponent.of(biome.getId()); } - } + }).collect(Collectors.toList()); + player.printInfo(TranslatableComponent.of(pluraliseI18n(messageKey, biomes.size()), TextUtils.join(components, TextComponent.of(", ")))); } @Command( @@ -193,7 +200,10 @@ public class BiomeCommands { FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace); Operations.completeLegacy(visitor); - player.print("Biomes were changed in " + visitor.getAffected() + " columns. You may have to rejoin your game (or close and reopen your world) to see a change."); + player.printInfo(TranslatableComponent.of( + pluraliseI18n("worldedit.setbiome.changed", visitor.getAffected()), + TextComponent.of(visitor.getAffected()) + )); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index e15159af6..5f716484a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -55,6 +55,8 @@ import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.request.RequestExtent; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.block.BlockTypes; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; @@ -88,7 +90,7 @@ public class BrushCommands { desc = "Unbind a bound brush from your current item" ) void none(Player player, LocalSession session) throws WorldEditException { - ToolCommands.setToolNone(player, session, "Brush"); + ToolCommands.setToolNone(player, session, true); } @Command( @@ -116,7 +118,7 @@ public class BrushCommands { tool.setBrush(new SphereBrush(), "worldedit.brush.sphere"); } - player.print(String.format("Sphere brush shape equipped (%.0f).", radius)); + player.printInfo(TranslatableComponent.of("worldedit.brush.sphere.equip", TextComponent.of((int) radius))); } @Command( @@ -147,7 +149,7 @@ public class BrushCommands { tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder"); } - player.print(String.format("Cylinder brush shape equipped (%.0f by %d).", radius, height)); + player.printInfo(TranslatableComponent.of("worldedit.brush.cylinder.equip", TextComponent.of((int) radius), TextComponent.of(height))); } @Command( @@ -183,7 +185,7 @@ public class BrushCommands { BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); tool.setBrush(new ClipboardBrush(newHolder, ignoreAir, usingOrigin, pasteEntities, pasteBiomes, sourceMask), "worldedit.brush.clipboard"); - player.print("Clipboard brush shape equipped."); + player.printInfo(TranslatableComponent.of("worldedit.brush.clipboard.equip")); } @Command( @@ -205,7 +207,12 @@ public class BrushCommands { tool.setSize(radius); tool.setBrush(new SmoothBrush(iterations, mask), "worldedit.brush.smooth"); - player.print(String.format("Smooth brush equipped (%.0f x %dx, using %s).", radius, iterations, mask == null ? "any block" : "filter")); + player.printInfo(TranslatableComponent.of( + "worldedit.brush.smooth.equip", + TextComponent.of((int) radius), + TextComponent.of(iterations), + TextComponent.of(mask == null ? "any block" : "filter") + )); } @Command( @@ -225,7 +232,7 @@ public class BrushCommands { tool.setMask(new BlockTypeMask(new RequestExtent(), BlockTypes.FIRE)); tool.setBrush(new SphereBrush(), "worldedit.brush.ex"); - player.print(String.format("Extinguisher equipped (%.0f).", radius)); + player.printInfo(TranslatableComponent.of("worldedit.brush.extinguish.equip", TextComponent.of((int) radius))); } @Command( @@ -245,8 +252,7 @@ public class BrushCommands { tool.setSize(radius); tool.setBrush(new GravityBrush(fromMaxY), "worldedit.brush.gravity"); - player.print(String.format("Gravity brush equipped (%.0f).", - radius)); + player.printInfo(TranslatableComponent.of("worldedit.brush.gravity.equip", TextComponent.of((int) radius))); } @Command( @@ -302,7 +308,7 @@ public class BrushCommands { tool.setSize(radius); tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher"); - player.print(String.format("Butcher brush equipped (%.0f).", radius)); + player.printInfo(TranslatableComponent.of("worldedit.brush.butcher.equip", TextComponent.of((int) radius))); } @Command( @@ -404,6 +410,6 @@ public class BrushCommands { tool.setFill(null); tool.setBrush(new OperationFactoryBrush(factory, shape, session), permission); - player.print("Set brush to " + factory); + player.printInfo(TranslatableComponent.of("worldedit.brush.operation.equip", TextComponent.of(factory.toString()))); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index b90fe7786..848ec49c0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -45,18 +45,21 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.Switch; -import java.util.List; - import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; +import java.util.List; + /** * Clipboard commands. */ @@ -87,9 +90,7 @@ public class ClipboardCommands { Operations.completeLegacy(copy); session.setClipboard(new ClipboardHolder(clipboard)); - List messages = Lists.newArrayList(); - copy.addStatusMessages(messages); - messages.forEach(actor::print); + copy.getStatusMessages().forEach(actor::print); } @Command( @@ -122,9 +123,7 @@ public class ClipboardCommands { Operations.completeLegacy(copy); session.setClipboard(new ClipboardHolder(clipboard)); - List messages = Lists.newArrayList(); - copy.addStatusMessages(messages); - messages.forEach(actor::print); + copy.getStatusMessages().forEach(actor::print); } @Command( @@ -153,7 +152,7 @@ public class ClipboardCommands { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); Region region = clipboard.getRegion(); - List messages = Lists.newArrayList(); + List messages = Lists.newArrayList(); BlockVector3 to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(actor); if (!onlySelect) { @@ -166,7 +165,7 @@ public class ClipboardCommands { .maskSource(sourceMask) .build(); Operations.completeLegacy(operation); - operation.addStatusMessages(messages); + messages.addAll(Lists.newArrayList(operation.getStatusMessages())); } if (selectPasted || onlySelect) { @@ -180,9 +179,9 @@ public class ClipboardCommands { } if (onlySelect) { - actor.print("Selected clipboard paste region."); + actor.printInfo(TranslatableComponent.of("worldedit.paste.selected")); } else { - actor.print("The clipboard has been pasted at " + to); + actor.printInfo(TranslatableComponent.of("worldedit.paste.pasted", TextComponent.of(to.toString()))); } messages.forEach(actor::print); } @@ -205,7 +204,7 @@ public class ClipboardCommands { if (Math.abs(yRotate % 90) > 0.001 || Math.abs(xRotate % 90) > 0.001 || Math.abs(zRotate % 90) > 0.001) { - actor.printDebug("Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended."); + actor.printDebug(TranslatableComponent.of("worldedit.rotate.no-interpolation")); } ClipboardHolder holder = session.getClipboard(); @@ -214,7 +213,7 @@ public class ClipboardCommands { transform = transform.rotateX(-xRotate); transform = transform.rotateZ(-zRotate); holder.setTransform(holder.getTransform().combine(transform)); - actor.print("The clipboard copy has been rotated."); + actor.printInfo(TranslatableComponent.of("worldedit.rotate.rotated")); } @Command( @@ -229,7 +228,7 @@ public class ClipboardCommands { AffineTransform transform = new AffineTransform(); transform = transform.scale(direction.abs().multiply(-2).add(1, 1, 1).toVector3()); holder.setTransform(holder.getTransform().combine(transform)); - actor.print("The clipboard copy has been flipped."); + actor.printInfo(TranslatableComponent.of("worldedit.flip.flipped")); } @Command( @@ -239,6 +238,6 @@ public class ClipboardCommands { @CommandPermissions("worldedit.clipboard.clear") public void clearClipboard(Actor actor, LocalSession session) throws WorldEditException { session.setClipboard(null); - actor.print("Clipboard cleared."); + actor.printInfo(TranslatableComponent.of("worldedit.clearclipboard.cleared")); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java index 748c7e3c5..b9a8a3093 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java @@ -48,6 +48,7 @@ import java.util.List; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; import static com.sk89q.worldedit.internal.command.CommandUtil.requireIV; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; /** * Extracted from {@link SelectionCommands} to allow importing of {@link Command}. @@ -89,7 +90,7 @@ public class ExpandCommands { private static Command createVertCommand(CommandManager commandManager) { return commandManager.newCommand("vert") - .description(TextComponent.of("Vertically expand the selection to world limits.")) + .description(TranslatableComponent.of("worldedit.expand.description.vert")) .action(parameters -> { expandVert( requireIV(Key.of(LocalSession.class), "localSession", parameters), @@ -110,8 +111,10 @@ public class ExpandCommands { session.getRegionSelector(player.getWorld()).learnChanges(); int newSize = region.getArea(); session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session); - player.print("Region expanded " + (newSize - oldSize) - + " blocks [top-to-bottom]."); + int changeSize = newSize - oldSize; + player.printInfo( + TranslatableComponent.of(pluraliseI18n("worldedit.expand.expanded.vert", changeSize), TextComponent.of(changeSize)) + ); } catch (RegionOperationException e) { player.printError(e.getMessage()); } @@ -148,7 +151,8 @@ public class ExpandCommands { session.getRegionSelector(world).explainRegionAdjust(actor, session); - actor.print("Region expanded " + (newSize - oldSize) + " block(s)."); + int changeSize = newSize - oldSize; + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.expand.expanded", changeSize), TextComponent.of(changeSize))); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 495b43663..80639abd3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.command; +import static com.google.common.base.Preconditions.checkNotNull; + import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; @@ -36,6 +38,9 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.util.formatting.component.PaginationBox; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.item.ItemType; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; @@ -50,8 +55,6 @@ import java.util.Map; import java.util.TreeMap; import java.util.concurrent.Callable; -import static com.google.common.base.Preconditions.checkNotNull; - /** * General WorldEdit commands. */ @@ -85,14 +88,17 @@ public class GeneralCommands { limit = limit == null ? config.defaultChangeLimit : Math.max(-1, limit); if (!mayDisable && config.maxChangeLimit > -1) { if (limit > config.maxChangeLimit) { - actor.printError("Your maximum allowable limit is " + config.maxChangeLimit + "."); + actor.printError(TranslatableComponent.of("worldedit.limit.too-high", TextComponent.of(config.maxChangeLimit))); return; } } session.setBlockChangeLimit(limit); - actor.print("Block change limit set to " + limit + "." - + (limit == config.defaultChangeLimit ? "" : " (Use //limit to go back to the default.)")); + Component component = TextComponent.empty().append(TranslatableComponent.of("worldedit.limit.set", TextComponent.of(limit))); + if (limit != config.defaultChangeLimit) { + component.append(TranslatableComponent.of("worldedit.limit.return-to-default", TextColor.GRAY)); + } + actor.printInfo(component); } @Command( @@ -109,14 +115,17 @@ public class GeneralCommands { limit = limit == null ? config.calculationTimeout : Math.max(-1, limit); if (!mayDisable && config.maxCalculationTimeout > -1) { if (limit > config.maxCalculationTimeout) { - actor.printError("Your maximum allowable timeout is " + config.maxCalculationTimeout + " ms."); + actor.printError(TranslatableComponent.of("worldedit.timeout.too-high", TextComponent.of(config.maxCalculationTimeout))); return; } } session.setTimeout(limit); - actor.print("Timeout time set to " + limit + " ms." - + (limit == config.calculationTimeout ? "" : " (Use //timeout to go back to the default.)")); + Component component = TextComponent.empty().append(TranslatableComponent.of("worldedit.timeout.set", TextComponent.of(limit))); + if (limit != config.calculationTimeout) { + component.append(TranslatableComponent.of("worldedit.timeout.return-to-default", TextColor.GRAY)); + } + actor.printInfo(component); } @Command( @@ -129,16 +138,16 @@ public class GeneralCommands { Boolean fastMode) { boolean hasFastMode = session.hasFastMode(); if (fastMode != null && fastMode == hasFastMode) { - actor.printError("Fast mode already " + (fastMode ? "enabled" : "disabled") + "."); + actor.printError(TranslatableComponent.of(fastMode ? "worldedit.fast.enabled.already" : "worldedit.fast.disabled.already")); return; } if (hasFastMode) { session.setFastMode(false); - actor.print("Fast mode disabled."); + actor.printInfo(TranslatableComponent.of("worldedit.fast.disabled")); } else { session.setFastMode(true); - actor.print("Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes."); + actor.printInfo(TranslatableComponent.of("worldedit.fast.enabled")); } } @@ -151,10 +160,10 @@ public class GeneralCommands { @Arg(desc = "The reorder mode", def = "") EditSession.ReorderMode reorderMode) { if (reorderMode == null) { - actor.print("The reorder mode is " + session.getReorderMode().getDisplayName()); + actor.printInfo(TranslatableComponent.of("worldedit.reorder.current", TextComponent.of(session.getReorderMode().getDisplayName()))); } else { session.setReorderMode(reorderMode); - actor.print("The reorder mode is now " + session.getReorderMode().getDisplayName()); + actor.printInfo(TranslatableComponent.of("worldedit.reorder.set", TextComponent.of(session.getReorderMode().getDisplayName()))); } } @@ -171,17 +180,17 @@ public class GeneralCommands { } boolean useServerCui = session.shouldUseServerCUI(); if (drawSelection != null && drawSelection == useServerCui) { - player.printError("Server CUI already " + (useServerCui ? "enabled" : "disabled") + "."); + player.printError(TranslatableComponent.of(useServerCui ? "worldedit.drawsel.enabled.already" : "worldedit.drawsel.disabled.already")); return; } if (useServerCui) { session.setUseServerCUI(false); session.updateServerCUI(player); - player.print("Server CUI disabled."); + player.printInfo(TranslatableComponent.of("worldedit.drawsel.disabled")); } else { session.setUseServerCUI(true); session.updateServerCUI(player); - player.print("Server CUI enabled. This only supports cuboid regions, with a maximum size of 32x32x32."); + player.printInfo(TranslatableComponent.of("worldedit.drawsel.enabled")); } } @@ -234,10 +243,10 @@ public class GeneralCommands { Mask mask) { if (mask == null) { session.setMask(null); - actor.print("Global mask disabled."); + actor.printInfo(TranslatableComponent.of("worldedit.gmask.disabled")); } else { session.setMask(mask); - actor.print("Global mask set."); + actor.printInfo(TranslatableComponent.of("worldedit.gmask.set")); } } @@ -248,9 +257,9 @@ public class GeneralCommands { ) public void togglePlace(Player player, LocalSession session) { if (session.togglePlacementPosition()) { - player.print("Now placing at pos #1."); + player.printInfo(TranslatableComponent.of("worldedit.toggleplace.pos1")); } else { - player.print("Now placing at the block you stand in."); + player.printInfo(TranslatableComponent.of("worldedit.toggleplace.player")); } } @@ -271,11 +280,11 @@ public class GeneralCommands { List query) { String search = String.join(" ", query); if (search.length() <= 2) { - actor.printError("Enter a longer search string (len > 2)."); + actor.printError(TranslatableComponent.of("worldedit.searchitem.too-short")); return; } if (blocksOnly && itemsOnly) { - actor.printError("You cannot use both the 'b' and 'i' flags simultaneously."); + actor.printError(TranslatableComponent.of("worldedit.searchitem.b-and-i")); return; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index d5adc0c59..1be270a60 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -27,6 +27,8 @@ import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; @@ -68,7 +70,7 @@ public class HistoryCommands { player.checkPermission("worldedit.history.undo.other"); undoSession = worldEdit.getSessionManager().findByName(playerName); if (undoSession == null) { - player.printError("Unable to find session for " + playerName); + player.printError(TranslatableComponent.of("worldedit.session.cant-find-session", TextComponent.of(playerName))); return; } } @@ -83,9 +85,9 @@ public class HistoryCommands { } } if (timesUndone > 0) { - player.print("Undid " + timesUndone + " available edits."); + player.printInfo(TranslatableComponent.of("worldedit.undo.undone", TextComponent.of(timesUndone))); } else { - player.printError("Nothing left to undo."); + player.printError(TranslatableComponent.of("worldedit.undo.none")); } } @@ -106,7 +108,7 @@ public class HistoryCommands { player.checkPermission("worldedit.history.redo.other"); redoSession = worldEdit.getSessionManager().findByName(playerName); if (redoSession == null) { - player.printError("Unable to find session for " + playerName); + player.printError(TranslatableComponent.of("worldedit.session.cant-find-session", TextComponent.of(playerName))); return; } } @@ -121,9 +123,9 @@ public class HistoryCommands { } } if (timesRedone > 0) { - player.print("Redid " + timesRedone + " available edits."); + player.printInfo(TranslatableComponent.of("worldedit.redo.redid", TextComponent.of(timesRedone))); } else { - player.printError("Nothing left to redo."); + player.printError(TranslatableComponent.of("worldedit.redo.none")); } } @@ -135,7 +137,7 @@ public class HistoryCommands { @CommandPermissions("worldedit.history.clear") public void clearHistory(Actor actor, LocalSession session) { session.clearHistory(); - actor.print("History cleared."); + actor.printInfo(TranslatableComponent.of("worldedit.clearhistory.cleared")); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index 0b70e0bd7..e168389b9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -27,6 +27,8 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; @@ -34,6 +36,7 @@ import org.enginehub.piston.annotation.param.Switch; import static com.google.common.base.Preconditions.checkNotNull; import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; /** * Commands for moving the player around. @@ -61,7 +64,7 @@ public class NavigationCommands { @CommandPermissions("worldedit.navigation.unstuck") public void unstuck(Player player) throws WorldEditException { player.findFreePosition(); - player.print("There you go!"); + player.printInfo(TranslatableComponent.of("worldedit.unstuck.moved")); } @Command( @@ -81,9 +84,9 @@ public class NavigationCommands { } } if (ascentLevels == 0) { - player.printError("No free spot above you found."); + player.printError(TranslatableComponent.of("worldedit.ascend.obstructed")); } else { - player.print((ascentLevels != 1) ? "Ascended " + ascentLevels + " levels." : "Ascended a level."); + player.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.ascend.moved", ascentLevels), TextComponent.of(ascentLevels))); } } @@ -104,9 +107,9 @@ public class NavigationCommands { } } if (descentLevels == 0) { - player.printError("No free spot below you found."); + player.printError(TranslatableComponent.of("worldedit.descend.obstructed")); } else { - player.print((descentLevels != 1) ? "Descended " + descentLevels + " levels." : "Descended a level."); + player.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.descend.moved", descentLevels), TextComponent.of(descentLevels))); } } @@ -127,9 +130,9 @@ public class NavigationCommands { boolean alwaysGlass = getAlwaysGlass(forceFlight, forceGlass); if (player.ascendToCeiling(clearance, alwaysGlass)) { - player.print("Whoosh!"); + player.printInfo(TranslatableComponent.of("worldedit.ceil.moved")); } else { - player.printError("No free spot above you found."); + player.printError(TranslatableComponent.of("worldedit.ceil.obstructed")); } } @@ -140,9 +143,9 @@ public class NavigationCommands { @CommandPermissions("worldedit.navigation.thru.command") public void thru(Player player) throws WorldEditException { if (player.passThroughForwardWall(6)) { - player.print("Whoosh!"); + player.printInfo(TranslatableComponent.of("worldedit.thru.moved")); } else { - player.printError("No free spot ahead of you found."); + player.printError(TranslatableComponent.of("worldedit.thru.obstructed")); } } @@ -157,9 +160,9 @@ public class NavigationCommands { Location pos = player.getSolidBlockTrace(300); if (pos != null) { player.findFreePosition(pos); - player.print("Poof!"); + player.printInfo(TranslatableComponent.of("worldedit.jumpto.moved")); } else { - player.printError("No block in sight!"); + player.printError(TranslatableComponent.of("worldedit.jumpto.none")); } } @@ -178,9 +181,9 @@ public class NavigationCommands { boolean forceGlass) throws WorldEditException { boolean alwaysGlass = getAlwaysGlass(forceFlight, forceGlass); if (player.ascendUpwards(distance, alwaysGlass)) { - player.print("Whoosh!"); + player.printInfo(TranslatableComponent.of("worldedit.up.moved")); } else { - player.printError("You would hit something above you."); + player.printError(TranslatableComponent.of("worldedit.up.obstructed")); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java index ea929ec49..964d1ae65 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java @@ -61,24 +61,24 @@ import static org.enginehub.piston.part.CommandParts.arg; @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class PaintBrushCommands { - private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region")) + private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TranslatableComponent.of("worldedit.brush.paint.shape")) .defaultsTo(ImmutableList.of()) .ofTypes(ImmutableList.of(Key.of(RegionFactory.class))) .build(); - private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TextComponent.of("The size of the brush")) + private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TranslatableComponent.of("worldedit.brush.paint.size")) .defaultsTo(ImmutableList.of("5")) .ofTypes(ImmutableList.of(Key.of(double.class))) .build(); - private static final CommandArgument DENSITY = arg(TranslatableComponent.of("density"), TextComponent.of("The density of the brush")) + private static final CommandArgument DENSITY = arg(TranslatableComponent.of("density"), TranslatableComponent.of("worldedit.brush.paint.density")) .defaultsTo(ImmutableList.of("20")) .ofTypes(ImmutableList.of(Key.of(double.class))) .build(); public static void register(CommandManagerService service, CommandManager commandManager, CommandRegistrationHandler registration) { commandManager.register("paint", builder -> { - builder.description(TextComponent.of("Paint brush, apply a function to a surface")); + builder.description(TranslatableComponent.of("worldedit.brush.paint.description")); builder.action(org.enginehub.piston.Command.Action.NULL_ACTION); CommandManager manager = service.newCommandManager(); @@ -91,7 +91,7 @@ public class PaintBrushCommands { builder.condition(new PermissionCondition(ImmutableSet.of("worldedit.brush.paint"))); builder.addParts(REGION_FACTORY, RADIUS, DENSITY); - builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use")) + builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TranslatableComponent.of("worldedit.brush.paint.type")) .withCommands(manager.getAllCommands().collect(Collectors.toList())) .required() .build()); @@ -131,8 +131,7 @@ public class PaintBrushCommands { @Direction(includeDiagonals = true) com.sk89q.worldedit.util.Direction direction) throws WorldEditException { player.print(TextComponent.builder().append("WARNING: ", TextColor.RED, TextDecoration.BOLD) - .append("This brush simulates item usages. Its effects may not work on all platforms, may not be undo-able," + - " and may cause strange interactions with other mods/plugins. Use at your own risk.").build()); + .append(TranslatableComponent.of("worldedit.brush.paint.item.warning")).build()); setPaintBrush(parameters, player, localSession, new ItemUseFactory(item, direction)); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 2aa18962f..3b9d11abe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.command; -import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; @@ -56,6 +55,10 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.util.formatting.component.TextUtils; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; @@ -99,12 +102,11 @@ public class RegionCommands { RegionVisitor visitor = new RegionVisitor(region, set); Operations.completeBlindly(visitor); - List messages = Lists.newArrayList(); - visitor.addStatusMessages(messages); + List messages = Lists.newArrayList(visitor.getStatusMessages()); if (messages.isEmpty()) { - actor.print("Operation completed."); + actor.printInfo(TranslatableComponent.of("worldedit.set.done")); } else { - actor.print("Operation completed (" + Joiner.on(", ").join(messages) + ")."); + actor.printInfo(TranslatableComponent.of("worldedit.set.done.verbose", TextUtils.join(messages, TextComponent.of(", ")))); } return visitor.getAffected(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java index fe197d04b..5adc7cd54 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java @@ -27,11 +27,11 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; -import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.util.formatting.component.PaginationBox; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; @@ -76,7 +76,7 @@ public class SnapshotCommands { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { - actor.printError("Snapshot/backup restore is not configured."); + actor.printError(TranslatableComponent.of("worldedit.restore.not-configured")); return; } @@ -101,7 +101,7 @@ public class SnapshotCommands { } } } catch (MissingWorldException ex) { - actor.printError("No snapshots were found for this world."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-for-world")); } } @@ -117,7 +117,7 @@ public class SnapshotCommands { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { - actor.printError("Snapshot/backup restore is not configured."); + actor.printError(TranslatableComponent.of("worldedit.restore.not-configured")); return; } @@ -128,12 +128,12 @@ public class SnapshotCommands { if (snapshot != null) { session.setSnapshot(null); - actor.print("Now using newest snapshot."); + actor.printInfo(TranslatableComponent.of("worldedit.snapshot.use.newest")); } else { - actor.printError("No snapshots were found."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-found")); } } catch (MissingWorldException ex) { - actor.printError("No snapshots were found for this world."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-for-world")); } } else { try { @@ -156,7 +156,7 @@ public class SnapshotCommands { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { - actor.printError("Snapshot/backup restore is not configured."); + actor.printError(TranslatableComponent.of("worldedit.restore.not-configured")); return; } @@ -179,7 +179,7 @@ public class SnapshotCommands { session.setSnapshot(snapshot); actor.print("Snapshot set to: " + snapshot.getName()); } catch (MissingWorldException e) { - actor.printError("No snapshots were found for this world."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-for-world")); } } @@ -195,7 +195,7 @@ public class SnapshotCommands { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { - actor.printError("Snapshot/backup restore is not configured."); + actor.printError(TranslatableComponent.of("worldedit.restore.not-configured")); return; } @@ -210,7 +210,7 @@ public class SnapshotCommands { actor.print("Snapshot set to: " + snapshot.getName()); } } catch (MissingWorldException ex) { - actor.printError("No snapshots were found for this world."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-for-world")); } } @@ -226,7 +226,7 @@ public class SnapshotCommands { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { - actor.printError("Snapshot/backup restore is not configured."); + actor.printError(TranslatableComponent.of("worldedit.restore.not-configured")); return; } @@ -240,7 +240,7 @@ public class SnapshotCommands { actor.print("Snapshot set to: " + snapshot.getName()); } } catch (MissingWorldException ex) { - actor.printError("No snapshots were found for this world."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-for-world")); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index f8dd5689a..37a0043b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -29,6 +29,8 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException; @@ -68,7 +70,7 @@ public class SnapshotUtilCommands { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { - actor.printError("Snapshot/backup restore is not configured."); + actor.printError(TranslatableComponent.of("worldedit.restore.not-configured")); return; } @@ -79,7 +81,7 @@ public class SnapshotUtilCommands { try { snapshot = config.snapshotRepo.getSnapshot(snapshotName); } catch (InvalidSnapshotException e) { - actor.printError("That snapshot does not exist or is not available."); + actor.printError(TranslatableComponent.of("worldedit.restore.not-available")); return; } } else { @@ -92,7 +94,7 @@ public class SnapshotUtilCommands { snapshot = config.snapshotRepo.getDefaultSnapshot(world.getName()); if (snapshot == null) { - actor.printError("No snapshots were found. See console for details."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-found-console")); // Okay, let's toss some debugging information! File dir = config.snapshotRepo.getDirectory(); @@ -109,7 +111,7 @@ public class SnapshotUtilCommands { return; } } catch (MissingWorldException ex) { - actor.printError("No snapshots were found for this world."); + actor.printError(TranslatableComponent.of("worldedit.restore.none-for-world")); return; } } @@ -119,9 +121,9 @@ public class SnapshotUtilCommands { // Load chunk store try { chunkStore = snapshot.getChunkStore(); - actor.print("Snapshot '" + snapshot.getName() + "' loaded; now restoring..."); + actor.printInfo(TranslatableComponent.of("worldedit.restore.loaded", TextComponent.of(snapshot.getName()))); } catch (DataException | IOException e) { - actor.printError("Failed to load snapshot: " + e.getMessage()); + actor.printError(TranslatableComponent.of("worldedit.restore.failed", TextComponent.of(e.getMessage()))); return; } @@ -135,18 +137,17 @@ public class SnapshotUtilCommands { if (restore.hadTotalFailure()) { String error = restore.getLastErrorMessage(); if (!restore.getMissingChunks().isEmpty()) { - actor.printError("Chunks were not present in snapshot."); + actor.printError(TranslatableComponent.of("worldedit.restore.chunk-not-present")); } else if (error != null) { - actor.printError("Errors prevented any blocks from being restored."); - actor.printError("Last error: " + error); + actor.printError(TranslatableComponent.of("worldedit.restore.block-place-failed")); + actor.printError(TranslatableComponent.of("worldedit.restore.block-place-error", TextComponent.of(error))); } else { - actor.printError("No chunks could be loaded. (Bad archive?)"); + actor.printError(TranslatableComponent.of("worldedit.restore.chunk-load-failed")); } } else { - actor.print(String.format("Restored; %d " - + "missing chunks and %d other errors.", - restore.getMissingChunks().size(), - restore.getErrorChunks().size())); + actor.printInfo(TranslatableComponent.of("worldedit.restore.restored", + TextComponent.of(restore.getMissingChunks().size()), + TextComponent.of(restore.getErrorChunks().size()))); } } finally { try { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java index 754473a9a..cec687204 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java @@ -29,6 +29,8 @@ import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; @@ -49,7 +51,7 @@ public class SuperPickaxeCommands { public void single(Player player, LocalSession session) throws WorldEditException { session.setSuperPickaxe(new SinglePickaxe()); session.enableSuperPickAxe(); - player.print("Mode changed. Left click with a pickaxe. // to disable."); + player.printInfo(TranslatableComponent.of("worldedit.superpickaxe.mode.single")); } @Command( @@ -64,13 +66,13 @@ public class SuperPickaxeCommands { LocalConfiguration config = we.getConfiguration(); if (range > config.maxSuperPickaxeSize) { - player.printError("Maximum range: " + config.maxSuperPickaxeSize); + player.printError(TranslatableComponent.of("worldedit.superpickaxe.max-range", TextComponent.of(config.maxSuperPickaxeSize))); return; } session.setSuperPickaxe(new AreaPickaxe(range)); session.enableSuperPickAxe(); - player.print("Mode changed. Left click with a pickaxe. // to disable."); + player.printInfo(TranslatableComponent.of("worldedit.superpickaxe.mode.area")); } @Command( @@ -86,12 +88,12 @@ public class SuperPickaxeCommands { LocalConfiguration config = we.getConfiguration(); if (range > config.maxSuperPickaxeSize) { - player.printError("Maximum range: " + config.maxSuperPickaxeSize); + player.printError(TranslatableComponent.of("worldedit.superpickaxe.max-range", TextComponent.of(config.maxSuperPickaxeSize))); return; } session.setSuperPickaxe(new RecursivePickaxe(range)); session.enableSuperPickAxe(); - player.print("Mode changed. Left click with a pickaxe. // to disable."); + player.printInfo(TranslatableComponent.of("worldedit.superpickaxe.mode.recursive")); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 9418804b6..dfcb66d1b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -24,7 +24,6 @@ import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.command.tool.BlockDataCyler; import com.sk89q.worldedit.command.tool.BlockReplacer; import com.sk89q.worldedit.command.tool.DistanceWand; @@ -122,10 +121,10 @@ public class ToolCommands { return "/tool " + name; } - static void setToolNone(Player player, LocalSession session, String type) + static void setToolNone(Player player, LocalSession session, boolean isBrush) throws InvalidToolBindException { session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null); - player.print(type + " unbound from your current item."); + player.printInfo(TranslatableComponent.of(isBrush ? "worldedit.brush.none.equip" : "worldedit.tool.none.equip")); } private final WorldEdit we; @@ -140,7 +139,7 @@ public class ToolCommands { desc = "Unbind a bound tool from your current item" ) public void none(Player player, LocalSession session) throws WorldEditException { - setToolNone(player, session, "Tool"); + setToolNone(player, session, false); } @Command( @@ -153,7 +152,7 @@ public class ToolCommands { final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); session.setTool(itemType, new SelectionWand()); - player.print("Selection wand bound to " + itemType.getName() + "."); + player.printInfo(TranslatableComponent.of("worldedit.tool.selwand.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -164,9 +163,9 @@ public class ToolCommands { @CommandPermissions("worldedit.setwand") public void navwand(Player player, LocalSession session) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new NavigationWand()); - player.print("Navigation wand bound to " + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new NavigationWand()); + player.printInfo(TranslatableComponent.of("worldedit.tool.navWand.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -176,10 +175,9 @@ public class ToolCommands { @CommandPermissions("worldedit.tool.info") public void info(Player player, LocalSession session) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new QueryTool()); - player.print("Info tool bound to " - + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new QueryTool()); + player.printInfo(TranslatableComponent.of("worldedit.tool.info.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -191,9 +189,9 @@ public class ToolCommands { @Arg(desc = "Type of tree to generate", def = "tree") TreeGenerator.TreeType type) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new TreePlanter(type)); - player.print("Tree tool bound to " + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new TreePlanter(type)); + player.printInfo(TranslatableComponent.of("worldedit.tool.tree.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -205,9 +203,9 @@ public class ToolCommands { @Arg(desc = "The pattern of blocks to place") Pattern pattern) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new BlockReplacer(pattern)); - player.print("Block replacer tool bound to " + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new BlockReplacer(pattern)); + player.printInfo(TranslatableComponent.of("worldedit.tool.repl.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -217,9 +215,9 @@ public class ToolCommands { @CommandPermissions("worldedit.tool.data-cycler") public void cycler(Player player, LocalSession session) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new BlockDataCyler()); - player.print("Block data cycler tool bound to " + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new BlockDataCyler()); + player.printInfo(TranslatableComponent.of("worldedit.tool.data-cycler.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -241,9 +239,9 @@ public class ToolCommands { return; } - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new FloodFillTool(range, pattern)); - player.print("Block flood fill tool bound to " + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new FloodFillTool(range, pattern)); + player.printInfo(TranslatableComponent.of("worldedit.tool.floodfill.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -253,10 +251,9 @@ public class ToolCommands { @CommandPermissions("worldedit.tool.deltree") public void deltree(Player player, LocalSession session) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new FloatingTreeRemover()); - player.print("Floating tree remover tool bound to " - + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new FloatingTreeRemover()); + player.printInfo(TranslatableComponent.of("worldedit.tool.deltree.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -266,9 +263,9 @@ public class ToolCommands { @CommandPermissions("worldedit.tool.farwand") public void farwand(Player player, LocalSession session) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new DistanceWand()); - player.print("Far wand tool bound to " + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new DistanceWand()); + player.printInfo(TranslatableComponent.of("worldedit.tool.farwand.equip", TextComponent.of(itemType.getName()))); } @Command( @@ -282,10 +279,10 @@ public class ToolCommands { Pattern primary, @Arg(desc = "Pattern to set on right-click") Pattern secondary) throws WorldEditException { - BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new LongRangeBuildTool(primary, secondary)); - player.print("Long-range building tool bound to " + itemStack.getType().getName() + "."); + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new LongRangeBuildTool(primary, secondary)); + player.printInfo(TranslatableComponent.of("worldedit.tool.lrbuild.equip", TextComponent.of(itemType.getName()))); String primaryName = "pattern"; String secondaryName = "pattern"; if (primary instanceof BlockStateHolder) { @@ -294,7 +291,6 @@ public class ToolCommands { if (secondary instanceof BlockStateHolder) { secondaryName = ((BlockStateHolder) secondary).getBlockType().getName(); } - player.print("Left-click set to " + primaryName + "; right-click set to " - + secondaryName + "."); + player.printInfo(TranslatableComponent.of("worldedit.tool.lrbuild.set", TextComponent.of(primaryName), TextComponent.of(secondaryName))); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index c70e452e0..1252a12c6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.command; import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.IncompleteRegionException; @@ -52,6 +53,7 @@ import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.formatting.component.SubtleFormat; import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockTypes; @@ -99,7 +101,7 @@ public class UtilityCommands { BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.fillXZ(pos, pattern, radius, depth, false); - actor.print(affected + " block(s) have been created."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.fill.created", affected), TextComponent.of(affected))); return affected; } @@ -123,7 +125,7 @@ public class UtilityCommands { BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.fillXZ(pos, pattern, radius, depth, true); - actor.print(affected + " block(s) have been created."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.fillr.created", affected), TextComponent.of(affected))); return affected; } @@ -140,9 +142,8 @@ public class UtilityCommands { boolean waterlogged) throws WorldEditException { radius = Math.max(0, radius); we.checkMaxRadius(radius); - int affected = editSession.drainArea( - session.getPlacementPosition(actor), radius, waterlogged); - actor.print(affected + " block(s) have been changed."); + int affected = editSession.drainArea(session.getPlacementPosition(actor), radius, waterlogged); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.drain.drained", affected), TextComponent.of(affected))); return affected; } @@ -159,7 +160,7 @@ public class UtilityCommands { radius = Math.max(0, radius); we.checkMaxRadius(radius); int affected = editSession.fixLiquid(session.getPlacementPosition(actor), radius, BlockTypes.LAVA); - actor.print(affected + " block(s) have been changed."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.fixlava.fixed", affected), TextComponent.of(affected))); return affected; } @@ -176,7 +177,7 @@ public class UtilityCommands { radius = Math.max(0, radius); we.checkMaxRadius(radius); int affected = editSession.fixLiquid(session.getPlacementPosition(actor), radius, BlockTypes.WATER); - actor.print(affected + " block(s) have been changed."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.fixwater.fixed", affected), TextComponent.of(affected))); return affected; } @@ -197,7 +198,7 @@ public class UtilityCommands { height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1); int affected = editSession.removeAbove(session.getPlacementPosition(actor), size, height); - actor.print(affected + " block(s) have been removed."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.removeabove.removed", affected), TextComponent.of(affected))); return affected; } @@ -218,7 +219,7 @@ public class UtilityCommands { height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1); int affected = editSession.removeBelow(session.getPlacementPosition(actor), size, height); - actor.print(affected + " block(s) have been removed."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.removebelow.removed", affected), TextComponent.of(affected))); return affected; } @@ -238,7 +239,7 @@ public class UtilityCommands { we.checkMaxRadius(radius); int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, radius); - actor.print(affected + " block(s) have been removed."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.removenear.removed", affected), TextComponent.of(affected))); return affected; } @@ -269,7 +270,7 @@ public class UtilityCommands { } int affected = editSession.replaceBlocks(region, from, to); - actor.print(affected + " block(s) have been replaced."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.replacenear.replaced", affected), TextComponent.of(affected))); return affected; } @@ -287,7 +288,7 @@ public class UtilityCommands { we.checkMaxRadius(size); int affected = editSession.simulateSnow(session.getPlacementPosition(actor), size); - actor.print(affected + " surface(s) covered. Let it snow~"); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.snow.created", affected), TextComponent.of(affected))); return affected; } @@ -305,7 +306,7 @@ public class UtilityCommands { we.checkMaxRadius(size); int affected = editSession.thaw(session.getPlacementPosition(actor), size); - actor.print(affected + " surface(s) thawed."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.thaw.removed", affected), TextComponent.of(affected))); return affected; } @@ -326,7 +327,7 @@ public class UtilityCommands { final boolean onlyNormalDirt = !convertCoarse; final int affected = editSession.green(session.getPlacementPosition(actor), size, onlyNormalDirt); - actor.print(affected + " surface(s) greened."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.green.changed", affected), TextComponent.of(affected))); return affected; } @@ -337,7 +338,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.extinguish") @Logging(PLACEMENT) - public void extinguish(Actor actor, LocalSession session, EditSession editSession, + public int extinguish(Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the square to remove in", def = "") Integer radius) throws WorldEditException { @@ -349,7 +350,8 @@ public class UtilityCommands { Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE); int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, size); - actor.print(affected + " block(s) have been removed."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.extinguish.removed", affected), TextComponent.of(affected))); + return affected; } @Command( @@ -382,7 +384,7 @@ public class UtilityCommands { if (radius == null) { radius = config.butcherDefaultRadius; } else if (radius < -1) { - actor.printError("Use -1 to remove all mobs in loaded chunks"); + actor.printError(TranslatableComponent.of("worldedit.butcher.explain-all")); return 0; } else if (radius == -1) { if (config.butcherMaxRadius != -1) { @@ -405,7 +407,11 @@ public class UtilityCommands { int killed = killMatchingEntities(radius, actor, flags::createFunction); - actor.print("Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + "."); + actor.printInfo(TranslatableComponent.of( + pluraliseI18n("worldedit.butcher.killed", killed), + TextComponent.of(killed), + TextComponent.of(radius) + )); return killed; } @@ -423,13 +429,12 @@ public class UtilityCommands { @Arg(desc = "The radius of the cuboid to remove from") int radius) throws WorldEditException { if (radius < -1) { - actor.printError("Use -1 to remove all entities in loaded chunks"); + actor.printError(TranslatableComponent.of("worldedit.remove.explain-all")); return 0; } int removed = killMatchingEntities(radius, actor, remover::createFunction); - - actor.print("Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal."); + actor.printInfo(TranslatableComponent.of(pluraliseI18n("worldedit.remove.removed", removed), TextComponent.of(removed))); return removed; } @@ -460,10 +465,10 @@ public class UtilityCommands { return killed; } - // get the formatter with the system locale. in the future, if we can get a local from a player, we can use that - private static final DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.getDefault()); - static { - formatter.applyPattern("#,##0.#####"); // pattern is locale-insensitive. this can translate to "1.234,56789" + private DecimalFormat formatForLocale(Locale locale) { + DecimalFormat format = (DecimalFormat) NumberFormat.getInstance(locale); + format.applyPattern("#,##0.#####"); + return format; } @Command( @@ -479,14 +484,13 @@ public class UtilityCommands { try { expression = Expression.compile(String.join(" ", input)); } catch (ExpressionException e) { - actor.printError(String.format( - "'%s' could not be parsed as a valid expression", input)); + actor.printError(TranslatableComponent.of("worldedit.calc.invalid", TextComponent.of(String.join(" ", input)))); return; } WorldEditAsyncCommandBuilder.createAndSendMessage(actor, () -> { double result = expression.evaluate( new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout()); - String formatted = Double.isNaN(result) ? "NaN" : formatter.format(result); + String formatted = Double.isNaN(result) ? "NaN" : formatForLocale(actor.getLocale()).format(result); return SubtleFormat.wrap(input + " = ").append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE)); }, null); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index 45041b587..748ee62d4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -30,9 +30,13 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.NoCapablePlatformException; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.PlatformManager; +import com.sk89q.worldedit.util.formatting.component.MessageBox; +import com.sk89q.worldedit.util.formatting.component.TextComponentProducer; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.util.paste.ActorCallbackPaste; import com.sk89q.worldedit.util.report.ConfigReport; import com.sk89q.worldedit.util.report.ReportList; @@ -45,14 +49,13 @@ import org.enginehub.piston.annotation.param.Switch; import java.io.File; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.TextStyle; import java.time.zone.ZoneRulesException; import java.util.List; -import java.util.Locale; @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class WorldEditCommands { @@ -70,25 +73,31 @@ public class WorldEditCommands { desc = "Get WorldEdit version" ) public void version(Actor actor) { - actor.print("WorldEdit version " + WorldEdit.getVersion()); - actor.print("https://github.com/EngineHub/worldedit/"); + actor.printInfo(TranslatableComponent.of("worldedit.version.version", TextComponent.of(WorldEdit.getVersion()))); + actor.printInfo(TextComponent.of("https://github.com/EngineHub/worldedit/")); PlatformManager pm = we.getPlatformManager(); - actor.printDebug("----------- Platforms -----------"); + TextComponentProducer producer = new TextComponentProducer(); for (Platform platform : pm.getPlatforms()) { - actor.printDebug(String.format("* %s (%s)", platform.getPlatformName(), platform.getPlatformVersion())); + producer.append( + TextComponent.of("* ", TextColor.GRAY) + .append(TextComponent.of(platform.getPlatformName())) + .append(TextComponent.of("(" + platform.getPlatformVersion() + ")")) + ).newline(); } + actor.print(new MessageBox("Platforms", producer, TextColor.GRAY).create()); - actor.printDebug("----------- Capabilities -----------"); + producer.reset(); for (Capability capability : Capability.values()) { - try { - Platform platform = pm.queryCapability(capability); - actor.printDebug(String.format("%s: %s", capability.name(), platform != null ? platform.getPlatformName() : "NONE")); - } catch (NoCapablePlatformException e) { - actor.printDebug(String.format("%s: %s", capability.name(), "NONE")); - } + Platform platform = pm.queryCapability(capability); + producer.append( + TextComponent.of(capability.name(), TextColor.GRAY) + .append(TextComponent.of(": ") + .append(TextComponent.of(platform != null ? platform.getPlatformName() : "NONE"))) + ).newline(); } + actor.print(new MessageBox("Capabilities", producer, TextColor.GRAY).create()); } @Command( @@ -99,7 +108,7 @@ public class WorldEditCommands { public void reload(Actor actor) { we.getPlatformManager().queryCapability(Capability.CONFIGURATION).reload(); we.getEventBus().post(new ConfigurationLoadEvent(we.getPlatformManager().queryCapability(Capability.CONFIGURATION).getConfiguration())); - actor.print("Configuration reloaded!"); + actor.printInfo(TranslatableComponent.of("worldedit.reload.config")); } @Command( @@ -117,15 +126,15 @@ public class WorldEditCommands { try { File dest = new File(we.getConfiguration().getWorkingDirectory(), "report.txt"); - Files.write(result, dest, Charset.forName("UTF-8")); - actor.print("WorldEdit report written to " + dest.getAbsolutePath()); + Files.write(result, dest, StandardCharsets.UTF_8); + actor.printInfo(TranslatableComponent.of("worldedit.report.written", TextComponent.of(dest.getAbsolutePath()))); } catch (IOException e) { - actor.printError("Failed to write report: " + e.getMessage()); + actor.printError(TranslatableComponent.of("worldedit.report.error", TextComponent.of(e.getMessage()))); } if (pastebin) { actor.checkPermission("worldedit.report.pastebin"); - ActorCallbackPaste.pastebin(we.getSupervisor(), actor, result, "WorldEdit report: %s.report"); + ActorCallbackPaste.pastebin(we.getSupervisor(), actor, result, TranslatableComponent.builder("worldedit.report.callback")); } } @@ -148,12 +157,13 @@ public class WorldEditCommands { try { ZoneId tz = ZoneId.of(timezone); session.setTimezone(tz); - actor.print("Timezone set for this session to: " + tz.getDisplayName( - TextStyle.FULL, Locale.ENGLISH - )); - actor.print("The current time in that timezone is: " + dateFormat.format(ZonedDateTime.now(tz))); + actor.printInfo(TranslatableComponent.of("worldedit.timezone.set", TextComponent.of(tz.getDisplayName( + TextStyle.FULL, actor.getLocale() + )))); + actor.print(TranslatableComponent.of("worldedit.timezone.current", + TextComponent.of(dateFormat.withLocale(actor.getLocale()).format(ZonedDateTime.now(tz))))); } catch (ZoneRulesException e) { - actor.printError("Invalid timezone"); + actor.printError(TranslatableComponent.of("worldedit.timezone.invalid")); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java index 662f8d71e..10005b6c3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -83,7 +84,7 @@ public class AreaPickaxe implements BlockTool { } } } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } finally { session.remember(editSession); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java index ac3376d8d..afb37c38e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java @@ -30,6 +30,8 @@ import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockState; @@ -61,12 +63,12 @@ public class BlockDataCyler implements DoubleActionBlockTool { if (!config.allowedDataCycleBlocks.isEmpty() && !player.hasPermission("worldedit.override.data-cycler") && !config.allowedDataCycleBlocks.contains(block.getBlockType().getId())) { - player.printError("You are not permitted to cycle the data value of that block."); + player.printError(TranslatableComponent.of("worldedit.tool.data-cycler.block-not-permitted")); return true; } if (block.getStates().keySet().isEmpty()) { - player.printError("That block's data cannot be cycled!"); + player.printError(TranslatableComponent.of("worldedit.tool.data-cycler.cant-cycle")); } else { Property currentProperty = selectedProperties.get(player.getUniqueId()); @@ -88,9 +90,13 @@ public class BlockDataCyler implements DoubleActionBlockTool { try { editSession.setBlock(blockPoint, newBlock); - player.print("Value of " + currentProperty.getName() + " is now " + currentProperty.getValues().get(index)); + player.printInfo(TranslatableComponent.of( + "worldedit.tool.data-cycler.new-value", + TextComponent.of(currentProperty.getName()), + TextComponent.of(String.valueOf(currentProperty.getValues().get(index))) + )); } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } finally { session.remember(editSession); } @@ -101,7 +107,7 @@ public class BlockDataCyler implements DoubleActionBlockTool { index = (index + 1) % properties.size(); currentProperty = properties.get(index); selectedProperties.put(player.getUniqueId(), currentProperty); - player.print("Now cycling " + currentProperty.getName()); + player.printInfo(TranslatableComponent.of("worldedit.tool.data-cycler.cycling", TextComponent.of(currentProperty.getName()))); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java index 65d3f0ea0..48e3bbe2e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java @@ -30,6 +30,8 @@ import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.block.BaseBlock; /** @@ -77,7 +79,7 @@ public class BlockReplacer implements DoubleActionBlockTool { if (targetBlock != null) { pattern = targetBlock; - player.print("Replacer tool switched to: " + targetBlock.getBlockType().getName()); + player.printInfo(TranslatableComponent.of("worldedit.tool.repl.switched", TextComponent.of(targetBlock.getBlockType().getName()))); } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index e8724208b..6e1c38cff 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -35,6 +35,7 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import javax.annotation.Nullable; @@ -183,7 +184,7 @@ public class BrushTool implements TraceTool { Location target = player.getBlockTrace(getRange(), true, traceMask); if (target == null) { - player.printError("No block in sight!"); + player.printError(TranslatableComponent.of("worldedit.tool.no-block")); return true; } @@ -207,7 +208,7 @@ public class BrushTool implements TraceTool { try { brush.build(editSession, target.toVector().toBlockPoint(), material, size); } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } finally { session.remember(editSession); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java index 781d24f8c..2aef51e92 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; /** * A wand that can be used at a distance. @@ -74,7 +75,7 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool { } if (target == null) { - player.printError("No block in sight!"); + player.printError(TranslatableComponent.of("worldedit.tool.no-block")); return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java index 6c644c35e..a5dc96984 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java @@ -29,6 +29,7 @@ import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockState; @@ -72,7 +73,7 @@ public class FloatingTreeRemover implements BlockTool { final BlockState state = world.getBlock(clicked.toVector().toBlockPoint()); if (!isTreeBlock(state.getBlockType())) { - player.printError("That's not a tree."); + player.printError(TranslatableComponent.of("worldedit.tool.deltree.not-tree")); return true; } @@ -80,7 +81,7 @@ public class FloatingTreeRemover implements BlockTool { try { final Set blockSet = bfs(world, clicked.toVector().toBlockPoint()); if (blockSet == null) { - player.printError("That's not a floating tree."); + player.printError(TranslatableComponent.of("worldedit.tool.deltree.not-floating")); return true; } @@ -91,7 +92,7 @@ public class FloatingTreeRemover implements BlockTool { } } } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } finally { session.remember(editSession); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloodFillTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloodFillTool.java index 2206b8f94..07a6114d6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloodFillTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloodFillTool.java @@ -29,6 +29,7 @@ import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -73,7 +74,7 @@ public class FloodFillTool implements BlockTool { try { recurse(editSession, origin, origin, range, initialType, new HashSet<>()); } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } finally { session.remember(editSession); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java index f82d6961f..5121d345c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java @@ -31,6 +31,7 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.block.BaseBlock; /** @@ -118,7 +119,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo } if (target == null) { - player.printError("No block in sight!"); + player.printError(TranslatableComponent.of("worldedit.tool.no-block")); return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java index ca4d12745..bf8f29748 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; public class NavigationWand implements DoubleActionTraceTool { @Override @@ -40,7 +41,7 @@ public class NavigationWand implements DoubleActionTraceTool { if (pos != null) { player.findFreePosition(pos); } else { - player.printError("No block in sight (or too far)!"); + player.printError(TranslatableComponent.of("worldedit.jumpto.none")); } return true; } @@ -56,7 +57,7 @@ public class NavigationWand implements DoubleActionTraceTool { } if (!player.passThroughForwardWall(Math.max(1, maxDist - 10))) { - player.printError("Nothing to pass through (or too far)!"); + player.printError(TranslatableComponent.of("worldedit.thru.obstructed")); } return true; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java index 2c4e8ff87..be3ab2bdf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java @@ -29,6 +29,7 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.World; @@ -58,15 +59,15 @@ public class QueryTool implements BlockTool { builder.append(TextComponent.of("@" + clicked.toVector().toBlockPoint() + ": ", TextColor.BLUE)); builder.append(TextComponent.of(block.getBlockType().getName(), TextColor.YELLOW)); builder.append(TextComponent.of(" (" + block + ") ", TextColor.GRAY) - .hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Block state")))); + .hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TranslatableComponent.of("worldedit.tool.info.blockstate.hover")))); final OptionalInt internalId = BlockStateIdAccess.getBlockStateId(block.toImmutableState()); if (internalId.isPresent()) { builder.append(TextComponent.of(" (" + internalId.getAsInt() + ") ", TextColor.DARK_GRAY) - .hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Internal ID")))); + .hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TranslatableComponent.of("worldedit.tool.info.internalid.hover")))); } builder.append(TextComponent.of(" (" + world.getBlockLightLevel(blockPoint) + "/" + world.getBlockLightLevel(blockPoint.add(0, 1, 0)) + ")", TextColor.WHITE) - .hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Block Light/Light Above")))); + .hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TranslatableComponent.of("worldedit.tool.info.light.hover")))); player.print(builder.build()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java index 50008bd16..f85055dab 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -74,7 +75,7 @@ public class RecursivePickaxe implements BlockTool { recurse(server, editSession, world, clicked.toVector().toBlockPoint(), clicked.toVector().toBlockPoint(), range, initialType, new HashSet<>()); } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } finally { session.remember(editSession); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java index 6766528f4..ea724bdd8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -55,7 +56,7 @@ public class SinglePickaxe implements BlockTool { editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop); editSession.setBlock(blockPoint, BlockTypes.AIR.getDefaultState()); } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java index ec6e16723..4eaed7f4f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java @@ -29,6 +29,7 @@ import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; /** * Plants a tree. @@ -62,10 +63,10 @@ public class TreePlanter implements BlockTool { } if (!successful) { - player.printError("A tree can't go there."); + player.printError(TranslatableComponent.of("worldedit.tool.tree.obstructed")); } } catch (MaxChangedBlocksException e) { - player.printError("Max. blocks changed reached."); + player.printError(TranslatableComponent.of("worldedit.tool.max-block-changes")); } finally { session.remember(editSession); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandBuilder.java index b01b2f4fd..e8abdb958 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandBuilder.java @@ -55,7 +55,7 @@ public final class AsyncCommandBuilder { @Nullable private String description; @Nullable - private String delayMessage; + private Component delayMessage; @Nullable private Component successMessage; @@ -84,7 +84,12 @@ public final class AsyncCommandBuilder { return this; } + @Deprecated public AsyncCommandBuilder sendMessageAfterDelay(String message) { + return sendMessageAfterDelay(TextComponent.of(checkNotNull(message))); + } + + public AsyncCommandBuilder sendMessageAfterDelay(Component message) { this.delayMessage = checkNotNull(message); return this; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/FutureProgressListener.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/FutureProgressListener.java index 54d366ba4..3a47679a6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/FutureProgressListener.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/FutureProgressListener.java @@ -24,6 +24,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import java.util.Timer; @@ -34,7 +36,12 @@ public class FutureProgressListener implements Runnable { private final MessageTimerTask task; + @Deprecated public FutureProgressListener(Actor sender, String message) { + this(sender, TextComponent.of(message)); + } + + public FutureProgressListener(Actor sender, Component message) { checkNotNull(sender); checkNotNull(message); @@ -47,8 +54,13 @@ public class FutureProgressListener implements Runnable { task.cancel(); } + @Deprecated public static void addProgressListener(ListenableFuture future, Actor sender, String message) { future.addListener(new FutureProgressListener(sender, message), MoreExecutors.directExecutor()); } + public static void addProgressListener(ListenableFuture future, Actor sender, Component message) { + future.addListener(new FutureProgressListener(sender, message), MoreExecutors.directExecutor()); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageTimerTask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageTimerTask.java index 4a2549318..fa12e40be 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageTimerTask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageTimerTask.java @@ -22,15 +22,22 @@ package com.sk89q.worldedit.command.util; import static com.google.common.base.Preconditions.checkNotNull; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import java.util.TimerTask; public class MessageTimerTask extends TimerTask { private final Actor sender; - private final String message; + private final Component message; + @Deprecated MessageTimerTask(Actor sender, String message) { + this(sender, TextComponent.of(message)); + } + + MessageTimerTask(Actor sender, Component message) { checkNotNull(sender); checkNotNull(message); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java index cdcba32a2..536e329f4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java @@ -24,8 +24,10 @@ import com.sk89q.worldedit.session.SessionOwner; import com.sk89q.worldedit.util.Identifiable; import com.sk89q.worldedit.util.auth.Subject; import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import java.io.File; +import java.util.Locale; /** * An object that can perform actions in WorldEdit. @@ -52,30 +54,65 @@ public interface Actor extends Identifiable, SessionOwner, Subject { * Print a message. * * @param msg The message text + * @deprecated Use component-based functions (print) */ + @Deprecated void printRaw(String msg); /** * Print a WorldEdit message. * * @param msg The message text + * @deprecated Use component-based functions (printDebug) */ + @Deprecated void printDebug(String msg); /** * Print a WorldEdit message. * * @param msg The message text + * @deprecated Use component-based functions (printInfo) */ + @Deprecated void print(String msg); /** * Print a WorldEdit error. * * @param msg The error message text + * @deprecated Use component-based functions (printError) */ + @Deprecated void printError(String msg); + /** + * Print a WorldEdit error. + * + * @param component The component to print + */ + default void printError(Component component) { + print(component.color(TextColor.RED)); + } + + /** + * Print a WorldEdit message. + * + * @param component The component to print + */ + default void printInfo(Component component) { + print(component.color(TextColor.LIGHT_PURPLE)); + } + + /** + * Print a WorldEdit message. + * + * @param component The component to print + */ + default void printDebug(Component component) { + print(component.color(TextColor.GRAY)); + } + /** * Print a {@link Component}. * @@ -120,4 +157,10 @@ public interface Actor extends Identifiable, SessionOwner, Subject { */ void dispatchCUIEvent(CUIEvent event); + /** + * Get the locale of this actor. + * + * @return The locale + */ + Locale getLocale(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index 2bcddc7f8..ec07821f2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -533,15 +533,15 @@ public final class PlatformCommandManager { if (config.profile) { long time = System.currentTimeMillis() - start; + double timeS = (time / 1000.0); int changed = editSession.getBlockChangeCount(); - if (time > 0) { - double throughput = changed / (time / 1000.0); - actor.printDebug((time / 1000.0) + "s elapsed (history: " - + changed + " changed; " - + Math.round(throughput) + " blocks/sec)."); - } else { - actor.printDebug((time / 1000.0) + "s elapsed."); - } + double throughput = timeS == 0 ? changed : changed / timeS; + actor.printDebug(TranslatableComponent.of( + "worldedit.command.time-elapsed", + TextComponent.of(timeS), + TextComponent.of(changed), + TextComponent.of(Math.round(throughput)) + )); } worldEdit.flushBlockBag(actor, editSession); @@ -577,7 +577,7 @@ public final class PlatformCommandManager { private void handleUnknownException(Actor actor, Throwable t) { actor.printError("Please report this error: [See console]"); - actor.printRaw(t.getClass().getName() + ": " + t.getMessage()); + actor.print(TextComponent.of(t.getClass().getName() + ": " + t.getMessage())); log.error("An unexpected error while handling a WorldEdit command", t); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 36e36914b..581d5141d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -34,10 +34,6 @@ import com.sk89q.worldedit.event.platform.Interaction; import com.sk89q.worldedit.event.platform.PlatformInitializeEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.event.platform.PlayerInputEvent; -import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Location; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java index 120dd47ac..d40bf4df4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java @@ -36,6 +36,7 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.gamemode.GameMode; +import java.util.Locale; import java.util.UUID; import javax.annotation.Nullable; @@ -183,4 +184,9 @@ class PlayerProxy extends AbstractPlayerActor { public void floatAt(int x, int y, int z, boolean alwaysGlass) { basePlayer.floatAt(x, y, z, alwaysGlass); } + + @Override + public Locale getLocale() { + return basePlayer.getLocale(); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java index 591cb936b..029c78953 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java @@ -109,10 +109,6 @@ public class ChunkBatchingExtent extends AbstractBufferingExtent { @Override public void cancel() { } - - @Override - public void addStatusMessages(List messages) { - } }; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java index 4c43f06f9..ba4dc6e0d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java @@ -146,10 +146,6 @@ public class FastModeExtent extends AbstractDelegateExtent { @Override public void cancel() { } - - @Override - public void addStatusMessages(List messages) { - } }; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java index 0098d455a..ce127f96a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.function.factory; import static com.google.common.base.Preconditions.checkNotNull; import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull; +import com.google.common.collect.Lists; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -36,7 +37,12 @@ import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.NullRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import java.util.Collection; import java.util.List; public class Deform implements Contextual { @@ -186,9 +192,11 @@ public class Deform implements Contextual { public void cancel() { } + @Override - public void addStatusMessages(List messages) { - messages.add("deformed using " + expression); + public Iterable getStatusMessages() { + return Lists.newArrayList(TranslatableComponent.of("worldedit.operation.deform.expression", + TextComponent.of(expression).color(TextColor.LIGHT_PURPLE))); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java index 54ea500f0..fbd065051 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java @@ -80,10 +80,6 @@ public class ChangeSetExecutor implements Operation { public void cancel() { } - @Override - public void addStatusMessages(List messages) { - } - /** * Create a new undo operation. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/DelegateOperation.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/DelegateOperation.java index 69560ec56..b0a881eae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/DelegateOperation.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/DelegateOperation.java @@ -21,8 +21,11 @@ package com.sk89q.worldedit.function.operation; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.collect.Iterables; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.util.formatting.text.Component; +import java.util.Collection; import java.util.List; /** @@ -60,9 +63,8 @@ public class DelegateOperation implements Operation { } @Override - public void addStatusMessages(List messages) { - original.addStatusMessages(messages); - delegate.addStatusMessages(messages); + public Iterable getStatusMessages() { + return Iterables.concat(original.getStatusMessages(), delegate.getStatusMessages()); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java index 9512b5c3d..ddc35e107 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.function.operation; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEditException; @@ -46,7 +47,12 @@ import com.sk89q.worldedit.math.transform.Identity; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.regions.FlatRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import java.util.ArrayList; import java.util.List; /** @@ -337,25 +343,16 @@ public class ForwardExtentCopy implements Operation { } @Override - public void addStatusMessages(List messages) { - StringBuilder msg = new StringBuilder(); - msg.append(affectedBlocks).append(" block(s)"); - if (affectedBiomeCols > 0) { - if (affectedEntities > 0) { - msg.append(", "); - } else { - msg.append(" and "); - } - msg.append(affectedBiomeCols).append(" biome(s)"); - } - if (affectedEntities > 0) { - if (affectedBiomeCols > 0) { - msg.append(","); - } - msg.append(" and ").append(affectedEntities).append(" entities(s)"); - } - msg.append(" affected."); - messages.add(msg.toString()); + public Iterable getStatusMessages() { + List messages = new ArrayList<>(); + messages.add(TranslatableComponent.of(pluraliseI18n("worldedit.operation.affected.block", affectedBlocks), + TextComponent.of(affectedBlocks)).color(TextColor.LIGHT_PURPLE)); + messages.add(TranslatableComponent.of(pluraliseI18n("worldedit.operation.affected.biome", affectedBiomeCols), + TextComponent.of(affectedBiomeCols)).color(TextColor.LIGHT_PURPLE)); + messages.add(TranslatableComponent.of(pluraliseI18n("worldedit.operation.affected.entity", affectedEntities), + TextComponent.of(affectedEntities)).color(TextColor.LIGHT_PURPLE)); + + return messages; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java index a69653151..5ae25eb2b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java @@ -20,8 +20,12 @@ package com.sk89q.worldedit.function.operation; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * An task that may be split into multiple steps to be run sequentially @@ -56,7 +60,22 @@ public interface Operation { * of the operation. * * @param messages The list to add messages to + * @deprecated Will be removed in WorldEdit 8.0 - use the Component variant */ - void addStatusMessages(List messages); + @Deprecated + default void addStatusMessages(List messages) { + } + /** + * Gets an iterable of messages that describe the current status of the + * operation. + * + * @return The status messages + */ + default Iterable getStatusMessages() { + // TODO Remove legacy code WorldEdit 8.0.0 + List oldMessages = new ArrayList<>(); + addStatusMessages(oldMessages); + return oldMessages.stream().map(TextComponent::of).collect(Collectors.toList()); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/OperationQueue.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/OperationQueue.java index 53e79fa3d..b9a9a36ab 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/OperationQueue.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/OperationQueue.java @@ -21,13 +21,16 @@ package com.sk89q.worldedit.function.operation; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.util.formatting.text.Component; import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; import java.util.List; +import java.util.stream.Collectors; /** * Executes multiple queues in order. @@ -105,10 +108,8 @@ public class OperationQueue implements Operation { } @Override - public void addStatusMessages(List messages) { - for (Operation operation : operations) { - operation.addStatusMessages(messages); - } + public Iterable getStatusMessages() { + return Iterables.concat(operations.stream().map(Operation::getStatusMessages).collect(Collectors.toList())); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/SetLocatedBlocks.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/SetLocatedBlocks.java index 1e418bb04..2989bdcec 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/SetLocatedBlocks.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/SetLocatedBlocks.java @@ -49,8 +49,4 @@ public class SetLocatedBlocks implements Operation { public void cancel() { } - @Override - public void addStatusMessages(List messages) { - } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java index 26b14f38c..9d4144d3f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java @@ -20,13 +20,19 @@ package com.sk89q.worldedit.function.visitor; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; +import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.RunContext; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import java.util.ArrayDeque; import java.util.ArrayList; @@ -119,10 +125,9 @@ public abstract class BreadthFirstSearch implements Operation { * @param position the position */ public void visit(BlockVector3 position) { - BlockVector3 blockVector = position; - if (!visited.contains(blockVector)) { - queue.add(blockVector); - visited.add(blockVector); + if (!visited.contains(position)) { + queue.add(position); + visited.add(position); } } @@ -133,11 +138,10 @@ public abstract class BreadthFirstSearch implements Operation { * @param to the block under question */ private void visit(BlockVector3 from, BlockVector3 to) { - BlockVector3 blockVector = to; - if (!visited.contains(blockVector)) { - visited.add(blockVector); + if (!visited.contains(to)) { + visited.add(to); if (isVisitable(from, to)) { - queue.add(blockVector); + queue.add(to); } } } @@ -183,8 +187,11 @@ public abstract class BreadthFirstSearch implements Operation { } @Override - public void addStatusMessages(List messages) { - messages.add(getAffected() + " blocks affected"); + public Iterable getStatusMessages() { + return Lists.newArrayList(TranslatableComponent.of( + pluraliseI18n("worldedit.operation.affected.block", getAffected()), + TextComponent.of(getAffected()) + ).color(TextColor.LIGHT_PURPLE)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java index c3ce36567..719fa3e60 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java @@ -20,13 +20,20 @@ package com.sk89q.worldedit.function.visitor; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; +import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.function.EntityFunction; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.RunContext; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -77,8 +84,11 @@ public class EntityVisitor implements Operation { } @Override - public void addStatusMessages(List messages) { - messages.add(getAffected() + " entities affected"); + public Iterable getStatusMessages() { + return Lists.newArrayList(TranslatableComponent.of( + pluraliseI18n("worldedit.operation.affected.entity", getAffected()), + TextComponent.of(getAffected()) + ).color(TextColor.LIGHT_PURPLE)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java index 46ef33dc0..e7b0daa57 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java @@ -20,14 +20,21 @@ package com.sk89q.worldedit.function.visitor; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; +import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.function.FlatRegionFunction; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.RunContext; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.FlatRegion; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import java.util.Collection; import java.util.List; /** @@ -78,8 +85,11 @@ public class FlatRegionVisitor implements Operation { } @Override - public void addStatusMessages(List messages) { - messages.add(getAffected() + " columns affected"); + public Iterable getStatusMessages() { + return Lists.newArrayList(TranslatableComponent.of( + pluraliseI18n("worldedit.operation.affected.column", getAffected()), + TextComponent.of(getAffected()) + ).color(TextColor.LIGHT_PURPLE)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java index f683637b3..3fed7f678 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java @@ -128,8 +128,4 @@ public class LayerVisitor implements Operation { public void cancel() { } - @Override - public void addStatusMessages(List messages) { - } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java index 12a955c0d..4f595584b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java @@ -19,14 +19,19 @@ package com.sk89q.worldedit.function.visitor; +import static com.sk89q.worldedit.util.translation.LocalisationHelpers.pluraliseI18n; + +import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.RunContext; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; - -import java.util.List; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; /** * Utility class to apply region functions to {@link com.sk89q.worldedit.regions.Region}. @@ -67,8 +72,11 @@ public class RegionVisitor implements Operation { } @Override - public void addStatusMessages(List messages) { - messages.add(getAffected() + " blocks affected"); + public Iterable getStatusMessages() { + return Lists.newArrayList(TranslatableComponent.of( + pluraliseI18n("worldedit.operation.affected.block", getAffected()), + TextComponent.of(getAffected()) + ).color(TextColor.LIGHT_PURPLE)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java index f31e0ba44..65fe99a7d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java @@ -32,6 +32,7 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.session.request.Request; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.io.file.FilenameException; import com.sk89q.worldedit.world.block.BaseBlock; @@ -114,7 +115,7 @@ public class CraftScriptContext extends CraftScriptEnvironment { * @param message a message */ public void print(String message) { - player.print(message); + player.printInfo(TextComponent.of(message)); } /** @@ -123,16 +124,16 @@ public class CraftScriptContext extends CraftScriptEnvironment { * @param message a message */ public void error(String message) { - player.printError(message); + player.printError(TextComponent.of(message)); } /** - * Print an raw message to the user. + * Print a raw message to the user. * * @param message a message */ public void printRaw(String message) { - player.printRaw(message); + player.print(TextComponent.of(message)); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/WorldEditText.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/WorldEditText.java index 897a3fa46..1e2b0728e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/WorldEditText.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/WorldEditText.java @@ -19,11 +19,14 @@ package com.sk89q.worldedit.util.formatting; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.util.formatting.text.Component; import org.enginehub.piston.config.ConfigHolder; import org.enginehub.piston.config.TextConfig; import org.enginehub.piston.util.TextHelper; +import java.util.Locale; + public class WorldEditText { public static final ConfigHolder CONFIG_HOLDER = ConfigHolder.create(); @@ -31,12 +34,12 @@ public class WorldEditText { CONFIG_HOLDER.getConfig(TextConfig.commandPrefix()).setValue("/"); } - public static Component format(Component component) { - return CONFIG_HOLDER.replace(component); + public static Component format(Component component, Locale locale) { + return CONFIG_HOLDER.replace(WorldEdit.getInstance().getTranslationManager().convertText(component, locale)); } - public static String reduceToText(Component component) { - return TextHelper.reduceToText(format(component)); + public static String reduceToText(Component component, Locale locale) { + return TextHelper.reduceToText(format(component, locale)); } private WorldEditText() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java index e5fceb008..223d92f16 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java @@ -36,13 +36,22 @@ public class MessageBox extends TextComponentProducer { private static final int GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH = 47; private TextComponentProducer contents; + private TextColor borderColor; /** * Create a new box. */ public MessageBox(String title, TextComponentProducer contents) { + this(title, contents, TextColor.YELLOW); + } + + /** + * Create a new box. + */ + public MessageBox(String title, TextComponentProducer contents, TextColor borderColor) { checkNotNull(title); + this.borderColor = borderColor; append(centerAndBorder(TextComponent.of(title))).newline(); this.contents = contents; } @@ -74,7 +83,7 @@ public class MessageBox extends TextComponentProducer { private TextComponent createBorder(int count) { return TextComponent.of(Strings.repeat("-", count), - TextColor.YELLOW, Sets.newHashSet(TextDecoration.STRIKETHROUGH)); + borderColor, Sets.newHashSet(TextDecoration.STRIKETHROUGH)); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/TextUtils.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/TextUtils.java new file mode 100644 index 000000000..f604d322a --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/TextUtils.java @@ -0,0 +1,49 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.formatting.component; + +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; + +import java.util.List; + +public class TextUtils { + + private TextUtils() { + } + + /** + * Join an array of components with a joiner component. + * + * @param components The components to join + * @param joiner The joiner component + * @return The joined component + */ + public static Component join(List components, Component joiner) { + TextComponent.Builder builder = TextComponent.builder(); + for (int i = 0; i < components.size(); i++) { + builder.append(components.get(i)); + if (i < components.size() - 1) { + builder.append(joiner); + } + } + return builder.build(); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ResourceLoader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ResourceLoader.java index 09ac4724f..1f3555353 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ResourceLoader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ResourceLoader.java @@ -40,4 +40,17 @@ public class ResourceLoader { } return url; } + + public static URL getResourceRoot(String name) throws IOException { + URL url = ResourceLoader.class.getResource("/" + name); + if (url == null) { + try { + return new URL("modjar://worldedit/" + name); + } catch (Exception e) { + // Not forge. + } + throw new IOException("Could not find " + name); + } + return url; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java index 1eb51a21f..a0d677e74 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java @@ -21,6 +21,8 @@ package com.sk89q.worldedit.util.paste; import com.sk89q.worldedit.command.util.AsyncCommandBuilder; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.task.Supervisor; import java.net.URL; @@ -41,7 +43,9 @@ public final class ActorCallbackPaste { * @param sender The sender * @param content The content * @param successMessage The message, formatted with {@link String#format(String, Object...)} on success + * @deprecated Use the Component-based version */ + @Deprecated public static void pastebin(Supervisor supervisor, final Actor sender, String content, final String successMessage) { Callable task = paster.paste(content); @@ -53,4 +57,24 @@ public final class ActorCallbackPaste { .buildAndExec(Pasters.getExecutor()); } + /** + * Submit data to a pastebin service and inform the sender of + * success or failure. + * + * @param supervisor The supervisor instance + * @param sender The sender + * @param content The content + * @param successMessage The message builder, given the URL as an arg + */ + public static void pastebin(Supervisor supervisor, final Actor sender, String content, final TranslatableComponent.Builder successMessage) { + Callable task = paster.paste(content); + + AsyncCommandBuilder.wrap(task, sender) + .registerWithSupervisor(supervisor, "Submitting content to a pastebin service.") + .sendMessageAfterDelay(TranslatableComponent.of("worldedit.pastebin.uploading")) + .onSuccess((String) null, url -> sender.printInfo(successMessage.args(TextComponent.of(url.toString())).build())) + .onFailure("Failed to submit paste", null) + .buildAndExec(Pasters.getExecutor()); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/LocalisationHelpers.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/LocalisationHelpers.java new file mode 100644 index 000000000..7909076b5 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/LocalisationHelpers.java @@ -0,0 +1,42 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.translation; + +public class LocalisationHelpers { + + private LocalisationHelpers() { + } + + /** + * Turn a translation key into a ".singular" or ".plural" + * depending on what the given number is. + * + * @param translationKey The base translation key + * @param number The number + * @return The key with .plural or .singular appended + */ + public static String pluraliseI18n(String translationKey, float number) { + if (number == 1) { + return translationKey + ".singular"; + } else { + return translationKey + ".plural"; + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/TranslationManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/TranslationManager.java new file mode 100644 index 000000000..ab5d1e3d1 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/TranslationManager.java @@ -0,0 +1,144 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.translation; + +import com.google.common.io.Files; +import com.google.common.io.Resources; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.renderer.FriendlyComponentRenderer; +import com.sk89q.worldedit.util.io.ResourceLoader; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Type; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Handles translations for the plugin. + * + * These should be in the following format: + * plugin.component.message[.meta]* + * + * Where, + * plugin = worldedit + * component = The part of the plugin, eg expand + * message = A descriptor for which message, eg, expanded + * meta = Any extra information such as plural/singular (Can have none to infinite) + */ +public class TranslationManager { + + private static final Gson gson = new GsonBuilder().create(); + private static final Type STRING_MAP_TYPE = new TypeToken>() {}.getType(); + + private final Map> translationMap = new HashMap<>(); + private final FriendlyComponentRenderer friendlyComponentRenderer = FriendlyComponentRenderer.from( + (locale, key) -> new MessageFormat(getTranslationMap(locale).getOrDefault(key, key), locale)); + private Locale defaultLocale = Locale.ENGLISH; + + private final WorldEdit worldEdit; + + private final Set checkedLocales = new HashSet<>(); + + public TranslationManager(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } + + public void setDefaultLocale(Locale defaultLocale) { + this.defaultLocale = defaultLocale; + } + + private Map parseTranslationFile(File file) throws IOException { + return gson.fromJson(Files.toString(file, StandardCharsets.UTF_8), STRING_MAP_TYPE); + } + + private Map parseTranslationFile(URL file) throws IOException { + return gson.fromJson(Resources.toString(file, StandardCharsets.UTF_8), STRING_MAP_TYPE); + } + + private Optional> loadTranslationFile(String filename) { + File localFile = worldEdit.getWorkingDirectoryFile("lang/" + filename); + if (localFile.exists()) { + try { + return Optional.of(parseTranslationFile(localFile)); + } catch (IOException e) { + return Optional.empty(); + } + } else { + try { + return Optional.of(parseTranslationFile(ResourceLoader.getResourceRoot("lang/" + filename))); + } catch (IOException e) { + return Optional.empty(); + } + } + } + + private boolean tryLoadTranslations(Locale locale) { + if (checkedLocales.contains(locale)) { + return false; + } + checkedLocales.add(locale); + Optional> langData = loadTranslationFile(locale.getLanguage() + "-" + locale.getCountry() + "/strings.json"); + if (!langData.isPresent()) { + langData = loadTranslationFile(locale.getLanguage() + "/strings.json"); + } + if (langData.isPresent()) { + translationMap.put(locale, langData.get()); + return true; + } + if (locale.equals(defaultLocale)) { + translationMap.put(Locale.ENGLISH, loadTranslationFile("strings.json").orElseThrow( + () -> new RuntimeException("Failed to load WorldEdit strings!") + )); + return true; + } + return false; + } + + private Map getTranslationMap(Locale locale) { + Map translations = translationMap.get(locale); + if (translations == null) { + if (tryLoadTranslations(locale)) { + return getTranslationMap(locale); + } + if (!locale.equals(defaultLocale)) { + translations = getTranslationMap(defaultLocale); + } + } + + return translations; + } + + public Component convertText(Component component, Locale locale) { + return friendlyComponentRenderer.render(component, locale); + } +} diff --git a/worldedit-core/src/main/resources/lang/.gitignore b/worldedit-core/src/main/resources/lang/.gitignore new file mode 100644 index 000000000..0a00d7014 --- /dev/null +++ b/worldedit-core/src/main/resources/lang/.gitignore @@ -0,0 +1 @@ +*/ \ No newline at end of file diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json new file mode 100644 index 000000000..f5ecde2b0 --- /dev/null +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -0,0 +1,198 @@ +{ + "worldedit.expand.description.vert": "Vertically expand the selection to world limits.", + "worldedit.expand.expanded.singular": "Region expanded {0} block", + "worldedit.expand.expanded.plural": "Region expanded {0} blocks", + "worldedit.expand.expanded.vert.singular": "Region expanded {0} block (top-to-bottom).", + "worldedit.expand.expanded.vert.plural": "Region expanded {0} blocks (top-to-bottom).", + + "worldedit.biomeinfo.lineofsight.singular": "Biome at line of sight point: {0}", + "worldedit.biomeinfo.lineofsight.plural": "Biomes at line of sight point: {0}", + "worldedit.biomeinfo.position.singular": "Biome at your position: {0}", + "worldedit.biomeinfo.position.plural": "Biomes at your position: {0}", + "worldedit.biomeinfo.selection.singular": "Biome in your selection: {0}", + "worldedit.biomeinfo.selection.plural": "Biomes in your selection: {0}", + + "worldedit.brush.apply.description": "Apply brush, apply a function to every block", + "worldedit.brush.apply.radius": "The size of the brush", + "worldedit.brush.apply.shape": "The shape of the region", + "worldedit.brush.apply.type": "Type of brush to use", + "worldedit.brush.apply.item.warning": "This brush simulates item usages. Its effects may not work on all platforms, may not be undo-able, and may cause strange interactions with other mods/plugins. Use at your own risk.", + "worldedit.brush.paint.description": "Paint brush, apply a function to a surface", + "worldedit.brush.paint.size": "The size of the brush", + "worldedit.brush.paint.shape": "The shape of the region", + "worldedit.brush.paint.density": "The density of the brush", + "worldedit.brush.paint.type": "Type of brush to use", + "worldedit.brush.paint.item.warning": "This brush simulates item usages. Its effects may not work on all platforms, may not be undo-able, and may cause strange interactions with other mods/plugins. Use at your own risk.", + "worldedit.brush.sphere.equip": "Sphere brush shape equipped ({0}).", + "worldedit.brush.cylinder.equip": "Cylinder brush shape equipped ({0} by {1}).", + "worldedit.brush.clipboard.equip": "Clipboard brush shape equipped.", + "worldedit.brush.smooth.equip": "Smooth brush equipped ({0} x {1}x using {2}).", + "worldedit.brush.extinguish.equip": "Extinguisher equipped ({0}).", + "worldedit.brush.gravity.equip": "Gravity brush equipped ({0}).", + "worldedit.brush.butcher.equip": "Butcher brush equipped ({0}).", + "worldedit.brush.operation.equip": "Set brush to {0}.", + "worldedit.brush.none.equip": "Brush unbound from your current item.", + + "worldedit.setbiome.changed.singular": "Biomes were changed in {0} column. You may have to rejoin your game (or close and reopen your world) to see a change.", + "worldedit.setbiome.changed.plural": "Biomes were changed in {0} columns. You may have to rejoin your game (or close and reopen your world) to see a change.", + + "worldedit.drawsel.disabled": "Server CUI disabled.", + "worldedit.drawsel.enabled": "Server CUI enabled. This only supports cuboid regions, with a maximum size of 32x32x32.", + "worldedit.drawsel.disabled.already": "Server CUI already disabled.", + "worldedit.drawsel.enabled.already": "Server CUI already enabled.", + "worldedit.limit.too-high": "Your maximum allowable limit is {0}.", + "worldedit.limit.set": "Block change limit set to {0}.", + "worldedit.limit.return-to-default": " (Use //limit to go back to the default.)", + "worldedit.timeout.too-high": "Your maximum allowable timeout is {0}ms.", + "worldedit.timeout.set": "Timeout time set to {0} ms.", + "worldedit.timeout.return-to-default": " (Use //timeout to go back to the default.)", + "worldedit.fast.disabled": "Fast mode disabled.", + "worldedit.fast.enabled": "Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.", + "worldedit.fast.disabled.already": "Fast mode already disabled.", + "worldedit.fast.enabled.already": "Fast mode already enabled.", + "worldedit.reorder.current": "The reorder mode is {0}", + "worldedit.reorder.set": "The reorder mode is now {0}", + "worldedit.gmask.disabled": "Global mask disabled.", + "worldedit.gmask.set": "Global mask set.", + "worldedit.toggleplace.pos1": "Now placing at pos #1.", + "worldedit.toggleplace.player": "Now placing at the block you stand in.", + "worldedit.searchitem.too-short": "Enter a longer search string (len > 2).", + "worldedit.searchitem.b-and-i": "You cannot use both the 'b' and 'i' flags simultaneously.", + + "worldedit.undo.undone": "Undid {0} available edits.", + "worldedit.undo.none": "Nothing left to undo.", + "worldedit.redo.undone": "Redid {0} available edits.", + "worldedit.redo.none": "Nothing left to redo.", + "worldedit.clearhistory.cleared": "History cleared.", + + "worldedit.raytrace.noblock": "No block in sight!", + + "worldedit.restore.not-configured": "Snapshot/backup restore is not configured.", + "worldedit.restore.not-available": "That snapshot does not exist or is not available.", + "worldedit.restore.failed": "Failed to load snapshot: {0}", + "worldedit.restore.loaded": "Snapshot '{0}' loaded; now restoring...", + "worldedit.restore.restored": "Restored; {0} missing chunks and {1} other errors.", + "worldedit.restore.none-for-world": "No snapshots were found for this world.", + "worldedit.restore.none-found": "No snapshots were found.", + "worldedit.restore.none-found-console": "No snapshots were found. See console for details.", + "worldedit.restore.chunk-not-present": "Chunks were not present in snapshot.", + "worldedit.restore.chunk-load-failed": "No chunks could be loaded. (Bad archive?)", + "worldedit.restore.block-place-failed": "Errors prevented any blocks from being restored.", + "worldedit.restore.block-place-error": "Last error: {0}", + + "worldedit.snapshot.use.newest": "Now using newest snapshot.", + + "worldedit.drain.drained.singular": "{0} block has been drained.", + "worldedit.drain.drained.plural": "{0} blocks have been drained.", + "worldedit.fill.created.singular": "{0} block has been filled.", + "worldedit.fill.created.plural": "{0} blocks have been filled.", + "worldedit.fillr.created.singular": "{0} block has been filled.", + "worldedit.fillr.created.plural": "{0} blocks have been filled.", + "worldedit.fixlava.fixed.singular": "{0} block has been fixed.", + "worldedit.fixlava.fixed.plural": "{0} blocks have been fixed.", + "worldedit.fixwater.fixed.singular": "{0} block has been fixed.", + "worldedit.fixwater.fixed.plural": "{0} blocks have been fixed.", + "worldedit.removeabove.removed.singular": "{0} block has been removed.", + "worldedit.removeabove.removed.plural": "{0} blocks have been removed.", + "worldedit.removebelow.removed.singular": "{0} block has been removed.", + "worldedit.removebelow.removed.plural": "{0} blocks have been removed.", + "worldedit.removenear.removed.singular": "{0} block has been removed.", + "worldedit.removenear.removed.plural": "{0} blocks have been removed.", + "worldedit.replacenear.replaced.singular": "{0} block has been replaced.", + "worldedit.replacenear.replaced.plural": "{0} blocks have been replaced.", + "worldedit.snow.created.singular": "{0} surface has been covered.", + "worldedit.snow.created.plural": "{0} surfaces have been covered.", + "worldedit.thaw.removed.singular": "{0} block has been thawed.", + "worldedit.thaw.removed.plural": "{0} blocks have been thawed.", + "worldedit.green.changed.singular": "{0} block has been greened.", + "worldedit.green.changed.plural": "{0} blocks have been greened.", + "worldedit.extinguish.removed.singular": "{0} fire has been extinguished.", + "worldedit.extinguish.removed.plural": "{0} fires have been extinguished.", + "worldedit.butcher.killed.singular": "{0} mob has been killed in a radius of {1}.", + "worldedit.butcher.killed.plural": "{0} mobs have been killed in a radius of {1}.", + "worldedit.butcher.explain-all": "Use -1 to remove all mobs in loaded chunks", + "worldedit.remove.removed.singular": "{0} entity has been marked for removal.", + "worldedit.remove.removed.plural": "{0} entities have been marked for removal.", + "worldedit.remove.explain-all": "Use -1 to remove all entities in loaded chunks", + "worldedit.calc.invalid": "'{0}' could not be parsed as a valid expression", + + "worldedit.paste.pasted": "The clipboard has been pasted at {0}", + "worldedit.paste.selected": "Selected clipboard paste region.", + "worldedit.rotate.no-interpolation": "Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended.", + "worldedit.rotate.rotated": "The clipboard copy has been rotated.", + "worldedit.flip.flipped": "The clipboard copy has been flipped.", + "worldedit.clearclipboard.cleared": "Clipboard cleared.", + + "worldedit.set.done": "Operation completed.", + "worldedit.set.done.verbose": "Operation completed ({0}).", + + "worldedit.unstuck.moved": "There you go!", + "worldedit.ascend.obstructed": "No free spot above you found.", + "worldedit.ascend.moved.singular": "Ascended a level.", + "worldedit.ascend.moved.plural": "Ascended {0} levels.", + "worldedit.descend.obstructed": "No free spot below you found.", + "worldedit.descend.moved.singular": "Descended a level.", + "worldedit.descend.moved.plural": "Descended {0} levels.", + "worldedit.ceil.obstructed": "No free spot above you found.", + "worldedit.ceil.moved": "Woosh!", + "worldedit.thru.obstructed": "No free spot ahead of you found.", + "worldedit.thru.moved": "Woosh!", + "worldedit.jumpto.moved": "Poof!", + "worldedit.jumpto.none": "No block in sight (or too far away)!", + "worldedit.up.obstructed": "You would hit something above you.", + "worldedit.up.moved": "Woosh!", + + "worldedit.reload.config": "Configuration reloaded!", + "worldedit.report.written": "WorldEdit report written to {0}", + "worldedit.report.error": "Failed to write report: {0}", + "worldedit.report.callback": "WorldEdit report: {0}.report", + "worldedit.timezone.invalid": "Invalid timezone", + "worldedit.timezone.set": "Timezone set for this session to: {0}", + "worldedit.timezone.current": "The current time in that timezone is: {0}", + "worldedit.version.version": "WorldEdit version {0}", + + "worldedit.command.time-elapsed": "{0}s elapsed (history: {1} changed; {2} blocks/sec).", + "worldedit.pastebin.uploading": "(Please wait... sending output to pastebin...)", + "worldedit.session.cant-find-session": "Unable to find session for {0}", + + "worldedit.tool.max-block-changes": "Max blocks change limit reached.", + "worldedit.tool.no-block": "No block in sight!", + "worldedit.tool.repl.equip": "Block replacer tool bound to {0}.", + "worldedit.tool.repl.switched": "Replacer tool switched to: {0}", + "worldedit.tool.data-cycler.equip": "Block data cycler tool bound to {0}.", + "worldedit.tool.data-cycler.block-not-permitted": "You are not permitted to cycle the data value of that block.", + "worldedit.tool.data-cycler.cant-cycle": "That block's data cannot be cycled!", + "worldedit.tool.data-cycler.new-value": "Value of {0} is now {1}.", + "worldedit.tool.data-cycler.cycling": "Now cycling {0}.", + "worldedit.tool.deltree.equip": "Floating tree remover tool bound to {0}.", + "worldedit.tool.deltree.not-tree": "That's not a tree.", + "worldedit.tool.deltree.not-floating": "That's not a floating tree.", + "worldedit.tool.tree.equip": "Tree tool bound to {0}.", + "worldedit.tool.tree.obstructed": "A tree can't go there.", + "worldedit.tool.info.equip": "Info tool bound to {0}.", + "worldedit.tool.info.blockstate.hover": "Block state", + "worldedit.tool.info.internalid.hover": "Internal ID", + "worldedit.tool.info.light.hover": "Block Light/Light Above", + "worldedit.tool.none.equip": "Tool unbound from your current item.", + "worldedit.tool.selwand.equip": "Selection wand bound to {0}.", + "worldedit.tool.navwand.equip": "Navigation wand bound to {0}.", + "worldedit.tool.floodfill.equip": "Block flood fill tool bound to {0}.", + "worldedit.tool.farwand.equip": "Far wand tool bound to {0}.", + "worldedit.tool.lrbuild.equip": "Long-range building tool bound to {0}.", + "worldedit.tool.lrbuild.set": "Left-click set to {0}; right-click set to {1}.", + + "worldedit.superpickaxe.mode.single": "Mode is now single. Left click with a pickaxe. // to disable.", + "worldedit.superpickaxe.mode.area": "Mode is now area. Left click with a pickaxe. // to disable.", + "worldedit.superpickaxe.mode.recursive": "Mode is now recursive. Left click with a pickaxe. // to disable.", + "worldedit.superpickaxe.max-range": "Maximum range is {0}.", + + "worldedit.operation.affected.biome.singular": "{0} biome affected", + "worldedit.operation.affected.biome.plural": "{0} biomes affected", + "worldedit.operation.affected.block.singular": "{0} block affected", + "worldedit.operation.affected.block.plural": "{0} blocks affected", + "worldedit.operation.affected.column.singular": "{0} column affected", + "worldedit.operation.affected.column.plural": "{0} columns affected", + "worldedit.operation.affected.entity.singular": "{0} entity affected", + "worldedit.operation.affected.entity.plural": "{0} entities affected", + "worldedit.operation.deform.expression": "deformed using {0}" +} \ No newline at end of file diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java index 60003a259..48507f8fe 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; import com.sk89q.worldedit.extent.inventory.BlockBag; +import com.sk89q.worldedit.fabric.mixin.AccessorServerPlayerEntity; import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.math.BlockVector3; @@ -56,6 +57,7 @@ import net.minecraft.util.math.BlockPos; import javax.annotation.Nullable; import java.io.IOException; +import java.util.Locale; import java.util.UUID; public class FabricPlayer extends AbstractPlayerActor { @@ -128,6 +130,11 @@ public class FabricPlayer extends AbstractPlayerActor { this.player.networkHandler.sendPacket(packet); } + @Override + public Locale getLocale() { + return Locale.forLanguageTag(((AccessorServerPlayerEntity) this.player).getClientLanguage().replace("_", "-")); + } + @Override public void printRaw(String msg) { for (String part : msg.split("\n")) { @@ -152,7 +159,7 @@ public class FabricPlayer extends AbstractPlayerActor { @Override public void print(Component component) { - this.player.sendMessage(Text.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component)))); + this.player.sendMessage(Text.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale())))); } private void sendColorized(String msg, Formatting formatting) { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerPlayerEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerPlayerEntity.java new file mode 100644 index 000000000..a7e86af41 --- /dev/null +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerPlayerEntity.java @@ -0,0 +1,31 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.fabric.mixin; + +import net.minecraft.server.network.ServerPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ServerPlayerEntity.class) +public interface AccessorServerPlayerEntity { + + @Accessor("clientLanguage") + String getClientLanguage(); +} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayerEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayerEntity.java index fbad989c1..822bb0954 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayerEntity.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayerEntity.java @@ -27,6 +27,7 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Hand; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; diff --git a/worldedit-fabric/src/main/resources/worldedit.mixins.json b/worldedit-fabric/src/main/resources/worldedit.mixins.json index fd6cd4f92..623a5c8d5 100644 --- a/worldedit-fabric/src/main/resources/worldedit.mixins.json +++ b/worldedit-fabric/src/main/resources/worldedit.mixins.json @@ -4,7 +4,8 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "MixinServerPlayerEntity", - "MixinMinecraftServer" + "MixinMinecraftServer", + "AccessorServerPlayerEntity" ], "server": [ ], diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 22250e0de..2c5a35573 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -55,6 +55,7 @@ import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TextFormatting; import java.io.IOException; +import java.util.Locale; import java.util.UUID; import javax.annotation.Nullable; @@ -153,7 +154,7 @@ public class ForgePlayer extends AbstractPlayerActor { @Override public void print(Component component) { - this.player.sendMessage(ITextComponent.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component)))); + this.player.sendMessage(ITextComponent.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale())))); } private void sendColorized(String msg, TextFormatting formatting) { @@ -203,6 +204,11 @@ public class ForgePlayer extends AbstractPlayerActor { } } + @Override + public Locale getLocale() { + return Locale.forLanguageTag(player.language.replace('_', '-')); + } + @Override public > void sendFakeBlock(BlockVector3 pos, B block) { World world = getWorld(); diff --git a/worldedit-forge/src/main/resources/META-INF/accesstransformer.cfg b/worldedit-forge/src/main/resources/META-INF/accesstransformer.cfg index 9c1530b89..5e9a97889 100644 --- a/worldedit-forge/src/main/resources/META-INF/accesstransformer.cfg +++ b/worldedit-forge/src/main/resources/META-INF/accesstransformer.cfg @@ -1 +1,2 @@ -public net.minecraft.server.MinecraftServer field_211151_aa # serverTime \ No newline at end of file +public net.minecraft.server.MinecraftServer field_211151_aa # serverTime +public net.minecraft.entity.player.ServerPlayerEntity field_71148_cg # language diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java index 01340ae4b..9564b1722 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java @@ -54,17 +54,17 @@ public abstract class CommandAdapter implements CommandCallable { @Override public Optional getShortDescription(CommandSource source) { return Optional.of(command.getDescription()) - .map(SpongeTextAdapter::convert); + .map(desc -> SpongeTextAdapter.convert(desc, source.getLocale())); } @Override public Optional getHelp(CommandSource source) { return Optional.of(command.getFullHelp()) - .map(SpongeTextAdapter::convert); + .map(help -> SpongeTextAdapter.convert(help, source.getLocale())); } @Override public Text getUsage(CommandSource source) { - return convert(command.getUsage()); + return convert(command.getUsage(), source.getLocale()); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java index 4f8b7fa44..fb3d31695 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java @@ -37,6 +37,7 @@ import org.spongepowered.api.text.format.TextColors; import org.spongepowered.api.text.serializer.TextSerializers; import java.io.File; +import java.util.Locale; import java.util.UUID; import javax.annotation.Nullable; @@ -94,7 +95,7 @@ public class SpongeCommandSender implements Actor { @Override public void print(Component component) { - TextAdapter.sendComponent(sender, WorldEditText.format(component)); + TextAdapter.sendComponent(sender, WorldEditText.format(component, getLocale())); } private void sendColorized(String msg, TextColor formatting) { @@ -141,6 +142,11 @@ public class SpongeCommandSender implements Actor { public void dispatchCUIEvent(CUIEvent event) { } + @Override + public Locale getLocale() { + return Locale.US; + } + @Override public SessionKey getSessionKey() { return new SessionKey() { diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java index aa0056710..6603a5bd4 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java @@ -51,6 +51,7 @@ import org.spongepowered.api.text.serializer.TextSerializers; import org.spongepowered.api.world.World; import java.nio.charset.StandardCharsets; +import java.util.Locale; import java.util.Optional; import java.util.UUID; @@ -154,7 +155,7 @@ public class SpongePlayer extends AbstractPlayerActor { @Override public void print(Component component) { - TextAdapter.sendComponent(player, WorldEditText.format(component)); + TextAdapter.sendComponent(player, WorldEditText.format(component, getLocale())); } private void sendColorized(String msg, TextColor formatting) { @@ -231,6 +232,11 @@ public class SpongePlayer extends AbstractPlayerActor { } } + @Override + public Locale getLocale() { + return player.getLocale(); + } + @Override public SessionKey getSessionKey() { return new SessionKeyImpl(player.getUniqueId(), player.getName()); diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java index 4e7b5c2fb..7b8a127e4 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java @@ -25,10 +25,12 @@ import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSer import org.spongepowered.api.text.Text; import org.spongepowered.api.text.serializer.TextSerializers; +import java.util.Locale; + public class SpongeTextAdapter { - public static Text convert(Component component) { - component = WorldEditText.format(component); + public static Text convert(Component component, Locale locale) { + component = WorldEditText.format(component, locale); return TextSerializers.JSON.deserialize(GsonComponentSerializer.INSTANCE.serialize(component)); }