1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_MAPGENERATOR
#define INCLUDED_MAPGENERATOR
#include "ps/FileIo.h"
#include "ps/ThreadUtil.h"
#include "ps/TemplateLoader.h"
#include "scriptinterface/ScriptInterface.h"
#include <boost/random/linear_congruential.hpp>
#include <set>
#include <string>
class CMapGeneratorWorker;
/**
* Random map generator interface. Initialized by CMapReader and then checked
* periodically during loading, until it's finished (progress value is 0).
*
* The actual work is performed by CMapGeneratorWorker in a separate thread.
*/
class CMapGenerator
{
NONCOPYABLE(CMapGenerator);
public:
CMapGenerator();
~CMapGenerator();
/**
* Start the map generator thread
*
* @param scriptFile The VFS path for the script, e.g. "maps/random/latium.js"
* @param settings JSON string containing settings for the map generator
*/
void GenerateMap(const VfsPath& scriptFile, const std::string& settings);
/**
* Get status of the map generator thread
*
* @return Progress percentage 1-100 if active, 0 when finished, or -1 on error
*/
int GetProgress();
/**
* Get random map data, according to this format:
* http://trac.wildfiregames.com/wiki/Random_Map_Generator_Internals#Dataformat
*
* @return StructuredClone containing map data
*/
shared_ptr<ScriptInterface::StructuredClone> GetResults();
private:
CMapGeneratorWorker* m_Worker;
};
/**
* Random map generator worker thread.
* (This is run in a thread so that the GUI remains responsive while loading)
*
* Thread-safety:
* - Initialize and constructor/destructor must be called from the main thread.
* - ScriptInterface created and destroyed by thread
* - StructuredClone used to return JS map data - JS:Values can't be used across threads/runtimes.
*/
class CMapGeneratorWorker
{
public:
CMapGeneratorWorker();
~CMapGeneratorWorker();
/**
* Start the map generator thread
*
* @param scriptFile The VFS path for the script, e.g. "maps/random/latium.js"
* @param settings JSON string containing settings for the map generator
*/
void Initialize(const VfsPath& scriptFile, const std::string& settings);
/**
* Get status of the map generator thread
*
* @return Progress percentage 1-100 if active, 0 when finished, or -1 on error
*/
int GetProgress();
/**
* Get random map data, according to this format:
* http://trac.wildfiregames.com/wiki/Random_Map_Generator_Internals#Dataformat
*
* @return StructuredClone containing map data
*/
shared_ptr<ScriptInterface::StructuredClone> GetResults();
private:
// Mapgen
/**
* Load all scripts of the given library
*
* @param libraryName String specifying name of the library (subfolder of ../maps/random/)
* @return true if all scripts ran successfully, false if there's an error
*/
bool LoadScripts(const std::wstring& libraryName);
// callbacks for script functions
static bool LoadLibrary(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& name);
static void ExportMap(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue data);
static JS::Value LoadHeightmap(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& src);
static JS::Value LoadMapTerrain(ScriptInterface::CxPrivate* pCxPrivate, const std::string& filename);
static void SetProgress(ScriptInterface::CxPrivate* pCxPrivate, int progress);
static CParamNode GetTemplate(ScriptInterface::CxPrivate* pCxPrivate, const std::string& templateName);
static bool TemplateExists(ScriptInterface::CxPrivate* pCxPrivate, const std::string& templateName);
static std::vector<std::string> FindTemplates(ScriptInterface::CxPrivate* pCxPrivate, const std::string& path, bool includeSubdirectories);
static std::vector<std::string> FindActorTemplates(ScriptInterface::CxPrivate* pCxPrivate, const std::string& path, bool includeSubdirectories);
static int GetTerrainTileSize(ScriptInterface::CxPrivate* pCxPrivate);
std::set<std::wstring> m_LoadedLibraries;
shared_ptr<ScriptInterface::StructuredClone> m_MapData;
boost::rand48 m_MapGenRNG;
int m_Progress;
ScriptInterface* m_ScriptInterface;
VfsPath m_ScriptPath;
std::string m_Settings;
CTemplateLoader m_TemplateLoader;
// Thread
static void* RunThread(void* data);
bool Run();
pthread_t m_WorkerThread;
CMutex m_WorkerMutex;
};
#endif //INCLUDED_MAPGENERATOR
|