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).
master
Eduardo Bart 12 years ago
parent 09425eba31
commit bc81c9c8bf

@ -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.");
return false;
}
if(!PHYSFS_setWriteDir(writeDir.c_str())) {
g_logger.error("Unable to set write directory.");
return false;
}
} }
addToSearchPath(writeDir, true);
//g_logger.debug(stdext::format("Setup write dir %s", writeDir)); if(!m_writeDir.empty())
removeSearchPath(m_writeDir);
m_writeDir = writeDir;
if(!addSearchPath(writeDir))
g_logger.error(stdext::format("Unable to add write directory '%s' to search path"));
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…
Cancel
Save