X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_netmaster.pas;h=41478f1cb94b74b6c0c8ef0b4b780366cd35fc99;hb=91a5ffe08943e28ecdcf8bb6752f88ff220a4cd9;hp=9e96a451f43f07326a693a2b78775945899ad2ea;hpb=d7d166dc3cd287276202e862746208892c4cc89f;p=d2df-sdl.git diff --git a/src/game/g_netmaster.pas b/src/game/g_netmaster.pas index 9e96a45..41478f1 100644 --- a/src/game/g_netmaster.pas +++ b/src/game/g_netmaster.pas @@ -1,4 +1,4 @@ -(* Copyright (C) DooM 2D:Forever Developers +(* Copyright (C) Doom 2D: Forever Developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -104,6 +104,18 @@ begin enet_socket_send(Sock, Addr(S.PingAddr), @Buf, 1); end; +procedure PingBcast(Sock: ENetSocket); +var + S: TNetServer; +begin + S.IP := '255.255.255.255'; + S.Port := NET_PING_PORT; + enet_address_set_host(Addr(S.PingAddr), PChar(Addr(S.IP[1]))); + S.Ping := -1; + S.PingAddr.port := S.Port; + PingServer(S, Sock); +end; + function g_Net_Slist_Fetch(var SL: TNetServerList): Boolean; var Cnt: Byte; @@ -115,15 +127,80 @@ var Buf: ENetBuffer; InMsg: TMsg; SvAddr: ENetAddress; + FromSL: Boolean; + + procedure ProcessLocal(); + begin + I := Length(SL); + SetLength(SL, I + 1); + with SL[I] do + begin + IP := DecodeIPV4(SvAddr.host); + Port := InMsg.ReadWord(); + Ping := InMsg.ReadInt64(); + Ping := GetTimerMS() - Ping; + Name := InMsg.ReadString(); + Map := InMsg.ReadString(); + GameMode := InMsg.ReadByte(); + Players := InMsg.ReadByte(); + MaxPlayers := InMsg.ReadByte(); + Protocol := InMsg.ReadByte(); + Password := InMsg.ReadByte() = 1; + LocalPl := InMsg.ReadByte(); + Bots := InMsg.ReadWord(); + end; + end; + procedure CheckLocalServers(); + begin + SetLength(SL, 0); + + Sock := enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); + if Sock = ENET_SOCKET_NULL then Exit; + enet_socket_set_option(Sock, ENET_SOCKOPT_NONBLOCK, 1); + enet_socket_set_option(Sock, ENET_SOCKOPT_BROADCAST, 1); + PingBcast(Sock); + + T := GetTimerMS(); + + InMsg.Alloc(NET_BUFSIZE); + Buf.data := InMsg.Data; + Buf.dataLength := InMsg.MaxSize; + while GetTimerMS() - T <= 500 do + begin + InMsg.Clear(); + + RX := enet_socket_receive(Sock, @SvAddr, @Buf, 1); + if RX <= 0 then continue; + InMsg.CurSize := RX; + + InMsg.BeginReading(); + + if InMsg.ReadChar() <> 'D' then continue; + if InMsg.ReadChar() <> 'F' then continue; + + ProcessLocal(); + end; + + InMsg.Free(); + enet_socket_destroy(Sock); + + if Length(SL) = 0 then SL := nil; + end; begin Result := False; SL := nil; if (NetMHost <> nil) or (NetMPeer <> nil) then + begin + CheckLocalServers(); Exit; + end; if not g_Net_Slist_Connect then + begin + CheckLocalServers(); Exit; + end; e_WriteLog('Fetching serverlist...', TMsgType.Notify); g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_SLIST_FETCH]); @@ -166,7 +243,7 @@ begin SL[I].Password := InMsg.ReadByte() = 1; enet_address_set_host(Addr(SL[I].PingAddr), PChar(Addr(SL[I].IP[1]))); SL[I].Ping := -1; - SL[I].PingAddr.port := SL[I].Port + 1; + SL[I].PingAddr.port := NET_PING_PORT; end; end; @@ -178,7 +255,11 @@ begin g_Net_Slist_Disconnect; NetOut.Clear(); - if Length(SL) = 0 then Exit; + if Length(SL) = 0 then + begin + CheckLocalServers(); + Exit; + end; Sock := enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); if Sock = ENET_SOCKET_NULL then Exit; @@ -187,16 +268,17 @@ begin for I := Low(SL) to High(SL) do PingServer(SL[I], Sock); + enet_socket_set_option(Sock, ENET_SOCKOPT_BROADCAST, 1); + PingBcast(Sock); + T := GetTimerMS(); InMsg.Alloc(NET_BUFSIZE); Buf.data := InMsg.Data; Buf.dataLength := InMsg.MaxSize; Cnt := 0; - while Cnt < Length(SL) do + while GetTimerMS() - T <= 500 do begin - if GetTimerMS() - T > 500 then break; - InMsg.Clear(); RX := enet_socket_receive(Sock, @SvAddr, @Buf, 1); @@ -208,12 +290,14 @@ begin if InMsg.ReadChar() <> 'D' then continue; if InMsg.ReadChar() <> 'F' then continue; + FromSL := False; for I := Low(SL) to High(SL) do if (SL[I].PingAddr.host = SvAddr.host) and (SL[I].PingAddr.port = SvAddr.port) then begin with SL[I] do begin + Port := InMsg.ReadWord(); Ping := InMsg.ReadInt64(); Ping := GetTimerMS() - Ping; Name := InMsg.ReadString(); @@ -226,9 +310,12 @@ begin LocalPl := InMsg.ReadByte(); Bots := InMsg.ReadWord(); end; + FromSL := True; Inc(Cnt); break; end; + if not FromSL then + ProcessLocal(); end; InMsg.Free(); @@ -505,13 +592,15 @@ begin end; procedure g_Serverlist_Control(var SL: TNetServerList); +var + qm: Boolean; begin if gConsoleShow or gChatShow then Exit; - e_PollInput(); + qm := g_ProcessMessages(); // this updates kbd - if e_KeyPressed(IK_ESCAPE) then + if qm or e_KeyPressed(IK_ESCAPE) or e_KeyPressed(VK_ESCAPE) then begin SL := nil; gState := STATE_MENU; @@ -522,7 +611,7 @@ begin Exit; end; - if e_KeyPressed(IK_SPACE) then + if e_KeyPressed(IK_SPACE) or e_KeyPressed(VK_JUMP) then begin if not slFetched then begin @@ -537,7 +626,8 @@ begin slWaitStr := _lc[I_NET_SLIST_NOSERVERS]; end else - slWaitStr := _lc[I_NET_SLIST_ERROR]; + if SL = nil then + slWaitStr := _lc[I_NET_SLIST_ERROR]; slFetched := True; slSelection := 0; end; @@ -547,7 +637,7 @@ begin if SL = nil then Exit; - if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) then + if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) then begin if not slReturnPressed then begin @@ -571,7 +661,7 @@ begin else slReturnPressed := False; - if e_KeyPressed(IK_DOWN) or e_KeyPressed(IK_KPDOWN) then + if e_KeyPressed(IK_DOWN) or e_KeyPressed(IK_KPDOWN) or e_KeyPressed(VK_DOWN) then begin if not slDirPressed then begin @@ -581,7 +671,7 @@ begin end; end; - if e_KeyPressed(IK_UP) or e_KeyPressed(IK_KPUP) then + if e_KeyPressed(IK_UP) or e_KeyPressed(IK_KPUP) or e_KeyPressed(VK_UP) then begin if not slDirPressed then begin @@ -592,7 +682,7 @@ begin end; end; - if (not e_KeyPressed(IK_DOWN)) and (not e_KeyPressed(IK_UP)) and (not e_KeyPressed(IK_KPDOWN)) and (not e_KeyPressed(IK_KPUP)) then + if (not e_KeyPressed(IK_DOWN)) and (not e_KeyPressed(IK_UP)) and (not e_KeyPressed(IK_KPDOWN)) and (not e_KeyPressed(IK_KPUP)) and (not e_KeyPressed(VK_DOWN)) and (not e_KeyPressed(VK_UP)) then slDirPressed := False; end;