PaperMC / Velocity

The modern, next-generation Minecraft server proxy.

Home Page:https://papermc.io/software/velocity

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

(Bug?) Translation keys in `VelocityBrigadierMessage` are sent as their literal key rather than allowing the client to translate

willkroboth opened this issue · comments

Reproduction

I created a Velocity server with a Paper backend server. On Velocity, I have this plugin:

public class VelocityTestPlugin {

    @Inject
    private ProxyServer server;

    @Subscribe
    public void onProxyInitialization(ProxyInitializeEvent event) {
        server.getCommandManager().register(new BrigadierCommand(
                LiteralArgumentBuilder.<CommandSource>literal("velocityCommand").then(
                        RequiredArgumentBuilder.<CommandSource, String>argument("player", StringArgumentType.word())
                                .suggests((context, builder) -> {
                                    server.getAllPlayers().stream().map(Player::getUsername).forEach(builder::suggest);
                                    return builder.buildFuture();
                                })
                                .executes(context -> {
                                    String playerName = context.getArgument("player", String.class);
                                    Optional<Player> optionalPlayer = server.getPlayer(playerName);

                                    if(optionalPlayer.isEmpty())
                                        throw new SimpleCommandExceptionType(VelocityBrigadierMessage.tooltip(Component.translatable("argument.player.unknown"))).create();

                                    optionalPlayer.get().sendMessage(Component.text("You were the target of the command"));

                                    return 1;
                                })
                )
        ));
    }
}

This plugin registers a BrigadierCommand that attempts to get a Player object from a string. If a player cannot be found for the given String, the command throws an error using one of Minecraft's language codes, argument.player.unknown.

On Paper, I have this plugin:

public final class BukkitTestPlugin extends JavaPlugin implements Listener {
    @Override
    public void onEnable() {
        getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, event -> {
            Commands commands = event.registrar();
            commands.register(
                    Commands.literal("paperCommand").then(
                            Commands.argument("player", StringArgumentType.word())
                                    .suggests((context, builder) -> {
                                        Bukkit.getOnlinePlayers().stream().map(Player::getName).forEach(builder::suggest);
                                        return builder.buildFuture();
                                    })
                                    .executes(context -> {
                                        String playerName = context.getArgument("player", String.class);
                                        Player player = Bukkit.getPlayer(playerName);


                                        if(player == null)
                                            throw new SimpleCommandExceptionType(PaperBrigadier.message(Component.translatable("argument.player.unknown"))).create();

                                        player.sendMessage(Component.text("You were the target of the command"));

                                        return 1;
                                    })
                    ).build()
            );
        });
    }
}

This uses API from PaperMC/Paper#8235 to register a command that is basically the same as the one on Velocity.

Observed results

When I join the server, I get these results when running the commands (I switched my client language from English to Spanish):

Translated error

When running /velocitycommand notPlayer, I expect the key argument.player.unknown to be translated to the client's language, which is what happens when running papercommand notPlayer. Instead, the player is sent the literal text argument.player.unknown.

I believe this comes from line 235 in VelocityCommandManager:

} catch (final CommandSyntaxException e) {
boolean isSyntaxError = !e.getType().equals(
CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand());
if (isSyntaxError) {
source.sendMessage(Component.text(e.getMessage(), NamedTextColor.RED));
result = com.velocitypowered.api.command.CommandResult.SYNTAX_ERROR;
// This is, of course, a lie, but the API will need to change...
return true;
} else {
result = CommandResult.FORWARDED;
return false;
}
} catch (final Throwable e) {

CommandSyntaxException#getMessage ends up flattening the Component held by VelocityBrigadierMessage into plain text (see here).

Instead, I believe this code should use CommandSyntaxException#getRawMessage. If the (Message e.getRawMessage()) instanceof VelocityBrigadierMessage, then the Component held by VelocityBrigadierMessage should be sent directly to the client. If that is a TranslateableComponent, then its key should be sent to the client for them to deal with as appropriate https://wiki.vg/Text_formatting#Translatable_content.

I'm not very familiar with how translated messages work on Velocity, but I expect that these equivalent commands on Paper and Velocity should work the same.