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
o.encoding = "UTF-8"
o.source = "17"
o.source = "21"
o.use()
o.links(

View File

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

View File

@@ -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)
}

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 potentials.get(0);
return potentials.getFirst();
}
return new ParseResults<>(contextSoFar, originalReader, Collections.emptyMap());
}

View File

@@ -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);
}
}

View File

@@ -70,7 +70,8 @@ public final class VelocityCommands {
maybeCommand = VelocityBrigadierCommandWrapper.wrap(delegate.getCommand(), registrant);
}
if (delegate instanceof LiteralCommandNode<CommandSource> lcn) {
return switch (delegate) {
case LiteralCommandNode<CommandSource> lcn -> {
var literalBuilder = shallowCopyAsBuilder(lcn, delegate.getName(), true);
literalBuilder.executes(maybeCommand);
// we also need to wrap any children
@@ -80,12 +81,12 @@ public final class VelocityCommands {
if (delegate.getRedirect() != null) {
literalBuilder.redirect(wrap(delegate.getRedirect(), registrant));
}
return literalBuilder.build();
} else if (delegate instanceof VelocityArgumentCommandNode<CommandSource, ?> vacn) {
return vacn.withCommand(maybeCommand)
yield literalBuilder.build();
}
case VelocityArgumentCommandNode<CommandSource, ?> vacn -> vacn.withCommand(maybeCommand)
.withRedirect(delegate.getRedirect() != null ? wrap(delegate.getRedirect(), registrant) : null);
} else if (delegate instanceof ArgumentCommandNode) {
var argBuilder = delegate.createBuilder().executes(maybeCommand);
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));
@@ -93,10 +94,10 @@ public final class VelocityCommands {
if (delegate.getRedirect() != null) {
argBuilder.redirect(wrap(delegate.getRedirect(), registrant));
}
return argBuilder.build();
} else {
throw new IllegalArgumentException("Unsupported node type: " + delegate.getClass());
yield argBuilder.build();
}
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";

View File

@@ -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);
}

View File

@@ -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",

View File

@@ -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()) {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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:
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
break;
}
}
return true;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -811,10 +811,9 @@ 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()
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);
@@ -823,27 +822,23 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
switch (status.getStatus()) {
// Impossible/nonsensical cases
case ALREADY_CONNECTED:
logger.error("{}: already connected to {}", this,
case ALREADY_CONNECTED -> logger.error("{}: already connected to {}", this,
status.getAttemptedConnection().getServerInfo().getName());
break;
case CONNECTION_IN_PROGRESS:
// Fatal case
case CONNECTION_CANCELLED:
case CONNECTION_IN_PROGRESS, CONNECTION_CANCELLED -> {
Component fallbackMsg = res.getMessageComponent();
if (fallbackMsg == null) {
fallbackMsg = friendlyReason;
}
disconnect(status.getReasonComponent().orElse(fallbackMsg));
break;
case SERVER_DISCONNECTED:
}
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:
}
case SUCCESS -> {
Component requestedMessage = res.getMessageComponent();
if (requestedMessage == null) {
requestedMessage = friendlyReason;
@@ -851,21 +846,21 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
if (requestedMessage != Component.empty()) {
sendMessage(requestedMessage);
}
break;
default:
}
default -> {
// The only remaining value is successful (no need to do anything!)
break;
}
}
}, connection.eventLoop());
} else if (event.getResult() instanceof final Notify res) {
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());
}

View File

@@ -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,15 +269,13 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
}
}, mcConnection.eventLoop())
.thenRun(() -> {
if (httpClient instanceof final AutoCloseable closeable) {
try {
closeable.close();
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) {
logger.error("Unable to enable encryption", e);

View File

@@ -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))

View File

@@ -100,9 +100,8 @@ public class ServerListPingHandler {
CompletableFuture<List<ServerPing>> pingResponses = CompletableFutures.successfulAsList(pings,
(ex) -> fallback);
switch (mode) {
case ALL:
return pingResponses.thenApply(responses -> {
return switch (mode) {
case ALL -> pingResponses.thenApply(responses -> {
// Find the first non-fallback
for (ServerPing response : responses) {
if (response == fallback) {
@@ -119,8 +118,7 @@ public class ServerListPingHandler {
}
return fallback;
});
case MODS:
return pingResponses.thenApply(responses -> {
case MODS -> pingResponses.thenApply(responses -> {
// Find the first non-fallback that contains a mod list
for (ServerPing response : responses) {
if (response == fallback) {
@@ -133,14 +131,12 @@ public class ServerListPingHandler {
}
return fallback;
});
case DESCRIPTION:
return pingResponses.thenApply(responses -> {
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;
}
@@ -156,9 +152,8 @@ public class ServerListPingHandler {
return fallback;
});
// Not possible, but covered for completeness.
default:
return CompletableFuture.completedFuture(fallback);
}
default -> 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.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);
}
}

View File

@@ -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;
}

View File

@@ -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")) {
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));
}
}
if (entry.getName().equals("plugin.yml") || entry.getName().equals("bungee.yml")) {
foundBungeeBukkitPluginFile = true;
case "paper-plugin.yml", "plugin.yml", "bungee.yml" -> foundBungeeBukkitPluginFile = true;
default -> {
}
}
}
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();

View File

@@ -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,12 +189,12 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
"Exception while writing GS4 response for query from {}", senderAddress, ex);
return null;
});
break;
}
default:
default -> {
// Invalid query type - just don't respond
}
}
}
private static void writeString(ByteBuf buf, String string) {
buf.writeCharSequence(string, StandardCharsets.ISO_8859_1);

View File

@@ -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();
}
}

View File

@@ -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,7 +234,7 @@ public class BossBarPacket implements MinecraftPacket {
ProtocolUtils.writeUuid(buf, uuid);
ProtocolUtils.writeVarInt(buf, action);
switch (action) {
case ADD:
case ADD -> {
if (name == null) {
throw new IllegalStateException("No name specified!");
}
@@ -251,27 +243,21 @@ public class BossBarPacket implements MinecraftPacket {
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:
}
case REMOVE -> {}
case UPDATE_PERCENT -> buf.writeFloat(percent);
case UPDATE_NAME -> {
if (name == null) {
throw new IllegalStateException("No name specified!");
}
name.write(buf);
break;
case UPDATE_STYLE:
}
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);
}
}

View File

@@ -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));
}
}
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:
}
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
break;
default:
throw new UnsupportedOperationException("Unknown action " + action);
}
default -> throw new UnsupportedOperationException("Unknown action " + action);
}
}
} else {
@@ -126,7 +118,7 @@ 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());
@@ -140,25 +132,18 @@ public class LegacyPlayerListItemPacket implements MinecraftPacket {
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;
}
}

View File

@@ -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());
}
}
}

View File

@@ -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) {

View File

@@ -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());

View File

@@ -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();
}

View File

@@ -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());
}
}

View File

@@ -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":
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.
return "bungeecord:main";
default:
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("");
}
};
}
}

View File

@@ -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:

View File

@@ -145,22 +145,21 @@ 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;
return switch (address) {
case Inet4Address v4 -> {
if (v4.isAnyLocalAddress() || v4.isLoopbackAddress()
|| v4.isLinkLocalAddress()
|| v4.isSiteLocalAddress()) {
return address.getHostAddress();
yield address.getHostAddress();
} else {
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) {
Inet6Address v6 = (Inet6Address) address;
} case Inet6Address v6 -> {
if (v6.isAnyLocalAddress() || v6.isLoopbackAddress()
|| v6.isSiteLocalAddress()
|| v6.isSiteLocalAddress()) {
return address.getHostAddress();
yield address.getHostAddress();
} else {
String[] bits = v6.getHostAddress().split(":");
String ret = "";
@@ -179,11 +178,11 @@ public enum InformationUtils {
flag = true;
}
}
return ret;
yield ret;
}
} else {
return address.getHostAddress();
}
default -> address.getHostAddress();
};
}
/**

View File

@@ -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 =

View File

@@ -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

View File

@@ -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")