Packages system with .otpkg files
When otclient initializes it tries to find all .otpkg files inside the current search paths (./ ./modules ./addons) and then add them to the front of current search paths. This way .otpkg can contains many modules/addons and modifications in a single file that otclient can recognize. otpkg files can be compressed files supported by PhysFS, which are ZIP (.zip) and LZMA (.7z).
This commit is contained in:
parent
09425eba31
commit
bc81c9c8bf
11
init.lua
11
init.lua
|
@ -8,18 +8,21 @@ g_logger.setLogFile(g_resources.getWorkDir() .. g_app.getCompactName() .. ".log"
|
||||||
g_logger.info(g_app.getName() .. ' ' .. g_app.getVersion() .. ' rev ' .. g_app.getBuildRevision() .. ' (' .. g_app.getBuildCommit() .. ') built on ' .. g_app.getBuildDate() .. ' for arch ' .. g_app.getBuildArch())
|
g_logger.info(g_app.getName() .. ' ' .. g_app.getVersion() .. ' rev ' .. g_app.getBuildRevision() .. ' (' .. g_app.getBuildCommit() .. ') built on ' .. g_app.getBuildDate() .. ' for arch ' .. g_app.getBuildArch())
|
||||||
|
|
||||||
--add base folder to search path
|
--add base folder to search path
|
||||||
g_resources.addToSearchPath(g_resources.getWorkDir())
|
g_resources.addSearchPath(g_resources.getWorkDir())
|
||||||
|
|
||||||
-- add modules directory to the search path
|
-- add modules directory to the search path
|
||||||
if not g_resources.addToSearchPath(g_resources.getWorkDir() .. "modules", true) then
|
if not g_resources.addSearchPath(g_resources.getWorkDir() .. "modules", true) then
|
||||||
g_logger.fatal("Unable to add modules directory to the search path.")
|
g_logger.fatal("Unable to add modules directory to the search path.")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- try to add addons path too
|
-- try to add addons path too
|
||||||
g_resources.addToSearchPath(g_resources.getWorkDir() .. "addons", true)
|
g_resources.addSearchPath(g_resources.getWorkDir() .. "addons", true)
|
||||||
|
|
||||||
-- setup directory for saving configurations
|
-- setup directory for saving configurations
|
||||||
g_resources.setupWriteDir(g_app.getCompactName())
|
g_resources.setupUserWriteDir(g_app.getCompactName())
|
||||||
|
|
||||||
|
-- search all packages
|
||||||
|
g_resources.searchAndAddPackages('/', '.otpkg', true)
|
||||||
|
|
||||||
-- load configurations
|
-- load configurations
|
||||||
g_configs.load("/config.otml")
|
g_configs.load("/config.otml")
|
||||||
|
|
|
@ -27,7 +27,7 @@ function Skins.init()
|
||||||
Skins.installSkins('skins')
|
Skins.installSkins('skins')
|
||||||
|
|
||||||
if installedSkins[defaultSkinName] then
|
if installedSkins[defaultSkinName] then
|
||||||
g_resources.addToSearchPath(getSkinPath(defaultSkinName), 0)
|
g_resources.addSearchPath(getSkinPath(defaultSkinName), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local userSkinName = g_settings.get('skin', 'false')
|
local userSkinName = g_settings.get('skin', 'false')
|
||||||
|
@ -50,9 +50,9 @@ function Skins.init()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Skins.terminate()
|
function Skins.terminate()
|
||||||
g_resources.removeFromSearchPath(getSkinPath(defaultSkinName))
|
g_resources.removeSearchPath(getSkinPath(defaultSkinName))
|
||||||
if currentSkin then
|
if currentSkin then
|
||||||
g_resources.removeFromSearchPath(getSkinPath(currentSkin.name))
|
g_resources.removeSearchPath(getSkinPath(currentSkin.name))
|
||||||
end
|
end
|
||||||
|
|
||||||
installedSkins = nil
|
installedSkins = nil
|
||||||
|
@ -98,10 +98,12 @@ function Skins.setSkin(name)
|
||||||
Skins.loadSkin(defaultSkin)
|
Skins.loadSkin(defaultSkin)
|
||||||
end
|
end
|
||||||
|
|
||||||
if currentSkin then
|
if currentSkin and currentSkin.name ~= defaultSkinName then
|
||||||
g_resources.removeFromSearchPath(getSkinPath(currentSkin.name))
|
g_resources.removeSearchPath(getSkinPath(currentSkin.name))
|
||||||
|
end
|
||||||
|
if skin.name ~= defaultSkinName then
|
||||||
|
g_resources.addSearchPath(getSkinPath(skin.name), true)
|
||||||
end
|
end
|
||||||
g_resources.addToSearchPath(getSkinPath(skin.name), true)
|
|
||||||
|
|
||||||
Skins.loadSkin(skin)
|
Skins.loadSkin(skin)
|
||||||
currentSkin = skin
|
currentSkin = skin
|
||||||
|
|
|
@ -38,7 +38,7 @@ function UIMessageBox.display(title, message, flags)
|
||||||
connect(messagebox, { onEscape = function(self) self:cancel() end })
|
connect(messagebox, { onEscape = function(self) self:cancel() end })
|
||||||
end
|
end
|
||||||
|
|
||||||
messagebox:lock()
|
--messagebox:lock()
|
||||||
|
|
||||||
return messagebox
|
return messagebox
|
||||||
end
|
end
|
||||||
|
|
|
@ -65,7 +65,7 @@ void ResourceManager::discoverWorkDir(const std::string& appName, const std::str
|
||||||
g_logger.fatal(stdext::format("Unable to find %s, the application cannot be initialized.", existentFile));
|
g_logger.fatal(stdext::format("Unable to find %s, the application cannot be initialized.", existentFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceManager::setupWriteDir(const std::string& appWriteDirName)
|
bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName)
|
||||||
{
|
{
|
||||||
std::string userDir = PHYSFS_getUserDir();
|
std::string userDir = PHYSFS_getUserDir();
|
||||||
std::string dirName;
|
std::string dirName;
|
||||||
|
@ -75,49 +75,69 @@ bool ResourceManager::setupWriteDir(const std::string& appWriteDirName)
|
||||||
dirName = appWriteDirName;
|
dirName = appWriteDirName;
|
||||||
#endif
|
#endif
|
||||||
std::string writeDir = userDir + dirName;
|
std::string writeDir = userDir + dirName;
|
||||||
|
return setWriteDir(writeDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceManager::setWriteDir(const std::string& writeDir, bool create)
|
||||||
|
{
|
||||||
|
if(!PHYSFS_setWriteDir(writeDir.c_str()) && !create) {
|
||||||
|
g_logger.error(stdext::format("Unable to set write directory '%s': %s", writeDir, PHYSFS_getLastError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PHYSFS_mkdir(writeDir.c_str())) {
|
||||||
|
g_logger.error(stdext::format("Unable to create write directory '%s': %s", writeDir, PHYSFS_getLastError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!PHYSFS_setWriteDir(writeDir.c_str())) {
|
if(!PHYSFS_setWriteDir(writeDir.c_str())) {
|
||||||
if(!PHYSFS_setWriteDir(userDir.c_str())) {
|
g_logger.error(stdext::format("Unable to set write directory '%s': %s", writeDir, PHYSFS_getLastError()));
|
||||||
g_logger.error("User directory not found.");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!PHYSFS_mkdir(dirName.c_str())) {
|
|
||||||
g_logger.error("Cannot create directory for saving configurations.");
|
if(!m_writeDir.empty())
|
||||||
return false;
|
removeSearchPath(m_writeDir);
|
||||||
}
|
|
||||||
if(!PHYSFS_setWriteDir(writeDir.c_str())) {
|
m_writeDir = writeDir;
|
||||||
g_logger.error("Unable to set write directory.");
|
|
||||||
return false;
|
if(!addSearchPath(writeDir))
|
||||||
}
|
g_logger.error(stdext::format("Unable to add write directory '%s' to search path"));
|
||||||
}
|
|
||||||
addToSearchPath(writeDir, true);
|
|
||||||
//g_logger.debug(stdext::format("Setup write dir %s", writeDir));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceManager::addToSearchPath(const std::string& path, bool insertInFront)
|
bool ResourceManager::addSearchPath(const std::string& path, bool pushFront)
|
||||||
{
|
{
|
||||||
if(!PHYSFS_addToSearchPath(path.c_str(), insertInFront ? 0 : 1))
|
if(!PHYSFS_addToSearchPath(path.c_str(), pushFront ? 0 : 1))
|
||||||
return false;
|
return false;
|
||||||
//g_logger.debug(stdext::format("Add search path %s", path));
|
if(pushFront)
|
||||||
|
m_searchPaths.push_front(path);
|
||||||
|
else
|
||||||
|
m_searchPaths.push_back(path);
|
||||||
m_hasSearchPath = true;
|
m_hasSearchPath = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceManager::removeFromSearchPath(const std::string& path)
|
bool ResourceManager::removeSearchPath(const std::string& path)
|
||||||
{
|
{
|
||||||
if(!PHYSFS_removeFromSearchPath(path.c_str()))
|
if(!PHYSFS_removeFromSearchPath(path.c_str()))
|
||||||
return false;
|
return false;
|
||||||
//g_logger.debug(stdext::format("Remove search path %s", path));
|
auto it = std::find(m_searchPaths.begin(), m_searchPaths.end(), path);
|
||||||
|
assert(it != m_searchPaths.end());
|
||||||
|
m_searchPaths.erase(it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::searchAndAddPackages(const std::string& packagesDir, const std::string& packageExt, bool append)
|
void ResourceManager::searchAndAddPackages(const std::string& packagesDir, const std::string& packageExt)
|
||||||
{
|
{
|
||||||
auto files = listDirectoryFiles(resolvePath(packagesDir));
|
auto files = listDirectoryFiles(packagesDir);
|
||||||
for(const std::string& file : files) {
|
for(auto it = files.rbegin(); it != files.rend(); ++it) {
|
||||||
if(boost::ends_with(file, packageExt))
|
const std::string& file = *it;
|
||||||
addToSearchPath(packagesDir + "/" + file, !append);
|
if(!boost::ends_with(file, packageExt))
|
||||||
|
continue;
|
||||||
|
std::string package = getRealDir(packagesDir) + "/" + file;
|
||||||
|
if(!addSearchPath(package, true))
|
||||||
|
g_logger.error(stdext::format("Unable to read package '%s': %s", package, PHYSFS_getLastError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +287,7 @@ std::string ResourceManager::resolvePath(const std::string& path)
|
||||||
std::string ResourceManager::getRealDir(const std::string& path)
|
std::string ResourceManager::getRealDir(const std::string& path)
|
||||||
{
|
{
|
||||||
std::string dir;
|
std::string dir;
|
||||||
const char *cdir = PHYSFS_getRealDir(path.c_str());
|
const char *cdir = PHYSFS_getRealDir(resolvePath(path).c_str());
|
||||||
if(cdir)
|
if(cdir)
|
||||||
dir = cdir;
|
dir = cdir;
|
||||||
return dir;
|
return dir;
|
||||||
|
|
|
@ -35,11 +35,12 @@ public:
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
void discoverWorkDir(const std::string& appName, const std::string& existentFile);
|
void discoverWorkDir(const std::string& appName, const std::string& existentFile);
|
||||||
bool setupWriteDir(const std::string& appWriteDirName);
|
bool setupUserWriteDir(const std::string& appWriteDirName);
|
||||||
|
bool setWriteDir(const std::string& writeDir, bool create = false);
|
||||||
|
|
||||||
bool addToSearchPath(const std::string& path, bool insertInFront = true);
|
bool addSearchPath(const std::string& path, bool pushFront = false);
|
||||||
bool removeFromSearchPath(const std::string& path);
|
bool removeSearchPath(const std::string& path);
|
||||||
void searchAndAddPackages(const std::string& packagesDir, const std::string& packagesExt, bool append);
|
void searchAndAddPackages(const std::string& packagesDir, const std::string& packagesExt);
|
||||||
|
|
||||||
bool fileExists(const std::string& fileName);
|
bool fileExists(const std::string& fileName);
|
||||||
bool directoryExists(const std::string& directoryName);
|
bool directoryExists(const std::string& directoryName);
|
||||||
|
@ -64,11 +65,15 @@ public:
|
||||||
std::string resolvePath(const std::string& path);
|
std::string resolvePath(const std::string& path);
|
||||||
std::string getRealDir(const std::string& path);
|
std::string getRealDir(const std::string& path);
|
||||||
std::string getBaseDir();
|
std::string getBaseDir();
|
||||||
|
std::string getWriteDir() { return m_writeDir; }
|
||||||
std::string getWorkDir() { return m_workDir; }
|
std::string getWorkDir() { return m_workDir; }
|
||||||
|
std::deque<std::string> getSearchPaths() { return m_searchPaths; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_workDir;
|
std::string m_workDir;
|
||||||
|
std::string m_writeDir;
|
||||||
Boolean<false> m_hasSearchPath;
|
Boolean<false> m_hasSearchPath;
|
||||||
|
std::deque<std::string> m_searchPaths;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ResourceManager g_resources;
|
extern ResourceManager g_resources;
|
||||||
|
|
|
@ -125,12 +125,15 @@ void Application::registerLuaFunctions()
|
||||||
|
|
||||||
// ResourceManager
|
// ResourceManager
|
||||||
g_lua.registerSingletonClass("g_resources");
|
g_lua.registerSingletonClass("g_resources");
|
||||||
g_lua.bindSingletonFunction("g_resources", "addToSearchPath", &ResourceManager::addToSearchPath, &g_resources);
|
g_lua.bindSingletonFunction("g_resources", "addSearchPath", &ResourceManager::addSearchPath, &g_resources);
|
||||||
g_lua.bindSingletonFunction("g_resources", "setupWriteDir", &ResourceManager::setupWriteDir, &g_resources);
|
g_lua.bindSingletonFunction("g_resources", "setupUserWriteDir", &ResourceManager::setupUserWriteDir, &g_resources);
|
||||||
g_lua.bindSingletonFunction("g_resources", "removeFromSearchPath", &ResourceManager::removeFromSearchPath, &g_resources);
|
g_lua.bindSingletonFunction("g_resources", "setWriteDir", &ResourceManager::setWriteDir, &g_resources);
|
||||||
|
g_lua.bindSingletonFunction("g_resources", "searchAndAddPackages", &ResourceManager::searchAndAddPackages, &g_resources);
|
||||||
|
g_lua.bindSingletonFunction("g_resources", "removeSearchPath", &ResourceManager::removeSearchPath, &g_resources);
|
||||||
g_lua.bindSingletonFunction("g_resources", "fileExists", &ResourceManager::fileExists, &g_resources);
|
g_lua.bindSingletonFunction("g_resources", "fileExists", &ResourceManager::fileExists, &g_resources);
|
||||||
g_lua.bindSingletonFunction("g_resources", "getRealDir", &ResourceManager::getRealDir, &g_resources);
|
g_lua.bindSingletonFunction("g_resources", "getRealDir", &ResourceManager::getRealDir, &g_resources);
|
||||||
g_lua.bindSingletonFunction("g_resources", "getWorkDir", &ResourceManager::getWorkDir, &g_resources);
|
g_lua.bindSingletonFunction("g_resources", "getWorkDir", &ResourceManager::getWorkDir, &g_resources);
|
||||||
|
g_lua.bindSingletonFunction("g_resources", "getSearchPaths", &ResourceManager::getSearchPaths, &g_resources);
|
||||||
|
|
||||||
// Module
|
// Module
|
||||||
g_lua.registerClass<Module>();
|
g_lua.registerClass<Module>();
|
||||||
|
|
Loading…
Reference in New Issue