1
1
forked from 0ad/0ad

Expose the same file listing function to JS GUI, simulation and rmgen, refs #4868.

Removes the workaround and limitations of globalscripts Resources
(52f311da2b) and loadCivFiles (89055ef858), allowing them to actually
become actually global.
Rename to ListDirectoryFiles as proposed by wraitii.

Differential Revision: https://code.wildfiregames.com/D1103
Reviewed By: s0600204
Proofread by: echotangoecho
Comments by: wraitii
Relevant discussions with leper in #4868, D1062

This was SVN commit r20586.
This commit is contained in:
elexis 2017-12-04 23:46:55 +00:00
parent 54904b1750
commit 7fda43d14e
11 changed files with 28 additions and 96 deletions

View File

@ -4,29 +4,12 @@
*/
function Resources()
{
let jsonFiles = [];
// Simulation context
if (Engine.FindJSONFiles)
{
jsonFiles = Engine.FindJSONFiles("resources", false);
for (let file in jsonFiles)
jsonFiles[file] = "simulation/data/resources/" + jsonFiles[file] + ".json";
}
// GUI context
else if (Engine.BuildDirEntList)
jsonFiles = Engine.BuildDirEntList("simulation/data/resources/", "*.json", false);
else
{
error("Resources: JSON functions are not available");
return;
}
this.resourceData = [];
this.resourceDataObj = {};
this.resourceCodes = [];
this.resourceNames = {};
for (let filename of jsonFiles)
for (let filename of Engine.ListDirectoryFiles("simulation/data/resources/", "*.json", false))
{
let data = Engine.ReadJSONFile(filename);
if (!data)

View File

@ -1,6 +1,5 @@
/**
* Loads history and gameplay data of all civs.
* Can be used from GUI and rmgen (because the simulation functions differ currently).
*
* @param selectableOnly {boolean} - Only load civs that can be selected
* in the gamesetup. Scenario maps might set non-selectable civs.
@ -13,7 +12,7 @@ function loadCivFiles(selectableOnly)
let civData = {};
for (let filename of Engine.BuildDirEntList("simulation/data/civs/", "*.json", false))
for (let filename of Engine.ListDirectoryFiles("simulation/data/civs/", "*.json", false))
{
let data = Engine.ReadJSONFile(filename);

View File

@ -10,7 +10,7 @@ var g_SoundNotifications = {
// Get list of XML files in pathname with recursion, excepting those starting with _
function getXMLFileList(pathname)
{
var files = Engine.BuildDirEntList(pathname, "*.xml", true);
var files = Engine.ListDirectoryFiles(pathname, "*.xml", true);
var result = [];
@ -33,7 +33,7 @@ function getXMLFileList(pathname)
function getJSONFileList(pathname)
{
// Remove the path and extension from each name, since we just want the filename
return Engine.BuildDirEntList(pathname, "*.json", false).map(
return Engine.ListDirectoryFiles(pathname, "*.json", false).map(
filename => filename.substring(pathname.length, filename.length - 5));
}

View File

@ -211,7 +211,7 @@ function loadMapTypes()
function loadBiomes()
{
return Engine.BuildDirEntList(g_BiomesDirectory, "*.json", false).map(file => {
return Engine.ListDirectoryFiles(g_BiomesDirectory, "*.json", false).map(file => {
let description = Engine.ReadJSONFile(file).Description;
return {
"Id": file.substr(g_BiomesDirectory.length).slice(0, -".json".length),
@ -230,7 +230,7 @@ function loadVictoryConditions()
{
let subdir = "victory_conditions/";
let files = Engine.BuildDirEntList(g_SettingsDirectory + subdir, "*.json", false).map(
let files = Engine.ListDirectoryFiles(g_SettingsDirectory + subdir, "*.json", false).map(
file => file.substr(g_SettingsDirectory.length));
let victoryConditions = files.map(file => {

View File

@ -8,7 +8,7 @@ function init(data)
Engine.SetCursor("cursor-wait");
// Get tip image and corresponding tip text
let tipTextLoadingArray = Engine.BuildDirEntList("gui/text/tips/", "*.txt", false);
let tipTextLoadingArray = Engine.ListDirectoryFiles("gui/text/tips/", "*.txt", false);
if (tipTextLoadingArray.length > 0)
{

View File

@ -291,7 +291,7 @@ function findAllAutoResearchedTechs()
{
let techList = [];
for (let filename of Engine.BuildDirEntList(g_TechnologyPath, "*.json", true))
for (let filename of Engine.ListDirectoryFiles(g_TechnologyPath, "*.json", true))
{
// -5 to strip off the file extension
let templateName = filename.slice(g_TechnologyPath.length, -5);

View File

@ -8,6 +8,9 @@ DataTemplateManager.prototype.Schema =
DataTemplateManager.prototype.Init = function()
{
this.technologiesPath = "simulation/data/technologies/";
this.aurasPath = "simulation/data/auras/";
this.allTechs = {};
this.allAuras = {};
@ -25,7 +28,7 @@ DataTemplateManager.prototype.GetTechnologyTemplate = function(template)
{
if (!this.allTechs[template])
{
this.allTechs[template] = Engine.ReadJSONFile("simulation/data/technologies/" + template + ".json");
this.allTechs[template] = Engine.ReadJSONFile(this.technologiesPath + template + ".json");
if (!this.allTechs[template])
error("Failed to load technology \"" + template + "\"");
}
@ -37,7 +40,7 @@ DataTemplateManager.prototype.GetAuraTemplate = function(template)
{
if (!this.allAuras[template])
{
this.allAuras[template] = Engine.ReadJSONFile("simulation/data/auras/" + template + ".json");
this.allAuras[template] = Engine.ReadJSONFile(this.aurasPath + template + ".json");
if (!this.allAuras[template])
error("Failed to load aura \"" + template + "\"");
}
@ -47,12 +50,12 @@ DataTemplateManager.prototype.GetAuraTemplate = function(template)
DataTemplateManager.prototype.ListAllTechs = function()
{
return Engine.FindJSONFiles("technologies", true);
return Engine.ListDirectoryFiles(this.technologiesPath, "*.json", true).map(file => file.slice(this.technologiesPath.length, -".json".length));
};
DataTemplateManager.prototype.ListAllAuras = function()
{
return Engine.FindJSONFiles("auras", true);
return Engine.ListDirectoryFiles(this.aurasPath, "*.json", true).map(file => file.slice(this.aurasPath.length, -".json".length));
};
DataTemplateManager.prototype.GetAllTechs = function()

View File

@ -76,16 +76,13 @@ static Status BuildDirEntListCB(const VfsPath& pathname, const CFileInfo& UNUSED
// Return an array of pathname strings, one for each matching entry in the
// specified directory.
//
// pathnames = buildDirEntList(start_path [, filter_string [, recursive ] ]);
// directory: VFS path
// filter_string: default "" matches everything; otherwise, see vfs_next_dirent.
// recurse: should subdirectories be included in the search? default false.
//
// note: full pathnames of each file/subdirectory are returned,
// ready for use as a "filename" for the other functions.
JS::Value JSI_VFS::BuildDirEntList(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& path, const std::wstring& filterStr, bool recurse)
JS::Value JSI_VFS::BuildDirEntList(ScriptInterface::CxPrivate* pCxPrivate, const std::vector<CStrW>& validPaths, const std::wstring& path, const std::wstring& filterStr, bool recurse)
{
if (!PathRestrictionMet(pCxPrivate, validPaths, path))
return JS::NullValue();
// convert to const wchar_t*; if there's no filter, pass 0 for speed
// (interpreted as: "accept all files without comparing").
const wchar_t* filter = 0;
@ -238,17 +235,20 @@ bool JSI_VFS::PathRestrictionMet(ScriptInterface::CxPrivate* pCxPrivate, const s
JS::Value Script_ReadJSONFile_##context(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& filePath)\
{\
return JSI_VFS::ReadJSONFile(pCxPrivate, PathRestriction_##context, filePath);\
}
}\
JS::Value Script_ListDirectoryFiles_##context(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& path, const std::wstring& filterStr, bool recurse)\
{\
return JSI_VFS::BuildDirEntList(pCxPrivate, PathRestriction_##context, path, filterStr, recurse);\
}\
VFS_ScriptFunctions(GUI);
VFS_ScriptFunctions(Simulation);
VFS_ScriptFunctions(Maps);
#undef VFS_ScriptFunctions
void JSI_VFS::RegisterScriptFunctions_GUI(const ScriptInterface& scriptInterface)
{
scriptInterface.RegisterFunction<JS::Value, std::wstring, std::wstring, bool, &JSI_VFS::BuildDirEntList>("BuildDirEntList");
scriptInterface.RegisterFunction<JS::Value, std::wstring, std::wstring, bool, &Script_ListDirectoryFiles_GUI>("ListDirectoryFiles");
scriptInterface.RegisterFunction<bool, CStrW, JSI_VFS::FileExists>("FileExists");
scriptInterface.RegisterFunction<double, std::wstring, &JSI_VFS::GetFileMTime>("GetFileMTime");
scriptInterface.RegisterFunction<unsigned int, std::wstring, &JSI_VFS::GetFileSize>("GetFileSize");
@ -260,12 +260,13 @@ void JSI_VFS::RegisterScriptFunctions_GUI(const ScriptInterface& scriptInterface
void JSI_VFS::RegisterScriptFunctions_Simulation(const ScriptInterface& scriptInterface)
{
scriptInterface.RegisterFunction<JS::Value, std::wstring, std::wstring, bool, &Script_ListDirectoryFiles_Simulation>("ListDirectoryFiles");
scriptInterface.RegisterFunction<JS::Value, std::wstring, &Script_ReadJSONFile_Simulation>("ReadJSONFile");
}
void JSI_VFS::RegisterScriptFunctions_Maps(const ScriptInterface& scriptInterface)
{
scriptInterface.RegisterFunction<JS::Value, std::wstring, std::wstring, bool, &JSI_VFS::BuildDirEntList>("BuildDirEntList");
scriptInterface.RegisterFunction<JS::Value, std::wstring, std::wstring, bool, &Script_ListDirectoryFiles_Maps>("ListDirectoryFiles");
scriptInterface.RegisterFunction<bool, CStrW, JSI_VFS::FileExists>("FileExists");
scriptInterface.RegisterFunction<JS::Value, std::wstring, &Script_ReadJSONFile_Maps>("ReadJSONFile");
}

View File

@ -30,15 +30,7 @@ namespace JSI_VFS
{
// Return an array of pathname strings, one for each matching entry in the
// specified directory.
//
// pathnames = buildDirEntList(start_path [, filter_string [, recursive ] ]);
// directory: VFS path
// filter_string: see match_wildcard; "" matches everything.
// recurse: should subdirectories be included in the search? default false.
//
// note: full pathnames of each file/subdirectory are returned,
// ready for use as a "filename" for the other functions.
JS::Value BuildDirEntList(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& path, const std::wstring& filterStr, bool recurse);
JS::Value BuildDirEntList(ScriptInterface::CxPrivate* pCxPrivate, const std::vector<CStrW>& validPaths, const std::wstring& path, const std::wstring& filterStr, bool recurse);
// Return true iff the file exists
bool FileExists(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& filename);

View File

@ -86,7 +86,6 @@ CComponentManager::CComponentManager(CSimContext& context, shared_ptr<ScriptRunt
m_ScriptInterface.RegisterFunction<void, int, CComponentManager::Script_DestroyEntity> ("DestroyEntity");
m_ScriptInterface.RegisterFunction<void, CComponentManager::Script_FlushDestroyedEntities> ("FlushDestroyedEntities");
m_ScriptInterface.RegisterFunction<bool, std::wstring, CComponentManager::Script_DataFileExists> ("DataFileExists");
m_ScriptInterface.RegisterFunction<std::vector<std::string>, std::wstring, bool, CComponentManager::Script_FindJSONFiles> ("FindJSONFiles");
}
// Define MT_*, IID_* as script globals, and store their names
@ -1191,38 +1190,3 @@ bool CComponentManager::Script_DataFileExists(ScriptInterface::CxPrivate* UNUSED
VfsPath path = VfsPath(L"simulation/data") / fileName;
return VfsFileExists(path);
}
Status CComponentManager::FindJSONFilesCallback(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
{
FindJSONFilesCallbackData* data = (FindJSONFilesCallbackData*)cbData;
VfsPath pathstem = pathname.ChangeExtension(L"");
// Strip the root from the path
std::wstring name = pathstem.string().substr(data->path.string().length());
data->templates.push_back(std::string(name.begin(), name.end()));
return INFO::OK;
}
std::vector<std::string> CComponentManager::Script_FindJSONFiles(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& subPath, bool recursive)
{
FindJSONFilesCallbackData cbData;
cbData.path = VfsPath(L"simulation/data/" + subPath + L"/");
int dir_flags = 0;
if (recursive) {
dir_flags = vfs::DIR_RECURSIVE;
}
// Find all simulation/data/{subPath}/*.json recursively
Status ret = vfs::ForEachFile(g_VFS, cbData.path, FindJSONFilesCallback, (uintptr_t)&cbData, L"*.json", dir_flags);
if (ret != INFO::OK)
{
// Some error reading directory
wchar_t error[200];
LOGERROR("Error reading directory '%s': %s", cbData.path.string8(), utf8_from_wstring(StatusDescription(ret, error, ARRAY_SIZE(error))));
}
return cbData.templates;
}

View File

@ -115,12 +115,6 @@ private:
}
};
struct FindJSONFilesCallbackData
{
VfsPath path;
std::vector<std::string> templates;
};
public:
CComponentManager(CSimContext&, shared_ptr<ScriptRuntime> rt, bool skipScriptFunctions = false);
~CComponentManager();
@ -333,10 +327,6 @@ private:
static void Script_DestroyEntity(ScriptInterface::CxPrivate* pCxPrivate, int ent);
static void Script_FlushDestroyedEntities(ScriptInterface::CxPrivate* pCxPrivate);
static bool Script_DataFileExists(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& fileName);
static std::vector<std::string> Script_FindJSONFiles(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& subPath, bool recursive);
// callback function to handle recursively finding files in a directory
static Status FindJSONFilesCallback(const VfsPath&, const CFileInfo&, const uintptr_t);
CMessage* ConstructMessage(int mtid, JS::HandleValue data);
void SendGlobalMessage(entity_id_t ent, const CMessage& msg);