Move Bungee and Sponge platforms to separate plugins

Bungee support is half broken due to not having the same injection points as Velocity and has become less and less stable with every update. The Sponge plugin has been almost entirely unused
This commit is contained in:
Nassim Jahnke 2024-05-30 21:51:38 +02:00
parent 5245a7ef2e
commit a48c3a6ec2
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
48 changed files with 6 additions and 3137 deletions

View File

@ -14,10 +14,8 @@ val main = setOf(
projects.viaversionCommon, projects.viaversionCommon,
projects.viaversionApi, projects.viaversionApi,
projects.viaversionBukkit, projects.viaversionBukkit,
projects.viaversionBungee, projects.viaversionVelocity,
projects.viaversionFabric, projects.viaversionFabric
projects.viaversionSponge,
projects.viaversionVelocity
).map { it.dependencyProject } ).map { it.dependencyProject }
// val special = setOf().map { it.dependencyProject } // val special = setOf().map { it.dependencyProject }

View File

@ -1,6 +0,0 @@
dependencies {
compileOnlyApi(projects.viaversionCommon)
compileOnly(libs.bungee)
}
publishShadowJar()

View File

@ -1,227 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion;
import com.google.common.collect.ImmutableList;
import com.google.gson.JsonObject;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.ViaAPI;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.platform.PlatformTask;
import com.viaversion.viaversion.api.platform.UnsupportedSoftware;
import com.viaversion.viaversion.api.platform.ViaServerProxyPlatform;
import com.viaversion.viaversion.bungee.commands.BungeeCommand;
import com.viaversion.viaversion.bungee.commands.BungeeCommandHandler;
import com.viaversion.viaversion.bungee.commands.BungeeCommandSender;
import com.viaversion.viaversion.bungee.platform.BungeeViaAPI;
import com.viaversion.viaversion.bungee.platform.BungeeViaConfig;
import com.viaversion.viaversion.bungee.platform.BungeeViaInjector;
import com.viaversion.viaversion.bungee.platform.BungeeViaLoader;
import com.viaversion.viaversion.bungee.platform.BungeeViaTask;
import com.viaversion.viaversion.bungee.service.ProtocolDetectorService;
import com.viaversion.viaversion.dump.PluginInfo;
import com.viaversion.viaversion.unsupported.UnsupportedServerSoftware;
import com.viaversion.viaversion.util.GsonUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.protocol.ProtocolConstants;
public class BungeePlugin extends Plugin implements ViaServerProxyPlatform<ProxiedPlayer>, Listener {
private final ProtocolDetectorService protocolDetectorService = new ProtocolDetectorService();
private BungeeViaAPI api;
private BungeeViaConfig config;
@Override
public void onLoad() {
try {
ProtocolConstants.class.getField("MINECRAFT_1_20_5");
} catch (NoSuchFieldException e) {
getLogger().warning(" / \\");
getLogger().warning(" / \\");
getLogger().warning(" / | \\");
getLogger().warning(" / | \\ BUNGEECORD IS OUTDATED");
getLogger().warning(" / \\ VIAVERSION MAY NOT WORK AS INTENDED");
getLogger().warning(" / o \\");
getLogger().warning("/_____________\\");
}
getLogger().warning("ViaVersion does not work as intended across many different server versions, especially the more recent ones. " +
"Consider moving Via plugins to your backend server or switching to Velocity.");
api = new BungeeViaAPI();
config = new BungeeViaConfig(getDataFolder(), getLogger());
BungeeCommandHandler commandHandler = new BungeeCommandHandler();
ProxyServer.getInstance().getPluginManager().registerCommand(this, new BungeeCommand(commandHandler));
// Init platform
Via.init(ViaManagerImpl.builder()
.platform(this)
.injector(new BungeeViaInjector())
.loader(new BungeeViaLoader(this))
.commandHandler(commandHandler)
.build());
config.reload();
}
@Override
public void onEnable() {
final ViaManagerImpl manager = (ViaManagerImpl) Via.getManager();
manager.init();
manager.onServerLoaded();
}
@Override
public String getPlatformName() {
return getProxy().getName();
}
@Override
public String getPlatformVersion() {
return getProxy().getVersion();
}
@Override
public boolean isProxy() {
return true;
}
@Override
public String getPluginVersion() {
return getDescription().getVersion();
}
@Override
public PlatformTask runAsync(Runnable runnable) {
return new BungeeViaTask(getProxy().getScheduler().runAsync(this, runnable));
}
@Override
public PlatformTask runRepeatingAsync(final Runnable runnable, final long ticks) {
return new BungeeViaTask(getProxy().getScheduler().schedule(this, runnable, 0, ticks * 50, TimeUnit.MILLISECONDS));
}
@Override
public PlatformTask runSync(Runnable runnable) {
return runAsync(runnable);
}
@Override
public PlatformTask runSync(Runnable runnable, long delay) {
return new BungeeViaTask(getProxy().getScheduler().schedule(this, runnable, delay * 50, TimeUnit.MILLISECONDS));
}
@Override
public PlatformTask runRepeatingSync(Runnable runnable, long period) {
return runRepeatingAsync(runnable, period);
}
@Override
public ViaCommandSender[] getOnlinePlayers() {
Collection<ProxiedPlayer> players = getProxy().getPlayers();
ViaCommandSender[] array = new ViaCommandSender[players.size()];
int i = 0;
for (ProxiedPlayer player : players) {
array[i++] = new BungeeCommandSender(player);
}
return array;
}
@Override
public void sendMessage(UUID uuid, String message) {
getProxy().getPlayer(uuid).sendMessage(message);
}
@Override
public boolean kickPlayer(UUID uuid, String message) {
ProxiedPlayer player = getProxy().getPlayer(uuid);
if (player != null) {
player.disconnect(message);
return true;
}
return false;
}
@Override
public boolean isPluginEnabled() {
return true;
}
@Override
public ViaAPI<ProxiedPlayer> getApi() {
return api;
}
@Override
public BungeeViaConfig getConf() {
return config;
}
@Override
public void onReload() {
// Injector prints a message <3
}
@Override
public JsonObject getDump() {
JsonObject platformSpecific = new JsonObject();
List<PluginInfo> plugins = new ArrayList<>();
for (Plugin p : ProxyServer.getInstance().getPluginManager().getPlugins())
plugins.add(new PluginInfo(
true,
p.getDescription().getName(),
p.getDescription().getVersion(),
p.getDescription().getMain(),
Collections.singletonList(p.getDescription().getAuthor())
));
platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins));
platformSpecific.add("servers", GsonUtil.getGson().toJsonTree(protocolDetectorService.detectedProtocolVersions()));
return platformSpecific;
}
@Override
public Collection<UnsupportedSoftware> getUnsupportedSoftwareClasses() {
final Collection<UnsupportedSoftware> list = new ArrayList<>(ViaServerProxyPlatform.super.getUnsupportedSoftwareClasses());
list.add(new UnsupportedServerSoftware.Builder()
.name("FlameCord")
.addClassName("dev._2lstudios.flamecord.FlameCord")
.reason(UnsupportedServerSoftware.Reason.BREAKING_PROXY_SOFTWARE)
.build());
return ImmutableList.copyOf(list);
}
@Override
public boolean hasPlugin(final String name) {
return getProxy().getPluginManager().getPlugin(name) != null;
}
@Override
public ProtocolDetectorService protocolDetectorService() {
return protocolDetectorService;
}
}

View File

@ -1,41 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.commands;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
public class BungeeCommand extends Command implements TabExecutor {
private final BungeeCommandHandler handler;
public BungeeCommand(BungeeCommandHandler handler) {
super("viaversion", "viaversion.command", "viaver", "vvbungee"); // The permission is also referenced here to filter root suggestions (/via<tab>)
this.handler = handler;
}
@Override
public void execute(CommandSender commandSender, String[] strings) {
handler.onCommand(new BungeeCommandSender(commandSender), strings);
}
@Override
public Iterable<String> onTabComplete(CommandSender commandSender, String[] strings) {
return handler.onTabComplete(new BungeeCommandSender(commandSender), strings);
}
}

View File

@ -1,28 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.commands;
import com.viaversion.viaversion.bungee.commands.subs.ProbeSubCmd;
import com.viaversion.viaversion.commands.ViaCommandHandler;
public class BungeeCommandHandler extends ViaCommandHandler {
public BungeeCommandHandler() {
registerSubCommand(new ProbeSubCmd());
}
}

View File

@ -1,50 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.commands;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import java.util.UUID;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public record BungeeCommandSender(CommandSender sender) implements ViaCommandSender {
@Override
public boolean hasPermission(String permission) {
return sender.hasPermission(permission);
}
@Override
public void sendMessage(String msg) {
sender.sendMessage(msg);
}
@Override
public UUID getUUID() {
if (sender instanceof ProxiedPlayer player) {
return player.getUniqueId();
} else {
return new UUID(0, 0);
}
}
@Override
public String getName() {
return sender.getName();
}
}

View File

@ -1,44 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.commands.subs;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.command.ViaSubCommand;
import com.viaversion.viaversion.bungee.platform.BungeeViaConfig;
public class ProbeSubCmd implements ViaSubCommand {
@Override
public String name() {
return "probe";
}
@Override
public String description() {
return "Forces ViaVersion to scan server protocol versions " +
(((BungeeViaConfig) Via.getConfig()).getBungeePingInterval() == -1 ?
"" : "(Also happens at an interval)");
}
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
Via.proxyPlatform().protocolDetectorService().probeAllServers();
sendMessage(sender, "&6Started searching for protocol versions");
return true;
}
}

View File

@ -1,69 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.handlers;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.connection.UserConnectionImpl;
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import java.lang.reflect.Method;
import java.util.logging.Level;
public class BungeeChannelInitializer extends ChannelInitializer<Channel> {
private final ChannelInitializer<Channel> original;
private Method method;
public BungeeChannelInitializer(ChannelInitializer<Channel> oldInit) {
this.original = oldInit;
try {
this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
this.method.setAccessible(true);
} catch (NoSuchMethodException e) {
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to get initChannel method", e);
}
}
@Override
protected void initChannel(Channel socketChannel) throws Exception {
if (!socketChannel.isActive()) {
return;
}
UserConnection info = new UserConnectionImpl(socketChannel);
// init protocol
new ProtocolPipelineImpl(info);
// Add originals
this.method.invoke(this.original, socketChannel);
if (!socketChannel.isActive()) return; // Don't inject if inactive
if (socketChannel.pipeline().get("packet-encoder") == null) return; // Don't inject if no packet-encoder
if (socketChannel.pipeline().get("packet-decoder") == null) return; // Don't inject if no packet-decoder
// Add our transformers
BungeeEncodeHandler encoder = new BungeeEncodeHandler(info);
BungeeDecodeHandler decoder = new BungeeDecodeHandler(info);
socketChannel.pipeline().addBefore("packet-encoder", "via-encoder", encoder);
socketChannel.pipeline().addBefore("packet-decoder", "via-decoder", decoder);
}
public ChannelInitializer<Channel> getOriginal() {
return original;
}
}

View File

@ -1,63 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.handlers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.exception.CancelCodecException;
import com.viaversion.viaversion.exception.CancelDecoderException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
@ChannelHandler.Sharable
public class BungeeDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
private final UserConnection info;
public BungeeDecodeHandler(UserConnection info) {
this.info = info;
}
@Override
protected void decode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
if (!ctx.channel().isActive()) {
throw CancelDecoderException.generate(null);
}
if (!info.checkServerboundPacket()) throw CancelDecoderException.generate(null);
if (!info.shouldTransformPacket()) {
out.add(bytebuf.retain());
return;
}
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
try {
info.transformServerbound(transformedBuf, CancelDecoderException::generate);
out.add(transformedBuf.retain());
} finally {
transformedBuf.release();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause instanceof CancelCodecException) return;
super.exceptionCaught(ctx, cause);
}
}

View File

@ -1,108 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.handlers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bungee.util.BungeePipelineUtil;
import com.viaversion.viaversion.exception.CancelCodecException;
import com.viaversion.viaversion.exception.CancelEncoderException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.util.List;
@ChannelHandler.Sharable
public class BungeeEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
private final UserConnection info;
private boolean handledCompression;
public BungeeEncodeHandler(UserConnection info) {
this.info = info;
}
@Override
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
if (!ctx.channel().isActive()) {
throw CancelEncoderException.generate(null);
}
if (!info.checkClientboundPacket()) throw CancelEncoderException.generate(null);
if (!info.shouldTransformPacket()) {
out.add(bytebuf.retain());
return;
}
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
try {
boolean needsCompress = handleCompressionOrder(ctx, transformedBuf);
info.transformClientbound(transformedBuf, CancelEncoderException::generate);
if (needsCompress) {
recompress(ctx, transformedBuf);
}
out.add(transformedBuf.retain());
} finally {
transformedBuf.release();
}
}
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buf) {
boolean needsCompress = false;
if (!handledCompression && ctx.pipeline().names().indexOf("compress") > ctx.pipeline().names().indexOf("via-encoder")) {
// Need to decompress this packet due to bad order
ByteBuf decompressed = BungeePipelineUtil.decompress(ctx, buf);
// Ensure the buffer wasn't reused
if (buf != decompressed) {
try {
buf.clear().writeBytes(decompressed);
} finally {
decompressed.release();
}
}
// Reorder the pipeline
ChannelHandler decoder = ctx.pipeline().get("via-decoder");
ChannelHandler encoder = ctx.pipeline().get("via-encoder");
ctx.pipeline().remove(decoder);
ctx.pipeline().remove(encoder);
ctx.pipeline().addAfter("decompress", "via-decoder", decoder);
ctx.pipeline().addAfter("compress", "via-encoder", encoder);
needsCompress = true;
handledCompression = true;
}
return needsCompress;
}
private void recompress(ChannelHandlerContext ctx, ByteBuf buf) {
ByteBuf compressed = BungeePipelineUtil.compress(ctx, buf);
try {
buf.clear().writeBytes(compressed);
} finally {
compressed.release();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause instanceof CancelCodecException) return;
super.exceptionCaught(ctx, cause);
}
}

View File

@ -1,289 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.handlers;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.ClientEntityIdChangeListener;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
import com.viaversion.viaversion.api.protocol.ProtocolPipeline;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.bungee.storage.BungeeStorage;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.rewriter.ItemPacketRewriter1_13;
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.EntityIdProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.storage.EntityTracker1_9;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.stream.Collectors;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.score.Team;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.PluginMessage;
// All of this is madness
public class BungeeServerHandler implements Listener {
private static final MethodHandle GET_HANDSHAKE;
private static final MethodHandle GET_REGISTERED_CHANNELS;
private static final MethodHandle GET_BRAND_MESSAGE;
private static final MethodHandle GET_ENTITY_MAP;
private static final MethodHandle SET_VERSION;
private static final MethodHandle SET_ENTITY_REWRITE;
private static final MethodHandle GET_CHANNEL_WRAPPER;
static {
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
final Class<?> initialHandlerClass = Class.forName("net.md_5.bungee.connection.InitialHandler");
GET_HANDSHAKE = lookup.findVirtual(initialHandlerClass, "getHandshake", MethodType.methodType(Handshake.class));
GET_REGISTERED_CHANNELS = lookup.findVirtual(initialHandlerClass, "getRegisteredChannels", MethodType.methodType(Set.class));
GET_BRAND_MESSAGE = lookup.findVirtual(initialHandlerClass, "getBrandMessage", MethodType.methodType(PluginMessage.class));
final Class<?> entityMapClass = Class.forName("net.md_5.bungee.entitymap.EntityMap");
final Class<?> channelWrapperClass = Class.forName("net.md_5.bungee.netty.ChannelWrapper");
GET_ENTITY_MAP = lookup.findStatic(entityMapClass, "getEntityMap", MethodType.methodType(entityMapClass, int.class));
SET_VERSION = lookup.findVirtual(channelWrapperClass, "setVersion", MethodType.methodType(void.class, int.class));
final Class<?> userConnectionClass = Class.forName("net.md_5.bungee.UserConnection");
final MethodHandles.Lookup privateLookup = MethodHandles.privateLookupIn(userConnectionClass, lookup);
GET_CHANNEL_WRAPPER = privateLookup.findGetter(userConnectionClass, "ch", channelWrapperClass);
SET_ENTITY_REWRITE = privateLookup.findSetter(userConnectionClass, "entityRewrite", entityMapClass);
} catch (final ReflectiveOperationException e) {
Via.getPlatform().getLogger().severe("Error initializing BungeeServerHandler, try updating BungeeCord or ViaVersion!");
throw new RuntimeException(e);
}
}
// Set the handshake version every time someone connects to any server
@EventHandler(priority = 120)
public void onServerConnect(ServerConnectEvent event) {
if (event.isCancelled()) {
return;
}
UserConnection user = Via.getManager().getConnectionManager().getConnectedClient(event.getPlayer().getUniqueId());
if (user == null) {
return;
}
if (!user.has(BungeeStorage.class)) {
user.put(new BungeeStorage(event.getPlayer()));
}
ProtocolVersion serverProtocolVersion = Via.proxyPlatform().protocolDetectorService().serverProtocolVersion(event.getTarget().getName());
ProtocolVersion clientProtocolVersion = user.getProtocolInfo().protocolVersion();
List<ProtocolPathEntry> protocols = Via.getManager().getProtocolManager().getProtocolPath(clientProtocolVersion, serverProtocolVersion);
// Check if ViaVersion can support that version
try {
Handshake handshake = (Handshake) GET_HANDSHAKE.invoke(event.getPlayer().getPendingConnection());
handshake.setProtocolVersion(protocols == null ? clientProtocolVersion.getVersion() : serverProtocolVersion.getVersion());
} catch (Throwable e) {
Via.getPlatform().getLogger().log(Level.SEVERE, "Error setting handshake version", e);
}
}
@EventHandler(priority = -120)
public void onServerConnected(ServerConnectedEvent event) {
try {
checkServerChange(event, Via.getManager().getConnectionManager().getConnectedClient(event.getPlayer().getUniqueId()));
} catch (Throwable e) {
Via.getPlatform().getLogger().log(Level.SEVERE, "Failed to handle server switch", e);
}
}
@EventHandler(priority = -120)
public void onServerSwitch(ServerSwitchEvent event) {
// Update entity id
UserConnection userConnection = Via.getManager().getConnectionManager().getConnectedClient(event.getPlayer().getUniqueId());
if (userConnection == null) {
return;
}
int playerId;
try {
playerId = Via.getManager().getProviders().get(EntityIdProvider.class).getEntityId(userConnection);
} catch (Exception ignored) {
return;
}
for (EntityTracker tracker : userConnection.getEntityTrackers()) {
tracker.setClientEntityId(playerId);
}
// For ViaRewind
for (StorableObject object : userConnection.getStoredObjects().values()) {
if (object instanceof ClientEntityIdChangeListener listener) {
listener.setClientEntityId(playerId);
}
}
}
public void checkServerChange(ServerConnectedEvent event, UserConnection user) throws Throwable {
if (user == null) {
return;
}
BungeeStorage storage = user.get(BungeeStorage.class);
if (storage == null) {
return;
}
Server server = event.getServer();
if (server == null || server.getInfo().getName().equals(storage.getCurrentServer())) {
return;
}
// Clear auto-team
EntityTracker1_9 oldEntityTracker = user.getEntityTracker(Protocol1_8To1_9.class);
if (oldEntityTracker != null && oldEntityTracker.isAutoTeam() && oldEntityTracker.isTeamExists()) {
oldEntityTracker.sendTeamPacket(false, true);
}
String serverName = server.getInfo().getName();
storage.setCurrentServer(serverName);
ProtocolVersion serverProtocolVersion = Via.proxyPlatform().protocolDetectorService().serverProtocolVersion(serverName);
if (serverProtocolVersion.olderThanOrEqualTo(ProtocolVersion.v1_8) && storage.getBossbar() != null) { // 1.8 doesn't have BossBar packet
// This ensures we can encode it properly as only the 1.9 protocol is currently implemented.
if (user.getProtocolInfo().getPipeline().contains(Protocol1_8To1_9.class)) {
for (UUID uuid : storage.getBossbar()) {
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9.BOSS_EVENT, null, user);
wrapper.write(Types.UUID, uuid);
wrapper.write(Types.VAR_INT, 1); // remove
wrapper.send(Protocol1_8To1_9.class);
}
}
storage.getBossbar().clear();
}
ProtocolInfo info = user.getProtocolInfo();
ProtocolVersion previousServerProtocol = info.serverProtocolVersion();
// Refresh the pipes
List<ProtocolPathEntry> protocolPath = Via.getManager().getProtocolManager().getProtocolPath(info.protocolVersion(), serverProtocolVersion);
ProtocolPipeline pipeline = user.getProtocolInfo().getPipeline();
user.clearStoredObjects(true);
pipeline.cleanPipes();
if (protocolPath != null) {
info.setServerProtocolVersion(serverProtocolVersion);
pipeline.add(protocolPath.stream().map(ProtocolPathEntry::protocol).collect(Collectors.toList()));
} else {
// TODO Check Bungee Supported Protocols? *shrugs*
serverProtocolVersion = info.protocolVersion();
info.setServerProtocolVersion(serverProtocolVersion);
}
// Add version-specific base Protocol
pipeline.add(Via.getManager().getProtocolManager().getBaseProtocol(serverProtocolVersion));
// Workaround 1.13 server change
boolean toNewId = previousServerProtocol.olderThan(ProtocolVersion.v1_13) && serverProtocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_13);
boolean toOldId = previousServerProtocol.newerThanOrEqualTo(ProtocolVersion.v1_13) && serverProtocolVersion.olderThan(ProtocolVersion.v1_13);
if (previousServerProtocol.isKnown() && (toNewId || toOldId)) {
Collection<String> registeredChannels = (Collection<String>) GET_REGISTERED_CHANNELS.invoke(event.getPlayer().getPendingConnection());
if (!registeredChannels.isEmpty()) {
Collection<String> newChannels = new HashSet<>();
for (Iterator<String> iterator = registeredChannels.iterator(); iterator.hasNext(); ) {
String channel = iterator.next();
String oldChannel = channel;
if (toNewId) {
channel = ItemPacketRewriter1_13.getNewPluginChannelId(channel);
} else {
channel = ItemPacketRewriter1_13.getOldPluginChannelId(channel);
}
if (channel == null) {
iterator.remove();
continue;
}
if (!oldChannel.equals(channel)) {
iterator.remove();
newChannels.add(channel);
}
}
registeredChannels.addAll(newChannels);
}
PluginMessage brandMessage = (PluginMessage) GET_BRAND_MESSAGE.invoke(event.getPlayer().getPendingConnection());
if (brandMessage != null) {
String channel = brandMessage.getTag();
if (toNewId) {
channel = ItemPacketRewriter1_13.getNewPluginChannelId(channel);
} else {
channel = ItemPacketRewriter1_13.getOldPluginChannelId(channel);
}
if (channel != null) {
brandMessage.setTag(channel);
}
}
}
user.put(storage);
user.setActive(protocolPath != null);
ProxiedPlayer player = storage.getPlayer();
EntityTracker1_9 newTracker = user.getEntityTracker(Protocol1_8To1_9.class);
if (newTracker != null && Via.getConfig().isAutoTeam()) {
String currentTeam = null;
for (Team team : player.getScoreboard().getTeams()) {
if (team.getPlayers().contains(info.getUsername())) {
currentTeam = team.getName();
}
}
// Reinitialize auto-team
newTracker.setAutoTeam(true);
if (currentTeam == null) {
// Send auto-team as it was cleared above
newTracker.sendTeamPacket(true, true);
newTracker.setCurrentTeam("viaversion");
} else {
// Auto-team will be sent when bungee send remove packet
newTracker.setAutoTeam(Via.getConfig().isAutoTeam());
newTracker.setCurrentTeam(currentTeam);
}
}
Object wrapper = GET_CHANNEL_WRAPPER.invoke(player);
SET_VERSION.invoke(wrapper, serverProtocolVersion.getVersion());
Object entityMap = GET_ENTITY_MAP.invoke(serverProtocolVersion.getVersion());
SET_ENTITY_REWRITE.invoke(player, entityMap);
}
}

View File

@ -1,58 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.listeners;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_9;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.storage.EntityTracker1_9;
import java.util.Collections;
import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
/*
* This patches https://github.com/ViaVersion/ViaVersion/issues/555
*/
public class ElytraPatch implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void onServerConnected(ServerConnectedEvent event) {
UserConnection user = Via.getManager().getConnectionManager().getConnectedClient(event.getPlayer().getUniqueId());
if (user == null) return;
if (user.getProtocolInfo().getPipeline().contains(Protocol1_8To1_9.class)) {
EntityTracker1_9 tracker = user.getEntityTracker(Protocol1_8To1_9.class);
int entityId = tracker.getProvidedEntityId();
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9.SET_ENTITY_DATA, null, user);
wrapper.write(Types.VAR_INT, entityId);
wrapper.write(Types1_9.ENTITY_DATA_LIST, Collections.singletonList(new EntityData(0, EntityDataTypes1_9.BYTE, (byte) 0)));
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
}
}

View File

@ -1,35 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.listeners;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.update.UpdateUtil;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
public class UpdateListener implements Listener {
@EventHandler
public void onJoin(PostLoginEvent e) {
if (e.getPlayer().hasPermission("viaversion.update")
&& Via.getConfig().isCheckForUpdates()) {
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId());
}
}
}

View File

@ -1,48 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.platform;
import com.viaversion.viaversion.ViaAPIBase;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bungee.service.ProtocolDetectorService;
import io.netty.buffer.ByteBuf;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BungeeViaAPI extends ViaAPIBase<ProxiedPlayer> {
@Override
public ProtocolVersion getPlayerProtocolVersion(ProxiedPlayer player) {
return getPlayerProtocolVersion(player.getUniqueId());
}
@Override
public void sendRawPacket(ProxiedPlayer player, ByteBuf packet) throws IllegalArgumentException {
sendRawPacket(player.getUniqueId(), packet);
}
/**
* Forces ViaVersion to probe a server
*
* @param serverInfo The serverinfo to probe
*/
public void probeServer(ServerInfo serverInfo) {
((ProtocolDetectorService) Via.proxyPlatform().protocolDetectorService()).probeServer(serverInfo);
}
}

View File

@ -1,124 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.platform;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bungee.providers.BungeeVersionProvider;
import com.viaversion.viaversion.configuration.AbstractViaConfig;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class BungeeViaConfig extends AbstractViaConfig {
private static final List<String> UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "quick-move-action-fix", "velocity-ping-interval", "velocity-ping-save", "velocity-servers", "blockconnection-method", "change-1_9-hitbox", "change-1_14-hitbox");
private int bungeePingInterval;
private boolean bungeePingSave;
private Map<String, Integer> bungeeServerProtocols;
public BungeeViaConfig(File folder, Logger logger) {
super(new File(folder, "config.yml"), logger);
}
@Override
protected void loadFields() {
super.loadFields();
bungeePingInterval = getInt("bungee-ping-interval", 60);
bungeePingSave = getBoolean("bungee-ping-save", true);
bungeeServerProtocols = get("bungee-servers", new HashMap<>());
}
@Override
protected void handleConfig(Map<String, Object> config) {
// Parse servers
Map<String, Object> servers;
if (!(config.get("bungee-servers") instanceof Map)) {
servers = new HashMap<>();
} else {
servers = (Map) config.get("bungee-servers");
}
// Convert any bad Protocol Ids
for (Map.Entry<String, Object> entry : new HashSet<>(servers.entrySet())) {
if (!(entry.getValue() instanceof Integer)) {
if (entry.getValue() instanceof String stringValue) {
ProtocolVersion found = ProtocolVersion.getClosest(stringValue);
if (found != null) {
servers.put(entry.getKey(), found.getVersion());
} else {
servers.remove(entry.getKey()); // Remove!
}
} else {
servers.remove(entry.getKey()); // Remove!
}
}
}
// Ensure default exists
if (!servers.containsKey("default")) {
servers.put("default", BungeeVersionProvider.getLowestSupportedVersion().getVersion());
}
// Put back
config.put("bungee-servers", servers);
}
@Override
public List<String> getUnsupportedOptions() {
return UNSUPPORTED;
}
@Override
public boolean isItemCache() {
return false;
}
@Override
public boolean isNMSPlayerTicking() {
return false;
}
/**
* What is the interval for checking servers via ping
* -1 for disabled
*
* @return Ping interval in seconds
*/
public int getBungeePingInterval() {
return bungeePingInterval;
}
/**
* Should the bungee ping be saved to the config on change.
*
* @return True if it should save
*/
public boolean isBungeePingSave() {
return bungeePingSave;
}
/**
* Get the listed server protocols in the config.
* default will be listed as default.
*
* @return Map of String, Integer
*/
public Map<String, Integer> getBungeeServerProtocols() {
return bungeeServerProtocols;
}
}

View File

@ -1,186 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.platform;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.platform.ViaInjector;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bungee.handlers.BungeeChannelInitializer;
import com.viaversion.viaversion.util.ReflectionUtil;
import com.viaversion.viaversion.util.SetWrapper;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import net.md_5.bungee.api.ProxyServer;
public class BungeeViaInjector implements ViaInjector {
private static final Field LISTENERS_FIELD;
private final List<Channel> injectedChannels = new ArrayList<>();
static {
try {
LISTENERS_FIELD = ProxyServer.getInstance().getClass().getDeclaredField("listeners");
LISTENERS_FIELD.setAccessible(true);
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Unable to access listeners field.", e);
}
}
@Override
public void inject() throws ReflectiveOperationException {
Set<Channel> listeners = (Set<Channel>) LISTENERS_FIELD.get(ProxyServer.getInstance());
// Iterate through current list
for (Channel channel : listeners) {
injectChannel(channel);
}
// Inject the list
Set<Channel> wrapper = new SetWrapper<>(listeners, channel -> {
try {
injectChannel(channel);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
LISTENERS_FIELD.set(ProxyServer.getInstance(), wrapper);
}
@Override
public void uninject() {
Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Bungee without a reboot!");
}
private void injectChannel(Channel channel) throws ReflectiveOperationException {
List<String> names = channel.pipeline().names();
ChannelHandler bootstrapAcceptor = null;
for (String name : names) {
ChannelHandler handler = channel.pipeline().get(name);
try {
ReflectionUtil.get(handler, "childHandler", ChannelInitializer.class);
bootstrapAcceptor = handler;
} catch (Exception e) {
// Not this one
}
}
// Default to first
if (bootstrapAcceptor == null) {
bootstrapAcceptor = channel.pipeline().first();
}
if (bootstrapAcceptor.getClass().getName().equals("net.md_5.bungee.query.QueryHandler")) {
return;
}
try {
ChannelInitializer<Channel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
ChannelInitializer<Channel> newInit = new BungeeChannelInitializer(oldInit);
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
this.injectedChannels.add(channel);
} catch (NoSuchFieldException ignored) {
throw new RuntimeException("Unable to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName());
}
}
@Override
public ProtocolVersion getServerProtocolVersion() throws ReflectiveOperationException {
return ProtocolVersion.getProtocol(getBungeeSupportedVersions().get(0));
}
@Override
public SortedSet<ProtocolVersion> getServerProtocolVersions() throws ReflectiveOperationException {
final SortedSet<ProtocolVersion> versions = new ObjectLinkedOpenHashSet<>();
for (final Integer version : getBungeeSupportedVersions()) {
versions.add(ProtocolVersion.getProtocol(version));
}
return versions;
}
private List<Integer> getBungeeSupportedVersions() throws ReflectiveOperationException {
return ReflectionUtil.getStatic(Class.forName("net.md_5.bungee.protocol.ProtocolConstants"), "SUPPORTED_VERSION_IDS", List.class);
}
@Override
public JsonObject getDump() {
JsonObject data = new JsonObject();
// Generate information about current injections
JsonArray injectedChannelInitializers = new JsonArray();
for (Channel channel : this.injectedChannels) {
JsonObject channelInfo = new JsonObject();
channelInfo.addProperty("channelClass", channel.getClass().getName());
// Get information about the pipes for this channel
JsonArray pipeline = new JsonArray();
for (String pipeName : channel.pipeline().names()) {
JsonObject handlerInfo = new JsonObject();
handlerInfo.addProperty("name", pipeName);
ChannelHandler channelHandler = channel.pipeline().get(pipeName);
if (channelHandler == null) {
handlerInfo.addProperty("status", "INVALID");
continue;
}
handlerInfo.addProperty("class", channelHandler.getClass().getName());
try {
Object child = ReflectionUtil.get(channelHandler, "childHandler", ChannelInitializer.class);
handlerInfo.addProperty("childClass", child.getClass().getName());
if (child instanceof BungeeChannelInitializer bungeeChannelInitializer) {
handlerInfo.addProperty("oldInit", bungeeChannelInitializer.getOriginal().getClass().getName());
}
} catch (ReflectiveOperationException e) {
// Don't display
}
pipeline.add(handlerInfo);
}
channelInfo.add("pipeline", pipeline);
injectedChannelInitializers.add(channelInfo);
}
data.add("injectedChannelInitializers", injectedChannelInitializers);
try {
Object list = LISTENERS_FIELD.get(ProxyServer.getInstance());
data.addProperty("currentList", list.getClass().getName());
if (list instanceof SetWrapper<?> wrapper) {
data.addProperty("wrappedList", wrapper.originalSet().getClass().getName());
}
} catch (ReflectiveOperationException ignored) {
// Ignored
}
return data;
}
}

View File

@ -1,98 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.platform;
import com.viaversion.viaversion.BungeePlugin;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.platform.ViaPlatformLoader;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.protocol.version.VersionProvider;
import com.viaversion.viaversion.bungee.handlers.BungeeServerHandler;
import com.viaversion.viaversion.bungee.listeners.ElytraPatch;
import com.viaversion.viaversion.bungee.listeners.UpdateListener;
import com.viaversion.viaversion.bungee.providers.BungeeBossBarProvider;
import com.viaversion.viaversion.bungee.providers.BungeeEntityIdProvider;
import com.viaversion.viaversion.bungee.providers.BungeeMainHandProvider;
import com.viaversion.viaversion.bungee.providers.BungeeVersionProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.BossBarProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.EntityIdProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.MainHandProvider;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.scheduler.ScheduledTask;
public class BungeeViaLoader implements ViaPlatformLoader {
private final Set<Listener> listeners = new HashSet<>();
private final Set<ScheduledTask> tasks = new HashSet<>();
private final BungeePlugin plugin;
public BungeeViaLoader(BungeePlugin plugin) {
this.plugin = plugin;
}
private void registerListener(Listener listener) {
listeners.add(listener);
ProxyServer.getInstance().getPluginManager().registerListener(plugin, listener);
}
@Override
public void load() {
// Listeners
registerListener(plugin);
registerListener(new UpdateListener());
registerListener(new BungeeServerHandler());
final ProtocolVersion protocolVersion = Via.getAPI().getServerVersion().lowestSupportedProtocolVersion();
if (protocolVersion.olderThan(ProtocolVersion.v1_9)) {
registerListener(new ElytraPatch());
}
// Providers
Via.getManager().getProviders().use(VersionProvider.class, new BungeeVersionProvider());
Via.getManager().getProviders().use(EntityIdProvider.class, new BungeeEntityIdProvider());
if (protocolVersion.olderThan(ProtocolVersion.v1_9)) {
Via.getManager().getProviders().use(BossBarProvider.class, new BungeeBossBarProvider());
Via.getManager().getProviders().use(MainHandProvider.class, new BungeeMainHandProvider());
}
if (plugin.getConf().getBungeePingInterval() > 0) {
tasks.add(plugin.getProxy().getScheduler().schedule(
plugin,
() -> Via.proxyPlatform().protocolDetectorService().probeAllServers(),
0, plugin.getConf().getBungeePingInterval(),
TimeUnit.SECONDS
));
}
}
@Override
public void unload() {
for (Listener listener : listeners) {
ProxyServer.getInstance().getPluginManager().unregisterListener(listener);
}
listeners.clear();
for (ScheduledTask task : tasks) {
task.cancel();
}
tasks.clear();
}
}

View File

@ -1,29 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.platform;
import com.viaversion.viaversion.api.platform.PlatformTask;
import net.md_5.bungee.api.scheduler.ScheduledTask;
public record BungeeViaTask(ScheduledTask task) implements PlatformTask<ScheduledTask> {
@Override
public void cancel() {
task.cancel();
}
}

View File

@ -1,46 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.providers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bungee.storage.BungeeStorage;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.BossBarProvider;
import java.util.UUID;
public class BungeeBossBarProvider extends BossBarProvider {
@Override
public void handleAdd(UserConnection user, UUID barUUID) {
if (user.has(BungeeStorage.class)) {
BungeeStorage storage = user.get(BungeeStorage.class);
// Check if bossbars are supported by bungee, static maybe
if (storage.getBossbar() != null) {
storage.getBossbar().add(barUUID);
}
}
}
@Override
public void handleRemove(UserConnection user, UUID barUUID) {
if (user.has(BungeeStorage.class)) {
BungeeStorage storage = user.get(BungeeStorage.class);
if (storage.getBossbar() != null) {
storage.getBossbar().remove(barUUID);
}
}
}
}

View File

@ -1,44 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.providers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bungee.storage.BungeeStorage;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.EntityIdProvider;
import java.lang.reflect.Method;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BungeeEntityIdProvider extends EntityIdProvider {
private static final Method GET_CLIENT_ENTITY_ID;
static {
try {
GET_CLIENT_ENTITY_ID = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getClientEntityId");
} catch (NoSuchMethodException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public int getEntityId(UserConnection user) throws Exception {
BungeeStorage storage = user.get(BungeeStorage.class);
ProxiedPlayer player = storage.getPlayer();
return (int) GET_CLIENT_ENTITY_ID.invoke(player);
}
}

View File

@ -1,60 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.providers;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.MainHandProvider;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/*
This solves the wrong main hand issue when you join with BungeeCord on a 1.8 server, and switch to a 1.9 or higher.
*/
public class BungeeMainHandProvider extends MainHandProvider {
private static Method getSettings;
private static Method setMainHand;
static {
try {
getSettings = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getSettings");
setMainHand = Class.forName("net.md_5.bungee.protocol.packet.ClientSettings").getDeclaredMethod("setMainHand", int.class);
} catch (Exception ignored) {
}
}
@Override
public void setMainHand(UserConnection user, int hand) {
ProtocolInfo info = user.getProtocolInfo();
if (info == null || info.getUuid() == null) return;
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(info.getUuid());
if (player == null) return;
try {
Object settings = getSettings.invoke(player);
if (settings != null) {
setMainHand.invoke(settings, hand);
}
} catch (IllegalAccessException | InvocationTargetException e) {
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to set main hand for " + player.getName(), e);
}
}
}

View File

@ -1,80 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.providers;
import com.google.common.collect.Lists;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.protocol.version.BaseVersionProvider;
import com.viaversion.viaversion.util.ReflectionUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.protocol.ProtocolConstants;
public class BungeeVersionProvider extends BaseVersionProvider {
@Override
public ProtocolVersion getClosestServerProtocol(UserConnection user) throws Exception {
// TODO Have one constant list forever until restart? (Might limit plugins if they change this)
List<Integer> list = ReflectionUtil.getStatic(ProtocolConstants.class, "SUPPORTED_VERSION_IDS", List.class);
List<Integer> sorted = new ArrayList<>(list);
Collections.sort(sorted);
ProtocolInfo info = user.getProtocolInfo();
// Bungee supports it
final ProtocolVersion clientProtocolVersion = info.protocolVersion();
if (new HashSet<>(sorted).contains(clientProtocolVersion.getVersion())) {
return clientProtocolVersion;
}
// Older than bungee supports, get the lowest version
if (clientProtocolVersion.getVersion() < sorted.get(0)) {
return getLowestSupportedVersion();
}
// Loop through all protocols to get the closest protocol id that bungee supports (and that viaversion does too)
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
// This is more of a workaround for snapshot support by bungee.
for (Integer protocol : Lists.reverse(sorted)) {
if (clientProtocolVersion.getVersion() > protocol && ProtocolVersion.isRegistered(protocol)) {
return ProtocolVersion.getProtocol(protocol);
}
}
Via.getPlatform().getLogger().severe("Panic, no protocol id found for " + clientProtocolVersion);
return clientProtocolVersion;
}
public static ProtocolVersion getLowestSupportedVersion() {
List<Integer> list;
try {
list = ReflectionUtil.getStatic(ProtocolConstants.class, "SUPPORTED_VERSION_IDS", List.class);
return ProtocolVersion.getProtocol(list.get(0));
} catch (NoSuchFieldException | IllegalAccessException ignored) {
// Fallback
return ProtocolVersion.getProtocol(ProxyServer.getInstance().getProtocolVersion());
}
}
}

View File

@ -1,94 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.service;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bungee.platform.BungeeViaConfig;
import com.viaversion.viaversion.bungee.providers.BungeeVersionProvider;
import com.viaversion.viaversion.platform.AbstractProtocolDetectorService;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
public final class ProtocolDetectorService extends AbstractProtocolDetectorService {
public void probeServer(final ServerInfo serverInfo) {
final String serverName = serverInfo.getName();
serverInfo.ping((serverPing, throwable) -> {
// Ensure protocol is positive, some services will return -1
if (throwable != null || serverPing == null || serverPing.getVersion() == null || serverPing.getVersion().getProtocol() <= 0) {
return;
}
final int oldProtocolVersion = serverProtocolVersion(serverName).getVersion();
if (oldProtocolVersion == serverPing.getVersion().getProtocol()) {
// Same value as previously
return;
}
setProtocolVersion(serverName, serverPing.getVersion().getProtocol());
final BungeeViaConfig config = (BungeeViaConfig) Via.getConfig();
if (config.isBungeePingSave()) {
final Map<String, Integer> servers = config.getBungeeServerProtocols();
final Integer protocol = servers.get(serverName);
if (protocol != null && protocol == serverPing.getVersion().getProtocol()) {
return;
}
// Ensure we're the only ones writing to the config
synchronized (Via.getManager().getConfigurationProvider()) {
servers.put(serverName, serverPing.getVersion().getProtocol());
}
config.save();
}
});
}
@Override
public void probeAllServers() {
final Collection<ServerInfo> servers = ProxyServer.getInstance().getServers().values();
final Set<String> serverNames = new HashSet<>(servers.size());
for (final ServerInfo serverInfo : servers) {
probeServer(serverInfo);
serverNames.add(serverInfo.getName());
}
// Remove servers that aren't registered anymore
lock.writeLock().lock();
try {
detectedProtocolIds.keySet().retainAll(serverNames);
} finally {
lock.writeLock().unlock();
}
}
@Override
protected Map<String, Integer> configuredServers() {
return ((BungeeViaConfig) Via.getConfig()).getBungeeServerProtocols();
}
@Override
protected ProtocolVersion lowestSupportedProtocolVersion() {
return BungeeVersionProvider.getLowestSupportedVersion();
}
}

View File

@ -1,95 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.storage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.StorableObject;
import java.lang.reflect.Field;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BungeeStorage implements StorableObject {
private static Field bossField;
static {
try {
Class<?> user = Class.forName("net.md_5.bungee.UserConnection");
bossField = user.getDeclaredField("sentBossBars");
bossField.setAccessible(true);
} catch (ClassNotFoundException e) {
// Not supported *shrug* probably modified
} catch (NoSuchFieldException e) {
// Not supported, old version probably
}
}
private final ProxiedPlayer player;
private String currentServer;
private Set<UUID> bossbar;
public BungeeStorage(ProxiedPlayer player) {
this.player = player;
this.currentServer = "";
// Get bossbar list if it's supported
if (bossField != null) {
try {
bossbar = (Set<UUID>) bossField.get(player);
} catch (IllegalAccessException e) {
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to get bossbar list", e);
}
}
}
public ProxiedPlayer getPlayer() {
return player;
}
public String getCurrentServer() {
return currentServer;
}
public void setCurrentServer(String currentServer) {
this.currentServer = currentServer;
}
public Set<UUID> getBossbar() {
return bossbar;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BungeeStorage that = (BungeeStorage) o;
if (!Objects.equals(player, that.player)) return false;
if (!Objects.equals(currentServer, that.currentServer)) return false;
return Objects.equals(bossbar, that.bossbar);
}
@Override
public int hashCode() {
int result = player != null ? player.hashCode() : 0;
result = 31 * result + (currentServer != null ? currentServer.hashCode() : 0);
result = 31 * result + (bossbar != null ? bossbar.hashCode() : 0);
return result;
}
}

View File

@ -1,81 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bungee.util;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class BungeePipelineUtil {
private static final Method DECODE_METHOD;
private static final Method ENCODE_METHOD;
static {
try {
DECODE_METHOD = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class);
DECODE_METHOD.setAccessible(true);
ENCODE_METHOD = MessageToByteEncoder.class.getDeclaredMethod("encode", ChannelHandlerContext.class, Object.class, ByteBuf.class);
ENCODE_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public static List<Object> callDecode(MessageToMessageDecoder decoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException {
List<Object> output = new ArrayList<>();
try {
BungeePipelineUtil.DECODE_METHOD.invoke(decoder, ctx, input, output);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return output;
}
public static ByteBuf callEncode(MessageToByteEncoder encoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException {
ByteBuf output = ctx.alloc().buffer();
try {
BungeePipelineUtil.ENCODE_METHOD.invoke(encoder, ctx, input, output);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return output;
}
public static ByteBuf decompress(ChannelHandlerContext ctx, ByteBuf bytebuf) {
try {
return (ByteBuf) callDecode((MessageToMessageDecoder) ctx.pipeline().get("decompress"), ctx.pipeline().context("decompress"), bytebuf).get(0);
} catch (InvocationTargetException e) {
e.printStackTrace();
return ctx.alloc().buffer();
}
}
public static ByteBuf compress(ChannelHandlerContext ctx, ByteBuf bytebuf) {
try {
return callEncode((MessageToByteEncoder) ctx.pipeline().get("compress"), ctx.pipeline().context("compress"), bytebuf);
} catch (InvocationTargetException e) {
e.printStackTrace();
return ctx.alloc().buffer();
}
}
}

View File

@ -1,5 +0,0 @@
name: ViaVersion
main: com.viaversion.viaversion.BungeePlugin
description: ${description}
author: _MylesC, creeper123123321, Gerrygames, kennytv, Matsv, EnZaXD, RK_01
version: ${version}

View File

@ -37,7 +37,7 @@ import com.viaversion.viaversion.protocols.v1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14; import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.storage.EntityTracker1_14; import com.viaversion.viaversion.protocols.v1_13_2to1_14.storage.EntityTracker1_14;
import com.viaversion.viaversion.rewriter.EntityRewriter; import com.viaversion.viaversion.rewriter.EntityRewriter;
import java.util.LinkedList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1_13, Protocol1_13_2To1_14> { public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1_13, Protocol1_13_2To1_14> {
@ -184,7 +184,7 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
PacketWrapper metadataPacket = wrapper.create(ClientboundPackets1_14.SET_ENTITY_DATA); PacketWrapper metadataPacket = wrapper.create(ClientboundPackets1_14.SET_ENTITY_DATA);
metadataPacket.write(Types.VAR_INT, entityId); metadataPacket.write(Types.VAR_INT, entityId);
List<EntityData> metadataList = new LinkedList<>(); List<EntityData> metadataList = new ArrayList<>();
if (tracker.clientEntityId() != entityId) { if (tracker.clientEntityId() != entityId) {
metadataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker))); metadataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker)));
} }
@ -242,7 +242,7 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
tracker.setSleeping(entityId, true); tracker.setSleeping(entityId, true);
BlockPosition position = wrapper.read(Types.BLOCK_POSITION1_8); BlockPosition position = wrapper.read(Types.BLOCK_POSITION1_8);
List<EntityData> metadataList = new LinkedList<>(); List<EntityData> metadataList = new ArrayList<>();
metadataList.add(new EntityData(12, Types1_14.ENTITY_DATA_TYPES.optionalBlockPositionType, position)); metadataList.add(new EntityData(12, Types1_14.ENTITY_DATA_TYPES.optionalBlockPositionType, position));
if (tracker.clientEntityId() != entityId) { if (tracker.clientEntityId() != entityId) {
metadataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker))); metadataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker)));

View File

@ -19,8 +19,6 @@ checkerQual = "3.43.0"
# Platforms # Platforms
paper = "1.20.4-R0.1-SNAPSHOT" paper = "1.20.4-R0.1-SNAPSHOT"
legacyBukkit = "1.8.8-R0.1-SNAPSHOT" legacyBukkit = "1.8.8-R0.1-SNAPSHOT"
bungee = "1.20-R0.3-SNAPSHOT"
sponge = "8.0.0"
velocity = "3.1.1" velocity = "3.1.1"
@ -43,8 +41,6 @@ checkerQual = { group = "org.checkerframework", name = "checker-qual", version.r
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" } paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
legacyBukkit = { group = "org.bukkit", name = "bukkit", version.ref = "legacyBukkit" } legacyBukkit = { group = "org.bukkit", name = "bukkit", version.ref = "legacyBukkit" }
bungee = { group = "net.md-5", name = "bungeecord-api", version.ref = "bungee" }
sponge = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" }
velocity = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" } velocity = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }

View File

@ -5,9 +5,6 @@ dependencyResolutionManagement {
repositories { repositories {
maven("https://repo.viaversion.com") maven("https://repo.viaversion.com")
maven("https://repo.papermc.io/repository/maven-public/") maven("https://repo.papermc.io/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots/")
maven("https://repo.spongepowered.org/repository/maven-public/")
maven("https://libraries.minecraft.net")
mavenCentral() mavenCentral()
} }
// only use these repos // only use these repos
@ -33,9 +30,7 @@ setupViaSubproject("api")
setupViaSubproject("common") setupViaSubproject("common")
setupViaSubproject("bukkit") setupViaSubproject("bukkit")
setupViaSubproject("bukkit-legacy") setupViaSubproject("bukkit-legacy")
setupViaSubproject("bungee")
setupViaSubproject("velocity") setupViaSubproject("velocity")
setupViaSubproject("sponge")
setupViaSubproject("fabric") setupViaSubproject("fabric")
setupViaSubproject("template") setupViaSubproject("template")

View File

@ -1,6 +0,0 @@
dependencies {
compileOnlyApi(projects.viaversionCommon)
compileOnly(libs.sponge)
}
publishShadowJar()

View File

@ -1,249 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion;
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.platform.PlatformTask;
import com.viaversion.viaversion.api.platform.ViaPlatform;
import com.viaversion.viaversion.dump.PluginInfo;
import com.viaversion.viaversion.sponge.commands.SpongeCommandHandler;
import com.viaversion.viaversion.sponge.commands.SpongePlayer;
import com.viaversion.viaversion.sponge.platform.SpongeViaAPI;
import com.viaversion.viaversion.sponge.platform.SpongeViaConfig;
import com.viaversion.viaversion.sponge.platform.SpongeViaInjector;
import com.viaversion.viaversion.sponge.platform.SpongeViaLoader;
import com.viaversion.viaversion.sponge.platform.SpongeViaTask;
import com.viaversion.viaversion.sponge.util.LoggerWrapper;
import com.viaversion.viaversion.util.GsonUtil;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.spongepowered.api.Game;
import org.spongepowered.api.Platform;
import org.spongepowered.api.Server;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.Command;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.lifecycle.ConstructPluginEvent;
import org.spongepowered.api.event.lifecycle.StartedEngineEvent;
import org.spongepowered.api.event.lifecycle.StartingEngineEvent;
import org.spongepowered.api.event.lifecycle.StoppingEngineEvent;
import org.spongepowered.api.scheduler.Task;
import org.spongepowered.api.util.Ticks;
import org.spongepowered.plugin.PluginContainer;
import org.spongepowered.plugin.builtin.jvm.Plugin;
import org.spongepowered.plugin.metadata.PluginMetadata;
import org.spongepowered.plugin.metadata.model.PluginContributor;
@Plugin("viaversion")
public class SpongePlugin implements ViaPlatform<Player> {
public static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.builder().extractUrls().build();
private final SpongeViaAPI api = new SpongeViaAPI();
private final PluginContainer container;
private final Game game;
@SuppressWarnings("SpongeLogging")
private final Logger logger;
private SpongeViaConfig conf;
@Inject
@ConfigDir(sharedRoot = false)
private Path configDir;
@Inject
SpongePlugin(final PluginContainer container, final Game game, final org.apache.logging.log4j.Logger logger) {
this.container = container;
this.game = game;
this.logger = new LoggerWrapper(logger);
}
@Listener
public void constructPlugin(ConstructPluginEvent event) {
// Setup Plugin
conf = new SpongeViaConfig(configDir.toFile(), getLogger());
// Init platform
Via.init(ViaManagerImpl.builder()
.platform(this)
.commandHandler(new SpongeCommandHandler())
.injector(new SpongeViaInjector())
.loader(new SpongeViaLoader(this))
.build());
conf.reload();
}
@Listener
public void onServerStart(StartingEngineEvent<Server> event) {
// Can't use the command register event for raw commands...
Sponge.server().commandManager().registrar(Command.Raw.class).get().register(container, (Command.Raw) Via.getManager().getCommandHandler(), "viaversion", "viaver", "vvsponge");
final ViaManagerImpl manager = (ViaManagerImpl) Via.getManager();
manager.init();
}
@Listener
public void onServerStarted(StartedEngineEvent<Server> event) {
final ViaManagerImpl manager = (ViaManagerImpl) Via.getManager();
manager.onServerLoaded();
}
@Listener
public void onServerStop(StoppingEngineEvent<Server> event) {
((ViaManagerImpl) Via.getManager()).destroy();
}
@Override
public String getPlatformName() {
return game.platform().container(Platform.Component.IMPLEMENTATION).metadata().name().orElse("unknown");
}
@Override
public String getPlatformVersion() {
return game.platform().container(Platform.Component.IMPLEMENTATION).metadata().version().toString();
}
@Override
public String getPluginVersion() {
return container.metadata().version().toString();
}
@Override
public PlatformTask runAsync(Runnable runnable) {
final Task task = Task.builder().plugin(container).execute(runnable).build();
return new SpongeViaTask(game.asyncScheduler().submit(task));
}
@Override
public PlatformTask runRepeatingAsync(final Runnable runnable, final long ticks) {
final Task task = Task.builder().plugin(container).execute(runnable).interval(Ticks.of(ticks)).build();
return new SpongeViaTask(game.asyncScheduler().submit(task));
}
@Override
public PlatformTask runSync(Runnable runnable) {
final Task task = Task.builder().plugin(container).execute(runnable).build();
return new SpongeViaTask(game.server().scheduler().submit(task));
}
@Override
public PlatformTask runSync(Runnable runnable, long delay) {
final Task task = Task.builder().plugin(container).execute(runnable).delay(Ticks.of(delay)).build();
return new SpongeViaTask(game.server().scheduler().submit(task));
}
@Override
public PlatformTask runRepeatingSync(Runnable runnable, long period) {
final Task task = Task.builder().plugin(container).execute(runnable).interval(Ticks.of(period)).build();
return new SpongeViaTask(game.server().scheduler().submit(task));
}
@Override
public ViaCommandSender[] getOnlinePlayers() {
Collection<ServerPlayer> players = game.server().onlinePlayers();
ViaCommandSender[] array = new ViaCommandSender[players.size()];
int i = 0;
for (ServerPlayer player : players) {
array[i++] = new SpongePlayer(player);
}
return array;
}
@Override
public void sendMessage(UUID uuid, String message) {
game.server().player(uuid).ifPresent(player -> player.sendMessage(LEGACY_SERIALIZER.deserialize(message)));
}
@Override
public boolean kickPlayer(UUID uuid, String message) {
return game.server().player(uuid).map(player -> {
player.kick(LegacyComponentSerializer.legacySection().deserialize(message));
return true;
}).orElse(false);
}
@Override
public boolean isPluginEnabled() {
return true;
}
@Override
public File getDataFolder() {
return configDir.toFile();
}
@Override
public void onReload() {
logger.severe("ViaVersion is already loaded, this should work fine. If you get any console errors, try rebooting.");
}
@Override
public JsonObject getDump() {
JsonObject platformSpecific = new JsonObject();
List<PluginInfo> plugins = new ArrayList<>();
for (PluginContainer plugin : game.pluginManager().plugins()) {
PluginMetadata metadata = plugin.metadata();
plugins.add(new PluginInfo(
true,
metadata.name().orElse("Unknown"),
metadata.version().toString(),
plugin.instance() != null ? plugin.instance().getClass().getCanonicalName() : "Unknown",
metadata.contributors().stream().map(PluginContributor::name).collect(Collectors.toList())
));
}
platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins));
return platformSpecific;
}
@Override
public boolean hasPlugin(final String name) {
return game.pluginManager().plugin(name).isPresent();
}
@Override
public SpongeViaAPI getApi() {
return api;
}
@Override
public SpongeViaConfig getConf() {
return conf;
}
@Override
public Logger getLogger() {
return logger;
}
public PluginContainer container() {
return container;
}
}

View File

@ -1,71 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.commands;
import com.viaversion.viaversion.commands.ViaCommandHandler;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.api.command.Command;
import org.spongepowered.api.command.CommandCause;
import org.spongepowered.api.command.CommandCompletion;
import org.spongepowered.api.command.CommandResult;
import org.spongepowered.api.command.parameter.ArgumentReader;
public class SpongeCommandHandler extends ViaCommandHandler implements Command.Raw {
@Override
public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) {
String[] args = !arguments.input().isEmpty() ? arguments.input().split(" ") : new String[0];
onCommand(new SpongeCommandSender(cause), args);
return CommandResult.success();
}
@Override
public List<CommandCompletion> complete(CommandCause cause, ArgumentReader.Mutable arguments) {
String[] args = arguments.input().split(" ", -1); // ViaCommandHandler handles empty String in array. -1: do not discard empty strings
return onTabComplete(new SpongeCommandSender(cause), args).stream().map(CommandCompletion::of).collect(Collectors.toList());
}
@Override
public boolean canExecute(CommandCause cause) {
return cause.hasPermission("viaversion.command");
}
@Override
public Optional<Component> shortDescription(CommandCause cause) {
return Optional.of(Component.text("Shows ViaVersion Version and more."));
}
@Override
public Optional<Component> extendedDescription(CommandCause cause) {
return shortDescription(cause);
}
@Override
public Optional<Component> help(@NotNull CommandCause cause) {
return Optional.empty();
}
@Override
public Component usage(CommandCause cause) {
return Component.text("Usage /viaversion");
}
}

View File

@ -1,58 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.commands;
import com.viaversion.viaversion.SpongePlugin;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import java.util.UUID;
import net.kyori.adventure.identity.Identity;
import org.spongepowered.api.command.CommandCause;
import org.spongepowered.api.util.Identifiable;
public class SpongeCommandSender implements ViaCommandSender {
private final CommandCause source;
public SpongeCommandSender(CommandCause source) {
this.source = source;
}
@Override
public boolean hasPermission(String permission) {
return source.hasPermission(permission);
}
@Override
public void sendMessage(String msg) {
source.sendMessage(Identity.nil(), SpongePlugin.LEGACY_SERIALIZER.deserialize(msg));
}
@Override
public UUID getUUID() {
if (source instanceof Identifiable identifiable) {
return identifiable.uniqueId();
} else {
return new UUID(0, 0);
}
}
@Override
public String getName() {
return source.friendlyIdentifier().orElse(source.identifier());
}
}

View File

@ -1,51 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.commands;
import com.viaversion.viaversion.SpongePlugin;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import java.util.UUID;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
public class SpongePlayer implements ViaCommandSender {
private final ServerPlayer player;
public SpongePlayer(ServerPlayer player) {
this.player = player;
}
@Override
public boolean hasPermission(String permission) {
return player.hasPermission(permission);
}
@Override
public void sendMessage(String msg) {
player.sendMessage(SpongePlugin.LEGACY_SERIALIZER.deserialize(msg));
}
@Override
public UUID getUUID() {
return player.uniqueId();
}
@Override
public String getName() {
return player.friendlyIdentifier().orElse(player.identifier());
}
}

View File

@ -1,75 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.handlers;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.connection.UserConnectionImpl;
import com.viaversion.viaversion.platform.WrappedChannelInitializer;
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import java.lang.reflect.Method;
public class SpongeChannelInitializer extends ChannelInitializer<Channel> implements WrappedChannelInitializer {
private static final Method INIT_CHANNEL_METHOD;
private final ChannelInitializer<Channel> original;
static {
try {
INIT_CHANNEL_METHOD = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
INIT_CHANNEL_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public SpongeChannelInitializer(ChannelInitializer<Channel> oldInit) {
this.original = oldInit;
}
@Override
protected void initChannel(Channel channel) throws Exception {
// Ensure ViaVersion is loaded
if (Via.getAPI().getServerVersion().isKnown()
&& channel instanceof SocketChannel) { // channel can be LocalChannel on internal server
UserConnection info = new UserConnectionImpl(channel);
// init protocol
new ProtocolPipelineImpl(info);
// Add originals
INIT_CHANNEL_METHOD.invoke(this.original, channel);
// Add our transformers
MessageToByteEncoder encoder = new SpongeEncodeHandler(info, (MessageToByteEncoder) channel.pipeline().get("encoder"));
ByteToMessageDecoder decoder = new SpongeDecodeHandler(info, (ByteToMessageDecoder) channel.pipeline().get("decoder"));
channel.pipeline().replace("encoder", "encoder", encoder);
channel.pipeline().replace("decoder", "decoder", decoder);
} else {
INIT_CHANNEL_METHOD.invoke(this.original, channel);
}
}
@Override
public ChannelInitializer<Channel> original() {
return original;
}
}

View File

@ -1,66 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.handlers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.exception.CancelCodecException;
import com.viaversion.viaversion.exception.CancelDecoderException;
import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
public class SpongeDecodeHandler extends ByteToMessageDecoder {
private final ByteToMessageDecoder minecraftDecoder;
private final UserConnection info;
public SpongeDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
this.info = info;
this.minecraftDecoder = minecraftDecoder;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> list) throws Exception {
if (!info.checkServerboundPacket()) {
bytebuf.clear(); // Don't accumulate
throw CancelDecoderException.generate(null);
}
ByteBuf transformedBuf = null;
try {
if (info.shouldTransformPacket()) {
transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
info.transformServerbound(transformedBuf, CancelDecoderException::generate);
}
list.addAll(PipelineUtil.callDecode(this.minecraftDecoder, ctx, transformedBuf == null ? bytebuf : transformedBuf));
} finally {
if (transformedBuf != null) {
transformedBuf.release();
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause instanceof CancelCodecException) return;
super.exceptionCaught(ctx, cause);
}
}

View File

@ -1,72 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.handlers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.exception.CancelCodecException;
import com.viaversion.viaversion.exception.CancelEncoderException;
import com.viaversion.viaversion.handlers.ChannelHandlerContextWrapper;
import com.viaversion.viaversion.handlers.ViaCodecHandler;
import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.lang.reflect.InvocationTargetException;
public class SpongeEncodeHandler extends MessageToByteEncoder<Object> implements ViaCodecHandler {
private final UserConnection info;
private final MessageToByteEncoder<?> minecraftEncoder;
public SpongeEncodeHandler(UserConnection info, MessageToByteEncoder<?> minecraftEncoder) {
this.info = info;
this.minecraftEncoder = minecraftEncoder;
}
@Override
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
// handle the packet type
if (!(o instanceof ByteBuf buf)) {
// call minecraft encoder
try {
PipelineUtil.callEncode(this.minecraftEncoder, new ChannelHandlerContextWrapper(ctx, this), o, bytebuf);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Exception cause) {
throw cause;
} else if (e.getCause() instanceof Error cause) {
throw cause;
}
}
} else {
bytebuf.writeBytes(buf);
}
transform(bytebuf);
}
@Override
public void transform(ByteBuf bytebuf) throws Exception {
if (!info.checkClientboundPacket()) throw CancelEncoderException.generate(null);
if (!info.shouldTransformPacket()) return;
info.transformClientbound(bytebuf, CancelEncoderException::generate);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause instanceof CancelCodecException) return;
super.exceptionCaught(ctx, cause);
}
}

View File

@ -1,33 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.listeners;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.update.UpdateUtil;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.network.ServerSideConnectionEvent;
public class UpdateListener {
@Listener
public void onJoin(ServerSideConnectionEvent.Join join) {
if (join.player().hasPermission("viaversion.update") && Via.getConfig().isCheckForUpdates()) {
UpdateUtil.sendUpdateMessage(join.player().uniqueId());
}
}
}

View File

@ -1,43 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.listeners;
import com.viaversion.viaversion.SpongePlugin;
import com.viaversion.viaversion.ViaListener;
import com.viaversion.viaversion.api.protocol.Protocol;
import java.lang.reflect.Field;
import org.spongepowered.api.Sponge;
public class ViaSpongeListener extends ViaListener {
private static Field entityIdField;
private final SpongePlugin plugin;
public ViaSpongeListener(SpongePlugin plugin, Class<? extends Protocol> requiredPipeline) {
super(requiredPipeline);
this.plugin = plugin;
}
@Override
public void register() {
if (isRegistered()) return;
Sponge.eventManager().registerListeners(plugin.container(), this);
setRegistered(true);
}
}

View File

@ -1,36 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.platform;
import com.viaversion.viaversion.ViaAPIBase;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.spongepowered.api.entity.living.player.Player;
public class SpongeViaAPI extends ViaAPIBase<Player> {
@Override
public ProtocolVersion getPlayerProtocolVersion(Player player) {
return getPlayerProtocolVersion(player.uniqueId());
}
@Override
public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException {
sendRawPacket(player.uniqueId(), packet);
}
}

View File

@ -1,43 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.platform;
import com.viaversion.viaversion.configuration.AbstractViaConfig;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class SpongeViaConfig extends AbstractViaConfig {
private static final List<String> UNSUPPORTED = Arrays.asList("bungee-ping-interval",
"bungee-ping-save", "bungee-servers", "velocity-ping-interval", "velocity-ping-save", "velocity-servers",
"quick-move-action-fix", "change-1_9-hitbox", "change-1_14-hitbox", "blockconnection-method");
public SpongeViaConfig(File folder, java.util.logging.Logger logger) {
super(new File(folder, "config.yml"), logger);
}
@Override
protected void handleConfig(Map<String, Object> config) {
}
@Override
public List<String> getUnsupportedOptions() {
return UNSUPPORTED;
}
}

View File

@ -1,70 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.platform;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.platform.LegacyViaInjector;
import com.viaversion.viaversion.platform.WrappedChannelInitializer;
import com.viaversion.viaversion.sponge.handlers.SpongeChannelInitializer;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.MinecraftVersion;
import org.spongepowered.api.Sponge;
public class SpongeViaInjector extends LegacyViaInjector {
@Override
public ProtocolVersion getServerProtocolVersion() throws ReflectiveOperationException {
MinecraftVersion version = Sponge.platform().minecraftVersion();
// 'protocolVersion' method was exposed to the API in a 1.19.4 build and 'getProtocol' no longer exists in the impl.
try {
return ProtocolVersion.getProtocol((int) version.getClass().getDeclaredMethod("getProtocol").invoke(version));
} catch (NoSuchMethodException e) {
return ProtocolVersion.getProtocol((int) version.getClass().getDeclaredMethod("protocolVersion").invoke(version));
}
}
@Override
protected @Nullable Object getServerConnection() throws ReflectiveOperationException {
Class<?> serverClazz = Class.forName("net.minecraft.server.MinecraftServer");
return serverClazz.getDeclaredMethod("getConnection").invoke(Sponge.server());
}
@Override
protected WrappedChannelInitializer createChannelInitializer(ChannelInitializer<Channel> oldInitializer) {
return new SpongeChannelInitializer(oldInitializer);
}
@Override
protected void blame(ChannelHandler bootstrapAcceptor) {
throw new RuntimeException("Unable to find core component 'childHandler', please check your plugins. Issue: " + bootstrapAcceptor.getClass().getName());
}
@Override
public String getEncoderName() {
return "encoder";
}
@Override
public String getDecoderName() {
return "decoder";
}
}

View File

@ -1,61 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.platform;
import com.viaversion.viaversion.SpongePlugin;
import com.viaversion.viaversion.api.platform.PlatformTask;
import com.viaversion.viaversion.api.platform.ViaPlatformLoader;
import com.viaversion.viaversion.sponge.listeners.UpdateListener;
import java.util.HashSet;
import java.util.Set;
import org.spongepowered.api.Sponge;
public class SpongeViaLoader implements ViaPlatformLoader {
private final SpongePlugin plugin;
private final Set<Object> listeners = new HashSet<>();
private final Set<PlatformTask> tasks = new HashSet<>();
public SpongeViaLoader(SpongePlugin plugin) {
this.plugin = plugin;
}
private void registerListener(Object listener) {
Sponge.eventManager().registerListeners(plugin.container(), storeListener(listener));
}
private <T> T storeListener(T listener) {
listeners.add(listener);
return listener;
}
@Override
public void load() {
// Update Listener
registerListener(new UpdateListener());
}
@Override
public void unload() {
listeners.forEach(Sponge.eventManager()::unregisterListeners);
listeners.clear();
tasks.forEach(PlatformTask::cancel);
tasks.clear();
}
}

View File

@ -1,29 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.platform;
import com.viaversion.viaversion.api.platform.PlatformTask;
import org.spongepowered.api.scheduler.ScheduledTask;
public record SpongeViaTask(ScheduledTask task) implements PlatformTask<ScheduledTask> {
@Override
public void cancel() {
task.cancel();
}
}

View File

@ -1,85 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.sponge.util;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import org.apache.logging.log4j.Logger;
public class LoggerWrapper extends java.util.logging.Logger {
private final Logger base;
public LoggerWrapper(Logger logger) {
super("logger", null);
this.base = logger;
}
@Override
public void log(LogRecord record) {
log(record.getLevel(), record.getMessage());
}
@Override
public void log(Level level, String msg) {
if (level == Level.FINE)
base.debug(msg);
else if (level == Level.WARNING)
base.warn(msg);
else if (level == Level.SEVERE)
base.error(msg);
else if (level == Level.INFO)
base.info(msg);
else
base.trace(msg);
}
@Override
public void log(Level level, String msg, Object param1) {
if (level == Level.FINE)
base.debug(msg, param1);
else if (level == Level.WARNING)
base.warn(msg, param1);
else if (level == Level.SEVERE)
base.error(msg, param1);
else if (level == Level.INFO)
base.info(msg, param1);
else
base.trace(msg, param1);
}
@Override
public void log(Level level, String msg, Object[] params) {
log(level, MessageFormat.format(msg, params)); // workaround not formatting correctly
}
@Override
public void log(Level level, String msg, Throwable params) {
if (level == Level.FINE)
base.debug(msg, params);
else if (level == Level.WARNING)
base.warn(msg, params);
else if (level == Level.SEVERE)
base.error(msg, params);
else if (level == Level.INFO)
base.info(msg, params);
else
base.trace(msg, params);
}
}

View File

@ -1,62 +0,0 @@
{
"loader": {
"name": "java_plain",
"version": "1.0"
},
"license": "GNU GPLv3",
"global": {
"version": "${version}",
"links": {
"homepage": "https://viaversion.com/",
"source": "https://github.com/ViaVersion/ViaVersion",
"issues": "https://github.com/ViaVersion/ViaVersion/issues"
},
"contributors": [
{
"name": "_MylesC",
"description": "Maintainer"
},
{
"name": "creeper123123321",
"description": "Contributor"
},
{
"name": "Gerrygames",
"description": "Contributor"
},
{
"name": "kennytv",
"description": "Maintainer"
},
{
"name": "Matsv",
"description": "Contributor"
},
{
"name": "EnZaXD",
"description": "Contributor"
},
{
"name": "RK_01",
"description": "Contributor"
}
],
"dependencies": [
{
"id": "spongeapi",
"version": "8.0.0"
}
],
"branding": {
"logo": "assets/viaversion/textures/logo.png"
}
},
"plugins": [
{
"id": "viaversion",
"name": "ViaVersion",
"entrypoint": "com.viaversion.viaversion.SpongePlugin",
"description": "${description}"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -6,10 +6,8 @@ plugins {
dependencies { dependencies {
api(projects.viaversionCommon) api(projects.viaversionCommon)
api(projects.viaversionBukkit) api(projects.viaversionBukkit)
api(projects.viaversionBungee)
api(projects.viaversionFabric)
api(projects.viaversionSponge)
api(projects.viaversionVelocity) api(projects.viaversionVelocity)
api(projects.viaversionFabric)
} }
tasks { tasks {