From 7d53b8719f818712900fefb1c36e41b1fe9b3f32 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Thu, 10 Oct 2019 12:01:53 +0300 Subject: [PATCH] net: do not hiccup when the game is in progress, and master server is not available the game repeatedly tries to connect to master server while the match is going on, and the master is not available. connection routine is blocking, so the whole game freezes for 3 seconds once a minute. definitely not a very pleasant expirience. i made connection to master optionally non-blocking. the game will still hang for 3 secs when loading a new map (this can be changed too, but i don't think that it really matters), but in-game hangups should be gone. --- src/game/g_game.pas | 13 +++---- src/game/g_language.pas | 5 ++- src/game/g_netmaster.pas | 83 +++++++++++++++++++++++++++++++++------- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 0d5a73c..2084d88 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -2130,7 +2130,7 @@ begin begin if (NetMHost = nil) or (NetMPeer = nil) then begin - if not g_Net_Slist_Connect then g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR]); + g_Net_Slist_Connect(false); // non-blocking connection to the master end; g_Net_Slist_Update; @@ -4888,9 +4888,10 @@ begin if NetUseMaster then begin if (NetMHost = nil) or (NetMPeer = nil) then - if not g_Net_Slist_Connect then - g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR]); - + begin + // let the connection be blocking here, why not? + g_Net_Slist_Connect(); + end; g_Net_Slist_Update; end; @@ -5501,9 +5502,7 @@ begin if g_Game_IsServer and g_Game_IsNet then if NetUseMaster then begin - if NetMPeer = nil then - if not g_Net_Slist_Connect() then - g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR]); + if NetMPeer = nil then g_Net_Slist_Connect(); g_Net_Slist_Update(); end else diff --git a/src/game/g_language.pas b/src/game/g_language.pas index 951ba6e..62361f3 100644 --- a/src/game/g_language.pas +++ b/src/game/g_language.pas @@ -393,6 +393,7 @@ type I_NET_SLIST_FETCH, I_NET_SLIST_RETRIEVED, I_NET_SLIST_CONN, + I_NET_SLIST_WCONN, I_NET_SLIST_DISC, I_NET_SLIST_LOST, I_NET_SLIST_ERROR, @@ -1001,7 +1002,7 @@ const ('MENU CONTROL TOUCH', 'Touchscreen Settings', 'Íàñòðîéêè ñåíñðíîãî ýêðàíà'), ('MENU CONTROL TOUCH ALT', 'Alternative layout:', - 'Àëüòåðíàòèâíàÿ ðàñêëàäêà:'), + 'Àëüòåðíàòèâíàÿ ðàñêëàäêà:'), ('MENU CONTROL TOUCH FIRE', 'Shoot Up/Down:', 'Ñòðåëÿòü ââåðõ/âíèç:'), ('MENU CONTROL TOUCH SIZE', 'Button size:', @@ -1355,6 +1356,8 @@ const 'Ïîëó÷åíî ñåðâåðîâ: %d'), ('NET SLIST CONN', 'Connected to masterserver.', 'Ïîäêëþ÷èëèñü ê ìàñòåðñåðâåðó.'), + ('NET SLIST WCONN', 'Connecting to masterserver...', + 'Ïîäêëþ÷àåìñÿ ê ìàñòåðñåðâåðó...'), ('NET SLIST DISC', 'Disconnected from masterserver.', 'Îòêëþ÷èëèñü îò ìàñòåðñåðâåðà.'), ('NET SLIST LOST', 'Lost connection with masterserver.', diff --git a/src/game/g_netmaster.pas b/src/game/g_netmaster.pas index 98f191c..beada6a 100644 --- a/src/game/g_netmaster.pas +++ b/src/game/g_netmaster.pas @@ -54,8 +54,8 @@ type TNetServerTable = array of TNetServerRow; var - NetMHost: pENetHost = nil; - NetMPeer: pENetPeer = nil; + NetMHost: pENetHost = nil; + NetMPeer: pENetPeer = nil; slCurrent: TNetServerList = nil; slTable: TNetServerTable = nil; @@ -69,7 +69,7 @@ procedure g_Net_Slist_Set(IP: string; Port: Word); function g_Net_Slist_Fetch(var SL: TNetServerList): Boolean; procedure g_Net_Slist_Update(); procedure g_Net_Slist_Remove(); -function g_Net_Slist_Connect(): Boolean; +function g_Net_Slist_Connect(blocking: Boolean=True): Boolean; procedure g_Net_Slist_Check(); procedure g_Net_Slist_Disconnect(); procedure g_Net_Slist_WriteInfo(); @@ -91,6 +91,10 @@ var slFetched: Boolean = False; slDirPressed: Boolean = False; slReadUrgent: Boolean = False; + // inside the game, calling `g_Net_Slist_Connect()` is disasterous, as it is blocking. + // so we'll use this variable to indicate if "connected" event is received. + NetHostConnected: Boolean = false; + NetHostConReqTime: Int64 = 0; // to timeout `connect` function GetTimerMS(): Int64; begin @@ -382,11 +386,40 @@ end; procedure g_Net_Slist_Update; var - P: pENetPacket; - + ct: Int64; begin - if (NetMHost = nil) or (NetMPeer = nil) then Exit; + if (NetMHost = nil) or (NetMPeer = nil) then exit; + + // we are waiting for connection + if (not NetHostConnected) then + begin + // check for connection packet + if (enet_host_service(NetMHost, @NetMEvent, 0) > 0) then + begin + if NetMEvent.kind = ENET_EVENT_TYPE_CONNECT then + begin + NetHostConnected := True; + g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_SLIST_CONN]); + end + else + begin + if NetMEvent.kind = ENET_EVENT_TYPE_RECEIVE then enet_packet_destroy(NetMEvent.packet); + end; + end; + // check for connection timeout + if (not NetHostConnected) then + begin + ct := GetTimerMS(); + if (ct-NetHostConReqTime >= 3000) then + begin + // do not spam with error messages, it looks like the master is down + //g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR], True); + g_Net_Slist_Disconnect(); + exit; + end; + end; + end; NetOut.Clear(); NetOut.Write(Byte(NET_MMSG_UPD)); @@ -405,7 +438,7 @@ procedure g_Net_Slist_Remove; var P: pENetPacket; begin - if (NetMHost = nil) or (NetMPeer = nil) then Exit; + if (NetMHost = nil) or (NetMPeer = nil) or (not NetHostConnected) then Exit; NetOut.Clear(); NetOut.Write(Byte(NET_MMSG_DEL)); NetOut.Write(NetAddr.port); @@ -417,9 +450,13 @@ begin NetOut.Clear(); end; -function g_Net_Slist_Connect: Boolean; +function g_Net_Slist_Connect (blocking: Boolean=True): Boolean; +var + delay: Integer; begin Result := False; + NetHostConnected := False; // just in case + NetHostConReqTime := 0; // just in case NetMHost := enet_host_create(nil, 1, NET_MCHANS, 0, 0); if (NetMHost = nil) then @@ -437,10 +474,12 @@ begin Exit; end; - if (enet_host_service(NetMHost, @NetMEvent, 3000) > 0) then + if (blocking) then delay := 3000 else delay := 0; + if (enet_host_service(NetMHost, @NetMEvent, delay) > 0) then if NetMEvent.kind = ENET_EVENT_TYPE_CONNECT then begin Result := True; + NetHostConnected := True; g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_SLIST_CONN]); Exit; end @@ -448,10 +487,22 @@ begin if NetMEvent.kind = ENET_EVENT_TYPE_RECEIVE then enet_packet_destroy(NetMEvent.packet); - g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR], True); + if (blocking) then + begin + g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR], True); - NetMHost := nil; - NetMPeer := nil; + if NetMPeer <> nil then enet_peer_reset(NetMPeer); + if NetMHost <> nil then enet_host_destroy(NetMHost); + NetMPeer := nil; + NetMHost := nil; + NetHostConnected := False; + NetHostConReqTime := 0; + end + else + begin + NetHostConReqTime := GetTimerMS(); + g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_SLIST_WCONN]); + end; end; procedure g_Net_Slist_Disconnect; @@ -468,13 +519,15 @@ begin NetMPeer := nil; NetMHost := nil; + NetHostConnected := False; + NetHostConReqTime := 0; g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_SLIST_DISC]); end; procedure g_Net_Slist_Check; begin - if (NetMHost = nil) or (NetMPeer = nil) then Exit; + if (NetMHost = nil) or (NetMPeer = nil) or (not NetHostConnected) then Exit; while (enet_host_service(NetMHost, @NetMEvent, 0) > 0) do begin @@ -485,6 +538,8 @@ begin if NetMHost <> nil then enet_host_destroy(NetMHost); NetMPeer := nil; NetMHost := nil; + NetHostConnected := False; + NetHostConReqTime := 0; Break; end else @@ -784,7 +839,7 @@ begin Exit; end; - // if there's a message on the screen, + // if there's a message on the screen, if not slReadUrgent and (slUrgent <> '') then begin if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or -- 2.29.2