Changed: #1051 Create a console-based working patcher

This commit is contained in:
kervala 2010-08-05 09:53:38 +02:00
parent 3460411dc1
commit 719e589d0d

View file

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