1
+ package me .ANONIMUS .mcprotocol .network .client ;
2
+
3
+ import io .netty .bootstrap .Bootstrap ;
4
+ import io .netty .channel .*;
5
+ import io .netty .channel .nio .NioEventLoopGroup ;
6
+ import io .netty .channel .socket .SocketChannel ;
7
+ import io .netty .channel .socket .nio .NioSocketChannel ;
8
+ import io .netty .handler .timeout .ReadTimeoutHandler ;
9
+ import lombok .Data ;
10
+ import me .ANONIMUS .mcprotocol .exception .BetterException ;
11
+ import me .ANONIMUS .mcprotocol .network .objects .Session ;
12
+ import me .ANONIMUS .mcprotocol .network .protocol .ProtocolType ;
13
+ import me .ANONIMUS .mcprotocol .network .protocol .data .ConnectionState ;
14
+ import me .ANONIMUS .mcprotocol .network .protocol .handlers .PacketCodec ;
15
+ import me .ANONIMUS .mcprotocol .network .protocol .handlers .VarInt21FrameCodec ;
16
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .Packet ;
17
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .PacketDirection ;
18
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .impl .client .play .ClientKeepAlivePacket ;
19
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .impl .server .login .ServerLoginDisconnectPacket ;
20
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .impl .server .login .ServerLoginSetCompressionPacket ;
21
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .impl .server .login .ServerLoginSuccessPacket ;
22
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .impl .server .play .ServerDisconnectPacket ;
23
+ import me .ANONIMUS .mcprotocol .network .protocol .packet .impl .server .play .ServerKeepAlivePacket ;
24
+ import me .ANONIMUS .mcprotocol .objects .GameProfile ;
25
+ import me .ANONIMUS .mcprotocol .objects .ServerData ;
26
+ import net .md_5 .bungee .api .chat .BaseComponent ;
27
+
28
+ import java .net .Proxy ;
29
+ import java .util .concurrent .TimeUnit ;
30
+
31
+ @ Data
32
+ public class MinecraftClient {
33
+ private final ConnectionState connectionState ;
34
+ private final int protocol ;
35
+ private Session remoteSession ;
36
+ private EventLoopGroup group ;
37
+
38
+ private ClientListener listener ;
39
+
40
+ public MinecraftClient (final ConnectionState connectionState , final ProtocolType protocolType ) {
41
+ this .connectionState = connectionState ;
42
+ this .protocol = protocolType .getProtocol ();
43
+ }
44
+
45
+ public MinecraftClient (final ConnectionState connectionState , final int protocol ) {
46
+ this (connectionState , ProtocolType .getByProtocolID (protocol ));
47
+ }
48
+
49
+ public MinecraftClient (final ConnectionState connectionState , final Session session ) {
50
+ this (connectionState , session .getProtocolID ());
51
+ }
52
+
53
+ public void connect (final String ip , final int port ) {
54
+ connect (ip , port , Proxy .NO_PROXY );
55
+ }
56
+
57
+ public void connect (final String ip , final int port , final Proxy proxy ) {
58
+ if (this .group != null || this .remoteSession != null )
59
+ return ;
60
+
61
+ this .group = new NioEventLoopGroup ();
62
+
63
+ Bootstrap bootstrap = new Bootstrap ()
64
+ .group (group )
65
+ .channel (NioSocketChannel .class )
66
+ .option (ChannelOption .TCP_NODELAY , true )
67
+ .option (ChannelOption .IP_TOS , 0x18 )
68
+ .handler (new ChannelInitializer <SocketChannel >() {
69
+ @ Override
70
+ protected void initChannel (SocketChannel socketChannel ) {
71
+ final ChannelPipeline pipeline = socketChannel .pipeline ();
72
+ pipeline .addLast ("timer" , new ReadTimeoutHandler (30 ));
73
+ pipeline .addLast ("frameCodec" , new VarInt21FrameCodec ());
74
+ pipeline .addLast ("packetCodec" , new PacketCodec (connectionState , PacketDirection .CLIENTBOUND ));
75
+ pipeline .addLast ("handler" , new SimpleChannelInboundHandler <Packet >() {
76
+
77
+ @ Override
78
+ public void channelActive (ChannelHandlerContext ctx ) throws InterruptedException {
79
+ TimeUnit .MILLISECONDS .sleep (150 );
80
+ listener .connected (remoteSession );
81
+ }
82
+
83
+ @ Override
84
+ public void exceptionCaught (ChannelHandlerContext ctx , Throwable cause ) {
85
+ cause .printStackTrace ();
86
+ }
87
+
88
+ @ Override
89
+ public void channelInactive (ChannelHandlerContext ctx ) {
90
+ remoteSession .disconnect ();
91
+ }
92
+
93
+ @ Override
94
+ protected void channelRead0 (ChannelHandlerContext channelHandlerContext , Packet packet ) {
95
+ if (packet instanceof ServerLoginSetCompressionPacket ) {
96
+ remoteSession .setCompressionThreshold (((ServerLoginSetCompressionPacket ) packet ).getThreshold ());
97
+ } else if (packet instanceof ServerLoginSuccessPacket ) {
98
+ remoteSession .setGameProfile (new GameProfile (((ServerLoginSuccessPacket ) packet ).getUuid (), ((ServerLoginSuccessPacket ) packet ).getUsername ()));
99
+ remoteSession .setConnectionState (ConnectionState .PLAY );
100
+ } else if (packet instanceof ServerLoginDisconnectPacket ) {
101
+ disconnect (BaseComponent .toLegacyText (((ServerLoginDisconnectPacket ) packet ).getReason ()), null );
102
+ } else if (packet instanceof ServerDisconnectPacket ) {
103
+ disconnect (BaseComponent .toLegacyText (((ServerDisconnectPacket ) packet ).getReason ()), null );
104
+ } else if (packet instanceof ServerKeepAlivePacket ) {
105
+ remoteSession .sendPacket (new ClientKeepAlivePacket (((ServerKeepAlivePacket ) packet ).getKeepaliveId ()));
106
+ }
107
+
108
+ listener .packetReceived (remoteSession , packet );
109
+ }
110
+ });
111
+ }
112
+ });
113
+ try {
114
+ remoteSession = (new Session (bootstrap .connect (ip , port ).syncUninterruptibly ().channel ()));
115
+ remoteSession .setProtocolID (protocol );
116
+ remoteSession .setConnectionState (connectionState );
117
+ remoteSession .setServerData (new ServerData (ip , port ));
118
+ } catch (Exception e ) {
119
+ disconnect ("Connection problem!" , null );
120
+ }
121
+ }
122
+
123
+ public void disconnect (String cause , Throwable throwable ) {
124
+ if (remoteSession != null ) {
125
+ remoteSession .disconnect ();
126
+ }
127
+ group .shutdownGracefully ();
128
+
129
+ listener .disconnected (remoteSession , cause , throwable );
130
+
131
+ throw new BetterException (cause );
132
+ }
133
+ }
0 commit comments