mirror of
https://github.com/PaperMC/Velocity.git
synced 2026-02-17 22:47:42 +01:00
Add localization support. Fixes #230
This is less flexible, but it is an Adventure-native solution and doesn't require an onerous amount of work to maintain.
This commit is contained in:
@@ -78,6 +78,7 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -90,7 +91,11 @@ import java.util.function.IntFunction;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.kyori.adventure.audience.Audience;
|
import net.kyori.adventure.audience.Audience;
|
||||||
import net.kyori.adventure.audience.ForwardingAudience;
|
import net.kyori.adventure.audience.ForwardingAudience;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
|
import net.kyori.adventure.translation.TranslationRegistry;
|
||||||
|
import net.kyori.adventure.util.UTF8ResourceBundleControl;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.asynchttpclient.AsyncHttpClient;
|
import org.asynchttpclient.AsyncHttpClient;
|
||||||
@@ -193,6 +198,8 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
logger.info("Booting up {} {}...", version().getName(), version().getVersion());
|
logger.info("Booting up {} {}...", version().getName(), version().getVersion());
|
||||||
console.setupStreams();
|
console.setupStreams();
|
||||||
|
|
||||||
|
registerTranslations();
|
||||||
|
|
||||||
serverKeyPair = EncryptionUtils.createRsaKeyPair(1024);
|
serverKeyPair = EncryptionUtils.createRsaKeyPair(1024);
|
||||||
|
|
||||||
cm.logChannelInformation();
|
cm.logChannelInformation();
|
||||||
@@ -236,6 +243,15 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
Metrics.VelocityMetrics.startMetrics(this, configuration.getMetrics());
|
Metrics.VelocityMetrics.startMetrics(this, configuration.getMetrics());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerTranslations() {
|
||||||
|
final TranslationRegistry translationRegistry = TranslationRegistry
|
||||||
|
.create(Key.key("velocity", "translations"));
|
||||||
|
translationRegistry.registerAll(Locale.US,
|
||||||
|
ResourceBundle.getBundle("com/velocitypowered/proxy/messages", Locale.US,
|
||||||
|
UTF8ResourceBundleControl.get()), false);
|
||||||
|
GlobalTranslator.get().addSource(translationRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings("DM_EXIT")
|
@SuppressFBWarnings("DM_EXIT")
|
||||||
private void doStartupConfigLoad() {
|
private void doStartupConfigLoad() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Velocity Contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.velocitypowered.proxy.command.builtin;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.TranslatableComponent;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
|
public class CommandMessages {
|
||||||
|
|
||||||
|
public static final TranslatableComponent PLAYERS_ONLY = Component.translatable(
|
||||||
|
"velocity.command.players-only", NamedTextColor.RED);
|
||||||
|
public static final TranslatableComponent SERVER_DOES_NOT_EXIST = Component.translatable(
|
||||||
|
"velocity.command.server-does-not-exist", NamedTextColor.RED);
|
||||||
|
}
|
||||||
@@ -78,11 +78,7 @@ public class GlistCommand {
|
|||||||
final CommandSource source = context.getSource();
|
final CommandSource source = context.getSource();
|
||||||
sendTotalProxyCount(source);
|
sendTotalProxyCount(source);
|
||||||
source.sendMessage(Identity.nil(),
|
source.sendMessage(Identity.nil(),
|
||||||
Component.text().content("To view all players on servers, use ")
|
Component.translatable("velocity.command.glist-view-all", NamedTextColor.YELLOW));
|
||||||
.color(NamedTextColor.YELLOW)
|
|
||||||
.append(Component.text("/glist all", NamedTextColor.DARK_AQUA))
|
|
||||||
.append(Component.text(".", NamedTextColor.YELLOW))
|
|
||||||
.build());
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +94,7 @@ public class GlistCommand {
|
|||||||
Optional<RegisteredServer> registeredServer = server.server(serverName);
|
Optional<RegisteredServer> registeredServer = server.server(serverName);
|
||||||
if (!registeredServer.isPresent()) {
|
if (!registeredServer.isPresent()) {
|
||||||
source.sendMessage(Identity.nil(),
|
source.sendMessage(Identity.nil(),
|
||||||
Component.text("Server " + serverName + " doesn't exist.", NamedTextColor.RED));
|
CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName)));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sendServerPlayers(source, registeredServer.get(), false);
|
sendServerPlayers(source, registeredServer.get(), false);
|
||||||
@@ -107,10 +103,19 @@ public class GlistCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendTotalProxyCount(CommandSource target) {
|
private void sendTotalProxyCount(CommandSource target) {
|
||||||
|
int online = server.countConnectedPlayers();
|
||||||
target.sendMessage(Identity.nil(), Component.text()
|
target.sendMessage(Identity.nil(), Component.text()
|
||||||
.content("There are ").color(NamedTextColor.YELLOW)
|
.append(Component.text(Integer.toString(online), NamedTextColor.GREEN))
|
||||||
.append(Component.text(server.connectedPlayers().size(), NamedTextColor.GREEN))
|
.append(Component.space())
|
||||||
.append(Component.text(" player(s) online.", NamedTextColor.YELLOW))
|
.append(Component.translatable(
|
||||||
|
online == 1
|
||||||
|
? "velocity.command.glist-player-singular"
|
||||||
|
: "velocity.command.glist-player-plural",
|
||||||
|
NamedTextColor.YELLOW
|
||||||
|
))
|
||||||
|
.append(Component.space())
|
||||||
|
.append(Component.translatable("velocity.command.glist-total-suffix",
|
||||||
|
NamedTextColor.YELLOW))
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import java.util.stream.Stream;
|
|||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.TextComponent;
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.TranslatableComponent;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
@@ -53,8 +54,7 @@ public class ServerCommand implements SimpleCommand {
|
|||||||
final String[] args = invocation.arguments();
|
final String[] args = invocation.arguments();
|
||||||
|
|
||||||
if (!(source instanceof Player)) {
|
if (!(source instanceof Player)) {
|
||||||
source.sendMessage(Identity.nil(), Component.text("Only players may run this command.",
|
source.sendMessage(Identity.nil(), CommandMessages.PLAYERS_ONLY);
|
||||||
NamedTextColor.RED));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +64,8 @@ public class ServerCommand implements SimpleCommand {
|
|||||||
String serverName = args[0];
|
String serverName = args[0];
|
||||||
Optional<RegisteredServer> toConnect = server.server(serverName);
|
Optional<RegisteredServer> toConnect = server.server(serverName);
|
||||||
if (!toConnect.isPresent()) {
|
if (!toConnect.isPresent()) {
|
||||||
player.sendMessage(Identity.nil(),
|
player.sendMessage(Identity.nil(), CommandMessages.SERVER_DOES_NOT_EXIST
|
||||||
Component.text("Server " + serverName + " doesn't exist.", NamedTextColor.RED));
|
.args(Component.text(serverName)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,19 +78,23 @@ public class ServerCommand implements SimpleCommand {
|
|||||||
private void outputServerInformation(Player executor) {
|
private void outputServerInformation(Player executor) {
|
||||||
String currentServer = executor.connectedServer().map(ServerConnection::serverInfo)
|
String currentServer = executor.connectedServer().map(ServerConnection::serverInfo)
|
||||||
.map(ServerInfo::name).orElse("<unknown>");
|
.map(ServerInfo::name).orElse("<unknown>");
|
||||||
executor.sendMessage(Identity.nil(), Component.text(
|
executor.sendMessage(Identity.nil(), Component.translatable(
|
||||||
"You are currently connected to " + currentServer + ".", NamedTextColor.YELLOW));
|
"velocity.command.server-current-server",
|
||||||
|
NamedTextColor.YELLOW,
|
||||||
|
Component.text(currentServer)));
|
||||||
|
|
||||||
List<RegisteredServer> servers = BuiltinCommandUtil.sortedServerList(server);
|
List<RegisteredServer> servers = BuiltinCommandUtil.sortedServerList(server);
|
||||||
if (servers.size() > MAX_SERVERS_TO_LIST) {
|
if (servers.size() > MAX_SERVERS_TO_LIST) {
|
||||||
executor.sendMessage(Identity.nil(), Component.text(
|
executor.sendMessage(Identity.nil(), Component.translatable(
|
||||||
"Too many servers to list. Tab-complete to show all servers.", NamedTextColor.RED));
|
"velocity.command.server-too-many", NamedTextColor.RED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assemble the list of servers as components
|
// Assemble the list of servers as components
|
||||||
TextComponent.Builder serverListBuilder = Component.text().content("Available servers: ")
|
TextComponent.Builder serverListBuilder = Component.text()
|
||||||
.color(NamedTextColor.YELLOW);
|
.append(Component.translatable("velocity.command.server-available",
|
||||||
|
NamedTextColor.YELLOW))
|
||||||
|
.append(Component.space());
|
||||||
for (int i = 0; i < servers.size(); i++) {
|
for (int i = 0; i < servers.size(); i++) {
|
||||||
RegisteredServer rs = servers.get(i);
|
RegisteredServer rs = servers.get(i);
|
||||||
serverListBuilder.append(formatServerComponent(currentServer, rs));
|
serverListBuilder.append(formatServerComponent(currentServer, rs));
|
||||||
@@ -106,17 +110,31 @@ public class ServerCommand implements SimpleCommand {
|
|||||||
ServerInfo serverInfo = server.serverInfo();
|
ServerInfo serverInfo = server.serverInfo();
|
||||||
TextComponent serverTextComponent = Component.text(serverInfo.name());
|
TextComponent serverTextComponent = Component.text(serverInfo.name());
|
||||||
|
|
||||||
String playersText = server.connectedPlayers().size() + " player(s) online";
|
int connectedPlayers = server.connectedPlayers().size();
|
||||||
|
TranslatableComponent playersTextComponent;
|
||||||
|
if (connectedPlayers == 1) {
|
||||||
|
playersTextComponent = Component.translatable("velocity.command.server-tooltip-player-online");
|
||||||
|
} else {
|
||||||
|
playersTextComponent = Component.translatable("velocity.command.server-tooltip-players-online");
|
||||||
|
}
|
||||||
|
playersTextComponent = playersTextComponent.args(Component.text(connectedPlayers));
|
||||||
|
|
||||||
if (serverInfo.name().equals(currentPlayerServer)) {
|
if (serverInfo.name().equals(currentPlayerServer)) {
|
||||||
serverTextComponent = serverTextComponent.color(NamedTextColor.GREEN)
|
serverTextComponent = serverTextComponent.color(NamedTextColor.GREEN)
|
||||||
.hoverEvent(
|
.hoverEvent(
|
||||||
showText(Component.text("Currently connected to this server\n" + playersText))
|
showText(
|
||||||
|
Component.translatable("velocity.command.server-tooltip-current-server")
|
||||||
|
.append(Component.newline())
|
||||||
|
.append(playersTextComponent))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
serverTextComponent = serverTextComponent.color(NamedTextColor.GRAY)
|
serverTextComponent = serverTextComponent.color(NamedTextColor.GRAY)
|
||||||
.clickEvent(ClickEvent.runCommand("/server " + serverInfo.name()))
|
.clickEvent(ClickEvent.runCommand("/server " + serverInfo.name()))
|
||||||
.hoverEvent(
|
.hoverEvent(
|
||||||
showText(Component.text("Click to connect to this server\n" + playersText))
|
showText(
|
||||||
|
Component.translatable("velocity.command.server-tooltip-offer-connect-server")
|
||||||
|
.append(Component.newline())
|
||||||
|
.append(playersTextComponent))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return serverTextComponent;
|
return serverTextComponent;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package com.velocitypowered.proxy.command.builtin;
|
package com.velocitypowered.proxy.command.builtin;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
@@ -49,6 +48,7 @@ import java.util.stream.Collectors;
|
|||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.TextComponent;
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.TranslatableComponent;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
@@ -180,17 +180,15 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
public void execute(CommandSource source, String @NonNull [] args) {
|
public void execute(CommandSource source, String @NonNull [] args) {
|
||||||
try {
|
try {
|
||||||
if (server.reloadConfiguration()) {
|
if (server.reloadConfiguration()) {
|
||||||
source.sendMessage(Identity.nil(), Component.text(
|
source.sendMessage(Component.translatable("velocity.command.reload-success",
|
||||||
"Configuration reloaded.", NamedTextColor.GREEN));
|
NamedTextColor.GREEN));
|
||||||
} else {
|
} else {
|
||||||
source.sendMessage(Identity.nil(), Component.text(
|
source.sendMessage(Component.translatable("velocity.command.reload-failure",
|
||||||
"Unable to reload your configuration. Check the console for more details.",
|
|
||||||
NamedTextColor.RED));
|
NamedTextColor.RED));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Unable to reload configuration", e);
|
logger.error("Unable to reload configuration", e);
|
||||||
source.sendMessage(Identity.nil(), Component.text(
|
source.sendMessage(Component.translatable("velocity.command.reload-failure",
|
||||||
"Unable to reload your configuration. Check the console for more details.",
|
|
||||||
NamedTextColor.RED));
|
NamedTextColor.RED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,33 +217,35 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
|
|
||||||
ProxyVersion version = server.version();
|
ProxyVersion version = server.version();
|
||||||
|
|
||||||
TextComponent velocity = Component.text().content(version.getName() + " ")
|
Component velocity = Component.text().content(version.getName() + " ")
|
||||||
.decoration(TextDecoration.BOLD, true)
|
.decoration(TextDecoration.BOLD, true)
|
||||||
.color(VELOCITY_COLOR)
|
.color(VELOCITY_COLOR)
|
||||||
.append(Component.text(version.getVersion()).decoration(TextDecoration.BOLD, false))
|
.append(Component.text(version.getVersion()).decoration(TextDecoration.BOLD, false))
|
||||||
.build();
|
.build();
|
||||||
TextComponent copyright = Component
|
Component copyright = Component
|
||||||
.text("Copyright 2018-2020 " + version.getVendor() + ". " + version.getName()
|
.translatable("velocity.command.version-copyright",
|
||||||
+ " is licensed under the terms of the GNU General Public License v3.");
|
Component.text(version.getVendor()),
|
||||||
|
Component.text(version.getName()));
|
||||||
source.sendMessage(Identity.nil(), velocity);
|
source.sendMessage(Identity.nil(), velocity);
|
||||||
source.sendMessage(Identity.nil(), copyright);
|
source.sendMessage(Identity.nil(), copyright);
|
||||||
|
|
||||||
if (version.getName().equals("Velocity")) {
|
if (version.getName().equals("Velocity")) {
|
||||||
TextComponent velocityWebsite = Component.text()
|
TextComponent embellishment = Component.text()
|
||||||
.content("Visit the ")
|
.append(Component.text().content("velocitypowered.com")
|
||||||
.append(Component.text().content("Velocity website")
|
|
||||||
.color(NamedTextColor.GREEN)
|
.color(NamedTextColor.GREEN)
|
||||||
|
.decoration(TextDecoration.UNDERLINED, true)
|
||||||
.clickEvent(
|
.clickEvent(
|
||||||
ClickEvent.openUrl("https://www.velocitypowered.com"))
|
ClickEvent.openUrl("https://www.velocitypowered.com"))
|
||||||
.build())
|
.build())
|
||||||
.append(Component.text(" or the "))
|
.append(Component.text(" - "))
|
||||||
.append(Component.text().content("Velocity GitHub")
|
.append(Component.text().content("GitHub")
|
||||||
.color(NamedTextColor.GREEN)
|
.color(NamedTextColor.GREEN)
|
||||||
|
.decoration(TextDecoration.UNDERLINED, true)
|
||||||
.clickEvent(ClickEvent.openUrl(
|
.clickEvent(ClickEvent.openUrl(
|
||||||
"https://github.com/VelocityPowered/Velocity"))
|
"https://github.com/VelocityPowered/Velocity"))
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
source.sendMessage(Identity.nil(), velocityWebsite);
|
source.sendMessage(Identity.nil(), embellishment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,12 +274,13 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
int pluginCount = plugins.size();
|
int pluginCount = plugins.size();
|
||||||
|
|
||||||
if (pluginCount == 0) {
|
if (pluginCount == 0) {
|
||||||
source.sendMessage(Identity.nil(), Component.text(
|
source.sendMessage(Component.translatable("velocity.command.no-plugins",
|
||||||
"No plugins installed.", NamedTextColor.YELLOW));
|
NamedTextColor.YELLOW));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextComponent.Builder output = Component.text().content("Plugins: ")
|
TranslatableComponent.Builder output = Component.translatable()
|
||||||
|
.key("velocity.command.plugins-list")
|
||||||
.color(NamedTextColor.YELLOW);
|
.color(NamedTextColor.YELLOW);
|
||||||
for (int i = 0; i < pluginCount; i++) {
|
for (int i = 0; i < pluginCount; i++) {
|
||||||
PluginContainer plugin = plugins.get(i);
|
PluginContainer plugin = plugins.get(i);
|
||||||
@@ -300,15 +301,21 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
|
|
||||||
description.url().ifPresent(url -> {
|
description.url().ifPresent(url -> {
|
||||||
hoverText.append(Component.newline());
|
hoverText.append(Component.newline());
|
||||||
hoverText.append(Component.text("Website: " + url));
|
hoverText.append(Component.translatable(
|
||||||
|
"velocity.command.plugin-tooltip-website",
|
||||||
|
Component.text(url)));
|
||||||
});
|
});
|
||||||
if (!description.authors().isEmpty()) {
|
if (!description.authors().isEmpty()) {
|
||||||
hoverText.append(Component.newline());
|
hoverText.append(Component.newline());
|
||||||
if (description.authors().size() == 1) {
|
if (description.authors().size() == 1) {
|
||||||
hoverText.append(Component.text("Author: " + description.authors().get(0)));
|
hoverText.append(Component.translatable("velocity.command.plugin-tooltip-author",
|
||||||
|
Component.text(description.authors().get(0))));
|
||||||
} else {
|
} else {
|
||||||
hoverText.append(Component.text("Authors: " + Joiner.on(", ")
|
hoverText.append(
|
||||||
.join(description.authors())));
|
Component.translatable("velocity.command.plugin-tooltip-author",
|
||||||
|
Component.text(String.join(", ", description.authors()))
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
description.description().ifPresent(pdesc -> {
|
description.description().ifPresent(pdesc -> {
|
||||||
@@ -352,8 +359,8 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
JsonArray connectOrder = new JsonArray();
|
JsonArray connectOrder = new JsonArray();
|
||||||
List<String> attemptedConnectionOrder = ImmutableList.copyOf(
|
List<String> attemptedConnectionOrder = ImmutableList.copyOf(
|
||||||
server.configuration().getAttemptConnectionOrder());
|
server.configuration().getAttemptConnectionOrder());
|
||||||
for (int i = 0; i < attemptedConnectionOrder.size(); i++) {
|
for (String s : attemptedConnectionOrder) {
|
||||||
connectOrder.add(attemptedConnectionOrder.get(i));
|
connectOrder.add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject proxyConfig = InformationUtils.collectProxyConfig(server.configuration());
|
JsonObject proxyConfig = InformationUtils.collectProxyConfig(server.configuration());
|
||||||
@@ -446,7 +453,7 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
e.getCause().printStackTrace();
|
e.getCause().printStackTrace();
|
||||||
} catch (JsonParseException e) {
|
} catch (JsonParseException e) {
|
||||||
source.sendMessage(Component.text()
|
source.sendMessage(Component.text()
|
||||||
.content("An error occurred on the Velocity-servers and the dump could not "
|
.content("An error occurred on the Velocity servers and the dump could not "
|
||||||
+ "be completed. Please contact the Velocity staff about this problem. "
|
+ "be completed. Please contact the Velocity staff about this problem. "
|
||||||
+ "If you do, provide the details about this error from the Velocity "
|
+ "If you do, provide the details about this error from the Velocity "
|
||||||
+ "console or server log.")
|
+ "console or server log.")
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@@ -72,25 +71,23 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
@Expose private final Advanced advanced;
|
@Expose private final Advanced advanced;
|
||||||
@Expose private final Query query;
|
@Expose private final Query query;
|
||||||
private final Metrics metrics;
|
private final Metrics metrics;
|
||||||
private final Messages messages;
|
|
||||||
private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent;
|
private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent;
|
||||||
private @Nullable Favicon favicon;
|
private @Nullable Favicon favicon;
|
||||||
|
|
||||||
private VelocityConfiguration(Servers servers, ForcedHosts forcedHosts, Advanced advanced,
|
private VelocityConfiguration(Servers servers, ForcedHosts forcedHosts, Advanced advanced,
|
||||||
Query query, Metrics metrics, Messages messages) {
|
Query query, Metrics metrics) {
|
||||||
this.servers = servers;
|
this.servers = servers;
|
||||||
this.forcedHosts = forcedHosts;
|
this.forcedHosts = forcedHosts;
|
||||||
this.advanced = advanced;
|
this.advanced = advanced;
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.metrics = metrics;
|
this.metrics = metrics;
|
||||||
this.messages = messages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode,
|
private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode,
|
||||||
boolean preventClientProxyConnections, boolean announceForge,
|
boolean preventClientProxyConnections, boolean announceForge,
|
||||||
PlayerInfoForwarding playerInfoForwardingMode, byte[] forwardingSecret,
|
PlayerInfoForwarding playerInfoForwardingMode, byte[] forwardingSecret,
|
||||||
boolean onlineModeKickExistingPlayers, PingPassthroughMode pingPassthrough, Servers servers,
|
boolean onlineModeKickExistingPlayers, PingPassthroughMode pingPassthrough, Servers servers,
|
||||||
ForcedHosts forcedHosts, Advanced advanced, Query query, Metrics metrics, Messages messages) {
|
ForcedHosts forcedHosts, Advanced advanced, Query query, Metrics metrics) {
|
||||||
this.bind = bind;
|
this.bind = bind;
|
||||||
this.motd = motd;
|
this.motd = motd;
|
||||||
this.showMaxPlayers = showMaxPlayers;
|
this.showMaxPlayers = showMaxPlayers;
|
||||||
@@ -106,7 +103,6 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
this.advanced = advanced;
|
this.advanced = advanced;
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.metrics = metrics;
|
this.metrics = metrics;
|
||||||
this.messages = messages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -373,10 +369,6 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
return advanced.isLogCommandExecutions();
|
return advanced.isLogCommandExecutions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Messages getMessages() {
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
@@ -450,7 +442,6 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
CommentedConfig advancedConfig = config.get("advanced");
|
CommentedConfig advancedConfig = config.get("advanced");
|
||||||
CommentedConfig queryConfig = config.get("query");
|
CommentedConfig queryConfig = config.get("query");
|
||||||
CommentedConfig metricsConfig = config.get("metrics");
|
CommentedConfig metricsConfig = config.get("metrics");
|
||||||
CommentedConfig messagesConfig = config.get("messages");
|
|
||||||
PlayerInfoForwarding forwardingMode = config.getEnumOrElse("player-info-forwarding-mode",
|
PlayerInfoForwarding forwardingMode = config.getEnumOrElse("player-info-forwarding-mode",
|
||||||
PlayerInfoForwarding.NONE);
|
PlayerInfoForwarding.NONE);
|
||||||
PingPassthroughMode pingPassthroughMode = config.getEnumOrElse("ping-passthrough",
|
PingPassthroughMode pingPassthroughMode = config.getEnumOrElse("ping-passthrough",
|
||||||
@@ -480,8 +471,7 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
new ForcedHosts(forcedHostsConfig),
|
new ForcedHosts(forcedHostsConfig),
|
||||||
new Advanced(advancedConfig),
|
new Advanced(advancedConfig),
|
||||||
new Query(queryConfig),
|
new Query(queryConfig),
|
||||||
new Metrics(metricsConfig),
|
new Metrics(metricsConfig)
|
||||||
new Messages(messagesConfig, defaultConfig.get("messages"))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -793,73 +783,4 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Messages {
|
|
||||||
|
|
||||||
private final CommentedConfig toml;
|
|
||||||
private final CommentedConfig defaultToml;
|
|
||||||
|
|
||||||
private final String kickPrefix;
|
|
||||||
private final String disconnectPrefix;
|
|
||||||
private final String onlineModeOnly;
|
|
||||||
private final String noAvailableServers;
|
|
||||||
private final String alreadyConnected;
|
|
||||||
private final String movedToNewServerPrefix;
|
|
||||||
private final String genericConnectionError;
|
|
||||||
|
|
||||||
private Messages(CommentedConfig toml, CommentedConfig defaultToml) {
|
|
||||||
this.toml = toml;
|
|
||||||
this.defaultToml = defaultToml;
|
|
||||||
this.kickPrefix = getString("kick-prefix");
|
|
||||||
this.disconnectPrefix = getString("disconnect-prefix");
|
|
||||||
this.onlineModeOnly = getString("online-mode-only");
|
|
||||||
this.noAvailableServers = getString("no-available-servers");
|
|
||||||
this.alreadyConnected = getString("already-connected");
|
|
||||||
this.movedToNewServerPrefix = getString("moved-to-new-server-prefix");
|
|
||||||
this.genericConnectionError = getString("generic-connection-error");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getString(String path) {
|
|
||||||
String def = defaultToml.getOrElse(path, "");
|
|
||||||
if (toml == null) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
return toml.getOrElse(path, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getKickPrefix(String server) {
|
|
||||||
return deserialize(String.format(kickPrefix, server));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getDisconnectPrefix(String server) {
|
|
||||||
return deserialize(String.format(disconnectPrefix, server));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getOnlineModeOnly() {
|
|
||||||
return deserialize(onlineModeOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getNoAvailableServers() {
|
|
||||||
return deserialize(noAvailableServers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getAlreadyConnected() {
|
|
||||||
return deserialize(alreadyConnected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getMovedToNewServerPrefix() {
|
|
||||||
return deserialize(movedToNewServerPrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getGenericConnectionError() {
|
|
||||||
return deserialize(genericConnectionError);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component deserialize(String str) {
|
|
||||||
if (str.startsWith("{")) {
|
|
||||||
return GsonComponentSerializer.gson().deserialize(str);
|
|
||||||
}
|
|
||||||
return LegacyComponentSerializer.legacyAmpersand().deserialize(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ import net.kyori.adventure.text.TextComponent;
|
|||||||
|
|
||||||
public class LoginSessionHandler implements MinecraftSessionHandler {
|
public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||||
|
|
||||||
private static final TextComponent MODERN_IP_FORWARDING_FAILURE = Component
|
private static final Component MODERN_IP_FORWARDING_FAILURE = Component
|
||||||
.text("Your server did not send a forwarding request to the proxy. Is it set up correctly?");
|
.translatable("velocity.error.modern-forwarding-failed");
|
||||||
|
|
||||||
private final VelocityServer server;
|
private final VelocityServer server;
|
||||||
private final VelocityServerConnection serverConn;
|
private final VelocityServerConnection serverConn;
|
||||||
|
|||||||
@@ -168,9 +168,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
.exceptionally(e -> {
|
.exceptionally(e -> {
|
||||||
logger.info("Exception occurred while running command for {}",
|
logger.info("Exception occurred while running command for {}",
|
||||||
player.username(), e);
|
player.username(), e);
|
||||||
player.sendMessage(Identity.nil(),
|
player.sendMessage(Component.translatable("velocity.command.generic-error",
|
||||||
Component.text("An error occurred while running this command.",
|
NamedTextColor.RED));
|
||||||
NamedTextColor.RED));
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -335,7 +334,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exception(Throwable throwable) {
|
public void exception(Throwable throwable) {
|
||||||
player.disconnect(server.configuration().getMessages().getGenericConnectionError());
|
player.disconnect(Component.translatable("velocity.error.player-connection-error",
|
||||||
|
NamedTextColor.RED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -446,18 +446,18 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
wrapped = cause;
|
wrapped = cause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String userMessage;
|
|
||||||
|
Component friendlyError;
|
||||||
if (connectedServer != null && connectedServer.serverInfo().equals(server.serverInfo())) {
|
if (connectedServer != null && connectedServer.serverInfo().equals(server.serverInfo())) {
|
||||||
userMessage = "Your connection to " + server.serverInfo().name() + " encountered an "
|
friendlyError = Component.translatable("velocity.error.connected-server-error",
|
||||||
+ "error.";
|
Component.text(server.serverInfo().name()));
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}: unable to connect to server {}", this, server.serverInfo().name(),
|
logger.error("{}: unable to connect to server {}", this, server.serverInfo().name(),
|
||||||
wrapped);
|
wrapped);
|
||||||
userMessage = "Unable to connect to " + server.serverInfo().name() + ". Try again "
|
friendlyError = Component.translatable("velocity.error.connecting-server-error",
|
||||||
+ "later.";
|
Component.text(server.serverInfo().name()));
|
||||||
}
|
}
|
||||||
handleConnectionException(server, null, Component.text(userMessage,
|
handleConnectionException(server, null, friendlyError.color(NamedTextColor.RED), safe);
|
||||||
NamedTextColor.RED), safe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -473,26 +473,22 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VelocityConfiguration.Messages messages = this.server.configuration().getMessages();
|
|
||||||
Component disconnectReason = GsonComponentSerializer.gson().deserialize(disconnect.getReason());
|
Component disconnectReason = GsonComponentSerializer.gson().deserialize(disconnect.getReason());
|
||||||
String plainTextReason = PASS_THRU_TRANSLATE.serialize(disconnectReason);
|
String plainTextReason = PASS_THRU_TRANSLATE.serialize(disconnectReason);
|
||||||
if (connectedServer != null && connectedServer.serverInfo().equals(server.serverInfo())) {
|
if (connectedServer != null && connectedServer.serverInfo().equals(server.serverInfo())) {
|
||||||
logger.error("{}: kicked from server {}: {}", this, server.serverInfo().name(),
|
logger.error("{}: kicked from server {}: {}", this, server.serverInfo().name(),
|
||||||
plainTextReason);
|
plainTextReason);
|
||||||
handleConnectionException(server, disconnectReason, Component.text()
|
handleConnectionException(server, disconnectReason,
|
||||||
.append(messages.getKickPrefix(server.serverInfo().name())
|
Component.translatable("velocity.error.moved-to-new-server", NamedTextColor.RED,
|
||||||
.colorIfAbsent(NamedTextColor.RED))
|
Component.text(server.serverInfo().name()),
|
||||||
.color(NamedTextColor.RED)
|
disconnectReason), safe);
|
||||||
.append(disconnectReason)
|
|
||||||
.build(), safe);
|
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}: disconnected while connecting to {}: {}", this,
|
logger.error("{}: disconnected while connecting to {}: {}", this,
|
||||||
server.serverInfo().name(), plainTextReason);
|
server.serverInfo().name(), plainTextReason);
|
||||||
handleConnectionException(server, disconnectReason, Component.text()
|
handleConnectionException(server, disconnectReason,
|
||||||
.append(messages.getDisconnectPrefix(server.serverInfo().name())
|
Component.translatable("velocity.error.cant-connect", NamedTextColor.RED,
|
||||||
.colorIfAbsent(NamedTextColor.RED))
|
Component.text(server.serverInfo().name()),
|
||||||
.append(disconnectReason)
|
disconnectReason), safe);
|
||||||
.build(), safe);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,8 +572,10 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
protocolVersion()), ((Impl) status).isSafe());
|
protocolVersion()), ((Impl) status).isSafe());
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
sendMessage(Identity.nil(), server.configuration().getMessages()
|
sendMessage(Component.translatable("velocity.error.moved-to-new-server",
|
||||||
.getMovedToNewServerPrefix().append(friendlyReason));
|
NamedTextColor.RED,
|
||||||
|
Component.text(originalEvent.server().serverInfo().name()),
|
||||||
|
friendlyReason));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// The only remaining value is successful (no need to do anything!)
|
// The only remaining value is successful (no need to do anything!)
|
||||||
|
|||||||
@@ -70,7 +70,10 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
@Override
|
@Override
|
||||||
public boolean handle(LegacyHandshakePacket packet) {
|
public boolean handle(LegacyHandshakePacket packet) {
|
||||||
connection.closeWith(LegacyDisconnectPacket
|
connection.closeWith(LegacyDisconnectPacket
|
||||||
.from(Component.text("Your client is old, please upgrade!", NamedTextColor.RED)));
|
.from(Component.text(
|
||||||
|
"Your client is extremely old. Please update to a newer version of Minecraft.",
|
||||||
|
NamedTextColor.RED)
|
||||||
|
));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +125,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
InetAddress address = ((InetSocketAddress) connection.getRemoteAddress()).getAddress();
|
InetAddress address = ((InetSocketAddress) connection.getRemoteAddress()).getAddress();
|
||||||
if (!server.getIpAttemptLimiter().attempt(address)) {
|
if (!server.getIpAttemptLimiter().attempt(address)) {
|
||||||
ic.disconnectQuietly(Component.text("You are logging in too fast, try again later."));
|
ic.disconnectQuietly(Component.translatable("velocity.error.logging-in-too-fast"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +135,8 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
// and lower, otherwise IP information will never get forwarded.
|
// and lower, otherwise IP information will never get forwarded.
|
||||||
if (server.configuration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
|
if (server.configuration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
|
||||||
&& handshake.getProtocolVersion().lt(ProtocolVersion.MINECRAFT_1_13)) {
|
&& handshake.getProtocolVersion().lt(ProtocolVersion.MINECRAFT_1_13)) {
|
||||||
ic.disconnectQuietly(Component.text("This server is only compatible with 1.13 and above."));
|
ic.disconnectQuietly(Component.translatable(
|
||||||
|
"velocity.error.modern-forwarding-needs-new-client"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.translation.GlobalTranslator;
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -152,7 +153,8 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
GameProfile.class), true);
|
GameProfile.class), true);
|
||||||
} else if (profileResponse.getStatusCode() == 204) {
|
} else if (profileResponse.getStatusCode() == 204) {
|
||||||
// Apparently an offline-mode user logged onto this online-mode proxy.
|
// Apparently an offline-mode user logged onto this online-mode proxy.
|
||||||
inbound.disconnect(server.configuration().getMessages().getOnlineModeOnly());
|
inbound.disconnect(Component.translatable("velocity.error.online-mode-only",
|
||||||
|
NamedTextColor.RED));
|
||||||
} else {
|
} else {
|
||||||
// Something else went wrong
|
// Something else went wrong
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -192,9 +194,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
Optional<Component> disconnectReason = result.denialReason();
|
Optional<Component> disconnectReason = result.denialReason();
|
||||||
if (disconnectReason.isPresent()) {
|
if (disconnectReason.isPresent()) {
|
||||||
// The component is guaranteed to be provided if the connection was denied.
|
// The component is guaranteed to be provided if the connection was denied.
|
||||||
Component disconnectReasonTranslated = GlobalTranslator.render(disconnectReason.get(),
|
inbound.disconnect(disconnectReason.get());
|
||||||
Locale.getDefault());
|
|
||||||
inbound.disconnect(disconnectReasonTranslated);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +243,8 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
mcConnection, inbound.connectedHost().orElse(null), onlineMode);
|
mcConnection, inbound.connectedHost().orElse(null), onlineMode);
|
||||||
this.connectedPlayer = player;
|
this.connectedPlayer = player;
|
||||||
if (!server.canRegisterConnection(player)) {
|
if (!server.canRegisterConnection(player)) {
|
||||||
player.disconnect0(server.configuration().getMessages().getAlreadyConnected(), true);
|
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy",
|
||||||
|
NamedTextColor.RED), true);
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,8 +305,8 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
player.disconnect0(reason.get(), true);
|
player.disconnect0(reason.get(), true);
|
||||||
} else {
|
} else {
|
||||||
if (!server.registerConnection(player)) {
|
if (!server.registerConnection(player)) {
|
||||||
player.disconnect0(server.configuration().getMessages()
|
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy"),
|
||||||
.getAlreadyConnected(), true);
|
true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,8 +334,8 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
.thenRunAsync(() -> {
|
.thenRunAsync(() -> {
|
||||||
Optional<RegisteredServer> toTry = event.initialServer();
|
Optional<RegisteredServer> toTry = event.initialServer();
|
||||||
if (!toTry.isPresent()) {
|
if (!toTry.isPresent()) {
|
||||||
player.disconnect0(server.configuration().getMessages()
|
player.disconnect0(Component.translatable("velocity.error.no-available-servers",
|
||||||
.getNoAvailableServers(), true);
|
NamedTextColor.RED), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.createConnectionRequest(toTry.get()).fireAndForget();
|
player.createConnectionRequest(toTry.get()).fireAndForget();
|
||||||
|
|||||||
@@ -19,16 +19,17 @@ package com.velocitypowered.proxy.connection.util;
|
|||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.TextComponent;
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.TranslatableComponent;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
public class ConnectionMessages {
|
public class ConnectionMessages {
|
||||||
|
|
||||||
public static final TextComponent ALREADY_CONNECTED = Component
|
public static final TranslatableComponent ALREADY_CONNECTED = Component
|
||||||
.text("You are already connected to this server!", NamedTextColor.RED);
|
.translatable("velocity.error.already-connected", NamedTextColor.RED);
|
||||||
public static final TextComponent IN_PROGRESS = Component
|
public static final TranslatableComponent IN_PROGRESS = Component
|
||||||
.text("You are already connecting to a server!", NamedTextColor.RED);
|
.translatable("velocity.error.already-connecting", NamedTextColor.RED);
|
||||||
public static final TextComponent INTERNAL_SERVER_CONNECTION_ERROR = Component
|
public static final TranslatableComponent INTERNAL_SERVER_CONNECTION_ERROR = Component
|
||||||
.text("An internal server connection error occurred.", NamedTextColor.RED);
|
.translatable("velocity.error.internal-server-connection-error", NamedTextColor.RED);
|
||||||
|
|
||||||
private ConnectionMessages() {
|
private ConnectionMessages() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
|
|||||||
@@ -26,9 +26,12 @@ import com.velocitypowered.api.permission.PermissionFunction;
|
|||||||
import com.velocitypowered.api.permission.Tristate;
|
import com.velocitypowered.api.permission.Tristate;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
import net.minecrell.terminalconsole.SimpleTerminalConsole;
|
import net.minecrell.terminalconsole.SimpleTerminalConsole;
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@@ -52,8 +55,8 @@ public final class VelocityConsole extends SimpleTerminalConsole implements Cons
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(@NonNull Identity identity, @NonNull Component message) {
|
public void sendMessage(@NonNull Identity identity, @NonNull Component message) {
|
||||||
logger.info(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()
|
Component translated = GlobalTranslator.render(message, Locale.getDefault());
|
||||||
.serialize(message));
|
logger.info(LegacyComponentSerializer.legacySection().serialize(translated));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -114,7 +117,8 @@ public final class VelocityConsole extends SimpleTerminalConsole implements Cons
|
|||||||
protected void runCommand(String command) {
|
protected void runCommand(String command) {
|
||||||
try {
|
try {
|
||||||
if (!this.server.commandManager().execute(this, command).join()) {
|
if (!this.server.commandManager().execute(this, command).join()) {
|
||||||
sendMessage(Component.text("Command not found.", NamedTextColor.RED));
|
sendMessage(Component.translatable("velocity.command.command-does-not-exist",
|
||||||
|
NamedTextColor.RED));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("An error occurred while running this command.", e);
|
logger.error("An error occurred while running this command.", e);
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 Velocity Contributors
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
velocity.error.already-connected=You are already connected to this server!
|
||||||
|
velocity.error.already-connected-proxy=You are already connected to this proxy!
|
||||||
|
velocity.error.already-connecting=You are already trying to connect to a server!
|
||||||
|
velocity.error.cant-connect=Unable to connect to {0}: {1}
|
||||||
|
velocity.error.connecting-server-error=Unable to connect you to {0}. Please try again later.
|
||||||
|
velocity.error.connected-server-error=Your connection to {0} encountered a problem.
|
||||||
|
velocity.error.internal-server-connection-error=An internal server connection error occurred.
|
||||||
|
velocity.error.logging-in-too-fast=You are logging in too fast, try again later.
|
||||||
|
velocity.error.online-mode-only=You are not logged into your Minecraft account. If you are logged into your Minecraft account, try restarting your Minecraft client.
|
||||||
|
velocity.error.player-connection-error=An internal error occurred in your connection.
|
||||||
|
velocity.error.modern-forwarding-needs-new-client=This server is only compatible with Minecraft 1.13 and above.
|
||||||
|
velocity.error.modern-forwarding-failed=Your server did not send a forwarding request to the proxy. Make sure the server is configured for Velocity forwarding.
|
||||||
|
velocity.error.moved-to-new-server=YOu were kicked from {0}: {1}
|
||||||
|
velocity.error.no-available-servers=There are no available servers to connect you to. Try again later or contact an admin.
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
velocity.command.generic-error=An error occurred while running this command.
|
||||||
|
velocity.command.command-does-not-exist=This command does not exist.
|
||||||
|
|
||||||
|
velocity.command.players-only=Only players can run this command.
|
||||||
|
velocity.command.server-does-not-exist=The specified server {0} does not exist.
|
||||||
|
|
||||||
|
velocity.command.server-current-server=You are currently connected to {0}.
|
||||||
|
velocity.command.server-too-many=There are too many servers set up. Use tab completion to get individual server counts.
|
||||||
|
velocity.command.server-available=Available servers:
|
||||||
|
velocity.command.server-tooltip-player-online={0} player online
|
||||||
|
velocity.command.server-tooltip-players-online={0} players online
|
||||||
|
velocity.command.server-tooltip-current-server=Currently connected to this server
|
||||||
|
velocity.command.server-tooltip-offer-connect-server=Click to connect to this server
|
||||||
|
|
||||||
|
velocity.command.glist-player-singular=player
|
||||||
|
velocity.command.glist-player-plural=players
|
||||||
|
velocity.command.glist-total-suffix= are currently connected to the proxy.
|
||||||
|
velocity.command.glist-view-all=To view all players on servers, use /glist all.
|
||||||
|
|
||||||
|
velocity.command.reload-success=Velocity configuration successfully reloaded.
|
||||||
|
velocity.command.reload-failure=Unable to reload your Velocity configuration. Check the console for more details.
|
||||||
|
|
||||||
|
velocity.command.version-copyright=Copyright 2018-2021 {0}. {1} is licensed under the terms of the GNU General Public License v3.
|
||||||
|
|
||||||
|
velocity.command.no-plugins=There are no plugins currently installed.
|
||||||
|
velocity.command.plugins-list=Plugins: {0}
|
||||||
|
velocity.command.plugin-tooltip-website=Website: {0}
|
||||||
|
velocity.command.plugin-tooltip-author=Author: {0}
|
||||||
|
velocity.command.plugin-tooltip-authors=Authors: {0}
|
||||||
@@ -141,20 +141,4 @@ port = 25577
|
|||||||
map = "Velocity"
|
map = "Velocity"
|
||||||
|
|
||||||
# Whether plugins should be shown in query response by default or not
|
# Whether plugins should be shown in query response by default or not
|
||||||
show-plugins = false
|
show-plugins = false
|
||||||
|
|
||||||
# Legacy color codes and JSON are accepted in all messages.
|
|
||||||
[messages]
|
|
||||||
# Prefix when the player gets kicked from a server.
|
|
||||||
# First argument '%s': the server name
|
|
||||||
kick-prefix = "&cKicked from %s: "
|
|
||||||
|
|
||||||
# Prefix when the player is disconnected from a server.
|
|
||||||
# First argument '%s': the server name
|
|
||||||
disconnect-prefix = "&cCan't connect to %s: "
|
|
||||||
|
|
||||||
online-mode-only = "&cThis server only accepts connections from online-mode clients.\n\n&7Did you change your username? Sign out of Minecraft, sign back in, and try again."
|
|
||||||
no-available-servers = "&cThere are no available servers."
|
|
||||||
already-connected = "&cYou are already connected to this proxy!"
|
|
||||||
moved-to-new-server-prefix = "&cThe server you were on kicked you: "
|
|
||||||
generic-connection-error = "&cAn internal error occurred in your connection."
|
|
||||||
Reference in New Issue
Block a user