Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-12-24 15:20:35 +01:00
Initial remapping support, fix protocol crap.
Dieser Commit ist enthalten in:
Ursprung
47bea89146
Commit
6b5cd703f0
@ -2,6 +2,7 @@ package com.velocitypowered.proxy.connection.backend;
|
||||
|
||||
import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
import com.velocitypowered.proxy.protocol.packets.*;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
|
||||
@ -46,7 +47,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
PluginMessage pm = (PluginMessage) packet;
|
||||
try {
|
||||
PluginMessage newPacket = pm;
|
||||
if (!canForwardMessage(newPacket)) {
|
||||
if (!canForwardPluginMessage(newPacket)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -72,7 +73,10 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
@Override
|
||||
public void handleUnknown(ByteBuf buf) {
|
||||
connection.getProxyPlayer().getConnection().write(buf.retain());
|
||||
ClientPlaySessionHandler playerHandler =
|
||||
(ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler();
|
||||
ByteBuf remapped = playerHandler.getIdRemapper().remap(buf, ProtocolConstants.Direction.CLIENTBOUND);
|
||||
connection.getProxyPlayer().getConnection().write(remapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,7 +84,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), throwable);
|
||||
}
|
||||
|
||||
private boolean canForwardMessage(PluginMessage message) {
|
||||
private boolean canForwardPluginMessage(PluginMessage message) {
|
||||
// TODO: Update for 1.13
|
||||
ClientPlaySessionHandler playerHandler =
|
||||
(ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler();
|
||||
|
@ -8,8 +8,10 @@ import com.velocitypowered.proxy.data.scoreboard.Score;
|
||||
import com.velocitypowered.proxy.data.scoreboard.Scoreboard;
|
||||
import com.velocitypowered.proxy.data.scoreboard.Team;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
import com.velocitypowered.proxy.protocol.packets.*;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.remap.EntityIdRemapper;
|
||||
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
|
||||
import com.velocitypowered.proxy.util.ThrowableUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
@ -39,6 +41,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
private PluginMessage brandMessage;
|
||||
private int currentDimension;
|
||||
private Scoreboard serverScoreboard = new Scoreboard();
|
||||
private EntityIdRemapper idRemapper;
|
||||
|
||||
public ClientPlaySessionHandler(ConnectedPlayer player) {
|
||||
this.player = player;
|
||||
@ -95,7 +98,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
@Override
|
||||
public void handleUnknown(ByteBuf buf) {
|
||||
player.getConnectedServer().getChannel().write(buf.retain());
|
||||
ByteBuf remapped = idRemapper.remap(buf, ProtocolConstants.Direction.SERVERBOUND);
|
||||
player.getConnectedServer().getChannel().write(remapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,6 +127,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
spawned = true;
|
||||
currentDimension = joinGame.getDimension();
|
||||
player.getConnection().delayedWrite(joinGame);
|
||||
idRemapper = EntityIdRemapper.getMapper(joinGame.getEntityId(), player.getConnection().getProtocolVersion());
|
||||
} else {
|
||||
// In order to handle switching to another server we will need send three packets:
|
||||
// - The join game packet from the backend server
|
||||
@ -130,6 +135,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
// - Another respawn with the correct dimension
|
||||
// We can't simply ignore the packet with the different dimension. If you try to be smart about it it doesn't
|
||||
// work.
|
||||
idRemapper.setServerEntityId(joinGame.getEntityId());
|
||||
player.getConnection().delayedWrite(joinGame);
|
||||
int tempDim = joinGame.getDimension() == 0 ? -1 : 0;
|
||||
player.getConnection().delayedWrite(new Respawn(tempDim, joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType()));
|
||||
@ -304,4 +310,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
public Set<String> getClientPluginMsgChannels() {
|
||||
return clientPluginMsgChannels;
|
||||
}
|
||||
|
||||
public EntityIdRemapper getIdRemapper() {
|
||||
return idRemapper;
|
||||
}
|
||||
}
|
||||
|
@ -107,8 +107,7 @@ public enum StateRegistry {
|
||||
private static final IntObjectMap<int[]> LINKED_PROTOCOL_VERSIONS = new IntObjectHashMap<>();
|
||||
|
||||
static {
|
||||
LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_10, new int[] { MINECRAFT_1_11 });
|
||||
LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_11, new int[] { MINECRAFT_1_11_1, MINECRAFT_1_12 });
|
||||
LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_10, new int[] { MINECRAFT_1_11, MINECRAFT_1_11_1, MINECRAFT_1_12 });
|
||||
LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_12, new int[] { MINECRAFT_1_12_1 });
|
||||
LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_12_1, new int[] { MINECRAFT_1_12_2 });
|
||||
}
|
||||
@ -142,6 +141,7 @@ public enum StateRegistry {
|
||||
if (version == null) {
|
||||
throw new IllegalArgumentException("Unknown protocol version " + mapping.protocolVersion);
|
||||
}
|
||||
|
||||
version.packetIdToSupplier.put(mapping.id, packetSupplier);
|
||||
version.packetClassToId.put(clazz, mapping.id);
|
||||
|
||||
|
@ -58,7 +58,7 @@ public class ScoreboardSetScore implements MinecraftPacket {
|
||||
this.entity = ProtocolUtils.readString(buf, 40);
|
||||
this.action = buf.readByte();
|
||||
this.objective = ProtocolUtils.readString(buf, 16);
|
||||
if (this.action == 0) {
|
||||
if (this.action != 1) {
|
||||
value = ProtocolUtils.readVarInt(buf);
|
||||
}
|
||||
}
|
||||
@ -68,7 +68,7 @@ public class ScoreboardSetScore implements MinecraftPacket {
|
||||
ProtocolUtils.writeString(buf, entity);
|
||||
buf.writeByte(action);
|
||||
ProtocolUtils.writeString(buf, objective);
|
||||
if (this.action == 0) {
|
||||
if (this.action != 1) {
|
||||
ProtocolUtils.writeVarInt(buf, value);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package com.velocitypowered.proxy.protocol.remap;
|
||||
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class DummyEntityIdRemapper implements EntityIdRemapper {
|
||||
public static final DummyEntityIdRemapper INSTANCE = new DummyEntityIdRemapper();
|
||||
|
||||
private DummyEntityIdRemapper() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf remap(ByteBuf original, ProtocolConstants.Direction direction) {
|
||||
return original.retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClientEntityId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerEntityId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServerEntityId(int id) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.velocitypowered.proxy.protocol.remap;
|
||||
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* Represents a protocol-specific entity ID remapper for certain Minecraft packets. This is mostly required to support
|
||||
* old versions of Minecraft. For Minecraft 1.9 clients and above, Velocity can use a more efficient method based on
|
||||
* sending JoinGame packets multiple times.
|
||||
*/
|
||||
public interface EntityIdRemapper {
|
||||
/**
|
||||
* Remaps the entity IDs in this packet so that they apply to the player.
|
||||
* @param original the packet to remap
|
||||
* @param direction the direction of the packet
|
||||
* @return a remapped packet, which may either be a retained version of the original buffer or an entirely new buffer
|
||||
*/
|
||||
ByteBuf remap(ByteBuf original, ProtocolConstants.Direction direction);
|
||||
|
||||
int getClientEntityId();
|
||||
|
||||
int getServerEntityId();
|
||||
|
||||
void setServerEntityId(int id);
|
||||
|
||||
static EntityIdRemapper getMapper(int eid, int protocolVersion) {
|
||||
return DummyEntityIdRemapper.INSTANCE;
|
||||
}
|
||||
}
|
@ -4,32 +4,35 @@ import com.velocitypowered.proxy.protocol.packets.Handshake;
|
||||
import com.velocitypowered.proxy.protocol.packets.KeepAlive;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.velocitypowered.proxy.protocol.ProtocolConstants.MINECRAFT_1_12;
|
||||
import static com.velocitypowered.proxy.protocol.ProtocolConstants.MINECRAFT_1_12_1;
|
||||
import static com.velocitypowered.proxy.protocol.ProtocolConstants.MINECRAFT_1_12_2;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class PacketRegistryTest {
|
||||
private StateRegistry.PacketRegistry setupRegistry() {
|
||||
StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry(ProtocolConstants.Direction.CLIENTBOUND);
|
||||
registry.register(Handshake.class, Handshake::new, new StateRegistry.PacketMapping(0x00, ProtocolConstants.MINECRAFT_1_12));
|
||||
registry.register(Handshake.class, Handshake::new, new StateRegistry.PacketMapping(0x00, MINECRAFT_1_12));
|
||||
return registry;
|
||||
}
|
||||
|
||||
@Test
|
||||
void packetRegistryWorks() {
|
||||
StateRegistry.PacketRegistry registry = setupRegistry();
|
||||
MinecraftPacket packet = registry.getVersion(ProtocolConstants.MINECRAFT_1_12).createPacket(0);
|
||||
MinecraftPacket packet = registry.getVersion(MINECRAFT_1_12).createPacket(0);
|
||||
assertNotNull(packet, "Packet was not found in registry");
|
||||
assertEquals(Handshake.class, packet.getClass(), "Registry returned wrong class");
|
||||
|
||||
assertEquals(0, registry.getVersion(ProtocolConstants.MINECRAFT_1_12).getPacketId(packet), "Registry did not return the correct packet ID");
|
||||
assertEquals(0, registry.getVersion(MINECRAFT_1_12).getPacketId(packet), "Registry did not return the correct packet ID");
|
||||
}
|
||||
|
||||
@Test
|
||||
void packetRegistryLinkingWorks() {
|
||||
StateRegistry.PacketRegistry registry = setupRegistry();
|
||||
MinecraftPacket packet = registry.getVersion(ProtocolConstants.MINECRAFT_1_12_1).createPacket(0);
|
||||
MinecraftPacket packet = registry.getVersion(MINECRAFT_1_12_1).createPacket(0);
|
||||
assertNotNull(packet, "Packet was not found in registry");
|
||||
assertEquals(Handshake.class, packet.getClass(), "Registry returned wrong class");
|
||||
assertEquals(0, registry.getVersion(ProtocolConstants.MINECRAFT_1_12_1).getPacketId(packet), "Registry did not return the correct packet ID");
|
||||
assertEquals(0, registry.getVersion(MINECRAFT_1_12_1).getPacketId(packet), "Registry did not return the correct packet ID");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -38,4 +41,14 @@ class PacketRegistryTest {
|
||||
assertThrows(IllegalArgumentException.class, () -> registry.register(Handshake.class, Handshake::new));
|
||||
assertThrows(IllegalArgumentException.class, () -> registry.getVersion(0).getPacketId(new Handshake()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void registrySuppliesCorrectPacketsByProtocol() {
|
||||
StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry(ProtocolConstants.Direction.CLIENTBOUND);
|
||||
registry.register(Handshake.class, Handshake::new, new StateRegistry.PacketMapping(0x00, MINECRAFT_1_12),
|
||||
new StateRegistry.PacketMapping(0x01, MINECRAFT_1_12_1));
|
||||
assertEquals(Handshake.class, registry.getVersion(MINECRAFT_1_12).createPacket(0x00).getClass());
|
||||
assertEquals(Handshake.class, registry.getVersion(MINECRAFT_1_12_1).createPacket(0x01).getClass());
|
||||
assertEquals(Handshake.class, registry.getVersion(MINECRAFT_1_12_2).createPacket(0x01).getClass());
|
||||
}
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren