Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] StringArgumentType.word() does not support non-ASCII characters #329

Closed
StepanovIgorS opened this issue Nov 2, 2021 · 20 comments
Closed
Labels

Comments

@StepanovIgorS
Copy link

StepanovIgorS commented Nov 2, 2021

Describe the bug
failed building project with error "could not find...". more info in screenshots

To Reproduce
Steps to reproduce the behavior:

  1. try to build project with chimera
  2. see error

Expected behavior
successful build

Screenshots
image

Environment (please complete the following information):

  • Java Version -16
  • Platform - Paper
  • Platform Version - 1.1.12
  • Chimera Version - 5.0.0

Additional context
tried to downloads two files: satisfactory and utilitary

when clicking on any link, a 404 error is returned

@Pante
Copy link
Owner

Pante commented Nov 3, 2021

The error message stems from Gradle trying to find those dependencies in the same repository. Just to confirm, are you trying to build a project that depends on Chimera, or build Chimera?

If it’s the first, it shouldn’t require Utiltiary & Satisfactory since they’re already shaded into Typist.

If it’s the latter and judging by the error message, you probably didn’t include the correct Maven repository as utilitary and satisfactory are hosted in a different repository from Chimera.

Lastly, would you mind attaching your build.gradle please?

@StepanovIgorS
Copy link
Author

StepanovIgorS commented Nov 3, 2021

I trying to run task build, but get error. Two days ago, it works succefully. but next morning (I don't touched build.gradle and settings.gradle) it don't work. I tried to fix this error myself, but failed :( (p.s sorry for my english)

My build.gradle.kts and settings.gradle.kts:
Screenshot_1
Screenshot_2

Screenshot_3

Pante added a commit that referenced this issue Nov 3, 2021
@Pante
Copy link
Owner

Pante commented Nov 3, 2021

Seems like I found the issue, it turns out I included maven-shade for all the projects except Typist.

I've deploy a fix to stable, please remove your cached version of Typist and try again. Do let me know if the issue persists. Thanks for taking the time to report the issue!

@StepanovIgorS
Copy link
Author

Thank you, it works! But I have one question. I wrote command, but when I trying to use argument on russian language or use special symbol, I get error:

image

How to fix this problem? When I trying to test this on CommandExecutor (without chimera) I don't get any errors.

@Pante
Copy link
Owner

Pante commented Nov 4, 2021

Could you post your code please? Internally both Chimera and Spigot/Paper uses Brigadier to parse commands so there shouldn’t be a difference.

@StepanovIgorS
Copy link
Author

image
image
image

@Pante
Copy link
Owner

Pante commented Nov 4, 2021

I'll be honest, I have no clue, sorry.

@ghost
Copy link

ghost commented Nov 4, 2021

#russianlivesmatter

@Pante
Copy link
Owner

Pante commented Nov 4, 2021

Thank you, it works! But I have one question. I wrote command, but when I trying to use argument on russian language or use special symbol, I get error:

image

How to fix this problem? When I trying to test this on CommandExecutor (without chimera) I don't get any errors.

Could you add the following information?

  • What exactly did you type to get the error?
  • What was the expected format? i.e. /my-command <arg1> <arg2>
  • What was the expected result?

On another note, please copy & paste the code, and surround it in ```my code here```, it's hard to read from the images.

@StepanovIgorS
Copy link
Author

StepanovIgorS commented Nov 6, 2021

  1. I entered russian symbols or special symbols.
  2. /prefix
  3. I shouldn't have gotten the error (see more info in code below)

code:

package ru.plugin.prefixes

import com.karuslabs.commons.command.OptionalContext
import com.karuslabs.commons.command.dispatcher.Dispatcher
import com.karuslabs.commons.command.tree.nodes.Argument
import com.karuslabs.commons.command.tree.nodes.Literal
import com.karuslabs.commons.command.types.PlayersType
import com.karuslabs.typist.annotations.Bind
import com.karuslabs.typist.annotations.Command
import com.karuslabs.typist.annotations.Let
import com.karuslabs.typist.annotations.Pack
import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.context.CommandContext
import com.mojang.brigadier.suggestion.SuggestionProvider
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.TextComponent
import net.kyori.adventure.text.format.NamedTextColor
import org.bukkit.Bukkit
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.function.Consumer

object PrefixCommand {
    fun initialize() {
        val player = Argument.of("player", PlayersType())
            .requires { it.hasPermission("Prefixes.canGivePrefixToOthers") }
            .executes { context ->
                val player = context.source as? Player ?: return@executes 0
                val rawOtherPlayer = context.getArgument("player", String::class.java)
                val otherPlayer: Player? = Bukkit.getPlayer(rawOtherPlayer)
                if (otherPlayer == null) {
                    player.sendMessage("Пользователь не найден")
                    return@executes 1
                }
                if (!otherPlayer.isOnline) {
                    player.sendMessage("Пользователь не в сети!")
                }
                Base.newConnection
                transaction {
                    val pref = Prefix.find { Prefixes.UUID eq otherPlayer.uniqueId.toString() }
                    val argumentPrefix = context.getArgument("prefix", String::class.java)
                    if (!pref.empty()) {
                        pref.first().prefix = argumentPrefix
                    } else {
                        Prefix.new {
                            UUID = otherPlayer.uniqueId.toString()
                            prefix = argumentPrefix
                        }
                    }
                    otherPlayer.displayName(Text.text("$argumentPrefix ${otherPlayer.name}"))
                    otherPlayer.playerListName(Text.text("$argumentPrefix ${otherPlayer.name}"))
                    commit()
                }
                player.sendMessage("Вы успешно изменили префикс пользователю ${otherPlayer.name}")
                otherPlayer.sendMessage("Вам был изменён префикс!")
                return@executes 1
            }.build()
        val prefixArgument = Argument.of("prefix", StringArgumentType.word())
            .executes { context ->
                val player = context.source as? Player ?: return@executes 0
                val argumentPrefix = context.getArgument("prefix", String::class.java)
                Base.newConnection
                transaction {
                    val pref = Prefix.find { Prefixes.UUID eq player.uniqueId.toString() }
                    if (!pref.empty()) {
                        pref.first().prefix = argumentPrefix
                    } else {
                        Prefix.new {
                            UUID = player.uniqueId.toString()
                            prefix = argumentPrefix
                        }
                    }
                }
                player.displayName(Text.text("$argumentPrefix ${player.name}"))
                player.playerListName(Text.text("$argumentPrefix ${player.name}"))
                player.sendMessage("Вы успешно изменили себе префикс")
                return@executes 1
            }.then(player).suggests { context, builder ->
                builder.suggest("Топчик").buildFuture()
            }

        val prefix = Literal.of("prefix")
            .requires {
                it.hasPermission("Prefixes.prefix")
            }.executes { context ->
                context.source.sendMessage(Text.text("Использование: /prefix prefix", NamedTextColor.RED))
                return@executes 1
            }.then(prefixArgument).build()

        val dispatcher = Dispatcher.of(plugin)
        dispatcher.root.addChild(prefix)
        dispatcher.update()
    }
}

operator fun Component.plus(component: Component) = append(component)

@Pante
Copy link
Owner

Pante commented Nov 6, 2021

From a glance, there doesn't seem to be an issue with the code snippet proven which means that it's probably a parsing issue with Brigadier or PlayersType.

The information you have provided is far too vague to pinpoint the issue, "I entered russian symbols or special symbols." doesn't really answer the question as we need a concrete example of the how the command was invoked to trigger the unexpected behaviour, i.e. /prefix some-argument player1, player2. Did it work when you did not use special characters in the prefix argument and in the argument, and vice versa?

@StepanovIgorS
Copy link
Author

when I don't use special symbols or russian symbols IT WORKS but when I use russian symbols or special symbols! command works without errors when I don't use russian or special symbols (because unfortunately, I live in russia, that many players are live in russia too).

@Pante
Copy link
Owner

Pante commented Nov 6, 2021

To re-iterate, it is extremely difficult to pinpoint, let alone reproduce the issue on our side if no sample input is provided. "I entered Russian symbols or special symbols." does not help us to pinpoint the issue. We need to know exactly what to input to trigger the error, in the form of an example. In addition, does it affect a specific argument, i.e. prefixArgument or player? Or does it cause the error regardless of where the special characters are used?

If no such example is provided, it is exceedingly difficult to make any progress on the issue.

@StepanovIgorS
Copy link
Author

try to enter "/prefix топчик" or "/prefix &7kdkd". You get error. And try to enter "/prefix test" - you don't get error (you have to rewrite my code because I use connection to database).

@Pante
Copy link
Owner

Pante commented Nov 7, 2021

After some investigation, it seems like I found the issue.

prefixArgument uses Brigadier's StringArgumentType.word() to parse strings. If we look at StringArgumentType.word()'s implementation:

    @Override
    public String parse(final StringReader reader) throws CommandSyntaxException {
        if (type == StringType.GREEDY_PHRASE) {
            final String text = reader.getRemaining();
            reader.setCursor(reader.getTotalLength());
            return text;
        } else if (type == StringType.SINGLE_WORD) {
            return reader.readUnquotedString(); // <-- calls this
        } else {
            return reader.readString();
        }
    }
    
    // Somewhere inside reader.readUnquotedString(), it calls
    public static boolean isAllowedInUnquotedString(final char c) {
        return c >= '0' && c <= '9'
            || c >= 'A' && c <= 'Z'
            || c >= 'a' && c <= 'z'
            || c == '_' || c == '-'
            || c == '.' || c == '+';
    }

This is honestly kind of silly and fundamentally broken since it only supports ASCII characters. Moving forward, I'll open an issue regarding this on Brigadier's repository. In the interim, I'll implement a custom ArgumentType in Chimera that supports non-ASCII word arguments in a 5.0.1 release.

@Pante Pante changed the title [BUG] [BUG] StringArgumentType.word() does not support non-ASCII characters Nov 7, 2021
@Pante
Copy link
Owner

Pante commented Nov 7, 2021

I've released 5.1.0 that addresses the issue. Please use WordType.word() instead of StringArgumentType.word(). One downside of this is that special characters in a string argument will cause the text to turn red on the client since Brigadier doesn't natively support this. Unfortunately there's nothing that can be done on our side to resolve that. I've created an issue in Brigadier's repository to track that.

Do let re-open this issue if the problem persists.

@Pante Pante closed this as completed Nov 7, 2021
@Pante Pante pinned this issue Nov 7, 2021
@StepanovIgorS
Copy link
Author

After update, I get error:

image

@Pante
Copy link
Owner

Pante commented Nov 7, 2021

Whoops, forgot to add maven-shade to plugin once again, I've redeployed 5.1.0 which should be available shortly.

@StepanovIgorS
Copy link
Author

error didn't fixed before your commit:

image

@Pante
Copy link
Owner

Pante commented Nov 7, 2021

I've just re-checked the maven repository and it does contain the shaded jar. Invalidate your local maven repository and try again.

@Pante Pante unpinned this issue Mar 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants