From cdb606fae6c58d58314a15b9515290545582944b Mon Sep 17 00:00:00 2001
From: joris <joris.dauphin@gmail.com>
Date: Sun, 7 Apr 2013 16:40:32 +0200
Subject: [PATCH] Move some network globals into a singleton. Remove
 configuration from the command line of NetworkLag, NetworkUpdates.

---
 src/include/network.h       | 26 ++++++-----
 src/network/master.cpp      |  2 +-
 src/network/net_message.cpp |  4 +-
 src/network/netconnect.cpp  |  6 +--
 src/network/network.cpp     | 89 +++++++++++++++++++++++--------------
 src/stratagus/stratagus.cpp | 19 ++------
 6 files changed, 81 insertions(+), 65 deletions(-)

diff --git a/src/include/network.h b/src/include/network.h
index 58437231d..ca13c3d3c 100644
--- a/src/include/network.h
+++ b/src/include/network.h
@@ -37,12 +37,6 @@
 
 #include "network/udpsocket.h"
 
-/*----------------------------------------------------------------------------
---  Defines
-----------------------------------------------------------------------------*/
-
-#define NetworkDefaultPort 6660  /// Default communication port
-
 /*----------------------------------------------------------------------------
 --  Declarations
 ----------------------------------------------------------------------------*/
@@ -50,16 +44,28 @@
 class CUnit;
 class CUnitType;
 
+class CNetworkParameter
+{
+public:
+	CNetworkParameter();
+	void FixValues();
+public:
+	std::string localHost;  /// Local network address to use
+	int localPort;          /// Local network port to use
+	int NetworkUpdates;  /// Network update each # game cycles
+	int NetworkLag;      /// Network lag (# game cycles) (multiple of NetworkUpdates)
+public:
+	static const int defaultPort = 6660; /// Default communication port
+public:
+	static CNetworkParameter Instance;
+};
+
 /*----------------------------------------------------------------------------
 --  Variables
 ----------------------------------------------------------------------------*/
 
-extern char *NetworkAddr;         /// Local network address to use
-extern int NetworkPort;           /// Local network port to use
 extern CUDPSocket NetworkFildes;  /// Network file descriptor
 extern int NetworkInSync;         /// Network is in sync
-extern int NetworkUpdates;        /// Network update each # game cycles
-extern int NetworkLag;            /// Network lag (# game cycles)
 
 /*----------------------------------------------------------------------------
 --  Functions
diff --git a/src/network/master.cpp b/src/network/master.cpp
index e02177359..a6618a7fd 100644
--- a/src/network/master.cpp
+++ b/src/network/master.cpp
@@ -89,7 +89,7 @@ int MetaInit()
 	const int port_range_max = 1244;
 
 	for (int i = port_range_min; i < port_range_max; ++i) {
-		MetaServerFildes = NetOpenTCP(NetworkAddr, i);  //FIXME: need to make a dynamic port allocation there...if (!MetaServerFildes) {...}
+		MetaServerFildes = NetOpenTCP(CNetworkParameter::Instance.localHost.c_str(), i);
 		if (MetaServerFildes != static_cast<Socket>(-1)) {
 			if (NetConnectTCP(MetaServerFildes, NetResolveHost(MasterHost), MasterPort) != -1) {
 				break;
diff --git a/src/network/net_message.cpp b/src/network/net_message.cpp
index a5e448e07..3ab37b219 100644
--- a/src/network/net_message.cpp
+++ b/src/network/net_message.cpp
@@ -395,8 +395,8 @@ void CInitMessage_ProtocolMismatch::Deserialize(const unsigned char *p)
 CInitMessage_Welcome::CInitMessage_Welcome() :
 	header(MessageInit_FromServer, ICMWelcome)
 {
-	this->Lag = NetworkLag;
-	this->Updates = NetworkUpdates;
+	this->Lag = CNetworkParameter::Instance.NetworkLag;
+	this->Updates = CNetworkParameter::Instance.NetworkUpdates;
 }
 
 const unsigned char *CInitMessage_Welcome::Serialize() const
diff --git a/src/network/netconnect.cpp b/src/network/netconnect.cpp
index 53a4189f4..5c61a9121 100644
--- a/src/network/netconnect.cpp
+++ b/src/network/netconnect.cpp
@@ -779,8 +779,8 @@ void CClient::Parse_Welcome(const unsigned char *buf)
 	networkState.MsgCnt = 0;
 	NetLocalHostsSlot = msg.hosts[0].PlyNr;
 	Hosts[0].SetName(msg.hosts[0].PlyName); // Name of server player
-	NetworkLag = msg.Lag;
-	NetworkUpdates = msg.Updates;
+	CNetworkParameter::Instance.NetworkLag = msg.Lag;
+	CNetworkParameter::Instance.NetworkUpdates = msg.Updates;
 
 	Hosts[0].Host = serverHost.getIp();
 	Hosts[0].Port = serverHost.getPort();
@@ -1723,7 +1723,7 @@ breakout:
 int NetworkSetupServerAddress(const std::string &serveraddr, int port)
 {
 	if (port == 0) {
-		port = NetworkDefaultPort;
+		port = CNetworkParameter::Instance.defaultPort;
 	}
 	CHost host(serveraddr.c_str(), port);
 	if (host.isValid() == false) {
diff --git a/src/network/network.cpp b/src/network/network.cpp
index 5bada2a58..b75eeb01b 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -262,7 +262,6 @@ public:
 	CNetworkCommand Data;  /// command content
 };
 
-
 /**
 **  Network Selection Info
 */
@@ -277,12 +276,28 @@ struct NetworkSelectionHeader {
 //  Variables
 //----------------------------------------------------------------------------
 
-char *NetworkAddr = NULL;                  /// Local network address to use
-int NetworkPort = NetworkDefaultPort;      /// Local network port to use
-CUDPSocket NetworkFildes;                  /// Network file descriptor
+/* static */ CNetworkParameter CNetworkParameter::Instance;
+
+CNetworkParameter::CNetworkParameter()
+{
+	localHost = "127.0.0.1";
+	localPort = defaultPort;
+	NetworkUpdates = 5;
+	NetworkLag = 10;
+}
+
+void CNetworkParameter::FixValues()
+{
+	NetworkUpdates = std::max(NetworkUpdates, 1);
+	NetworkLag = std::max(NetworkLag, 2 * NetworkUpdates);
+	// Lag must be multiple of updates
+	NetworkLag = (NetworkLag / NetworkUpdates) * NetworkUpdates;
+}
+
 int NetworkInSync = 1;                     /// Network is in sync
-int NetworkUpdates = 5;                    /// Network update each # game cycles
-int NetworkLag = 10;                       /// Network lag in # game cycles
+
+CUDPSocket NetworkFildes;                  /// Network file descriptor
+
 static unsigned long NetworkLastFrame[PlayerMax]; /// Last frame received packet
 static const int NetworkTimeout = 45;             /// Number of seconds until player times out
 
@@ -373,6 +388,8 @@ static void NetworkSendPacket(const CNetworkCommandQueue (&ncq)[MaxNetworkComman
 */
 void InitNetwork1()
 {
+	CNetworkParameter::Instance.FixValues();
+
 	CommandsIn.clear();
 	MsgCommandsIn.clear();
 	NumNCQs = 0;
@@ -385,14 +402,11 @@ void InitNetwork1()
 	for (int i = 0; i < PlayerMax; ++i) {
 		NetMsgBufLen[i] = 0;
 	}
-	NetworkUpdates = std::max(NetworkUpdates, 1);
-	// Lag must be multiple of updates
-	NetworkLag = (NetworkLag / NetworkUpdates) * NetworkUpdates;
 
 	// Our communication port
-	int port = NetworkPort;
+	int port = CNetworkParameter::Instance.localPort;
 	for (int i = 0; i < 10; ++i) {
-		NetworkFildes.Open(CHost(NetworkAddr, port + i));
+		NetworkFildes.Open(CHost(CNetworkParameter::Instance.localHost.c_str(), port + i));
 		if (NetworkFildes.IsValid()) {
 			port = port + i;
 			break;
@@ -463,15 +477,19 @@ void InitNetwork2()
 	for (int i = 0; i < HostsCount; ++i) {
 		Players[Hosts[i].PlyNr].SetName(Hosts[i].PlyName);
 	}
-	DebugPrint("Lag %d, Updates %d, Hosts %d\n" _C_ NetworkLag _C_ NetworkUpdates _C_ HostsCount);
+	DebugPrint("Updates %d, Lag %d, Hosts %d\n" _C_
+			   CNetworkParameter::Instance.NetworkUpdates _C_
+			   CNetworkParameter::Instance.NetworkLag _C_ HostsCount);
 	// Prepare first time without syncs.
 	memset(NetworkIn, 0, sizeof(NetworkIn));
-	for (int i = 0; i <= NetworkLag; i += NetworkUpdates) {
+	for (int i = 0; i <= CNetworkParameter::Instance.NetworkLag; i += CNetworkParameter::Instance.NetworkUpdates) {
 		for (int n = 0; n < HostsCount; ++n) {
-			for (int c = 0; c < MaxNetworkCommands; ++c) {
-				NetworkIn[i][Hosts[n].PlyNr][c].Time = i;
-				NetworkIn[i][Hosts[n].PlyNr][c].Type = MessageSync;
-			}
+			CNetworkCommandQueue (&ncqs)[MaxNetworkCommands] = NetworkIn[i][Hosts[n].PlyNr];
+
+			ncqs[0].Time = i;
+			ncqs[0].Type = MessageSync;
+			ncqs[1].Time = i;
+			ncqs[1].Type = MessageNone;
 		}
 	}
 	memset(NetworkSyncSeeds, 0, sizeof(NetworkSyncSeeds));
@@ -841,7 +859,8 @@ static void NetworkParseInGameEvent(unsigned char *buf, int len, const CHost &ho
 	}
 	// Waiting for this time slot
 	if (!NetworkInSync) {
-		unsigned long n = (GameCycle / NetworkUpdates) * NetworkUpdates + NetworkUpdates;
+		const int networkUpdates = CNetworkParameter::Instance.NetworkUpdates;
+		unsigned long n = ((GameCycle / networkUpdates) + 1) * networkUpdates;
 		if (IsNetworkCommandReady(n) == true) {
 			NetworkInSync = 1;
 		}
@@ -892,6 +911,8 @@ void NetworkQuit()
 	if (!ThisPlayer) {
 		return;
 	}
+	const int NetworkUpdates = CNetworkParameter::Instance.NetworkUpdates;
+	const int NetworkLag = CNetworkParameter::Instance.NetworkLag;
 	const int n = (GameCycle + NetworkUpdates) / NetworkUpdates * NetworkUpdates + NetworkLag;
 	CNetworkCommandQueue (&ncqs)[MaxNetworkCommands] = NetworkIn[n & 0xFF][ThisPlayer->Index];
 	ncqs[0].Type = MessageQuit;
@@ -1091,15 +1112,15 @@ void NetworkCommands()
 	if (!IsNetworkGame()) {
 		return;
 	}
-	if ((GameCycle % NetworkUpdates) != 0) {
+	if ((GameCycle % CNetworkParameter::Instance.NetworkUpdates) != 0) {
 		return;
 	}
 	// Send messages to all clients (other players)
-	NetworkSendCommands(GameCycle + NetworkLag);
+	NetworkSendCommands(GameCycle + CNetworkParameter::Instance.NetworkLag);
 	NetworkExecCommands(GameCycle);
-	if (IsNetworkCommandReady(GameCycle + NetworkUpdates) == false) {
+	if (IsNetworkCommandReady(GameCycle + CNetworkParameter::Instance.NetworkUpdates) == false) {
 		NetworkInSync = 0;
-		NetworkDelay = FrameCounter + NetworkUpdates;
+		NetworkDelay = FrameCounter + CNetworkParameter::Instance.NetworkUpdates;
 		// FIXME: should send a resend request.
 	}
 }
@@ -1117,12 +1138,13 @@ static void NetworkResendCommands()
 	++NetworkSendResend;
 #endif
 
+	const int NetworkUpdates = CNetworkParameter::Instance.NetworkUpdates;
+	const int gameCycle = ((GameCycle / NetworkUpdates) + 1) * NetworkUpdates;
 	// Build packet
 	CNetworkPacket packet;
 	packet.Header.Type[0] = MessageResend;
 	packet.Header.Type[1] = MessageNone;
-	packet.Header.Cycle =
-		(uint8_t)((GameCycle / NetworkUpdates) * NetworkUpdates + NetworkUpdates);
+	packet.Header.Cycle = uint8_t(gameCycle & 0xFF);
 
 	NetworkBroadcast(packet, 1);
 }
@@ -1139,18 +1161,19 @@ void NetworkRecover()
 	if (FrameCounter <= NetworkDelay) {
 		return;
 	}
-	NetworkDelay += NetworkUpdates;
+	NetworkDelay += CNetworkParameter::Instance.NetworkUpdates;
 
 	// Check for players that timed out
 	for (int i = 0; i < HostsCount; ++i) {
-		if (!NetworkLastFrame[Hosts[i].PlyNr]) {
+		const unsigned long lastFrame = NetworkLastFrame[Hosts[i].PlyNr];
+		if (!lastFrame) {
 			continue;
 		}
-		int secs = (FrameCounter - NetworkLastFrame[Hosts[i].PlyNr]) /
-				   (FRAMES_PER_SECOND * VideoSyncSpeed / 100);
+		const int secs = (FrameCounter - lastFrame) /
+						 (FRAMES_PER_SECOND * VideoSyncSpeed / 100);
 		// FIXME: display a menu while we wait
-		if (secs >= 3 && secs < NetworkTimeout) {
-			if (FrameCounter % FRAMES_PER_SECOND < (unsigned long)NetworkUpdates) {
+		if (3 <= secs && secs < NetworkTimeout) {
+			if (FrameCounter % FRAMES_PER_SECOND < (unsigned long)CNetworkParameter::Instance.NetworkUpdates) {
 				SetMessage(_("Waiting for player \"%s\": %d:%02d"), Hosts[i].PlyName,
 						   (NetworkTimeout - secs) / 60, (NetworkTimeout - secs) % 60);
 			}
@@ -1159,7 +1182,7 @@ void NetworkRecover()
 			CNetworkCommand nc;
 			CNetworkPacket np;
 
-			unsigned long n = GameCycle + NetworkUpdates;
+			const unsigned long n = GameCycle + CNetworkParameter::Instance.NetworkUpdates;
 			nc.X = Hosts[i].PlyNr;
 			NetworkIn[n & 0xFF][Hosts[i].PlyNr][0].Time = n;
 			NetworkIn[n & 0xFF][Hosts[i].PlyNr][0].Type = MessageQuit;
@@ -1174,9 +1197,9 @@ void NetworkRecover()
 
 			NetworkBroadcast(np, 1);
 
-			if (IsNetworkCommandReady(GameCycle + NetworkUpdates) == false) {
+			if (IsNetworkCommandReady(GameCycle + CNetworkParameter::Instance.NetworkUpdates) == false) {
 				NetworkInSync = 0;
-				NetworkDelay = FrameCounter + NetworkUpdates;
+				NetworkDelay = FrameCounter + CNetworkParameter::Instance.NetworkUpdates;
 				// FIXME: should send a resend request.
 			}
 		}
diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp
index 792821506..050e8976b 100644
--- a/src/stratagus/stratagus.cpp
+++ b/src/stratagus/stratagus.cpp
@@ -438,7 +438,6 @@ static void Usage()
 		"\t-h\t\tHelp shows this page\n"
 		"\t-I addr\t\tNetwork address to use\n"
 		"\t-l\t\tDisable command log\n"
-		"\t-L lag\t\tNetwork lag in # frames (default 10 = 333ms)\n"
 		"\t-N name\t\tName of the player\n"
 #if defined(USE_OPENGL) || defined(USE_GLES)
 		"\t-o\t\tDo not use OpenGL or OpenGL ES 1.1\n"
@@ -447,7 +446,6 @@ static void Usage()
 		"\t-P port\t\tNetwork port to use\n"
 		"\t-s sleep\tNumber of frames for the AI to sleep before it starts\n"
 		"\t-S speed\tSync speed (100 = 30 frames/s)\n"
-		"\t-U update\tNetwork update rate in # frames (default 5=6x per s)\n"
 		"\t-v mode\t\tVideo mode resolution in format <xres>x<yres>\n"
 		"\t-W\t\tWindowed video mode\n"
 		"map is relative to StratagusLibPath=datapath, use ./map for relative to cwd\n",
@@ -500,7 +498,7 @@ static void RedirectOutput()
 void ParseCommandLine(int argc, char **argv, Parameters &parameters)
 {
 	for (;;) {
-		switch (getopt(argc, argv, "c:d:D:eE:FhI:lL:N:oOP:s:S:U:v:W?")) {
+		switch (getopt(argc, argv, "c:d:D:eE:FhI:lN:oOP:s:S:v:W?")) {
 			case 'c':
 				parameters.luaStartFilename = optarg;
 				continue;
@@ -526,19 +524,11 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
 				Video.FullScreen = 1;
 				continue;
 			case 'I':
-				NetworkAddr = optarg;
+				CNetworkParameter::Instance.localHost = optarg;
 				continue;
 			case 'l':
 				CommandLogDisabled = true;
 				continue;
-			case 'L':
-				NetworkLag = atoi(optarg);
-				if (!NetworkLag) {
-					fprintf(stderr, "%s: zero lag not supported\n", argv[0]);
-					Usage();
-					ExitFatal(-1);
-				}
-				continue;
 			case 'N':
 				parameters.LocalPlayerName = optarg;
 				continue;
@@ -553,7 +543,7 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
 				continue;
 #endif
 			case 'P':
-				NetworkPort = atoi(optarg);
+				CNetworkParameter::Instance.localPort = atoi(optarg);
 				continue;
 			case 's':
 				AiSleepCycles = atoi(optarg);
@@ -561,9 +551,6 @@ void ParseCommandLine(int argc, char **argv, Parameters &parameters)
 			case 'S':
 				VideoSyncSpeed = atoi(optarg);
 				continue;
-			case 'U':
-				NetworkUpdates = atoi(optarg);
-				continue;
 			case 'v': {
 				char *sep = strchr(optarg, 'x');
 				if (!sep || !*(sep + 1)) {