Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-17 05:20:14 +01:00
Integrate BungeeQuack functionality into Velocity
Dieser Commit ist enthalten in:
Ursprung
9b570ff599
Commit
9d5930d96b
@ -31,6 +31,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
private final VelocityServerConnection serverConn;
|
private final VelocityServerConnection serverConn;
|
||||||
private final ClientPlaySessionHandler playerSessionHandler;
|
private final ClientPlaySessionHandler playerSessionHandler;
|
||||||
private final MinecraftConnection playerConnection;
|
private final MinecraftConnection playerConnection;
|
||||||
|
private final BungeeCordMessageResponder bungeecordMessageResponder;
|
||||||
private boolean exceptionTriggered = false;
|
private boolean exceptionTriggered = false;
|
||||||
|
|
||||||
BackendPlaySessionHandler(VelocityServer server, VelocityServerConnection serverConn) {
|
BackendPlaySessionHandler(VelocityServer server, VelocityServerConnection serverConn) {
|
||||||
@ -44,6 +45,9 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
"Initializing BackendPlaySessionHandler with no backing client play session handler!");
|
"Initializing BackendPlaySessionHandler with no backing client play session handler!");
|
||||||
}
|
}
|
||||||
this.playerSessionHandler = (ClientPlaySessionHandler) psh;
|
this.playerSessionHandler = (ClientPlaySessionHandler) psh;
|
||||||
|
|
||||||
|
this.bungeecordMessageResponder = new BungeeCordMessageResponder(server,
|
||||||
|
serverConn.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -86,6 +90,10 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(PluginMessage packet) {
|
public boolean handle(PluginMessage packet) {
|
||||||
|
if (bungeecordMessageResponder.process(packet)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!serverConn.getPlayer().canForwardPluginMessage(serverConn.ensureConnected()
|
if (!serverConn.getPlayer().canForwardPluginMessage(serverConn.ensureConnected()
|
||||||
.getProtocolVersion(), packet)) {
|
.getProtocolVersion(), packet)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -0,0 +1,325 @@
|
|||||||
|
package com.velocitypowered.proxy.connection.backend;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.ServerConnection;
|
||||||
|
import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier;
|
||||||
|
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
||||||
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import com.velocitypowered.api.util.UuidUtils;
|
||||||
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
||||||
|
import com.velocitypowered.proxy.protocol.util.ByteBufDataInput;
|
||||||
|
import com.velocitypowered.proxy.protocol.util.ByteBufDataOutput;
|
||||||
|
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufUtil;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
|
|
||||||
|
class BungeeCordMessageResponder {
|
||||||
|
|
||||||
|
private static final MinecraftChannelIdentifier MODERN_CHANNEL = MinecraftChannelIdentifier
|
||||||
|
.create("bungeecord", "main");
|
||||||
|
private static final LegacyChannelIdentifier LEGACY_CHANNEL =
|
||||||
|
new LegacyChannelIdentifier("BungeeCord");
|
||||||
|
|
||||||
|
private final VelocityServer proxy;
|
||||||
|
private final ConnectedPlayer player;
|
||||||
|
|
||||||
|
BungeeCordMessageResponder(VelocityServer proxy, ConnectedPlayer player) {
|
||||||
|
this.proxy = proxy;
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processConnect(ByteBufDataInput in) {
|
||||||
|
String serverName = in.readUTF();
|
||||||
|
proxy.getServer(serverName).ifPresent(server -> player.createConnectionRequest(server)
|
||||||
|
.fireAndForget());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processConnectOther(ByteBufDataInput in) {
|
||||||
|
String playerName = in.readUTF();
|
||||||
|
String serverName = in.readUTF();
|
||||||
|
|
||||||
|
proxy.getPlayer(playerName).ifPresent(player -> {
|
||||||
|
proxy.getServer(serverName).ifPresent(server -> player.createConnectionRequest(server)
|
||||||
|
.fireAndForget());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processIp(ByteBufDataInput in) {
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
out.writeUTF("IP");
|
||||||
|
out.writeUTF(player.getRemoteAddress().getHostString());
|
||||||
|
out.writeInt(player.getRemoteAddress().getPort());
|
||||||
|
sendResponse(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processPlayerCount(ByteBufDataInput in) {
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
|
String target = in.readUTF();
|
||||||
|
if (target.equals("ALL")) {
|
||||||
|
out.writeUTF("PlayerCount");
|
||||||
|
out.writeUTF("ALL");
|
||||||
|
out.writeInt(proxy.getPlayerCount());
|
||||||
|
} else {
|
||||||
|
proxy.getServer(target).ifPresent(rs -> {
|
||||||
|
int playersOnServer = rs.getPlayersConnected().size();
|
||||||
|
out.writeUTF("PlayerCount");
|
||||||
|
out.writeUTF(rs.getServerInfo().getName());
|
||||||
|
out.writeInt(playersOnServer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf.isReadable()) {
|
||||||
|
sendResponse(buf);
|
||||||
|
} else {
|
||||||
|
buf.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processPlayerList(ByteBufDataInput in) {
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
|
String target = in.readUTF();
|
||||||
|
if (target.equals("ALL")) {
|
||||||
|
out.writeUTF("PlayerList");
|
||||||
|
out.writeUTF("ALL");
|
||||||
|
|
||||||
|
StringJoiner joiner = new StringJoiner(", ");
|
||||||
|
for (Player online : proxy.getAllPlayers()) {
|
||||||
|
joiner.add(online.getUsername());
|
||||||
|
}
|
||||||
|
out.writeUTF(joiner.toString());
|
||||||
|
} else {
|
||||||
|
proxy.getServer(target).ifPresent(info -> {
|
||||||
|
out.writeUTF("PlayerList");
|
||||||
|
out.writeUTF(info.getServerInfo().getName());
|
||||||
|
|
||||||
|
StringJoiner joiner = new StringJoiner(", ");
|
||||||
|
for (Player online : info.getPlayersConnected()) {
|
||||||
|
joiner.add(online.getUsername());
|
||||||
|
}
|
||||||
|
out.writeUTF(joiner.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf.isReadable()) {
|
||||||
|
sendResponse(buf);
|
||||||
|
} else {
|
||||||
|
buf.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processGetServers(ByteBufDataInput in) {
|
||||||
|
StringJoiner joiner = new StringJoiner(", ");
|
||||||
|
for (RegisteredServer server : proxy.getAllServers()) {
|
||||||
|
joiner.add(server.getServerInfo().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
out.writeUTF("GetServers");
|
||||||
|
out.writeUTF(joiner.toString());
|
||||||
|
|
||||||
|
sendResponse(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMessage(ByteBufDataInput in) {
|
||||||
|
String target = in.readUTF();
|
||||||
|
String message = in.readUTF();
|
||||||
|
if (target.equals("ALL")) {
|
||||||
|
for (Player player : proxy.getAllPlayers()) {
|
||||||
|
player.sendMessage(LegacyComponentSerializer.INSTANCE.deserialize(message));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proxy.getPlayer(target).ifPresent(player -> {
|
||||||
|
player.sendMessage(LegacyComponentSerializer.INSTANCE.deserialize(message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processGetServer(ByteBufDataInput in) {
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
|
out.writeUTF("GetServer");
|
||||||
|
out.writeUTF(player.ensureAndGetCurrentServer().getServerInfo().getName());
|
||||||
|
|
||||||
|
sendResponse(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processUuid(ByteBufDataInput in) {
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
|
out.writeUTF("UUID");
|
||||||
|
out.writeUTF(UuidUtils.toUndashed(player.getUniqueId()));
|
||||||
|
|
||||||
|
sendResponse(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processUuidOther(ByteBufDataInput in) {
|
||||||
|
proxy.getPlayer(in.readUTF()).ifPresent(player -> {
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
|
out.writeUTF("UUIDOther");
|
||||||
|
out.writeUTF(player.getUsername());
|
||||||
|
out.writeUTF(UuidUtils.toUndashed(player.getUniqueId()));
|
||||||
|
|
||||||
|
sendResponse(buf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processServerIp(ByteBufDataInput in) {
|
||||||
|
proxy.getServer(in.readUTF()).ifPresent(info -> {
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
|
out.writeUTF("ServerIP");
|
||||||
|
out.writeUTF(info.getServerInfo().getName());
|
||||||
|
out.writeUTF(info.getServerInfo().getAddress().getHostString());
|
||||||
|
out.writeShort(info.getServerInfo().getAddress().getPort());
|
||||||
|
|
||||||
|
sendResponse(buf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processKick(ByteBufDataInput in) {
|
||||||
|
proxy.getPlayer(in.readUTF()).ifPresent(player -> {
|
||||||
|
String kickReason = in.readUTF();
|
||||||
|
player.disconnect(LegacyComponentSerializer.INSTANCE.deserialize(kickReason));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuf prepareForwardMessage(ByteBufDataInput in) {
|
||||||
|
String channel = in.readUTF();
|
||||||
|
short messageLength = in.readShort();
|
||||||
|
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
ByteBufDataOutput forwarded = new ByteBufDataOutput(buf);
|
||||||
|
forwarded.writeUTF(channel);
|
||||||
|
forwarded.writeShort(messageLength);
|
||||||
|
buf.writeBytes(in.unwrap().readSlice(messageLength));
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processForwardToPlayer(ByteBufDataInput in) {
|
||||||
|
proxy.getPlayer(in.readUTF())
|
||||||
|
.flatMap(Player::getCurrentServer)
|
||||||
|
.ifPresent(server -> sendResponse(player, prepareForwardMessage(in)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processForwardToServer(ByteBufDataInput in) {
|
||||||
|
ByteBuf toForward = prepareForwardMessage(in);
|
||||||
|
String target = in.readUTF();
|
||||||
|
if (target.equals("ALL")) {
|
||||||
|
ByteBuf unreleasableForward = Unpooled.unreleasableBuffer(toForward);
|
||||||
|
try {
|
||||||
|
for (RegisteredServer rs : proxy.getAllServers()) {
|
||||||
|
((VelocityRegisteredServer) rs).sendPluginMessage(LEGACY_CHANNEL, unreleasableForward);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
toForward.release();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proxy.getServer(target).ifPresent(rs -> ((VelocityRegisteredServer) rs)
|
||||||
|
.sendPluginMessage(LEGACY_CHANNEL, toForward));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this method will always release the buffer!
|
||||||
|
private void sendResponse(ByteBuf buf) {
|
||||||
|
sendResponse(this.player, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this method will always release the buffer!
|
||||||
|
private static void sendResponse(ConnectedPlayer player, ByteBuf buf) {
|
||||||
|
MinecraftConnection serverConnection = player.ensureAndGetCurrentServer().ensureConnected();
|
||||||
|
String chan = serverConnection.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_13)
|
||||||
|
>= 0 ? MODERN_CHANNEL.getId() : LEGACY_CHANNEL.getId();
|
||||||
|
|
||||||
|
PluginMessage msg = null;
|
||||||
|
boolean released = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
VelocityServerConnection vsc = player.getConnectedServer();
|
||||||
|
if (vsc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftConnection serverConn = vsc.ensureConnected();
|
||||||
|
msg = new PluginMessage(chan, buf);
|
||||||
|
serverConn.write(msg);
|
||||||
|
released = true;
|
||||||
|
} finally {
|
||||||
|
if (!released && msg != null) {
|
||||||
|
msg.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean process(PluginMessage message) {
|
||||||
|
if (!MODERN_CHANNEL.getId().equals(message.getChannel()) && !LEGACY_CHANNEL.getId()
|
||||||
|
.equals(message.getChannel())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBufDataInput in = new ByteBufDataInput(message.content());
|
||||||
|
String subChannel = in.readUTF();
|
||||||
|
if (subChannel.equals("ForwardToPlayer")) {
|
||||||
|
this.processForwardToPlayer(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("Forward")) {
|
||||||
|
this.processForwardToServer(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("Connect")) {
|
||||||
|
this.processConnect(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("ConnectOther")) {
|
||||||
|
this.processConnectOther(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("IP")) {
|
||||||
|
this.processIp(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("PlayerCount")) {
|
||||||
|
this.processPlayerCount(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("PlayerList")) {
|
||||||
|
this.processPlayerList(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("GetServers")) {
|
||||||
|
this.processGetServers(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("Message")) {
|
||||||
|
this.processMessage(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("GetServer")) {
|
||||||
|
this.processGetServer(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("UUID")) {
|
||||||
|
this.processUuid(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("UUIDOther")) {
|
||||||
|
this.processUuidOther(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("ServerIP")) {
|
||||||
|
this.processServerIp(in);
|
||||||
|
}
|
||||||
|
if (subChannel.equals("KickPlayer")) {
|
||||||
|
this.processKick(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,7 @@ import com.velocitypowered.proxy.protocol.packet.Handshake;
|
|||||||
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
||||||
import com.velocitypowered.proxy.protocol.packet.ServerLogin;
|
import com.velocitypowered.proxy.protocol.packet.ServerLogin;
|
||||||
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
@ -210,12 +211,16 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
||||||
|
return sendPluginMessage(identifier, Unpooled.wrappedBuffer(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendPluginMessage(ChannelIdentifier identifier, ByteBuf data) {
|
||||||
Preconditions.checkNotNull(identifier, "identifier");
|
Preconditions.checkNotNull(identifier, "identifier");
|
||||||
Preconditions.checkNotNull(data, "data");
|
Preconditions.checkNotNull(data, "data");
|
||||||
|
|
||||||
MinecraftConnection mc = ensureConnected();
|
MinecraftConnection mc = ensureConnected();
|
||||||
|
|
||||||
PluginMessage message = new PluginMessage(identifier.getId(), Unpooled.wrappedBuffer(data));
|
PluginMessage message = new PluginMessage(identifier.getId(), data);
|
||||||
mc.write(message);
|
mc.write(message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,14 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
return Optional.ofNullable(connectedServer);
|
return Optional.ofNullable(connectedServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VelocityServerConnection ensureAndGetCurrentServer() {
|
||||||
|
VelocityServerConnection con = this.connectedServer;
|
||||||
|
if (con == null) {
|
||||||
|
throw new IllegalStateException("Not connected to server!");
|
||||||
|
}
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GameProfile getGameProfile() {
|
public GameProfile getGameProfile() {
|
||||||
return profile;
|
return profile;
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
package com.velocitypowered.proxy.protocol.util;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper around {@link io.netty.buffer.ByteBuf} that implements the exception-free
|
||||||
|
* {@link ByteArrayDataInput} interface from Guava.
|
||||||
|
*/
|
||||||
|
public class ByteBufDataInput implements ByteArrayDataInput, DataInput {
|
||||||
|
|
||||||
|
private final ByteBuf in;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ByteBufDataInput instance. The ByteBufDataInput simply "borrows" the ByteBuf
|
||||||
|
* while it is in use.
|
||||||
|
*
|
||||||
|
* @param buf the buffer to read from
|
||||||
|
*/
|
||||||
|
public ByteBufDataInput(ByteBuf buf) {
|
||||||
|
this.in = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf unwrap() {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readFully(byte[] b) {
|
||||||
|
in.readBytes(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readFully(byte[] b, int off, int len) {
|
||||||
|
in.readBytes(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int skipBytes(int n) {
|
||||||
|
in.skipBytes(n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean readBoolean() {
|
||||||
|
return in.readBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte readByte() {
|
||||||
|
return in.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readUnsignedByte() {
|
||||||
|
return in.readUnsignedByte() & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short readShort() {
|
||||||
|
return in.readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readUnsignedShort() {
|
||||||
|
return in.readUnsignedShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char readChar() {
|
||||||
|
return in.readChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readInt() {
|
||||||
|
return in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readLong() {
|
||||||
|
return in.readLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float readFloat() {
|
||||||
|
return in.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double readDouble() {
|
||||||
|
return in.readDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readLine() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readUTF() {
|
||||||
|
try {
|
||||||
|
return DataInputStream.readUTF(this);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.velocitypowered.proxy.protocol.util;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufUtil;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link DataOutput} equivalent to {@link ByteBufDataInput}.
|
||||||
|
*/
|
||||||
|
public class ByteBufDataOutput extends OutputStream implements DataOutput, ByteArrayDataOutput {
|
||||||
|
|
||||||
|
private final ByteBuf buf;
|
||||||
|
private final DataOutputStream utf8out;
|
||||||
|
|
||||||
|
public ByteBufDataOutput(ByteBuf buf) {
|
||||||
|
this.buf = buf;
|
||||||
|
this.utf8out = new DataOutputStream(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
return ByteBufUtil.getBytes(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) {
|
||||||
|
buf.writeByte(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b) {
|
||||||
|
buf.writeBytes(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b, int off, int len) {
|
||||||
|
buf.writeBytes(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeBoolean(boolean v) {
|
||||||
|
buf.writeBoolean(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeByte(int v) {
|
||||||
|
buf.writeByte(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeShort(int v) {
|
||||||
|
buf.writeShort(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeChar(int v) {
|
||||||
|
buf.writeChar(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeInt(int v) {
|
||||||
|
buf.writeInt(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeLong(long v) {
|
||||||
|
buf.writeLong(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeFloat(float v) {
|
||||||
|
buf.writeFloat(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeDouble(double v) {
|
||||||
|
buf.writeDouble(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeBytes(String s) {
|
||||||
|
buf.writeCharSequence(s, StandardCharsets.US_ASCII);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeChars(String s) {
|
||||||
|
for (char c : s.toCharArray()) {
|
||||||
|
buf.writeChar(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeUTF(String s) {
|
||||||
|
try {
|
||||||
|
this.utf8out.writeUTF(s);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,12 +18,16 @@ import com.velocitypowered.api.proxy.server.ServerInfo;
|
|||||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
|
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
||||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
|
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
|
||||||
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
|
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
|
||||||
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder;
|
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder;
|
||||||
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder;
|
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
@ -119,8 +123,12 @@ public class VelocityRegisteredServer implements RegisteredServer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
||||||
|
return sendPluginMessage(identifier, Unpooled.wrappedBuffer(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendPluginMessage(ChannelIdentifier identifier, ByteBuf data) {
|
||||||
for (ConnectedPlayer player : players) {
|
for (ConnectedPlayer player : players) {
|
||||||
ServerConnection connection = player.getConnectedServer();
|
VelocityServerConnection connection = player.getConnectedServer();
|
||||||
if (connection != null && connection.getServerInfo().equals(serverInfo)) {
|
if (connection != null && connection.getServerInfo().equals(serverInfo)) {
|
||||||
return connection.sendPluginMessage(identifier, data);
|
return connection.sendPluginMessage(identifier, data);
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren