13
0
geforkt von Mirrors/Velocity

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.connection.client.ClientPlaySessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.packets.*; import com.velocitypowered.proxy.protocol.packets.*;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
@ -46,7 +47,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
PluginMessage pm = (PluginMessage) packet; PluginMessage pm = (PluginMessage) packet;
try { try {
PluginMessage newPacket = pm; PluginMessage newPacket = pm;
if (!canForwardMessage(newPacket)) { if (!canForwardPluginMessage(newPacket)) {
return; return;
} }
@ -72,7 +73,10 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public void handleUnknown(ByteBuf buf) { 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 @Override
@ -80,7 +84,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), throwable); connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), throwable);
} }
private boolean canForwardMessage(PluginMessage message) { private boolean canForwardPluginMessage(PluginMessage message) {
// TODO: Update for 1.13 // TODO: Update for 1.13
ClientPlaySessionHandler playerHandler = ClientPlaySessionHandler playerHandler =
(ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler(); (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.Scoreboard;
import com.velocitypowered.proxy.data.scoreboard.Team; import com.velocitypowered.proxy.data.scoreboard.Team;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.packets.*; import com.velocitypowered.proxy.protocol.packets.*;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.remap.EntityIdRemapper;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import com.velocitypowered.proxy.util.ThrowableUtils; import com.velocitypowered.proxy.util.ThrowableUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
@ -39,6 +41,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
private PluginMessage brandMessage; private PluginMessage brandMessage;
private int currentDimension; private int currentDimension;
private Scoreboard serverScoreboard = new Scoreboard(); private Scoreboard serverScoreboard = new Scoreboard();
private EntityIdRemapper idRemapper;
public ClientPlaySessionHandler(ConnectedPlayer player) { public ClientPlaySessionHandler(ConnectedPlayer player) {
this.player = player; this.player = player;
@ -95,7 +98,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public void handleUnknown(ByteBuf buf) { 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 @Override
@ -123,6 +127,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
spawned = true; spawned = true;
currentDimension = joinGame.getDimension(); currentDimension = joinGame.getDimension();
player.getConnection().delayedWrite(joinGame); player.getConnection().delayedWrite(joinGame);
idRemapper = EntityIdRemapper.getMapper(joinGame.getEntityId(), player.getConnection().getProtocolVersion());
} else { } else {
// In order to handle switching to another server we will need send three packets: // In order to handle switching to another server we will need send three packets:
// - The join game packet from the backend server // - The join game packet from the backend server
@ -130,6 +135,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
// - Another respawn with the correct dimension // - 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 // We can't simply ignore the packet with the different dimension. If you try to be smart about it it doesn't
// work. // work.
idRemapper.setServerEntityId(joinGame.getEntityId());
player.getConnection().delayedWrite(joinGame); player.getConnection().delayedWrite(joinGame);
int tempDim = joinGame.getDimension() == 0 ? -1 : 0; int tempDim = joinGame.getDimension() == 0 ? -1 : 0;
player.getConnection().delayedWrite(new Respawn(tempDim, joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType())); 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() { public Set<String> getClientPluginMsgChannels() {
return clientPluginMsgChannels; 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<>(); private static final IntObjectMap<int[]> LINKED_PROTOCOL_VERSIONS = new IntObjectHashMap<>();
static { static {
LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_10, new int[] { MINECRAFT_1_11 }); 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_11, new int[] { 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, new int[] { MINECRAFT_1_12_1 });
LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_12_1, new int[] { MINECRAFT_1_12_2 }); LINKED_PROTOCOL_VERSIONS.put(MINECRAFT_1_12_1, new int[] { MINECRAFT_1_12_2 });
} }
@ -142,6 +141,7 @@ public enum StateRegistry {
if (version == null) { if (version == null) {
throw new IllegalArgumentException("Unknown protocol version " + mapping.protocolVersion); throw new IllegalArgumentException("Unknown protocol version " + mapping.protocolVersion);
} }
version.packetIdToSupplier.put(mapping.id, packetSupplier); version.packetIdToSupplier.put(mapping.id, packetSupplier);
version.packetClassToId.put(clazz, mapping.id); version.packetClassToId.put(clazz, mapping.id);

Datei anzeigen

@ -58,7 +58,7 @@ public class ScoreboardSetScore implements MinecraftPacket {
this.entity = ProtocolUtils.readString(buf, 40); this.entity = ProtocolUtils.readString(buf, 40);
this.action = buf.readByte(); this.action = buf.readByte();
this.objective = ProtocolUtils.readString(buf, 16); this.objective = ProtocolUtils.readString(buf, 16);
if (this.action == 0) { if (this.action != 1) {
value = ProtocolUtils.readVarInt(buf); value = ProtocolUtils.readVarInt(buf);
} }
} }
@ -68,7 +68,7 @@ public class ScoreboardSetScore implements MinecraftPacket {
ProtocolUtils.writeString(buf, entity); ProtocolUtils.writeString(buf, entity);
buf.writeByte(action); buf.writeByte(action);
ProtocolUtils.writeString(buf, objective); ProtocolUtils.writeString(buf, objective);
if (this.action == 0) { if (this.action != 1) {
ProtocolUtils.writeVarInt(buf, value); 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 com.velocitypowered.proxy.protocol.packets.KeepAlive;
import org.junit.jupiter.api.Test; 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.*; import static org.junit.jupiter.api.Assertions.*;
class PacketRegistryTest { class PacketRegistryTest {
private StateRegistry.PacketRegistry setupRegistry() { private StateRegistry.PacketRegistry setupRegistry() {
StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry(ProtocolConstants.Direction.CLIENTBOUND); 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; return registry;
} }
@Test @Test
void packetRegistryWorks() { void packetRegistryWorks() {
StateRegistry.PacketRegistry registry = setupRegistry(); 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"); assertNotNull(packet, "Packet was not found in registry");
assertEquals(Handshake.class, packet.getClass(), "Registry returned wrong class"); 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 @Test
void packetRegistryLinkingWorks() { void packetRegistryLinkingWorks() {
StateRegistry.PacketRegistry registry = setupRegistry(); 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"); assertNotNull(packet, "Packet was not found in registry");
assertEquals(Handshake.class, packet.getClass(), "Registry returned wrong class"); 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 @Test
@ -38,4 +41,14 @@ class PacketRegistryTest {
assertThrows(IllegalArgumentException.class, () -> registry.register(Handshake.class, Handshake::new)); assertThrows(IllegalArgumentException.class, () -> registry.register(Handshake.class, Handshake::new));
assertThrows(IllegalArgumentException.class, () -> registry.getVersion(0).getPacketId(new Handshake())); 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());
}
} }