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:
parent
d84f61fc96
commit
7e1b0d71c5
@ -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.
|
||||
|
@ -5,8 +5,8 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema",
|
||||
"required" : [ "general", "video", "adventure", "pathfinder", "battle", "server", "logging", "launcher" ],
|
||||
"definitions" : {
|
||||
"logLevelEnum" : {
|
||||
"type" : "string",
|
||||
"logLevelEnum" : {
|
||||
"type" : "string",
|
||||
"enum" : [ "trace", "debug", "info", "warn", "error" ]
|
||||
}
|
||||
},
|
||||
@ -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" : {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user