· 6 years ago · May 05, 2019, 08:48 AM
1package org.spacehq.mc.protocol;
2
3import net.vexio.hproxy.managers.FakeNickManager;
4import org.spacehq.mc.auth.data.GameProfile;
5import org.spacehq.mc.auth.exception.request.InvalidCredentialsException;
6import org.spacehq.mc.auth.exception.request.RequestException;
7import org.spacehq.mc.auth.exception.request.ServiceUnavailableException;
8import org.spacehq.mc.auth.service.SessionService;
9import org.spacehq.mc.protocol.data.SubProtocol;
10import org.spacehq.mc.protocol.data.game.values.HandshakeIntent;
11import org.spacehq.mc.protocol.data.status.ServerStatusInfo;
12import org.spacehq.mc.protocol.data.status.handler.ServerInfoHandler;
13import org.spacehq.mc.protocol.data.status.handler.ServerPingTimeHandler;
14import org.spacehq.mc.protocol.packet.handshake.client.HandshakePacket;
15import org.spacehq.mc.protocol.packet.ingame.client.ClientKeepAlivePacket;
16import org.spacehq.mc.protocol.packet.ingame.server.ServerDisconnectPacket;
17import org.spacehq.mc.protocol.packet.ingame.server.ServerKeepAlivePacket;
18import org.spacehq.mc.protocol.packet.ingame.server.ServerSetCompressionPacket;
19import org.spacehq.mc.protocol.packet.login.client.EncryptionResponsePacket;
20import org.spacehq.mc.protocol.packet.login.client.LoginStartPacket;
21import org.spacehq.mc.protocol.packet.login.server.EncryptionRequestPacket;
22import org.spacehq.mc.protocol.packet.login.server.LoginDisconnectPacket;
23import org.spacehq.mc.protocol.packet.login.server.LoginSetCompressionPacket;
24import org.spacehq.mc.protocol.packet.login.server.LoginSuccessPacket;
25import org.spacehq.mc.protocol.packet.status.client.StatusPingPacket;
26import org.spacehq.mc.protocol.packet.status.client.StatusQueryPacket;
27import org.spacehq.mc.protocol.packet.status.server.StatusPongPacket;
28import org.spacehq.mc.protocol.packet.status.server.StatusResponsePacket;
29import org.spacehq.mc.protocol.util.CryptUtil;
30import org.spacehq.packetlib.event.session.ConnectedEvent;
31import org.spacehq.packetlib.event.session.PacketReceivedEvent;
32import org.spacehq.packetlib.event.session.SessionAdapter;
33
34import javax.crypto.SecretKey;
35import java.math.BigInteger;
36import java.net.Proxy;
37import java.util.UUID;
38
39public class ClientListener extends SessionAdapter {
40 public ClientListener() {
41 }
42
43 public void packetReceived(PacketReceivedEvent event) {
44 MinecraftProtocol protocol = (MinecraftProtocol)event.getSession().getPacketProtocol();
45 if (protocol.getSubProtocol() == SubProtocol.LOGIN) {
46 if (event.getPacket() instanceof EncryptionRequestPacket) {
47 EncryptionRequestPacket packet = event.getPacket();
48 SecretKey key = CryptUtil.generateSharedKey();
49 Proxy proxy = event.getSession().getFlag("auth-proxy");
50 if (proxy == null) {
51 proxy = Proxy.NO_PROXY;
52 }
53
54 GameProfile profile = event.getSession().getFlag("profile");
55 String serverHash = (new BigInteger(CryptUtil.getServerIdHash(packet.getServerId(), packet.getPublicKey(), key))).toString(16);
56 String accessToken = event.getSession().getFlag("access-token");
57
58 try {
59 (new SessionService(proxy)).joinServer(profile, accessToken, serverHash);
60 } catch (ServiceUnavailableException var10) {
61 event.getSession().disconnect("Login failed: Authentication service unavailable.", var10);
62 return;
63 } catch (InvalidCredentialsException var11) {
64 event.getSession().disconnect("Login failed: Invalid login session.", var11);
65 return;
66 } catch (RequestException var12) {
67 event.getSession().disconnect("Login failed: Authentication error: " + var12.getMessage(), var12);
68 return;
69 }
70
71 event.getSession().send(new EncryptionResponsePacket(key, packet.getPublicKey(), packet.getVerifyToken()));
72 protocol.enableEncryption(key);
73 } else if (event.getPacket() instanceof LoginSuccessPacket) {
74 LoginSuccessPacket packet = event.getPacket();
75 event.getSession().setFlag("profile", packet.getProfile());
76 protocol.setSubProtocol(SubProtocol.GAME, true, event.getSession());
77 } else if (event.getPacket() instanceof LoginDisconnectPacket) {
78 LoginDisconnectPacket packet = event.getPacket();
79 event.getSession().disconnect(packet.getReason().getFullText());
80 } else if (event.getPacket() instanceof LoginSetCompressionPacket) {
81 event.getSession().setCompressionThreshold(((LoginSetCompressionPacket)event.getPacket()).getThreshold());
82 }
83 } else if (protocol.getSubProtocol() == SubProtocol.STATUS) {
84 if (event.getPacket() instanceof StatusResponsePacket) {
85 ServerStatusInfo info = ((StatusResponsePacket)event.getPacket()).getInfo();
86 ServerInfoHandler handler = event.getSession().getFlag("server-info-handler");
87 if (handler != null) {
88 handler.handle(event.getSession(), info);
89 }
90
91 event.getSession().send(new StatusPingPacket(System.currentTimeMillis()));
92 } else if (event.getPacket() instanceof StatusPongPacket) {
93 long time = System.currentTimeMillis() - ((StatusPongPacket)event.getPacket()).getPingTime();
94 ServerPingTimeHandler handler = event.getSession().getFlag("server-ping-time-handler");
95 if (handler != null) {
96 handler.handle(event.getSession(), time);
97 }
98
99 event.getSession().disconnect("Finished");
100 }
101 } else if (protocol.getSubProtocol() == SubProtocol.GAME) {
102 if (event.getPacket() instanceof ServerKeepAlivePacket) {
103 event.getSession().send(new ClientKeepAlivePacket(((ServerKeepAlivePacket)event.getPacket()).getPingId()));
104 } else if (event.getPacket() instanceof ServerDisconnectPacket) {
105 event.getSession().disconnect(((ServerDisconnectPacket)event.getPacket()).getReason().getFullText());
106 } else if (event.getPacket() instanceof ServerSetCompressionPacket) {
107 event.getSession().setCompressionThreshold(((ServerSetCompressionPacket)event.getPacket()).getThreshold());
108 }
109 }
110 }
111
112 public void connected(ConnectedEvent event) {
113 MinecraftProtocol protocol = (MinecraftProtocol)event.getSession().getPacketProtocol();
114 if (protocol.getSubProtocol() == SubProtocol.LOGIN) {
115 GameProfile profile = event.getSession().getFlag("profile");
116 protocol.setSubProtocol(SubProtocol.HANDSHAKE, true, event.getSession());
117 if (!FakeNickManager.names.containsKey(profile.getName())) event.getSession().send(new HandshakePacket(47, event.getSession().getHost(), event.getSession().getPort(), HandshakeIntent.LOGIN));
118 else {
119 String hostname = event.getSession().getHost() + "\u0000127.0.0.1\u0000" + UUID.nameUUIDFromBytes(("OfflinePlayer:" + FakeNickManager.names.get(profile.getName())).getBytes()).toString().replace("-", "");
120 event.getSession().send(new HandshakePacket(47, hostname, event.getSession().getPort(), HandshakeIntent.LOGIN));
121 FakeNickManager.names.remove(profile.getName());
122 }
123 protocol.setSubProtocol(SubProtocol.LOGIN, true, event.getSession());
124 event.getSession().send(new LoginStartPacket(profile.getName()));
125 } else if (protocol.getSubProtocol() == SubProtocol.STATUS) {
126 protocol.setSubProtocol(SubProtocol.HANDSHAKE, true, event.getSession());
127 event.getSession().send(new HandshakePacket(47, event.getSession().getHost(), event.getSession().getPort(), HandshakeIntent.STATUS));
128 protocol.setSubProtocol(SubProtocol.STATUS, true, event.getSession());
129 event.getSession().send(new StatusQueryPacket());
130 }
131
132 }
133}