1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Added option for saving generated maps on client side (#307)

* new configuration option 'general.saveRandomMaps'
* maps being saved to 'userCachePath/RandomMaps'
* no deletion of old random maps
* map filename generated based on template name and random seed
This commit is contained in:
Alexander Shishkin 2017-06-04 20:33:28 +03:00 committed by GitHub
parent d84f61fc96
commit 7e1b0d71c5
7 changed files with 70 additions and 12 deletions

View File

@ -408,10 +408,9 @@ void CClient::newGame( CConnection *con, StartInfo *si )
// Initialize game state // Initialize game state
gs = new CGameState(); gs = new CGameState();
logNetwork->infoStream() <<"\tCreating gamestate: "<<tmh.getDiff(); logNetwork->info("\tCreating gamestate: %i",tmh.getDiff());
gs->scenarioOps = si; gs->init(si, settings["general"]["saveRandomMaps"].Bool());
gs->init(si);
logNetwork->infoStream() <<"Initializing GameState (together): "<<tmh.getDiff(); logNetwork->infoStream() <<"Initializing GameState (together): "<<tmh.getDiff();
// Now after possible random map gen, we know exact player count. // Now after possible random map gen, we know exact player count.

View File

@ -17,7 +17,7 @@
"type" : "object", "type" : "object",
"default": {}, "default": {},
"additionalProperties" : false, "additionalProperties" : false,
"required" : [ "playerName", "showfps", "music", "sound", "encoding", "swipe" ], "required" : [ "playerName", "showfps", "music", "sound", "encoding", "swipe", "saveRandomMaps" ],
"properties" : { "properties" : {
"playerName" : { "playerName" : {
"type":"string", "type":"string",
@ -43,6 +43,10 @@
"type" : "boolean", "type" : "boolean",
"default" : false "default" : false
}, },
"saveRandomMaps" : {
"type" : "boolean",
"default" : false
}
} }
}, },
"video" : { "video" : {

View File

@ -24,8 +24,10 @@
#include "rmg/CMapGenerator.h" #include "rmg/CMapGenerator.h"
#include "CStopWatch.h" #include "CStopWatch.h"
#include "mapping/CMapEditManager.h" #include "mapping/CMapEditManager.h"
#include "mapping/CMapService.h"
#include "serializer/CTypeList.h" #include "serializer/CTypeList.h"
#include "serializer/CMemorySerializer.h" #include "serializer/CMemorySerializer.h"
#include "VCMIDirs.h"
#ifdef min #ifdef min
#undef min #undef min
@ -698,7 +700,7 @@ CGameState::~CGameState()
ptr.second.dellNull(); ptr.second.dellNull();
} }
void CGameState::init(StartInfo * si) void CGameState::init(StartInfo * si, bool allowSavingRandomMap)
{ {
logGlobal->infoStream() << "\tUsing random seed: "<< si->seedToBeUsed; logGlobal->infoStream() << "\tUsing random seed: "<< si->seedToBeUsed;
getRandomGenerator().setSeed(si->seedToBeUsed); getRandomGenerator().setSeed(si->seedToBeUsed);
@ -709,7 +711,7 @@ void CGameState::init(StartInfo * si)
switch(scenarioOps->mode) switch(scenarioOps->mode)
{ {
case StartInfo::NEW_GAME: case StartInfo::NEW_GAME:
initNewGame(); initNewGame(allowSavingRandomMap);
break; break;
case StartInfo::CAMPAIGN: case StartInfo::CAMPAIGN:
initCampaign(); initCampaign();
@ -771,7 +773,7 @@ void CGameState::init(StartInfo * si)
} }
} }
void CGameState::initNewGame() void CGameState::initNewGame(bool allowSavingRandomMap)
{ {
if(scenarioOps->createRandomMap()) if(scenarioOps->createRandomMap())
{ {
@ -780,8 +782,37 @@ void CGameState::initNewGame()
// Gen map // Gen map
CMapGenerator mapGenerator; CMapGenerator mapGenerator;
map = mapGenerator.generate(scenarioOps->mapGenOptions.get(), scenarioOps->seedToBeUsed).release();
std::unique_ptr<CMap> randomMap = mapGenerator.generate(scenarioOps->mapGenOptions.get(), scenarioOps->seedToBeUsed);
if(allowSavingRandomMap)
{
try
{
auto path = VCMIDirs::get().userCachePath() / "RandomMaps";
boost::filesystem::create_directories(path);
std::shared_ptr<CMapGenOptions> options = scenarioOps->mapGenOptions;
const std::string templateName = options->getMapTemplate()->getName();
const ui32 seed = scenarioOps->seedToBeUsed;
const std::string fileName = boost::str(boost::format("%s_%d.vmap") % templateName % seed );
const auto fullPath = path / fileName;
CMapService::saveMap(randomMap, fullPath);
logGlobal->info("Random map has been saved to:");
logGlobal->info(fullPath.string());
}
catch(...)
{
logGlobal->error("Saving random map failed with exception");
handleException();
}
}
map = randomMap.release();
// Update starting options // Update starting options
for(int i = 0; i < map->players.size(); ++i) for(int i = 0; i < map->players.size(); ++i)
{ {

View File

@ -201,7 +201,7 @@ public:
CGameState(); CGameState();
virtual ~CGameState(); virtual ~CGameState();
void init(StartInfo * si); void init(StartInfo * si, bool allowSavingRandomMap = false);
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized) ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
PlayerColor currentPlayer; //ID of player currently having turn PlayerColor currentPlayer; //ID of player currently having turn
@ -283,7 +283,7 @@ private:
// ----- initialization ----- // ----- initialization -----
void initNewGame(); void initNewGame(bool allowSavingRandomMap);
void initCampaign(); void initCampaign();
void initDuel(); void initDuel();
void checkMapChecksum(); void checkMapChecksum();

View File

@ -5,6 +5,7 @@
#include "../filesystem/CBinaryReader.h" #include "../filesystem/CBinaryReader.h"
#include "../filesystem/CCompressedStream.h" #include "../filesystem/CCompressedStream.h"
#include "../filesystem/CMemoryStream.h" #include "../filesystem/CMemoryStream.h"
#include "../filesystem/CMemoryBuffer.h"
#include "CMap.h" #include "CMap.h"
@ -52,6 +53,23 @@ std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int s
return header; return header;
} }
void CMapService::saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath)
{
CMemoryBuffer serializeBuffer;
{
CMapSaverJson saver(&serializeBuffer);
saver.saveMap(map);
}
{
boost::filesystem::remove(fullPath);
boost::filesystem::ofstream tmp(fullPath, boost::filesystem::ofstream::binary);
tmp.write((const char *)serializeBuffer.getBuffer().data(),serializeBuffer.getSize());
tmp.flush();
tmp.close();
}
}
std::unique_ptr<CInputStream> CMapService::getStreamFromFS(const std::string & name) std::unique_ptr<CInputStream> CMapService::getStreamFromFS(const std::string & name)
{ {
return CResourceHandler::get()->load(ResourceID(name, EResType::MAP)); return CResourceHandler::get()->load(ResourceID(name, EResType::MAP));

View File

@ -69,6 +69,7 @@ public:
*/ */
static std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name); static std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name);
static void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath);
private: private:
/** /**
* Gets a map input stream object specified by a map name. * Gets a map input stream object specified by a map name.

View File

@ -1212,6 +1212,8 @@ void CMapSaverJson::saveMap(const std::unique_ptr<CMap>& map)
void CMapSaverJson::writeHeader() void CMapSaverJson::writeHeader()
{ {
logGlobal->trace("Saving header");
JsonNode header; JsonNode header;
JsonSerializer handler(mapObjectResolver.get(), header); JsonSerializer handler(mapObjectResolver.get(), header);
@ -1283,6 +1285,7 @@ JsonNode CMapSaverJson::writeTerrainLevel(const int index)
void CMapSaverJson::writeTerrain() void CMapSaverJson::writeTerrain()
{ {
logGlobal->trace("Saving terrain");
//todo: multilevel map save support //todo: multilevel map save support
JsonNode surface = writeTerrainLevel(0); JsonNode surface = writeTerrainLevel(0);
@ -1297,12 +1300,14 @@ void CMapSaverJson::writeTerrain()
void CMapSaverJson::writeObjects() void CMapSaverJson::writeObjects()
{ {
logGlobal->trace("Saving objects");
JsonNode data(JsonNode::DATA_STRUCT); JsonNode data(JsonNode::DATA_STRUCT);
JsonSerializer handler(mapObjectResolver.get(), data); JsonSerializer handler(mapObjectResolver.get(), data);
for(CGObjectInstance * obj : map->objects) for(CGObjectInstance * obj : map->objects)
{ {
logGlobal->trace("\t%s", obj->instanceName);
auto temp = handler.enterStruct(obj->instanceName); auto temp = handler.enterStruct(obj->instanceName);
obj->serializeJson(handler); obj->serializeJson(handler);