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())
--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
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.")
end
-- 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
g_resources.setupWriteDir(g_app.getCompactName())
g_resources.setupUserWriteDir(g_app.getCompactName())
-- search all packages
g_resources.searchAndAddPackages('/', '.otpkg', true)
-- load configurations
g_configs.load("/config.otml")

@ -27,7 +27,7 @@ function Skins.init()
Skins.installSkins('skins')
if installedSkins[defaultSkinName] then
g_resources.addToSearchPath(getSkinPath(defaultSkinName), 0)
g_resources.addSearchPath(getSkinPath(defaultSkinName), 0)
end
local userSkinName = g_settings.get('skin', 'false')
@ -50,9 +50,9 @@ function Skins.init()
end
function Skins.terminate()
g_resources.removeFromSearchPath(getSkinPath(defaultSkinName))
g_resources.removeSearchPath(getSkinPath(defaultSkinName))
if currentSkin then
g_resources.removeFromSearchPath(getSkinPath(currentSkin.name))
g_resources.removeSearchPath(getSkinPath(currentSkin.name))
end
installedSkins = nil
@ -98,10 +98,12 @@ function Skins.setSkin(name)
Skins.loadSkin(defaultSkin)
end
if currentSkin then
g_resources.removeFromSearchPath(getSkinPath(currentSkin.name))
if currentSkin and currentSkin.name ~= defaultSkinName then
g_resources.removeSearchPath(getSkinPath(currentSkin.name))
end
if skin.name ~= defaultSkinName then
g_resources.addSearchPath(getSkinPath(skin.name), true)
end
g_resources.addToSearchPath(getSkinPath(skin.name), true)
Skins.loadSkin(skin)
currentSkin = skin

@ -38,7 +38,7 @@ function UIMessageBox.display(title, message, flags)
connect(messagebox, { onEscape = function(self) self:cancel() end })
end
messagebox:lock()
--messagebox:lock()
return messagebox
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));
}
bool ResourceManager::setupWriteDir(const std::string& appWriteDirName)
bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName)
{
std::string userDir = PHYSFS_getUserDir();
std::string dirName;
@ -75,49 +75,69 @@ bool ResourceManager::setupWriteDir(const std::string& appWriteDirName)
dirName = appWriteDirName;
#endif
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(userDir.c_str())) {
g_logger.error("User directory not found.");
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;
}
g_logger.error(stdext::format("Unable to set write directory '%s': %s", writeDir, PHYSFS_getLastError()));
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;
}
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;
//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;
return true;
}
bool ResourceManager::removeFromSearchPath(const std::string& path)
bool ResourceManager::removeSearchPath(const std::string& path)
{
if(!PHYSFS_removeFromSearchPath(path.c_str()))
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;
}
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));
for(const std::string& file : files) {
if(boost::ends_with(file, packageExt))
addToSearchPath(packagesDir + "/" + file, !append);
auto files = listDirectoryFiles(packagesDir);
for(auto it = files.rbegin(); it != files.rend(); ++it) {
const std::string& file = *it;
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 dir;
const char *cdir = PHYSFS_getRealDir(path.c_str());
const char *cdir = PHYSFS_getRealDir(resolvePath(path).c_str());
if(cdir)
dir = cdir;
return dir;

@ -35,11 +35,12 @@ public:
void terminate();
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 removeFromSearchPath(const std::string& path);
void searchAndAddPackages(const std::string& packagesDir, const std::string& packagesExt, bool append);
bool addSearchPath(const std::string& path, bool pushFront = false);
bool removeSearchPath(const std::string& path);
void searchAndAddPackages(const std::string& packagesDir, const std::string& packagesExt);
bool fileExists(const std::string& fileName);
bool directoryExists(const std::string& directoryName);
@ -64,11 +65,15 @@ public:
std::string resolvePath(const std::string& path);
std::string getRealDir(const std::string& path);
std::string getBaseDir();
std::string getWriteDir() { return m_writeDir; }
std::string getWorkDir() { return m_workDir; }
std::deque<std::string> getSearchPaths() { return m_searchPaths; }
private:
std::string m_workDir;
std::string m_writeDir;
Boolean<false> m_hasSearchPath;
std::deque<std::string> m_searchPaths;
};
extern ResourceManager g_resources;

@ -125,12 +125,15 @@ void Application::registerLuaFunctions()
// ResourceManager
g_lua.registerSingletonClass("g_resources");
g_lua.bindSingletonFunction("g_resources", "addToSearchPath", &ResourceManager::addToSearchPath, &g_resources);
g_lua.bindSingletonFunction("g_resources", "setupWriteDir", &ResourceManager::setupWriteDir, &g_resources);
g_lua.bindSingletonFunction("g_resources", "removeFromSearchPath", &ResourceManager::removeFromSearchPath, &g_resources);
g_lua.bindSingletonFunction("g_resources", "addSearchPath", &ResourceManager::addSearchPath, &g_resources);
g_lua.bindSingletonFunction("g_resources", "setupUserWriteDir", &ResourceManager::setupUserWriteDir, &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", "getRealDir", &ResourceManager::getRealDir, &g_resources);
g_lua.bindSingletonFunction("g_resources", "getWorkDir", &ResourceManager::getWorkDir, &g_resources);
g_lua.bindSingletonFunction("g_resources", "getSearchPaths", &ResourceManager::getSearchPaths, &g_resources);
// Module
g_lua.registerClass<Module>();

Loading…
Cancel
Save