6 e_log
, e_fixedbuffer
, ENet
, ENetTypes
, ENetPlatform
, Classes
;
9 NET_PROTOCOL_VER
= 164;
15 NET_CHAN_IMPORTANT
= 1;
18 NET_CHAN_PLAYERPOS
= 4;
20 NET_CHAN_MONSTERPOS
= 6;
21 NET_CHAN_LARGEDATA
= 7;
23 NET_CHAN_DOWNLOAD
= 9;
34 NET_DISC_NONE
: enet_uint32
= 0;
35 NET_DISC_PROTOCOL
: enet_uint32
= 1;
36 NET_DISC_VERSION
: enet_uint32
= 2;
37 NET_DISC_FULL
: enet_uint32
= 3;
38 NET_DISC_KICK
: enet_uint32
= 4;
39 NET_DISC_DOWN
: enet_uint32
= 5;
40 NET_DISC_PASSWORD
: enet_uint32
= 6;
41 NET_DISC_TEMPBAN
: enet_uint32
= 7;
42 NET_DISC_BAN
: enet_uint32
= 8;
43 NET_DISC_MAX
: enet_uint32
= 8;
49 BANLIST_FILENAME
= 'banlist.txt';
58 RequestedFullUpdate
: Boolean;
66 pTNetClient
= ^TNetClient
;
68 AByte
= array of Byte;
71 NetInitDone
: Boolean = False;
72 NetMode
: Byte = NET_NONE
;
74 NetServerName
: string = 'Unnamed Server';
75 NetPassword
: string = '';
76 NetPort
: Word = 25666;
78 NetAllowRCON
: Boolean = False;
79 NetRCONPassword
: string = '';
81 NetTimeToUpdate
: Cardinal = 0;
82 NetTimeToReliable
: Cardinal = 0;
83 NetTimeToMaster
: Cardinal = 0;
85 NetHost
: pENetHost
= nil;
86 NetPeer
: pENetPeer
= nil;
90 NetPongAddr
: ENetAddress
;
91 NetPongSock
: ENetSocket
= ENET_SOCKET_NULL
;
93 NetUseMaster
: Boolean = True;
94 NetSlistAddr
: ENetAddress
;
95 NetSlistIP
: string = 'mpms.doom2d.org';
96 NetSlistPort
: Word = 25665;
98 NetClientIP
: string = '127.0.0.1';
99 NetClientPort
: Word = 25666;
101 NetIn
, NetOut
: TBuffer
;
103 NetClients
: array of TNetClient
;
104 NetClientCount
: Byte = 0;
105 NetMaxClients
: Byte = 255;
106 NetBannedHosts
: array of TBanRecord
;
108 NetState
: Integer = NET_STATE_NONE
;
110 NetMyID
: Integer = -1;
111 NetPlrUID1
: Integer = -1;
112 NetPlrUID2
: Integer = -1;
114 NetInterpLevel
: Integer = 1;
115 NetUpdateRate
: Cardinal = 0; // as soon as possible
116 NetRelupdRate
: Cardinal = 18; // around two times a second
117 NetMasterRate
: Cardinal = 60000;
119 NetForcePlayerUpdate
: Boolean = False;
120 NetPredictSelf
: Boolean = True;
121 NetGotKeys
: Boolean = False;
123 NetGotEverything
: Boolean = False;
125 function g_Net_Init(): Boolean;
126 procedure g_Net_Cleanup();
127 procedure g_Net_Free();
128 procedure g_Net_Flush();
130 function g_Net_Host(IPAddr
: LongWord; Port
: enet_uint16
; MaxClients
: Cardinal = 16): Boolean;
131 procedure g_Net_Host_Die();
132 procedure g_Net_Host_Send(ID
: Integer; Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
133 function g_Net_Host_Update(): enet_size_t
;
135 function g_Net_Connect(IP
: string; Port
: enet_uint16
): Boolean;
136 procedure g_Net_Disconnect(Forced
: Boolean = False);
137 procedure g_Net_Client_Send(Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
138 function g_Net_Client_Update(): enet_size_t
;
139 function g_Net_Client_UpdateWhileLoading(): enet_size_t
;
141 function g_Net_Client_ByName(Name
: string): pTNetClient
;
142 function g_Net_Client_ByPlayer(PID
: Word): pTNetClient
;
143 function g_Net_ClientName_ByID(ID
: Integer): string;
145 procedure g_Net_SendData(Data
:AByte
; peer
: pENetPeer
; Reliable
: Boolean; Chan
: Byte = NET_CHAN_DOWNLOAD
);
146 function g_Net_Wait_Event(msgId
: Word): TMemoryStream
;
148 function IpToStr(IP
: LongWord): string;
149 function StrToIp(IPstr
: string; var IP
: LongWord): Boolean;
151 function g_Net_IsHostBanned(IP
: LongWord; Perm
: Boolean = False): Boolean;
152 procedure g_Net_BanHost(IP
: LongWord; Perm
: Boolean = True); overload
;
153 procedure g_Net_BanHost(IP
: string; Perm
: Boolean = True); overload
;
154 function g_Net_UnbanHost(IP
: string): Boolean; overload
;
155 function g_Net_UnbanHost(IP
: LongWord): Boolean; overload
;
156 procedure g_Net_UnbanNonPermHosts();
157 procedure g_Net_SaveBanList();
163 e_input
, g_nethandler
, g_netmsg
, g_netmaster
, g_player
, g_window
, g_console
,
164 g_main
, g_game
, g_language
, g_weapons
;
167 { /// SERVICE FUNCTIONS /// }
170 function g_Net_FindSlot(): Integer;
179 for I
:= Low(NetClients
) to High(NetClients
) do
181 if NetClients
[I
].Used
then
190 if C
>= NetMaxClients
then
198 if (Length(NetClients
) >= NetMaxClients
) then
202 SetLength(NetClients
, Length(NetClients
) + 1);
203 N
:= High(NetClients
);
209 NetClients
[N
].Used
:= True;
210 NetClients
[N
].ID
:= N
;
211 NetClients
[N
].RequestedFullUpdate
:= False;
212 NetClients
[N
].RCONAuth
:= False;
213 NetClients
[N
].Voted
:= False;
214 NetClients
[N
].Player
:= 0;
220 function g_Net_Init(): Boolean;
226 e_Buffer_Clear(@NetIn
);
227 e_Buffer_Clear(@NetOut
);
228 SetLength(NetClients
, 0);
234 NetAddr
.port
:= 25666;
235 SetLength(NetBannedHosts
, 0);
236 if FileExists(DataDir
+ BANLIST_FILENAME
) then
238 Assign(F
, DataDir
+ BANLIST_FILENAME
);
243 if StrToIp(IPstr
, IP
) then
250 Result
:= (enet_initialize() = 0);
253 procedure g_Net_Flush();
255 enet_host_flush(NetHost
);
258 procedure g_Net_Cleanup();
260 e_Buffer_Clear(@NetIn
);
261 e_Buffer_Clear(@NetOut
);
263 SetLength(NetClients
, 0);
273 NetState
:= NET_STATE_NONE
;
275 NetPongSock
:= ENET_SOCKET_NULL
;
277 NetTimeToMaster
:= 0;
278 NetTimeToUpdate
:= 0;
279 NetTimeToReliable
:= 0;
284 procedure g_Net_Free();
289 NetInitDone
:= False;
293 { /// SERVER FUNCTIONS /// }
296 function g_Net_Host(IPAddr
: LongWord; Port
: enet_uint16
; MaxClients
: Cardinal = 16): Boolean;
298 if NetMode
<> NET_NONE
then
300 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_INGAME
]);
307 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_HOST
], [Port
]));
308 if not NetInitDone
then
310 if (not g_Net_Init()) then
312 g_Console_Add(_lc
[I_NET_MSG_FERROR
] + _lc
[I_NET_ERR_ENET
]);
320 NetAddr
.host
:= IPAddr
;
321 NetAddr
.port
:= Port
;
323 NetHost
:= enet_host_create(@NetAddr
, NET_MAXCLIENTS
, NET_CHANS
, 0, 0);
325 if (NetHost
= nil) then
327 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + Format(_lc
[I_NET_ERR_HOST
], [Port
]));
333 NetPongSock
:= enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM
);
334 if NetPongSock
<> ENET_SOCKET_NULL
then
336 NetPongAddr
.host
:= IPAddr
;
337 NetPongAddr
.port
:= Port
+ 1;
338 if enet_socket_bind(NetPongSock
, @NetPongAddr
) < 0 then
340 enet_socket_destroy(NetPongSock
);
341 NetPongSock
:= ENET_SOCKET_NULL
;
344 enet_socket_set_option(NetPongSock
, ENET_SOCKOPT_NONBLOCK
, 1);
347 NetMode
:= NET_SERVER
;
348 e_Buffer_Clear(@NetOut
);
351 procedure g_Net_Host_Die();
355 if NetMode
<> NET_SERVER
then Exit
;
357 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_DISCALL
]);
358 for I
:= 0 to High(NetClients
) do
359 if NetClients
[I
].Used
then
360 enet_peer_disconnect(NetClients
[I
].Peer
, NET_DISC_DOWN
);
362 while enet_host_service(NetHost
, @NetEvent
, 1000) > 0 do
363 if NetEvent
.kind
= ENET_EVENT_TYPE_RECEIVE
then
364 enet_packet_destroy(NetEvent
.packet
);
366 for I
:= 0 to High(NetClients
) do
367 if NetClients
[I
].Used
then
369 FreeMemory(NetClients
[I
].Peer
^.data
);
370 NetClients
[I
].Peer
^.data
:= nil;
371 enet_peer_reset(NetClients
[I
].Peer
);
372 NetClients
[I
].Peer
:= nil;
373 NetClients
[I
].Used
:= False;
376 if (NetMPeer
<> nil) and (NetMHost
<> nil) then g_Net_Slist_Disconnect
;
377 if NetPongSock
<> ENET_SOCKET_NULL
then
378 enet_socket_destroy(NetPongSock
);
380 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_DIE
]);
381 enet_host_destroy(NetHost
);
386 e_WriteLog('NET: Server stopped', MSG_NOTIFY
);
390 procedure g_Net_Host_Send(ID
: Integer; Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
396 F
:= LongWord(ENET_PACKET_FLAG_RELIABLE
)
402 if ID
> High(NetClients
) then Exit
;
403 if NetClients
[ID
].Peer
= nil then Exit
;
405 P
:= enet_packet_create(Addr(NetOut
.Data
), NetOut
.Len
, F
);
406 if not Assigned(P
) then Exit
;
408 enet_peer_send(NetClients
[ID
].Peer
, Chan
, P
);
412 P
:= enet_packet_create(Addr(NetOut
.Data
), NetOut
.Len
, F
);
413 if not Assigned(P
) then Exit
;
415 enet_host_widecast(NetHost
, Chan
, P
);
419 e_Buffer_Clear(@NetOut
);
422 procedure g_Net_Host_CheckPings();
426 Len
, ClTime
: Integer;
427 Ping
: array [0..5] of Byte;
430 if NetPongSock
= ENET_SOCKET_NULL
then Exit
;
432 Buf
.data
:= Addr(Ping
[0]);
437 Len
:= enet_socket_receive(NetPongSock
, @ClAddr
, @Buf
, 1);
438 if Len
< 0 then Exit
;
440 if (Ping
[0] = Ord('D')) and (Ping
[1] = Ord('F')) then
442 ClTime
:= Integer(Addr(Ping
[2])^);
444 e_Buffer_Clear(@NetOut
);
445 e_Buffer_Write(@NetOut
, Byte(Ord('D')));
446 e_Buffer_Write(@NetOut
, Byte(Ord('F')));
447 e_Buffer_Write(@NetOut
, ClTime
);
448 g_Net_Slist_WriteInfo();
450 if gPlayer1
<> nil then Inc(NPl
);
451 if gPlayer2
<> nil then Inc(NPl
);
452 e_Buffer_Write(@NetOut
, NPl
);
453 e_Buffer_Write(@NetOut
, gNumBots
);
455 Buf
.data
:= Addr(NetOut
.Data
[0]);
456 Buf
.dataLength
:= NetOut
.WritePos
;
457 enet_socket_send(NetPongSock
, @ClAddr
, @Buf
, 1);
459 e_Buffer_Clear(@NetOut
);
463 function g_Net_Host_Update(): enet_size_t
;
477 g_Net_Host_CheckPings
;
480 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
482 case (NetEvent
.kind
) of
483 ENET_EVENT_TYPE_CONNECT
:
485 IP
:= IpToStr(NetEvent
.Peer
^.address
.host
);
486 Port
:= NetEvent
.Peer
^.address
.port
;
487 g_Console_Add(_lc
[I_NET_MSG
] +
488 Format(_lc
[I_NET_MSG_HOST_CONN
], [IP
, Port
]));
490 if (NetEvent
.data
<> NET_PROTOCOL_VER
) then
492 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_REJECT
] +
493 _lc
[I_NET_DISC_PROTOCOL
]);
494 NetEvent
.peer
^.data
:= GetMemory(SizeOf(Byte));
495 Byte(NetEvent
.peer
^.data
^) := 255;
496 enet_peer_disconnect(NetEvent
.peer
, NET_DISC_PROTOCOL
);
497 enet_host_flush(NetHost
);
501 ID
:= g_Net_FindSlot();
505 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_REJECT
] +
506 _lc
[I_NET_DISC_FULL
]);
507 NetEvent
.Peer
^.data
:= GetMemory(SizeOf(Byte));
508 Byte(NetEvent
.peer
^.data
^) := 255;
509 enet_peer_disconnect(NetEvent
.peer
, NET_DISC_FULL
);
510 enet_host_flush(NetHost
);
514 NetClients
[ID
].Peer
:= NetEvent
.peer
;
515 NetClients
[ID
].Peer
^.data
:= GetMemory(SizeOf(Byte));
516 Byte(NetClients
[ID
].Peer
^.data
^) := ID
;
517 NetClients
[ID
].State
:= NET_STATE_AUTH
;
518 NetClients
[ID
].RCONAuth
:= False;
520 enet_peer_timeout(NetEvent
.peer
, ENET_PEER_TIMEOUT_LIMIT
* 2, ENET_PEER_TIMEOUT_MINIMUM
* 2, ENET_PEER_TIMEOUT_MAXIMUM
* 2);
523 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_HOST_ADD
], [ID
]));
526 ENET_EVENT_TYPE_RECEIVE
:
528 ID
:= Byte(NetEvent
.peer
^.data
^);
529 if ID
> High(NetClients
) then Exit
;
530 TC
:= @NetClients
[ID
];
532 g_Net_HostMsgHandler(TC
, NetEvent
.packet
);
535 ENET_EVENT_TYPE_DISCONNECT
:
537 ID
:= Byte(NetEvent
.peer
^.data
^);
538 if ID
> High(NetClients
) then Exit
;
539 TC
:= @NetClients
[ID
];
540 if TC
= nil then Exit
;
542 if not (TC
^.Used
) then Exit
;
544 TP
:= g_Player_Get(TC
^.Player
);
549 TP
.Kill(K_SIMPLEKILL
, 0, HIT_DISCON
);
550 g_Console_Add(Format(_lc
[I_PLAYER_LEAVE
], [TP
.Name
]), True);
551 e_WriteLog('NET: Client ' + TP
.Name
+ ' [' + IntToStr(ID
) + '] disconnected.', MSG_NOTIFY
);
552 g_Player_Remove(TP
.UID
);
556 TC
^.State
:= NET_STATE_NONE
;
559 TC
^.RequestedFullUpdate
:= False;
561 FreeMemory(NetEvent
.peer
^.data
);
562 NetEvent
.peer
^.data
:= nil;
563 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_HOST_DISC
], [ID
]));
566 if NetUseMaster
then g_Net_Slist_Update
;
573 { /// CLIENT FUNCTIONS /// }
576 procedure g_Net_Disconnect(Forced
: Boolean = False);
578 if NetMode
<> NET_CLIENT
then Exit
;
579 if (NetHost
= nil) or (NetPeer
= nil) then Exit
;
583 enet_peer_disconnect(NetPeer
, NET_DISC_NONE
);
585 while (enet_host_service(NetHost
, @NetEvent
, 1500) > 0) do
587 if (NetEvent
.kind
= ENET_EVENT_TYPE_DISCONNECT
) then
593 if (NetEvent
.kind
= ENET_EVENT_TYPE_RECEIVE
) then
594 enet_packet_destroy(NetEvent
.packet
);
597 if NetPeer
<> nil then
599 enet_peer_reset(NetPeer
);
605 e_WriteLog('NET: Kicked from server: ' + IntToStr(NetEvent
.data
), MSG_NOTIFY
);
606 if (NetEvent
.data
<= NET_DISC_MAX
) then
607 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_KICK
] +
608 _lc
[TStrings_Locale(Cardinal(I_NET_DISC_NONE
) + NetEvent
.data
)], True);
611 if NetHost
<> nil then
613 enet_host_destroy(NetHost
);
616 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_CLIENT_DISC
]);
619 e_WriteLog('NET: Disconnected', MSG_NOTIFY
);
622 procedure g_Net_Client_Send(Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
628 F
:= LongWord(ENET_PACKET_FLAG_RELIABLE
)
632 P
:= enet_packet_create(Addr(NetOut
.Data
), NetOut
.Len
, F
);
633 if not Assigned(P
) then Exit
;
635 enet_peer_send(NetPeer
, Chan
, P
);
637 e_Buffer_Clear(@NetOut
);
640 function g_Net_Client_Update(): enet_size_t
;
643 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
645 case NetEvent
.kind
of
646 ENET_EVENT_TYPE_RECEIVE
:
647 g_Net_ClientMsgHandler(NetEvent
.packet
);
649 ENET_EVENT_TYPE_DISCONNECT
:
651 g_Net_Disconnect(True);
659 function g_Net_Client_UpdateWhileLoading(): enet_size_t
;
662 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
664 case NetEvent
.kind
of
665 ENET_EVENT_TYPE_RECEIVE
:
666 g_Net_ClientLightMsgHandler(NetEvent
.packet
);
668 ENET_EVENT_TYPE_DISCONNECT
:
670 g_Net_Disconnect(True);
679 function g_Net_Connect(IP
: string; Port
: enet_uint16
): Boolean;
683 if NetMode
<> NET_NONE
then
685 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_ERR_INGAME
], True);
692 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_CLIENT_CONN
],
694 if not NetInitDone
then
696 if (not g_Net_Init()) then
698 g_Console_Add(_lc
[I_NET_MSG_FERROR
] + _lc
[I_NET_ERR_ENET
], True);
706 NetHost
:= enet_host_create(nil, 1, NET_CHANS
, 0, 0);
708 if (NetHost
= nil) then
710 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_CLIENT
], True);
716 enet_address_set_host(@NetAddr
, PChar(Addr(IP
[1])));
717 NetAddr
.port
:= Port
;
719 NetPeer
:= enet_host_connect(NetHost
, @NetAddr
, NET_CHANS
, NET_PROTOCOL_VER
);
721 if (NetPeer
= nil) then
723 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_CLIENT
], True);
724 enet_host_destroy(NetHost
);
733 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
735 if (NetEvent
.kind
= ENET_EVENT_TYPE_CONNECT
) then
737 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_CLIENT_DONE
]);
738 NetMode
:= NET_CLIENT
;
739 e_Buffer_Clear(@NetOut
);
740 enet_peer_timeout(NetPeer
, ENET_PEER_TIMEOUT_LIMIT
* 2, ENET_PEER_TIMEOUT_MINIMUM
* 2, ENET_PEER_TIMEOUT_MAXIMUM
* 2);
742 NetClientPort
:= Port
;
751 if e_KeyPressed(IK_ESCAPE
) or e_KeyPressed(IK_SPACE
) then
755 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_TIMEOUT
], True);
756 if NetPeer
<> nil then enet_peer_reset(NetPeer
);
757 if NetHost
<> nil then
759 enet_host_destroy(NetHost
);
766 function IpToStr(IP
: LongWord): string;
774 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
)) + '.';
775 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
)) + '.';
776 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
)) + '.';
777 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
));
781 function StrToIp(IPstr
: string; var IP
: LongWord): Boolean;
785 Result
:= enet_address_set_host(@EAddr
, PChar(@IPstr
[1])) = 0;
789 function g_Net_Client_ByName(Name
: string): pTNetClient
;
795 for a
:= Low(NetClients
) to High(NetClients
) do
796 if (NetClients
[a
].Used
) and (NetClients
[a
].State
= NET_STATE_GAME
) then
798 pl
:= g_Player_Get(NetClients
[a
].Player
);
799 if pl
= nil then continue
;
800 if Copy(LowerCase(pl
.Name
), 1, Length(Name
)) <> LowerCase(Name
) then continue
;
801 if NetClients
[a
].Peer
<> nil then
803 Result
:= @NetClients
[a
];
809 function g_Net_Client_ByPlayer(PID
: Word): pTNetClient
;
814 for a
:= Low(NetClients
) to High(NetClients
) do
815 if (NetClients
[a
].Used
) and (NetClients
[a
].State
= NET_STATE_GAME
) then
816 if NetClients
[a
].Player
= PID
then
818 Result
:= @NetClients
[a
];
823 function g_Net_ClientName_ByID(ID
: Integer): string;
829 if ID
= NET_EVERYONE
then
831 for a
:= Low(NetClients
) to High(NetClients
) do
832 if (NetClients
[a
].ID
= ID
) and (NetClients
[a
].Used
) and (NetClients
[a
].State
= NET_STATE_GAME
) then
834 pl
:= g_Player_Get(NetClients
[a
].Player
);
835 if pl
= nil then Exit
;
840 procedure g_Net_SendData(Data
:AByte
; peer
: pENetPeer
; Reliable
: Boolean; Chan
: Byte = NET_CHAN_DOWNLOAD
);
844 dataLength
: Cardinal;
846 dataLength
:= Length(Data
);
849 F
:= LongWord(ENET_PACKET_FLAG_RELIABLE
)
853 if (peer
<> nil) then
855 P
:= enet_packet_create(@Data
[0], dataLength
, F
);
856 if not Assigned(P
) then Exit
;
857 enet_peer_send(peer
, Chan
, P
);
861 P
:= enet_packet_create(@Data
[0], dataLength
, F
);
862 if not Assigned(P
) then Exit
;
863 enet_host_widecast(NetHost
, Chan
, P
);
866 enet_host_flush(NetHost
);
869 function g_Net_Wait_Event(msgId
: Word): TMemoryStream
;
871 downloadEvent
: ENetEvent
;
875 msgStream
: TMemoryStream
;
877 FillChar(downloadEvent
, SizeOf(downloadEvent
), 0);
882 while (enet_host_service(NetHost
, @downloadEvent
, 0) > 0) do
884 if (downloadEvent
.kind
= ENET_EVENT_TYPE_RECEIVE
) then
886 Ptr
:= downloadEvent
.packet
^.data
;
890 if (MID
= msgId
) then
892 msgStream
:= TMemoryStream
.Create
;
893 msgStream
.SetSize(downloadEvent
.packet
^.dataLength
);
894 msgStream
.WriteBuffer(Ptr
^, downloadEvent
.packet
^.dataLength
);
895 msgStream
.Seek(0, soFromBeginning
);
898 enet_packet_destroy(downloadEvent
.packet
);
902 enet_packet_destroy(downloadEvent
.packet
);
906 if (downloadEvent
.kind
= ENET_EVENT_TYPE_DISCONNECT
) then
908 if (downloadEvent
.data
<= NET_DISC_MAX
) then
909 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_CONN
] + ' ' +
910 _lc
[TStrings_Locale(Cardinal(I_NET_DISC_NONE
) + downloadEvent
.data
)], True);
920 if e_KeyPressed(IK_ESCAPE
) or e_KeyPressed(IK_SPACE
) then
926 function g_Net_IsHostBanned(IP
: LongWord; Perm
: Boolean = False): Boolean;
931 if NetBannedHosts
= nil then
933 for I
:= 0 to High(NetBannedHosts
) do
934 if (NetBannedHosts
[I
].IP
= IP
) and ((not Perm
) or (NetBannedHosts
[I
].Perm
)) then
941 procedure g_Net_BanHost(IP
: LongWord; Perm
: Boolean = True); overload
;
947 if g_Net_IsHostBanned(IP
, Perm
) then
951 for I
:= Low(NetBannedHosts
) to High(NetBannedHosts
) do
952 if NetBannedHosts
[I
].IP
= 0 then
960 SetLength(NetBannedHosts
, Length(NetBannedHosts
) + 1);
961 P
:= High(NetBannedHosts
);
964 NetBannedHosts
[P
].IP
:= IP
;
965 NetBannedHosts
[P
].Perm
:= Perm
;
968 procedure g_Net_BanHost(IP
: string; Perm
: Boolean = True); overload
;
975 g_Net_BanHost(a
, Perm
);
978 procedure g_Net_UnbanNonPermHosts();
982 if NetBannedHosts
= nil then
984 for I
:= Low(NetBannedHosts
) to High(NetBannedHosts
) do
985 if (NetBannedHosts
[I
].IP
> 0) and not NetBannedHosts
[I
].Perm
then
987 NetBannedHosts
[I
].IP
:= 0;
988 NetBannedHosts
[I
].Perm
:= True;
992 function g_Net_UnbanHost(IP
: string): Boolean; overload
;
996 Result
:= StrToIp(IP
, a
);
998 Result
:= g_Net_UnbanHost(a
);
1001 function g_Net_UnbanHost(IP
: LongWord): Boolean; overload
;
1008 if NetBannedHosts
= nil then
1010 for I
:= 0 to High(NetBannedHosts
) do
1011 if NetBannedHosts
[I
].IP
= IP
then
1013 NetBannedHosts
[I
].IP
:= 0;
1014 NetBannedHosts
[I
].Perm
:= True;
1016 // no break here to clear all bans of this host, perm and non-perm
1020 procedure g_Net_SaveBanList();
1025 Assign(F
, DataDir
+ BANLIST_FILENAME
);
1027 if NetBannedHosts
<> nil then
1028 for I
:= 0 to High(NetBannedHosts
) do
1029 if NetBannedHosts
[I
].Perm
and (NetBannedHosts
[I
].IP
> 0) then
1030 Writeln(F
, IpToStr(NetBannedHosts
[I
].IP
));