fa3d1904c29be532f66056f96f9c38c6c9e11961
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 {$INCLUDE ../shared/a_modes.inc}
18 interface
20 uses
23 const
33 const
34 // all timeouts in seconds
37 //NMASTER_TIMEOUT_RECONNECT = 30; // 5 minutes
38 //NMASTER_FORCE_UPDATE_TIMEOUT = 20;
39 //NMASTER_FORCE_UPDATE_TIMEOUT = 0;
41 type
65 type
67 public
70 public
73 // inside the game, calling `connect()` is disasterous, as it is blocking.
74 // so we'll use this variable to indicate if "connected" event is received.
79 updateSent: Boolean; // was at least one update sent? (used to decide if we should call `remove()`)
81 // server list request working flags
87 // temporary mark
91 private
94 public
106 // call as often as you want, the object will do the rest
107 // but try to call this at least once in 100 msecs
124 var
139 // make this server private
141 // make this server public
144 // called while the server is running
146 // called when the server is started
148 // called when the server is stopped
151 // called when new netword player comes
153 // called when new netword player comes
155 // started new map
157 // this server renamed (or password mode changed, or other params changed)
160 // non-zero timeout ignores current status (used to fetch server list)
172 implementation
174 uses
180 // ////////////////////////////////////////////////////////////////////////// //
181 var
194 //==========================================================================
195 //
196 // GetTimerMS
197 //
198 //==========================================================================
200 begin
205 //==========================================================================
206 //
207 // findByPeer
208 //
209 //==========================================================================
211 var
213 begin
219 //==========================================================================
220 //
221 // ShutdownAll
222 //
223 //==========================================================================
225 var
229 begin
232 begin
234 begin
237 begin
241 //mlist[f].disconnect(false);
248 begin
252 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
253 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
254 // thank you, enet. let's ignore failures altogether then.
256 // if (sres < 0) then break;
261 begin
263 continue;
267 begin
269 //mlist[idx].disconnect(false);
271 end
273 begin
276 end
278 begin
288 //==========================================================================
289 //
290 // DisconnectAll
291 //
292 //==========================================================================
294 var
296 begin
298 begin
304 //==========================================================================
305 //
306 // ConnectAll
307 //
308 //==========================================================================
310 var
312 begin
313 // set flags; pulse will take care of the rest
315 begin
316 // force reconnect
318 // force updating
320 begin
328 //==========================================================================
329 //
330 // UpdateAll
331 //
332 //==========================================================================
334 var
336 begin
337 // set flags; pulse will take care of the rest
339 begin
347 //**************************************************************************
348 //
349 // public api
350 //
351 //**************************************************************************
353 //==========================================================================
354 //
355 // g_Net_Slist_Private
356 //
357 // make this server private
358 //
359 //==========================================================================
361 begin
367 //==========================================================================
368 //
369 // g_Net_Slist_Public
370 //
371 // make this server public
372 //
373 //==========================================================================
375 begin
377 begin
384 //==========================================================================
385 //
386 // g_Net_Slist_ServerUpdate
387 //
388 // called while the server is running
389 //
390 //==========================================================================
392 begin
397 // called when the server is started
399 begin
402 begin
409 //==========================================================================
410 //
411 // g_Net_Slist_ServerClosed
412 //
413 // called when the server is stopped
414 //
415 //==========================================================================
417 var
419 begin
421 begin
424 begin
432 //==========================================================================
433 //
434 // g_Net_Slist_ServerPlayerComes
435 //
436 // called when new netword player comes
437 //
438 //==========================================================================
440 begin
445 //==========================================================================
446 //
447 // g_Net_Slist_ServerPlayerLeaves
448 //
449 // called when new netword player comes
450 //
451 //==========================================================================
453 begin
458 //==========================================================================
459 //
460 // g_Net_Slist_ServerMapStarted
461 //
462 // started new map
463 //
464 //==========================================================================
466 begin
471 //==========================================================================
472 //
473 // g_Net_Slist_ServerRenamed
474 //
475 // this server renamed (or password mode changed, or other params changed)
476 //
477 //==========================================================================
479 begin
484 //**************************************************************************
485 //
486 // TMasterHost
487 //
488 //**************************************************************************
490 //==========================================================================
491 //
492 // TMasterHost.Create
493 //
494 //==========================================================================
496 begin
518 //==========================================================================
519 //
520 // TMasterHost.clear
521 //
522 //==========================================================================
524 begin
538 //==========================================================================
539 //
540 // TMasterHost.setAddress
541 //
542 //==========================================================================
544 begin
560 if (length(hostStr) > 0) then hostName := hostStr else hostName := IntToStr(enetAddr.host)+':'+IntToStr(ea.port);
566 //==========================================================================
567 //
568 // TMasterHost.isValid
569 //
570 //==========================================================================
572 begin
577 //==========================================================================
578 //
579 // TMasterHost.isAlive
580 //
581 // not disconnected
582 //
583 //==========================================================================
585 begin
590 //==========================================================================
591 //
592 // TMasterHost.isConnecting
593 //
594 // is connection in progress?
595 //
596 //==========================================================================
598 begin
603 //==========================================================================
604 //
605 // TMasterHost.isConnected
606 //
607 //==========================================================================
609 begin
614 //==========================================================================
615 //
616 // TMasterHost.connectedEvent
617 //
618 //==========================================================================
620 begin
626 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
630 //==========================================================================
631 //
632 // TMasterHost.disconnectedEvent
633 //
634 //==========================================================================
636 begin
640 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
644 //==========================================================================
645 //
646 // TMasterHost.receivedEvent
647 //
648 // `pkt` is never `nil`
649 //
650 //==========================================================================
652 var
658 begin
661 // packet type
668 //slUrgent := '';
670 // number of items
672 //g_Console_Add(_lc[I_NET_MSG]+Format(_lc[I_NET_SLIST_RETRIEVED], [Cnt, hostName]), True);
675 begin
678 begin
696 begin
697 // new master, supports version reports
700 begin
701 { TODO }
704 // even newer master, supports extra info
706 begin
708 if (slMOTD <> '') then e_LogWritefln('got MOTD from master at [%s]: %s', [hostName, slMOTD], TMsgType.Notify);
710 // check if the message has updated and the user has to read it again
713 if (s <> '') then e_LogWritefln('got urgent from master at [%s]: %s', [hostName, s], TMsgType.Notify);
719 //==========================================================================
720 //
721 // TMasterHost.disconnect
722 //
723 //==========================================================================
725 begin
727 begin
730 begin
735 end
736 else
737 begin
739 // main pulse will take care of the rest
742 end
743 else
744 begin
745 // just in case
753 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
757 //==========================================================================
758 //
759 // TMasterHost.connect
760 //
761 //==========================================================================
763 begin
767 begin
769 if (NetHostConReqTime = -1) then e_LogWritefln('ketmar broke master [%s] logic! (000)', [hostName], TMsgType.Notify);
770 if (isAlive()) then e_LogWritefln('ketmar broke master [%s] logic! (001)', [hostName], TMsgType.Notify);
771 end
772 else
773 begin
789 begin
791 exit;
799 //==========================================================================
800 //
801 // TMasterHost.writeInfo
802 //
803 //==========================================================================
805 var
807 begin
825 //==========================================================================
826 //
827 // TMasterHost.update
828 //
829 //==========================================================================
831 var
833 begin
836 begin
838 exit;
844 begin
845 try
848 //writeln(formatstrf('%08x', [NetAddr.host]), ' : ', NetAddr.host);
854 begin
856 begin
862 finally
865 end
866 else
867 begin
873 //==========================================================================
874 //
875 // TMasterHost.remove
876 //
877 //==========================================================================
879 var
881 begin
889 try
895 begin
898 finally
904 //==========================================================================
905 //
906 // TMasterHost.pulse
907 //
908 // this performs various scheduled tasks, if necessary
909 //
910 //==========================================================================
912 var
915 begin
919 // process pending connection timeout
921 begin
923 begin
925 // do not spam with error messages, it looks like the master is down
926 //g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR], True);
929 exit;
931 // send update, if necessary
933 begin
939 begin
940 //e_LogWritefln('update timeout: %d', [Integer(mrate)], TMsgType.Notify);
948 //**************************************************************************
949 //
950 // other functions
951 //
952 //**************************************************************************
953 type
956 var
960 //==========================================================================
961 //
962 // parseAddressPort
963 //
964 //==========================================================================
966 var
970 begin
982 begin
987 begin
988 try
990 except
1002 begin
1004 end
1005 else
1006 begin
1008 begin
1010 exit;
1019 //==========================================================================
1020 //
1021 // addMasterRecord
1022 //
1023 //==========================================================================
1025 var
1028 begin
1031 begin
1033 begin
1035 exit;
1040 begin
1051 //==========================================================================
1052 //
1053 // g_Net_Slist_Set
1054 //
1055 //==========================================================================
1057 var
1062 begin
1068 //writeln('list=[', list, ']');
1070 begin
1075 //writeln(' sa=[', sa, ']');
1079 // remove unknown master servers
1082 begin
1085 begin
1094 //**************************************************************************
1095 //
1096 // main pulse
1097 //
1098 //**************************************************************************
1100 //==========================================================================
1101 //
1102 // isMasterReportsEnabled
1103 //
1104 //==========================================================================
1106 begin
1111 //==========================================================================
1112 //
1113 // g_Net_Slist_Pulse
1114 //
1115 // non-zero timeout ignores current status (used to fetch server list)
1116 //
1117 //==========================================================================
1119 var
1126 begin
1130 begin
1132 begin
1135 exit;
1140 begin
1143 begin
1144 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_create)', TMsgType.Notify);
1147 Exit;
1153 // reconnect/disconnect/pulse for each master
1155 begin
1158 begin
1159 // not connected; try to reconnect if we're asking for a host list, or we are in netgame, and we are the host
1161 begin
1162 if (mlist[f].lastDisconnectTime = 0) or (ct < mlist[f].lastDisconnectTime) or (ct-mlist[f].lastDisconnectTime >= 1000*NMASTER_TIMEOUT_RECONNECT) then
1163 begin
1166 end
1167 else
1168 begin
1169 //e_LogWritefln('DEAD master [%s]: ct=%d; ldt=%d; diff=%d', [mlist[f].hostName, Integer(ct), Integer(mlist[f].lastDisconnectTime), Integer(ct-mlist[f].lastDisconnectTime)], TMsgType.Notify);
1172 end
1173 else
1174 begin
1175 // if we're not in slist query, and not in netgame (or not a host), disconnect
1177 begin
1179 begin
1190 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
1191 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
1192 // thank you, enet. let's ignore failures altogether then.
1196 begin
1197 {
1198 if (sres < 0) then
1199 begin
1200 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_service)', TMsgType.Notify);
1201 for f := 0 to High(mlist) do mlist[f].clear();
1202 SetLength(mlist, 0);
1203 enet_host_destroy(NetMHost);
1204 NetMHost := nil;
1205 exit;
1206 end;
1207 }
1211 begin
1214 end
1215 else
1216 begin
1218 begin
1220 end
1222 begin
1224 end
1226 begin
1239 //**************************************************************************
1240 //
1241 // gui and server list
1242 //
1243 //**************************************************************************
1245 //==========================================================================
1246 //
1247 // PingServer
1248 //
1249 //==========================================================================
1251 var
1255 begin
1269 //==========================================================================
1270 //
1271 // PingBcast
1272 //
1273 //==========================================================================
1275 var
1277 begin
1287 //==========================================================================
1288 //
1289 // g_Net_Slist_Fetch
1290 //
1291 //==========================================================================
1293 var
1306 begin
1310 begin
1328 begin
1343 begin
1364 var
1369 begin
1374 begin
1376 exit;
1384 begin
1392 // TODO: what should we identify the build with?
1396 try
1400 // wait until all servers connected and answered
1403 begin
1407 begin
1408 {
1409 e_LogWritefln(' master #%d: [%s] valid=%d; alive=%d; connected=%d; connecting=%d',
1410 [f, mlist[f].hostName, Integer(mlist[f].isValid()), Integer(mlist[f].isAlive()),
1411 Integer(mlist[f].isConnected()), Integer(mlist[f].isConnecting())], TMsgType.Notify);
1412 }
1415 begin
1417 begin
1420 begin
1421 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_WCONN], [mlist[f].hostName]));
1425 end
1427 begin
1430 end
1432 begin
1433 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
1435 begin
1438 begin
1440 begin
1446 end
1448 begin
1450 end
1452 begin
1456 end
1458 begin
1463 // check for timeout
1470 begin
1473 exit;
1477 {
1478 slUrgent := '';
1479 slReadUrgent := true;
1480 }
1484 begin
1487 begin
1490 begin
1492 begin
1494 break;
1498 begin
1506 begin
1508 begin
1514 begin
1522 begin
1524 exit;
1543 begin
1559 begin
1561 begin
1577 break;
1585 finally
1591 //==========================================================================
1592 //
1593 // GetServerFromTable
1594 //
1595 //==========================================================================
1596 function GetServerFromTable (Index: Integer; SL: TNetServerList; ST: TNetServerTable): TNetServer;
1597 begin
1613 Exit;
1615 Exit;
1620 //==========================================================================
1621 //
1622 // g_Serverlist_Draw
1623 //
1624 //==========================================================================
1626 var
1634 begin
1651 e_TextureFontPrintEx(gScreenWidth div 2 - mw, gScreenHeight-24, ip, gStdFont, 225, 225, 225, 1);
1653 // MOTD
1655 begin
1661 // Urgent message
1663 begin
1682 Exit;
1686 begin
1693 Exit;
1698 begin
1705 else
1707 end else
1734 begin
1736 // Name and map
1740 // Ping and similar count
1743 else
1746 else
1747 e_TextureFontPrintEx(mx - 68, y, IntToStr(Srv.Ping) + _lc[I_NET_SLIST_PING_MS], gStdFont, 255, 255, 255, 1);
1750 e_TextureFontPrintEx(mx - 68, y + 16, '< ' + IntToStr(Length(ST[I].Indices)) + ' >', gStdFont, 210, 210, 210, 1);
1752 // Game mode
1755 // Players
1756 e_TextureFontPrintEx(mx + 54, y, IntToStr(Srv.Players) + '/' + IntToStr(Srv.MaxPlayers), gStdFont, 255, 255, 255, 1);
1757 e_TextureFontPrintEx(mx + 54, y + 16, IntToStr(Srv.LocalPl) + '+' + IntToStr(Srv.Bots), gStdFont, 210, 210, 210, 1);
1759 // Version
1772 //==========================================================================
1773 //
1774 // g_Serverlist_GenerateTable
1775 //
1776 //==========================================================================
1778 var
1782 var
1784 begin
1787 Exit;
1789 begin
1791 continue;
1793 begin
1795 Exit;
1800 var
1802 begin
1810 var
1813 begin
1817 begin
1824 var
1827 begin
1831 begin
1837 begin
1840 Exit;
1842 begin
1845 begin
1851 end
1852 else
1853 begin
1866 //==========================================================================
1867 //
1868 // g_Serverlist_Control
1869 //
1870 //==========================================================================
1872 var
1875 begin
1879 Exit;
1886 begin
1894 Exit;
1897 // if there's a message on the screen,
1899 begin
1900 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1901 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1903 Exit;
1907 e_KeyPressed(JOY0_ACTIVATE) or e_KeyPressed(JOY1_ACTIVATE) or e_KeyPressed(JOY2_ACTIVATE) or e_KeyPressed(JOY3_ACTIVATE) then
1908 begin
1910 begin
1913 g_Game_Draw;
1914 sys_Repaint;
1917 begin
1920 end
1921 else
1928 end
1929 else
1934 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1935 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1936 begin
1938 begin
1941 begin
1949 Exit;
1950 end
1951 else
1956 Exit;
1958 end
1959 else
1963 e_KeyPressed(JOY0_DOWN) or e_KeyPressed(JOY1_DOWN) or e_KeyPressed(JOY2_DOWN) or e_KeyPressed(JOY3_DOWN) then
1964 begin
1966 begin
1974 e_KeyPressed(JOY0_UP) or e_KeyPressed(JOY1_UP) or e_KeyPressed(JOY2_UP) or e_KeyPressed(JOY3_UP) then
1975 begin
1977 begin
1986 e_KeyPressed(JOY0_RIGHT) or e_KeyPressed(JOY1_RIGHT) or e_KeyPressed(JOY2_RIGHT) or e_KeyPressed(JOY3_RIGHT) then
1987 begin
1989 begin
1997 e_KeyPressed(JOY0_LEFT) or e_KeyPressed(JOY1_LEFT) or e_KeyPressed(JOY2_LEFT) or e_KeyPressed(JOY3_LEFT) then
1998 begin
2000 begin
2001 if ST[slSelection].Current = 0 then ST[slSelection].Current := Length(ST[slSelection].Indices);
2020 (not e_KeyPressed(JOY0_UP)) and (not e_KeyPressed(JOY1_UP)) and (not e_KeyPressed(JOY2_UP)) and (not e_KeyPressed(JOY3_UP)) and
2021 (not e_KeyPressed(JOY0_DOWN)) and (not e_KeyPressed(JOY1_DOWN)) and (not e_KeyPressed(JOY2_DOWN)) and (not e_KeyPressed(JOY3_DOWN)) and
2022 (not e_KeyPressed(JOY0_LEFT)) and (not e_KeyPressed(JOY1_LEFT)) and (not e_KeyPressed(JOY2_LEFT)) and (not e_KeyPressed(JOY3_LEFT)) and
2023 (not e_KeyPressed(JOY0_RIGHT)) and (not e_KeyPressed(JOY1_RIGHT)) and (not e_KeyPressed(JOY2_RIGHT)) and (not e_KeyPressed(JOY3_RIGHT))
2024 then