Changed: #1051 Create a console-based working patcher
This commit is contained in:
parent
bb3bbe8a6d
commit
d4ff95bf3a
1 changed files with 130 additions and 34 deletions
|
@ -1,6 +1,7 @@
|
||||||
#include "stdpch.h"
|
#include "stdpch.h"
|
||||||
#include "login_patch.h"
|
#include "login_patch.h"
|
||||||
#include "client_cfg.h"
|
#include "client_cfg.h"
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -26,10 +27,32 @@ uint32 LoginShardId = 0xFFFFFFFF;
|
||||||
// stuff which is defined in other .cpp files
|
// stuff which is defined in other .cpp files
|
||||||
extern void tmpFlagRemovedPatchCategories(NLMISC::CConfigFile &cf);
|
extern void tmpFlagRemovedPatchCategories(NLMISC::CConfigFile &cf);
|
||||||
|
|
||||||
|
bool useUtf8 = false;
|
||||||
|
|
||||||
|
std::string convert(const ucstring &str)
|
||||||
|
{
|
||||||
|
if (useUtf8)
|
||||||
|
return str.toUtf8();
|
||||||
|
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printError(const std::string &str)
|
||||||
|
{
|
||||||
|
// display error in red
|
||||||
|
printf("\033[22;31mError: %s\033[0m\n", str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void printProgress(const std::string &str)
|
||||||
|
{
|
||||||
|
// display progress in green
|
||||||
|
printf("\033[F\033[22;31mError: %d\033[0m\033[[1J\n", str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// init the Nel context
|
// init the Nel context
|
||||||
CApplicationContext *appContext = new CApplicationContext;
|
CApplicationContext appContext;
|
||||||
|
|
||||||
createDebug();
|
createDebug();
|
||||||
|
|
||||||
|
@ -48,25 +71,75 @@ int main(int argc, char *argv[])
|
||||||
CPath::setCurrentPath(currentPath);
|
CPath::setCurrentPath(currentPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string lang;
|
||||||
|
|
||||||
|
char *locale = setlocale(LC_CTYPE, NULL);
|
||||||
|
|
||||||
|
if (locale)
|
||||||
|
lang = toLower(std::string(locale));
|
||||||
|
useUtf8 = (lang.find("utf8") != string::npos || lang.find("utf-8") != string::npos);
|
||||||
|
|
||||||
|
// create or load client.cfg
|
||||||
ClientCfg.init("client.cfg");
|
ClientCfg.init("client.cfg");
|
||||||
|
|
||||||
|
// check if PatchServer is defined
|
||||||
|
if (ClientCfg.PatchServer.empty())
|
||||||
|
{
|
||||||
|
printError("PatchServer not defined in client_default.cfg or client.cfg");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default paths
|
||||||
std::string dataPath = "./data/";
|
std::string dataPath = "./data/";
|
||||||
std::string rootPath = "./";
|
std::string rootPath = "./";
|
||||||
|
|
||||||
|
// use custom data path if specified
|
||||||
if (!ClientCfg.DataPath.empty())
|
if (!ClientCfg.DataPath.empty())
|
||||||
{
|
{
|
||||||
dataPath = CPath::standardizePath(ClientCfg.DataPath[0]);
|
dataPath = CPath::standardizePath(ClientCfg.DataPath.front());
|
||||||
string::size_type pos = dataPath.rfind('/', dataPath.length()-2);
|
string::size_type pos = dataPath.rfind('/', dataPath.length()-2);
|
||||||
if (pos != string::npos)
|
if (pos != string::npos)
|
||||||
rootPath = dataPath.substr(0, pos+1);
|
rootPath = dataPath.substr(0, pos+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add .bnp containing translations
|
std::string unpackPath = CPath::standardizePath(rootPath + "unpack");
|
||||||
CPath::addSearchBigFile(dataPath + "gamedev.bnp", true, false);
|
|
||||||
|
// check if user can write in data directory
|
||||||
|
if (!CFile::isExists(unpackPath))
|
||||||
|
{
|
||||||
|
if (!CFile::createDirectoryTree(unpackPath))
|
||||||
|
{
|
||||||
|
printError("You don't have permission to create " + unpackPath);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!CFile::createEmptyFile(unpackPath + "empty"))
|
||||||
|
{
|
||||||
|
printError("You don't have write permission in " + unpackPath);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFile::deleteFile(unpackPath + "empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
// only use PreDataPath for looking paths
|
||||||
|
if (!ClientCfg.PreDataPath.empty())
|
||||||
|
{
|
||||||
|
for(uint i = 0; i < ClientCfg.PreDataPath.size(); ++i)
|
||||||
|
{
|
||||||
|
CPath::addSearchPath(ClientCfg.PreDataPath[i], true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// load translation
|
// load translation
|
||||||
CI18N::load(ClientCfg.LanguageCode);
|
CI18N::load(ClientCfg.LanguageCode);
|
||||||
|
|
||||||
|
printf("Checking %s files to patch...\n", convert(CI18N::get("TheSagaOfRyzom")).c_str());
|
||||||
|
|
||||||
|
printf("Using language: %s\n", convert(CI18N::get("LanguageName")).c_str());
|
||||||
|
|
||||||
#ifdef NL_OS_UNIX
|
#ifdef NL_OS_UNIX
|
||||||
// don't use cfg, exe and dll from Windows version
|
// don't use cfg, exe and dll from Windows version
|
||||||
CConfigFile::CVar var;
|
CConfigFile::CVar var;
|
||||||
|
@ -84,8 +157,10 @@ int main(int argc, char *argv[])
|
||||||
// initialize patch manager and set the ryzom full path, before it's used
|
// initialize patch manager and set the ryzom full path, before it's used
|
||||||
CPatchManager *pPM = CPatchManager::getInstance();
|
CPatchManager *pPM = CPatchManager::getInstance();
|
||||||
|
|
||||||
|
// set the correct root path
|
||||||
pPM->setClientRootPath(rootPath);
|
pPM->setClientRootPath(rootPath);
|
||||||
|
|
||||||
|
// use PatchServer URL
|
||||||
vector<string> patchURLs;
|
vector<string> patchURLs;
|
||||||
pPM->init(patchURLs, ClientCfg.PatchServer, ClientCfg.PatchVersion);
|
pPM->init(patchURLs, ClientCfg.PatchServer, ClientCfg.PatchVersion);
|
||||||
pPM->startCheckThread(true /* include background patchs */);
|
pPM->startCheckThread(true /* include background patchs */);
|
||||||
|
@ -105,19 +180,15 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
for(uint i = 0; i < log.size(); ++i)
|
for(uint i = 0; i < log.size(); ++i)
|
||||||
{
|
{
|
||||||
printf("%s\n", log[i].toUtf8().c_str());
|
printf("%s\n", convert(log[i]).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!res)
|
if (!res && !pPM->getLastErrorMessage().empty())
|
||||||
{
|
{
|
||||||
ucstring errMsg = CI18N::get("uiErrChecking");
|
printError(convert(CI18N::get("uiErrChecking") + " " + pPM->getLastErrorMessage()));
|
||||||
if (!pPM->getLastErrorMessage().empty())
|
return 1;
|
||||||
{
|
|
||||||
ucstring errMsg = pPM->getLastErrorMessage();
|
|
||||||
printf("Error: %s\n", errMsg.toUtf8().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CPatchManager::SPatchInfo InfoOnPatch;
|
CPatchManager::SPatchInfo InfoOnPatch;
|
||||||
|
@ -125,18 +196,17 @@ int main(int argc, char *argv[])
|
||||||
// Check is good now ask the player if he wants to apply the patch
|
// Check is good now ask the player if he wants to apply the patch
|
||||||
pPM->getInfoToDisp(InfoOnPatch);
|
pPM->getInfoToDisp(InfoOnPatch);
|
||||||
|
|
||||||
uint AvailablePatchs = InfoOnPatch.getAvailablePatchsBitfield();
|
|
||||||
|
|
||||||
// Get the list of optional categories to patch
|
// Get the list of optional categories to patch
|
||||||
vector<string> vCategories;
|
vector<string> vCategories;
|
||||||
|
|
||||||
for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
|
for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
|
||||||
{
|
{
|
||||||
// Ok for the moment all optional categories must be patched even if the player
|
// Ok for the moment all optional categories must be patched even if the player
|
||||||
// does not want it. Because we cant detect that a continent have to be patched ingame.
|
// does not want it. Because we can't detect that a continent have to be patched ingame.
|
||||||
vCategories.push_back(InfoOnPatch.OptCat[i].Name);
|
vCategories.push_back(InfoOnPatch.OptCat[i].Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start patch thread
|
||||||
pPM->startPatchThread(vCategories, true);
|
pPM->startPatchThread(vCategories, true);
|
||||||
|
|
||||||
res = false;
|
res = false;
|
||||||
|
@ -150,30 +220,58 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if (pPM->getThreadState(state, log))
|
if (pPM->getThreadState(state, log))
|
||||||
{
|
{
|
||||||
printf("%s\n", state.toUtf8().c_str());
|
printProgress(convert(state));
|
||||||
|
|
||||||
for(uint i = 0; i < log.size(); ++i)
|
for(uint i = 0; i < log.size(); ++i)
|
||||||
{
|
{
|
||||||
printf("%s\n", log[i].toUtf8().c_str());
|
printf("%s\n", convert(log[i]).c_str());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
ucstring errMsg = CI18N::get("uiErrChecking");
|
|
||||||
if (!pPM->getLastErrorMessage().empty())
|
|
||||||
{
|
|
||||||
ucstring errMsg = pPM->getLastErrorMessage();
|
|
||||||
printf("Error: %s\n", errMsg.toUtf8().c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!res && !pPM->getLastErrorMessage().empty())
|
||||||
|
{
|
||||||
|
printError(convert(CI18N::get("uiErrPatching") + " " + pPM->getLastErrorMessage()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (CPatchManager::getInstance()->mustLaunchBatFile())
|
if (CPatchManager::getInstance()->mustLaunchBatFile())
|
||||||
{
|
{
|
||||||
// move downloaded files to final location
|
std::string error;
|
||||||
pPM->createBatchFile(pPM->getDescFile(), false, false);
|
|
||||||
CFile::createEmptyFile("show_eula");
|
try
|
||||||
|
{
|
||||||
|
// move downloaded files to final location
|
||||||
|
pPM->createBatchFile(pPM->getDescFile(), false, false);
|
||||||
|
CFile::createEmptyFile("show_eula");
|
||||||
|
|
||||||
|
if (!pPM->getLastErrorMessage().empty())
|
||||||
|
{
|
||||||
|
error = convert(pPM->getLastErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const EDiskFullError &)
|
||||||
|
{
|
||||||
|
error = convert(CI18N::get("uiPatchDiskFull"));;
|
||||||
|
}
|
||||||
|
catch(const EWriteError &)
|
||||||
|
{
|
||||||
|
error = convert(CI18N::get("uiPatchWriteError"));;
|
||||||
|
}
|
||||||
|
catch(const Exception &e)
|
||||||
|
{
|
||||||
|
error = convert(CI18N::get("uiCheckEndWithErr") + " " + e.what());
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
error = "unknown exception";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error.empty())
|
||||||
|
{
|
||||||
|
printError(convert(CI18N::get("uiErrPatchApply")) + " " + error);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -184,8 +282,6 @@ int main(int argc, char *argv[])
|
||||||
pPM->askForStopScanDataThread();
|
pPM->askForStopScanDataThread();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
delete appContext;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue