1 | unit UNetworkClient;
|
---|
2 |
|
---|
3 | {$mode delphi}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils{$IFDEF LINUX}, fpAsync, fpsock{$ENDIF}, Protocol;
|
---|
9 |
|
---|
10 | {$IFDEF LINUX}
|
---|
11 | type
|
---|
12 | { TTCPClientThread }
|
---|
13 |
|
---|
14 | TTCPClientThread = class(TThread)
|
---|
15 | TCPClient: TTCPClient;
|
---|
16 | procedure Execute; override;
|
---|
17 | end;
|
---|
18 |
|
---|
19 | { TNetworkClient }
|
---|
20 |
|
---|
21 | TNetworkClient = class
|
---|
22 | private
|
---|
23 | DataAvailableHandle: Pointer;
|
---|
24 | TCPClientThread: TTCPClientThread;
|
---|
25 | ReceiveBuffer: TMemoryStream;
|
---|
26 | procedure DataAvailableExecute(Sender: TObject);
|
---|
27 | procedure ConnectionStateChangeExecute(Sender: TClientConnectionSocket;
|
---|
28 | OldState, NewState: TConnectionState);
|
---|
29 | procedure DataAvailableSync;
|
---|
30 | public
|
---|
31 | AuxServer: TServerCall;
|
---|
32 | LocalClient: TClientCall;
|
---|
33 | TCPClient: TTCPClient;
|
---|
34 | ClientEventLoop: TEventLoop;
|
---|
35 | function Server(Command: TCommand; Player, Subject: Integer; var Data): Integer;
|
---|
36 | constructor Create;
|
---|
37 | destructor Destroy; override;
|
---|
38 | end;
|
---|
39 |
|
---|
40 | var
|
---|
41 | NetworkClient: TNetworkClient;
|
---|
42 | {$ENDIF}
|
---|
43 |
|
---|
44 | procedure Client(Command, Player: Integer; var Data); stdcall;
|
---|
45 |
|
---|
46 |
|
---|
47 | implementation
|
---|
48 |
|
---|
49 | uses
|
---|
50 | LocalPlayer{$IFDEF LINUX}, Global, UNetworkCommon{$ENDIF};
|
---|
51 |
|
---|
52 | procedure Client(Command, Player: Integer; var Data);
|
---|
53 | {$IFDEF LINUX}
|
---|
54 | var
|
---|
55 | Cmd: TCommand;
|
---|
56 | {$ENDIF}
|
---|
57 | begin
|
---|
58 | {$IFDEF LINUX}
|
---|
59 | Cmd := TCommand(Command);
|
---|
60 | case Cmd of
|
---|
61 | cmInitModule: begin
|
---|
62 | if not Assigned(NetworkClient) then
|
---|
63 | NetworkClient := TNetworkClient.Create;
|
---|
64 | NetworkClient.AuxServer := TInitModuleData(Data).Server;
|
---|
65 | TInitModuleData(Data).Flags := aiThreaded;
|
---|
66 | NetworkClient.LocalClient := LocalPlayer.Client;
|
---|
67 | end;
|
---|
68 | cmReleaseModule: begin
|
---|
69 | FreeAndNil(NetworkClient);
|
---|
70 | end;
|
---|
71 | end;
|
---|
72 | {$ENDIF}
|
---|
73 | end;
|
---|
74 |
|
---|
75 | {$IFDEF LINUX}
|
---|
76 | function LocalServer(Command, Player, Subject: Integer; var Data): Integer; stdcall;
|
---|
77 | begin
|
---|
78 | if Assigned(NetworkClient) then
|
---|
79 | Result := NetworkClient.Server(TCommand(Command), Player, Subject, Data);
|
---|
80 | end;
|
---|
81 |
|
---|
82 | { TTCPClientThread }
|
---|
83 |
|
---|
84 | procedure TTCPClientThread.Execute;
|
---|
85 | begin
|
---|
86 | TCPClient.EventLoop.Run;
|
---|
87 | end;
|
---|
88 |
|
---|
89 | { TNetworkClient }
|
---|
90 |
|
---|
91 | procedure TNetworkClient.DataAvailableExecute(Sender: TObject);
|
---|
92 | begin
|
---|
93 | TCPClientThread.Synchronize(TCPClientThread, DataAvailableSync);
|
---|
94 |
|
---|
95 | ClientEventLoop.ClearDataAvailableNotify(DataAvailableHandle);
|
---|
96 | DataAvailableHandle := ClientEventLoop.SetDataAvailableNotify(TCPClient.Stream.Handle, DataAvailableExecute, nil);
|
---|
97 | end;
|
---|
98 |
|
---|
99 | procedure TNetworkClient.ConnectionStateChangeExecute(
|
---|
100 | Sender: TClientConnectionSocket; OldState, NewState: TConnectionState);
|
---|
101 | begin
|
---|
102 | if NewState = connConnected then
|
---|
103 | DataAvailableHandle := ClientEventLoop.SetDataAvailableNotify(TCPClient.Stream.Handle, DataAvailableExecute, nil);
|
---|
104 | end;
|
---|
105 |
|
---|
106 | procedure TNetworkClient.DataAvailableSync;
|
---|
107 | var
|
---|
108 | Command: Integer;
|
---|
109 | ReadCount: Integer;
|
---|
110 | Player: Integer;
|
---|
111 | Data: array of Byte;
|
---|
112 | begin
|
---|
113 | StreamAppend(ReceiveBuffer, TCPClient.Stream);
|
---|
114 | while ReceiveBuffer.Size >= 2 * SizeOf(Integer) do begin
|
---|
115 | ReceiveBuffer.Position := 0;
|
---|
116 | Command := Integer(ReceiveBuffer.ReadDWord);
|
---|
117 | Player := Integer(ReceiveBuffer.ReadDWord);
|
---|
118 | SetLength(Data, GetCommandDataSize(TCommand(Command)));
|
---|
119 | if Length(Data) > 0 then begin
|
---|
120 | ReadCount := ReceiveBuffer.Read(Data[0], Length(Data));
|
---|
121 | SetLength(Data, ReadCount);
|
---|
122 | end;
|
---|
123 |
|
---|
124 | // Rewrite server address received from network by local handler
|
---|
125 | if Command = cInitModule then begin
|
---|
126 | PInitModuleData(@Data[0])^.Server := LocalServer;
|
---|
127 | end;
|
---|
128 |
|
---|
129 | if Length(Data) > 0 then
|
---|
130 | LocalClient(Command, Player, Data[0])
|
---|
131 | else LocalClient(Command, Player, nil^);
|
---|
132 |
|
---|
133 | StreamRemoveRead(ReceiveBuffer);
|
---|
134 | end;
|
---|
135 | end;
|
---|
136 |
|
---|
137 | function TNetworkClient.Server(Command: TCommand; Player, Subject: Integer;
|
---|
138 | var Data): Integer;
|
---|
139 | begin
|
---|
140 | with TCPClient.Stream do begin
|
---|
141 | WriteDWord(DWord(Command));
|
---|
142 | WriteDWord(Player);
|
---|
143 | WriteDWord(Subject);
|
---|
144 | if GetCommandDataSize(Command) > 0 then
|
---|
145 | Write(Data, GetCommandDataSize(Command));
|
---|
146 | Result := ReadDWord;
|
---|
147 | end;
|
---|
148 | end;
|
---|
149 |
|
---|
150 | constructor TNetworkClient.Create;
|
---|
151 | begin
|
---|
152 | ReceiveBuffer := TMemoryStream.Create;
|
---|
153 | ClientEventLoop := TEventLoop.Create;
|
---|
154 | TCPClient := TTCPClient.Create(nil);
|
---|
155 | with TCPClient do begin
|
---|
156 | EventLoop := ClientEventLoop;
|
---|
157 | Host := '127.0.0.1';
|
---|
158 | Port := CevoNetworkPort;
|
---|
159 | OnConnectionStateChange := ConnectionStateChangeExecute;
|
---|
160 | Active := True;
|
---|
161 | end;
|
---|
162 | TCPClientThread := TTCPClientThread.Create(True);
|
---|
163 | TCPClientThread.TCPClient := TCPClient;
|
---|
164 | TCPClientThread.Start;
|
---|
165 | end;
|
---|
166 |
|
---|
167 | destructor TNetworkClient.Destroy;
|
---|
168 | begin
|
---|
169 | ClientEventLoop.Break;
|
---|
170 | FreeAndNil(TCPClientThread);
|
---|
171 | FreeAndNil(TCPClient);
|
---|
172 | FreeAndNil(ClientEventLoop);
|
---|
173 | FreeAndNil(ReceiveBuffer);
|
---|
174 | inherited;
|
---|
175 | end;
|
---|
176 | {$ENDIF}
|
---|
177 |
|
---|
178 | end.
|
---|
179 |
|
---|