Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package gg.grounds.proxy.velocity.command

import gg.grounds.i18n.MessageKey
import gg.grounds.i18n.Translations
import net.kyori.adventure.audience.Audience
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.event.ClickEvent
import net.kyori.adventure.text.event.HoverEvent

internal data class CommandAction(val command: String, val runsImmediately: Boolean) {
companion object {
fun run(command: String) = CommandAction(command, runsImmediately = true)

fun suggest(command: String) = CommandAction(command, runsImmediately = false)
}
}

/** Makes a localized action label discoverable without showing its command syntax in chat. */
internal fun interactiveCommand(
message: Component,
action: CommandAction,
hint: String,
): Component =
message
.clickEvent(
if (action.runsImmediately) ClickEvent.runCommand(action.command)
else ClickEvent.suggestCommand(action.command)
)
.hoverEvent(HoverEvent.showText(Component.text(hint)))

/**
* Sends an interactive localized system message through the normal renderer, keeping its category,
* level, prefix, and palette intact.
*/
internal fun Translations.sendInteractive(
audience: Audience,
key: MessageKey,
action: CommandAction,
hint: String,
vararg arguments: Pair<String, Any>,
) {
sendRendered(audience, key, interactiveCommand(render(key, audience, *arguments), action, hint))
}

/**
* Read-only MOTD help can run immediately; edits and the destructive reset stay in the input box.
*/
internal fun motdHelpAction(usage: String): CommandAction {
val command = usage.substringBefore(" <").substringBefore(" [")
return when (command) {
"/motd",
"/motd preview" -> CommandAction.run(command)
else -> CommandAction.suggest(command + if ('<' in usage) " " else "")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ class MotdCommand(

private fun set(source: CommandSource, text: String) {
if (text.isEmpty()) {
messages.send(
messages.sendInteractive(
source,
ProxySystemMessage.MOTD_USAGE_SET,
"usage" to "/motd set <MiniMessage>",
CommandAction.suggest("/motd set "),
"/motd set <MiniMessage>",
)
return
}
Expand All @@ -117,10 +118,11 @@ class MotdCommand(

private fun import(source: CommandSource, idOrUrl: String) {
if (idOrUrl.isEmpty()) {
messages.send(
messages.sendInteractive(
source,
ProxySystemMessage.MOTD_USAGE_IMPORT,
"usage" to "/motd import <motd.gg link or id>",
CommandAction.suggest("/motd import "),
"/motd import <motd.gg link or id>",
)
return
}
Expand Down Expand Up @@ -161,16 +163,22 @@ class MotdCommand(
private fun maxPlayers(source: CommandSource, argument: String) {
val document = manager.current()
if (document == null) {
messages.send(source, ProxySystemMessage.MOTD_REQUIRED_FOR_MAX_PLAYERS)
messages.sendInteractive(
source,
ProxySystemMessage.MOTD_REQUIRED_FOR_MAX_PLAYERS,
CommandAction.suggest("/motd set "),
"/motd set <MiniMessage>",
)
return
}
val value =
when {
argument.isEmpty() -> {
messages.send(
messages.sendInteractive(
source,
ProxySystemMessage.MOTD_USAGE_MAX_PLAYERS,
"usage" to "/motd maxplayers <number|clear>",
CommandAction.suggest("/motd maxplayers "),
"/motd maxplayers <number|clear>",
)
return
}
Expand Down Expand Up @@ -237,7 +245,7 @@ class MotdCommand(
ProxySystemMessage.MOTD_HELP_RESET to "/motd reset",
)
.forEach { (key, usage) ->
messages.send(source, key, "usage" to usage, "newline" to "<newline>")
messages.sendInteractive(source, key, motdHelpAction(usage), usage)
}
messages.send(
source,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,25 @@ class ProxyCommand(
?.proxies
?.sortedBy { it.proxyId }
?.forEach { entry ->
messages.send(
source,
if (entry.proxyId == proxyId) ProxySystemMessage.PROXY_ENTRY_CURRENT
else ProxySystemMessage.PROXY_ENTRY,
"proxy" to entry.proxyId,
"region" to (entry.region ?: "—"),
"count" to entry.players,
)
val arguments =
arrayOf(
"proxy" to entry.proxyId,
"region" to (entry.region ?: "—"),
"count" to entry.players,
)
if (entry.proxyId == proxyId) {
messages.send(source, ProxySystemMessage.PROXY_ENTRY_CURRENT, *arguments)
} else {
messages.sendInteractive(
source,
ProxySystemMessage.PROXY_ENTRY,
CommandAction.run("/proxy ${entry.proxyId}"),
"/proxy ${entry.proxyId}",
*arguments,
)
}
}
messages.send(source, ProxySystemMessage.PROXY_USAGE, "syntax" to "/proxy <id>")
messages.send(source, ProxySystemMessage.PROXY_USAGE)
}

override fun suggest(invocation: SimpleCommand.Invocation): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,23 @@ class RegionCommand(
messages.send(player, ProxySystemMessage.REGION_HEADER)
catalog.regions.forEach { region ->
val isHere = here != null && region.code.equals(here, true)
messages.send(
player,
if (isHere) ProxySystemMessage.REGION_ENTRY_CURRENT
else ProxySystemMessage.REGION_ENTRY,
"region" to region.code,
)
if (isHere) {
messages.send(
player,
ProxySystemMessage.REGION_ENTRY_CURRENT,
"region" to region.code,
)
} else {
messages.sendInteractive(
player,
ProxySystemMessage.REGION_ENTRY,
CommandAction.run("/region ${region.code}"),
"/region ${region.code}",
"region" to region.code,
)
}
}
messages.send(player, ProxySystemMessage.REGION_USAGE, "syntax" to "/region <code>")
messages.send(player, ProxySystemMessage.REGION_USAGE)
}

override fun suggest(invocation: SimpleCommand.Invocation): List<String> {
Expand Down
30 changes: 15 additions & 15 deletions velocity/src/main/resources/gg/grounds/proxy/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ region.already-here=<warning>You are already in <region>.</warning>
region.unavailable=<danger>Region switching is unavailable right now.</danger>
region.moving=<success>Moving you to <region>...</success>
region.header=<text>--- Regions ---</text>
region.entry=<muted><region></muted>
region.entry=<muted>Move to <region></muted>
region.entry.current=<success><region> (you are here)</success>
region.usage=<muted>Use <syntax> to move.</muted>
region.usage=<muted>Click a region to move.</muted>
party.transfer.following=<success>Following the party leader to <server>...</success>
motd.unknown-subcommand=<danger>Unknown subcommand '<subcommand>'.</danger>
motd.not-set=<warning>No MOTD is set; the proxy default is being served.</warning>
Expand All @@ -32,30 +32,30 @@ motd.changed-at=<muted>changed at: <text><time></text></muted>
motd.max-players=<muted>max players: <text><count></text></muted>
motd.max-players.default=<muted>max players: <text>proxy default</text></muted>
motd.raw=<muted>raw:</muted>
motd.usage.set=<warning>Usage: <usage></warning>
motd.usage.set=<warning>Set MOTD</warning>
motd.updated=<success>MOTD updated.</success>
motd.usage.import=<warning>Usage: <usage></warning>
motd.usage.import=<warning>Import MOTD</warning>
motd.fetching=<muted>Fetching from motd.gg...</muted>
motd.import-failed=<danger>Import failed: <error></danger>
motd.icon-skipped=<warning>The motd.gg document has a server icon; it was not imported (the network icon is served from the CDN).</warning>
motd.imported=<success>MOTD imported from motd.gg/<id>.</success>
motd.imported.named=<success>MOTD imported from motd.gg/<id> (<name>).</success>
motd.max-players.required=<danger>No MOTD is set — run /motd set first; max players is stored alongside it.</danger>
motd.usage.max-players=<warning>Usage: <usage></warning>
motd.max-players.required=<danger>No MOTD is set. Set MOTD first; max players is stored alongside it.</danger>
motd.usage.max-players=<warning>Set maximum players</warning>
motd.invalid-player-count=<danger>'<value>' is not a player count.</danger>
motd.max-players.cleared=<success>Max players cleared; the proxy value is used again.</success>
motd.max-players.set=<success>Max players set to <count>.</success>
motd.removed=<success>MOTD removed; the proxy default is served again.</success>
motd.nothing-to-remove=<info>There was no MOTD to remove.</info>
motd.remove-failed=<danger>Could not remove the MOTD: <error></danger>
motd.nothing-to-preview=<danger>Nothing to preview: no MOTD is set.</danger>
motd.help.header=<text>--- /motd ---</text>
motd.help.show=<text><usage></text><muted> — show the MOTD in use</muted>
motd.help.set=<text><usage></text><muted> — change it; <newline> starts the second line</muted>
motd.help.import=<text><usage></text><muted> — take the design from motd.gg</muted>
motd.help.max-players=<text><usage></text><muted> — the number right of the slash</muted>
motd.help.preview=<text><usage></text><muted> — render it here without changing anything</muted>
motd.help.reset=<text><usage></text><muted> — remove it and serve the proxy default</muted>
motd.help.header=<text>--- MOTD ---</text>
motd.help.show=<text>Show current MOTD</text>
motd.help.set=<text>Change MOTD; \\<newline> starts the second line</text>
motd.help.import=<text>Import a design from motd.gg</text>
motd.help.max-players=<text>Set maximum players</text>
motd.help.preview=<text>Preview MOTD without changing it</text>
motd.help.reset=<text>Remove MOTD and use the proxy default</text>
motd.placeholders=<muted>Placeholders: <placeholders></muted>
motd.save-failed=<danger>Could not save the MOTD: <error></danger>
motd.invalid-mini-message=<danger>That is not valid MiniMessage: <error></danger>
Expand All @@ -75,6 +75,6 @@ proxy.moving=<success>Looking for proxy <proxy>...</success>
proxy.arrived=<success>You are now on <proxy>.</success>
proxy.not-reached=<danger>Did not reach <proxy> after <hops> attempts; you are on <current>.</danger>
proxy.current=<text>You are on <proxy>.</text>
proxy.entry=<muted><proxy> (<region>): <count></muted>
proxy.entry=<muted>Switch to <proxy> (<region>): <count></muted>
proxy.entry.current=<success><proxy> (<region>): <count> (you are here)</success>
proxy.usage=<muted>Use <syntax> to switch.</muted>
proxy.usage=<muted>Click a proxy to switch.</muted>
30 changes: 15 additions & 15 deletions velocity/src/main/resources/gg/grounds/proxy/messages_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ region.already-here=<warning>Du bist bereits in <region>.</warning>
region.unavailable=<danger>Der Regionswechsel ist derzeit nicht verfügbar.</danger>
region.moving=<success>Du wirst nach <region> verschoben...</success>
region.header=<text>--- Regionen ---</text>
region.entry=<muted><region></muted>
region.entry=<muted>Zu <region> wechseln</muted>
region.entry.current=<success><region> (du bist hier)</success>
region.usage=<muted>Nutze <syntax>, um zu wechseln.</muted>
region.usage=<muted>Klicke auf eine Region, um zu wechseln.</muted>
party.transfer.following=<success>Folge dem Party-Leader zu <server>...</success>
motd.unknown-subcommand=<danger>Unbekannter Unterbefehl '<subcommand>'.</danger>
motd.not-set=<warning>Keine MOTD gesetzt; der Proxy-Standard wird angezeigt.</warning>
Expand All @@ -30,30 +30,30 @@ motd.changed-at=<muted>geändert am: <text><time></text></muted>
motd.max-players=<muted>maximale Spieler: <text><count></text></muted>
motd.max-players.default=<muted>maximale Spieler: <text>Proxy-Standard</text></muted>
motd.raw=<muted>Rohtext:</muted>
motd.usage.set=<warning>Verwendung: <usage></warning>
motd.usage.set=<warning>MOTD setzen</warning>
motd.updated=<success>MOTD aktualisiert.</success>
motd.usage.import=<warning>Verwendung: <usage></warning>
motd.usage.import=<warning>MOTD importieren</warning>
motd.fetching=<muted>Von motd.gg wird geladen...</muted>
motd.import-failed=<danger>Import fehlgeschlagen: <error></danger>
motd.icon-skipped=<warning>Das motd.gg-Dokument enthält ein Server-Icon; es wurde nicht importiert (das Netzwerk-Icon kommt vom CDN).</warning>
motd.imported=<success>MOTD von motd.gg/<id> importiert.</success>
motd.imported.named=<success>MOTD von motd.gg/<id> (<name>) importiert.</success>
motd.max-players.required=<danger>Keine MOTD gesetzt — führe zuerst /motd set aus; die maximale Spielerzahl wird damit gespeichert.</danger>
motd.usage.max-players=<warning>Verwendung: <usage></warning>
motd.max-players.required=<danger>Keine MOTD gesetzt. Setze zuerst eine MOTD; die maximale Spielerzahl wird damit gespeichert.</danger>
motd.usage.max-players=<warning>Maximale Spielerzahl setzen</warning>
motd.invalid-player-count=<danger>'<value>' ist keine Spielerzahl.</danger>
motd.max-players.cleared=<success>Maximale Spielerzahl entfernt; der Proxy-Wert wird wieder verwendet.</success>
motd.max-players.set=<success>Maximale Spielerzahl auf <count> gesetzt.</success>
motd.removed=<success>MOTD entfernt; der Proxy-Standard wird wieder angezeigt.</success>
motd.nothing-to-remove=<info>Es gab keine MOTD zum Entfernen.</info>
motd.remove-failed=<danger>MOTD konnte nicht entfernt werden: <error></danger>
motd.nothing-to-preview=<danger>Keine Vorschau möglich: Es ist keine MOTD gesetzt.</danger>
motd.help.header=<text>--- /motd ---</text>
motd.help.show=<text><usage></text><muted> — verwendete MOTD anzeigen</muted>
motd.help.set=<text><usage></text><muted> — ändern; <newline> beginnt die zweite Zeile</muted>
motd.help.import=<text><usage></text><muted> — Design von motd.gg übernehmen</muted>
motd.help.max-players=<text><usage></text><muted> — Zahl rechts vom Schrägstrich</muted>
motd.help.preview=<text><usage></text><muted> — hier anzeigen, ohne etwas zu ändern</muted>
motd.help.reset=<text><usage></text><muted> — entfernen und Proxy-Standard verwenden</muted>
motd.help.header=<text>--- MOTD ---</text>
motd.help.show=<text>Aktuelle MOTD anzeigen</text>
motd.help.set=<text>MOTD ändern; \\<newline> beginnt die zweite Zeile</text>
motd.help.import=<text>Design von motd.gg importieren</text>
motd.help.max-players=<text>Maximale Spielerzahl setzen</text>
motd.help.preview=<text>MOTD anzeigen, ohne etwas zu ändern</text>
motd.help.reset=<text>MOTD entfernen und Proxy-Standard verwenden</text>
motd.placeholders=<muted>Platzhalter: <placeholders></muted>
motd.save-failed=<danger>MOTD konnte nicht gespeichert werden: <error></danger>
motd.invalid-mini-message=<danger>Das ist kein gültiges MiniMessage: <error></danger>
Expand All @@ -73,6 +73,6 @@ proxy.moving=<success>Suche Proxy <proxy>...</success>
proxy.arrived=<success>Du bist jetzt auf <proxy>.</success>
proxy.not-reached=<danger><proxy> nach <hops> Versuchen nicht erreicht; du bist auf <current>.</danger>
proxy.current=<text>Du bist auf <proxy>.</text>
proxy.entry=<muted><proxy> (<region>): <count></muted>
proxy.entry=<muted>Zu <proxy> wechseln (<region>): <count></muted>
proxy.entry.current=<success><proxy> (<region>): <count> (du bist hier)</success>
proxy.usage=<muted>Nutze <syntax>, um zu wechseln.</muted>
proxy.usage=<muted>Klicke auf einen Proxy, um zu wechseln.</muted>
Loading
Loading