diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java index 6d91ce1d0..f89881bab 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java @@ -56,9 +56,15 @@ public class ProtocolPipeline extends Protocol { if (protocolList != null) { protocolList.add(protocol); protocol.init(userConnection); - // Move BaseProtocol to end, so the login packets can be modified by other protocols - protocolList.remove(ProtocolRegistry.BASE_PROTOCOL); - protocolList.add(ProtocolRegistry.BASE_PROTOCOL); + // Move base Protocols to the end, so the login packets can be modified by other protocols + List toMove = new ArrayList<>(); + for (Protocol p : protocolList) { + if (ProtocolRegistry.isBaseProtocol(p)) { + toMove.add(p); + } + } + protocolList.removeAll(toMove); + protocolList.addAll(toMove); } else { throw new NullPointerException("Tried to add protocol to early"); } diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java index 6a450c4c9..4e0883eae 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java @@ -1,10 +1,13 @@ package us.myles.ViaVersion.api.protocol; import com.google.common.collect.Lists; +import com.google.common.collect.Range; import com.google.common.collect.Sets; import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.protocols.base.BaseProtocol; +import us.myles.ViaVersion.protocols.base.BaseProtocol1_13; +import us.myles.ViaVersion.protocols.base.BaseProtocol1_7; import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4; import us.myles.ViaVersion.protocols.protocol1_11_1to1_11.Protocol1_11_1To1_11; import us.myles.ViaVersion.protocols.protocol1_11to1_10.Protocol1_11To1_10; @@ -29,10 +32,14 @@ public class ProtocolRegistry { private static final Map, List>> pathCache = new ConcurrentHashMap<>(); private static final List registerList = Lists.newCopyOnWriteArrayList(); private static final Set supportedVersions = Sets.newConcurrentHashSet(); + private static final List, Protocol>> baseProtocols = Lists.newCopyOnWriteArrayList(); static { // Base Protocol - registerProtocol(BASE_PROTOCOL, Collections.emptyList(), -1); + registerBaseProtocol(BASE_PROTOCOL, Range.lessThan(Integer.MIN_VALUE)); + registerBaseProtocol(new BaseProtocol1_7(), Range.lessThan(ProtocolVersion.v1_13.getId())); + registerBaseProtocol(new BaseProtocol1_13(), Range.atLeast(ProtocolVersion.v1_13.getId())); + // Register built in protocols registerProtocol(new Protocol1_9TO1_8(), Collections.singletonList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_8.getId()); registerProtocol(new Protocol1_9_1TO1_9(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9.getId()); @@ -82,6 +89,25 @@ public class ProtocolRegistry { } } + /** + * Registers a base protocol. + * Base Protocols registered later have higher priority + * Only one base protocol will be added to pipeline + * + * @param baseProtocol Base Protocol to register + * @param supportedProtocols Versions that baseProtocol supports + */ + public static void registerBaseProtocol(Protocol baseProtocol, Range supportedProtocols) { + baseProtocols.add(new Pair<>(supportedProtocols, baseProtocol)); + if (Via.getPlatform().isPluginEnabled()) { + baseProtocol.registerListeners(); + baseProtocol.register(Via.getManager().getProviders()); + refreshVersions(); + } else { + registerList.add(baseProtocol); + } + } + public static void refreshVersions() { supportedVersions.clear(); @@ -197,4 +223,23 @@ public class ProtocolRegistry { } return outputPath; } + + public static Protocol getBaseProtocol(int serverVersion) { + for (Pair, Protocol> rangeProtocol : Lists.reverse(baseProtocols)) { + if (rangeProtocol.getKey().contains(serverVersion)) { + return rangeProtocol.getValue(); + } + } + throw new IllegalStateException("No Base Protocol for " + serverVersion); + } + + public static boolean isBaseProtocol(Protocol protocol) { + for (Pair, Protocol> p : baseProtocols) { + if (p.getValue() == protocol) { + return true; + } + } + return false; + } + } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java index dfc510f8d..a15f78f6b 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java @@ -1,13 +1,5 @@ package us.myles.ViaVersion.protocols.base; -import com.google.common.base.Joiner; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import io.netty.channel.ChannelFuture; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import net.md_5.bungee.api.ChatColor; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Via; @@ -21,137 +13,13 @@ import us.myles.ViaVersion.api.remapper.PacketRemapper; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.packets.Direction; import us.myles.ViaVersion.packets.State; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; -import us.myles.ViaVersion.util.GsonUtil; import java.util.List; -import java.util.UUID; -import java.util.logging.Level; -// TODO Make it work on 1.13 servers public class BaseProtocol extends Protocol { @Override protected void registerPackets() { - /* Outgoing Packets */ - - // Status Response Packet - registerOutgoing(State.STATUS, 0x00, 0x00, new PacketRemapper() { // Status Response Packet - @Override - public void registerMap() { - map(Type.STRING); - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); - String originalStatus = wrapper.get(Type.STRING, 0); - try { - JsonElement json = GsonUtil.getGson().fromJson(originalStatus, JsonElement.class); - JsonObject version; - int protocolVersion = 0; // Unknown! - - if (json.isJsonObject()) { - if (json.getAsJsonObject().has("version")) { - version = json.getAsJsonObject().get("version").getAsJsonObject(); - if (version.has("protocol")) { - protocolVersion = ((Long) version.get("protocol").getAsLong()).intValue(); - } - } else { - version = new JsonObject(); - json.getAsJsonObject().add("version", version); - } - } else { - // Format properly - json = new JsonObject(); - version = new JsonObject(); - json.getAsJsonObject().add("version", version); - } - if (Via.getConfig().isSendSupportedVersions()) //Send supported versions - version.add("supportedVersions", GsonUtil.getGson().toJsonTree(Via.getAPI().getSupportedVersions())); - - if (ProtocolRegistry.SERVER_PROTOCOL == -1) // Set the Server protocol if the detection on startup failed - ProtocolRegistry.SERVER_PROTOCOL = protocolVersion; - // Ensure the server has a version provider - if (Via.getManager().getProviders().get(VersionProvider.class) == null) { - wrapper.user().setActive(false); - return; - } - int protocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); - List> protocols = null; - - // Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it) - if (info.getProtocolVersion() >= protocol || Via.getPlatform().isOldClientsAllowed()) { - protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocol); - } - - if (protocols != null) { - if (protocolVersion != 9999) { - //Fix ServerListPlus - version.addProperty("protocol", info.getProtocolVersion()); - } - } else { - // not compatible :(, *plays very sad violin* - wrapper.user().setActive(false); - } - - if (Via.getConfig().getBlockedProtocols().contains(info.getProtocolVersion())) - version.addProperty("protocol", -1); // Show blocked versions as outdated - - wrapper.set(Type.STRING, 0, GsonUtil.getGson().toJson(json)); // Update value - } catch (JsonParseException e) { - e.printStackTrace(); - } - } - }); - } - }); - - registerOutgoing(State.STATUS, 0x01, 0x01); // Status Pong Packet - - registerOutgoing(State.LOGIN, 0x00, 0x00); // Login Disconnect Packet - registerOutgoing(State.LOGIN, 0x01, 0x01); // Encryption Request Packet - - // Login Success Packet - registerOutgoing(State.LOGIN, 0x02, 0x02, new PacketRemapper() { - @Override - public void registerMap() { - map(Type.STRING); // 0 - UUID as String - map(Type.STRING); // 1 - Player Username - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); - info.setState(State.PLAY); - // Save other info - String stringUUID = wrapper.get(Type.STRING, 0); - if (stringUUID.length() == 32) { // Trimmed UUIDs are 32 characters - // Trimmed - stringUUID = addDashes(stringUUID); - } - UUID uuid = UUID.fromString(stringUUID); - info.setUuid(uuid); - info.setUsername(wrapper.get(Type.STRING, 1)); - // Add to ported clients - Via.getManager().addPortedClient(wrapper.user()); - - if (info.getPipeline().pipes().size() == 1 && info.getPipeline().pipes().get(0).getClass() == BaseProtocol.class) // Only base protocol - wrapper.user().setActive(false); - - if (Via.getManager().isDebug()) { - // Print out the route to console - Via.getPlatform().getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}", - new Object[]{ - wrapper.get(Type.STRING, 1), - info.getProtocolVersion(), - Joiner.on(", ").join(info.getPipeline().pipes(), ", ") - }); - } - } - }); - } - }); - - registerOutgoing(State.LOGIN, 0x03, 0x03); // Login Set Compression Packet /* Incoming Packets */ // Handshake Packet @@ -194,6 +62,9 @@ public class BaseProtocol extends Protocol { wrapper.set(Type.VAR_INT, 0, protocol); } + // Add Base Protocol + pipeline.add(ProtocolRegistry.getBaseProtocol(protocol)); + // Change state if (state == 1) { info.setState(State.STATUS); @@ -205,38 +76,6 @@ public class BaseProtocol extends Protocol { }); } }); - registerIncoming(State.STATUS, 0x00, 0x00); // Status Request Packet - registerIncoming(State.STATUS, 0x01, 0x01); // Status Ping Packet - - // Login Start Packet - registerIncoming(State.LOGIN, 0x00, 0x00, new PacketRemapper() { - @Override - public void registerMap() { - handler(new PacketHandler() { - @Override - public void handle(final PacketWrapper wrapper) throws Exception { - int protocol = wrapper.user().get(ProtocolInfo.class).getProtocolVersion(); - if (Via.getConfig().getBlockedProtocols().contains(protocol)) { - if (!wrapper.user().getChannel().isOpen()) return; - - PacketWrapper disconnectPacket = new PacketWrapper(0x00, null, wrapper.user()); // Disconnect Packet - Protocol1_9TO1_8.FIX_JSON.write(disconnectPacket, ChatColor.translateAlternateColorCodes('&', Via.getConfig().getBlockedDisconnectMsg())); - wrapper.cancel(); // cancel current - - // Send and close - ChannelFuture future = disconnectPacket.sendFuture(BaseProtocol.class); - future.addListener(new GenericFutureListener>() { - @Override - public void operationComplete(Future future) throws Exception { - wrapper.user().getChannel().close(); - } - }); - } - } - }); - } - }); // Login Start Packet - registerIncoming(State.LOGIN, 0x01, 0x01); // Encryption Response Packet } @Override @@ -254,18 +93,9 @@ public class BaseProtocol extends Protocol { super.transform(direction, state, packetWrapper); if (direction == Direction.INCOMING && state == State.HANDSHAKE) { // Disable if it isn't a handshake packet. - if (packetWrapper.getId() > 0) { + if (packetWrapper.getId() != 0) { packetWrapper.user().setActive(false); } } } - - public static String addDashes(String trimmedUUID) { - StringBuilder idBuff = new StringBuilder(trimmedUUID); - idBuff.insert(20, '-'); - idBuff.insert(16, '-'); - idBuff.insert(12, '-'); - idBuff.insert(8, '-'); - return idBuff.toString(); - } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_13.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_13.java new file mode 100644 index 000000000..68acc9750 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_13.java @@ -0,0 +1,195 @@ +package us.myles.ViaVersion.protocols.base; + +import com.google.common.base.Joiner; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import io.netty.channel.ChannelFuture; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; +import net.md_5.bungee.api.ChatColor; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.Protocol; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.api.remapper.PacketHandler; +import us.myles.ViaVersion.api.remapper.PacketRemapper; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.util.GsonUtil; + +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; + +public class BaseProtocol1_13 extends Protocol { + @Override + protected void registerPackets() { + /* Outgoing Packets */ + + // Status Response Packet + registerOutgoing(State.STATUS, 0x00, 0x00, new PacketRemapper() { // Status Response Packet + @Override + public void registerMap() { + map(Type.STRING); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); + String originalStatus = wrapper.get(Type.STRING, 0); + try { + JsonElement json = GsonUtil.getGson().fromJson(originalStatus, JsonElement.class); + JsonObject version; + int protocolVersion = 0; // Unknown! + + if (json.isJsonObject()) { + if (json.getAsJsonObject().has("version")) { + version = json.getAsJsonObject().get("version").getAsJsonObject(); + if (version.has("protocol")) { + protocolVersion = ((Long) version.get("protocol").getAsLong()).intValue(); + } + } else { + version = new JsonObject(); + json.getAsJsonObject().add("version", version); + } + } else { + // Format properly + json = new JsonObject(); + version = new JsonObject(); + json.getAsJsonObject().add("version", version); + } + if (Via.getConfig().isSendSupportedVersions()) //Send supported versions + version.add("supportedVersions", GsonUtil.getGson().toJsonTree(Via.getAPI().getSupportedVersions())); + + if (ProtocolRegistry.SERVER_PROTOCOL == -1) // Set the Server protocol if the detection on startup failed + ProtocolRegistry.SERVER_PROTOCOL = protocolVersion; + // Ensure the server has a version provider + if (Via.getManager().getProviders().get(VersionProvider.class) == null) { + wrapper.user().setActive(false); + return; + } + int protocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); + List> protocols = null; + + // Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it) + if (info.getProtocolVersion() >= protocol || Via.getPlatform().isOldClientsAllowed()) { + protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocol); + } + + if (protocols != null) { + if (protocolVersion != 9999) { + //Fix ServerListPlus + version.addProperty("protocol", info.getProtocolVersion()); + } + } else { + // not compatible :(, *plays very sad violin* + wrapper.user().setActive(false); + } + + if (Via.getConfig().getBlockedProtocols().contains(info.getProtocolVersion())) + version.addProperty("protocol", -1); // Show blocked versions as outdated + + wrapper.set(Type.STRING, 0, GsonUtil.getGson().toJson(json)); // Update value + } catch (JsonParseException e) { + e.printStackTrace(); + } + } + }); + } + }); + + registerOutgoing(State.STATUS, 0x01, 0x01); // Status Pong Packet + + registerOutgoing(State.LOGIN, 0x00, 0x00); // Login Plugin Message + registerOutgoing(State.LOGIN, 0x01, 0x01); // Login Disconnect Packet + registerOutgoing(State.LOGIN, 0x02, 0x02); // Encryption Request Packet + + // Login Success Packet + registerOutgoing(State.LOGIN, 0x03, 0x03, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); // 0 - UUID as String + map(Type.STRING); // 1 - Player Username + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); + info.setState(State.PLAY); + // Save other info + String stringUUID = wrapper.get(Type.STRING, 0); + /*if (stringUUID.length() == 32) { // Trimmed UUIDs are 32 characters + // Trimmed + stringUUID = addDashes(stringUUID); + }*/ + UUID uuid = UUID.fromString(stringUUID); + info.setUuid(uuid); + info.setUsername(wrapper.get(Type.STRING, 1)); + // Add to ported clients + Via.getManager().addPortedClient(wrapper.user()); + + if (info.getPipeline().pipes().size() == 2 + && info.getPipeline().pipes().get(1).getClass() == BaseProtocol1_13.class + && info.getPipeline().pipes().get(0).getClass() == BaseProtocol.class) // Only base protocol + wrapper.user().setActive(false); + + if (Via.getManager().isDebug()) { + // Print out the route to console + Via.getPlatform().getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}", + new Object[]{ + wrapper.get(Type.STRING, 1), + info.getProtocolVersion(), + Joiner.on(", ").join(info.getPipeline().pipes(), ", ") + }); + } + } + }); + } + }); + + registerOutgoing(State.LOGIN, 0x04, 0x04); // Login Set Compression Packet + + /* Incoming Packets */ + + registerIncoming(State.STATUS, 0x00, 0x00); // Status Request Packet + registerIncoming(State.STATUS, 0x01, 0x01); // Status Ping Packet + + registerIncoming(State.LOGIN, 0x00, 0x00); // Login Plugin Message + // Login Start Packet + registerIncoming(State.LOGIN, 0x01, 0x01, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(final PacketWrapper wrapper) throws Exception { + int protocol = wrapper.user().get(ProtocolInfo.class).getProtocolVersion(); + if (Via.getConfig().getBlockedProtocols().contains(protocol)) { + if (!wrapper.user().getChannel().isOpen()) return; + + PacketWrapper disconnectPacket = new PacketWrapper(0x00, null, wrapper.user()); // Disconnect Packet + Protocol1_9TO1_8.FIX_JSON.write(disconnectPacket, ChatColor.translateAlternateColorCodes('&', Via.getConfig().getBlockedDisconnectMsg())); + wrapper.cancel(); // cancel current + + // Send and close + ChannelFuture future = disconnectPacket.sendFuture(BaseProtocol.class); + future.addListener(new GenericFutureListener>() { + @Override + public void operationComplete(Future future) throws Exception { + wrapper.user().getChannel().close(); + } + }); + } + } + }); + } + }); // Login Start Packet + registerIncoming(State.LOGIN, 0x02, 0x02); // Encryption Response Packet + } + + @Override + public void init(UserConnection userConnection) { + + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_7.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_7.java new file mode 100644 index 000000000..468972d5c --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_7.java @@ -0,0 +1,203 @@ +package us.myles.ViaVersion.protocols.base; + +import com.google.common.base.Joiner; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import io.netty.channel.ChannelFuture; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; +import net.md_5.bungee.api.ChatColor; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.Protocol; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.api.remapper.PacketHandler; +import us.myles.ViaVersion.api.remapper.PacketRemapper; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.util.GsonUtil; + +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; + +public class BaseProtocol1_7 extends Protocol { + + @Override + protected void registerPackets() { + /* Outgoing Packets */ + + // Status Response Packet + registerOutgoing(State.STATUS, 0x00, 0x00, new PacketRemapper() { // Status Response Packet + @Override + public void registerMap() { + map(Type.STRING); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); + String originalStatus = wrapper.get(Type.STRING, 0); + try { + JsonElement json = GsonUtil.getGson().fromJson(originalStatus, JsonElement.class); + JsonObject version; + int protocolVersion = 0; // Unknown! + + if (json.isJsonObject()) { + if (json.getAsJsonObject().has("version")) { + version = json.getAsJsonObject().get("version").getAsJsonObject(); + if (version.has("protocol")) { + protocolVersion = ((Long) version.get("protocol").getAsLong()).intValue(); + } + } else { + version = new JsonObject(); + json.getAsJsonObject().add("version", version); + } + } else { + // Format properly + json = new JsonObject(); + version = new JsonObject(); + json.getAsJsonObject().add("version", version); + } + if (Via.getConfig().isSendSupportedVersions()) //Send supported versions + version.add("supportedVersions", GsonUtil.getGson().toJsonTree(Via.getAPI().getSupportedVersions())); + + if (ProtocolRegistry.SERVER_PROTOCOL == -1) // Set the Server protocol if the detection on startup failed + ProtocolRegistry.SERVER_PROTOCOL = protocolVersion; + // Ensure the server has a version provider + if (Via.getManager().getProviders().get(VersionProvider.class) == null) { + wrapper.user().setActive(false); + return; + } + int protocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); + List> protocols = null; + + // Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it) + if (info.getProtocolVersion() >= protocol || Via.getPlatform().isOldClientsAllowed()) { + protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocol); + } + + if (protocols != null) { + if (protocolVersion != 9999) { + //Fix ServerListPlus + version.addProperty("protocol", info.getProtocolVersion()); + } + } else { + // not compatible :(, *plays very sad violin* + wrapper.user().setActive(false); + } + + if (Via.getConfig().getBlockedProtocols().contains(info.getProtocolVersion())) + version.addProperty("protocol", -1); // Show blocked versions as outdated + + wrapper.set(Type.STRING, 0, GsonUtil.getGson().toJson(json)); // Update value + } catch (JsonParseException e) { + e.printStackTrace(); + } + } + }); + } + }); + + registerOutgoing(State.STATUS, 0x01, 0x01); // Status Pong Packet + + registerOutgoing(State.LOGIN, 0x00, 0x00); // Login Disconnect Packet + registerOutgoing(State.LOGIN, 0x01, 0x01); // Encryption Request Packet + + // Login Success Packet + registerOutgoing(State.LOGIN, 0x02, 0x02, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); // 0 - UUID as String + map(Type.STRING); // 1 - Player Username + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); + info.setState(State.PLAY); + // Save other info + String stringUUID = wrapper.get(Type.STRING, 0); + if (stringUUID.length() == 32) { // Trimmed UUIDs are 32 characters + // Trimmed + stringUUID = addDashes(stringUUID); + } + UUID uuid = UUID.fromString(stringUUID); + info.setUuid(uuid); + info.setUsername(wrapper.get(Type.STRING, 1)); + // Add to ported clients + Via.getManager().addPortedClient(wrapper.user()); + + if (info.getPipeline().pipes().size() == 2 + && info.getPipeline().pipes().get(1).getClass() == BaseProtocol1_7.class + && info.getPipeline().pipes().get(0).getClass() == BaseProtocol.class) // Only base protocol + wrapper.user().setActive(false); + + if (Via.getManager().isDebug()) { + // Print out the route to console + Via.getPlatform().getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}", + new Object[]{ + wrapper.get(Type.STRING, 1), + info.getProtocolVersion(), + Joiner.on(", ").join(info.getPipeline().pipes(), ", ") + }); + } + } + }); + } + }); + + registerOutgoing(State.LOGIN, 0x03, 0x03); // Login Set Compression Packet + + /* Incoming Packets */ + + registerIncoming(State.STATUS, 0x00, 0x00); // Status Request Packet + registerIncoming(State.STATUS, 0x01, 0x01); // Status Ping Packet + + // Login Start Packet + registerIncoming(State.LOGIN, 0x00, 0x00, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(final PacketWrapper wrapper) throws Exception { + int protocol = wrapper.user().get(ProtocolInfo.class).getProtocolVersion(); + if (Via.getConfig().getBlockedProtocols().contains(protocol)) { + if (!wrapper.user().getChannel().isOpen()) return; + + PacketWrapper disconnectPacket = new PacketWrapper(0x00, null, wrapper.user()); // Disconnect Packet + Protocol1_9TO1_8.FIX_JSON.write(disconnectPacket, ChatColor.translateAlternateColorCodes('&', Via.getConfig().getBlockedDisconnectMsg())); + wrapper.cancel(); // cancel current + + // Send and close + ChannelFuture future = disconnectPacket.sendFuture(BaseProtocol.class); + future.addListener(new GenericFutureListener>() { + @Override + public void operationComplete(Future future) throws Exception { + wrapper.user().getChannel().close(); + } + }); + } + } + }); + } + }); // Login Start Packet + registerIncoming(State.LOGIN, 0x01, 0x01); // Encryption Response Packet + } + + @Override + public void init(UserConnection userConnection) { + + } + + public static String addDashes(String trimmedUUID) { + StringBuilder idBuff = new StringBuilder(trimmedUUID); + idBuff.insert(20, '-'); + idBuff.insert(16, '-'); + idBuff.insert(12, '-'); + idBuff.insert(8, '-'); + return idBuff.toString(); + } +}