Explorar o código

GameState now uses random generator from server. Blocked access to rmg
on client

Ivan Savenko hai 1 ano
pai
achega
0d66ddbeec

+ 7 - 0
client/Client.cpp

@@ -556,6 +556,13 @@ void CClient::invalidatePaths()
 	pathCache.clear();
 }
 
+vstd::RNG & CClient::getRandomGenerator()
+{
+	// Client should use CRandomGenerator::getDefault() for UI logic
+	// Gamestate should never call this method on client!
+	throw std::runtime_error("Illegal access to random number generator from client code!");
+}
+
 std::shared_ptr<const CPathsInfo> CClient::getPathsInfo(const CGHeroInstance * h)
 {
 	assert(h);

+ 2 - 0
client/Client.h

@@ -218,6 +218,8 @@ public:
 	void showInfoDialog(InfoWindow * iw) override {};
 	void removeGUI() const;
 
+	vstd::RNG & getRandomGenerator() override;
+
 #if SCRIPTING_ENABLED
 	scripting::Pool * getGlobalContextPool() const override;
 #endif

+ 3 - 0
lib/IGameCallback.h

@@ -135,6 +135,9 @@ public:
 	virtual void changeFogOfWar(std::unordered_set<int3> &tiles, PlayerColor player, ETileVisibility mode) = 0;
 	
 	virtual void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) = 0;
+
+	virtual vstd::RNG & getRandomGenerator() = 0;
+
 };
 
 class DLL_LINKAGE CNonConstInfoCallback : public CPrivilegedInfoCallback

+ 1 - 3
lib/gameState/CGameState.cpp

@@ -185,8 +185,6 @@ void CGameState::init(const IMapService * mapService, StartInfo * si, Load::Prog
 {
 	assert(services);
 	assert(callback);
-	logGlobal->info("\tUsing random seed: %d", si->seedToBeUsed);
-	rand = std::make_unique<CRandomGenerator>(si->seedToBeUsed);
 	scenarioOps = CMemorySerializer::deepCopy(*si).release();
 	initialOpts = CMemorySerializer::deepCopy(*si).release();
 	si = nullptr;
@@ -1966,7 +1964,7 @@ TeamState::TeamState()
 
 vstd::RNG & CGameState::getRandomGenerator()
 {
-	return *rand;
+	return callback->getRandomGenerator();
 }
 
 ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, int flags, std::function<bool(ArtifactID)> accepts)

+ 9 - 6
lib/gameState/CGameState.h

@@ -9,10 +9,10 @@
  */
 #pragma once
 
-#include "bonuses/CBonusSystemNode.h"
-#include "IGameCallback.h"
-#include "LoadProgress.h"
-#include "ConstTransitivePtr.h"
+#include "../bonuses/CBonusSystemNode.h"
+#include "../IGameCallback.h"
+#include "../LoadProgress.h"
+#include "../ConstTransitivePtr.h"
 
 namespace boost
 {
@@ -186,7 +186,11 @@ public:
 		h & teams;
 		h & heroesPool;
 		h & globalEffects;
-		h & rand;
+		if (h.version < Handler::Version::REMOVE_LIB_RNG)
+		{
+			std::string oldStateOfRNG;
+			h & oldStateOfRNG;
+		}
 		h & rumor;
 		h & campaign;
 		h & allocatedArtifacts;
@@ -234,7 +238,6 @@ private:
 
 	// ---- data -----
 	std::shared_ptr<CApplier<CBaseForGSApply>> applier;
-	std::unique_ptr<CRandomGenerator> rand;
 	Services * services;
 
 	/// Pointer to campaign state manager. Nullptr for single scenarios

+ 2 - 1
lib/serializer/ESerializationVersion.h

@@ -56,6 +56,7 @@ enum class ESerializationVersion : int32_t
 	REMOVE_FOG_OF_WAR_POINTER, // 846 - fog of war is serialized as reference instead of pointer
 	SIMPLE_TEXT_CONTAINER_SERIALIZATION, // 847 - text container is serialized using common routine instead of custom approach
 	MAP_FORMAT_ADDITIONAL_INFOS, // 848 - serialize new infos in map format
+	REMOVE_LIB_RNG, // 849 - removed random number generators from library classes
 
-	CURRENT = MAP_FORMAT_ADDITIONAL_INFOS
+	CURRENT = REMOVE_LIB_RNG
 };

+ 4 - 2
server/CGameHandler.cpp

@@ -549,9 +549,11 @@ void CGameHandler::reinitScripting()
 void CGameHandler::init(StartInfo *si, Load::ProgressAccumulator & progressTracking)
 {
 	if (si->seedToBeUsed == 0)
-	{
 		si->seedToBeUsed = CRandomGenerator::getDefault().nextInt();
-	}
+
+	logGlobal->info("Using random seed: %d", si->seedToBeUsed);
+	randomNumberGenerator = std::make_unique<CRandomGenerator>(si->seedToBeUsed);
+
 	CMapService mapService;
 	gs = new CGameState();
 	gs->preInit(VLC, this);

+ 1 - 1
server/CGameHandler.h

@@ -277,7 +277,7 @@ public:
 	void checkVictoryLossConditions(const std::set<PlayerColor> & playerColors);
 	void checkVictoryLossConditionsForAll();
 
-	vstd::RNG & getRandomGenerator();
+	vstd::RNG & getRandomGenerator() override;
 
 #if SCRIPTING_ENABLED
 	scripting::Pool * getGlobalContextPool() const override;

+ 5 - 0
test/mock/mock_IGameCallback.cpp

@@ -31,3 +31,8 @@ void GameCallbackMock::sendAndApply(CPackForClient * pack)
 {
 	upperCallback->apply(pack);
 }
+
+vstd::RNG & GameCallbackMock::getRandomGenerator()
+{
+	throw std::runtime_error("Not implemented!");
+}

+ 2 - 0
test/mock/mock_IGameCallback.h

@@ -93,6 +93,8 @@ public:
 	///useful callback methods
 	void sendAndApply(CPackForClient * pack) override;
 
+	vstd::RNG & getRandomGenerator() override;
+
 #if SCRIPTING_ENABLED
 	MOCK_CONST_METHOD0(getGlobalContextPool, scripting::Pool *());
 #endif