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 type
57 type
59 public
62 public
65 // inside the game, calling `connect()` is disasterous, as it is blocking.
66 // so we'll use this variable to indicate if "connected" event is received.
73 // server list request working flags
79 // temporary mark
82 private
85 public
97 // call as often as you want, the object will do the rest
98 // but try to call this at least once in 100 msecs
115 var
128 // make this server private
130 // make this server public
133 // called while the server is running
135 // called when the server is started
137 // called when the server is stopped
140 // called when new netword player comes
142 // called when new netword player comes
144 // started new map
146 // this server renamed (or password mode changed, or other params changed)
149 // non-zero timeout ignores current status (used to fetch server list)
161 implementation
163 uses
169 // ////////////////////////////////////////////////////////////////////////// //
170 var
183 //==========================================================================
184 //
185 // GetTimerMS
186 //
187 //==========================================================================
189 begin
194 //==========================================================================
195 //
196 // findByPeer
197 //
198 //==========================================================================
200 var
202 begin
208 //==========================================================================
209 //
210 // ShutdownAll
211 //
212 //==========================================================================
214 var
218 begin
221 begin
223 begin
226 begin
230 //mlist[f].disconnect(false);
237 begin
241 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
242 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
243 // thank you, enet. let's ignore failures altogether then.
245 // if (sres < 0) then break;
250 begin
252 continue;
256 begin
258 //mlist[idx].disconnect(false);
260 end
262 begin
265 end
267 begin
277 //==========================================================================
278 //
279 // DisconnectAll
280 //
281 //==========================================================================
283 var
285 begin
287 begin
293 //==========================================================================
294 //
295 // ConnectAll
296 //
297 //==========================================================================
299 var
301 begin
303 begin
304 // force reconnect
306 //if (not mlist[f].isAlive()) then continue;
307 // force updating
309 begin
317 //==========================================================================
318 //
319 // UpdateAll
320 //
321 //==========================================================================
323 var
325 begin
327 begin
335 //**************************************************************************
336 //
337 // public api
338 //
339 //**************************************************************************
341 //==========================================================================
342 //
343 // g_Net_Slist_Private
344 //
345 // make this server private
346 //
347 //==========================================================================
349 begin
355 //==========================================================================
356 //
357 // g_Net_Slist_Public
358 //
359 // make this server public
360 //
361 //==========================================================================
363 begin
365 begin
372 //==========================================================================
373 //
374 // g_Net_Slist_ServerUpdate
375 //
376 // called while the server is running
377 //
378 //==========================================================================
380 begin
385 // called when the server is started
387 begin
390 begin
397 //==========================================================================
398 //
399 // g_Net_Slist_ServerClosed
400 //
401 // called when the server is stopped
402 //
403 //==========================================================================
405 var
407 begin
409 begin
412 begin
420 //==========================================================================
421 //
422 // g_Net_Slist_ServerPlayerComes
423 //
424 // called when new netword player comes
425 //
426 //==========================================================================
428 begin
433 //==========================================================================
434 //
435 // g_Net_Slist_ServerPlayerLeaves
436 //
437 // called when new netword player comes
438 //
439 //==========================================================================
441 begin
446 //==========================================================================
447 //
448 // g_Net_Slist_ServerMapStarted
449 //
450 // started new map
451 //
452 //==========================================================================
454 begin
459 //==========================================================================
460 //
461 // g_Net_Slist_ServerRenamed
462 //
463 // this server renamed (or password mode changed, or other params changed)
464 //
465 //==========================================================================
467 begin
472 //**************************************************************************
473 //
474 // TMasterHost
475 //
476 //**************************************************************************
478 //==========================================================================
479 //
480 // TMasterHost.Create
481 //
482 //==========================================================================
484 begin
504 //==========================================================================
505 //
506 // TMasterHost.clear
507 //
508 //==========================================================================
510 begin
524 //==========================================================================
525 //
526 // TMasterHost.setAddress
527 //
528 //==========================================================================
530 begin
546 if (length(hostStr) > 0) then hostName := hostStr else hostName := IntToStr(enetAddr.host)+':'+IntToStr(ea.port);
552 //==========================================================================
553 //
554 // TMasterHost.isValid
555 //
556 //==========================================================================
558 begin
563 //==========================================================================
564 //
565 // TMasterHost.isAlive
566 //
567 // not disconnected
568 //
569 //==========================================================================
571 begin
576 //==========================================================================
577 //
578 // TMasterHost.isConnecting
579 //
580 // is connection in progress?
581 //
582 //==========================================================================
584 begin
589 //==========================================================================
590 //
591 // TMasterHost.isConnected
592 //
593 //==========================================================================
595 begin
600 //==========================================================================
601 //
602 // TMasterHost.connectedEvent
603 //
604 //==========================================================================
606 begin
611 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
615 //==========================================================================
616 //
617 // TMasterHost.disconnectedEvent
618 //
619 //==========================================================================
621 begin
625 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
629 //==========================================================================
630 //
631 // TMasterHost.receivedEvent
632 //
633 // `pkt` is never `nil`
634 //
635 //==========================================================================
637 var
643 begin
646 // packet type
653 //slUrgent := '';
655 // number of items
657 //g_Console_Add(_lc[I_NET_MSG]+Format(_lc[I_NET_SLIST_RETRIEVED], [Cnt, hostName]), True);
660 begin
663 begin
681 begin
682 // new master, supports version reports
685 begin
686 { TODO }
689 // even newer master, supports extra info
691 begin
693 if (slMOTD <> '') then e_LogWritefln('got MOTD from master at [%s]: %s', [hostName, slMOTD], TMsgType.Notify);
695 // check if the message has updated and the user has to read it again
698 if (s <> '') then e_LogWritefln('got urgent from master at [%s]: %s', [hostName, s], TMsgType.Notify);
704 //==========================================================================
705 //
706 // TMasterHost.pulse
707 //
708 // this performs various scheduled tasks, if necessary
709 //
710 //==========================================================================
712 var
715 begin
719 // process pending connection timeout
721 begin
723 begin
725 // do not spam with error messages, it looks like the master is down
726 //g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR], True);
728 // main pulse will take care of the rest
731 exit;
733 // send update, if necessary
735 begin
740 begin
748 //==========================================================================
749 //
750 // TMasterHost.disconnect
751 //
752 //==========================================================================
754 begin
758 begin
762 end
763 else
764 begin
766 // main pulse will take care of the rest
772 //updateSent := false;
774 //lastConnectTime := 0;
775 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
779 //==========================================================================
780 //
781 // TMasterHost.connect
782 //
783 //==========================================================================
785 begin
789 begin
791 end
792 else
793 begin
808 begin
810 exit;
818 //==========================================================================
819 //
820 // TMasterHost.writeInfo
821 //
822 //==========================================================================
824 var
826 begin
844 //==========================================================================
845 //
846 // TMasterHost.update
847 //
848 //==========================================================================
850 var
852 begin
855 begin
857 exit;
863 begin
864 try
867 //writeln(formatstrf('%08x', [NetAddr.host]), ' : ', NetAddr.host);
873 begin
875 begin
881 finally
884 end
885 else
886 begin
892 //==========================================================================
893 //
894 // TMasterHost.remove
895 //
896 //==========================================================================
898 var
900 begin
908 try
914 begin
917 finally
923 //**************************************************************************
924 //
925 // other functions
926 //
927 //**************************************************************************
928 type
931 var
935 //==========================================================================
936 //
937 // parseAddressPort
938 //
939 //==========================================================================
941 var
945 begin
957 begin
962 begin
963 try
965 except
977 begin
979 end
980 else
981 begin
983 begin
985 exit;
994 //==========================================================================
995 //
996 // addMasterRecord
997 //
998 //==========================================================================
1000 var
1003 begin
1006 begin
1008 begin
1010 exit;
1015 begin
1026 //==========================================================================
1027 //
1028 // g_Net_Slist_Set
1029 //
1030 //==========================================================================
1032 var
1037 begin
1044 begin
1050 //writeln('list=[', list, ']');
1052 begin
1057 //writeln(' sa=[', sa, ']');
1061 // remove unknown master servers
1064 begin
1067 begin
1076 //**************************************************************************
1077 //
1078 // main pulse
1079 //
1080 //**************************************************************************
1082 //==========================================================================
1083 //
1084 // g_Net_Slist_Pulse
1085 //
1086 // non-zero timeout ignores current status (used to fetch server list)
1087 //
1088 //==========================================================================
1090 var
1095 begin
1099 begin
1101 begin
1104 exit;
1109 begin
1112 begin
1113 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_create)', TMsgType.Notify);
1116 Exit;
1122 begin
1125 begin
1126 if (timeout > 0) or (reportsEnabled and g_Game_IsServer() and g_Game_IsNet() and NetUseMaster) then
1127 begin
1128 if (mlist[f].lastConnectTime = 0) or (ct < mlist[f].lastConnectTime) or (ct-mlist[f].lastConnectTime >= 1000*60*5) then
1129 begin
1134 end
1135 else
1136 begin
1137 if (timeout = 0) and (not reportsEnabled or not g_Game_IsServer() or not g_Game_IsNet() or not NetUseMaster) then
1138 begin
1140 begin
1144 //e_LogWritefln('disconnecting from master [%s]', [mlist[f].hostName], TMsgType.Notify);
1151 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
1152 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
1153 // thank you, enet. let's ignore failures altogether then.
1156 begin
1158 begin
1159 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_service)', TMsgType.Notify);
1164 exit;
1169 begin
1172 end
1173 else
1174 begin
1176 begin
1178 end
1180 begin
1182 end
1184 begin
1194 //**************************************************************************
1195 //
1196 // gui and server list
1197 //
1198 //**************************************************************************
1200 //==========================================================================
1201 //
1202 // PingServer
1203 //
1204 //==========================================================================
1206 var
1210 begin
1224 //==========================================================================
1225 //
1226 // PingBcast
1227 //
1228 //==========================================================================
1230 var
1232 begin
1242 //==========================================================================
1243 //
1244 // g_Net_Slist_Fetch
1245 //
1246 //==========================================================================
1248 var
1261 begin
1265 begin
1283 begin
1298 begin
1319 var
1324 begin
1329 begin
1331 exit;
1341 // TODO: what should we identify the build with?
1345 try
1349 // wait until all servers connected and answered
1352 begin
1356 begin
1357 {
1358 e_LogWritefln(' master #%d: [%s] valid=%d; alive=%d; connected=%d; connecting=%d',
1359 [f, mlist[f].hostName, Integer(mlist[f].isValid()), Integer(mlist[f].isAlive()),
1360 Integer(mlist[f].isConnected()), Integer(mlist[f].isConnecting())], TMsgType.Notify);
1361 }
1364 begin
1367 begin
1368 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_WCONN], [mlist[f].hostName]));
1372 end
1374 begin
1375 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
1377 begin
1380 begin
1382 begin
1388 end
1390 begin
1392 end
1394 begin
1397 end
1399 begin
1404 // check for timeout
1411 begin
1414 exit;
1418 {
1419 slUrgent := '';
1420 slReadUrgent := true;
1421 }
1425 begin
1428 begin
1431 begin
1433 begin
1435 break;
1439 begin
1447 begin
1449 begin
1455 begin
1463 begin
1465 exit;
1484 begin
1500 begin
1502 begin
1518 break;
1526 finally
1532 //==========================================================================
1533 //
1534 // GetServerFromTable
1535 //
1536 //==========================================================================
1537 function GetServerFromTable (Index: Integer; SL: TNetServerList; ST: TNetServerTable): TNetServer;
1538 begin
1554 Exit;
1556 Exit;
1561 //==========================================================================
1562 //
1563 // g_Serverlist_Draw
1564 //
1565 //==========================================================================
1567 var
1575 begin
1592 e_TextureFontPrintEx(gScreenWidth div 2 - mw, gScreenHeight-24, ip, gStdFont, 225, 225, 225, 1);
1594 // MOTD
1596 begin
1602 // Urgent message
1604 begin
1623 Exit;
1627 begin
1634 Exit;
1639 begin
1646 else
1648 end else
1675 begin
1677 // Name and map
1681 // Ping and similar count
1684 else
1687 else
1688 e_TextureFontPrintEx(mx - 68, y, IntToStr(Srv.Ping) + _lc[I_NET_SLIST_PING_MS], gStdFont, 255, 255, 255, 1);
1691 e_TextureFontPrintEx(mx - 68, y + 16, '< ' + IntToStr(Length(ST[I].Indices)) + ' >', gStdFont, 210, 210, 210, 1);
1693 // Game mode
1696 // Players
1697 e_TextureFontPrintEx(mx + 54, y, IntToStr(Srv.Players) + '/' + IntToStr(Srv.MaxPlayers), gStdFont, 255, 255, 255, 1);
1698 e_TextureFontPrintEx(mx + 54, y + 16, IntToStr(Srv.LocalPl) + '+' + IntToStr(Srv.Bots), gStdFont, 210, 210, 210, 1);
1700 // Version
1713 //==========================================================================
1714 //
1715 // g_Serverlist_GenerateTable
1716 //
1717 //==========================================================================
1719 var
1723 var
1725 begin
1728 Exit;
1730 begin
1732 continue;
1734 begin
1736 Exit;
1741 var
1743 begin
1751 var
1754 begin
1758 begin
1765 var
1768 begin
1772 begin
1778 begin
1781 Exit;
1783 begin
1786 begin
1792 end
1793 else
1794 begin
1807 //==========================================================================
1808 //
1809 // g_Serverlist_Control
1810 //
1811 //==========================================================================
1813 var
1816 begin
1820 Exit;
1827 begin
1835 Exit;
1838 // if there's a message on the screen,
1840 begin
1841 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1842 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1844 Exit;
1848 e_KeyPressed(JOY0_ACTIVATE) or e_KeyPressed(JOY1_ACTIVATE) or e_KeyPressed(JOY2_ACTIVATE) or e_KeyPressed(JOY3_ACTIVATE) then
1849 begin
1851 begin
1854 g_Game_Draw;
1855 sys_Repaint;
1858 begin
1861 end
1862 else
1869 end
1870 else
1875 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1876 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1877 begin
1879 begin
1882 begin
1890 Exit;
1891 end
1892 else
1897 Exit;
1899 end
1900 else
1904 e_KeyPressed(JOY0_DOWN) or e_KeyPressed(JOY1_DOWN) or e_KeyPressed(JOY2_DOWN) or e_KeyPressed(JOY3_DOWN) then
1905 begin
1907 begin
1915 e_KeyPressed(JOY0_UP) or e_KeyPressed(JOY1_UP) or e_KeyPressed(JOY2_UP) or e_KeyPressed(JOY3_UP) then
1916 begin
1918 begin
1927 e_KeyPressed(JOY0_RIGHT) or e_KeyPressed(JOY1_RIGHT) or e_KeyPressed(JOY2_RIGHT) or e_KeyPressed(JOY3_RIGHT) then
1928 begin
1930 begin
1938 e_KeyPressed(JOY0_LEFT) or e_KeyPressed(JOY1_LEFT) or e_KeyPressed(JOY2_LEFT) or e_KeyPressed(JOY3_LEFT) then
1939 begin
1941 begin
1942 if ST[slSelection].Current = 0 then ST[slSelection].Current := Length(ST[slSelection].Indices);
1961 (not e_KeyPressed(JOY0_UP)) and (not e_KeyPressed(JOY1_UP)) and (not e_KeyPressed(JOY2_UP)) and (not e_KeyPressed(JOY3_UP)) and
1962 (not e_KeyPressed(JOY0_DOWN)) and (not e_KeyPressed(JOY1_DOWN)) and (not e_KeyPressed(JOY2_DOWN)) and (not e_KeyPressed(JOY3_DOWN)) and
1963 (not e_KeyPressed(JOY0_LEFT)) and (not e_KeyPressed(JOY1_LEFT)) and (not e_KeyPressed(JOY2_LEFT)) and (not e_KeyPressed(JOY3_LEFT)) and
1964 (not e_KeyPressed(JOY0_RIGHT)) and (not e_KeyPressed(JOY1_RIGHT)) and (not e_KeyPressed(JOY2_RIGHT)) and (not e_KeyPressed(JOY3_RIGHT))
1965 then