mirror of
https://github.com/PaperMC/Velocity.git
synced 2026-02-17 06:27:42 +01:00
Update minimum Java version to 21 (#1649)
This commit is contained in:
@@ -59,7 +59,7 @@ tasks {
|
||||
|
||||
val o = options as StandardJavadocDocletOptions
|
||||
o.encoding = "UTF-8"
|
||||
o.source = "17"
|
||||
o.source = "21"
|
||||
|
||||
o.use()
|
||||
o.links(
|
||||
|
||||
@@ -12,7 +12,7 @@ subprojects {
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ plugins {
|
||||
|
||||
application {
|
||||
mainClass.set("com.velocitypowered.proxy.Velocity")
|
||||
applicationDefaultJvmArgs += listOf("-Dvelocity.packet-decode-logging=true");
|
||||
applicationDefaultJvmArgs += listOf("-Dvelocity.packet-decode-logging=true")
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -135,7 +135,6 @@ fill {
|
||||
dependencies {
|
||||
implementation(project(":velocity-api"))
|
||||
implementation(project(":velocity-native"))
|
||||
implementation(project(":velocity-proxy-log4j2-plugin"))
|
||||
|
||||
implementation(libs.bundles.log4j)
|
||||
implementation(libs.kyori.ansi)
|
||||
@@ -172,4 +171,5 @@ dependencies {
|
||||
testImplementation(libs.mockito)
|
||||
|
||||
annotationProcessor(libs.auto.service)
|
||||
annotationProcessor(libs.log4j.core)
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
dependencies {
|
||||
implementation(libs.bundles.log4j)
|
||||
annotationProcessor(libs.log4j.core)
|
||||
}
|
||||
@@ -344,7 +344,7 @@ final class SuggestionsProvider<S> {
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
return potentials.get(0);
|
||||
return potentials.getFirst();
|
||||
}
|
||||
return new ParseResults<>(contextSoFar, originalReader, Collections.emptyMap());
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ public class VelocityCommandManager implements CommandManager {
|
||||
command + " implements multiple registrable Command subinterfaces: "
|
||||
+ implementedInterfaces);
|
||||
} else {
|
||||
this.internalRegister(commandRegistrars.get(0), command, meta);
|
||||
this.internalRegister(commandRegistrars.getFirst(), command, meta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,33 +70,34 @@ public final class VelocityCommands {
|
||||
maybeCommand = VelocityBrigadierCommandWrapper.wrap(delegate.getCommand(), registrant);
|
||||
}
|
||||
|
||||
if (delegate instanceof LiteralCommandNode<CommandSource> lcn) {
|
||||
var literalBuilder = shallowCopyAsBuilder(lcn, delegate.getName(), true);
|
||||
literalBuilder.executes(maybeCommand);
|
||||
// we also need to wrap any children
|
||||
for (final CommandNode<CommandSource> child : delegate.getChildren()) {
|
||||
literalBuilder.then(wrap(child, registrant));
|
||||
return switch (delegate) {
|
||||
case LiteralCommandNode<CommandSource> lcn -> {
|
||||
var literalBuilder = shallowCopyAsBuilder(lcn, delegate.getName(), true);
|
||||
literalBuilder.executes(maybeCommand);
|
||||
// we also need to wrap any children
|
||||
for (final CommandNode<CommandSource> child : delegate.getChildren()) {
|
||||
literalBuilder.then(wrap(child, registrant));
|
||||
}
|
||||
if (delegate.getRedirect() != null) {
|
||||
literalBuilder.redirect(wrap(delegate.getRedirect(), registrant));
|
||||
}
|
||||
yield literalBuilder.build();
|
||||
}
|
||||
if (delegate.getRedirect() != null) {
|
||||
literalBuilder.redirect(wrap(delegate.getRedirect(), registrant));
|
||||
case VelocityArgumentCommandNode<CommandSource, ?> vacn -> vacn.withCommand(maybeCommand)
|
||||
.withRedirect(delegate.getRedirect() != null ? wrap(delegate.getRedirect(), registrant) : null);
|
||||
case ArgumentCommandNode<CommandSource, ?> node -> {
|
||||
var argBuilder = node.createBuilder().executes(maybeCommand);
|
||||
// we also need to wrap any children
|
||||
for (final CommandNode<CommandSource> child : delegate.getChildren()) {
|
||||
argBuilder.then(wrap(child, registrant));
|
||||
}
|
||||
if (delegate.getRedirect() != null) {
|
||||
argBuilder.redirect(wrap(delegate.getRedirect(), registrant));
|
||||
}
|
||||
yield argBuilder.build();
|
||||
}
|
||||
return literalBuilder.build();
|
||||
} else if (delegate instanceof VelocityArgumentCommandNode<CommandSource, ?> vacn) {
|
||||
return vacn.withCommand(maybeCommand)
|
||||
.withRedirect(delegate.getRedirect() != null ? wrap(delegate.getRedirect(), registrant) : null);
|
||||
} else if (delegate instanceof ArgumentCommandNode) {
|
||||
var argBuilder = delegate.createBuilder().executes(maybeCommand);
|
||||
// we also need to wrap any children
|
||||
for (final CommandNode<CommandSource> child : delegate.getChildren()) {
|
||||
argBuilder.then(wrap(child, registrant));
|
||||
}
|
||||
if (delegate.getRedirect() != null) {
|
||||
argBuilder.redirect(wrap(delegate.getRedirect(), registrant));
|
||||
}
|
||||
return argBuilder.build();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported node type: " + delegate.getClass());
|
||||
}
|
||||
default -> throw new IllegalArgumentException("Unsupported node type: " + delegate.getClass());
|
||||
};
|
||||
}
|
||||
|
||||
// Normalization
|
||||
@@ -133,7 +134,7 @@ public final class VelocityCommands {
|
||||
if (nodes.isEmpty()) {
|
||||
throw new IllegalArgumentException("Cannot read alias from empty node list");
|
||||
}
|
||||
return nodes.get(0).getNode().getName();
|
||||
return nodes.getFirst().getNode().getName();
|
||||
}
|
||||
|
||||
public static final String ARGS_NODE_NAME = "arguments";
|
||||
|
||||
@@ -118,14 +118,12 @@ public class VelocityArgumentCommandNode<S, T> extends ArgumentCommandNode<S, St
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof VelocityArgumentCommandNode)) {
|
||||
if (!(o instanceof VelocityArgumentCommandNode that)) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
if (!super.equals(that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final VelocityArgumentCommandNode<?, ?> that = (VelocityArgumentCommandNode<?, ?>) o;
|
||||
return this.type.equals(that.type);
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ public final class VelocityCommand {
|
||||
hoverText.append(Component.newline());
|
||||
if (description.getAuthors().size() == 1) {
|
||||
hoverText.append(Component.translatable("velocity.command.plugin-tooltip-author",
|
||||
Component.text(description.getAuthors().get(0))));
|
||||
Component.text(description.getAuthors().getFirst())));
|
||||
} else {
|
||||
hoverText.append(
|
||||
Component.translatable("velocity.command.plugin-tooltip-author",
|
||||
|
||||
@@ -156,19 +156,16 @@ public class VelocityConfiguration implements ProxyConfig {
|
||||
}
|
||||
|
||||
switch (playerInfoForwardingMode) {
|
||||
case NONE:
|
||||
logger.warn("Player info forwarding is disabled! All players will appear to be connecting "
|
||||
case NONE -> logger.warn("Player info forwarding is disabled! All players will appear to be connecting "
|
||||
+ "from the proxy and will have offline-mode UUIDs.");
|
||||
break;
|
||||
case MODERN:
|
||||
case BUNGEEGUARD:
|
||||
case MODERN, BUNGEEGUARD -> {
|
||||
if (forwardingSecret == null || forwardingSecret.length == 0) {
|
||||
logger.error("You don't have a forwarding secret set. This is required for security.");
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
|
||||
if (servers.getServers().isEmpty()) {
|
||||
|
||||
@@ -153,13 +153,13 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
||||
|
||||
if (msg instanceof MinecraftPacket pkt) {
|
||||
if (!pkt.handle(activeSessionHandler)) {
|
||||
activeSessionHandler.handleGeneric((MinecraftPacket) msg);
|
||||
activeSessionHandler.handleGeneric(pkt);
|
||||
}
|
||||
} else if (msg instanceof HAProxyMessage proxyMessage) {
|
||||
this.remoteAddress = new InetSocketAddress(proxyMessage.sourceAddress(),
|
||||
proxyMessage.sourcePort());
|
||||
} else if (msg instanceof ByteBuf) {
|
||||
activeSessionHandler.handleUnknown((ByteBuf) msg);
|
||||
} else if (msg instanceof ByteBuf buf) {
|
||||
activeSessionHandler.handleUnknown(buf);
|
||||
}
|
||||
} finally {
|
||||
ReferenceCountUtil.release(msg);
|
||||
|
||||
@@ -452,8 +452,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
@Override
|
||||
public void handleGeneric(MinecraftPacket packet) {
|
||||
if (packet instanceof PluginMessagePacket) {
|
||||
((PluginMessagePacket) packet).retain();
|
||||
if (packet instanceof PluginMessagePacket pluginMessage) {
|
||||
pluginMessage.retain();
|
||||
}
|
||||
playerConnection.delayedWrite(packet);
|
||||
if (++packetsFlushed >= MAXIMUM_PACKETS_TO_FLUSH) {
|
||||
|
||||
@@ -344,66 +344,30 @@ public class BungeeCordMessageResponder {
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteBufDataInput in = new ByteBufDataInput(message.content());
|
||||
String subChannel = in.readUTF();
|
||||
final ByteBufDataInput in = new ByteBufDataInput(message.content());
|
||||
final String subChannel = in.readUTF();
|
||||
switch (subChannel) {
|
||||
case "GetPlayerServer":
|
||||
this.processGetPlayerServer(in);
|
||||
break;
|
||||
case "ForwardToPlayer":
|
||||
this.processForwardToPlayer(in);
|
||||
break;
|
||||
case "Forward":
|
||||
this.processForwardToServer(in);
|
||||
break;
|
||||
case "Connect":
|
||||
this.processConnect(in);
|
||||
break;
|
||||
case "ConnectOther":
|
||||
this.processConnectOther(in);
|
||||
break;
|
||||
case "IP":
|
||||
this.processIp(in);
|
||||
break;
|
||||
case "PlayerCount":
|
||||
this.processPlayerCount(in);
|
||||
break;
|
||||
case "PlayerList":
|
||||
this.processPlayerList(in);
|
||||
break;
|
||||
case "GetServers":
|
||||
this.processGetServers();
|
||||
break;
|
||||
case "Message":
|
||||
this.processMessage(in);
|
||||
break;
|
||||
case "MessageRaw":
|
||||
this.processMessageRaw(in);
|
||||
break;
|
||||
case "GetServer":
|
||||
this.processGetServer();
|
||||
break;
|
||||
case "UUID":
|
||||
this.processUuid();
|
||||
break;
|
||||
case "UUIDOther":
|
||||
this.processUuidOther(in);
|
||||
break;
|
||||
case "IPOther":
|
||||
this.processIpOther(in);
|
||||
break;
|
||||
case "ServerIP":
|
||||
this.processServerIp(in);
|
||||
break;
|
||||
case "KickPlayer":
|
||||
this.processKick(in);
|
||||
break;
|
||||
case "KickPlayerRaw":
|
||||
this.processKickRaw(in);
|
||||
break;
|
||||
default:
|
||||
// Do nothing, unknown command
|
||||
break;
|
||||
case "GetPlayerServer" -> this.processGetPlayerServer(in);
|
||||
case "ForwardToPlayer" -> this.processForwardToPlayer(in);
|
||||
case "Forward" -> this.processForwardToServer(in);
|
||||
case "Connect" -> this.processConnect(in);
|
||||
case "ConnectOther" -> this.processConnectOther(in);
|
||||
case "IP" -> this.processIp(in);
|
||||
case "PlayerCount" -> this.processPlayerCount(in);
|
||||
case "PlayerList" -> this.processPlayerList(in);
|
||||
case "GetServers" -> this.processGetServers();
|
||||
case "Message" -> this.processMessage(in);
|
||||
case "MessageRaw" -> this.processMessageRaw(in);
|
||||
case "GetServer" -> this.processGetServer();
|
||||
case "UUID" -> this.processUuid();
|
||||
case "UUIDOther" -> this.processUuidOther(in);
|
||||
case "IPOther" -> this.processIpOther(in);
|
||||
case "ServerIP" -> this.processServerIp(in);
|
||||
case "KickPlayer" -> this.processKick(in);
|
||||
case "KickPlayerRaw" -> this.processKickRaw(in);
|
||||
default -> {
|
||||
// Do nothing, unknown command
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -122,9 +122,8 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
|
||||
// Change the client to use the ClientPlaySessionHandler if required.
|
||||
ClientPlaySessionHandler playHandler;
|
||||
if (player.getConnection()
|
||||
.getActiveSessionHandler() instanceof ClientPlaySessionHandler) {
|
||||
playHandler =
|
||||
(ClientPlaySessionHandler) player.getConnection().getActiveSessionHandler();
|
||||
.getActiveSessionHandler() instanceof ClientPlaySessionHandler sessionHandler) {
|
||||
playHandler = sessionHandler;
|
||||
} else {
|
||||
playHandler = new ClientPlaySessionHandler(server, player);
|
||||
player.getConnection().setActiveSessionHandler(StateRegistry.PLAY, playHandler);
|
||||
|
||||
@@ -180,9 +180,8 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
handshake.setServerAddress(createBungeeGuardForwardingAddress(secret));
|
||||
} else if (proxyPlayer.getConnection().getType() == ConnectionTypes.LEGACY_FORGE) {
|
||||
handshake.setServerAddress(playerVhost + HANDSHAKE_HOSTNAME_TOKEN);
|
||||
} else if (proxyPlayer.getConnection().getType() instanceof ModernForgeConnectionType) {
|
||||
handshake.setServerAddress(playerVhost + ((ModernForgeConnectionType) proxyPlayer
|
||||
.getConnection().getType()).getModernToken());
|
||||
} else if (proxyPlayer.getConnection().getType() instanceof ModernForgeConnectionType forgeConnection) {
|
||||
handshake.setServerAddress(playerVhost + forgeConnection.getModernToken());
|
||||
} else {
|
||||
handshake.setServerAddress(playerVhost);
|
||||
}
|
||||
|
||||
@@ -811,61 +811,56 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getResult() instanceof final DisconnectPlayer res) {
|
||||
disconnect(res.getReasonComponent());
|
||||
} else if (event.getResult() instanceof final RedirectPlayer res) {
|
||||
createConnectionRequest(res.getServer(), previousConnection).connect()
|
||||
.whenCompleteAsync((status, throwable) -> {
|
||||
if (throwable != null) {
|
||||
handleConnectionException(res.getServer(), throwable, true);
|
||||
return;
|
||||
}
|
||||
switch (event.getResult()) {
|
||||
case DisconnectPlayer res -> disconnect(res.getReasonComponent());
|
||||
case RedirectPlayer res -> createConnectionRequest(res.getServer(), previousConnection).connect()
|
||||
.whenCompleteAsync((status, throwable) -> {
|
||||
if (throwable != null) {
|
||||
handleConnectionException(res.getServer(), throwable, true);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status.getStatus()) {
|
||||
// Impossible/nonsensical cases
|
||||
case ALREADY_CONNECTED:
|
||||
logger.error("{}: already connected to {}", this,
|
||||
status.getAttemptedConnection().getServerInfo().getName());
|
||||
break;
|
||||
case CONNECTION_IN_PROGRESS:
|
||||
// Fatal case
|
||||
case CONNECTION_CANCELLED:
|
||||
Component fallbackMsg = res.getMessageComponent();
|
||||
if (fallbackMsg == null) {
|
||||
fallbackMsg = friendlyReason;
|
||||
switch (status.getStatus()) {
|
||||
// Impossible/nonsensical cases
|
||||
case ALREADY_CONNECTED -> logger.error("{}: already connected to {}", this,
|
||||
status.getAttemptedConnection().getServerInfo().getName());
|
||||
case CONNECTION_IN_PROGRESS, CONNECTION_CANCELLED -> {
|
||||
Component fallbackMsg = res.getMessageComponent();
|
||||
if (fallbackMsg == null) {
|
||||
fallbackMsg = friendlyReason;
|
||||
}
|
||||
disconnect(status.getReasonComponent().orElse(fallbackMsg));
|
||||
}
|
||||
case SERVER_DISCONNECTED -> {
|
||||
Component reason = status.getReasonComponent()
|
||||
.orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR);
|
||||
handleConnectionException(res.getServer(),
|
||||
DisconnectPacket.create(reason, getProtocolVersion(), connection.getState()),
|
||||
((Impl) status).isSafe());
|
||||
}
|
||||
case SUCCESS -> {
|
||||
Component requestedMessage = res.getMessageComponent();
|
||||
if (requestedMessage == null) {
|
||||
requestedMessage = friendlyReason;
|
||||
}
|
||||
if (requestedMessage != Component.empty()) {
|
||||
sendMessage(requestedMessage);
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
// The only remaining value is successful (no need to do anything!)
|
||||
}
|
||||
}
|
||||
disconnect(status.getReasonComponent().orElse(fallbackMsg));
|
||||
break;
|
||||
case SERVER_DISCONNECTED:
|
||||
Component reason = status.getReasonComponent()
|
||||
.orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR);
|
||||
handleConnectionException(res.getServer(),
|
||||
DisconnectPacket.create(reason, getProtocolVersion(), connection.getState()),
|
||||
((Impl) status).isSafe());
|
||||
break;
|
||||
case SUCCESS:
|
||||
Component requestedMessage = res.getMessageComponent();
|
||||
if (requestedMessage == null) {
|
||||
requestedMessage = friendlyReason;
|
||||
}
|
||||
if (requestedMessage != Component.empty()) {
|
||||
sendMessage(requestedMessage);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// The only remaining value is successful (no need to do anything!)
|
||||
break;
|
||||
}
|
||||
}, connection.eventLoop());
|
||||
} else if (event.getResult() instanceof final Notify res) {
|
||||
if (event.kickedDuringServerConnect() && previousConnection != null) {
|
||||
sendMessage(res.getMessageComponent());
|
||||
} else {
|
||||
disconnect(res.getMessageComponent());
|
||||
}, connection.eventLoop());
|
||||
case Notify res -> {
|
||||
if (event.kickedDuringServerConnect() && previousConnection != null) {
|
||||
sendMessage(res.getMessageComponent());
|
||||
} else {
|
||||
disconnect(res.getMessageComponent());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In case someone gets creative, assume we want to disconnect the player.
|
||||
disconnect(friendlyReason);
|
||||
default -> disconnect(friendlyReason);
|
||||
}
|
||||
}, connection.eventLoop());
|
||||
}
|
||||
|
||||
@@ -214,6 +214,7 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
|
||||
server.getVersion().getName() + "/" + server.getVersion().getVersion())
|
||||
.uri(URI.create(url))
|
||||
.build();
|
||||
//noinspection resource
|
||||
final HttpClient httpClient = server.createHttpClient();
|
||||
httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())
|
||||
.whenCompleteAsync((response, throwable) -> {
|
||||
@@ -268,14 +269,12 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
|
||||
}
|
||||
}, mcConnection.eventLoop())
|
||||
.thenRun(() -> {
|
||||
if (httpClient instanceof final AutoCloseable closeable) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (Exception e) {
|
||||
// In Java 21, the HttpClient does not throw any Exception
|
||||
// when trying to clean its resources, so this should not happen
|
||||
logger.error("An unknown error occurred while trying to close an HttpClient", e);
|
||||
}
|
||||
try {
|
||||
httpClient.close();
|
||||
} catch (Exception e) {
|
||||
// In Java 21, the HttpClient does not throw any Exception
|
||||
// when trying to clean its resources, so this should not happen
|
||||
logger.error("An unknown error occurred while trying to close an HttpClient", e);
|
||||
}
|
||||
});
|
||||
} catch (GeneralSecurityException e) {
|
||||
|
||||
@@ -94,7 +94,7 @@ public final class ModernResourcePackHandler extends ResourcePackHandler {
|
||||
this.outstandingResourcePacks.get(info.getId());
|
||||
outstandingResourcePacks.add(info);
|
||||
if (outstandingResourcePacks.size() == 1) {
|
||||
tickResourcePackQueue(outstandingResourcePacks.get(0).getId());
|
||||
tickResourcePackQueue(outstandingResourcePacks.getFirst().getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class ModernResourcePackHandler extends ResourcePackHandler {
|
||||
final List<ResourcePackInfo> outstandingResourcePacks =
|
||||
this.outstandingResourcePacks.get(uuid);
|
||||
if (!outstandingResourcePacks.isEmpty()) {
|
||||
sendResourcePackRequestPacket(outstandingResourcePacks.get(0));
|
||||
sendResourcePackRequestPacket(outstandingResourcePacks.getFirst());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ public final class ModernResourcePackHandler extends ResourcePackHandler {
|
||||
this.outstandingResourcePacks.get(uuid);
|
||||
final boolean peek = bundle.status().isIntermediate();
|
||||
final ResourcePackInfo queued = outstandingResourcePacks.isEmpty() ? null :
|
||||
peek ? outstandingResourcePacks.get(0) : outstandingResourcePacks.remove(0);
|
||||
peek ? outstandingResourcePacks.getFirst() : outstandingResourcePacks.removeFirst();
|
||||
|
||||
server.getEventManager()
|
||||
.fire(new PlayerResourcePackStatusEvent(this.player, uuid, bundle.status(), queued))
|
||||
|
||||
@@ -100,65 +100,60 @@ public class ServerListPingHandler {
|
||||
|
||||
CompletableFuture<List<ServerPing>> pingResponses = CompletableFutures.successfulAsList(pings,
|
||||
(ex) -> fallback);
|
||||
switch (mode) {
|
||||
case ALL:
|
||||
return pingResponses.thenApply(responses -> {
|
||||
// Find the first non-fallback
|
||||
for (ServerPing response : responses) {
|
||||
if (response == fallback) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (response.getDescriptionComponent() == null) {
|
||||
return response.asBuilder()
|
||||
.description(Component.empty())
|
||||
.build();
|
||||
}
|
||||
|
||||
return response;
|
||||
return switch (mode) {
|
||||
case ALL -> pingResponses.thenApply(responses -> {
|
||||
// Find the first non-fallback
|
||||
for (ServerPing response : responses) {
|
||||
if (response == fallback) {
|
||||
continue;
|
||||
}
|
||||
return fallback;
|
||||
});
|
||||
case MODS:
|
||||
return pingResponses.thenApply(responses -> {
|
||||
// Find the first non-fallback that contains a mod list
|
||||
for (ServerPing response : responses) {
|
||||
if (response == fallback) {
|
||||
continue;
|
||||
}
|
||||
Optional<ModInfo> modInfo = response.getModinfo();
|
||||
if (modInfo.isPresent()) {
|
||||
return fallback.asBuilder().mods(modInfo.get()).build();
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
});
|
||||
case DESCRIPTION:
|
||||
return pingResponses.thenApply(responses -> {
|
||||
// Find the first non-fallback. If it includes a modlist, add it too.
|
||||
for (ServerPing response : responses) {
|
||||
if (response == fallback) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (response.getDescriptionComponent() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return new ServerPing(
|
||||
fallback.getVersion(),
|
||||
fallback.getPlayers().orElse(null),
|
||||
response.getDescriptionComponent(),
|
||||
fallback.getFavicon().orElse(null),
|
||||
response.getModinfo().orElse(null)
|
||||
);
|
||||
if (response.getDescriptionComponent() == null) {
|
||||
return response.asBuilder()
|
||||
.description(Component.empty())
|
||||
.build();
|
||||
}
|
||||
return fallback;
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
return fallback;
|
||||
});
|
||||
case MODS -> pingResponses.thenApply(responses -> {
|
||||
// Find the first non-fallback that contains a mod list
|
||||
for (ServerPing response : responses) {
|
||||
if (response == fallback) {
|
||||
continue;
|
||||
}
|
||||
Optional<ModInfo> modInfo = response.getModinfo();
|
||||
if (modInfo.isPresent()) {
|
||||
return fallback.asBuilder().mods(modInfo.get()).build();
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
});
|
||||
case DESCRIPTION -> pingResponses.thenApply(responses -> {
|
||||
// Find the first non-fallback. If it includes a modlist, add it too.
|
||||
for (ServerPing response : responses) {
|
||||
if (response == fallback) {
|
||||
continue;
|
||||
}
|
||||
if (response.getDescriptionComponent() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return new ServerPing(
|
||||
fallback.getVersion(),
|
||||
fallback.getPlayers().orElse(null),
|
||||
response.getDescriptionComponent(),
|
||||
fallback.getFavicon().orElse(null),
|
||||
response.getModinfo().orElse(null)
|
||||
);
|
||||
}
|
||||
return fallback;
|
||||
});
|
||||
// Not possible, but covered for completeness.
|
||||
default:
|
||||
return CompletableFuture.completedFuture(fallback);
|
||||
}
|
||||
default -> CompletableFuture.completedFuture(fallback);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,6 +33,7 @@ import net.kyori.adventure.permission.PermissionChecker;
|
||||
import net.kyori.adventure.platform.facet.FacetPointers;
|
||||
import net.kyori.adventure.platform.facet.FacetPointers.Type;
|
||||
import net.kyori.adventure.pointer.Pointers;
|
||||
import net.kyori.adventure.pointer.PointersSupplier;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
@@ -59,11 +60,11 @@ public final class VelocityConsole extends SimpleTerminalConsole implements Cons
|
||||
|
||||
private final VelocityServer server;
|
||||
private PermissionFunction permissionFunction = ALWAYS_TRUE;
|
||||
private final @NotNull Pointers pointers = ConsoleCommandSource.super.pointers().toBuilder()
|
||||
.withDynamic(PermissionChecker.POINTER, this::getPermissionChecker)
|
||||
.withDynamic(Identity.LOCALE, () -> ClosestLocaleMatcher.INSTANCE
|
||||
private static final @NotNull PointersSupplier<VelocityConsole> POINTERS = PointersSupplier.<VelocityConsole>builder()
|
||||
.resolving(PermissionChecker.POINTER, VelocityConsole::getPermissionChecker)
|
||||
.resolving(Identity.LOCALE, (console) -> ClosestLocaleMatcher.INSTANCE
|
||||
.lookupClosest(Locale.getDefault()))
|
||||
.withStatic(FacetPointers.TYPE, Type.CONSOLE)
|
||||
.resolving(FacetPointers.TYPE, (console) -> Type.CONSOLE)
|
||||
.build();
|
||||
|
||||
public VelocityConsole(VelocityServer server) {
|
||||
@@ -153,6 +154,6 @@ public final class VelocityConsole extends SimpleTerminalConsole implements Cons
|
||||
|
||||
@Override
|
||||
public @NotNull Pointers pointers() {
|
||||
return pointers;
|
||||
return POINTERS.view(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public final class SeparatePoolInetNameResolver extends InetNameResolver {
|
||||
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
|
||||
List<InetAddress> addresses = cache.getIfPresent(inetHost);
|
||||
if (addresses != null) {
|
||||
promise.trySuccess(addresses.get(0));
|
||||
promise.trySuccess(addresses.getFirst());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public class JavaPluginLoader implements PluginLoader {
|
||||
|
||||
@Override
|
||||
public PluginDescription createPluginFromCandidate(PluginDescription candidate) throws Exception {
|
||||
if (!(candidate instanceof JavaVelocityPluginDescriptionCandidate)) {
|
||||
if (!(candidate instanceof JavaVelocityPluginDescriptionCandidate candidateInst)) {
|
||||
throw new IllegalArgumentException("Description provided isn't of the Java plugin loader");
|
||||
}
|
||||
|
||||
@@ -93,8 +93,6 @@ public class JavaPluginLoader implements PluginLoader {
|
||||
PluginClassLoader loader = new PluginClassLoader(new URL[]{pluginJarUrl});
|
||||
loader.addToClassloaders();
|
||||
|
||||
JavaVelocityPluginDescriptionCandidate candidateInst =
|
||||
(JavaVelocityPluginDescriptionCandidate) candidate;
|
||||
Class<?> mainClass = loader.loadClass(candidateInst.getMainClass());
|
||||
return createDescription(candidateInst, mainClass);
|
||||
}
|
||||
@@ -102,11 +100,10 @@ public class JavaPluginLoader implements PluginLoader {
|
||||
@Override
|
||||
public Module createModule(PluginContainer container) {
|
||||
PluginDescription description = container.getDescription();
|
||||
if (!(description instanceof JavaVelocityPluginDescription)) {
|
||||
if (!(description instanceof JavaVelocityPluginDescription javaDescription)) {
|
||||
throw new IllegalArgumentException("Description provided isn't of the Java plugin loader");
|
||||
}
|
||||
|
||||
JavaVelocityPluginDescription javaDescription = (JavaVelocityPluginDescription) description;
|
||||
Optional<Path> source = javaDescription.getSource();
|
||||
|
||||
if (source.isEmpty()) {
|
||||
@@ -118,24 +115,23 @@ public class JavaPluginLoader implements PluginLoader {
|
||||
|
||||
@Override
|
||||
public void createPlugin(PluginContainer container, Module... modules) {
|
||||
if (!(container instanceof VelocityPluginContainer)) {
|
||||
if (!(container instanceof VelocityPluginContainer pluginContainer)) {
|
||||
throw new IllegalArgumentException("Container provided isn't of the Java plugin loader");
|
||||
}
|
||||
PluginDescription description = container.getDescription();
|
||||
if (!(description instanceof JavaVelocityPluginDescription)) {
|
||||
PluginDescription description = pluginContainer.getDescription();
|
||||
if (!(description instanceof JavaVelocityPluginDescription javaPluginDescription)) {
|
||||
throw new IllegalArgumentException("Description provided isn't of the Java plugin loader");
|
||||
}
|
||||
|
||||
Injector injector = Guice.createInjector(modules);
|
||||
Object instance = injector
|
||||
.getInstance(((JavaVelocityPluginDescription) description).getMainClass());
|
||||
Object instance = injector.getInstance(javaPluginDescription.getMainClass());
|
||||
|
||||
if (instance == null) {
|
||||
throw new IllegalStateException(
|
||||
"Got nothing from injector for plugin " + description.getId());
|
||||
}
|
||||
|
||||
((VelocityPluginContainer) container).setInstance(instance);
|
||||
pluginContainer.setInstance(instance);
|
||||
}
|
||||
|
||||
private Optional<SerializedPluginDescription> getSerializedPluginInfo(Path source)
|
||||
@@ -145,22 +141,23 @@ public class JavaPluginLoader implements PluginLoader {
|
||||
new BufferedInputStream(Files.newInputStream(source)))) {
|
||||
JarEntry entry;
|
||||
while ((entry = in.getNextJarEntry()) != null) {
|
||||
if (entry.getName().equals("velocity-plugin.json")) {
|
||||
try (Reader pluginInfoReader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
|
||||
return Optional.of(VelocityServer.GENERAL_GSON.fromJson(pluginInfoReader,
|
||||
SerializedPluginDescription.class));
|
||||
switch (entry.getName()) {
|
||||
case "velocity-plugin.json" -> {
|
||||
try (Reader pluginInfoReader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
|
||||
return Optional.of(VelocityServer.GENERAL_GSON.fromJson(pluginInfoReader,
|
||||
SerializedPluginDescription.class));
|
||||
}
|
||||
}
|
||||
case "paper-plugin.yml", "plugin.yml", "bungee.yml" -> foundBungeeBukkitPluginFile = true;
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.getName().equals("plugin.yml") || entry.getName().equals("bungee.yml")) {
|
||||
foundBungeeBukkitPluginFile = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundBungeeBukkitPluginFile) {
|
||||
throw new InvalidPluginException("The plugin file " + source.getFileName() + " appears to "
|
||||
+ "be a Bukkit or BungeeCord plugin. Velocity does not support Bukkit or BungeeCord "
|
||||
+ "plugins.");
|
||||
+ "be a Paper, Bukkit or BungeeCord plugin. Velocity does not support plugins from these "
|
||||
+ "platforms.");
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
@@ -119,7 +119,7 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
|
||||
int sessionId = queryMessage.readInt();
|
||||
|
||||
switch (type) {
|
||||
case QUERY_TYPE_HANDSHAKE: {
|
||||
case QUERY_TYPE_HANDSHAKE -> {
|
||||
// Generate new challenge token and put it into the sessions cache
|
||||
int challengeToken = random.nextInt();
|
||||
sessions.put(senderAddress, challengeToken);
|
||||
@@ -132,10 +132,9 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
|
||||
|
||||
DatagramPacket responsePacket = new DatagramPacket(queryResponse, msg.sender());
|
||||
ctx.writeAndFlush(responsePacket, ctx.voidPromise());
|
||||
break;
|
||||
}
|
||||
|
||||
case QUERY_TYPE_STAT: {
|
||||
case QUERY_TYPE_STAT -> {
|
||||
// Check if query was done with session previously generated using a handshake packet
|
||||
int challengeToken = queryMessage.readInt();
|
||||
Integer session = sessions.getIfPresent(senderAddress);
|
||||
@@ -190,10 +189,10 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
|
||||
"Exception while writing GS4 response for query from {}", senderAddress, ex);
|
||||
return null;
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Invalid query type - just don't respond
|
||||
default -> {
|
||||
// Invalid query type - just don't respond
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
@@ -331,12 +330,10 @@ public class AvailableCommandsPacket implements MinecraftPacket {
|
||||
.add("redirectTo", redirectTo);
|
||||
|
||||
if (args != null) {
|
||||
if (args instanceof LiteralArgumentBuilder) {
|
||||
helper.add("argsLabel",
|
||||
((LiteralArgumentBuilder<CommandSource>) args).getLiteral());
|
||||
} else if (args instanceof RequiredArgumentBuilder) {
|
||||
helper.add("argsName",
|
||||
((RequiredArgumentBuilder<CommandSource, ?>) args).getName());
|
||||
if (args instanceof LiteralArgumentBuilder literal) {
|
||||
helper.add("argsLabel", literal.getLiteral());
|
||||
} else if (args instanceof RequiredArgumentBuilder required) {
|
||||
helper.add("argsName", required.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,17 +345,11 @@ public class AvailableCommandsPacket implements MinecraftPacket {
|
||||
* A placeholder {@link SuggestionProvider} used internally to preserve the suggestion provider
|
||||
* name.
|
||||
*/
|
||||
public static class ProtocolSuggestionProvider implements SuggestionProvider<CommandSource> {
|
||||
|
||||
private final String name;
|
||||
|
||||
public ProtocolSuggestionProvider(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public record ProtocolSuggestionProvider(String name) implements SuggestionProvider<CommandSource> {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSource> context,
|
||||
SuggestionsBuilder builder) throws CommandSyntaxException {
|
||||
SuggestionsBuilder builder) {
|
||||
return builder.buildFuture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,30 +207,22 @@ public class BossBarPacket implements MinecraftPacket {
|
||||
this.uuid = ProtocolUtils.readUuid(buf);
|
||||
this.action = ProtocolUtils.readVarInt(buf);
|
||||
switch (action) {
|
||||
case ADD:
|
||||
case ADD -> {
|
||||
this.name = ComponentHolder.read(buf, version);
|
||||
this.percent = buf.readFloat();
|
||||
this.color = ProtocolUtils.readVarInt(buf);
|
||||
this.overlay = ProtocolUtils.readVarInt(buf);
|
||||
this.flags = buf.readUnsignedByte();
|
||||
break;
|
||||
case REMOVE:
|
||||
break;
|
||||
case UPDATE_PERCENT:
|
||||
this.percent = buf.readFloat();
|
||||
break;
|
||||
case UPDATE_NAME:
|
||||
this.name = ComponentHolder.read(buf, version);
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
}
|
||||
case REMOVE -> {}
|
||||
case UPDATE_PERCENT -> this.percent = buf.readFloat();
|
||||
case UPDATE_NAME -> this.name = ComponentHolder.read(buf, version);
|
||||
case UPDATE_STYLE -> {
|
||||
this.color = ProtocolUtils.readVarInt(buf);
|
||||
this.overlay = ProtocolUtils.readVarInt(buf);
|
||||
break;
|
||||
case UPDATE_PROPERTIES:
|
||||
this.flags = buf.readUnsignedByte();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
case UPDATE_PROPERTIES -> this.flags = buf.readUnsignedByte();
|
||||
default -> throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,36 +234,30 @@ public class BossBarPacket implements MinecraftPacket {
|
||||
ProtocolUtils.writeUuid(buf, uuid);
|
||||
ProtocolUtils.writeVarInt(buf, action);
|
||||
switch (action) {
|
||||
case ADD:
|
||||
if (name == null) {
|
||||
throw new IllegalStateException("No name specified!");
|
||||
}
|
||||
name.write(buf);
|
||||
buf.writeFloat(percent);
|
||||
case ADD -> {
|
||||
if (name == null) {
|
||||
throw new IllegalStateException("No name specified!");
|
||||
}
|
||||
name.write(buf);
|
||||
buf.writeFloat(percent);
|
||||
ProtocolUtils.writeVarInt(buf, color);
|
||||
ProtocolUtils.writeVarInt(buf, overlay);
|
||||
buf.writeByte(flags);
|
||||
}
|
||||
case REMOVE -> {}
|
||||
case UPDATE_PERCENT -> buf.writeFloat(percent);
|
||||
case UPDATE_NAME -> {
|
||||
if (name == null) {
|
||||
throw new IllegalStateException("No name specified!");
|
||||
}
|
||||
name.write(buf);
|
||||
}
|
||||
case UPDATE_STYLE -> {
|
||||
ProtocolUtils.writeVarInt(buf, color);
|
||||
ProtocolUtils.writeVarInt(buf, overlay);
|
||||
buf.writeByte(flags);
|
||||
break;
|
||||
case REMOVE:
|
||||
break;
|
||||
case UPDATE_PERCENT:
|
||||
buf.writeFloat(percent);
|
||||
break;
|
||||
case UPDATE_NAME:
|
||||
if (name == null) {
|
||||
throw new IllegalStateException("No name specified!");
|
||||
}
|
||||
name.write(buf);
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
ProtocolUtils.writeVarInt(buf, color);
|
||||
ProtocolUtils.writeVarInt(buf, overlay);
|
||||
break;
|
||||
case UPDATE_PROPERTIES:
|
||||
buf.writeByte(flags);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
case UPDATE_PROPERTIES -> buf.writeByte(flags);
|
||||
default -> throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,33 +69,25 @@ public class LegacyPlayerListItemPacket implements MinecraftPacket {
|
||||
Item item = new Item(ProtocolUtils.readUuid(buf));
|
||||
items.add(item);
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
case ADD_PLAYER -> {
|
||||
item.setName(ProtocolUtils.readString(buf));
|
||||
item.setProperties(ProtocolUtils.readProperties(buf));
|
||||
item.setGameMode(ProtocolUtils.readVarInt(buf));
|
||||
item.setLatency(ProtocolUtils.readVarInt(buf));
|
||||
item.setDisplayName(readOptionalComponent(buf, version));
|
||||
|
||||
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) {
|
||||
if (buf.readBoolean()) {
|
||||
item.setPlayerKey(ProtocolUtils.readPlayerKey(version, buf));
|
||||
}
|
||||
if (buf.readBoolean()) {
|
||||
item.setPlayerKey(ProtocolUtils.readPlayerKey(version, buf));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UPDATE_GAMEMODE:
|
||||
item.setGameMode(ProtocolUtils.readVarInt(buf));
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
item.setLatency(ProtocolUtils.readVarInt(buf));
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
item.setDisplayName(readOptionalComponent(buf, version));
|
||||
break;
|
||||
case REMOVE_PLAYER:
|
||||
//Do nothing, all that is needed is the uuid
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
case UPDATE_GAMEMODE -> item.setGameMode(ProtocolUtils.readVarInt(buf));
|
||||
case UPDATE_LATENCY -> item.setLatency(ProtocolUtils.readVarInt(buf));
|
||||
case UPDATE_DISPLAY_NAME -> item.setDisplayName(readOptionalComponent(buf, version));
|
||||
case REMOVE_PLAYER -> {
|
||||
//Do nothing, all that is needed is the uuid
|
||||
}
|
||||
default -> throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -126,39 +118,32 @@ public class LegacyPlayerListItemPacket implements MinecraftPacket {
|
||||
|
||||
ProtocolUtils.writeUuid(buf, uuid);
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
case ADD_PLAYER -> {
|
||||
ProtocolUtils.writeString(buf, item.getName());
|
||||
ProtocolUtils.writeProperties(buf, item.getProperties());
|
||||
ProtocolUtils.writeVarInt(buf, item.getGameMode());
|
||||
ProtocolUtils.writeVarInt(buf, item.getLatency());
|
||||
writeDisplayName(buf, item.getDisplayName(), version);
|
||||
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) {
|
||||
if (item.getPlayerKey() != null) {
|
||||
buf.writeBoolean(true);
|
||||
ProtocolUtils.writePlayerKey(buf, item.getPlayerKey());
|
||||
} else {
|
||||
buf.writeBoolean(false);
|
||||
}
|
||||
if (item.getPlayerKey() != null) {
|
||||
buf.writeBoolean(true);
|
||||
ProtocolUtils.writePlayerKey(buf, item.getPlayerKey());
|
||||
} else {
|
||||
buf.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UPDATE_GAMEMODE:
|
||||
ProtocolUtils.writeVarInt(buf, item.getGameMode());
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
ProtocolUtils.writeVarInt(buf, item.getLatency());
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
writeDisplayName(buf, item.getDisplayName(), version);
|
||||
break;
|
||||
case REMOVE_PLAYER:
|
||||
}
|
||||
case UPDATE_GAMEMODE -> ProtocolUtils.writeVarInt(buf, item.getGameMode());
|
||||
case UPDATE_LATENCY -> ProtocolUtils.writeVarInt(buf, item.getLatency());
|
||||
case UPDATE_DISPLAY_NAME -> writeDisplayName(buf, item.getDisplayName(), version);
|
||||
case REMOVE_PLAYER -> {
|
||||
// Do nothing, all that is needed is the uuid
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
default -> throw new UnsupportedOperationException("Unknown action " + action);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Item item = items.get(0);
|
||||
Item item = items.getFirst();
|
||||
Component displayNameComponent = item.getDisplayName();
|
||||
if (displayNameComponent != null) {
|
||||
String displayName = LegacyComponentSerializer.legacySection()
|
||||
@@ -269,7 +254,7 @@ public class LegacyPlayerListItemPacket implements MinecraftPacket {
|
||||
return this;
|
||||
}
|
||||
|
||||
public IdentifiedKey getPlayerKey() {
|
||||
public @Nullable IdentifiedKey getPlayerKey() {
|
||||
return playerKey;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,32 +37,21 @@ class StringArgumentPropertySerializer implements ArgumentPropertySerializer<Str
|
||||
@Override
|
||||
public StringArgumentType deserialize(ByteBuf buf, ProtocolVersion protocolVersion) {
|
||||
int type = ProtocolUtils.readVarInt(buf);
|
||||
switch (type) {
|
||||
case 0:
|
||||
return StringArgumentType.word();
|
||||
case 1:
|
||||
return StringArgumentType.string();
|
||||
case 2:
|
||||
return StringArgumentType.greedyString();
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid string argument type " + type);
|
||||
}
|
||||
return switch (type) {
|
||||
case 0 -> StringArgumentType.word();
|
||||
case 1 -> StringArgumentType.string();
|
||||
case 2 -> StringArgumentType.greedyString();
|
||||
default -> throw new IllegalArgumentException("Invalid string argument type " + type);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(StringArgumentType object, ByteBuf buf, ProtocolVersion protocolVersion) {
|
||||
switch (object.getType()) {
|
||||
case SINGLE_WORD:
|
||||
ProtocolUtils.writeVarInt(buf, 0);
|
||||
break;
|
||||
case QUOTABLE_PHRASE:
|
||||
ProtocolUtils.writeVarInt(buf, 1);
|
||||
break;
|
||||
case GREEDY_PHRASE:
|
||||
ProtocolUtils.writeVarInt(buf, 2);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid string argument type " + object.getType());
|
||||
case SINGLE_WORD -> ProtocolUtils.writeVarInt(buf, 0);
|
||||
case QUOTABLE_PHRASE -> ProtocolUtils.writeVarInt(buf, 1);
|
||||
case GREEDY_PHRASE -> ProtocolUtils.writeVarInt(buf, 2);
|
||||
default -> throw new IllegalArgumentException("Invalid string argument type " + object.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,23 +113,18 @@ public class ComponentHolder {
|
||||
public static BinaryTag serialize(JsonElement json) {
|
||||
if (json instanceof JsonPrimitive jsonPrimitive) {
|
||||
if (jsonPrimitive.isNumber()) {
|
||||
Number number = json.getAsNumber();
|
||||
final Number number = json.getAsNumber();
|
||||
|
||||
if (number instanceof Byte) {
|
||||
return ByteBinaryTag.byteBinaryTag((Byte) number);
|
||||
} else if (number instanceof Short) {
|
||||
return ShortBinaryTag.shortBinaryTag((Short) number);
|
||||
} else if (number instanceof Integer) {
|
||||
return IntBinaryTag.intBinaryTag((Integer) number);
|
||||
} else if (number instanceof Long) {
|
||||
return LongBinaryTag.longBinaryTag((Long) number);
|
||||
} else if (number instanceof Float) {
|
||||
return FloatBinaryTag.floatBinaryTag((Float) number);
|
||||
} else if (number instanceof Double) {
|
||||
return DoubleBinaryTag.doubleBinaryTag((Double) number);
|
||||
} else if (number instanceof LazilyParsedNumber) {
|
||||
return IntBinaryTag.intBinaryTag(number.intValue());
|
||||
}
|
||||
return switch (number) {
|
||||
case Byte b -> ByteBinaryTag.byteBinaryTag(b);
|
||||
case Short s -> ShortBinaryTag.shortBinaryTag(s);
|
||||
case Integer i -> IntBinaryTag.intBinaryTag(i);
|
||||
case Long l -> LongBinaryTag.longBinaryTag(l);
|
||||
case Float f -> FloatBinaryTag.floatBinaryTag(f);
|
||||
case Double d -> DoubleBinaryTag.doubleBinaryTag(d);
|
||||
case LazilyParsedNumber l -> IntBinaryTag.intBinaryTag(l.intValue());
|
||||
default -> throw new IllegalArgumentException("Unknown number type: " + number);
|
||||
};
|
||||
} else if (jsonPrimitive.isString()) {
|
||||
return StringBinaryTag.stringBinaryTag(jsonPrimitive.getAsString());
|
||||
} else if (jsonPrimitive.isBoolean()) {
|
||||
@@ -137,16 +132,16 @@ public class ComponentHolder {
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown JSON primitive: " + jsonPrimitive);
|
||||
}
|
||||
} else if (json instanceof JsonObject) {
|
||||
} else if (json instanceof JsonObject object) {
|
||||
CompoundBinaryTag.Builder compound = CompoundBinaryTag.builder();
|
||||
|
||||
for (Map.Entry<String, JsonElement> property : ((JsonObject) json).entrySet()) {
|
||||
for (Map.Entry<String, JsonElement> property : object.entrySet()) {
|
||||
compound.put(property.getKey(), serialize(property.getValue()));
|
||||
}
|
||||
|
||||
return compound.build();
|
||||
} else if (json instanceof JsonArray) {
|
||||
List<JsonElement> jsonArray = ((JsonArray) json).asList();
|
||||
} else if (json instanceof JsonArray array) {
|
||||
List<JsonElement> jsonArray = array.asList();
|
||||
|
||||
if (jsonArray.isEmpty()) {
|
||||
return ListBinaryTag.empty();
|
||||
@@ -206,20 +201,21 @@ public class ComponentHolder {
|
||||
}
|
||||
|
||||
public static JsonElement deserialize(BinaryTag tag) {
|
||||
switch (tag.type().id()) {
|
||||
case 1://BinaryTagTypes.BYTE:
|
||||
return new JsonPrimitive(((ByteBinaryTag) tag).value());
|
||||
case 2://BinaryTagTypes.SHORT:
|
||||
return new JsonPrimitive(((ShortBinaryTag) tag).value());
|
||||
case 3://BinaryTagTypes.INT:
|
||||
return new JsonPrimitive(((IntBinaryTag) tag).value());
|
||||
case 4://BinaryTagTypes.LONG:
|
||||
return new JsonPrimitive(((LongBinaryTag) tag).value());
|
||||
case 5://BinaryTagTypes.FLOAT:
|
||||
return new JsonPrimitive(((FloatBinaryTag) tag).value());
|
||||
case 6://BinaryTagTypes.DOUBLE:
|
||||
return new JsonPrimitive(((DoubleBinaryTag) tag).value());
|
||||
case 7://BinaryTagTypes.BYTE_ARRAY:
|
||||
return switch (tag.type().id()) {
|
||||
//BinaryTagTypes.BYTE
|
||||
case 1 -> new JsonPrimitive(((ByteBinaryTag) tag).value());
|
||||
//BinaryTagTypes.SHORT
|
||||
case 2 -> new JsonPrimitive(((ShortBinaryTag) tag).value());
|
||||
//BinaryTagTypes.INT:
|
||||
case 3 -> new JsonPrimitive(((IntBinaryTag) tag).value());
|
||||
//BinaryTagTypes.LONG:
|
||||
case 4 -> new JsonPrimitive(((LongBinaryTag) tag).value());
|
||||
//BinaryTagTypes.FLOAT:
|
||||
case 5 -> new JsonPrimitive(((FloatBinaryTag) tag).value());
|
||||
//BinaryTagTypes.DOUBLE:
|
||||
case 6 -> new JsonPrimitive(((DoubleBinaryTag) tag).value());
|
||||
//BinaryTagTypes.BYTE_ARRAY:
|
||||
case 7 -> {
|
||||
byte[] byteArray = ((ByteArrayBinaryTag) tag).value();
|
||||
|
||||
JsonArray jsonByteArray = new JsonArray(byteArray.length);
|
||||
@@ -227,10 +223,12 @@ public class ComponentHolder {
|
||||
jsonByteArray.add(new JsonPrimitive(b));
|
||||
}
|
||||
|
||||
return jsonByteArray;
|
||||
case 8://BinaryTagTypes.STRING:
|
||||
return new JsonPrimitive(((StringBinaryTag) tag).value());
|
||||
case 9://BinaryTagTypes.LIST:
|
||||
yield jsonByteArray;
|
||||
}
|
||||
//BinaryTagTypes.STRING:
|
||||
case 8 -> new JsonPrimitive(((StringBinaryTag) tag).value());
|
||||
//BinaryTagTypes.LIST:
|
||||
case 9 -> {
|
||||
ListBinaryTag items = (ListBinaryTag) tag;
|
||||
JsonArray jsonList = new JsonArray(items.size());
|
||||
|
||||
@@ -238,8 +236,10 @@ public class ComponentHolder {
|
||||
jsonList.add(deserialize(subTag));
|
||||
}
|
||||
|
||||
return jsonList;
|
||||
case 10://BinaryTagTypes.COMPOUND:
|
||||
yield jsonList;
|
||||
}
|
||||
//BinaryTagTypes.COMPOUND:
|
||||
case 10 -> {
|
||||
CompoundBinaryTag compound = (CompoundBinaryTag) tag;
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
|
||||
@@ -252,8 +252,10 @@ public class ComponentHolder {
|
||||
jsonObject.add(key.isEmpty() ? "text" : key, deserialize(compound.get(key)));
|
||||
});
|
||||
|
||||
return jsonObject;
|
||||
case 11://BinaryTagTypes.INT_ARRAY:
|
||||
yield jsonObject;
|
||||
}
|
||||
//BinaryTagTypes.INT_ARRAY:
|
||||
case 11 -> {
|
||||
int[] intArray = ((IntArrayBinaryTag) tag).value();
|
||||
|
||||
JsonArray jsonIntArray = new JsonArray(intArray.length);
|
||||
@@ -261,8 +263,10 @@ public class ComponentHolder {
|
||||
jsonIntArray.add(new JsonPrimitive(i));
|
||||
}
|
||||
|
||||
return jsonIntArray;
|
||||
case 12://BinaryTagTypes.LONG_ARRAY:
|
||||
yield jsonIntArray;
|
||||
}
|
||||
//BinaryTagTypes.LONG_ARRAY:
|
||||
case 12 -> {
|
||||
long[] longArray = ((LongArrayBinaryTag) tag).value();
|
||||
|
||||
JsonArray jsonLongArray = new JsonArray(longArray.length);
|
||||
@@ -270,10 +274,10 @@ public class ComponentHolder {
|
||||
jsonLongArray.add(new JsonPrimitive(l));
|
||||
}
|
||||
|
||||
return jsonLongArray;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown NBT tag: " + tag);
|
||||
}
|
||||
yield jsonLongArray;
|
||||
}
|
||||
default -> throw new IllegalArgumentException("Unknown NBT tag: " + tag);
|
||||
};
|
||||
}
|
||||
|
||||
public static ComponentHolder read(ByteBuf buf, ProtocolVersion version) {
|
||||
|
||||
@@ -59,14 +59,9 @@ public class SystemChatPacket implements MinecraftPacket {
|
||||
component.write(buf);
|
||||
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) {
|
||||
switch (type) {
|
||||
case SYSTEM:
|
||||
buf.writeBoolean(false);
|
||||
break;
|
||||
case GAME_INFO:
|
||||
buf.writeBoolean(true);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid chat type");
|
||||
case SYSTEM -> buf.writeBoolean(false);
|
||||
case GAME_INFO -> buf.writeBoolean(true);
|
||||
default -> throw new IllegalArgumentException("Invalid chat type");
|
||||
}
|
||||
} else {
|
||||
ProtocolUtils.writeVarInt(buf, type.getId());
|
||||
|
||||
@@ -105,26 +105,14 @@ public abstract class GenericTitlePacket implements MinecraftPacket {
|
||||
public static GenericTitlePacket constructTitlePacket(ActionType type, ProtocolVersion version) {
|
||||
GenericTitlePacket packet = null;
|
||||
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_17)) {
|
||||
switch (type) {
|
||||
case SET_ACTION_BAR:
|
||||
packet = new TitleActionbarPacket();
|
||||
break;
|
||||
case SET_SUBTITLE:
|
||||
packet = new TitleSubtitlePacket();
|
||||
break;
|
||||
case SET_TIMES:
|
||||
packet = new TitleTimesPacket();
|
||||
break;
|
||||
case SET_TITLE:
|
||||
packet = new TitleTextPacket();
|
||||
break;
|
||||
case HIDE:
|
||||
case RESET:
|
||||
packet = new TitleClearPacket();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid ActionType");
|
||||
}
|
||||
packet = switch (type) {
|
||||
case SET_ACTION_BAR -> new TitleActionbarPacket();
|
||||
case SET_SUBTITLE -> new TitleSubtitlePacket();
|
||||
case SET_TIMES -> new TitleTimesPacket();
|
||||
case SET_TITLE -> new TitleTextPacket();
|
||||
case HIDE, RESET -> new TitleClearPacket();
|
||||
default -> throw new IllegalArgumentException("Invalid ActionType");
|
||||
};
|
||||
} else {
|
||||
packet = new LegacyTitlePacket();
|
||||
}
|
||||
|
||||
@@ -40,24 +40,19 @@ public class LegacyTitlePacket extends GenericTitlePacket {
|
||||
ProtocolUtils.writeVarInt(buf, getAction().getAction(version));
|
||||
|
||||
switch (getAction()) {
|
||||
case SET_TITLE:
|
||||
case SET_SUBTITLE:
|
||||
case SET_ACTION_BAR:
|
||||
case SET_TITLE, SET_SUBTITLE, SET_ACTION_BAR -> {
|
||||
if (component == null) {
|
||||
throw new IllegalStateException("No component found for " + getAction());
|
||||
}
|
||||
component.write(buf);
|
||||
break;
|
||||
case SET_TIMES:
|
||||
}
|
||||
case SET_TIMES -> {
|
||||
buf.writeInt(fadeIn);
|
||||
buf.writeInt(stay);
|
||||
buf.writeInt(fadeOut);
|
||||
break;
|
||||
case HIDE:
|
||||
case RESET:
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown action " + getAction());
|
||||
}
|
||||
case HIDE, RESET -> {}
|
||||
default -> throw new UnsupportedOperationException("Unknown action " + getAction());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -230,23 +230,20 @@ public final class PluginMessageUtil {
|
||||
}
|
||||
|
||||
// Before falling into the fallback, explicitly rewrite certain messages.
|
||||
switch (name) {
|
||||
case REGISTER_CHANNEL_LEGACY:
|
||||
return REGISTER_CHANNEL;
|
||||
case UNREGISTER_CHANNEL_LEGACY:
|
||||
return UNREGISTER_CHANNEL;
|
||||
case BRAND_CHANNEL_LEGACY:
|
||||
return BRAND_CHANNEL;
|
||||
case "BungeeCord":
|
||||
// This is a special historical case we are compelled to support for the benefit of
|
||||
// BungeeQuack.
|
||||
return "bungeecord:main";
|
||||
default:
|
||||
return switch (name) {
|
||||
case REGISTER_CHANNEL_LEGACY -> REGISTER_CHANNEL;
|
||||
case UNREGISTER_CHANNEL_LEGACY -> UNREGISTER_CHANNEL;
|
||||
case BRAND_CHANNEL_LEGACY -> BRAND_CHANNEL;
|
||||
// This is a special historical case we are compelled to support for the benefit of
|
||||
// BungeeQuack.
|
||||
case "BungeeCord" -> "bungeecord:main";
|
||||
default -> {
|
||||
// This is very likely a legacy name, so transform it. Velocity uses the same scheme as
|
||||
// BungeeCord does to transform channels, but also removes clearly invalid characters as
|
||||
// well.
|
||||
String lower = name.toLowerCase(Locale.ROOT);
|
||||
return "legacy:" + INVALID_IDENTIFIER_REGEX.matcher(lower).replaceAll("");
|
||||
}
|
||||
final String lower = name.toLowerCase(Locale.ROOT);
|
||||
yield "legacy:" + INVALID_IDENTIFIER_REGEX.matcher(lower).replaceAll("");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class VelocityTabListLegacy extends KeyedVelocityTabList {
|
||||
|
||||
@Override
|
||||
public void processLegacy(LegacyPlayerListItemPacket packet) {
|
||||
Item item = packet.getItems().get(0); // Only one item per packet in 1.7
|
||||
Item item = packet.getItems().getFirst(); // Only one item per packet in 1.7
|
||||
|
||||
switch (packet.getAction()) {
|
||||
case LegacyPlayerListItemPacket.ADD_PLAYER:
|
||||
|
||||
@@ -145,45 +145,44 @@ public enum InformationUtils {
|
||||
* @return {@link String} address with public parts redacted
|
||||
*/
|
||||
public static String anonymizeInetAddress(InetAddress address) {
|
||||
if (address instanceof Inet4Address) {
|
||||
Inet4Address v4 = (Inet4Address) address;
|
||||
if (v4.isAnyLocalAddress() || v4.isLoopbackAddress()
|
||||
|| v4.isLinkLocalAddress()
|
||||
|| v4.isSiteLocalAddress()) {
|
||||
return address.getHostAddress();
|
||||
} else {
|
||||
byte[] addr = v4.getAddress();
|
||||
return (addr[0] & 0xff) + "." + (addr[1] & 0xff) + ".XXX.XXX";
|
||||
}
|
||||
} else if (address instanceof Inet6Address) {
|
||||
Inet6Address v6 = (Inet6Address) address;
|
||||
if (v6.isAnyLocalAddress() || v6.isLoopbackAddress()
|
||||
|| v6.isSiteLocalAddress()
|
||||
|| v6.isSiteLocalAddress()) {
|
||||
return address.getHostAddress();
|
||||
} else {
|
||||
String[] bits = v6.getHostAddress().split(":");
|
||||
String ret = "";
|
||||
boolean flag = false;
|
||||
for (int iter = 0; iter < bits.length; iter++) {
|
||||
if (flag) {
|
||||
ret += ":X";
|
||||
continue;
|
||||
}
|
||||
if (!bits[iter].equals("0")) {
|
||||
if (iter == 0) {
|
||||
ret = bits[iter];
|
||||
} else {
|
||||
ret = "::" + bits[iter];
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
return switch (address) {
|
||||
case Inet4Address v4 -> {
|
||||
if (v4.isAnyLocalAddress() || v4.isLoopbackAddress()
|
||||
|| v4.isLinkLocalAddress()
|
||||
|| v4.isSiteLocalAddress()) {
|
||||
yield address.getHostAddress();
|
||||
} else {
|
||||
byte[] addr = v4.getAddress();
|
||||
yield (addr[0] & 0xff) + "." + (addr[1] & 0xff) + ".XXX.XXX";
|
||||
}
|
||||
} case Inet6Address v6 -> {
|
||||
if (v6.isAnyLocalAddress() || v6.isLoopbackAddress()
|
||||
|| v6.isSiteLocalAddress()
|
||||
|| v6.isSiteLocalAddress()) {
|
||||
yield address.getHostAddress();
|
||||
} else {
|
||||
String[] bits = v6.getHostAddress().split(":");
|
||||
String ret = "";
|
||||
boolean flag = false;
|
||||
for (int iter = 0; iter < bits.length; iter++) {
|
||||
if (flag) {
|
||||
ret += ":X";
|
||||
continue;
|
||||
}
|
||||
if (!bits[iter].equals("0")) {
|
||||
if (iter == 0) {
|
||||
ret = bits[iter];
|
||||
} else {
|
||||
ret = "::" + bits[iter];
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
yield ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
return address.getHostAddress();
|
||||
}
|
||||
default -> address.getHostAddress();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,8 +64,8 @@ public class VelocityArgumentCommandNodeTests {
|
||||
assertFalse(reader.canRead());
|
||||
|
||||
assertFalse(this.contextBuilder.getNodes().isEmpty());
|
||||
assertSame(node, this.contextBuilder.getNodes().get(0).getNode());
|
||||
assertEquals(expectedRange, this.contextBuilder.getNodes().get(0).getRange());
|
||||
assertSame(node, this.contextBuilder.getNodes().getFirst().getNode());
|
||||
assertEquals(expectedRange, this.contextBuilder.getNodes().getFirst().getRange());
|
||||
|
||||
assertTrue(this.contextBuilder.getArguments().containsKey("foo"));
|
||||
final ParsedArgument<Object, String[]> parsed =
|
||||
|
||||
@@ -62,16 +62,12 @@ public class FakePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public @NonNull Optional<PluginContainer> getPlugin(@NonNull String id) {
|
||||
switch (id) {
|
||||
case "a":
|
||||
return Optional.of(containerA);
|
||||
case "b":
|
||||
return Optional.of(containerB);
|
||||
case "velocity":
|
||||
return Optional.of(containerVelocity);
|
||||
default:
|
||||
return Optional.empty();
|
||||
}
|
||||
return switch (id) {
|
||||
case "a" -> Optional.of(containerA);
|
||||
case "b" -> Optional.of(containerB);
|
||||
case "velocity" -> Optional.of(containerVelocity);
|
||||
default -> Optional.empty();
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,8 +36,3 @@ sequenceOf(
|
||||
val deprecatedConfigurateModule = ":deprecated-configurate3"
|
||||
include(deprecatedConfigurateModule)
|
||||
project(deprecatedConfigurateModule).projectDir = file("proxy/deprecated/configurate3")
|
||||
|
||||
// Log4J2 plugin
|
||||
val log4j2ProxyPlugin = ":velocity-proxy-log4j2-plugin"
|
||||
include(log4j2ProxyPlugin)
|
||||
project(log4j2ProxyPlugin).projectDir = file("proxy/log4j2-plugin")
|
||||
|
||||
Reference in New Issue
Block a user