3
0
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:
Andrew Steinborn 2018-07-30 20:35:05 -04:00
Ursprung 47bea89146
Commit 6b5cd703f0
7 geänderte Dateien mit 101 neuen und 13 gelöschten Zeilen

Datei anzeigen

@ -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();

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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);

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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) {
}
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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());
}
}