1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +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
gs = new CGameState();
logNetwork->infoStream() <<"\tCreating gamestate: "<<tmh.getDiff();
logNetwork->info("\tCreating gamestate: %i",tmh.getDiff());
gs->scenarioOps = si;
gs->init(si);
gs->init(si, settings["general"]["saveRandomMaps"].Bool());
logNetwork->infoStream() <<"Initializing GameState (together): "<<tmh.getDiff();
// Now after possible random map gen, we know exact player count.

View File

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

View File

@ -24,8 +24,10 @@
#include "rmg/CMapGenerator.h"
#include "CStopWatch.h"
#include "mapping/CMapEditManager.h"
#include "mapping/CMapService.h"
#include "serializer/CTypeList.h"
#include "serializer/CMemorySerializer.h"
#include "VCMIDirs.h"
#ifdef min
#undef min
@ -698,7 +700,7 @@ CGameState::~CGameState()
ptr.second.dellNull();
}
void CGameState::init(StartInfo * si)
void CGameState::init(StartInfo * si, bool allowSavingRandomMap)
{
logGlobal->infoStream() << "\tUsing random seed: "<< si->seedToBeUsed;
getRandomGenerator().setSeed(si->seedToBeUsed);
@ -709,7 +711,7 @@ void CGameState::init(StartInfo * si)
switch(scenarioOps->mode)
{
case StartInfo::NEW_GAME:
initNewGame();
initNewGame(allowSavingRandomMap);
break;
case StartInfo::CAMPAIGN:
initCampaign();
@ -771,7 +773,7 @@ void CGameState::init(StartInfo * si)
}
}
void CGameState::initNewGame()
void CGameState::initNewGame(bool allowSavingRandomMap)
{
if(scenarioOps->createRandomMap())
{
@ -780,8 +782,37 @@ void CGameState::initNewGame()
// Gen map
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
for(int i = 0; i < map->players.size(); ++i)
{

View File

@ -201,7 +201,7 @@ public:
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)
PlayerColor currentPlayer; //ID of player currently having turn
@ -283,7 +283,7 @@ private:
// ----- initialization -----
void initNewGame();
void initNewGame(bool allowSavingRandomMap);
void initCampaign();
void initDuel();
void checkMapChecksum();

View File

@ -5,6 +5,7 @@
#include "../filesystem/CBinaryReader.h"
#include "../filesystem/CCompressedStream.h"
#include "../filesystem/CMemoryStream.h"
#include "../filesystem/CMemoryBuffer.h"
#include "CMap.h"
@ -52,6 +53,23 @@ std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int s
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)
{
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 void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath);
private:
/**
* 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()
{
logGlobal->trace("Saving header");
JsonNode header;
JsonSerializer handler(mapObjectResolver.get(), header);
@ -1283,6 +1285,7 @@ JsonNode CMapSaverJson::writeTerrainLevel(const int index)
void CMapSaverJson::writeTerrain()
{
logGlobal->trace("Saving terrain");
//todo: multilevel map save support
JsonNode surface = writeTerrainLevel(0);
@ -1297,12 +1300,14 @@ void CMapSaverJson::writeTerrain()
void CMapSaverJson::writeObjects()
{
logGlobal->trace("Saving objects");
JsonNode data(JsonNode::DATA_STRUCT);
JsonSerializer handler(mapObjectResolver.get(), data);
for(CGObjectInstance * obj : map->objects)
{
logGlobal->trace("\t%s", obj->instanceName);
auto temp = handler.enterStruct(obj->instanceName);
obj->serializeJson(handler);