e92b08728be8ff3a9b6f120148cc97e2ff93519d
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
179 {$IFDEF ENABLE_MENU}
181 {$ENDIF}
182 {$IFDEF ENABLE_RENDER}
183 r_render,
184 {$ENDIF}
185 {$IFDEF ENABLE_SYSTEM}
186 g_system,
187 {$ENDIF}
193 // ////////////////////////////////////////////////////////////////////////// //
194 var
205 //==========================================================================
206 //
207 // GetTimerMS
208 //
209 //==========================================================================
211 begin
216 //==========================================================================
217 //
218 // findByPeer
219 //
220 //==========================================================================
222 var
224 begin
230 //==========================================================================
231 //
232 // ShutdownAll
233 //
234 //==========================================================================
236 var
240 begin
243 begin
245 begin
248 begin
252 //mlist[f].disconnect(false);
259 begin
263 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
264 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
265 // thank you, enet. let's ignore failures altogether then.
267 // if (sres < 0) then break;
272 begin
274 continue;
278 begin
280 //mlist[idx].disconnect(false);
282 end
284 begin
287 end
289 begin
299 //==========================================================================
300 //
301 // DisconnectAll
302 //
303 //==========================================================================
305 var
307 begin
309 begin
315 //==========================================================================
316 //
317 // ConnectAll
318 //
319 //==========================================================================
321 var
323 begin
324 // set flags; pulse will take care of the rest
326 begin
327 // force reconnect
329 // force updating
331 begin
339 //==========================================================================
340 //
341 // UpdateAll
342 //
343 //==========================================================================
345 var
347 begin
348 // set flags; pulse will take care of the rest
350 begin
358 //**************************************************************************
359 //
360 // public api
361 //
362 //**************************************************************************
364 //==========================================================================
365 //
366 // g_Net_Slist_Private
367 //
368 // make this server private
369 //
370 //==========================================================================
372 begin
378 //==========================================================================
379 //
380 // g_Net_Slist_Public
381 //
382 // make this server public
383 //
384 //==========================================================================
386 begin
388 begin
395 //==========================================================================
396 //
397 // g_Net_Slist_ServerUpdate
398 //
399 // called while the server is running
400 //
401 //==========================================================================
403 begin
408 // called when the server is started
410 begin
413 begin
420 //==========================================================================
421 //
422 // g_Net_Slist_ServerClosed
423 //
424 // called when the server is stopped
425 //
426 //==========================================================================
428 var
430 begin
432 begin
435 begin
443 //==========================================================================
444 //
445 // g_Net_Slist_ServerPlayerComes
446 //
447 // called when new netword player comes
448 //
449 //==========================================================================
451 begin
456 //==========================================================================
457 //
458 // g_Net_Slist_ServerPlayerLeaves
459 //
460 // called when new netword player comes
461 //
462 //==========================================================================
464 begin
469 //==========================================================================
470 //
471 // g_Net_Slist_ServerMapStarted
472 //
473 // started new map
474 //
475 //==========================================================================
477 begin
482 //==========================================================================
483 //
484 // g_Net_Slist_ServerRenamed
485 //
486 // this server renamed (or password mode changed, or other params changed)
487 //
488 //==========================================================================
490 begin
495 //**************************************************************************
496 //
497 // TMasterHost
498 //
499 //**************************************************************************
501 //==========================================================================
502 //
503 // TMasterHost.Create
504 //
505 //==========================================================================
507 begin
529 //==========================================================================
530 //
531 // TMasterHost.clear
532 //
533 //==========================================================================
535 begin
549 //==========================================================================
550 //
551 // TMasterHost.setAddress
552 //
553 //==========================================================================
555 begin
571 if (length(hostStr) > 0) then hostName := hostStr else hostName := IntToStr(enetAddr.host)+':'+IntToStr(ea.port);
577 //==========================================================================
578 //
579 // TMasterHost.isValid
580 //
581 //==========================================================================
583 begin
588 //==========================================================================
589 //
590 // TMasterHost.isAlive
591 //
592 // not disconnected
593 //
594 //==========================================================================
596 begin
601 //==========================================================================
602 //
603 // TMasterHost.isConnecting
604 //
605 // is connection in progress?
606 //
607 //==========================================================================
609 begin
614 //==========================================================================
615 //
616 // TMasterHost.isConnected
617 //
618 //==========================================================================
620 begin
625 //==========================================================================
626 //
627 // TMasterHost.connectedEvent
628 //
629 //==========================================================================
631 begin
637 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
641 //==========================================================================
642 //
643 // TMasterHost.disconnectedEvent
644 //
645 //==========================================================================
647 begin
651 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
655 //==========================================================================
656 //
657 // TMasterHost.receivedEvent
658 //
659 // `pkt` is never `nil`
660 //
661 //==========================================================================
663 var
669 begin
672 // packet type
679 //slUrgent := '';
681 // number of items
683 //g_Console_Add(_lc[I_NET_MSG]+Format(_lc[I_NET_SLIST_RETRIEVED], [Cnt, hostName]), True);
686 begin
689 begin
707 begin
708 // new master, supports version reports
711 begin
712 { TODO }
715 // even newer master, supports extra info
717 begin
719 if (slMOTD <> '') then e_LogWritefln('got MOTD from master at [%s]: %s', [hostName, slMOTD], TMsgType.Notify);
721 // check if the message has updated and the user has to read it again
724 if (s <> '') then e_LogWritefln('got urgent from master at [%s]: %s', [hostName, s], TMsgType.Notify);
730 //==========================================================================
731 //
732 // TMasterHost.disconnect
733 //
734 //==========================================================================
736 begin
738 begin
741 begin
746 end
747 else
748 begin
750 // main pulse will take care of the rest
753 end
754 else
755 begin
756 // just in case
764 //if (spamConsole) then g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_DISC], [hostName]));
768 //==========================================================================
769 //
770 // TMasterHost.connect
771 //
772 //==========================================================================
774 begin
778 begin
780 if (NetHostConReqTime = -1) then e_LogWritefln('ketmar broke master [%s] logic! (000)', [hostName], TMsgType.Notify);
781 if (isAlive()) then e_LogWritefln('ketmar broke master [%s] logic! (001)', [hostName], TMsgType.Notify);
782 end
783 else
784 begin
800 begin
802 exit;
810 //==========================================================================
811 //
812 // TMasterHost.writeInfo
813 //
814 //==========================================================================
816 var
818 begin
836 //==========================================================================
837 //
838 // TMasterHost.update
839 //
840 //==========================================================================
842 var
844 begin
847 begin
849 exit;
855 begin
856 try
859 //writeln(formatstrf('%08x', [NetAddr.host]), ' : ', NetAddr.host);
865 begin
867 begin
873 finally
876 end
877 else
878 begin
884 //==========================================================================
885 //
886 // TMasterHost.remove
887 //
888 //==========================================================================
890 var
892 begin
900 try
906 begin
909 finally
915 //==========================================================================
916 //
917 // TMasterHost.pulse
918 //
919 // this performs various scheduled tasks, if necessary
920 //
921 //==========================================================================
923 var
926 begin
930 // process pending connection timeout
932 begin
934 begin
936 // do not spam with error messages, it looks like the master is down
937 //g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR], True);
940 exit;
942 // send update, if necessary
944 begin
950 begin
951 //e_LogWritefln('update timeout: %d', [Integer(mrate)], TMsgType.Notify);
959 //**************************************************************************
960 //
961 // other functions
962 //
963 //**************************************************************************
964 type
967 var
971 //==========================================================================
972 //
973 // parseAddressPort
974 //
975 //==========================================================================
977 var
981 begin
993 begin
998 begin
999 try
1001 except
1013 begin
1015 end
1016 else
1017 begin
1019 begin
1021 exit;
1030 //==========================================================================
1031 //
1032 // addMasterRecord
1033 //
1034 //==========================================================================
1036 var
1039 begin
1042 begin
1044 begin
1046 exit;
1051 begin
1062 //==========================================================================
1063 //
1064 // g_Net_Slist_Set
1065 //
1066 //==========================================================================
1068 var
1073 begin
1079 //writeln('list=[', list, ']');
1081 begin
1086 //writeln(' sa=[', sa, ']');
1090 // remove unknown master servers
1093 begin
1096 begin
1105 //**************************************************************************
1106 //
1107 // main pulse
1108 //
1109 //**************************************************************************
1111 //==========================================================================
1112 //
1113 // isMasterReportsEnabled
1114 //
1115 //==========================================================================
1117 begin
1122 //==========================================================================
1123 //
1124 // g_Net_Slist_Pulse
1125 //
1126 // non-zero timeout ignores current status (used to fetch server list)
1127 //
1128 //==========================================================================
1130 var
1137 begin
1141 begin
1143 begin
1146 exit;
1151 begin
1154 begin
1155 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_create)', TMsgType.Notify);
1158 Exit;
1164 // reconnect/disconnect/pulse for each master
1166 begin
1169 begin
1170 // not connected; try to reconnect if we're asking for a host list, or we are in netgame, and we are the host
1172 begin
1173 if (mlist[f].lastDisconnectTime = 0) or (ct < mlist[f].lastDisconnectTime) or (ct-mlist[f].lastDisconnectTime >= 1000*NMASTER_TIMEOUT_RECONNECT) then
1174 begin
1177 end
1178 else
1179 begin
1180 //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);
1183 end
1184 else
1185 begin
1186 // if we're not in slist query, and not in netgame (or not a host), disconnect
1188 begin
1190 begin
1201 // fuck! https://www.mail-archive.com/enet-discuss@cubik.org/msg00852.html
1202 // tl;dr: on shitdows, we can get -1 sometimes, and it is *NOT* a failure.
1203 // thank you, enet. let's ignore failures altogether then.
1207 begin
1208 {
1209 if (sres < 0) then
1210 begin
1211 e_LogWriteln(_lc[I_NET_MSG_ERROR] + _lc[I_NET_ERR_CLIENT] + ' (host_service)', TMsgType.Notify);
1212 for f := 0 to High(mlist) do mlist[f].clear();
1213 SetLength(mlist, 0);
1214 enet_host_destroy(NetMHost);
1215 NetMHost := nil;
1216 exit;
1217 end;
1218 }
1222 begin
1225 end
1226 else
1227 begin
1229 begin
1231 end
1233 begin
1235 end
1237 begin
1250 //**************************************************************************
1251 //
1252 // gui and server list
1253 //
1254 //**************************************************************************
1256 //==========================================================================
1257 //
1258 // PingServer
1259 //
1260 //==========================================================================
1262 var
1266 begin
1280 //==========================================================================
1281 //
1282 // PingBcast
1283 //
1284 //==========================================================================
1286 var
1288 begin
1298 //==========================================================================
1299 //
1300 // g_Net_Slist_Fetch
1301 //
1302 //==========================================================================
1304 var
1317 begin
1321 begin
1339 begin
1354 begin
1375 var
1381 begin
1386 begin
1388 exit;
1396 begin
1404 // TODO: what should we identify the build with?
1408 try
1412 // wait until all servers connected and answered
1415 begin
1419 begin
1420 {
1421 e_LogWritefln(' master #%d: [%s] valid=%d; alive=%d; connected=%d; connecting=%d',
1422 [f, mlist[f].hostName, Integer(mlist[f].isValid()), Integer(mlist[f].isAlive()),
1423 Integer(mlist[f].isConnected()), Integer(mlist[f].isConnecting())], TMsgType.Notify);
1424 }
1427 begin
1429 begin
1432 begin
1433 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_WCONN], [mlist[f].hostName]));
1437 end
1439 begin
1442 end
1444 begin
1445 //g_Console_Add(Format(_lc[I_NET_MSG]+_lc[I_NET_SLIST_CONN], [mlist[f].hostName]));
1447 begin
1450 begin
1452 begin
1458 end
1460 begin
1462 end
1464 begin
1468 end
1470 begin
1475 // check for timeout
1482 begin
1485 exit;
1490 {
1491 slUrgent := '';
1492 slReadUrgent := true;
1493 }
1497 begin
1500 begin
1503 begin
1505 begin
1507 break;
1511 begin
1519 begin
1521 begin
1527 begin
1535 begin
1537 exit;
1556 begin
1569 begin
1591 begin
1596 break;
1600 begin
1610 finally
1616 //==========================================================================
1617 //
1618 // GetServerFromTable
1619 //
1620 //==========================================================================
1621 function GetServerFromTable (Index: Integer; SL: TNetServerList; ST: TNetServerTable): TNetServer;
1622 begin
1638 Exit;
1640 Exit;
1645 //==========================================================================
1646 //
1647 // g_Serverlist_GenerateTable
1648 //
1649 //==========================================================================
1651 var
1655 var
1657 begin
1660 Exit;
1662 begin
1664 continue;
1666 begin
1668 Exit;
1673 var
1675 begin
1683 var
1686 begin
1690 begin
1697 var
1700 begin
1704 begin
1710 begin
1713 Exit;
1716 begin
1719 begin
1725 end
1726 else
1727 begin
1740 //==========================================================================
1741 //
1742 // g_Serverlist_Control
1743 //
1744 //==========================================================================
1746 var
1749 begin
1753 Exit;
1755 {$IFDEF ENABLE_SYSTEM}
1757 {$ELSE}
1759 {$ENDIF}
1764 begin
1768 {$IFDEF ENABLE_MENU}
1773 {$ENDIF}
1774 Exit;
1777 // if there's a message on the screen,
1779 begin
1780 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1781 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1783 Exit;
1787 e_KeyPressed(JOY0_ACTIVATE) or e_KeyPressed(JOY1_ACTIVATE) or e_KeyPressed(JOY2_ACTIVATE) or e_KeyPressed(JOY3_ACTIVATE) then
1788 begin
1790 begin
1793 {$IFDEF ENABLE_RENDER}
1794 r_Render_Draw;
1795 {$ENDIF}
1798 begin
1801 end
1802 else
1809 end
1810 else
1815 if e_KeyPressed(IK_RETURN) or e_KeyPressed(IK_KPRETURN) or e_KeyPressed(VK_FIRE) or e_KeyPressed(VK_OPEN) or
1816 e_KeyPressed(JOY0_ATTACK) or e_KeyPressed(JOY1_ATTACK) or e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK) then
1817 begin
1819 begin
1822 begin
1823 {$IFDEF ENABLE_MENU}
1826 {$ENDIF}
1828 {$IFDEF ENABLE_MENU}
1830 {$ENDIF}
1834 Exit;
1835 end
1836 else
1841 Exit;
1843 end
1844 else
1848 e_KeyPressed(JOY0_DOWN) or e_KeyPressed(JOY1_DOWN) or e_KeyPressed(JOY2_DOWN) or e_KeyPressed(JOY3_DOWN) then
1849 begin
1851 begin
1859 e_KeyPressed(JOY0_UP) or e_KeyPressed(JOY1_UP) or e_KeyPressed(JOY2_UP) or e_KeyPressed(JOY3_UP) then
1860 begin
1862 begin
1871 e_KeyPressed(JOY0_RIGHT) or e_KeyPressed(JOY1_RIGHT) or e_KeyPressed(JOY2_RIGHT) or e_KeyPressed(JOY3_RIGHT) then
1872 begin
1874 begin
1882 e_KeyPressed(JOY0_LEFT) or e_KeyPressed(JOY1_LEFT) or e_KeyPressed(JOY2_LEFT) or e_KeyPressed(JOY3_LEFT) then
1883 begin
1885 begin
1886 if ST[slSelection].Current = 0 then ST[slSelection].Current := Length(ST[slSelection].Indices);
1905 (not e_KeyPressed(JOY0_UP)) and (not e_KeyPressed(JOY1_UP)) and (not e_KeyPressed(JOY2_UP)) and (not e_KeyPressed(JOY3_UP)) and
1906 (not e_KeyPressed(JOY0_DOWN)) and (not e_KeyPressed(JOY1_DOWN)) and (not e_KeyPressed(JOY2_DOWN)) and (not e_KeyPressed(JOY3_DOWN)) and
1907 (not e_KeyPressed(JOY0_LEFT)) and (not e_KeyPressed(JOY1_LEFT)) and (not e_KeyPressed(JOY2_LEFT)) and (not e_KeyPressed(JOY3_LEFT)) and
1908 (not e_KeyPressed(JOY0_RIGHT)) and (not e_KeyPressed(JOY1_RIGHT)) and (not e_KeyPressed(JOY2_RIGHT)) and (not e_KeyPressed(JOY3_RIGHT))
1909 then