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)
168 function GetServerFromTable (Index: Integer; SL: TNetServerList; ST: TNetServerTable): TNetServer;
176 implementation
178 uses
184 // ////////////////////////////////////////////////////////////////////////// //
185 var
196 //==========================================================================
197 //
198 // GetTimerMS
199 //
200 //==========================================================================
202 begin
207 //==========================================================================
208 //
209 // findByPeer
210 //
211 //==========================================================================
213 var
215 begin
221 //==========================================================================
222 //
223 // ShutdownAll
224 //
225 //==========================================================================
227 var
231 begin
234 begin
236 begin
239 begin
243 //mlist[f].disconnect(false);
250 begin
254 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
255 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
256 // thank you, enet. let's ignore failures altogether then.
258 // if (sres < 0) then break;
263 begin
265 continue;
269 begin
271 //mlist[idx].disconnect(false);
273 end
275 begin
278 end
280 begin
290 //==========================================================================
291 //
292 // DisconnectAll
293 //
294 //==========================================================================
296 var
298 begin
300 begin
306 //==========================================================================
307 //
308 // ConnectAll
309 //
310 //==========================================================================
312 var
314 begin
315 // set flags; pulse will take care of the rest
317 begin
318 // force reconnect
320 // force updating
322 begin
330 //==========================================================================
331 //
332 // UpdateAll
333 //
334 //==========================================================================
336 var
338 begin
339 // set flags; pulse will take care of the rest
341 begin
349 //**************************************************************************
350 //
351 // public api
352 //
353 //**************************************************************************
355 //==========================================================================
356 //
357 // g_Net_Slist_Private
358 //
359 // make this server private
360 //
361 //==========================================================================
363 begin
369 //==========================================================================
370 //
371 // g_Net_Slist_Public
372 //
373 // make this server public
374 //
375 //==========================================================================
377 begin
379 begin
386 //==========================================================================
387 //
388 // g_Net_Slist_ServerUpdate
389 //
390 // called while the server is running
391 //
392 //==========================================================================
394 begin
399 // called when the server is started
401 begin
404 begin
411 //==========================================================================
412 //
413 // g_Net_Slist_ServerClosed
414 //
415 // called when the server is stopped
416 //
417 //==========================================================================
419 var
421 begin
423 begin
426 begin
434 //==========================================================================
435 //
436 // g_Net_Slist_ServerPlayerComes
437 //
438 // called when new netword player comes
439 //
440 //==========================================================================
442 begin
447 //==========================================================================
448 //
449 // g_Net_Slist_ServerPlayerLeaves
450 //
451 // called when new netword player comes
452 //
453 //==========================================================================
455 begin
460 //==========================================================================
461 //
462 // g_Net_Slist_ServerMapStarted
463 //
464 // started new map
465 //
466 //==========================================================================
468 begin
473 //==========================================================================
474 //
475 // g_Net_Slist_ServerRenamed
476 //
477 // this server renamed (or password mode changed, or other params changed)
478 //
479 //==========================================================================
481 begin
486 //**************************************************************************
487 //
488 // TMasterHost
489 //
490 //**************************************************************************
492 //==========================================================================
493 //
494 // TMasterHost.Create
495 //
496 //==========================================================================
498 begin
520 //==========================================================================
521 //
522 // TMasterHost.clear
523 //
524 //==========================================================================
526 begin
540 //==========================================================================
541 //
542 // TMasterHost.setAddress
543 //
544 //==========================================================================
546 begin
562 if (length(hostStr) > 0) then hostName := hostStr else hostName := IntToStr(enetAddr.host)+':'+IntToStr(ea.port);
568 //==========================================================================
569 //
570 // TMasterHost.isValid
571 //
572 //==========================================================================
574 begin
579 //==========================================================================
580 //
581 // TMasterHost.isAlive
582 //
583 // not disconnected
584 //
585 //==========================================================================
587 begin
592 //==========================================================================
593 //
594 // TMasterHost.isConnecting
595 //
596 // is connection in progress?
597 //
598 //==========================================================================
600 begin
605 //==========================================================================
606 //
607 // TMasterHost.isConnected
608 //
609 //==========================================================================
611 begin
616 //==========================================================================
617 //
618 // TMasterHost.connectedEvent
619 //
620 //==========================================================================
622 begin
628 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
632 //==========================================================================
633 //
634 // TMasterHost.disconnectedEvent
635 //
636 //==========================================================================
638 begin
642 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
646 //==========================================================================
647 //
648 // TMasterHost.receivedEvent
649 //
650 // `pkt` is never `nil`
651 //
652 //==========================================================================
654 var
660 begin
663 // packet type
670 //slUrgent := '';
672 // number of items
674 //g_Console_Add(_lc[I_NET_MSG]+Format(_lc[I_NET_SLIST_RETRIEVED], [Cnt, hostName]), True);
677 begin
680 begin
698 begin
699 // new master, supports version reports
702 begin
703 { TODO }
706 // even newer master, supports extra info
708 begin
710 if (slMOTD <> '') then e_LogWritefln('got MOTD from master at [%s]: %s', [hostName, slMOTD], TMsgType.Notify);
712 // check if the message has updated and the user has to read it again
715 if (s <> '') then e_LogWritefln('got urgent from master at [%s]: %s', [hostName, s], TMsgType.Notify);
721 //==========================================================================
722 //
723 // TMasterHost.disconnect
724 //
725 //==========================================================================
727 begin
729 begin
732 begin
737 end
738 else
739 begin
741 // main pulse will take care of the rest
744 end
745 else
746 begin
747 // just in case
755 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
759 //==========================================================================
760 //
761 // TMasterHost.connect
762 //
763 //==========================================================================
765 begin
769 begin
771 if (NetHostConReqTime = -1) then e_LogWritefln('ketmar broke master [%s] logic! (000)', [hostName], TMsgType.Notify);
772 if (isAlive()) then e_LogWritefln('ketmar broke master [%s] logic! (001)', [hostName], TMsgType.Notify);
773 end
774 else
775 begin
791 begin
793 exit;
801 //==========================================================================
802 //
803 // TMasterHost.writeInfo
804 //
805 //==========================================================================
807 var
809 begin
827 //==========================================================================
828 //
829 // TMasterHost.update
830 //
831 //==========================================================================
833 var
835 begin
838 begin
840 exit;
846 begin
847 try
850 //writeln(formatstrf('%08x', [NetAddr.host]), ' : ', NetAddr.host);
856 begin
858 begin
864 finally
867 end
868 else
869 begin
875 //==========================================================================
876 //
877 // TMasterHost.remove
878 //
879 //==========================================================================
881 var
883 begin
891 try
897 begin
900 finally
906 //==========================================================================
907 //
908 // TMasterHost.pulse
909 //
910 // this performs various scheduled tasks, if necessary
911 //
912 //==========================================================================
914 var
917 begin
921 // process pending connection timeout
923 begin
925 begin
927 // do not spam with error messages, it looks like the master is down
928 //g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR], True);
931 exit;
933 // send update, if necessary
935 begin
941 begin
942 //e_LogWritefln('update timeout: %d', [Integer(mrate)], TMsgType.Notify);
950 //**************************************************************************
951 //
952 // other functions
953 //
954 //**************************************************************************
955 type
958 var
962 //==========================================================================
963 //
964 // parseAddressPort
965 //
966 //==========================================================================
968 var
972 begin
984 begin
989 begin
990 try
992 except
1004 begin
1006 end
1007 else
1008 begin
1010 begin
1012 exit;
1021 //==========================================================================
1022 //
1023 // addMasterRecord
1024 //
1025 //==========================================================================
1027 var
1030 begin
1033 begin
1035 begin
1037 exit;
1042 begin
1053 //==========================================================================
1054 //
1055 // g_Net_Slist_Set
1056 //
1057 //==========================================================================
1059 var
1064 begin
1070 //writeln('list=[', list, ']');
1072 begin
1077 //writeln(' sa=[', sa, ']');
1081 // remove unknown master servers
1084 begin
1087 begin
1096 //**************************************************************************
1097 //
1098 // main pulse
1099 //
1100 //**************************************************************************
1102 //==========================================================================
1103 //
1104 // isMasterReportsEnabled
1105 //
1106 //==========================================================================
1108 begin
1113 //==========================================================================
1114 //
1115 // g_Net_Slist_Pulse
1116 //
1117 // non-zero timeout ignores current status (used to fetch server list)
1118 //
1119 //==========================================================================
1121 var
1128 begin
1132 begin
1134 begin
1137 exit;
1142 begin
1145 begin
1146 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_create)', TMsgType.Notify);
1149 Exit;
1155 // reconnect/disconnect/pulse for each master
1157 begin
1160 begin
1161 // not connected; try to reconnect if we're asking for a host list, or we are in netgame, and we are the host
1163 begin
1164 if (mlist[f].lastDisconnectTime = 0) or (ct < mlist[f].lastDisconnectTime) or (ct-mlist[f].lastDisconnectTime >= 1000*NMASTER_TIMEOUT_RECONNECT) then
1165 begin
1168 end
1169 else
1170 begin
1171 //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);
1174 end
1175 else
1176 begin
1177 // if we're not in slist query, and not in netgame (or not a host), disconnect
1179 begin
1181 begin
1192 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
1193 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
1194 // thank you, enet. let's ignore failures altogether then.
1198 begin
1199 {
1200 if (sres < 0) then
1201 begin
1202 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_service)', TMsgType.Notify);
1203 for f := 0 to High(mlist) do mlist[f].clear();
1204 SetLength(mlist, 0);
1205 enet_host_destroy(NetMHost);
1206 NetMHost := nil;
1207 exit;
1208 end;
1209 }
1213 begin
1216 end
1217 else
1218 begin
1220 begin
1222 end
1224 begin
1226 end
1228 begin
1241 //**************************************************************************
1242 //
1243 // gui and server list
1244 //
1245 //**************************************************************************
1247 //==========================================================================
1248 //
1249 // PingServer
1250 //
1251 //==========================================================================
1253 var
1257 begin
1271 //==========================================================================
1272 //
1273 // PingBcast
1274 //
1275 //==========================================================================
1277 var
1279 begin
1289 //==========================================================================
1290 //
1291 // g_Net_Slist_Fetch
1292 //
1293 //==========================================================================
1295 var
1308 begin
1312 begin
1330 begin
1345 begin
1366 var
1372 begin
1377 begin
1379 exit;
1387 begin
1395 // TODO: what should we identify the build with?
1399 try
1403 // wait until all servers connected and answered
1406 begin
1410 begin
1411 {
1412 e_LogWritefln(' master #%d: [%s] valid=%d; alive=%d; connected=%d; connecting=%d',
1413 [f, mlist[f].hostName, Integer(mlist[f].isValid()), Integer(mlist[f].isAlive()),
1414 Integer(mlist[f].isConnected()), Integer(mlist[f].isConnecting())], TMsgType.Notify);
1415 }
1418 begin
1420 begin
1423 begin
1424 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_WCONN], [mlist[f].hostName]));
1428 end
1430 begin
1433 end
1435 begin
1436 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
1438 begin
1441 begin
1443 begin
1449 end
1451 begin
1453 end
1455 begin
1459 end
1461 begin
1466 // check for timeout
1473 begin
1476 exit;
1480 {
1481 slUrgent := '';
1482 slReadUrgent := true;
1483 }
1487 begin
1490 begin
1493 begin
1495 begin
1497 break;
1501 begin
1509 begin
1511 begin
1517 begin
1525 begin
1527 exit;
1546 begin
1559 begin
1581 begin
1586 break;
1590 begin
1600 finally
1606 //==========================================================================
1607 //
1608 // GetServerFromTable
1609 //
1610 //==========================================================================
1611 function GetServerFromTable (Index: Integer; SL: TNetServerList; ST: TNetServerTable): TNetServer;
1612 begin
1628 Exit;
1630 Exit;
1635 //==========================================================================
1636 //
1637 // g_Serverlist_GenerateTable
1638 //
1639 //==========================================================================
1641 var
1645 var
1647 begin
1650 Exit;
1652 begin
1654 continue;
1656 begin
1658 Exit;
1663 var
1665 begin
1673 var
1676 begin
1680 begin
1687 var
1690 begin
1694 begin
1700 begin
1703 Exit;
1706 begin
1709 begin
1715 end
1716 else
1717 begin
1730 //==========================================================================
1731 //
1732 // g_Serverlist_Control
1733 //
1734 //==========================================================================
1736 var
1739 begin
1743 Exit;
1750 begin
1758 Exit;
1761 // if there's a message on the screen,
1763 begin
1764 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1765 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1767 Exit;
1771 e_KeyPressed(JOY0_ACTIVATE) or e_KeyPressed(JOY1_ACTIVATE) or e_KeyPressed(JOY2_ACTIVATE) or e_KeyPressed(JOY3_ACTIVATE) then
1772 begin
1774 begin
1777 r_Game_Draw;
1778 sys_Repaint;
1781 begin
1784 end
1785 else
1792 end
1793 else
1798 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1799 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1800 begin
1802 begin
1805 begin
1813 Exit;
1814 end
1815 else
1820 Exit;
1822 end
1823 else
1827 e_KeyPressed(JOY0_DOWN) or e_KeyPressed(JOY1_DOWN) or e_KeyPressed(JOY2_DOWN) or e_KeyPressed(JOY3_DOWN) then
1828 begin
1830 begin
1838 e_KeyPressed(JOY0_UP) or e_KeyPressed(JOY1_UP) or e_KeyPressed(JOY2_UP) or e_KeyPressed(JOY3_UP) then
1839 begin
1841 begin
1850 e_KeyPressed(JOY0_RIGHT) or e_KeyPressed(JOY1_RIGHT) or e_KeyPressed(JOY2_RIGHT) or e_KeyPressed(JOY3_RIGHT) then
1851 begin
1853 begin
1861 e_KeyPressed(JOY0_LEFT) or e_KeyPressed(JOY1_LEFT) or e_KeyPressed(JOY2_LEFT) or e_KeyPressed(JOY3_LEFT) then
1862 begin
1864 begin
1865 if ST[slSelection].Current = 0 then ST[slSelection].Current := Length(ST[slSelection].Indices);
1884 (not e_KeyPressed(JOY0_UP)) and (not e_KeyPressed(JOY1_UP)) and (not e_KeyPressed(JOY2_UP)) and (not e_KeyPressed(JOY3_UP)) and
1885 (not e_KeyPressed(JOY0_DOWN)) and (not e_KeyPressed(JOY1_DOWN)) and (not e_KeyPressed(JOY2_DOWN)) and (not e_KeyPressed(JOY3_DOWN)) and
1886 (not e_KeyPressed(JOY0_LEFT)) and (not e_KeyPressed(JOY1_LEFT)) and (not e_KeyPressed(JOY2_LEFT)) and (not e_KeyPressed(JOY3_LEFT)) and
1887 (not e_KeyPressed(JOY0_RIGHT)) and (not e_KeyPressed(JOY1_RIGHT)) and (not e_KeyPressed(JOY2_RIGHT)) and (not e_KeyPressed(JOY3_RIGHT))
1888 then