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:
Eduardo Bart 2012-07-16 16:35:14 -03:00
parent 09425eba31
commit bc81c9c8bf
6 changed files with 77 additions and 44 deletions

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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>();