7 e_log
, e_fixedbuffer
, ENet
, ENetTypes
, ENetPlatform
, Classes
;
10 NET_PROTOCOL_VER
= 166;
16 NET_CHAN_IMPORTANT
= 1;
19 NET_CHAN_PLAYERPOS
= 4;
21 NET_CHAN_MONSTERPOS
= 6;
22 NET_CHAN_LARGEDATA
= 7;
24 NET_CHAN_DOWNLOAD
= 9;
35 NET_DISC_NONE
: enet_uint32
= 0;
36 NET_DISC_PROTOCOL
: enet_uint32
= 1;
37 NET_DISC_VERSION
: enet_uint32
= 2;
38 NET_DISC_FULL
: enet_uint32
= 3;
39 NET_DISC_KICK
: enet_uint32
= 4;
40 NET_DISC_DOWN
: enet_uint32
= 5;
41 NET_DISC_PASSWORD
: enet_uint32
= 6;
42 NET_DISC_TEMPBAN
: enet_uint32
= 7;
43 NET_DISC_BAN
: enet_uint32
= 8;
44 NET_DISC_MAX
: enet_uint32
= 8;
50 BANLIST_FILENAME
= 'banlist.txt';
59 RequestedFullUpdate
: Boolean;
67 pTNetClient
= ^TNetClient
;
69 AByte
= array of Byte;
72 NetInitDone
: Boolean = False;
73 NetMode
: Byte = NET_NONE
;
75 NetServerName
: string = 'Unnamed Server';
76 NetPassword
: string = '';
77 NetPort
: Word = 25666;
79 NetAllowRCON
: Boolean = False;
80 NetRCONPassword
: string = '';
82 NetTimeToUpdate
: Cardinal = 0;
83 NetTimeToReliable
: Cardinal = 0;
84 NetTimeToMaster
: Cardinal = 0;
86 NetHost
: pENetHost
= nil;
87 NetPeer
: pENetPeer
= nil;
91 NetPongAddr
: ENetAddress
;
92 NetPongSock
: ENetSocket
= ENET_SOCKET_NULL
;
94 NetUseMaster
: Boolean = True;
95 NetSlistAddr
: ENetAddress
;
96 NetSlistIP
: string = 'mpms.doom2d.org';
97 NetSlistPort
: Word = 25665;
99 NetClientIP
: string = '127.0.0.1';
100 NetClientPort
: Word = 25666;
102 NetIn
, NetOut
: TBuffer
;
104 NetClients
: array of TNetClient
;
105 NetClientCount
: Byte = 0;
106 NetMaxClients
: Byte = 255;
107 NetBannedHosts
: array of TBanRecord
;
109 NetState
: Integer = NET_STATE_NONE
;
111 NetMyID
: Integer = -1;
112 NetPlrUID1
: Integer = -1;
113 NetPlrUID2
: Integer = -1;
115 NetInterpLevel
: Integer = 1;
116 NetUpdateRate
: Cardinal = 0; // as soon as possible
117 NetRelupdRate
: Cardinal = 18; // around two times a second
118 NetMasterRate
: Cardinal = 60000;
120 NetForcePlayerUpdate
: Boolean = False;
121 NetPredictSelf
: Boolean = True;
122 NetGotKeys
: Boolean = False;
124 NetGotEverything
: Boolean = False;
126 function g_Net_Init(): Boolean;
127 procedure g_Net_Cleanup();
128 procedure g_Net_Free();
129 procedure g_Net_Flush();
131 function g_Net_Host(IPAddr
: LongWord; Port
: enet_uint16
; MaxClients
: Cardinal = 16): Boolean;
132 procedure g_Net_Host_Die();
133 procedure g_Net_Host_Send(ID
: Integer; Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
134 function g_Net_Host_Update(): enet_size_t
;
136 function g_Net_Connect(IP
: string; Port
: enet_uint16
): Boolean;
137 procedure g_Net_Disconnect(Forced
: Boolean = False);
138 procedure g_Net_Client_Send(Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
139 function g_Net_Client_Update(): enet_size_t
;
140 function g_Net_Client_UpdateWhileLoading(): enet_size_t
;
142 function g_Net_Client_ByName(Name
: string): pTNetClient
;
143 function g_Net_Client_ByPlayer(PID
: Word): pTNetClient
;
144 function g_Net_ClientName_ByID(ID
: Integer): string;
146 procedure g_Net_SendData(Data
:AByte
; peer
: pENetPeer
; Reliable
: Boolean; Chan
: Byte = NET_CHAN_DOWNLOAD
);
147 function g_Net_Wait_Event(msgId
: Word): TMemoryStream
;
149 function IpToStr(IP
: LongWord): string;
150 function StrToIp(IPstr
: string; var IP
: LongWord): Boolean;
152 function g_Net_IsHostBanned(IP
: LongWord; Perm
: Boolean = False): Boolean;
153 procedure g_Net_BanHost(IP
: LongWord; Perm
: Boolean = True); overload
;
154 procedure g_Net_BanHost(IP
: string; Perm
: Boolean = True); overload
;
155 function g_Net_UnbanHost(IP
: string): Boolean; overload
;
156 function g_Net_UnbanHost(IP
: LongWord): Boolean; overload
;
157 procedure g_Net_UnbanNonPermHosts();
158 procedure g_Net_SaveBanList();
164 e_input
, g_nethandler
, g_netmsg
, g_netmaster
, g_player
, g_window
, g_console
,
165 g_main
, g_game
, g_language
, g_weapons
;
168 { /// SERVICE FUNCTIONS /// }
171 function g_Net_FindSlot(): Integer;
180 for I
:= Low(NetClients
) to High(NetClients
) do
182 if NetClients
[I
].Used
then
191 if C
>= NetMaxClients
then
199 if (Length(NetClients
) >= NetMaxClients
) then
203 SetLength(NetClients
, Length(NetClients
) + 1);
204 N
:= High(NetClients
);
210 NetClients
[N
].Used
:= True;
211 NetClients
[N
].ID
:= N
;
212 NetClients
[N
].RequestedFullUpdate
:= False;
213 NetClients
[N
].RCONAuth
:= False;
214 NetClients
[N
].Voted
:= False;
215 NetClients
[N
].Player
:= 0;
221 function g_Net_Init(): Boolean;
227 e_Buffer_Clear(@NetIn
);
228 e_Buffer_Clear(@NetOut
);
229 SetLength(NetClients
, 0);
235 NetAddr
.port
:= 25666;
236 SetLength(NetBannedHosts
, 0);
237 if FileExists(DataDir
+ BANLIST_FILENAME
) then
239 Assign(F
, DataDir
+ BANLIST_FILENAME
);
244 if StrToIp(IPstr
, IP
) then
251 Result
:= (enet_initialize() = 0);
254 procedure g_Net_Flush();
256 enet_host_flush(NetHost
);
259 procedure g_Net_Cleanup();
261 e_Buffer_Clear(@NetIn
);
262 e_Buffer_Clear(@NetOut
);
264 SetLength(NetClients
, 0);
274 NetState
:= NET_STATE_NONE
;
276 NetPongSock
:= ENET_SOCKET_NULL
;
278 NetTimeToMaster
:= 0;
279 NetTimeToUpdate
:= 0;
280 NetTimeToReliable
:= 0;
285 procedure g_Net_Free();
290 NetInitDone
:= False;
294 { /// SERVER FUNCTIONS /// }
297 function g_Net_Host(IPAddr
: LongWord; Port
: enet_uint16
; MaxClients
: Cardinal = 16): Boolean;
299 if NetMode
<> NET_NONE
then
301 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_INGAME
]);
308 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_HOST
], [Port
]));
309 if not NetInitDone
then
311 if (not g_Net_Init()) then
313 g_Console_Add(_lc
[I_NET_MSG_FERROR
] + _lc
[I_NET_ERR_ENET
]);
321 NetAddr
.host
:= IPAddr
;
322 NetAddr
.port
:= Port
;
324 NetHost
:= enet_host_create(@NetAddr
, NET_MAXCLIENTS
, NET_CHANS
, 0, 0);
326 if (NetHost
= nil) then
328 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + Format(_lc
[I_NET_ERR_HOST
], [Port
]));
334 NetPongSock
:= enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM
);
335 if NetPongSock
<> ENET_SOCKET_NULL
then
337 NetPongAddr
.host
:= IPAddr
;
338 NetPongAddr
.port
:= Port
+ 1;
339 if enet_socket_bind(NetPongSock
, @NetPongAddr
) < 0 then
341 enet_socket_destroy(NetPongSock
);
342 NetPongSock
:= ENET_SOCKET_NULL
;
345 enet_socket_set_option(NetPongSock
, ENET_SOCKOPT_NONBLOCK
, 1);
348 NetMode
:= NET_SERVER
;
349 e_Buffer_Clear(@NetOut
);
352 procedure g_Net_Host_Die();
356 if NetMode
<> NET_SERVER
then Exit
;
358 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_DISCALL
]);
359 for I
:= 0 to High(NetClients
) do
360 if NetClients
[I
].Used
then
361 enet_peer_disconnect(NetClients
[I
].Peer
, NET_DISC_DOWN
);
363 while enet_host_service(NetHost
, @NetEvent
, 1000) > 0 do
364 if NetEvent
.kind
= ENET_EVENT_TYPE_RECEIVE
then
365 enet_packet_destroy(NetEvent
.packet
);
367 for I
:= 0 to High(NetClients
) do
368 if NetClients
[I
].Used
then
370 FreeMemory(NetClients
[I
].Peer
^.data
);
371 NetClients
[I
].Peer
^.data
:= nil;
372 enet_peer_reset(NetClients
[I
].Peer
);
373 NetClients
[I
].Peer
:= nil;
374 NetClients
[I
].Used
:= False;
377 if (NetMPeer
<> nil) and (NetMHost
<> nil) then g_Net_Slist_Disconnect
;
378 if NetPongSock
<> ENET_SOCKET_NULL
then
379 enet_socket_destroy(NetPongSock
);
381 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_DIE
]);
382 enet_host_destroy(NetHost
);
387 e_WriteLog('NET: Server stopped', MSG_NOTIFY
);
391 procedure g_Net_Host_Send(ID
: Integer; Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
397 F
:= LongWord(ENET_PACKET_FLAG_RELIABLE
)
403 if ID
> High(NetClients
) then Exit
;
404 if NetClients
[ID
].Peer
= nil then Exit
;
406 P
:= enet_packet_create(Addr(NetOut
.Data
), NetOut
.Len
, F
);
407 if not Assigned(P
) then Exit
;
409 enet_peer_send(NetClients
[ID
].Peer
, Chan
, P
);
413 P
:= enet_packet_create(Addr(NetOut
.Data
), NetOut
.Len
, F
);
414 if not Assigned(P
) then Exit
;
416 enet_host_widecast(NetHost
, Chan
, P
);
420 e_Buffer_Clear(@NetOut
);
423 procedure g_Net_Host_CheckPings();
429 Ping
: array [0..9] of Byte;
432 if NetPongSock
= ENET_SOCKET_NULL
then Exit
;
434 Buf
.data
:= Addr(Ping
[0]);
435 Buf
.dataLength
:= 2+8;
439 Len
:= enet_socket_receive(NetPongSock
, @ClAddr
, @Buf
, 1);
440 if Len
< 0 then Exit
;
442 if (Ping
[0] = Ord('D')) and (Ping
[1] = Ord('F')) then
444 ClTime
:= Int64(Addr(Ping
[2])^);
446 e_Buffer_Clear(@NetOut
);
447 e_Buffer_Write(@NetOut
, Byte(Ord('D')));
448 e_Buffer_Write(@NetOut
, Byte(Ord('F')));
449 e_Buffer_Write(@NetOut
, ClTime
);
450 g_Net_Slist_WriteInfo();
452 if gPlayer1
<> nil then Inc(NPl
);
453 if gPlayer2
<> nil then Inc(NPl
);
454 e_Buffer_Write(@NetOut
, NPl
);
455 e_Buffer_Write(@NetOut
, gNumBots
);
457 Buf
.data
:= Addr(NetOut
.Data
[0]);
458 Buf
.dataLength
:= NetOut
.WritePos
;
459 enet_socket_send(NetPongSock
, @ClAddr
, @Buf
, 1);
461 e_Buffer_Clear(@NetOut
);
465 function g_Net_Host_Update(): enet_size_t
;
479 g_Net_Host_CheckPings
;
482 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
484 case (NetEvent
.kind
) of
485 ENET_EVENT_TYPE_CONNECT
:
487 IP
:= IpToStr(NetEvent
.Peer
^.address
.host
);
488 Port
:= NetEvent
.Peer
^.address
.port
;
489 g_Console_Add(_lc
[I_NET_MSG
] +
490 Format(_lc
[I_NET_MSG_HOST_CONN
], [IP
, Port
]));
492 if (NetEvent
.data
<> NET_PROTOCOL_VER
) then
494 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_REJECT
] +
495 _lc
[I_NET_DISC_PROTOCOL
]);
496 NetEvent
.peer
^.data
:= GetMemory(SizeOf(Byte));
497 Byte(NetEvent
.peer
^.data
^) := 255;
498 enet_peer_disconnect(NetEvent
.peer
, NET_DISC_PROTOCOL
);
499 enet_host_flush(NetHost
);
503 ID
:= g_Net_FindSlot();
507 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_HOST_REJECT
] +
508 _lc
[I_NET_DISC_FULL
]);
509 NetEvent
.Peer
^.data
:= GetMemory(SizeOf(Byte));
510 Byte(NetEvent
.peer
^.data
^) := 255;
511 enet_peer_disconnect(NetEvent
.peer
, NET_DISC_FULL
);
512 enet_host_flush(NetHost
);
516 NetClients
[ID
].Peer
:= NetEvent
.peer
;
517 NetClients
[ID
].Peer
^.data
:= GetMemory(SizeOf(Byte));
518 Byte(NetClients
[ID
].Peer
^.data
^) := ID
;
519 NetClients
[ID
].State
:= NET_STATE_AUTH
;
520 NetClients
[ID
].RCONAuth
:= False;
522 enet_peer_timeout(NetEvent
.peer
, ENET_PEER_TIMEOUT_LIMIT
* 2, ENET_PEER_TIMEOUT_MINIMUM
* 2, ENET_PEER_TIMEOUT_MAXIMUM
* 2);
525 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_HOST_ADD
], [ID
]));
528 ENET_EVENT_TYPE_RECEIVE
:
530 ID
:= Byte(NetEvent
.peer
^.data
^);
531 if ID
> High(NetClients
) then Exit
;
532 TC
:= @NetClients
[ID
];
534 g_Net_HostMsgHandler(TC
, NetEvent
.packet
);
537 ENET_EVENT_TYPE_DISCONNECT
:
539 ID
:= Byte(NetEvent
.peer
^.data
^);
540 if ID
> High(NetClients
) then Exit
;
541 TC
:= @NetClients
[ID
];
542 if TC
= nil then Exit
;
544 if not (TC
^.Used
) then Exit
;
546 TP
:= g_Player_Get(TC
^.Player
);
551 TP
.Kill(K_SIMPLEKILL
, 0, HIT_DISCON
);
552 g_Console_Add(Format(_lc
[I_PLAYER_LEAVE
], [TP
.Name
]), True);
553 e_WriteLog('NET: Client ' + TP
.Name
+ ' [' + IntToStr(ID
) + '] disconnected.', MSG_NOTIFY
);
554 g_Player_Remove(TP
.UID
);
558 TC
^.State
:= NET_STATE_NONE
;
561 TC
^.RequestedFullUpdate
:= False;
563 FreeMemory(NetEvent
.peer
^.data
);
564 NetEvent
.peer
^.data
:= nil;
565 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_HOST_DISC
], [ID
]));
568 if NetUseMaster
then g_Net_Slist_Update
;
575 { /// CLIENT FUNCTIONS /// }
578 procedure g_Net_Disconnect(Forced
: Boolean = False);
580 if NetMode
<> NET_CLIENT
then Exit
;
581 if (NetHost
= nil) or (NetPeer
= nil) then Exit
;
585 enet_peer_disconnect(NetPeer
, NET_DISC_NONE
);
587 while (enet_host_service(NetHost
, @NetEvent
, 1500) > 0) do
589 if (NetEvent
.kind
= ENET_EVENT_TYPE_DISCONNECT
) then
595 if (NetEvent
.kind
= ENET_EVENT_TYPE_RECEIVE
) then
596 enet_packet_destroy(NetEvent
.packet
);
599 if NetPeer
<> nil then
601 enet_peer_reset(NetPeer
);
607 e_WriteLog('NET: Kicked from server: ' + IntToStr(NetEvent
.data
), MSG_NOTIFY
);
608 if (NetEvent
.data
<= NET_DISC_MAX
) then
609 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_KICK
] +
610 _lc
[TStrings_Locale(Cardinal(I_NET_DISC_NONE
) + NetEvent
.data
)], True);
613 if NetHost
<> nil then
615 enet_host_destroy(NetHost
);
618 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_CLIENT_DISC
]);
621 e_WriteLog('NET: Disconnected', MSG_NOTIFY
);
624 procedure g_Net_Client_Send(Reliable
: Boolean; Chan
: Byte = NET_CHAN_GAME
);
630 F
:= LongWord(ENET_PACKET_FLAG_RELIABLE
)
634 P
:= enet_packet_create(Addr(NetOut
.Data
), NetOut
.Len
, F
);
635 if not Assigned(P
) then Exit
;
637 enet_peer_send(NetPeer
, Chan
, P
);
639 e_Buffer_Clear(@NetOut
);
642 function g_Net_Client_Update(): enet_size_t
;
645 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
647 case NetEvent
.kind
of
648 ENET_EVENT_TYPE_RECEIVE
:
649 g_Net_ClientMsgHandler(NetEvent
.packet
);
651 ENET_EVENT_TYPE_DISCONNECT
:
653 g_Net_Disconnect(True);
661 function g_Net_Client_UpdateWhileLoading(): enet_size_t
;
664 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
666 case NetEvent
.kind
of
667 ENET_EVENT_TYPE_RECEIVE
:
668 g_Net_ClientLightMsgHandler(NetEvent
.packet
);
670 ENET_EVENT_TYPE_DISCONNECT
:
672 g_Net_Disconnect(True);
681 function g_Net_Connect(IP
: string; Port
: enet_uint16
): Boolean;
685 if NetMode
<> NET_NONE
then
687 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_ERR_INGAME
], True);
694 g_Console_Add(_lc
[I_NET_MSG
] + Format(_lc
[I_NET_MSG_CLIENT_CONN
],
696 if not NetInitDone
then
698 if (not g_Net_Init()) then
700 g_Console_Add(_lc
[I_NET_MSG_FERROR
] + _lc
[I_NET_ERR_ENET
], True);
708 NetHost
:= enet_host_create(nil, 1, NET_CHANS
, 0, 0);
710 if (NetHost
= nil) then
712 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_CLIENT
], True);
718 enet_address_set_host(@NetAddr
, PChar(Addr(IP
[1])));
719 NetAddr
.port
:= Port
;
721 NetPeer
:= enet_host_connect(NetHost
, @NetAddr
, NET_CHANS
, NET_PROTOCOL_VER
);
723 if (NetPeer
= nil) then
725 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_CLIENT
], True);
726 enet_host_destroy(NetHost
);
735 while (enet_host_service(NetHost
, @NetEvent
, 0) > 0) do
737 if (NetEvent
.kind
= ENET_EVENT_TYPE_CONNECT
) then
739 g_Console_Add(_lc
[I_NET_MSG
] + _lc
[I_NET_MSG_CLIENT_DONE
]);
740 NetMode
:= NET_CLIENT
;
741 e_Buffer_Clear(@NetOut
);
742 enet_peer_timeout(NetPeer
, ENET_PEER_TIMEOUT_LIMIT
* 2, ENET_PEER_TIMEOUT_MINIMUM
* 2, ENET_PEER_TIMEOUT_MAXIMUM
* 2);
744 NetClientPort
:= Port
;
753 if e_KeyPressed(IK_ESCAPE
) or e_KeyPressed(IK_SPACE
) then
757 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_TIMEOUT
], True);
758 if NetPeer
<> nil then enet_peer_reset(NetPeer
);
759 if NetHost
<> nil then
761 enet_host_destroy(NetHost
);
768 function IpToStr(IP
: LongWord): string;
776 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
)) + '.';
777 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
)) + '.';
778 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
)) + '.';
779 Result
:= Result
+ IntToStr(e_Raw_Read_Byte(Ptr
));
783 function StrToIp(IPstr
: string; var IP
: LongWord): Boolean;
787 Result
:= enet_address_set_host(@EAddr
, PChar(@IPstr
[1])) = 0;
791 function g_Net_Client_ByName(Name
: string): pTNetClient
;
797 for a
:= Low(NetClients
) to High(NetClients
) do
798 if (NetClients
[a
].Used
) and (NetClients
[a
].State
= NET_STATE_GAME
) then
800 pl
:= g_Player_Get(NetClients
[a
].Player
);
801 if pl
= nil then continue
;
802 if Copy(LowerCase(pl
.Name
), 1, Length(Name
)) <> LowerCase(Name
) then continue
;
803 if NetClients
[a
].Peer
<> nil then
805 Result
:= @NetClients
[a
];
811 function g_Net_Client_ByPlayer(PID
: Word): pTNetClient
;
816 for a
:= Low(NetClients
) to High(NetClients
) do
817 if (NetClients
[a
].Used
) and (NetClients
[a
].State
= NET_STATE_GAME
) then
818 if NetClients
[a
].Player
= PID
then
820 Result
:= @NetClients
[a
];
825 function g_Net_ClientName_ByID(ID
: Integer): string;
831 if ID
= NET_EVERYONE
then
833 for a
:= Low(NetClients
) to High(NetClients
) do
834 if (NetClients
[a
].ID
= ID
) and (NetClients
[a
].Used
) and (NetClients
[a
].State
= NET_STATE_GAME
) then
836 pl
:= g_Player_Get(NetClients
[a
].Player
);
837 if pl
= nil then Exit
;
842 procedure g_Net_SendData(Data
:AByte
; peer
: pENetPeer
; Reliable
: Boolean; Chan
: Byte = NET_CHAN_DOWNLOAD
);
846 dataLength
: Cardinal;
848 dataLength
:= Length(Data
);
851 F
:= LongWord(ENET_PACKET_FLAG_RELIABLE
)
855 if (peer
<> nil) then
857 P
:= enet_packet_create(@Data
[0], dataLength
, F
);
858 if not Assigned(P
) then Exit
;
859 enet_peer_send(peer
, Chan
, P
);
863 P
:= enet_packet_create(@Data
[0], dataLength
, F
);
864 if not Assigned(P
) then Exit
;
865 enet_host_widecast(NetHost
, Chan
, P
);
868 enet_host_flush(NetHost
);
871 function g_Net_Wait_Event(msgId
: Word): TMemoryStream
;
873 downloadEvent
: ENetEvent
;
877 msgStream
: TMemoryStream
;
879 FillChar(downloadEvent
, SizeOf(downloadEvent
), 0);
884 while (enet_host_service(NetHost
, @downloadEvent
, 0) > 0) do
886 if (downloadEvent
.kind
= ENET_EVENT_TYPE_RECEIVE
) then
888 Ptr
:= downloadEvent
.packet
^.data
;
892 if (MID
= msgId
) then
894 msgStream
:= TMemoryStream
.Create
;
895 msgStream
.SetSize(downloadEvent
.packet
^.dataLength
);
896 msgStream
.WriteBuffer(Ptr
^, downloadEvent
.packet
^.dataLength
);
897 msgStream
.Seek(0, soFromBeginning
);
900 enet_packet_destroy(downloadEvent
.packet
);
904 enet_packet_destroy(downloadEvent
.packet
);
908 if (downloadEvent
.kind
= ENET_EVENT_TYPE_DISCONNECT
) then
910 if (downloadEvent
.data
<= NET_DISC_MAX
) then
911 g_Console_Add(_lc
[I_NET_MSG_ERROR
] + _lc
[I_NET_ERR_CONN
] + ' ' +
912 _lc
[TStrings_Locale(Cardinal(I_NET_DISC_NONE
) + downloadEvent
.data
)], True);
922 if e_KeyPressed(IK_ESCAPE
) or e_KeyPressed(IK_SPACE
) then
928 function g_Net_IsHostBanned(IP
: LongWord; Perm
: Boolean = False): Boolean;
933 if NetBannedHosts
= nil then
935 for I
:= 0 to High(NetBannedHosts
) do
936 if (NetBannedHosts
[I
].IP
= IP
) and ((not Perm
) or (NetBannedHosts
[I
].Perm
)) then
943 procedure g_Net_BanHost(IP
: LongWord; Perm
: Boolean = True); overload
;
949 if g_Net_IsHostBanned(IP
, Perm
) then
953 for I
:= Low(NetBannedHosts
) to High(NetBannedHosts
) do
954 if NetBannedHosts
[I
].IP
= 0 then
962 SetLength(NetBannedHosts
, Length(NetBannedHosts
) + 1);
963 P
:= High(NetBannedHosts
);
966 NetBannedHosts
[P
].IP
:= IP
;
967 NetBannedHosts
[P
].Perm
:= Perm
;
970 procedure g_Net_BanHost(IP
: string; Perm
: Boolean = True); overload
;
977 g_Net_BanHost(a
, Perm
);
980 procedure g_Net_UnbanNonPermHosts();
984 if NetBannedHosts
= nil then
986 for I
:= Low(NetBannedHosts
) to High(NetBannedHosts
) do
987 if (NetBannedHosts
[I
].IP
> 0) and not NetBannedHosts
[I
].Perm
then
989 NetBannedHosts
[I
].IP
:= 0;
990 NetBannedHosts
[I
].Perm
:= True;
994 function g_Net_UnbanHost(IP
: string): Boolean; overload
;
998 Result
:= StrToIp(IP
, a
);
1000 Result
:= g_Net_UnbanHost(a
);
1003 function g_Net_UnbanHost(IP
: LongWord): Boolean; overload
;
1010 if NetBannedHosts
= nil then
1012 for I
:= 0 to High(NetBannedHosts
) do
1013 if NetBannedHosts
[I
].IP
= IP
then
1015 NetBannedHosts
[I
].IP
:= 0;
1016 NetBannedHosts
[I
].Perm
:= True;
1018 // no break here to clear all bans of this host, perm and non-perm
1022 procedure g_Net_SaveBanList();
1027 Assign(F
, DataDir
+ BANLIST_FILENAME
);
1029 if NetBannedHosts
<> nil then
1030 for I
:= 0 to High(NetBannedHosts
) do
1031 if NetBannedHosts
[I
].Perm
and (NetBannedHosts
[I
].IP
> 0) then
1032 Writeln(F
, IpToStr(NetBannedHosts
[I
].IP
));