Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-17 05:20:14 +01:00
Finished the port to new session handler stuff
Dieser Commit ist enthalten in:
Ursprung
c7bd0d100e
Commit
79d566bcee
@ -6,7 +6,6 @@ import com.velocitypowered.api.command.CommandManager;
|
|||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class VelocityCommandManager implements CommandManager {
|
public class VelocityCommandManager implements CommandManager {
|
||||||
private final Map<String, Command> commands = new HashMap<>();
|
private final Map<String, Command> commands = new HashMap<>();
|
||||||
@ -57,6 +56,10 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasCommand(String command) {
|
||||||
|
return commands.containsKey(command);
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<List<String>> offerSuggestions(CommandSource source, String cmdLine) {
|
public Optional<List<String>> offerSuggestions(CommandSource source, String cmdLine) {
|
||||||
Preconditions.checkNotNull(source, "source");
|
Preconditions.checkNotNull(source, "source");
|
||||||
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
||||||
|
@ -69,12 +69,19 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
if (msg instanceof MinecraftPacket) {
|
if (msg instanceof MinecraftPacket) {
|
||||||
|
if (sessionHandler.beforeHandle()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MinecraftPacket pkt = (MinecraftPacket) msg;
|
MinecraftPacket pkt = (MinecraftPacket) msg;
|
||||||
if (!pkt.handle(sessionHandler)) {
|
if (!pkt.handle(sessionHandler)) {
|
||||||
sessionHandler.handleGeneric((MinecraftPacket) msg);
|
sessionHandler.handleGeneric((MinecraftPacket) msg);
|
||||||
}
|
}
|
||||||
} else if (msg instanceof ByteBuf) {
|
} else if (msg instanceof ByteBuf) {
|
||||||
try {
|
try {
|
||||||
|
if (sessionHandler.beforeHandle()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
sessionHandler.handleUnknown((ByteBuf) msg);
|
sessionHandler.handleUnknown((ByteBuf) msg);
|
||||||
} finally {
|
} finally {
|
||||||
ReferenceCountUtil.release(msg);
|
ReferenceCountUtil.release(msg);
|
||||||
|
@ -5,10 +5,16 @@ import com.velocitypowered.proxy.protocol.packet.*;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
public interface MinecraftSessionHandler {
|
public interface MinecraftSessionHandler {
|
||||||
void handleGeneric(MinecraftPacket packet);
|
default boolean beforeHandle() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default void handleGeneric(MinecraftPacket packet) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
default void handleUnknown(ByteBuf buf) {
|
default void handleUnknown(ByteBuf buf) {
|
||||||
// No-op: we'll release the buffer later.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default void connected() {
|
default void connected() {
|
||||||
|
@ -17,10 +17,12 @@ import io.netty.buffer.ByteBuf;
|
|||||||
public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||||
private final VelocityServer server;
|
private final VelocityServer server;
|
||||||
private final VelocityServerConnection serverConn;
|
private final VelocityServerConnection serverConn;
|
||||||
|
private final ClientPlaySessionHandler playerSessionHandler;
|
||||||
|
|
||||||
public BackendPlaySessionHandler(VelocityServer server, VelocityServerConnection serverConn) {
|
public BackendPlaySessionHandler(VelocityServer server, VelocityServerConnection serverConn) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.serverConn = serverConn;
|
this.serverConn = serverConn;
|
||||||
|
this.playerSessionHandler = (ClientPlaySessionHandler) serverConn.getPlayer().getConnection().getSessionHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -29,6 +31,93 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
serverConn.getServer().addPlayer(serverConn.getPlayer());
|
serverConn.getServer().addPlayer(serverConn.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean beforeHandle() {
|
||||||
|
if (!serverConn.getPlayer().isActive()) {
|
||||||
|
// Obsolete connection
|
||||||
|
serverConn.disconnect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(KeepAlive packet) {
|
||||||
|
serverConn.setLastPingId(packet.getRandomId());
|
||||||
|
return false; // forwards on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(Disconnect packet) {
|
||||||
|
serverConn.disconnect();
|
||||||
|
serverConn.getPlayer().handleConnectionException(serverConn.getServer(), packet);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(JoinGame packet) {
|
||||||
|
playerSessionHandler.handleBackendJoinGame(packet);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(BossBar packet) {
|
||||||
|
switch (packet.getAction()) {
|
||||||
|
case 0: // add
|
||||||
|
playerSessionHandler.getServerBossBars().add(packet.getUuid());
|
||||||
|
break;
|
||||||
|
case 1: // remove
|
||||||
|
playerSessionHandler.getServerBossBars().remove(packet.getUuid());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false; // forward
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(PluginMessage packet) {
|
||||||
|
if (!canForwardPluginMessage(packet)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PluginMessageUtil.isMCBrand(packet)) {
|
||||||
|
serverConn.getPlayer().getConnection().write(PluginMessageUtil.rewriteMCBrand(packet));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverConn.hasCompletedJoin() && packet.getChannel().equals(VelocityConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL)) {
|
||||||
|
if (!serverConn.isLegacyForge()) {
|
||||||
|
serverConn.setLegacyForge(true);
|
||||||
|
|
||||||
|
// We must always reset the handshake before a modded connection is established if
|
||||||
|
// we haven't done so already.
|
||||||
|
serverConn.getPlayer().sendLegacyForgeHandshakeResetPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always forward these messages during login
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelIdentifier id = server.getChannelRegistrar().getFromId(packet.getChannel());
|
||||||
|
if (id == null) {
|
||||||
|
serverConn.getPlayer().getConnection().write(packet);
|
||||||
|
} else {
|
||||||
|
PluginMessageEvent event = new PluginMessageEvent(serverConn, serverConn.getPlayer(), id, packet.getData());
|
||||||
|
server.getEventManager().fire(event)
|
||||||
|
.thenAcceptAsync(pme -> {
|
||||||
|
if (pme.getResult().isAllowed()) {
|
||||||
|
serverConn.getPlayer().getConnection().write(packet);
|
||||||
|
}
|
||||||
|
}, serverConn.getConnection().eventLoop());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(TabCompleteResponse packet) {
|
||||||
|
playerSessionHandler.handleTabCompleteResponse(packet);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleGeneric(MinecraftPacket packet) {
|
public void handleGeneric(MinecraftPacket packet) {
|
||||||
if (!serverConn.getPlayer().isActive()) {
|
if (!serverConn.getPlayer().isActive()) {
|
||||||
@ -38,69 +127,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientPlaySessionHandler playerHandler =
|
if (serverConn.hasCompletedJoin()) {
|
||||||
(ClientPlaySessionHandler) serverConn.getPlayer().getConnection().getSessionHandler();
|
|
||||||
if (packet instanceof KeepAlive) {
|
|
||||||
// Forward onto the player
|
|
||||||
serverConn.setLastPingId(((KeepAlive) packet).getRandomId());
|
|
||||||
serverConn.getPlayer().getConnection().write(packet);
|
|
||||||
} else if (packet instanceof Disconnect) {
|
|
||||||
Disconnect original = (Disconnect) packet;
|
|
||||||
serverConn.disconnect();
|
|
||||||
serverConn.getPlayer().handleConnectionException(serverConn.getServer(), original);
|
|
||||||
} else if (packet instanceof JoinGame) {
|
|
||||||
playerHandler.handleBackendJoinGame((JoinGame) packet);
|
|
||||||
} else if (packet instanceof BossBar) {
|
|
||||||
BossBar bossBar = (BossBar) packet;
|
|
||||||
switch (bossBar.getAction()) {
|
|
||||||
case 0: // add
|
|
||||||
playerHandler.getServerBossBars().add(bossBar.getUuid());
|
|
||||||
break;
|
|
||||||
case 1: // remove
|
|
||||||
playerHandler.getServerBossBars().remove(bossBar.getUuid());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
serverConn.getPlayer().getConnection().write(packet);
|
|
||||||
} else if (packet instanceof PluginMessage) {
|
|
||||||
PluginMessage pm = (PluginMessage) packet;
|
|
||||||
if (!canForwardPluginMessage(pm)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PluginMessageUtil.isMCBrand(pm)) {
|
|
||||||
serverConn.getPlayer().getConnection().write(PluginMessageUtil.rewriteMCBrand(pm));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serverConn.hasCompletedJoin() && pm.getChannel().equals(VelocityConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL)) {
|
|
||||||
if (!serverConn.isLegacyForge()) {
|
|
||||||
serverConn.setLegacyForge(true);
|
|
||||||
|
|
||||||
// We must always reset the handshake before a modded connection is established if
|
|
||||||
// we haven't done so already.
|
|
||||||
serverConn.getPlayer().sendLegacyForgeHandshakeResetPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always forward these messages during login
|
|
||||||
serverConn.getPlayer().getConnection().write(pm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelIdentifier id = server.getChannelRegistrar().getFromId(pm.getChannel());
|
|
||||||
if (id == null) {
|
|
||||||
serverConn.getPlayer().getConnection().write(pm);
|
|
||||||
} else {
|
|
||||||
PluginMessageEvent event = new PluginMessageEvent(serverConn, serverConn.getPlayer(), id, pm.getData());
|
|
||||||
server.getEventManager().fire(event)
|
|
||||||
.thenAcceptAsync(pme -> {
|
|
||||||
if (pme.getResult().isAllowed()) {
|
|
||||||
serverConn.getPlayer().getConnection().write(pm);
|
|
||||||
}
|
|
||||||
}, serverConn.getConnection().eventLoop());
|
|
||||||
}
|
|
||||||
} else if (packet instanceof TabCompleteResponse) {
|
|
||||||
playerHandler.handleTabCompleteResponse((TabCompleteResponse) packet);
|
|
||||||
} else if (serverConn.hasCompletedJoin()) {
|
|
||||||
// Just forward the packet on. We don't have anything to handle at this time.
|
// Just forward the packet on. We don't have anything to handle at this time.
|
||||||
serverConn.getPlayer().getConnection().write(packet);
|
serverConn.getPlayer().getConnection().write(packet);
|
||||||
}
|
}
|
||||||
|
@ -36,65 +36,77 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleGeneric(MinecraftPacket packet) {
|
public boolean handle(EncryptionRequest packet) {
|
||||||
if (packet instanceof EncryptionRequest) {
|
throw new IllegalStateException("Backend server is online-mode!");
|
||||||
throw new IllegalStateException("Backend server is online-mode!");
|
}
|
||||||
} else if (packet instanceof LoginPluginMessage) {
|
|
||||||
LoginPluginMessage message = (LoginPluginMessage) packet;
|
|
||||||
VelocityConfiguration configuration = server.getConfiguration();
|
|
||||||
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN &&
|
|
||||||
message.getChannel().equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) {
|
|
||||||
LoginPluginResponse response = new LoginPluginResponse();
|
|
||||||
response.setSuccess(true);
|
|
||||||
response.setId(message.getId());
|
|
||||||
response.setData(createForwardingData(configuration.getForwardingSecret(),
|
|
||||||
serverConn.getPlayer().getRemoteAddress().getHostString(),
|
|
||||||
serverConn.getPlayer().getProfile()));
|
|
||||||
serverConn.getConnection().write(response);
|
|
||||||
informationForwarded = true;
|
|
||||||
} else {
|
|
||||||
// Don't understand
|
|
||||||
LoginPluginResponse response = new LoginPluginResponse();
|
|
||||||
response.setSuccess(false);
|
|
||||||
response.setId(message.getId());
|
|
||||||
response.setData(Unpooled.EMPTY_BUFFER);
|
|
||||||
serverConn.getConnection().write(response);
|
|
||||||
}
|
|
||||||
} else if (packet instanceof Disconnect) {
|
|
||||||
Disconnect disconnect = (Disconnect) packet;
|
|
||||||
// Do we have an outstanding notification? If so, fulfill it.
|
|
||||||
doNotify(ConnectionRequestResults.forDisconnect(disconnect));
|
|
||||||
serverConn.disconnect();
|
|
||||||
} else if (packet instanceof SetCompression) {
|
|
||||||
SetCompression sc = (SetCompression) packet;
|
|
||||||
serverConn.getConnection().setCompressionThreshold(sc.getThreshold());
|
|
||||||
} else if (packet instanceof ServerLoginSuccess) {
|
|
||||||
if (server.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN && !informationForwarded) {
|
|
||||||
doNotify(ConnectionRequestResults.forDisconnect(
|
|
||||||
TextComponent.of("Your server did not send a forwarding request to the proxy. Is it set up correctly?")));
|
|
||||||
serverConn.disconnect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The player has been logged on to the backend server.
|
@Override
|
||||||
serverConn.getConnection().setState(StateRegistry.PLAY);
|
public boolean handle(LoginPluginMessage packet) {
|
||||||
VelocityServerConnection existingConnection = serverConn.getPlayer().getConnectedServer();
|
VelocityConfiguration configuration = server.getConfiguration();
|
||||||
if (existingConnection == null) {
|
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN && packet.getChannel()
|
||||||
// Strap on the play session handler
|
.equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) {
|
||||||
serverConn.getPlayer().getConnection().setSessionHandler(new ClientPlaySessionHandler(server, serverConn.getPlayer()));
|
LoginPluginResponse response = new LoginPluginResponse();
|
||||||
} else {
|
response.setSuccess(true);
|
||||||
// The previous server connection should become obsolete.
|
response.setId(packet.getId());
|
||||||
// Before we remove it, if the server we are departing is modded, we must always reset the client state.
|
response.setData(createForwardingData(configuration.getForwardingSecret(),
|
||||||
if (existingConnection.isLegacyForge()) {
|
serverConn.getPlayer().getRemoteAddress().getHostString(),
|
||||||
serverConn.getPlayer().sendLegacyForgeHandshakeResetPacket();
|
serverConn.getPlayer().getProfile()));
|
||||||
}
|
serverConn.getConnection().write(response);
|
||||||
existingConnection.disconnect();
|
informationForwarded = true;
|
||||||
}
|
} else {
|
||||||
|
// Don't understand
|
||||||
doNotify(ConnectionRequestResults.SUCCESSFUL);
|
LoginPluginResponse response = new LoginPluginResponse();
|
||||||
serverConn.getConnection().setSessionHandler(new BackendPlaySessionHandler(server, serverConn));
|
response.setSuccess(false);
|
||||||
serverConn.getPlayer().setConnectedServer(serverConn);
|
response.setId(packet.getId());
|
||||||
|
response.setData(Unpooled.EMPTY_BUFFER);
|
||||||
|
serverConn.getConnection().write(response);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(Disconnect packet) {
|
||||||
|
Disconnect disconnect = (Disconnect) packet;
|
||||||
|
// Do we have an outstanding notification? If so, fulfill it.
|
||||||
|
doNotify(ConnectionRequestResults.forDisconnect(disconnect));
|
||||||
|
serverConn.disconnect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(SetCompression packet) {
|
||||||
|
serverConn.getConnection().setCompressionThreshold(packet.getThreshold());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(ServerLoginSuccess packet) {
|
||||||
|
if (server.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN && !informationForwarded) {
|
||||||
|
doNotify(ConnectionRequestResults.forDisconnect(
|
||||||
|
TextComponent.of("Your server did not send a forwarding request to the proxy. Is it set up correctly?")));
|
||||||
|
serverConn.disconnect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The player has been logged on to the backend server.
|
||||||
|
serverConn.getConnection().setState(StateRegistry.PLAY);
|
||||||
|
VelocityServerConnection existingConnection = serverConn.getPlayer().getConnectedServer();
|
||||||
|
if (existingConnection == null) {
|
||||||
|
// Strap on the play session handler
|
||||||
|
serverConn.getPlayer().getConnection().setSessionHandler(new ClientPlaySessionHandler(server, serverConn.getPlayer()));
|
||||||
|
} else {
|
||||||
|
// The previous server connection should become obsolete.
|
||||||
|
// Before we remove it, if the server we are departing is modded, we must always reset the client state.
|
||||||
|
if (existingConnection.isLegacyForge()) {
|
||||||
|
serverConn.getPlayer().sendLegacyForgeHandshakeResetPacket();
|
||||||
|
}
|
||||||
|
existingConnection.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
doNotify(ConnectionRequestResults.SUCCESSFUL);
|
||||||
|
serverConn.getConnection().setSessionHandler(new BackendPlaySessionHandler(server, serverConn));
|
||||||
|
serverConn.getPlayer().setConnectedServer(serverConn);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,6 +48,128 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
player.getConnection().write(register);
|
player.getConnection().write(register);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(KeepAlive packet) {
|
||||||
|
VelocityServerConnection serverConnection = player.getConnectedServer();
|
||||||
|
if (serverConnection != null && packet.getRandomId() == serverConnection.getLastPingId()) {
|
||||||
|
player.setPing(System.currentTimeMillis() - serverConnection.getLastPingSent());
|
||||||
|
serverConnection.getConnection().write(packet);
|
||||||
|
serverConnection.resetLastPingId();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(ClientSettings packet) {
|
||||||
|
player.setPlayerSettings(packet);
|
||||||
|
return false; // will forward onto the handleGeneric below, which will write the packet to the remote server
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(Chat packet) {
|
||||||
|
String msg = packet.getMessage();
|
||||||
|
if (msg.startsWith("/")) {
|
||||||
|
try {
|
||||||
|
if (!server.getCommandManager().execute(player, msg.substring(1))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.info("Exception occurred while running command for {}", player.getProfile().getName(), e);
|
||||||
|
player.sendMessage(TextComponent.of("An error occurred while running this command.", TextColor.RED));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VelocityServerConnection serverConnection = player.getConnectedServer();
|
||||||
|
if (serverConnection == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
PlayerChatEvent event = new PlayerChatEvent(player, msg);
|
||||||
|
server.getEventManager().fire(event)
|
||||||
|
.thenAcceptAsync(pme -> {
|
||||||
|
if (pme.getResult().equals(PlayerChatEvent.ChatResult.allowed())){
|
||||||
|
serverConnection.getConnection().write(packet);
|
||||||
|
} else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){
|
||||||
|
serverConnection.getConnection().write(Chat.createServerbound(pme.getResult().getMessage().get()));
|
||||||
|
}
|
||||||
|
}, serverConnection.getConnection().eventLoop());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(TabCompleteRequest packet) {
|
||||||
|
// Record the request so that the outstanding request can be augmented later.
|
||||||
|
if (!packet.isAssumeCommand() && packet.getCommand().startsWith("/")) {
|
||||||
|
int spacePos = packet.getCommand().indexOf(' ');
|
||||||
|
if (spacePos > 0) {
|
||||||
|
String cmd = packet.getCommand().substring(1, spacePos);
|
||||||
|
if (server.getCommandManager().hasCommand(cmd)) {
|
||||||
|
Optional<List<String>> suggestions = server.getCommandManager().offerSuggestions(player, packet.getCommand().substring(1));
|
||||||
|
if (suggestions.isPresent()) {
|
||||||
|
TabCompleteResponse resp = new TabCompleteResponse();
|
||||||
|
resp.getOffers().addAll(suggestions.get());
|
||||||
|
player.getConnection().write(resp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outstandingTabComplete = packet;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(PluginMessage packet) {
|
||||||
|
if (PluginMessageUtil.isMCRegister(packet)) {
|
||||||
|
List<String> actuallyRegistered = new ArrayList<>();
|
||||||
|
List<String> channels = PluginMessageUtil.getChannels(packet);
|
||||||
|
for (String channel : channels) {
|
||||||
|
if (clientPluginMsgChannels.size() >= MAX_PLUGIN_CHANNELS &&
|
||||||
|
!clientPluginMsgChannels.contains(channel)) {
|
||||||
|
throw new IllegalStateException("Too many plugin message channels registered");
|
||||||
|
}
|
||||||
|
if (clientPluginMsgChannels.add(channel)) {
|
||||||
|
actuallyRegistered.add(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actuallyRegistered.size() > 0) {
|
||||||
|
PluginMessage newRegisterPacket = PluginMessageUtil.constructChannelsPacket(player.getProtocolVersion(), actuallyRegistered);
|
||||||
|
player.getConnectedServer().getConnection().write(newRegisterPacket);
|
||||||
|
}
|
||||||
|
} else if (PluginMessageUtil.isMCUnregister(packet)) {
|
||||||
|
List<String> channels = PluginMessageUtil.getChannels(packet);
|
||||||
|
clientPluginMsgChannels.removeAll(channels);
|
||||||
|
player.getConnectedServer().getConnection().write(packet);
|
||||||
|
} else if (PluginMessageUtil.isMCBrand(packet)) {
|
||||||
|
player.getConnectedServer().getConnection().write(PluginMessageUtil.rewriteMCBrand(packet));
|
||||||
|
} else if (player.getConnectedServer().isLegacyForge() && !player.getConnectedServer().hasCompletedJoin()) {
|
||||||
|
if (packet.getChannel().equals(VelocityConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL)) {
|
||||||
|
// Always forward the FML handshake to the remote server.
|
||||||
|
player.getConnectedServer().getConnection().write(packet);
|
||||||
|
} else {
|
||||||
|
// The client is trying to send messages too early. This is primarily caused by mods, but it's further
|
||||||
|
// aggravated by Velocity. To work around these issues, we will queue any non-FML handshake messages to
|
||||||
|
// be sent once the JoinGame packet has been received by the proxy.
|
||||||
|
loginPluginMessages.add(packet);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ChannelIdentifier id = server.getChannelRegistrar().getFromId(packet.getChannel());
|
||||||
|
if (id == null) {
|
||||||
|
player.getConnectedServer().getConnection().write(packet);
|
||||||
|
} else {
|
||||||
|
PluginMessageEvent event = new PluginMessageEvent(player, player.getConnectedServer(), id, packet.getData());
|
||||||
|
server.getEventManager().fire(event)
|
||||||
|
.thenAcceptAsync(pme -> {
|
||||||
|
if (pme.getResult().isAllowed()) {
|
||||||
|
player.getConnectedServer().getConnection().write(packet);
|
||||||
|
}
|
||||||
|
}, player.getConnectedServer().getConnection().eventLoop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleGeneric(MinecraftPacket packet) {
|
public void handleGeneric(MinecraftPacket packet) {
|
||||||
VelocityServerConnection serverConnection = player.getConnectedServer();
|
VelocityServerConnection serverConnection = player.getConnectedServer();
|
||||||
@ -56,65 +178,9 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet instanceof KeepAlive) {
|
|
||||||
KeepAlive keepAlive = (KeepAlive) packet;
|
|
||||||
if (keepAlive.getRandomId() != serverConnection.getLastPingId()) {
|
|
||||||
// The last keep alive we got was probably from a different server. Let's ignore it, and hope the next
|
|
||||||
// ping is alright.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
player.setPing(System.currentTimeMillis() - serverConnection.getLastPingSent());
|
|
||||||
serverConnection.getConnection().write(packet);
|
|
||||||
serverConnection.resetLastPingId();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet instanceof ClientSettings) {
|
|
||||||
player.setPlayerSettings((ClientSettings) packet);
|
|
||||||
// forward it on
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet instanceof Chat) {
|
|
||||||
// Try to handle any commands on the proxy. If that fails, send it onto the client.
|
|
||||||
Chat chat = (Chat) packet;
|
|
||||||
String msg = ((Chat) packet).getMessage();
|
|
||||||
if (msg.startsWith("/")) {
|
|
||||||
try {
|
|
||||||
if (!server.getCommandManager().execute(player, msg.substring(1))) {
|
|
||||||
player.getConnectedServer().getConnection().write(chat);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.info("Exception occurred while running command for {}", player.getProfile().getName(), e);
|
|
||||||
player.sendMessage(TextComponent.of("An error occurred while running this command.", TextColor.RED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PlayerChatEvent event = new PlayerChatEvent(player, msg);
|
|
||||||
server.getEventManager().fire(event)
|
|
||||||
.thenAcceptAsync(pme -> {
|
|
||||||
if (pme.getResult().equals(PlayerChatEvent.ChatResult.allowed())){
|
|
||||||
serverConnection.getConnection().write(chat);
|
|
||||||
} else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){
|
|
||||||
serverConnection.getConnection().write(Chat.createServerbound(pme.getResult().getMessage().get()));
|
|
||||||
}
|
|
||||||
}, serverConnection.getConnection().eventLoop());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet instanceof TabCompleteRequest) {
|
|
||||||
// Record the request so that the outstanding request can be augmented later.
|
|
||||||
outstandingTabComplete = (TabCompleteRequest) packet;
|
|
||||||
serverConnection.getConnection().write(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet instanceof PluginMessage) {
|
|
||||||
handleClientPluginMessage((PluginMessage) packet);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we don't want to handle this packet, just forward it on.
|
// If we don't want to handle this packet, just forward it on.
|
||||||
if (serverConnection.hasCompletedJoin()) {
|
if (serverConnection.hasCompletedJoin()) {
|
||||||
|
logger.info("Will write {}", packet);
|
||||||
serverConnection.getConnection().write(packet);
|
serverConnection.getConnection().write(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,62 +311,15 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
return serverBossBars;
|
return serverBossBars;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleClientPluginMessage(PluginMessage packet) {
|
|
||||||
if (PluginMessageUtil.isMCRegister(packet)) {
|
|
||||||
List<String> actuallyRegistered = new ArrayList<>();
|
|
||||||
List<String> channels = PluginMessageUtil.getChannels(packet);
|
|
||||||
for (String channel : channels) {
|
|
||||||
if (clientPluginMsgChannels.size() >= MAX_PLUGIN_CHANNELS &&
|
|
||||||
!clientPluginMsgChannels.contains(channel)) {
|
|
||||||
throw new IllegalStateException("Too many plugin message channels registered");
|
|
||||||
}
|
|
||||||
if (clientPluginMsgChannels.add(channel)) {
|
|
||||||
actuallyRegistered.add(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actuallyRegistered.size() > 0) {
|
|
||||||
PluginMessage newRegisterPacket = PluginMessageUtil.constructChannelsPacket(player.getProtocolVersion(), actuallyRegistered);
|
|
||||||
player.getConnectedServer().getConnection().write(newRegisterPacket);
|
|
||||||
}
|
|
||||||
} else if (PluginMessageUtil.isMCUnregister(packet)) {
|
|
||||||
List<String> channels = PluginMessageUtil.getChannels(packet);
|
|
||||||
clientPluginMsgChannels.removeAll(channels);
|
|
||||||
player.getConnectedServer().getConnection().write(packet);
|
|
||||||
} else if (PluginMessageUtil.isMCBrand(packet)) {
|
|
||||||
player.getConnectedServer().getConnection().write(PluginMessageUtil.rewriteMCBrand(packet));
|
|
||||||
} else if (player.getConnectedServer().isLegacyForge() && !player.getConnectedServer().hasCompletedJoin()) {
|
|
||||||
if (packet.getChannel().equals(VelocityConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL)) {
|
|
||||||
// Always forward the FML handshake to the remote server.
|
|
||||||
player.getConnectedServer().getConnection().write(packet);
|
|
||||||
} else {
|
|
||||||
// The client is trying to send messages too early. This is primarily caused by mods, but it's further
|
|
||||||
// aggravated by Velocity. To work around these issues, we will queue any non-FML handshake messages to
|
|
||||||
// be sent once the JoinGame packet has been received by the proxy.
|
|
||||||
loginPluginMessages.add(packet);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ChannelIdentifier id = server.getChannelRegistrar().getFromId(packet.getChannel());
|
|
||||||
if (id == null) {
|
|
||||||
player.getConnectedServer().getConnection().write(packet);
|
|
||||||
} else {
|
|
||||||
PluginMessageEvent event = new PluginMessageEvent(player, player.getConnectedServer(), id, packet.getData());
|
|
||||||
server.getEventManager().fire(event)
|
|
||||||
.thenAcceptAsync(pme -> {
|
|
||||||
if (pme.getResult().isAllowed()) {
|
|
||||||
player.getConnectedServer().getConnection().write(packet);
|
|
||||||
}
|
|
||||||
}, player.getConnectedServer().getConnection().eventLoop());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> getClientPluginMsgChannels() {
|
public Set<String> getClientPluginMsgChannels() {
|
||||||
return clientPluginMsgChannels;
|
return clientPluginMsgChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleTabCompleteResponse(TabCompleteResponse response) {
|
public void handleTabCompleteResponse(TabCompleteResponse response) {
|
||||||
|
logger.info("Got {}", response);
|
||||||
|
logger.info("Request {}", outstandingTabComplete);
|
||||||
if (outstandingTabComplete != null) {
|
if (outstandingTabComplete != null) {
|
||||||
|
logger.info("HANDLING");
|
||||||
if (!outstandingTabComplete.isAssumeCommand()) {
|
if (!outstandingTabComplete.isAssumeCommand()) {
|
||||||
String command = outstandingTabComplete.getCommand().substring(1);
|
String command = outstandingTabComplete.getCommand().substring(1);
|
||||||
try {
|
try {
|
||||||
|
@ -117,7 +117,8 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUnknown(ByteBuf buf) {
|
public void handleUnknown(ByteBuf buf) {
|
||||||
throw new IllegalStateException("Unknown data " + ByteBufUtil.hexDump(buf));
|
// what even is going on?
|
||||||
|
connection.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LegacyInboundConnection implements InboundConnection {
|
private static class LegacyInboundConnection implements InboundConnection {
|
||||||
|
@ -59,89 +59,94 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleGeneric(MinecraftPacket packet) {
|
public boolean handle(ServerLogin packet) {
|
||||||
if (packet instanceof LoginPluginResponse) {
|
this.login = packet;
|
||||||
LoginPluginResponse lpr = (LoginPluginResponse) packet;
|
if (inbound.getProtocolVersion() >= ProtocolConstants.MINECRAFT_1_13) {
|
||||||
if (lpr.getId() == playerInfoId) {
|
LoginPluginMessage message = new LoginPluginMessage();
|
||||||
if (lpr.isSuccess()) {
|
playerInfoId = ThreadLocalRandom.current().nextInt();
|
||||||
// Uh oh, someone's trying to run Velocity behind Velocity. We don't want that happening.
|
message.setId(playerInfoId);
|
||||||
inbound.closeWith(Disconnect.create(
|
message.setChannel(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL);
|
||||||
TextComponent.of("Running Velocity behind Velocity isn't supported.", TextColor.RED)
|
message.setData(Unpooled.EMPTY_BUFFER);
|
||||||
));
|
inbound.write(message);
|
||||||
} else {
|
} else {
|
||||||
// Proceed with the regular login process.
|
beginPreLogin();
|
||||||
beginPreLogin();
|
}
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
} else if (packet instanceof ServerLogin) {
|
|
||||||
this.login = (ServerLogin) packet;
|
|
||||||
|
|
||||||
if (inbound.getProtocolVersion() >= ProtocolConstants.MINECRAFT_1_13) {
|
@Override
|
||||||
LoginPluginMessage message = new LoginPluginMessage();
|
public boolean handle(LoginPluginResponse packet) {
|
||||||
playerInfoId = ThreadLocalRandom.current().nextInt();
|
if (packet.getId() == playerInfoId) {
|
||||||
message.setId(playerInfoId);
|
if (packet.isSuccess()) {
|
||||||
message.setChannel(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL);
|
// Uh oh, someone's trying to run Velocity behind Velocity. We don't want that happening.
|
||||||
message.setData(Unpooled.EMPTY_BUFFER);
|
inbound.closeWith(Disconnect.create(
|
||||||
inbound.write(message);
|
TextComponent.of("Running Velocity behind Velocity isn't supported.", TextColor.RED)
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
|
// Proceed with the regular login process.
|
||||||
beginPreLogin();
|
beginPreLogin();
|
||||||
}
|
}
|
||||||
} else if (packet instanceof EncryptionResponse) {
|
|
||||||
try {
|
|
||||||
KeyPair serverKeyPair = server.getServerKeyPair();
|
|
||||||
EncryptionResponse response = (EncryptionResponse) packet;
|
|
||||||
byte[] decryptedVerifyToken = EncryptionUtils.decryptRsa(serverKeyPair, response.getVerifyToken());
|
|
||||||
if (!Arrays.equals(verify, decryptedVerifyToken)) {
|
|
||||||
throw new IllegalStateException("Unable to successfully decrypt the verification token.");
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] decryptedSharedSecret = EncryptionUtils.decryptRsa(serverKeyPair, response.getSharedSecret());
|
|
||||||
String serverId = EncryptionUtils.generateServerId(decryptedSharedSecret, serverKeyPair.getPublic());
|
|
||||||
|
|
||||||
String playerIp = ((InetSocketAddress) inbound.getChannel().remoteAddress()).getHostString();
|
|
||||||
server.getHttpClient()
|
|
||||||
.get(new URL(String.format(MOJANG_SERVER_AUTH_URL, login.getUsername(), serverId, playerIp)))
|
|
||||||
.thenAcceptAsync(profileResponse -> {
|
|
||||||
if (inbound.isClosed()) {
|
|
||||||
// The player disconnected after we authenticated them.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go ahead and enable encryption. Once the client sends EncryptionResponse, encryption is
|
|
||||||
// enabled.
|
|
||||||
try {
|
|
||||||
inbound.enableEncryption(decryptedSharedSecret);
|
|
||||||
} catch (GeneralSecurityException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profileResponse.getCode() == 200) {
|
|
||||||
// All went well, initialize the session.
|
|
||||||
initializePlayer(VelocityServer.GSON.fromJson(profileResponse.getBody(), GameProfile.class), true);
|
|
||||||
} else if (profileResponse.getCode() == 204) {
|
|
||||||
// Apparently an offline-mode user logged onto this online-mode proxy. The client has enabled
|
|
||||||
// encryption, so we need to do that as well.
|
|
||||||
logger.warn("An offline-mode client ({} from {}) tried to connect!", login.getUsername(), playerIp);
|
|
||||||
inbound.closeWith(Disconnect.create(TextComponent.of("This server only accepts connections from online-mode clients.")));
|
|
||||||
} else {
|
|
||||||
// Something else went wrong
|
|
||||||
logger.error("Got an unexpected error code {} whilst contacting Mojang to log in {} ({})",
|
|
||||||
profileResponse.getCode(), login.getUsername(), playerIp);
|
|
||||||
inbound.close();
|
|
||||||
}
|
|
||||||
}, inbound.eventLoop())
|
|
||||||
.exceptionally(exception -> {
|
|
||||||
logger.error("Unable to enable encryption", exception);
|
|
||||||
inbound.close();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
} catch (GeneralSecurityException e) {
|
|
||||||
logger.error("Unable to enable encryption", e);
|
|
||||||
inbound.close();
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(EncryptionResponse packet) {
|
||||||
|
try {
|
||||||
|
KeyPair serverKeyPair = server.getServerKeyPair();
|
||||||
|
EncryptionResponse response = (EncryptionResponse) packet;
|
||||||
|
byte[] decryptedVerifyToken = EncryptionUtils.decryptRsa(serverKeyPair, response.getVerifyToken());
|
||||||
|
if (!Arrays.equals(verify, decryptedVerifyToken)) {
|
||||||
|
throw new IllegalStateException("Unable to successfully decrypt the verification token.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] decryptedSharedSecret = EncryptionUtils.decryptRsa(serverKeyPair, response.getSharedSecret());
|
||||||
|
String serverId = EncryptionUtils.generateServerId(decryptedSharedSecret, serverKeyPair.getPublic());
|
||||||
|
|
||||||
|
String playerIp = ((InetSocketAddress) inbound.getChannel().remoteAddress()).getHostString();
|
||||||
|
server.getHttpClient()
|
||||||
|
.get(new URL(String.format(MOJANG_SERVER_AUTH_URL, login.getUsername(), serverId, playerIp)))
|
||||||
|
.thenAcceptAsync(profileResponse -> {
|
||||||
|
if (inbound.isClosed()) {
|
||||||
|
// The player disconnected after we authenticated them.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go ahead and enable encryption. Once the client sends EncryptionResponse, encryption is
|
||||||
|
// enabled.
|
||||||
|
try {
|
||||||
|
inbound.enableEncryption(decryptedSharedSecret);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profileResponse.getCode() == 200) {
|
||||||
|
// All went well, initialize the session.
|
||||||
|
initializePlayer(VelocityServer.GSON.fromJson(profileResponse.getBody(), GameProfile.class), true);
|
||||||
|
} else if (profileResponse.getCode() == 204) {
|
||||||
|
// Apparently an offline-mode user logged onto this online-mode proxy. The client has enabled
|
||||||
|
// encryption, so we need to do that as well.
|
||||||
|
logger.warn("An offline-mode client ({} from {}) tried to connect!", login.getUsername(), playerIp);
|
||||||
|
inbound.closeWith(Disconnect.create(TextComponent.of("This server only accepts connections from online-mode clients.")));
|
||||||
|
} else {
|
||||||
|
// Something else went wrong
|
||||||
|
logger.error("Got an unexpected error code {} whilst contacting Mojang to log in {} ({})",
|
||||||
|
profileResponse.getCode(), login.getUsername(), playerIp);
|
||||||
|
inbound.close();
|
||||||
|
}
|
||||||
|
}, inbound.eventLoop())
|
||||||
|
.exceptionally(exception -> {
|
||||||
|
logger.error("Unable to enable encryption", exception);
|
||||||
|
inbound.close();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
logger.error("Unable to enable encryption", e);
|
||||||
|
inbound.close();
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void beginPreLogin() {
|
private void beginPreLogin() {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.velocitypowered.proxy.connection.client;
|
package com.velocitypowered.proxy.connection.client;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
||||||
import com.velocitypowered.api.proxy.InboundConnection;
|
import com.velocitypowered.api.proxy.InboundConnection;
|
||||||
@ -9,13 +8,11 @@ import com.velocitypowered.proxy.VelocityServer;
|
|||||||
import com.velocitypowered.proxy.config.VelocityConfiguration;
|
import com.velocitypowered.proxy.config.VelocityConfiguration;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||||
import com.velocitypowered.proxy.protocol.packet.StatusPing;
|
import com.velocitypowered.proxy.protocol.packet.StatusPing;
|
||||||
import com.velocitypowered.proxy.protocol.packet.StatusRequest;
|
import com.velocitypowered.proxy.protocol.packet.StatusRequest;
|
||||||
import com.velocitypowered.proxy.protocol.packet.StatusResponse;
|
import com.velocitypowered.proxy.protocol.packet.StatusResponse;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
|
||||||
|
|
||||||
public class StatusSessionHandler implements MinecraftSessionHandler {
|
public class StatusSessionHandler implements MinecraftSessionHandler {
|
||||||
private final VelocityServer server;
|
private final VelocityServer server;
|
||||||
@ -29,19 +26,15 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleGeneric(MinecraftPacket packet) {
|
public boolean handle(StatusPing packet) {
|
||||||
Preconditions.checkArgument(packet instanceof StatusPing || packet instanceof StatusRequest,
|
connection.closeWith(packet);
|
||||||
"Unrecognized packet type " + packet.getClass().getName());
|
return true;
|
||||||
|
}
|
||||||
if (packet instanceof StatusPing) {
|
|
||||||
// Just send back the client's packet, no processing to do here.
|
|
||||||
connection.closeWith(packet);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(StatusRequest packet) {
|
||||||
VelocityConfiguration configuration = server.getConfiguration();
|
VelocityConfiguration configuration = server.getConfiguration();
|
||||||
|
|
||||||
// Status request
|
|
||||||
int shownVersion = ProtocolConstants.isSupported(connection.getProtocolVersion()) ? connection.getProtocolVersion() :
|
int shownVersion = ProtocolConstants.isSupported(connection.getProtocolVersion()) ? connection.getProtocolVersion() :
|
||||||
ProtocolConstants.MAXIMUM_GENERIC_VERSION;
|
ProtocolConstants.MAXIMUM_GENERIC_VERSION;
|
||||||
ServerPing initialPing = new ServerPing(
|
ServerPing initialPing = new ServerPing(
|
||||||
@ -59,10 +52,12 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
|||||||
response.setStatus(VelocityServer.GSON.toJson(event.getPing()));
|
response.setStatus(VelocityServer.GSON.toJson(event.getPing()));
|
||||||
connection.write(response);
|
connection.write(response);
|
||||||
}, connection.eventLoop());
|
}, connection.eventLoop());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUnknown(ByteBuf buf) {
|
public void handleUnknown(ByteBuf buf) {
|
||||||
throw new IllegalStateException("Unknown data " + ByteBufUtil.hexDump(buf));
|
// what even is going on?
|
||||||
|
connection.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package com.velocitypowered.proxy.server.ping;
|
package com.velocitypowered.proxy.server.ping;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
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.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||||
import com.velocitypowered.proxy.protocol.StateRegistry;
|
import com.velocitypowered.proxy.protocol.StateRegistry;
|
||||||
import com.velocitypowered.proxy.protocol.packet.Handshake;
|
import com.velocitypowered.proxy.protocol.packet.Handshake;
|
||||||
@ -42,15 +40,14 @@ public class PingSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleGeneric(MinecraftPacket packet) {
|
public boolean handle(StatusResponse packet) {
|
||||||
Preconditions.checkState(packet instanceof StatusResponse, "Did not get status response back from connection");
|
|
||||||
|
|
||||||
// All good!
|
// All good!
|
||||||
completed = true;
|
completed = true;
|
||||||
connection.close();
|
connection.close();
|
||||||
|
|
||||||
ServerPing ping = VelocityServer.GSON.fromJson(((StatusResponse) packet).getStatus(), ServerPing.class);
|
ServerPing ping = VelocityServer.GSON.fromJson(((StatusResponse) packet).getStatus(), ServerPing.class);
|
||||||
result.complete(ping);
|
result.complete(ping);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren