Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-26 16:12:42 +01:00
inject into velocity backend (currently broken)
Add client-side mode for UserConnection remove unused code fix duplicate method on rebase
Dieser Commit ist enthalten in:
Ursprung
69c8cf8ffb
Commit
4813cc3077
@ -61,7 +61,7 @@ public class BukkitEncodeHandler extends MessageToByteEncoder implements ViaHand
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transform(ByteBuf bytebuf) throws Exception {
|
public void transform(ByteBuf bytebuf) throws Exception {
|
||||||
info.checkOutgoingPacket();
|
if (!info.checkOutgoingPacket()) throw CancelEncoderException.generate(null);
|
||||||
if (!info.shouldTransformPacket()) return;
|
if (!info.shouldTransformPacket()) return;
|
||||||
info.transformOutgoing(bytebuf, CancelEncoderException::generate);
|
info.transformOutgoing(bytebuf, CancelEncoderException::generate);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
|
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
|
||||||
info.checkOutgoingPacket();
|
if (!info.checkOutgoingPacket()) throw CancelEncoderException.generate(null);
|
||||||
if (!info.shouldTransformPacket()) {
|
if (!info.shouldTransformPacket()) {
|
||||||
out.add(bytebuf.retain());
|
out.add(bytebuf.retain());
|
||||||
return;
|
return;
|
||||||
|
@ -18,7 +18,6 @@ import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
|||||||
import us.myles.ViaVersion.util.PipelineUtil;
|
import us.myles.ViaVersion.util.PipelineUtil;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -29,6 +28,7 @@ public class UserConnection {
|
|||||||
private final Channel channel;
|
private final Channel channel;
|
||||||
private ProtocolInfo protocolInfo;
|
private ProtocolInfo protocolInfo;
|
||||||
Map<Class, StoredObject> storedObjects = new ConcurrentHashMap<>();
|
Map<Class, StoredObject> storedObjects = new ConcurrentHashMap<>();
|
||||||
|
private final boolean clientSide;
|
||||||
private boolean active = true;
|
private boolean active = true;
|
||||||
private boolean pendingDisconnect;
|
private boolean pendingDisconnect;
|
||||||
private Object lastPacket;
|
private Object lastPacket;
|
||||||
@ -42,8 +42,23 @@ public class UserConnection {
|
|||||||
private int secondsObserved;
|
private int secondsObserved;
|
||||||
private int warnings;
|
private int warnings;
|
||||||
|
|
||||||
public UserConnection(@Nullable Channel channel) {
|
/**
|
||||||
|
* Creates an UserConnection. When it's a client-side connection, some method behaviors are modified.
|
||||||
|
* @param channel netty channel.
|
||||||
|
* @param clientSide true if it's a client-side connection
|
||||||
|
*/
|
||||||
|
public UserConnection(@Nullable Channel channel, boolean clientSide) {
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
|
this.clientSide = clientSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @see #UserConnection(Channel, boolean)
|
||||||
|
* @param channel
|
||||||
|
*/
|
||||||
|
public UserConnection(@Nullable Channel channel) {
|
||||||
|
this(channel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,12 +106,24 @@ public class UserConnection {
|
|||||||
* @param packet The raw packet to send
|
* @param packet The raw packet to send
|
||||||
* @param currentThread Should it run in the same thread
|
* @param currentThread Should it run in the same thread
|
||||||
*/
|
*/
|
||||||
public void sendRawPacket(ByteBuf packet, boolean currentThread) {
|
public void sendRawPacket(final ByteBuf packet, boolean currentThread) {
|
||||||
ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
|
Runnable act;
|
||||||
if (currentThread) {
|
if (clientSide) {
|
||||||
channel.pipeline().context(handler).writeAndFlush(packet);
|
// We'll just assume that Via decoder isn't wrapping the original decoder
|
||||||
|
act = () -> getChannel().pipeline()
|
||||||
|
.context(Via.getManager().getInjector().getDecoderName()).fireChannelRead(packet);
|
||||||
} else {
|
} else {
|
||||||
channel.eventLoop().submit(() -> channel.pipeline().context(handler).writeAndFlush(packet));
|
act = () -> channel.pipeline().context(Via.getManager().getInjector().getEncoderName()).writeAndFlush(packet);
|
||||||
|
}
|
||||||
|
if (currentThread) {
|
||||||
|
act.run();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
channel.eventLoop().submit(act);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
packet.release(); // Couldn't schedule
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,11 +133,25 @@ public class UserConnection {
|
|||||||
* @param packet The raw packet to send
|
* @param packet The raw packet to send
|
||||||
* @return ChannelFuture of the packet being sent
|
* @return ChannelFuture of the packet being sent
|
||||||
*/
|
*/
|
||||||
public ChannelFuture sendRawPacketFuture(ByteBuf packet) {
|
public ChannelFuture sendRawPacketFuture(final ByteBuf packet) {
|
||||||
ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
|
if (clientSide) {
|
||||||
|
return sendRawPacketFutureClientSide(packet);
|
||||||
|
} else {
|
||||||
|
return sendRawPacketFutureServerSide(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChannelFuture sendRawPacketFutureServerSide(final ByteBuf packet) {
|
||||||
|
final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
|
||||||
return channel.pipeline().context(handler).writeAndFlush(packet);
|
return channel.pipeline().context(handler).writeAndFlush(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ChannelFuture sendRawPacketFutureClientSide(final ByteBuf packet) {
|
||||||
|
// Assume that decoder isn't wrapping
|
||||||
|
getChannel().pipeline().context(Via.getManager().getInjector().getDecoderName()).fireChannelRead(packet);
|
||||||
|
return getChannel().newSucceededFuture();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a raw packet to the player (netty thread).
|
* Send a raw packet to the player (netty thread).
|
||||||
*
|
*
|
||||||
@ -156,6 +197,7 @@ public class UserConnection {
|
|||||||
* @see #incrementReceived()
|
* @see #incrementReceived()
|
||||||
*/
|
*/
|
||||||
public boolean exceedsMaxPPS() {
|
public boolean exceedsMaxPPS() {
|
||||||
|
if (clientSide) return false; // Don't apply PPS limiting for client-side
|
||||||
ViaVersionConfig conf = Via.getConfig();
|
ViaVersionConfig conf = Via.getConfig();
|
||||||
// Max PPS Checker
|
// Max PPS Checker
|
||||||
if (conf.getMaxPPS() > 0) {
|
if (conf.getMaxPPS() > 0) {
|
||||||
@ -195,14 +237,8 @@ public class UserConnection {
|
|||||||
if (!channel.isOpen() || pendingDisconnect) return;
|
if (!channel.isOpen() || pendingDisconnect) return;
|
||||||
|
|
||||||
pendingDisconnect = true;
|
pendingDisconnect = true;
|
||||||
UUID uuid = protocolInfo.getUuid();
|
|
||||||
if (uuid == null) {
|
|
||||||
channel.close(); // Just disconnect, we don't know what the connection is
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Via.getPlatform().runSync(() -> {
|
Via.getPlatform().runSync(() -> {
|
||||||
if (!Via.getPlatform().kickPlayer(uuid, ChatColor.translateAlternateColorCodes('&', reason))) {
|
if (!Via.getPlatform().disconnect(this, ChatColor.translateAlternateColorCodes('&', reason))) {
|
||||||
channel.close(); // =)
|
channel.close(); // =)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -214,9 +250,20 @@ public class UserConnection {
|
|||||||
* @param packet Raw packet to be sent
|
* @param packet Raw packet to be sent
|
||||||
* @param currentThread If {@code true} executes immediately, {@code false} submits a task to EventLoop
|
* @param currentThread If {@code true} executes immediately, {@code false} submits a task to EventLoop
|
||||||
*/
|
*/
|
||||||
public void sendRawPacketToServer(ByteBuf packet, boolean currentThread) {
|
public void sendRawPacketToServer(final ByteBuf packet, boolean currentThread) {
|
||||||
ByteBuf buf = packet.alloc().buffer();
|
if (clientSide) {
|
||||||
|
sendRawPacketToServerClientSide(packet, currentThread);
|
||||||
|
} else {
|
||||||
|
sendRawPacketToServerServerSide(packet, currentThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendRawPacketToServerServerSide(final ByteBuf packet, boolean currentThread) {
|
||||||
|
final ByteBuf buf = packet.alloc().buffer();
|
||||||
try {
|
try {
|
||||||
|
// We'll use passing through because there are some encoder wrappers
|
||||||
|
ChannelHandlerContext context = PipelineUtil
|
||||||
|
.getPreviousContext(Via.getManager().getInjector().getDecoderName(), channel.pipeline());
|
||||||
try {
|
try {
|
||||||
Type.VAR_INT.writePrimitive(buf, PacketWrapper.PASSTHROUGH_ID);
|
Type.VAR_INT.writePrimitive(buf, PacketWrapper.PASSTHROUGH_ID);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -224,23 +271,18 @@ public class UserConnection {
|
|||||||
Via.getPlatform().getLogger().warning("Type.VAR_INT.write thrown an exception: " + e);
|
Via.getPlatform().getLogger().warning("Type.VAR_INT.write thrown an exception: " + e);
|
||||||
}
|
}
|
||||||
buf.writeBytes(packet);
|
buf.writeBytes(packet);
|
||||||
ChannelHandlerContext context = PipelineUtil
|
Runnable act = () -> {
|
||||||
.getPreviousContext(Via.getManager().getInjector().getDecoderName(), channel.pipeline());
|
|
||||||
if (currentThread) {
|
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
context.fireChannelRead(buf);
|
context.fireChannelRead(buf);
|
||||||
} else {
|
} else {
|
||||||
channel.pipeline().fireChannelRead(buf);
|
channel.pipeline().fireChannelRead(buf);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
if (currentThread) {
|
||||||
|
act.run();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
channel.eventLoop().submit(() -> {
|
channel.eventLoop().submit(act);
|
||||||
if (context != null) {
|
|
||||||
context.fireChannelRead(buf);
|
|
||||||
} else {
|
|
||||||
channel.pipeline().fireChannelRead(buf);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// Couldn't schedule
|
// Couldn't schedule
|
||||||
buf.release();
|
buf.release();
|
||||||
@ -252,6 +294,21 @@ public class UserConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendRawPacketToServerClientSide(final ByteBuf packet, boolean currentThread) {
|
||||||
|
Runnable act = () -> getChannel().pipeline()
|
||||||
|
.context(Via.getManager().getInjector().getEncoderName()).writeAndFlush(packet);
|
||||||
|
if (currentThread) {
|
||||||
|
act.run();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
getChannel().eventLoop().submit(act);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
packet.release(); // Couldn't schedule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a raw packet to the server. It will submit a task to EventLoop.
|
* Sends a raw packet to the server. It will submit a task to EventLoop.
|
||||||
*
|
*
|
||||||
@ -262,11 +319,24 @@ public class UserConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitors serverbound packets.
|
* Monitors incoming packets
|
||||||
*
|
*
|
||||||
* @return false if this packet should be cancelled
|
* @return false if this packet should be cancelled
|
||||||
*/
|
*/
|
||||||
public boolean checkIncomingPacket() {
|
public boolean checkIncomingPacket() {
|
||||||
|
if (clientSide) {
|
||||||
|
return checkClientBound();
|
||||||
|
} else {
|
||||||
|
return checkServerBound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkClientBound() {
|
||||||
|
incrementSent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkServerBound() {
|
||||||
// Ignore if pending disconnect
|
// Ignore if pending disconnect
|
||||||
if (pendingDisconnect) return false;
|
if (pendingDisconnect) return false;
|
||||||
// Increment received + Check PPS
|
// Increment received + Check PPS
|
||||||
@ -274,10 +344,16 @@ public class UserConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitors clientbound packets.
|
* Monitors outgoing packets
|
||||||
|
*
|
||||||
|
* @return false if this packet should be cancelled
|
||||||
*/
|
*/
|
||||||
public void checkOutgoingPacket() {
|
public boolean checkOutgoingPacket() {
|
||||||
incrementSent();
|
if (clientSide) {
|
||||||
|
return checkServerBound();
|
||||||
|
} else {
|
||||||
|
return checkClientBound();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -290,7 +366,8 @@ public class UserConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms the clientbound packet contained in an outgoing ByteBuf.
|
* Transforms the outgoing packet contained in ByteBuf. When clientSide is true, this packet is considered
|
||||||
|
* serverbound.
|
||||||
*
|
*
|
||||||
* @param buf ByteBuf with packet id and packet contents
|
* @param buf ByteBuf with packet id and packet contents
|
||||||
* @param cancelSupplier Function called with original CancelException for generating the Exception used when
|
* @param cancelSupplier Function called with original CancelException for generating the Exception used when
|
||||||
@ -301,11 +378,12 @@ public class UserConnection {
|
|||||||
*/
|
*/
|
||||||
public void transformOutgoing(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception {
|
public void transformOutgoing(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception {
|
||||||
if (!buf.isReadable()) return;
|
if (!buf.isReadable()) return;
|
||||||
transform(buf, Direction.OUTGOING, cancelSupplier);
|
transform(buf, clientSide ? Direction.INCOMING : Direction.OUTGOING, cancelSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms the serverbound packet contained in an incoming ByteBuf.
|
* Transforms the incoming packet contained in ByteBuf. When clientSide is true, this packet is considered
|
||||||
|
* clientbound
|
||||||
*
|
*
|
||||||
* @param buf ByteBuf with packet id and packet contents
|
* @param buf ByteBuf with packet id and packet contents
|
||||||
* @param cancelSupplier Function called with original CancelException for generating the Exception used when
|
* @param cancelSupplier Function called with original CancelException for generating the Exception used when
|
||||||
@ -316,7 +394,7 @@ public class UserConnection {
|
|||||||
*/
|
*/
|
||||||
public void transformIncoming(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception {
|
public void transformIncoming(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception {
|
||||||
if (!buf.isReadable()) return;
|
if (!buf.isReadable()) return;
|
||||||
transform(buf, Direction.INCOMING, cancelSupplier);
|
transform(buf, clientSide ? Direction.OUTGOING : Direction.INCOMING, cancelSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transform(ByteBuf buf, Direction direction, Function<Throwable, Exception> cancelSupplier) throws Exception {
|
private void transform(ByteBuf buf, Direction direction, Function<Throwable, Exception> cancelSupplier) throws Exception {
|
||||||
@ -459,4 +537,12 @@ public class UserConnection {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Long.hashCode(id);
|
return Long.hashCode(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClientSide() {
|
||||||
|
return clientSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldApplyBlockProtocol() {
|
||||||
|
return !clientSide; // Don't apply protocol blocking on client-side
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package us.myles.ViaVersion.api.platform;
|
package us.myles.ViaVersion.api.platform;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import us.myles.ViaVersion.api.Via;
|
||||||
import us.myles.ViaVersion.api.ViaAPI;
|
import us.myles.ViaVersion.api.ViaAPI;
|
||||||
import us.myles.ViaVersion.api.ViaVersionConfig;
|
import us.myles.ViaVersion.api.ViaVersionConfig;
|
||||||
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
||||||
import us.myles.ViaVersion.api.configuration.ConfigurationProvider;
|
import us.myles.ViaVersion.api.configuration.ConfigurationProvider;
|
||||||
|
import us.myles.ViaVersion.api.data.UserConnection;
|
||||||
|
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -121,6 +124,20 @@ public interface ViaPlatform<T> {
|
|||||||
*/
|
*/
|
||||||
boolean kickPlayer(UUID uuid, String message);
|
boolean kickPlayer(UUID uuid, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects an UserConnection for a reason
|
||||||
|
*
|
||||||
|
* @param connection The UserConnection
|
||||||
|
* @param message The message to kick them with
|
||||||
|
* @return True if it was successful
|
||||||
|
*/
|
||||||
|
default boolean disconnect(UserConnection connection, String message) {
|
||||||
|
if (connection.isClientSide()) return false;
|
||||||
|
UUID uuid = connection.get(ProtocolInfo.class).getUuid();
|
||||||
|
if (uuid == null) return false;
|
||||||
|
return kickPlayer(uuid, message);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the plugin is enabled.
|
* Check if the plugin is enabled.
|
||||||
*
|
*
|
||||||
|
@ -165,6 +165,7 @@ public class BaseProtocol1_7 extends SimpleProtocol {
|
|||||||
int protocol = wrapper.user().getProtocolInfo().getProtocolVersion();
|
int protocol = wrapper.user().getProtocolInfo().getProtocolVersion();
|
||||||
if (Via.getConfig().getBlockedProtocols().contains(protocol)) {
|
if (Via.getConfig().getBlockedProtocols().contains(protocol)) {
|
||||||
if (!wrapper.user().getChannel().isOpen()) return;
|
if (!wrapper.user().getChannel().isOpen()) return;
|
||||||
|
if (!wrapper.user().shouldApplyBlockProtocol()) return;
|
||||||
|
|
||||||
PacketWrapper disconnectPacket = new PacketWrapper(0x00, null, wrapper.user()); // Disconnect Packet
|
PacketWrapper disconnectPacket = new PacketWrapper(0x00, null, wrapper.user()); // Disconnect Packet
|
||||||
Protocol1_9To1_8.FIX_JSON.write(disconnectPacket, ChatColor.translateAlternateColorCodes('&', Via.getConfig().getBlockedDisconnectMsg()));
|
Protocol1_9To1_8.FIX_JSON.write(disconnectPacket, ChatColor.translateAlternateColorCodes('&', Via.getConfig().getBlockedDisconnectMsg()));
|
||||||
|
@ -42,7 +42,7 @@ public class SpongeEncodeHandler extends MessageToByteEncoder<Object> implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transform(ByteBuf bytebuf) throws Exception {
|
public void transform(ByteBuf bytebuf) throws Exception {
|
||||||
info.checkOutgoingPacket();
|
if (!info.checkOutgoingPacket()) throw CancelEncoderException.generate(null);
|
||||||
if (!info.shouldTransformPacket()) return;
|
if (!info.shouldTransformPacket()) return;
|
||||||
info.transformOutgoing(bytebuf, CancelEncoderException::generate);
|
info.transformOutgoing(bytebuf, CancelEncoderException::generate);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ public class VelocityPlugin implements ViaPlatform<Player> {
|
|||||||
api = new VelocityViaAPI();
|
api = new VelocityViaAPI();
|
||||||
conf = new VelocityViaConfig(configDir.toFile());
|
conf = new VelocityViaConfig(configDir.toFile());
|
||||||
logger = new LoggerWrapper(loggerslf4j);
|
logger = new LoggerWrapper(loggerslf4j);
|
||||||
connectionManager = new ViaConnectionManager();
|
connectionManager = new VelocityConnectionManager();
|
||||||
Via.init(ViaManager.builder()
|
Via.init(ViaManager.builder()
|
||||||
.platform(this)
|
.platform(this)
|
||||||
.commandHandler(commandHandler)
|
.commandHandler(commandHandler)
|
||||||
|
@ -7,12 +7,14 @@ import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
|
|||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class VelocityChannelInitializer extends ChannelInitializer {
|
public class VelocityChannelInitializer extends ChannelInitializer<Channel> {
|
||||||
private final ChannelInitializer original;
|
private final ChannelInitializer<?> original;
|
||||||
|
private final boolean clientSide;
|
||||||
private static Method initChannel;
|
private static Method initChannel;
|
||||||
|
|
||||||
public VelocityChannelInitializer(ChannelInitializer original) {
|
public VelocityChannelInitializer(ChannelInitializer<?> original, boolean clientSide) {
|
||||||
this.original = original;
|
this.original = original;
|
||||||
|
this.clientSide = clientSide;
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -28,7 +30,7 @@ public class VelocityChannelInitializer extends ChannelInitializer {
|
|||||||
protected void initChannel(Channel channel) throws Exception {
|
protected void initChannel(Channel channel) throws Exception {
|
||||||
initChannel.invoke(original, channel);
|
initChannel.invoke(original, channel);
|
||||||
|
|
||||||
UserConnection user = new UserConnection(channel);
|
UserConnection user = new UserConnection(channel, clientSide);
|
||||||
new ProtocolPipeline(user);
|
new ProtocolPipeline(user);
|
||||||
|
|
||||||
// We need to add a separated handler because Velocity uses pipeline().get(MINECRAFT_DECODER)
|
// We need to add a separated handler because Velocity uses pipeline().get(MINECRAFT_DECODER)
|
||||||
|
@ -3,16 +3,22 @@ package us.myles.ViaVersion.velocity.handlers;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||||
|
import us.myles.ViaVersion.api.PacketWrapper;
|
||||||
import us.myles.ViaVersion.api.data.UserConnection;
|
import us.myles.ViaVersion.api.data.UserConnection;
|
||||||
|
import us.myles.ViaVersion.api.type.Type;
|
||||||
import us.myles.ViaVersion.exception.CancelDecoderException;
|
import us.myles.ViaVersion.exception.CancelDecoderException;
|
||||||
import us.myles.ViaVersion.exception.CancelCodecException;
|
import us.myles.ViaVersion.exception.CancelCodecException;
|
||||||
|
import us.myles.ViaVersion.util.PipelineUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ChannelHandler.Sharable
|
@ChannelHandler.Sharable
|
||||||
public class VelocityDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
public class VelocityDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
||||||
private final UserConnection info;
|
private final UserConnection info;
|
||||||
|
boolean handledCompression;
|
||||||
|
|
||||||
public VelocityDecodeHandler(UserConnection info) {
|
public VelocityDecodeHandler(UserConnection info) {
|
||||||
this.info = info;
|
this.info = info;
|
||||||
@ -28,13 +34,55 @@ public class VelocityDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
|||||||
|
|
||||||
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
|
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
|
||||||
try {
|
try {
|
||||||
info.transformIncoming(transformedBuf, CancelDecoderException::generate);
|
boolean needsCompress = handleCompressionOrder(ctx, draft);
|
||||||
out.add(transformedBuf.retain());
|
|
||||||
|
info.transformIncoming(draft, CancelDecoderException::generate);
|
||||||
|
|
||||||
|
if (needsCompress) {
|
||||||
|
recompress(ctx, draft);
|
||||||
|
}
|
||||||
|
out.add(draft.retain());
|
||||||
} finally {
|
} finally {
|
||||||
transformedBuf.release();
|
transformedBuf.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf draft) throws InvocationTargetException {
|
||||||
|
//if (handledCompression) return false;
|
||||||
|
|
||||||
|
int decoderIndex = ctx.pipeline().names().indexOf("compression-decoder");
|
||||||
|
if (decoderIndex == -1) return false;
|
||||||
|
handledCompression = true;
|
||||||
|
if (decoderIndex > ctx.pipeline().names().indexOf("via-decoder")) {
|
||||||
|
System.out.println("bad decoder order");
|
||||||
|
// Need to decompress this packet due to bad order
|
||||||
|
ByteBuf decompressed = (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder<?>) ctx.pipeline().get("compression-decoder"), ctx, draft).get(0);
|
||||||
|
try {
|
||||||
|
draft.clear().writeBytes(decompressed);
|
||||||
|
} finally {
|
||||||
|
decompressed.release();
|
||||||
|
}
|
||||||
|
ChannelHandler encoder = ctx.pipeline().get("via-encoder");
|
||||||
|
ChannelHandler decoder = ctx.pipeline().get("via-decoder");
|
||||||
|
ctx.pipeline().remove(encoder);
|
||||||
|
ctx.pipeline().remove(decoder);
|
||||||
|
ctx.pipeline().addAfter("compression-encoder", "via-encoder", encoder);
|
||||||
|
ctx.pipeline().addAfter("compression-decoder", "via-decoder", decoder);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recompress(ChannelHandlerContext ctx, ByteBuf draft) throws Exception {
|
||||||
|
ByteBuf compressed = ctx.alloc().buffer();
|
||||||
|
try {
|
||||||
|
PipelineUtil.callEncode((MessageToByteEncoder<?>) ctx.pipeline().get("compression-encoder"), ctx, draft, compressed);
|
||||||
|
draft.clear().writeBytes(compressed);
|
||||||
|
} finally {
|
||||||
|
compressed.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
if (cause instanceof CancelCodecException) return;
|
if (cause instanceof CancelCodecException) return;
|
||||||
|
@ -25,7 +25,7 @@ public class VelocityEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
|
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
|
||||||
info.checkOutgoingPacket();
|
if (!info.checkOutgoingPacket()) throw CancelEncoderException.generate(null);
|
||||||
if (!info.shouldTransformPacket()) {
|
if (!info.shouldTransformPacket()) {
|
||||||
out.add(bytebuf.retain());
|
out.add(bytebuf.retain());
|
||||||
return;
|
return;
|
||||||
@ -46,10 +46,14 @@ public class VelocityEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
|
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf draft) throws InvocationTargetException {
|
||||||
boolean needsCompress = false;
|
//if (handledCompression) return false;
|
||||||
if (!handledCompression
|
|
||||||
&& ctx.pipeline().names().indexOf("compression-encoder") > ctx.pipeline().names().indexOf("via-encoder")) {
|
int encoderIndex = ctx.pipeline().names().indexOf("compression-encoder");
|
||||||
|
if (encoderIndex == -1) return false;
|
||||||
|
handledCompression = true;
|
||||||
|
if (encoderIndex > ctx.pipeline().names().indexOf("via-encoder")) {
|
||||||
|
System.out.println("bad decoder order");
|
||||||
// Need to decompress this packet due to bad order
|
// Need to decompress this packet due to bad order
|
||||||
ByteBuf decompressed = (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder<?>) ctx.pipeline().get("compression-decoder"), ctx, buf).get(0);
|
ByteBuf decompressed = (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder<?>) ctx.pipeline().get("compression-decoder"), ctx, buf).get(0);
|
||||||
try {
|
try {
|
||||||
@ -63,10 +67,9 @@ public class VelocityEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
|||||||
ctx.pipeline().remove(decoder);
|
ctx.pipeline().remove(decoder);
|
||||||
ctx.pipeline().addAfter("compression-encoder", "via-encoder", encoder);
|
ctx.pipeline().addAfter("compression-encoder", "via-encoder", encoder);
|
||||||
ctx.pipeline().addAfter("compression-decoder", "via-decoder", decoder);
|
ctx.pipeline().addAfter("compression-decoder", "via-decoder", decoder);
|
||||||
needsCompress = true;
|
return true;
|
||||||
handledCompression = true;
|
|
||||||
}
|
}
|
||||||
return needsCompress;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recompress(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
|
private void recompress(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package us.myles.ViaVersion.velocity.platform;
|
||||||
|
|
||||||
|
import io.netty.channel.ServerChannel;
|
||||||
|
import us.myles.ViaVersion.api.data.UserConnection;
|
||||||
|
import us.myles.ViaVersion.api.platform.ViaConnectionManager;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class VelocityConnectionManager extends ViaConnectionManager {
|
||||||
|
@Override
|
||||||
|
public void onLoginSuccess(UserConnection connection) {
|
||||||
|
if (connection.isClientSide()) {
|
||||||
|
System.out.println("backend connect!");
|
||||||
|
Objects.requireNonNull(connection, "connection is null!");
|
||||||
|
connections.add(connection);
|
||||||
|
} else {
|
||||||
|
System.out.println("frontend connect!");
|
||||||
|
super.onLoginSuccess(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnect(UserConnection connection) {
|
||||||
|
if (connection.isClientSide()) {
|
||||||
|
System.out.println("backend disconnect!");
|
||||||
|
Objects.requireNonNull(connection, "connection is null!");
|
||||||
|
connections.remove(connection);
|
||||||
|
} else {
|
||||||
|
System.out.println("frontend disconnect!");
|
||||||
|
super.onDisconnect(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,13 +30,25 @@ public class VelocityViaInjector implements ViaInjector {
|
|||||||
return (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get");
|
return (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ChannelInitializer getBackendInitializer() throws Exception {
|
||||||
|
Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class);
|
||||||
|
Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getBackendChannelInitializer");
|
||||||
|
return (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inject() throws Exception {
|
public void inject() throws Exception {
|
||||||
Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class);
|
Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class);
|
||||||
Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer");
|
Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer");
|
||||||
ChannelInitializer originalInitializer = getInitializer();
|
ChannelInitializer originalInitializer = getInitializer();
|
||||||
channelInitializerHolder.getClass().getMethod("set", ChannelInitializer.class)
|
channelInitializerHolder.getClass().getMethod("set", ChannelInitializer.class)
|
||||||
.invoke(channelInitializerHolder, new VelocityChannelInitializer(originalInitializer));
|
.invoke(channelInitializerHolder, new VelocityChannelInitializer(originalInitializer, false));
|
||||||
|
|
||||||
|
|
||||||
|
Object backendInitializerHolder = ReflectionUtil.invoke(connectionManager, "getBackendChannelInitializer");
|
||||||
|
ChannelInitializer backendInitializer = getBackendInitializer();
|
||||||
|
backendInitializerHolder.getClass().getMethod("set", ChannelInitializer.class)
|
||||||
|
.invoke(backendInitializerHolder, new VelocityChannelInitializer(backendInitializer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,7 +26,7 @@ public class VelocityViaLoader implements ViaPlatformLoader {
|
|||||||
if (ProtocolRegistry.SERVER_PROTOCOL < ProtocolVersion.v1_9.getVersion()) {
|
if (ProtocolRegistry.SERVER_PROTOCOL < ProtocolVersion.v1_9.getVersion()) {
|
||||||
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new VelocityMovementTransmitter());
|
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new VelocityMovementTransmitter());
|
||||||
Via.getManager().getProviders().use(BossBarProvider.class, new VelocityBossBarProvider());
|
Via.getManager().getProviders().use(BossBarProvider.class, new VelocityBossBarProvider());
|
||||||
VelocityPlugin.PROXY.getEventManager().register(plugin, new ElytraPatch());
|
//VelocityPlugin.PROXY.getEventManager().register(plugin, new ElytraPatch());
|
||||||
}
|
}
|
||||||
|
|
||||||
Via.getManager().getProviders().use(VersionProvider.class, new VelocityVersionProvider());
|
Via.getManager().getProviders().use(VersionProvider.class, new VelocityVersionProvider());
|
||||||
@ -34,7 +34,7 @@ public class VelocityViaLoader implements ViaPlatformLoader {
|
|||||||
// We don't need main hand patch because Join Game packet makes client send hand data again
|
// We don't need main hand patch because Join Game packet makes client send hand data again
|
||||||
|
|
||||||
VelocityPlugin.PROXY.getEventManager().register(plugin, new UpdateListener());
|
VelocityPlugin.PROXY.getEventManager().register(plugin, new UpdateListener());
|
||||||
VelocityPlugin.PROXY.getEventManager().register(plugin, new VelocityServerHandler());
|
//VelocityPlugin.PROXY.getEventManager().register(plugin, new VelocityServerHandler());
|
||||||
|
|
||||||
int pingInterval = ((VelocityViaConfig) Via.getPlatform().getConf()).getVelocityPingInterval();
|
int pingInterval = ((VelocityViaConfig) Via.getPlatform().getConf()).getVelocityPingInterval();
|
||||||
if (pingInterval > 0) {
|
if (pingInterval > 0) {
|
||||||
|
@ -1,20 +1,46 @@
|
|||||||
package us.myles.ViaVersion.velocity.providers;
|
package us.myles.ViaVersion.velocity.providers;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.ServerConnection;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.ServerChannel;
|
||||||
import us.myles.ViaVersion.VelocityPlugin;
|
import us.myles.ViaVersion.VelocityPlugin;
|
||||||
import us.myles.ViaVersion.api.Via;
|
import us.myles.ViaVersion.api.Via;
|
||||||
import us.myles.ViaVersion.api.data.UserConnection;
|
import us.myles.ViaVersion.api.data.UserConnection;
|
||||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||||
import us.myles.ViaVersion.protocols.base.VersionProvider;
|
import us.myles.ViaVersion.protocols.base.VersionProvider;
|
||||||
import us.myles.ViaVersion.velocity.platform.VelocityViaInjector;
|
import us.myles.ViaVersion.velocity.platform.VelocityViaInjector;
|
||||||
|
import us.myles.ViaVersion.velocity.service.ProtocolDetectorService;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
public class VelocityVersionProvider extends VersionProvider {
|
public class VelocityVersionProvider extends VersionProvider {
|
||||||
|
private static Method getAssociation;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
getAssociation = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection").getMethod("getAssociation");
|
||||||
|
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getServerProtocol(UserConnection user) throws Exception {
|
public int getServerProtocol(UserConnection user) throws Exception {
|
||||||
int playerVersion = user.getProtocolInfo().getProtocolVersion();
|
return user.isClientSide() ? getBackProtocol(user) : getFrontProtocol(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getBackProtocol(UserConnection user) throws Exception {
|
||||||
|
System.out.println("backend protocol!");
|
||||||
|
ChannelHandler mcHandler = user.getChannel().pipeline().get("handler");
|
||||||
|
return ProtocolDetectorService.getProtocolId(
|
||||||
|
((ServerConnection) getAssociation.invoke(mcHandler)).getServerInfo().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getFrontProtocol(UserConnection user) throws Exception {
|
||||||
|
System.out.println("frontend protocol!");
|
||||||
|
int playerVersion = user.get(ProtocolInfo.class).getProtocolVersion();
|
||||||
|
|
||||||
IntStream versions = com.velocitypowered.api.network.ProtocolVersion.SUPPORTED_VERSIONS.stream()
|
IntStream versions = com.velocitypowered.api.network.ProtocolVersion.SUPPORTED_VERSIONS.stream()
|
||||||
.mapToInt(com.velocitypowered.api.network.ProtocolVersion::getProtocol);
|
.mapToInt(com.velocitypowered.api.network.ProtocolVersion::getProtocol);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren