Changeset View
Changeset View
Standalone View
Standalone View
source/graphics/MapGenerator.cpp
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | MapGeneratorInterruptCallback(JSContext* UNUSED(cx)) | ||||
{ | { | ||||
LOGWARNING("Quit requested!"); | LOGWARNING("Quit requested!"); | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
CMapGeneratorWorker::CMapGeneratorWorker() | CMapGeneratorWorker::CMapGeneratorWorker(const bool testing, ScriptInterface* scriptInterface) : | ||||
m_Testing(testing), m_ScriptInterface(scriptInterface) | |||||
{ | { | ||||
// If something happens before we initialize, that's a failure | // If something happens before we initialize, that's a failure | ||||
m_Progress = -1; | m_Progress = -1; | ||||
} | } | ||||
CMapGeneratorWorker::~CMapGeneratorWorker() | CMapGeneratorWorker::~CMapGeneratorWorker() | ||||
{ | { | ||||
// Wait for thread to end | // Wait for thread to end | ||||
if (!m_Testing) | |||||
pthread_join(m_WorkerThread, NULL); | pthread_join(m_WorkerThread, NULL); | ||||
wraitii: Use std::thread and m_WorkerThread.joinable() instead, see https://code.wildfiregames. | |||||
} | } | ||||
void CMapGeneratorWorker::Initialize(const VfsPath& scriptFile, const std::string& settings) | void CMapGeneratorWorker::Initialize(const VfsPath& scriptFile, const std::string& settings) | ||||
{ | { | ||||
std::lock_guard<std::mutex> lock(m_WorkerMutex); | std::lock_guard<std::mutex> lock(m_WorkerMutex); | ||||
// Set progress to positive value | // Set progress to positive value | ||||
m_Progress = 1; | m_Progress = 1; | ||||
m_ScriptPath = scriptFile; | m_ScriptPath = scriptFile; | ||||
m_Settings = settings; | m_Settings = settings; | ||||
// For tests, the Run function is called in the same thread | |||||
if (m_Testing) | |||||
return; | |||||
// Launch the worker thread | // Launch the worker thread | ||||
int ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this); | int ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this); | ||||
ENSURE(ret == 0); | ENSURE(ret == 0); | ||||
} | } | ||||
wraitiiUnsubmitted Not Done Inline ActionsWhy call this at all during testing? wraitii: Why call this at all during testing? | |||||
void* CMapGeneratorWorker::RunThread(void *data) | void* CMapGeneratorWorker::RunThread(void *data) | ||||
{ | { | ||||
debug_SetThreadName("MapGenerator"); | debug_SetThreadName("MapGenerator"); | ||||
g_Profiler2.RegisterCurrentThread("MapGenerator"); | g_Profiler2.RegisterCurrentThread("MapGenerator"); | ||||
CMapGeneratorWorker* self = static_cast<CMapGeneratorWorker*>(data); | CMapGeneratorWorker* self = static_cast<CMapGeneratorWorker*>(data); | ||||
Show All 18 Lines | void* CMapGeneratorWorker::RunThread(void *data) | ||||
// and can die. The data will be stored in m_MapData already if successful, or m_Progress | // and can die. The data will be stored in m_MapData already if successful, or m_Progress | ||||
// will contain an error value on failure. | // will contain an error value on failure. | ||||
return NULL; | return NULL; | ||||
} | } | ||||
bool CMapGeneratorWorker::Run() | bool CMapGeneratorWorker::Run() | ||||
{ | { | ||||
JSContext* cx = m_ScriptInterface->GetContext(); | |||||
JSAutoRequest rq(cx); | |||||
m_ScriptInterface->SetCallbackData(static_cast<void*> (this)); | m_ScriptInterface->SetCallbackData(static_cast<void*> (this)); | ||||
RegisterScriptFunctions_Common(); | |||||
// Replace RNG with a seeded deterministic function | // Replace RNG with a seeded deterministic function | ||||
m_ScriptInterface->ReplaceNondeterministicRNG(m_MapGenRNG); | m_ScriptInterface->ReplaceNondeterministicRNG(m_MapGenRNG); | ||||
RegisterScriptFunctions(); | if (m_Testing) | ||||
{ | |||||
m_MapGenRNG.seed(0); | |||||
return m_ScriptInterface->LoadGlobalScriptFile(m_ScriptPath); | |||||
} | |||||
else | |||||
{ | |||||
RegisterScriptFunctions_MapGenerator(); | |||||
return RunMapGenerator(); | |||||
} | |||||
} | |||||
wraitiiUnsubmitted Not Done Inline ActionsI would rather you directly called RegisterScriptFunctions_Common() in test_mapgen_scripts, set m_MapGenRNG to 0, and called m_ScriptInterface->LoadGlobalScriptFile(path);, and just let this be the old Run() function for the actual game code. Then you no longer need m_Testing or calling Initialize() wraitii: I would rather you directly called RegisterScriptFunctions_Common() in `test_mapgen_scripts`… | |||||
bool CMapGeneratorWorker::RunMapGenerator() | |||||
{ | |||||
JSContext* cx = m_ScriptInterface->GetContext(); | |||||
JSAutoRequest rq(cx); | |||||
// Parse settings | // Parse settings | ||||
JS::RootedValue settingsVal(cx); | JS::RootedValue settingsVal(cx); | ||||
if (!m_ScriptInterface->ParseJSON(m_Settings, &settingsVal) && settingsVal.isUndefined()) | if (!m_ScriptInterface->ParseJSON(m_Settings, &settingsVal) && settingsVal.isUndefined()) | ||||
{ | { | ||||
LOGERROR("CMapGeneratorWorker::Run: Failed to parse settings"); | LOGERROR("CMapGeneratorWorker::Run: Failed to parse settings"); | ||||
return false; | return false; | ||||
} | } | ||||
Show All 27 Lines | bool CMapGeneratorWorker::RunMapGenerator() | ||||
{ | { | ||||
LOGERROR("CMapGeneratorWorker::Run: Failed to load RMS '%s'", m_ScriptPath.string8()); | LOGERROR("CMapGeneratorWorker::Run: Failed to load RMS '%s'", m_ScriptPath.string8()); | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void CMapGeneratorWorker::RegisterScriptFunctions() | void CMapGeneratorWorker::RegisterScriptFunctions_Common() | ||||
{ | { | ||||
// VFS | // VFS | ||||
JSI_VFS::RegisterScriptFunctions_Maps(*m_ScriptInterface); | JSI_VFS::RegisterScriptFunctions_Maps(*m_ScriptInterface); | ||||
// Globalscripts may use VFS script functions | // Globalscripts may use VFS script functions | ||||
m_ScriptInterface->LoadGlobalScripts(); | m_ScriptInterface->LoadGlobalScripts(); | ||||
// File loading | // File loading | ||||
m_ScriptInterface->RegisterFunction<bool, VfsPath, CMapGeneratorWorker::LoadLibrary>("LoadLibrary"); | m_ScriptInterface->RegisterFunction<bool, VfsPath, CMapGeneratorWorker::LoadLibrary>("LoadLibrary"); | ||||
m_ScriptInterface->RegisterFunction<JS::Value, VfsPath, CMapGeneratorWorker::LoadHeightmap>("LoadHeightmapImage"); | m_ScriptInterface->RegisterFunction<JS::Value, VfsPath, CMapGeneratorWorker::LoadHeightmap>("LoadHeightmapImage"); | ||||
m_ScriptInterface->RegisterFunction<JS::Value, VfsPath, CMapGeneratorWorker::LoadMapTerrain>("LoadMapTerrain"); | m_ScriptInterface->RegisterFunction<JS::Value, VfsPath, CMapGeneratorWorker::LoadMapTerrain>("LoadMapTerrain"); | ||||
// Progression and profiling | |||||
m_ScriptInterface->RegisterFunction<void, int, CMapGeneratorWorker::SetProgress>("SetProgress"); | |||||
m_ScriptInterface->RegisterFunction<double, CMapGeneratorWorker::GetMicroseconds>("GetMicroseconds"); | |||||
m_ScriptInterface->RegisterFunction<void, JS::HandleValue, CMapGeneratorWorker::ExportMap>("ExportMap"); | |||||
// Template functions | |||||
m_ScriptInterface->RegisterFunction<CParamNode, std::string, CMapGeneratorWorker::GetTemplate>("GetTemplate"); | |||||
m_ScriptInterface->RegisterFunction<bool, std::string, CMapGeneratorWorker::TemplateExists>("TemplateExists"); | |||||
m_ScriptInterface->RegisterFunction<std::vector<std::string>, std::string, bool, CMapGeneratorWorker::FindTemplates>("FindTemplates"); | |||||
m_ScriptInterface->RegisterFunction<std::vector<std::string>, std::string, bool, CMapGeneratorWorker::FindActorTemplates>("FindActorTemplates"); | |||||
// Engine constants | // Engine constants | ||||
// Length of one tile of the terrain grid in metres. | // Length of one tile of the terrain grid in metres. | ||||
// Useful to transform footprint sizes to the tilegrid coordinate system. | // Useful to transform footprint sizes to the tilegrid coordinate system. | ||||
m_ScriptInterface->SetGlobal("TERRAIN_TILE_SIZE", static_cast<int>(TERRAIN_TILE_SIZE)); | m_ScriptInterface->SetGlobal("TERRAIN_TILE_SIZE", static_cast<int>(TERRAIN_TILE_SIZE)); | ||||
// Number of impassable tiles at the map border | // Number of impassable tiles at the map border | ||||
m_ScriptInterface->SetGlobal("MAP_BORDER_WIDTH", static_cast<int>(MAP_EDGE_TILES)); | m_ScriptInterface->SetGlobal("MAP_BORDER_WIDTH", static_cast<int>(MAP_EDGE_TILES)); | ||||
} | } | ||||
void CMapGeneratorWorker::RegisterScriptFunctions_MapGenerator() | |||||
{ | |||||
// Template functions | |||||
m_ScriptInterface->RegisterFunction<CParamNode, std::string, CMapGeneratorWorker::GetTemplate>("GetTemplate"); | |||||
m_ScriptInterface->RegisterFunction<bool, std::string, CMapGeneratorWorker::TemplateExists>("TemplateExists"); | |||||
m_ScriptInterface->RegisterFunction<std::vector<std::string>, std::string, bool, CMapGeneratorWorker::FindTemplates>("FindTemplates"); | |||||
m_ScriptInterface->RegisterFunction<std::vector<std::string>, std::string, bool, CMapGeneratorWorker::FindActorTemplates>("FindActorTemplates"); | |||||
// Progression and profiling | |||||
m_ScriptInterface->RegisterFunction<void, int, CMapGeneratorWorker::SetProgress>("SetProgress"); | |||||
m_ScriptInterface->RegisterFunction<double, CMapGeneratorWorker::GetMicroseconds>("GetMicroseconds"); | |||||
m_ScriptInterface->RegisterFunction<void, JS::HandleValue, CMapGeneratorWorker::ExportMap>("ExportMap"); | |||||
} | |||||
int CMapGeneratorWorker::GetProgress() | int CMapGeneratorWorker::GetProgress() | ||||
{ | { | ||||
std::lock_guard<std::mutex> lock(m_WorkerMutex); | std::lock_guard<std::mutex> lock(m_WorkerMutex); | ||||
return m_Progress; | return m_Progress; | ||||
} | } | ||||
double CMapGeneratorWorker::GetMicroseconds(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) | double CMapGeneratorWorker::GetMicroseconds(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | JS::Value CMapGeneratorWorker::LoadMapTerrain(ScriptInterface::CxPrivate* pCxPrivate, const VfsPath& filename) | ||||
self->m_ScriptInterface->SetProperty(returnValue, "textureIDs", textureIDs); | self->m_ScriptInterface->SetProperty(returnValue, "textureIDs", textureIDs); | ||||
return returnValue; | return returnValue; | ||||
} | } | ||||
////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////// | ||||
////////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////////// | ||||
CMapGenerator::CMapGenerator() : m_Worker(new CMapGeneratorWorker()) | CMapGenerator::CMapGenerator() : m_Worker(new CMapGeneratorWorker(false, nullptr)) | ||||
{ | { | ||||
} | } | ||||
CMapGenerator::~CMapGenerator() | CMapGenerator::~CMapGenerator() | ||||
{ | { | ||||
delete m_Worker; | delete m_Worker; | ||||
} | } | ||||
Show All 14 Lines |
Wildfire Games · Phabricator
Use std::thread and m_WorkerThread.joinable() instead, see https://code.wildfiregames.com/D1917#change-h8KW8LIyVdrv