Update minimum Java version to 21 (#1649)

This commit is contained in:
Adrian
2026-01-25 13:22:54 -05:00
committed by GitHub
parent d69431a08e
commit 75ecb64159
38 changed files with 410 additions and 550 deletions

View File

@@ -59,7 +59,7 @@ tasks {
val o = options as StandardJavadocDocletOptions val o = options as StandardJavadocDocletOptions
o.encoding = "UTF-8" o.encoding = "UTF-8"
o.source = "17" o.source = "21"
o.use() o.use()
o.links( o.links(

View File

@@ -12,7 +12,7 @@ subprojects {
java { java {
toolchain { toolchain {
languageVersion.set(JavaLanguageVersion.of(17)) languageVersion.set(JavaLanguageVersion.of(21))
} }
} }

View File

@@ -10,7 +10,7 @@ plugins {
application { application {
mainClass.set("com.velocitypowered.proxy.Velocity") mainClass.set("com.velocitypowered.proxy.Velocity")
applicationDefaultJvmArgs += listOf("-Dvelocity.packet-decode-logging=true"); applicationDefaultJvmArgs += listOf("-Dvelocity.packet-decode-logging=true")
} }
tasks { tasks {
@@ -135,7 +135,6 @@ fill {
dependencies { dependencies {
implementation(project(":velocity-api")) implementation(project(":velocity-api"))
implementation(project(":velocity-native")) implementation(project(":velocity-native"))
implementation(project(":velocity-proxy-log4j2-plugin"))
implementation(libs.bundles.log4j) implementation(libs.bundles.log4j)
implementation(libs.kyori.ansi) implementation(libs.kyori.ansi)
@@ -172,4 +171,5 @@ dependencies {
testImplementation(libs.mockito) testImplementation(libs.mockito)
annotationProcessor(libs.auto.service) annotationProcessor(libs.auto.service)
annotationProcessor(libs.log4j.core)
} }

View File

@@ -1,4 +0,0 @@
dependencies {
implementation(libs.bundles.log4j)
annotationProcessor(libs.log4j.core)
}

View File

@@ -344,7 +344,7 @@ final class SuggestionsProvider<S> {
return 0; return 0;
}); });
} }
return potentials.get(0); return potentials.getFirst();
} }
return new ParseResults<>(contextSoFar, originalReader, Collections.emptyMap()); return new ParseResults<>(contextSoFar, originalReader, Collections.emptyMap());
} }

View File

@@ -140,7 +140,7 @@ public class VelocityCommandManager implements CommandManager {
command + " implements multiple registrable Command subinterfaces: " command + " implements multiple registrable Command subinterfaces: "
+ implementedInterfaces); + implementedInterfaces);
} else { } else {
this.internalRegister(commandRegistrars.get(0), command, meta); this.internalRegister(commandRegistrars.getFirst(), command, meta);
} }
} }

View File

@@ -70,33 +70,34 @@ public final class VelocityCommands {
maybeCommand = VelocityBrigadierCommandWrapper.wrap(delegate.getCommand(), registrant); maybeCommand = VelocityBrigadierCommandWrapper.wrap(delegate.getCommand(), registrant);
} }
if (delegate instanceof LiteralCommandNode<CommandSource> lcn) { return switch (delegate) {
var literalBuilder = shallowCopyAsBuilder(lcn, delegate.getName(), true); case LiteralCommandNode<CommandSource> lcn -> {
literalBuilder.executes(maybeCommand); var literalBuilder = shallowCopyAsBuilder(lcn, delegate.getName(), true);
// we also need to wrap any children literalBuilder.executes(maybeCommand);
for (final CommandNode<CommandSource> child : delegate.getChildren()) { // we also need to wrap any children
literalBuilder.then(wrap(child, registrant)); 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) { case VelocityArgumentCommandNode<CommandSource, ?> vacn -> vacn.withCommand(maybeCommand)
literalBuilder.redirect(wrap(delegate.getRedirect(), registrant)); .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(); default -> throw new IllegalArgumentException("Unsupported node type: " + delegate.getClass());
} 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());
}
} }
// Normalization // Normalization
@@ -133,7 +134,7 @@ public final class VelocityCommands {
if (nodes.isEmpty()) { if (nodes.isEmpty()) {
throw new IllegalArgumentException("Cannot read alias from empty node list"); 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"; public static final String ARGS_NODE_NAME = "arguments";

View File

@@ -118,14 +118,12 @@ public class VelocityArgumentCommandNode<S, T> extends ArgumentCommandNode<S, St
if (this == o) { if (this == o) {
return true; return true;
} }
if (!(o instanceof VelocityArgumentCommandNode)) { if (!(o instanceof VelocityArgumentCommandNode that)) {
return false; return false;
} }
if (!super.equals(o)) { if (!super.equals(that)) {
return false; return false;
} }
final VelocityArgumentCommandNode<?, ?> that = (VelocityArgumentCommandNode<?, ?>) o;
return this.type.equals(that.type); return this.type.equals(that.type);
} }

View File

@@ -242,7 +242,7 @@ public final class VelocityCommand {
hoverText.append(Component.newline()); hoverText.append(Component.newline());
if (description.getAuthors().size() == 1) { if (description.getAuthors().size() == 1) {
hoverText.append(Component.translatable("velocity.command.plugin-tooltip-author", hoverText.append(Component.translatable("velocity.command.plugin-tooltip-author",
Component.text(description.getAuthors().get(0)))); Component.text(description.getAuthors().getFirst())));
} else { } else {
hoverText.append( hoverText.append(
Component.translatable("velocity.command.plugin-tooltip-author", Component.translatable("velocity.command.plugin-tooltip-author",

View File

@@ -156,19 +156,16 @@ public class VelocityConfiguration implements ProxyConfig {
} }
switch (playerInfoForwardingMode) { switch (playerInfoForwardingMode) {
case NONE: case NONE -> logger.warn("Player info forwarding is disabled! All players will appear to be connecting "
logger.warn("Player info forwarding is disabled! All players will appear to be connecting "
+ "from the proxy and will have offline-mode UUIDs."); + "from the proxy and will have offline-mode UUIDs.");
break; case MODERN, BUNGEEGUARD -> {
case MODERN:
case BUNGEEGUARD:
if (forwardingSecret == null || forwardingSecret.length == 0) { if (forwardingSecret == null || forwardingSecret.length == 0) {
logger.error("You don't have a forwarding secret set. This is required for security."); logger.error("You don't have a forwarding secret set. This is required for security.");
valid = false; valid = false;
} }
break; }
default: default -> {
break; }
} }
if (servers.getServers().isEmpty()) { if (servers.getServers().isEmpty()) {

View File

@@ -153,13 +153,13 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
if (msg instanceof MinecraftPacket pkt) { if (msg instanceof MinecraftPacket pkt) {
if (!pkt.handle(activeSessionHandler)) { if (!pkt.handle(activeSessionHandler)) {
activeSessionHandler.handleGeneric((MinecraftPacket) msg); activeSessionHandler.handleGeneric(pkt);
} }
} else if (msg instanceof HAProxyMessage proxyMessage) { } else if (msg instanceof HAProxyMessage proxyMessage) {
this.remoteAddress = new InetSocketAddress(proxyMessage.sourceAddress(), this.remoteAddress = new InetSocketAddress(proxyMessage.sourceAddress(),
proxyMessage.sourcePort()); proxyMessage.sourcePort());
} else if (msg instanceof ByteBuf) { } else if (msg instanceof ByteBuf buf) {
activeSessionHandler.handleUnknown((ByteBuf) msg); activeSessionHandler.handleUnknown(buf);
} }
} finally { } finally {
ReferenceCountUtil.release(msg); ReferenceCountUtil.release(msg);

View File

@@ -452,8 +452,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public void handleGeneric(MinecraftPacket packet) { public void handleGeneric(MinecraftPacket packet) {
if (packet instanceof PluginMessagePacket) { if (packet instanceof PluginMessagePacket pluginMessage) {
((PluginMessagePacket) packet).retain(); pluginMessage.retain();
} }
playerConnection.delayedWrite(packet); playerConnection.delayedWrite(packet);
if (++packetsFlushed >= MAXIMUM_PACKETS_TO_FLUSH) { if (++packetsFlushed >= MAXIMUM_PACKETS_TO_FLUSH) {

View File

@@ -344,66 +344,30 @@ public class BungeeCordMessageResponder {
return false; return false;
} }
ByteBufDataInput in = new ByteBufDataInput(message.content()); final ByteBufDataInput in = new ByteBufDataInput(message.content());
String subChannel = in.readUTF(); final String subChannel = in.readUTF();
switch (subChannel) { switch (subChannel) {
case "GetPlayerServer": case "GetPlayerServer" -> this.processGetPlayerServer(in);
this.processGetPlayerServer(in); case "ForwardToPlayer" -> this.processForwardToPlayer(in);
break; case "Forward" -> this.processForwardToServer(in);
case "ForwardToPlayer": case "Connect" -> this.processConnect(in);
this.processForwardToPlayer(in); case "ConnectOther" -> this.processConnectOther(in);
break; case "IP" -> this.processIp(in);
case "Forward": case "PlayerCount" -> this.processPlayerCount(in);
this.processForwardToServer(in); case "PlayerList" -> this.processPlayerList(in);
break; case "GetServers" -> this.processGetServers();
case "Connect": case "Message" -> this.processMessage(in);
this.processConnect(in); case "MessageRaw" -> this.processMessageRaw(in);
break; case "GetServer" -> this.processGetServer();
case "ConnectOther": case "UUID" -> this.processUuid();
this.processConnectOther(in); case "UUIDOther" -> this.processUuidOther(in);
break; case "IPOther" -> this.processIpOther(in);
case "IP": case "ServerIP" -> this.processServerIp(in);
this.processIp(in); case "KickPlayer" -> this.processKick(in);
break; case "KickPlayerRaw" -> this.processKickRaw(in);
case "PlayerCount": default -> {
this.processPlayerCount(in); // Do nothing, unknown command
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;
} }
return true; return true;

View File

@@ -122,9 +122,8 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
// Change the client to use the ClientPlaySessionHandler if required. // Change the client to use the ClientPlaySessionHandler if required.
ClientPlaySessionHandler playHandler; ClientPlaySessionHandler playHandler;
if (player.getConnection() if (player.getConnection()
.getActiveSessionHandler() instanceof ClientPlaySessionHandler) { .getActiveSessionHandler() instanceof ClientPlaySessionHandler sessionHandler) {
playHandler = playHandler = sessionHandler;
(ClientPlaySessionHandler) player.getConnection().getActiveSessionHandler();
} else { } else {
playHandler = new ClientPlaySessionHandler(server, player); playHandler = new ClientPlaySessionHandler(server, player);
player.getConnection().setActiveSessionHandler(StateRegistry.PLAY, playHandler); player.getConnection().setActiveSessionHandler(StateRegistry.PLAY, playHandler);

View File

@@ -180,9 +180,8 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
handshake.setServerAddress(createBungeeGuardForwardingAddress(secret)); handshake.setServerAddress(createBungeeGuardForwardingAddress(secret));
} else if (proxyPlayer.getConnection().getType() == ConnectionTypes.LEGACY_FORGE) { } else if (proxyPlayer.getConnection().getType() == ConnectionTypes.LEGACY_FORGE) {
handshake.setServerAddress(playerVhost + HANDSHAKE_HOSTNAME_TOKEN); handshake.setServerAddress(playerVhost + HANDSHAKE_HOSTNAME_TOKEN);
} else if (proxyPlayer.getConnection().getType() instanceof ModernForgeConnectionType) { } else if (proxyPlayer.getConnection().getType() instanceof ModernForgeConnectionType forgeConnection) {
handshake.setServerAddress(playerVhost + ((ModernForgeConnectionType) proxyPlayer handshake.setServerAddress(playerVhost + forgeConnection.getModernToken());
.getConnection().getType()).getModernToken());
} else { } else {
handshake.setServerAddress(playerVhost); handshake.setServerAddress(playerVhost);
} }

View File

@@ -811,61 +811,56 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
return; return;
} }
if (event.getResult() instanceof final DisconnectPlayer res) { switch (event.getResult()) {
disconnect(res.getReasonComponent()); case DisconnectPlayer res -> disconnect(res.getReasonComponent());
} else if (event.getResult() instanceof final RedirectPlayer res) { case RedirectPlayer res -> createConnectionRequest(res.getServer(), previousConnection).connect()
createConnectionRequest(res.getServer(), previousConnection).connect() .whenCompleteAsync((status, throwable) -> {
.whenCompleteAsync((status, throwable) -> { if (throwable != null) {
if (throwable != null) { handleConnectionException(res.getServer(), throwable, true);
handleConnectionException(res.getServer(), throwable, true); return;
return; }
}
switch (status.getStatus()) { switch (status.getStatus()) {
// Impossible/nonsensical cases // Impossible/nonsensical cases
case ALREADY_CONNECTED: case ALREADY_CONNECTED -> logger.error("{}: already connected to {}", this,
logger.error("{}: already connected to {}", this, status.getAttemptedConnection().getServerInfo().getName());
status.getAttemptedConnection().getServerInfo().getName()); case CONNECTION_IN_PROGRESS, CONNECTION_CANCELLED -> {
break; Component fallbackMsg = res.getMessageComponent();
case CONNECTION_IN_PROGRESS: if (fallbackMsg == null) {
// Fatal case fallbackMsg = friendlyReason;
case CONNECTION_CANCELLED: }
Component fallbackMsg = res.getMessageComponent(); disconnect(status.getReasonComponent().orElse(fallbackMsg));
if (fallbackMsg == null) { }
fallbackMsg = friendlyReason; 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)); }, connection.eventLoop());
break; case Notify res -> {
case SERVER_DISCONNECTED: if (event.kickedDuringServerConnect() && previousConnection != null) {
Component reason = status.getReasonComponent() sendMessage(res.getMessageComponent());
.orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR); } else {
handleConnectionException(res.getServer(), disconnect(res.getMessageComponent());
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());
} }
} else {
// In case someone gets creative, assume we want to disconnect the player. // In case someone gets creative, assume we want to disconnect the player.
disconnect(friendlyReason); default -> disconnect(friendlyReason);
} }
}, connection.eventLoop()); }, connection.eventLoop());
} }

View File

@@ -214,6 +214,7 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
server.getVersion().getName() + "/" + server.getVersion().getVersion()) server.getVersion().getName() + "/" + server.getVersion().getVersion())
.uri(URI.create(url)) .uri(URI.create(url))
.build(); .build();
//noinspection resource
final HttpClient httpClient = server.createHttpClient(); final HttpClient httpClient = server.createHttpClient();
httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString()) httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())
.whenCompleteAsync((response, throwable) -> { .whenCompleteAsync((response, throwable) -> {
@@ -268,14 +269,12 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
} }
}, mcConnection.eventLoop()) }, mcConnection.eventLoop())
.thenRun(() -> { .thenRun(() -> {
if (httpClient instanceof final AutoCloseable closeable) { try {
try { httpClient.close();
closeable.close(); } catch (Exception e) {
} catch (Exception e) { // In Java 21, the HttpClient does not throw any Exception
// In Java 21, the HttpClient does not throw any Exception // when trying to clean its resources, so this should not happen
// when trying to clean its resources, so this should not happen logger.error("An unknown error occurred while trying to close an HttpClient", e);
logger.error("An unknown error occurred while trying to close an HttpClient", e);
}
} }
}); });
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {

View File

@@ -94,7 +94,7 @@ public final class ModernResourcePackHandler extends ResourcePackHandler {
this.outstandingResourcePacks.get(info.getId()); this.outstandingResourcePacks.get(info.getId());
outstandingResourcePacks.add(info); outstandingResourcePacks.add(info);
if (outstandingResourcePacks.size() == 1) { 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 = final List<ResourcePackInfo> outstandingResourcePacks =
this.outstandingResourcePacks.get(uuid); this.outstandingResourcePacks.get(uuid);
if (!outstandingResourcePacks.isEmpty()) { if (!outstandingResourcePacks.isEmpty()) {
sendResourcePackRequestPacket(outstandingResourcePacks.get(0)); sendResourcePackRequestPacket(outstandingResourcePacks.getFirst());
} }
} }
@@ -124,7 +124,7 @@ public final class ModernResourcePackHandler extends ResourcePackHandler {
this.outstandingResourcePacks.get(uuid); this.outstandingResourcePacks.get(uuid);
final boolean peek = bundle.status().isIntermediate(); final boolean peek = bundle.status().isIntermediate();
final ResourcePackInfo queued = outstandingResourcePacks.isEmpty() ? null : final ResourcePackInfo queued = outstandingResourcePacks.isEmpty() ? null :
peek ? outstandingResourcePacks.get(0) : outstandingResourcePacks.remove(0); peek ? outstandingResourcePacks.getFirst() : outstandingResourcePacks.removeFirst();
server.getEventManager() server.getEventManager()
.fire(new PlayerResourcePackStatusEvent(this.player, uuid, bundle.status(), queued)) .fire(new PlayerResourcePackStatusEvent(this.player, uuid, bundle.status(), queued))

View File

@@ -100,65 +100,60 @@ public class ServerListPingHandler {
CompletableFuture<List<ServerPing>> pingResponses = CompletableFutures.successfulAsList(pings, CompletableFuture<List<ServerPing>> pingResponses = CompletableFutures.successfulAsList(pings,
(ex) -> fallback); (ex) -> fallback);
switch (mode) { return switch (mode) {
case ALL: case ALL -> pingResponses.thenApply(responses -> {
return pingResponses.thenApply(responses -> { // Find the first non-fallback
// Find the first non-fallback for (ServerPing response : responses) {
for (ServerPing response : responses) { if (response == fallback) {
if (response == fallback) { continue;
continue;
}
if (response.getDescriptionComponent() == null) {
return response.asBuilder()
.description(Component.empty())
.build();
}
return response;
} }
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) { if (response.getDescriptionComponent() == null) {
continue; return response.asBuilder()
} .description(Component.empty())
.build();
return new ServerPing(
fallback.getVersion(),
fallback.getPlayers().orElse(null),
response.getDescriptionComponent(),
fallback.getFavicon().orElse(null),
response.getModinfo().orElse(null)
);
} }
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. // Not possible, but covered for completeness.
default: default -> CompletableFuture.completedFuture(fallback);
return CompletableFuture.completedFuture(fallback); };
}
} }
/** /**

View File

@@ -33,6 +33,7 @@ import net.kyori.adventure.permission.PermissionChecker;
import net.kyori.adventure.platform.facet.FacetPointers; import net.kyori.adventure.platform.facet.FacetPointers;
import net.kyori.adventure.platform.facet.FacetPointers.Type; import net.kyori.adventure.platform.facet.FacetPointers.Type;
import net.kyori.adventure.pointer.Pointers; import net.kyori.adventure.pointer.Pointers;
import net.kyori.adventure.pointer.PointersSupplier;
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.logger.slf4j.ComponentLogger; 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 final VelocityServer server;
private PermissionFunction permissionFunction = ALWAYS_TRUE; private PermissionFunction permissionFunction = ALWAYS_TRUE;
private final @NotNull Pointers pointers = ConsoleCommandSource.super.pointers().toBuilder() private static final @NotNull PointersSupplier<VelocityConsole> POINTERS = PointersSupplier.<VelocityConsole>builder()
.withDynamic(PermissionChecker.POINTER, this::getPermissionChecker) .resolving(PermissionChecker.POINTER, VelocityConsole::getPermissionChecker)
.withDynamic(Identity.LOCALE, () -> ClosestLocaleMatcher.INSTANCE .resolving(Identity.LOCALE, (console) -> ClosestLocaleMatcher.INSTANCE
.lookupClosest(Locale.getDefault())) .lookupClosest(Locale.getDefault()))
.withStatic(FacetPointers.TYPE, Type.CONSOLE) .resolving(FacetPointers.TYPE, (console) -> Type.CONSOLE)
.build(); .build();
public VelocityConsole(VelocityServer server) { public VelocityConsole(VelocityServer server) {
@@ -153,6 +154,6 @@ public final class VelocityConsole extends SimpleTerminalConsole implements Cons
@Override @Override
public @NotNull Pointers pointers() { public @NotNull Pointers pointers() {
return pointers; return POINTERS.view(this);
} }
} }

View File

@@ -71,7 +71,7 @@ public final class SeparatePoolInetNameResolver extends InetNameResolver {
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception { protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
List<InetAddress> addresses = cache.getIfPresent(inetHost); List<InetAddress> addresses = cache.getIfPresent(inetHost);
if (addresses != null) { if (addresses != null) {
promise.trySuccess(addresses.get(0)); promise.trySuccess(addresses.getFirst());
return; return;
} }

View File

@@ -83,7 +83,7 @@ public class JavaPluginLoader implements PluginLoader {
@Override @Override
public PluginDescription createPluginFromCandidate(PluginDescription candidate) throws Exception { 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"); 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}); PluginClassLoader loader = new PluginClassLoader(new URL[]{pluginJarUrl});
loader.addToClassloaders(); loader.addToClassloaders();
JavaVelocityPluginDescriptionCandidate candidateInst =
(JavaVelocityPluginDescriptionCandidate) candidate;
Class<?> mainClass = loader.loadClass(candidateInst.getMainClass()); Class<?> mainClass = loader.loadClass(candidateInst.getMainClass());
return createDescription(candidateInst, mainClass); return createDescription(candidateInst, mainClass);
} }
@@ -102,11 +100,10 @@ public class JavaPluginLoader implements PluginLoader {
@Override @Override
public Module createModule(PluginContainer container) { public Module createModule(PluginContainer container) {
PluginDescription description = container.getDescription(); 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"); throw new IllegalArgumentException("Description provided isn't of the Java plugin loader");
} }
JavaVelocityPluginDescription javaDescription = (JavaVelocityPluginDescription) description;
Optional<Path> source = javaDescription.getSource(); Optional<Path> source = javaDescription.getSource();
if (source.isEmpty()) { if (source.isEmpty()) {
@@ -118,24 +115,23 @@ public class JavaPluginLoader implements PluginLoader {
@Override @Override
public void createPlugin(PluginContainer container, Module... modules) { 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"); throw new IllegalArgumentException("Container provided isn't of the Java plugin loader");
} }
PluginDescription description = container.getDescription(); PluginDescription description = pluginContainer.getDescription();
if (!(description instanceof JavaVelocityPluginDescription)) { if (!(description instanceof JavaVelocityPluginDescription javaPluginDescription)) {
throw new IllegalArgumentException("Description provided isn't of the Java plugin loader"); throw new IllegalArgumentException("Description provided isn't of the Java plugin loader");
} }
Injector injector = Guice.createInjector(modules); Injector injector = Guice.createInjector(modules);
Object instance = injector Object instance = injector.getInstance(javaPluginDescription.getMainClass());
.getInstance(((JavaVelocityPluginDescription) description).getMainClass());
if (instance == null) { if (instance == null) {
throw new IllegalStateException( throw new IllegalStateException(
"Got nothing from injector for plugin " + description.getId()); "Got nothing from injector for plugin " + description.getId());
} }
((VelocityPluginContainer) container).setInstance(instance); pluginContainer.setInstance(instance);
} }
private Optional<SerializedPluginDescription> getSerializedPluginInfo(Path source) private Optional<SerializedPluginDescription> getSerializedPluginInfo(Path source)
@@ -145,22 +141,23 @@ public class JavaPluginLoader implements PluginLoader {
new BufferedInputStream(Files.newInputStream(source)))) { new BufferedInputStream(Files.newInputStream(source)))) {
JarEntry entry; JarEntry entry;
while ((entry = in.getNextJarEntry()) != null) { while ((entry = in.getNextJarEntry()) != null) {
if (entry.getName().equals("velocity-plugin.json")) { switch (entry.getName()) {
try (Reader pluginInfoReader = new InputStreamReader(in, StandardCharsets.UTF_8)) { case "velocity-plugin.json" -> {
return Optional.of(VelocityServer.GENERAL_GSON.fromJson(pluginInfoReader, try (Reader pluginInfoReader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
SerializedPluginDescription.class)); 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) { if (foundBungeeBukkitPluginFile) {
throw new InvalidPluginException("The plugin file " + source.getFileName() + " appears to " throw new InvalidPluginException("The plugin file " + source.getFileName() + " appears to "
+ "be a Bukkit or BungeeCord plugin. Velocity does not support Bukkit or BungeeCord " + "be a Paper, Bukkit or BungeeCord plugin. Velocity does not support plugins from these "
+ "plugins."); + "platforms.");
} }
return Optional.empty(); return Optional.empty();

View File

@@ -119,7 +119,7 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
int sessionId = queryMessage.readInt(); int sessionId = queryMessage.readInt();
switch (type) { switch (type) {
case QUERY_TYPE_HANDSHAKE: { case QUERY_TYPE_HANDSHAKE -> {
// Generate new challenge token and put it into the sessions cache // Generate new challenge token and put it into the sessions cache
int challengeToken = random.nextInt(); int challengeToken = random.nextInt();
sessions.put(senderAddress, challengeToken); sessions.put(senderAddress, challengeToken);
@@ -132,10 +132,9 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
DatagramPacket responsePacket = new DatagramPacket(queryResponse, msg.sender()); DatagramPacket responsePacket = new DatagramPacket(queryResponse, msg.sender());
ctx.writeAndFlush(responsePacket, ctx.voidPromise()); 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 // Check if query was done with session previously generated using a handshake packet
int challengeToken = queryMessage.readInt(); int challengeToken = queryMessage.readInt();
Integer session = sessions.getIfPresent(senderAddress); 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); "Exception while writing GS4 response for query from {}", senderAddress, ex);
return null; return null;
}); });
break;
} }
default: default -> {
// Invalid query type - just don't respond // Invalid query type - just don't respond
}
} }
} }

View File

@@ -25,7 +25,6 @@ import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.mojang.brigadier.suggestion.SuggestionsBuilder;
@@ -331,12 +330,10 @@ public class AvailableCommandsPacket implements MinecraftPacket {
.add("redirectTo", redirectTo); .add("redirectTo", redirectTo);
if (args != null) { if (args != null) {
if (args instanceof LiteralArgumentBuilder) { if (args instanceof LiteralArgumentBuilder literal) {
helper.add("argsLabel", helper.add("argsLabel", literal.getLiteral());
((LiteralArgumentBuilder<CommandSource>) args).getLiteral()); } else if (args instanceof RequiredArgumentBuilder required) {
} else if (args instanceof RequiredArgumentBuilder) { helper.add("argsName", required.getName());
helper.add("argsName",
((RequiredArgumentBuilder<CommandSource, ?>) args).getName());
} }
} }
@@ -348,17 +345,11 @@ public class AvailableCommandsPacket implements MinecraftPacket {
* A placeholder {@link SuggestionProvider} used internally to preserve the suggestion provider * A placeholder {@link SuggestionProvider} used internally to preserve the suggestion provider
* name. * name.
*/ */
public static class ProtocolSuggestionProvider implements SuggestionProvider<CommandSource> { public record ProtocolSuggestionProvider(String name) implements SuggestionProvider<CommandSource> {
private final String name;
public ProtocolSuggestionProvider(String name) {
this.name = name;
}
@Override @Override
public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSource> context, public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSource> context,
SuggestionsBuilder builder) throws CommandSyntaxException { SuggestionsBuilder builder) {
return builder.buildFuture(); return builder.buildFuture();
} }
} }

View File

@@ -207,30 +207,22 @@ public class BossBarPacket implements MinecraftPacket {
this.uuid = ProtocolUtils.readUuid(buf); this.uuid = ProtocolUtils.readUuid(buf);
this.action = ProtocolUtils.readVarInt(buf); this.action = ProtocolUtils.readVarInt(buf);
switch (action) { switch (action) {
case ADD: case ADD -> {
this.name = ComponentHolder.read(buf, version); this.name = ComponentHolder.read(buf, version);
this.percent = buf.readFloat(); this.percent = buf.readFloat();
this.color = ProtocolUtils.readVarInt(buf); this.color = ProtocolUtils.readVarInt(buf);
this.overlay = ProtocolUtils.readVarInt(buf); this.overlay = ProtocolUtils.readVarInt(buf);
this.flags = buf.readUnsignedByte(); this.flags = buf.readUnsignedByte();
break; }
case REMOVE: case REMOVE -> {}
break; case UPDATE_PERCENT -> this.percent = buf.readFloat();
case UPDATE_PERCENT: case UPDATE_NAME -> this.name = ComponentHolder.read(buf, version);
this.percent = buf.readFloat(); case UPDATE_STYLE -> {
break;
case UPDATE_NAME:
this.name = ComponentHolder.read(buf, version);
break;
case UPDATE_STYLE:
this.color = ProtocolUtils.readVarInt(buf); this.color = ProtocolUtils.readVarInt(buf);
this.overlay = ProtocolUtils.readVarInt(buf); this.overlay = ProtocolUtils.readVarInt(buf);
break; }
case UPDATE_PROPERTIES: case UPDATE_PROPERTIES -> this.flags = buf.readUnsignedByte();
this.flags = buf.readUnsignedByte(); default -> throw new UnsupportedOperationException("Unknown action " + action);
break;
default:
throw new UnsupportedOperationException("Unknown action " + action);
} }
} }
@@ -242,36 +234,30 @@ public class BossBarPacket implements MinecraftPacket {
ProtocolUtils.writeUuid(buf, uuid); ProtocolUtils.writeUuid(buf, uuid);
ProtocolUtils.writeVarInt(buf, action); ProtocolUtils.writeVarInt(buf, action);
switch (action) { switch (action) {
case ADD: case ADD -> {
if (name == null) { if (name == null) {
throw new IllegalStateException("No name specified!"); throw new IllegalStateException("No name specified!");
} }
name.write(buf); name.write(buf);
buf.writeFloat(percent); 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, color);
ProtocolUtils.writeVarInt(buf, overlay); ProtocolUtils.writeVarInt(buf, overlay);
buf.writeByte(flags); }
break; case UPDATE_PROPERTIES -> buf.writeByte(flags);
case REMOVE: default -> throw new UnsupportedOperationException("Unknown action " + action);
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);
} }
} }

View File

@@ -69,33 +69,25 @@ public class LegacyPlayerListItemPacket implements MinecraftPacket {
Item item = new Item(ProtocolUtils.readUuid(buf)); Item item = new Item(ProtocolUtils.readUuid(buf));
items.add(item); items.add(item);
switch (action) { switch (action) {
case ADD_PLAYER: case ADD_PLAYER -> {
item.setName(ProtocolUtils.readString(buf)); item.setName(ProtocolUtils.readString(buf));
item.setProperties(ProtocolUtils.readProperties(buf)); item.setProperties(ProtocolUtils.readProperties(buf));
item.setGameMode(ProtocolUtils.readVarInt(buf)); item.setGameMode(ProtocolUtils.readVarInt(buf));
item.setLatency(ProtocolUtils.readVarInt(buf)); item.setLatency(ProtocolUtils.readVarInt(buf));
item.setDisplayName(readOptionalComponent(buf, version)); item.setDisplayName(readOptionalComponent(buf, version));
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) {
if (buf.readBoolean()) { if (buf.readBoolean()) {
item.setPlayerKey(ProtocolUtils.readPlayerKey(version, buf)); item.setPlayerKey(ProtocolUtils.readPlayerKey(version, buf));
} }
} }
break; }
case UPDATE_GAMEMODE: case UPDATE_GAMEMODE -> item.setGameMode(ProtocolUtils.readVarInt(buf));
item.setGameMode(ProtocolUtils.readVarInt(buf)); case UPDATE_LATENCY -> item.setLatency(ProtocolUtils.readVarInt(buf));
break; case UPDATE_DISPLAY_NAME -> item.setDisplayName(readOptionalComponent(buf, version));
case UPDATE_LATENCY: case REMOVE_PLAYER -> {
item.setLatency(ProtocolUtils.readVarInt(buf)); //Do nothing, all that is needed is the uuid
break; }
case UPDATE_DISPLAY_NAME: default -> throw new UnsupportedOperationException("Unknown action " + action);
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);
} }
} }
} else { } else {
@@ -126,39 +118,32 @@ public class LegacyPlayerListItemPacket implements MinecraftPacket {
ProtocolUtils.writeUuid(buf, uuid); ProtocolUtils.writeUuid(buf, uuid);
switch (action) { switch (action) {
case ADD_PLAYER: case ADD_PLAYER -> {
ProtocolUtils.writeString(buf, item.getName()); ProtocolUtils.writeString(buf, item.getName());
ProtocolUtils.writeProperties(buf, item.getProperties()); ProtocolUtils.writeProperties(buf, item.getProperties());
ProtocolUtils.writeVarInt(buf, item.getGameMode()); ProtocolUtils.writeVarInt(buf, item.getGameMode());
ProtocolUtils.writeVarInt(buf, item.getLatency()); ProtocolUtils.writeVarInt(buf, item.getLatency());
writeDisplayName(buf, item.getDisplayName(), version); writeDisplayName(buf, item.getDisplayName(), version);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) {
if (item.getPlayerKey() != null) { if (item.getPlayerKey() != null) {
buf.writeBoolean(true); buf.writeBoolean(true);
ProtocolUtils.writePlayerKey(buf, item.getPlayerKey()); ProtocolUtils.writePlayerKey(buf, item.getPlayerKey());
} else { } else {
buf.writeBoolean(false); buf.writeBoolean(false);
} }
} }
break; }
case UPDATE_GAMEMODE: case UPDATE_GAMEMODE -> ProtocolUtils.writeVarInt(buf, item.getGameMode());
ProtocolUtils.writeVarInt(buf, item.getGameMode()); case UPDATE_LATENCY -> ProtocolUtils.writeVarInt(buf, item.getLatency());
break; case UPDATE_DISPLAY_NAME -> writeDisplayName(buf, item.getDisplayName(), version);
case UPDATE_LATENCY: case REMOVE_PLAYER -> {
ProtocolUtils.writeVarInt(buf, item.getLatency());
break;
case UPDATE_DISPLAY_NAME:
writeDisplayName(buf, item.getDisplayName(), version);
break;
case REMOVE_PLAYER:
// Do nothing, all that is needed is the uuid // Do nothing, all that is needed is the uuid
break; }
default: default -> throw new UnsupportedOperationException("Unknown action " + action);
throw new UnsupportedOperationException("Unknown action " + action);
} }
} }
} else { } else {
Item item = items.get(0); Item item = items.getFirst();
Component displayNameComponent = item.getDisplayName(); Component displayNameComponent = item.getDisplayName();
if (displayNameComponent != null) { if (displayNameComponent != null) {
String displayName = LegacyComponentSerializer.legacySection() String displayName = LegacyComponentSerializer.legacySection()
@@ -269,7 +254,7 @@ public class LegacyPlayerListItemPacket implements MinecraftPacket {
return this; return this;
} }
public IdentifiedKey getPlayerKey() { public @Nullable IdentifiedKey getPlayerKey() {
return playerKey; return playerKey;
} }
} }

View File

@@ -37,32 +37,21 @@ class StringArgumentPropertySerializer implements ArgumentPropertySerializer<Str
@Override @Override
public StringArgumentType deserialize(ByteBuf buf, ProtocolVersion protocolVersion) { public StringArgumentType deserialize(ByteBuf buf, ProtocolVersion protocolVersion) {
int type = ProtocolUtils.readVarInt(buf); int type = ProtocolUtils.readVarInt(buf);
switch (type) { return switch (type) {
case 0: case 0 -> StringArgumentType.word();
return StringArgumentType.word(); case 1 -> StringArgumentType.string();
case 1: case 2 -> StringArgumentType.greedyString();
return StringArgumentType.string(); default -> throw new IllegalArgumentException("Invalid string argument type " + type);
case 2: };
return StringArgumentType.greedyString();
default:
throw new IllegalArgumentException("Invalid string argument type " + type);
}
} }
@Override @Override
public void serialize(StringArgumentType object, ByteBuf buf, ProtocolVersion protocolVersion) { public void serialize(StringArgumentType object, ByteBuf buf, ProtocolVersion protocolVersion) {
switch (object.getType()) { switch (object.getType()) {
case SINGLE_WORD: case SINGLE_WORD -> ProtocolUtils.writeVarInt(buf, 0);
ProtocolUtils.writeVarInt(buf, 0); case QUOTABLE_PHRASE -> ProtocolUtils.writeVarInt(buf, 1);
break; case GREEDY_PHRASE -> ProtocolUtils.writeVarInt(buf, 2);
case QUOTABLE_PHRASE: default -> throw new IllegalArgumentException("Invalid string argument type " + object.getType());
ProtocolUtils.writeVarInt(buf, 1);
break;
case GREEDY_PHRASE:
ProtocolUtils.writeVarInt(buf, 2);
break;
default:
throw new IllegalArgumentException("Invalid string argument type " + object.getType());
} }
} }
} }

View File

@@ -113,23 +113,18 @@ public class ComponentHolder {
public static BinaryTag serialize(JsonElement json) { public static BinaryTag serialize(JsonElement json) {
if (json instanceof JsonPrimitive jsonPrimitive) { if (json instanceof JsonPrimitive jsonPrimitive) {
if (jsonPrimitive.isNumber()) { if (jsonPrimitive.isNumber()) {
Number number = json.getAsNumber(); final Number number = json.getAsNumber();
if (number instanceof Byte) { return switch (number) {
return ByteBinaryTag.byteBinaryTag((Byte) number); case Byte b -> ByteBinaryTag.byteBinaryTag(b);
} else if (number instanceof Short) { case Short s -> ShortBinaryTag.shortBinaryTag(s);
return ShortBinaryTag.shortBinaryTag((Short) number); case Integer i -> IntBinaryTag.intBinaryTag(i);
} else if (number instanceof Integer) { case Long l -> LongBinaryTag.longBinaryTag(l);
return IntBinaryTag.intBinaryTag((Integer) number); case Float f -> FloatBinaryTag.floatBinaryTag(f);
} else if (number instanceof Long) { case Double d -> DoubleBinaryTag.doubleBinaryTag(d);
return LongBinaryTag.longBinaryTag((Long) number); case LazilyParsedNumber l -> IntBinaryTag.intBinaryTag(l.intValue());
} else if (number instanceof Float) { default -> throw new IllegalArgumentException("Unknown number type: " + number);
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());
}
} else if (jsonPrimitive.isString()) { } else if (jsonPrimitive.isString()) {
return StringBinaryTag.stringBinaryTag(jsonPrimitive.getAsString()); return StringBinaryTag.stringBinaryTag(jsonPrimitive.getAsString());
} else if (jsonPrimitive.isBoolean()) { } else if (jsonPrimitive.isBoolean()) {
@@ -137,16 +132,16 @@ public class ComponentHolder {
} else { } else {
throw new IllegalArgumentException("Unknown JSON primitive: " + jsonPrimitive); throw new IllegalArgumentException("Unknown JSON primitive: " + jsonPrimitive);
} }
} else if (json instanceof JsonObject) { } else if (json instanceof JsonObject object) {
CompoundBinaryTag.Builder compound = CompoundBinaryTag.builder(); 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())); compound.put(property.getKey(), serialize(property.getValue()));
} }
return compound.build(); return compound.build();
} else if (json instanceof JsonArray) { } else if (json instanceof JsonArray array) {
List<JsonElement> jsonArray = ((JsonArray) json).asList(); List<JsonElement> jsonArray = array.asList();
if (jsonArray.isEmpty()) { if (jsonArray.isEmpty()) {
return ListBinaryTag.empty(); return ListBinaryTag.empty();
@@ -206,20 +201,21 @@ public class ComponentHolder {
} }
public static JsonElement deserialize(BinaryTag tag) { public static JsonElement deserialize(BinaryTag tag) {
switch (tag.type().id()) { return switch (tag.type().id()) {
case 1://BinaryTagTypes.BYTE: //BinaryTagTypes.BYTE
return new JsonPrimitive(((ByteBinaryTag) tag).value()); case 1 -> new JsonPrimitive(((ByteBinaryTag) tag).value());
case 2://BinaryTagTypes.SHORT: //BinaryTagTypes.SHORT
return new JsonPrimitive(((ShortBinaryTag) tag).value()); case 2 -> new JsonPrimitive(((ShortBinaryTag) tag).value());
case 3://BinaryTagTypes.INT: //BinaryTagTypes.INT:
return new JsonPrimitive(((IntBinaryTag) tag).value()); case 3 -> new JsonPrimitive(((IntBinaryTag) tag).value());
case 4://BinaryTagTypes.LONG: //BinaryTagTypes.LONG:
return new JsonPrimitive(((LongBinaryTag) tag).value()); case 4 -> new JsonPrimitive(((LongBinaryTag) tag).value());
case 5://BinaryTagTypes.FLOAT: //BinaryTagTypes.FLOAT:
return new JsonPrimitive(((FloatBinaryTag) tag).value()); case 5 -> new JsonPrimitive(((FloatBinaryTag) tag).value());
case 6://BinaryTagTypes.DOUBLE: //BinaryTagTypes.DOUBLE:
return new JsonPrimitive(((DoubleBinaryTag) tag).value()); case 6 -> new JsonPrimitive(((DoubleBinaryTag) tag).value());
case 7://BinaryTagTypes.BYTE_ARRAY: //BinaryTagTypes.BYTE_ARRAY:
case 7 -> {
byte[] byteArray = ((ByteArrayBinaryTag) tag).value(); byte[] byteArray = ((ByteArrayBinaryTag) tag).value();
JsonArray jsonByteArray = new JsonArray(byteArray.length); JsonArray jsonByteArray = new JsonArray(byteArray.length);
@@ -227,10 +223,12 @@ public class ComponentHolder {
jsonByteArray.add(new JsonPrimitive(b)); jsonByteArray.add(new JsonPrimitive(b));
} }
return jsonByteArray; yield jsonByteArray;
case 8://BinaryTagTypes.STRING: }
return new JsonPrimitive(((StringBinaryTag) tag).value()); //BinaryTagTypes.STRING:
case 9://BinaryTagTypes.LIST: case 8 -> new JsonPrimitive(((StringBinaryTag) tag).value());
//BinaryTagTypes.LIST:
case 9 -> {
ListBinaryTag items = (ListBinaryTag) tag; ListBinaryTag items = (ListBinaryTag) tag;
JsonArray jsonList = new JsonArray(items.size()); JsonArray jsonList = new JsonArray(items.size());
@@ -238,8 +236,10 @@ public class ComponentHolder {
jsonList.add(deserialize(subTag)); jsonList.add(deserialize(subTag));
} }
return jsonList; yield jsonList;
case 10://BinaryTagTypes.COMPOUND: }
//BinaryTagTypes.COMPOUND:
case 10 -> {
CompoundBinaryTag compound = (CompoundBinaryTag) tag; CompoundBinaryTag compound = (CompoundBinaryTag) tag;
JsonObject jsonObject = new JsonObject(); JsonObject jsonObject = new JsonObject();
@@ -252,8 +252,10 @@ public class ComponentHolder {
jsonObject.add(key.isEmpty() ? "text" : key, deserialize(compound.get(key))); jsonObject.add(key.isEmpty() ? "text" : key, deserialize(compound.get(key)));
}); });
return jsonObject; yield jsonObject;
case 11://BinaryTagTypes.INT_ARRAY: }
//BinaryTagTypes.INT_ARRAY:
case 11 -> {
int[] intArray = ((IntArrayBinaryTag) tag).value(); int[] intArray = ((IntArrayBinaryTag) tag).value();
JsonArray jsonIntArray = new JsonArray(intArray.length); JsonArray jsonIntArray = new JsonArray(intArray.length);
@@ -261,8 +263,10 @@ public class ComponentHolder {
jsonIntArray.add(new JsonPrimitive(i)); jsonIntArray.add(new JsonPrimitive(i));
} }
return jsonIntArray; yield jsonIntArray;
case 12://BinaryTagTypes.LONG_ARRAY: }
//BinaryTagTypes.LONG_ARRAY:
case 12 -> {
long[] longArray = ((LongArrayBinaryTag) tag).value(); long[] longArray = ((LongArrayBinaryTag) tag).value();
JsonArray jsonLongArray = new JsonArray(longArray.length); JsonArray jsonLongArray = new JsonArray(longArray.length);
@@ -270,10 +274,10 @@ public class ComponentHolder {
jsonLongArray.add(new JsonPrimitive(l)); jsonLongArray.add(new JsonPrimitive(l));
} }
return jsonLongArray; yield jsonLongArray;
default: }
throw new IllegalArgumentException("Unknown NBT tag: " + tag); default -> throw new IllegalArgumentException("Unknown NBT tag: " + tag);
} };
} }
public static ComponentHolder read(ByteBuf buf, ProtocolVersion version) { public static ComponentHolder read(ByteBuf buf, ProtocolVersion version) {

View File

@@ -59,14 +59,9 @@ public class SystemChatPacket implements MinecraftPacket {
component.write(buf); component.write(buf);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) {
switch (type) { switch (type) {
case SYSTEM: case SYSTEM -> buf.writeBoolean(false);
buf.writeBoolean(false); case GAME_INFO -> buf.writeBoolean(true);
break; default -> throw new IllegalArgumentException("Invalid chat type");
case GAME_INFO:
buf.writeBoolean(true);
break;
default:
throw new IllegalArgumentException("Invalid chat type");
} }
} else { } else {
ProtocolUtils.writeVarInt(buf, type.getId()); ProtocolUtils.writeVarInt(buf, type.getId());

View File

@@ -105,26 +105,14 @@ public abstract class GenericTitlePacket implements MinecraftPacket {
public static GenericTitlePacket constructTitlePacket(ActionType type, ProtocolVersion version) { public static GenericTitlePacket constructTitlePacket(ActionType type, ProtocolVersion version) {
GenericTitlePacket packet = null; GenericTitlePacket packet = null;
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_17)) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_17)) {
switch (type) { packet = switch (type) {
case SET_ACTION_BAR: case SET_ACTION_BAR -> new TitleActionbarPacket();
packet = new TitleActionbarPacket(); case SET_SUBTITLE -> new TitleSubtitlePacket();
break; case SET_TIMES -> new TitleTimesPacket();
case SET_SUBTITLE: case SET_TITLE -> new TitleTextPacket();
packet = new TitleSubtitlePacket(); case HIDE, RESET -> new TitleClearPacket();
break; default -> throw new IllegalArgumentException("Invalid ActionType");
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");
}
} else { } else {
packet = new LegacyTitlePacket(); packet = new LegacyTitlePacket();
} }

View File

@@ -40,24 +40,19 @@ public class LegacyTitlePacket extends GenericTitlePacket {
ProtocolUtils.writeVarInt(buf, getAction().getAction(version)); ProtocolUtils.writeVarInt(buf, getAction().getAction(version));
switch (getAction()) { switch (getAction()) {
case SET_TITLE: case SET_TITLE, SET_SUBTITLE, SET_ACTION_BAR -> {
case SET_SUBTITLE:
case SET_ACTION_BAR:
if (component == null) { if (component == null) {
throw new IllegalStateException("No component found for " + getAction()); throw new IllegalStateException("No component found for " + getAction());
} }
component.write(buf); component.write(buf);
break; }
case SET_TIMES: case SET_TIMES -> {
buf.writeInt(fadeIn); buf.writeInt(fadeIn);
buf.writeInt(stay); buf.writeInt(stay);
buf.writeInt(fadeOut); buf.writeInt(fadeOut);
break; }
case HIDE: case HIDE, RESET -> {}
case RESET: default -> throw new UnsupportedOperationException("Unknown action " + getAction());
break;
default:
throw new UnsupportedOperationException("Unknown action " + getAction());
} }
} }

View File

@@ -230,23 +230,20 @@ public final class PluginMessageUtil {
} }
// Before falling into the fallback, explicitly rewrite certain messages. // Before falling into the fallback, explicitly rewrite certain messages.
switch (name) { return switch (name) {
case REGISTER_CHANNEL_LEGACY: case REGISTER_CHANNEL_LEGACY -> REGISTER_CHANNEL;
return REGISTER_CHANNEL; case UNREGISTER_CHANNEL_LEGACY -> UNREGISTER_CHANNEL;
case UNREGISTER_CHANNEL_LEGACY: case BRAND_CHANNEL_LEGACY -> BRAND_CHANNEL;
return UNREGISTER_CHANNEL; // This is a special historical case we are compelled to support for the benefit of
case BRAND_CHANNEL_LEGACY: // BungeeQuack.
return BRAND_CHANNEL; case "BungeeCord" -> "bungeecord:main";
case "BungeeCord": default -> {
// This is a special historical case we are compelled to support for the benefit of
// BungeeQuack.
return "bungeecord:main";
default:
// This is very likely a legacy name, so transform it. Velocity uses the same scheme as // 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 // BungeeCord does to transform channels, but also removes clearly invalid characters as
// well. // well.
String lower = name.toLowerCase(Locale.ROOT); final String lower = name.toLowerCase(Locale.ROOT);
return "legacy:" + INVALID_IDENTIFIER_REGEX.matcher(lower).replaceAll(""); yield "legacy:" + INVALID_IDENTIFIER_REGEX.matcher(lower).replaceAll("");
} }
};
} }
} }

View File

@@ -85,7 +85,7 @@ public class VelocityTabListLegacy extends KeyedVelocityTabList {
@Override @Override
public void processLegacy(LegacyPlayerListItemPacket packet) { 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()) { switch (packet.getAction()) {
case LegacyPlayerListItemPacket.ADD_PLAYER: case LegacyPlayerListItemPacket.ADD_PLAYER:

View File

@@ -145,45 +145,44 @@ public enum InformationUtils {
* @return {@link String} address with public parts redacted * @return {@link String} address with public parts redacted
*/ */
public static String anonymizeInetAddress(InetAddress address) { public static String anonymizeInetAddress(InetAddress address) {
if (address instanceof Inet4Address) { return switch (address) {
Inet4Address v4 = (Inet4Address) address; case Inet4Address v4 -> {
if (v4.isAnyLocalAddress() || v4.isLoopbackAddress() if (v4.isAnyLocalAddress() || v4.isLoopbackAddress()
|| v4.isLinkLocalAddress() || v4.isLinkLocalAddress()
|| v4.isSiteLocalAddress()) { || v4.isSiteLocalAddress()) {
return address.getHostAddress(); yield address.getHostAddress();
} else { } else {
byte[] addr = v4.getAddress(); byte[] addr = v4.getAddress();
return (addr[0] & 0xff) + "." + (addr[1] & 0xff) + ".XXX.XXX"; yield (addr[0] & 0xff) + "." + (addr[1] & 0xff) + ".XXX.XXX";
} }
} else if (address instanceof Inet6Address) { } case Inet6Address v6 -> {
Inet6Address v6 = (Inet6Address) address; if (v6.isAnyLocalAddress() || v6.isLoopbackAddress()
if (v6.isAnyLocalAddress() || v6.isLoopbackAddress() || v6.isSiteLocalAddress()
|| v6.isSiteLocalAddress() || v6.isSiteLocalAddress()) {
|| v6.isSiteLocalAddress()) { yield address.getHostAddress();
return address.getHostAddress(); } else {
} else { String[] bits = v6.getHostAddress().split(":");
String[] bits = v6.getHostAddress().split(":"); String ret = "";
String ret = ""; boolean flag = false;
boolean flag = false; for (int iter = 0; iter < bits.length; iter++) {
for (int iter = 0; iter < bits.length; iter++) { if (flag) {
if (flag) { ret += ":X";
ret += ":X"; continue;
continue; }
} if (!bits[iter].equals("0")) {
if (!bits[iter].equals("0")) { if (iter == 0) {
if (iter == 0) { ret = bits[iter];
ret = bits[iter]; } else {
} else { ret = "::" + bits[iter];
ret = "::" + bits[iter]; }
} flag = true;
flag = true; }
} }
yield ret;
} }
return ret;
} }
} else { default -> address.getHostAddress();
return address.getHostAddress(); };
}
} }
/** /**

View File

@@ -64,8 +64,8 @@ public class VelocityArgumentCommandNodeTests {
assertFalse(reader.canRead()); assertFalse(reader.canRead());
assertFalse(this.contextBuilder.getNodes().isEmpty()); assertFalse(this.contextBuilder.getNodes().isEmpty());
assertSame(node, this.contextBuilder.getNodes().get(0).getNode()); assertSame(node, this.contextBuilder.getNodes().getFirst().getNode());
assertEquals(expectedRange, this.contextBuilder.getNodes().get(0).getRange()); assertEquals(expectedRange, this.contextBuilder.getNodes().getFirst().getRange());
assertTrue(this.contextBuilder.getArguments().containsKey("foo")); assertTrue(this.contextBuilder.getArguments().containsKey("foo"));
final ParsedArgument<Object, String[]> parsed = final ParsedArgument<Object, String[]> parsed =

View File

@@ -62,16 +62,12 @@ public class FakePluginManager implements PluginManager {
@Override @Override
public @NonNull Optional<PluginContainer> getPlugin(@NonNull String id) { public @NonNull Optional<PluginContainer> getPlugin(@NonNull String id) {
switch (id) { return switch (id) {
case "a": case "a" -> Optional.of(containerA);
return Optional.of(containerA); case "b" -> Optional.of(containerB);
case "b": case "velocity" -> Optional.of(containerVelocity);
return Optional.of(containerB); default -> Optional.empty();
case "velocity": };
return Optional.of(containerVelocity);
default:
return Optional.empty();
}
} }
@Override @Override

View File

@@ -36,8 +36,3 @@ sequenceOf(
val deprecatedConfigurateModule = ":deprecated-configurate3" val deprecatedConfigurateModule = ":deprecated-configurate3"
include(deprecatedConfigurateModule) include(deprecatedConfigurateModule)
project(deprecatedConfigurateModule).projectDir = file("proxy/deprecated/configurate3") project(deprecatedConfigurateModule).projectDir = file("proxy/deprecated/configurate3")
// Log4J2 plugin
val log4j2ProxyPlugin = ":velocity-proxy-log4j2-plugin"
include(log4j2ProxyPlugin)
project(log4j2ProxyPlugin).projectDir = file("proxy/log4j2-plugin")