Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-17 05:20:14 +01:00
Very basic multi-server switching functionality
Dieser Commit ist enthalten in:
Ursprung
60ac285b17
Commit
6ae9798a1b
@ -33,11 +33,17 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
}
|
||||
|
||||
if (packet instanceof ServerLoginSuccess) {
|
||||
// the player has been logged on.
|
||||
// The player has been logged on to the backend server.
|
||||
connection.getChannel().setState(StateRegistry.PLAY);
|
||||
connection.getProxyPlayer().setConnectedServer(connection);
|
||||
if (connection.getProxyPlayer().getConnectedServer() == null) {
|
||||
// Strap on the play session handler
|
||||
connection.getProxyPlayer().getConnection().setSessionHandler(new com.velocitypowered.proxy.connection.client.PlaySessionHandler(connection.getProxyPlayer()));
|
||||
} else {
|
||||
// The previous server connection should become obsolete.
|
||||
connection.getProxyPlayer().getConnectedServer().disconnect();
|
||||
}
|
||||
connection.getChannel().setSessionHandler(new PlaySessionHandler(connection));
|
||||
connection.getProxyPlayer().setConnectedServer(connection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.velocitypowered.proxy.connection.backend;
|
||||
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.packets.Disconnect;
|
||||
import com.velocitypowered.proxy.protocol.packets.JoinGame;
|
||||
import com.velocitypowered.proxy.protocol.packets.Ping;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
@ -31,6 +32,10 @@ public class PlaySessionHandler implements MinecraftSessionHandler {
|
||||
.append(ComponentSerializers.JSON.deserialize(original.getReason()))
|
||||
.build();
|
||||
connection.getProxyPlayer().close(reason);
|
||||
} else if (packet instanceof JoinGame) {
|
||||
com.velocitypowered.proxy.connection.client.PlaySessionHandler playerHandler =
|
||||
(com.velocitypowered.proxy.connection.client.PlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler();
|
||||
playerHandler.handleBackendJoinGame((JoinGame) packet);
|
||||
} else {
|
||||
// Just forward the packet on. We don't have anything to handle at this time.
|
||||
connection.getProxyPlayer().getConnection().write(packet);
|
||||
|
@ -1,11 +1,18 @@
|
||||
package com.velocitypowered.proxy.connection.client;
|
||||
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.backend.ServerConnection;
|
||||
import com.velocitypowered.proxy.data.ServerInfo;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.packets.Chat;
|
||||
import com.velocitypowered.proxy.protocol.packets.JoinGame;
|
||||
import com.velocitypowered.proxy.protocol.packets.Ping;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.packets.Respawn;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.EventLoop;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -14,6 +21,8 @@ public class PlaySessionHandler implements MinecraftSessionHandler {
|
||||
private final ConnectedPlayer player;
|
||||
private ScheduledFuture<?> pingTask;
|
||||
private long lastPing = -1;
|
||||
private boolean spawned = false;
|
||||
private int currentDimension;
|
||||
|
||||
public PlaySessionHandler(ConnectedPlayer player) {
|
||||
this.player = player;
|
||||
@ -38,12 +47,22 @@ public class PlaySessionHandler implements MinecraftSessionHandler {
|
||||
if (packet instanceof Ping) {
|
||||
Ping ping = (Ping) packet;
|
||||
if (ping.getRandomId() != lastPing) {
|
||||
throw new IllegalStateException("Client sent invalid ping; expected " + lastPing + ", got " + ping.getRandomId());
|
||||
// throw new IllegalStateException("Client sent invalid ping; expected " + lastPing + ", got " + ping.getRandomId());
|
||||
}
|
||||
|
||||
// Do not forward the packet to the player's server, because we handle pings for all servers already.
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet instanceof Chat) {
|
||||
Chat chat = (Chat) packet;
|
||||
if (chat.getMessage().equals("/connect")) {
|
||||
ServerInfo info = new ServerInfo("test", new InetSocketAddress("localhost", 25566));
|
||||
ServerConnection connection = new ServerConnection(info, player, VelocityServer.getServer());
|
||||
connection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't want to handle this packet, just forward it on.
|
||||
player.getConnectedServer().getChannel().write(packet);
|
||||
}
|
||||
@ -62,4 +81,25 @@ public class PlaySessionHandler implements MinecraftSessionHandler {
|
||||
pingTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleBackendJoinGame(JoinGame joinGame) {
|
||||
if (!spawned) {
|
||||
// nothing special to do here
|
||||
spawned = true;
|
||||
currentDimension = joinGame.getDimension();
|
||||
player.getConnection().write(joinGame);
|
||||
} else {
|
||||
// In order to handle switching to another server we will need send three packets:
|
||||
// - The join game packet
|
||||
// - A respawn packet, with a different dimension, if it differs
|
||||
// - Another respawn with the correct dimension
|
||||
player.getConnection().write(joinGame);
|
||||
if (joinGame.getDimension() == currentDimension) {
|
||||
int tempDim = joinGame.getDimension() == 0 ? -1 : 0;
|
||||
player.getConnection().write(new Respawn(tempDim, joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType()));
|
||||
}
|
||||
player.getConnection().write(new Respawn(joinGame.getDimension(), joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType()));
|
||||
currentDimension = joinGame.getDimension();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,10 @@ public enum StateRegistry {
|
||||
map(0x1A, MINECRAFT_1_12));
|
||||
TO_CLIENT.register(Ping.class, Ping::new,
|
||||
map(0x1F, MINECRAFT_1_12));
|
||||
TO_CLIENT.register(JoinGame.class, JoinGame::new,
|
||||
map(0x23, MINECRAFT_1_12));
|
||||
TO_CLIENT.register(Respawn.class, Respawn::new,
|
||||
map(0x35, MINECRAFT_1_12));
|
||||
}
|
||||
},
|
||||
LOGIN {
|
||||
|
107
src/main/java/com/velocitypowered/proxy/protocol/packets/JoinGame.java
Normale Datei
107
src/main/java/com/velocitypowered/proxy/protocol/packets/JoinGame.java
Normale Datei
@ -0,0 +1,107 @@
|
||||
package com.velocitypowered.proxy.protocol.packets;
|
||||
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class JoinGame implements MinecraftPacket {
|
||||
private int entityId;
|
||||
private short gamemode;
|
||||
private int dimension;
|
||||
private short difficulty;
|
||||
private short maxPlayers;
|
||||
private String levelType;
|
||||
private boolean reducedDebugInfo;
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(int entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public short getGamemode() {
|
||||
return gamemode;
|
||||
}
|
||||
|
||||
public void setGamemode(short gamemode) {
|
||||
this.gamemode = gamemode;
|
||||
}
|
||||
|
||||
public int getDimension() {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
public void setDimension(int dimension) {
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public short getDifficulty() {
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
public void setDifficulty(short difficulty) {
|
||||
this.difficulty = difficulty;
|
||||
}
|
||||
|
||||
public short getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
public void setMaxPlayers(short maxPlayers) {
|
||||
this.maxPlayers = maxPlayers;
|
||||
}
|
||||
|
||||
public String getLevelType() {
|
||||
return levelType;
|
||||
}
|
||||
|
||||
public void setLevelType(String levelType) {
|
||||
this.levelType = levelType;
|
||||
}
|
||||
|
||||
public boolean isReducedDebugInfo() {
|
||||
return reducedDebugInfo;
|
||||
}
|
||||
|
||||
public void setReducedDebugInfo(boolean reducedDebugInfo) {
|
||||
this.reducedDebugInfo = reducedDebugInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JoinGame{" +
|
||||
"entityId=" + entityId +
|
||||
", gamemode=" + gamemode +
|
||||
", dimension=" + dimension +
|
||||
", difficulty=" + difficulty +
|
||||
", maxPlayers=" + maxPlayers +
|
||||
", levelType='" + levelType + '\'' +
|
||||
", reducedDebugInfo=" + reducedDebugInfo +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
|
||||
this.entityId = buf.readInt();
|
||||
this.gamemode = buf.readUnsignedByte();
|
||||
this.dimension = buf.readInt();
|
||||
this.difficulty = buf.readUnsignedByte();
|
||||
this.maxPlayers = buf.readUnsignedByte();
|
||||
this.levelType = ProtocolUtils.readString(buf, 16);
|
||||
this.reducedDebugInfo = buf.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
|
||||
buf.writeInt(entityId);
|
||||
buf.writeByte(gamemode);
|
||||
buf.writeInt(dimension);
|
||||
buf.writeByte(difficulty);
|
||||
buf.writeByte(maxPlayers);
|
||||
ProtocolUtils.writeString(buf, levelType);
|
||||
buf.writeBoolean(reducedDebugInfo);
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package com.velocitypowered.proxy.protocol.packets;
|
||||
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class Respawn implements MinecraftPacket {
|
||||
private int dimension;
|
||||
private short difficulty;
|
||||
private short gamemode;
|
||||
private String levelType;
|
||||
|
||||
public Respawn() {
|
||||
}
|
||||
|
||||
public Respawn(int dimension, short difficulty, short gamemode, String levelType) {
|
||||
this.dimension = dimension;
|
||||
this.difficulty = difficulty;
|
||||
this.gamemode = gamemode;
|
||||
this.levelType = levelType;
|
||||
}
|
||||
|
||||
public int getDimension() {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
public void setDimension(int dimension) {
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public short getDifficulty() {
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
public void setDifficulty(short difficulty) {
|
||||
this.difficulty = difficulty;
|
||||
}
|
||||
|
||||
public short getGamemode() {
|
||||
return gamemode;
|
||||
}
|
||||
|
||||
public void setGamemode(short gamemode) {
|
||||
this.gamemode = gamemode;
|
||||
}
|
||||
|
||||
public String getLevelType() {
|
||||
return levelType;
|
||||
}
|
||||
|
||||
public void setLevelType(String levelType) {
|
||||
this.levelType = levelType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Respawn{" +
|
||||
"dimension=" + dimension +
|
||||
", difficulty=" + difficulty +
|
||||
", gamemode=" + gamemode +
|
||||
", levelType='" + levelType + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
|
||||
this.dimension = buf.readInt();
|
||||
this.difficulty = buf.readUnsignedByte();
|
||||
this.gamemode = buf.readUnsignedByte();
|
||||
this.levelType = ProtocolUtils.readString(buf, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
|
||||
buf.writeInt(dimension);
|
||||
buf.writeByte(difficulty);
|
||||
buf.writeByte(gamemode);
|
||||
ProtocolUtils.writeString(buf, levelType);
|
||||
}
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren