Quellcode durchsuchen

Switch turn timers handling to boost asio timer

Ivan Savenko vor 1 Jahr
Ursprung
Commit
aa7ecea683

+ 2 - 1
lib/network/NetworkListener.h

@@ -30,6 +30,7 @@ class DLL_LINKAGE INetworkServerListener : public INetworkConnectionListener
 	friend class NetworkServer;
 protected:
 	virtual void onNewConnection(const std::shared_ptr<NetworkConnection> &) = 0;
+	virtual void onTimer() = 0;
 
 	~INetworkServerListener() = default;
 };
@@ -38,9 +39,9 @@ class DLL_LINKAGE INetworkClientListener : public INetworkConnectionListener
 {
 	friend class NetworkClient;
 protected:
-	virtual void onTimer() = 0;
 	virtual void onConnectionFailed(const std::string & errorMessage) = 0;
 	virtual void onConnectionEstablished(const std::shared_ptr<NetworkConnection> &) = 0;
+	virtual void onTimer() = 0;
 
 	~INetworkClientListener() = default;
 };

+ 10 - 0
lib/network/NetworkServer.cpp

@@ -80,4 +80,14 @@ void NetworkServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &
 	listener.onPacketReceived(connection, message);
 }
 
+void NetworkServer::setTimer(std::chrono::milliseconds duration)
+{
+	auto timer = std::make_shared<NetworkTimer>(*io, duration);
+	timer->async_wait([this, timer](const boost::system::error_code& error){
+		if (!error)
+			listener.onTimer();
+	});
+}
+
+
 VCMI_LIB_NAMESPACE_END

+ 1 - 0
lib/network/NetworkServer.h

@@ -34,6 +34,7 @@ public:
 
 	void sendPacket(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message);
 	void closeConnection(const std::shared_ptr<NetworkConnection> &);
+	void setTimer(std::chrono::milliseconds duration);
 
 	void start(uint16_t port);
 	void run(std::chrono::milliseconds duration);

+ 5 - 0
lobby/LobbyServer.cpp

@@ -107,6 +107,11 @@ void LobbyServer::sendMessage(const std::shared_ptr<NetworkConnection> & target,
 	networkServer->sendPacket(target, payloadBuffer);
 }
 
+void LobbyServer::onTimer()
+{
+	// no-op
+}
+
 void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> & connection)
 {
 }

+ 1 - 0
lobby/LobbyServer.h

@@ -56,6 +56,7 @@ class LobbyServer : public INetworkServerListener
 	void onNewConnection(const std::shared_ptr<NetworkConnection> &) override;
 	void onDisconnected(const std::shared_ptr<NetworkConnection> &) override;
 	void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
+	void onTimer() override;
 
 	void sendMessage(const std::shared_ptr<NetworkConnection> & target, const JsonNode & json);
 public:

+ 20 - 18
server/CVCMIServer.cpp

@@ -236,29 +236,29 @@ void CVCMIServer::run()
 		vmHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "onServerReady");
 	}
 #endif
+	networkServer->run();
+}
 
-	static const int serverUpdateIntervalMilliseconds = 50;
-	auto clockInitial = std::chrono::steady_clock::now();
-	int64_t msPassedLast = 0;
+void CVCMIServer::onTimer()
+{
+	if (state != EServerState::GAMEPLAY)
+		return;
 
-	while(state != EServerState::SHUTDOWN)
-	{
-		networkServer->run(std::chrono::milliseconds(serverUpdateIntervalMilliseconds));
+	static const auto serverUpdateInterval = std::chrono::milliseconds(100);
 
-		const auto clockNow = std::chrono::steady_clock::now();
-		const auto clockPassed = clockNow - clockInitial;
-		const int64_t msPassedNow = std::chrono::duration_cast<std::chrono::milliseconds>(clockPassed).count();
-		const int64_t msDelta = msPassedNow - msPassedLast;
-		msPassedLast = msPassedNow;
+	auto timeNow = std::chrono::steady_clock::now();
+	auto timePassedBefore = lastTimerUpdateTime - gameplayStartTime;
+	auto timePassedNow = timeNow - gameplayStartTime;
 
-		if (state == EServerState::GAMEPLAY)
-			gh->tick(msDelta);
-	}
-}
+	lastTimerUpdateTime = timeNow;
 
-void CVCMIServer::onTimer()
-{
-	// FIXME: move GameHandler updates here
+	auto msPassedBefore = std::chrono::duration_cast<std::chrono::milliseconds>(timePassedBefore);
+	auto msPassedNow = std::chrono::duration_cast<std::chrono::milliseconds>(timePassedNow);
+	auto msDelta = msPassedNow - msPassedBefore;
+
+	if (msDelta.count())
+		gh->tick(msDelta.count());
+	networkServer->setTimer(serverUpdateInterval);
 }
 
 void CVCMIServer::establishOutgoingConnection()
@@ -372,6 +372,8 @@ void CVCMIServer::startGameImmediately()
 
 	gh->start(si->mode == StartInfo::LOAD_GAME);
 	state = EServerState::GAMEPLAY;
+	lastTimerUpdateTime = gameplayStartTime = std::chrono::steady_clock::now();
+	onTimer();
 }
 
 void CVCMIServer::onDisconnected(const std::shared_ptr<NetworkConnection> & connection)

+ 3 - 0
server/CVCMIServer.h

@@ -55,6 +55,9 @@ class CVCMIServer : public LobbyInfo, public INetworkServerListener, public INet
 	/// Outgoing connection established by this server to game lobby for proxy mode (only in lobby game)
 	std::unique_ptr<NetworkClient> outgoingConnection;
 
+	std::chrono::steady_clock::time_point gameplayStartTime;
+	std::chrono::steady_clock::time_point lastTimerUpdateTime;
+
 public:
 	/// List of all active connections
 	std::vector<std::shared_ptr<CConnection>> activeConnections;