index 9e96a451f43f07326a693a2b78775945899ad2ea..41478f1cb94b74b6c0c8ef0b4b780366cd35fc99 100644 (file)
--- a/src/game/g_netmaster.pas
+++ b/src/game/g_netmaster.pas
-(* 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
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;
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]);
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;
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;
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);
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();
LocalPl := InMsg.ReadByte();
Bots := InMsg.ReadWord();
end;
+ FromSL := True;
Inc(Cnt);
break;
end;
+ if not FromSL then
+ ProcessLocal();
end;
InMsg.Free();
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;
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
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;
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
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
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
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;