package rsx; /** * Builds the echo packet. * * The nonce travels in the packet's channel name, so no payload buffer has to * be built or parsed: a server that supports the mod echoes the channel back * and the client recognises its own echo by the name. * * The packet class is vendor code with no stable name, so the profile has to * carry it. When it does not, the echo is simply unavailable and the modloader * falls back to the keep-alive estimate - which is why nothing here fails loudly * on a build it does not recognise. */ public final class EchoPacket { public static final String CHANNEL = "rsx_echo"; private EchoPacket() { } /** * @return a packet carrying the nonce, or null when this build has no echo */ public static Object create(Object netHandlerPlayClient, int nonce) { Profile p = Resolver.profile(); if (p == null) { return null; } String[] ctor = p.member("rsx.net.echoPacket", "ctor"); if (ctor == null) { return null; } try { Class cls = Resolver.findLoaded(p.obf("rsx.net.echoPacket")); if (cls == null) { return null; } Class buffer = Resolver.findLoaded( p.obf("rsx.net.echoBuffer")); java.lang.reflect.Constructor c = cls.getDeclaredConstructor( String.class, buffer); c.setAccessible(true); return c.newInstance(CHANNEL + ":" + nonce, null); } catch (Throwable t) { return null; } } /** The nonce from a channel name, or -1 when it is not ours. */ public static int nonceOf(String channel) { if (channel == null || !channel.startsWith(CHANNEL + ":")) { return -1; } try { return Integer.parseInt(channel.substring(CHANNEL.length() + 1)); } catch (Throwable t) { return -1; } } /** True when this build can send an echo at all. */ public static boolean available() { Profile p = Resolver.profile(); return p != null && p.member("rsx.net.echoPacket", "ctor") != null; } }