diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index ff85e0d..a073f55 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -38,6 +38,8 @@ public class Ambassador { private static final int MAX_DATA_LENGTH = 16000; private static final int PACKET_LENGTH_INDEX = 14; + private static ForgeHandshakeDataHandler forgeHandshakeDataHandler; + @Inject public Ambassador(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { this.server = server; @@ -60,6 +62,7 @@ public class Ambassador { forgeServer = server.getServer("lobby").orElseThrow(IllegalAccessError::new); loginWrapperChannel = MinecraftChannelIdentifier.create("fml","loginwrapper"); + forgeHandshakeDataHandler = new ForgeHandshakeDataHandler(forgeServer,logger); } private int numberOfRecivedParts; @@ -79,11 +82,12 @@ public class Ambassador { } inbound = (LoginPhaseConnection) event.getConnection(); - recivedParts = new byte[2000000]; + /*recivedParts = new byte[2000000]; recivedBytes = 0; numberOfRecivedParts = 0; ping(continuation); - + */ + forgeHandshakeDataHandler.onPreLogin(event,continuation); } private void ping(Continuation continuation) { @@ -108,26 +112,29 @@ public class Ambassador { logger.info("Downloaded part " + String.valueOf(numberOfRecivedParts) + " out of " + String.valueOf(parts)); - - byte[] temp = pair.getId().getBytes(StandardCharsets.ISO_8859_1); - head = (recivedPartNr-1)*MAX_DATA_LENGTH; - for(int i = 0;i= parts) { - sendHandshake(splitPacket(recivedParts,values)); + sendHandshake(splitPackets(recivedParts,values)); continuation.resume(); } else { ping(continuation); } } - private List splitPacket(byte[] data, int[] startPacketMarkers) { + + private void placePartInArray(byte[] temp, int partNr) { + head = partNr*MAX_DATA_LENGTH; + for(int i = 0;i splitPackets(byte[] data, int[] startPacketMarkers) { List list = new ArrayList<>(); for(int i = 0;i { + sendModlist(p.modListPacket,(LoginPhaseConnection) event.getConnection()); + sendOther(p.otherPackets,(LoginPhaseConnection) event.getConnection()); + continuation.resume(); + }); + } + } + + + + private void sendModlist(byte[] modListPacket, LoginPhaseConnection connection) { + connection.sendLoginPluginMessage(MinecraftChannelIdentifier.create("fml","loginwrapper"), modListPacket, responseBody -> recivedClientModlist = responseBody); + } + + private void sendOther(List otherPackets, LoginPhaseConnection connection) { + otherPackets.forEach((packet) -> { + connection.sendLoginPluginMessage(MinecraftChannelIdentifier.create("fml","loginwrapper"), packet, responseBody -> recivedClientACK = responseBody); + }); + } + + + + private class handshakeReceiver { + + private static final int MAX_DATA_LENGTH = 16000; + + private final Logger logger; + + private int numberOfRecivedParts; + private byte[] recivedParts; + private int recivedBytes; + private final RegisteredServer forgeServer; + + private handshakeReceiver(RegisteredServer server, Logger logger) { + recivedParts = new byte[2000000]; + + this.logger = logger; + this.forgeServer = server; + + } + + public CompletableFuture getHandshake() { + CompletableFuture future = new CompletableFuture(); + ping(future); + return future; + } + + private void ping(CompletableFuture future) { + forgeServer.ping().thenAccept((s) -> onBackendPong(s, future)); + } + + public void onBackendPong(ServerPing status, CompletableFuture future) { + numberOfRecivedParts++; + if ((!status.getModinfo().isPresent()) || (!Objects.equals(status.getModinfo().get().getType(), "ambassador"))) { + future.cancel(true); + logger.error("The specified Forge server is not running the Forge-side version of this plugin!"); + return; + } + + + ModInfo.Mod pair = status.getModinfo().orElseThrow(IllegalAccessError::new).getMods().get(0); + + int[] values = Arrays.stream(pair.getVersion().substring(pair.getVersion().indexOf(":") + 1).split(":")).map(Integer::parseInt).mapToInt(x -> x).toArray(); + + int parts = Integer.parseInt((pair.getVersion().split(":")[0].split("-"))[1]); + int recivedPartNr = Integer.parseInt((pair.getVersion().split(":")[0].split("-"))[0]); + + logger.info("Downloaded part " + String.valueOf(numberOfRecivedParts) + " out of " + String.valueOf(parts)); + + placePartInArray(pair.getId().getBytes(StandardCharsets.ISO_8859_1), recivedPartNr - 1); + + if (numberOfRecivedParts >= parts) { + List packets = splitPackets(recivedParts,values); + future.complete(new CachedServerHandshake("",packets.get(0),packets.subList(1,packets.size()-1))); + } else { + ping(future); + } + } + + + + private void placePartInArray(byte[] temp, int partNr) { + int head = partNr * MAX_DATA_LENGTH; + for (int i = 0; i < temp.length; i++) { + recivedParts[head] = temp[i]; + head++; + recivedBytes++; + } + } + + private byte[] getPacket(byte[] data, int startByteIndex, int lastByteIndex) { + byte[] temp = new byte[lastByteIndex - startByteIndex + 1]; + + for (int i = startByteIndex; i <= lastByteIndex; i++) { + temp[i - startByteIndex] = data[i]; + } + return temp; + } + + + private List splitPackets(byte[] data, int[] startPacketMarkers) { + List list = new ArrayList<>(); + for (int i = 0; i < startPacketMarkers.length - 1; i++) { + list.add(getPacket(data, startPacketMarkers[i], startPacketMarkers[i + 1] - 1)); + } + list.add(getPacket(data, startPacketMarkers[startPacketMarkers.length - 1], recivedBytes - 1)); + return list; + } + + + private class CachedServerHandshake { + private String sessionID; + private byte[] modListPacket; + private List otherPackets; + + private CachedServerHandshake(String sessionID,byte[] modListPacket,List otherPackets) { + this.sessionID = sessionID; + this.modListPacket = modListPacket; + this.otherPackets = otherPackets; + } + } + } +}