merge from compatibility-develop

This commit is contained in:
SIELA1915 2016-02-12 18:28:23 +01:00
parent 3cd8969cd7
commit f5459a1b9b
54 changed files with 2992 additions and 1742 deletions

View file

@ -269,10 +269,6 @@ IF(WITH_QT5)
# Gui # Gui
SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Gui Qt5::OpenGL) SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Gui Qt5::OpenGL)
IF(WIN32)
SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::WinExtras)
ENDIF()
ADD_QT_LIBRARY(PrintSupport) ADD_QT_LIBRARY(PrintSupport)
IF(WIN32) IF(WIN32)
@ -390,10 +386,6 @@ IF(WITH_QT5)
ENDIF() ENDIF()
ELSE() ELSE()
SET(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::Xml Qt5::Gui Qt5::OpenGL Qt5::Core) SET(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::Xml Qt5::Gui Qt5::OpenGL Qt5::Core)
IF(WIN32)
SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::WinExtras)
ENDIF()
ENDIF() ENDIF()
ELSE() ELSE()
MESSAGE(WARNING "Unable to find Qt 5") MESSAGE(WARNING "Unable to find Qt 5")

View file

@ -0,0 +1,74 @@
# - Locate Steam API
# This module defines
# STEAM_LIBRARY, the library to link against
# VORBIS_FOUND, if false, do not try to link to VORBIS
# VORBIS_INCLUDE_DIR, where to find headers.
IF(STEAM_LIBRARY AND STEAM_INCLUDE_DIR)
# in cache already
SET(Steam_FIND_QUIETLY TRUE)
ENDIF()
FIND_PATH(STEAM_INCLUDE_DIR
steam_api.h
PATH_SUFFIXES steam
PATHS
$ENV{STEAM_DIR}/public
)
IF(WIN32)
IF(TARGET_X64)
SET(STEAM_LIBNAME steam_api64)
SET(STEAM_RUNTIMENAME steam_api64.dll)
SET(STEAM_PATHNAME redistributable_bin/win64)
ELSE()
SET(STEAM_LIBNAME steam_api)
SET(STEAM_RUNTIMENAME steam_api.dll)
SET(STEAM_PATHNAME redistributable_bin)
ENDIF()
ELSEIF(APPLE)
# universal binary
SET(STEAM_LIBNAME steam_api)
SET(STEAM_RUNTIMENAME libsteam_api.dylib)
SET(STEAM_PATHNAME redistributable_bin/osx32)
ELSE()
SET(STEAM_LIBNAME steam_api)
SET(STEAM_RUNTIMENAME libsteam_api.so)
IF(TARGET_X64)
SET(STEAM_PATHNAME redistributable_bin/linux64)
ELSE()
SET(STEAM_PATHNAME redistributable_bin/linux32)
ENDIF()
ENDIF()
FIND_LIBRARY(STEAM_LIBRARY
NAMES ${STEAM_LIBNAME}
HINTS
$ENV{STEAM_DIR}/${STEAM_PATHNAME}
)
FIND_FILE(STEAM_RUNTIME
NAMES ${STEAM_RUNTIMENAME}
HINTS
$ENV{STEAM_DIR}/${STEAM_PATHNAME}
PATHS
${EXTERNAL_BINARY_PATH}
${CMAKE_LIBRARY_PATH}
/usr/local/lib
/usr/lib
)
# Don't need to check STEAM_LIBRARY because we're dynamically loading Steam DLL
IF(STEAM_INCLUDE_DIR)
SET(STEAM_FOUND ON)
SET(STEAM_LIBRARIES ${STEAM_LIBRARY})
SET(STEAM_INCLUDE_DIRS ${STEAM_INCLUDE_DIR})
IF(NOT Steam_FIND_QUIETLY)
MESSAGE(STATUS "Found Steam: ${STEAM_INCLUDE_DIR} and ${STEAM_RUNTIME}")
ENDIF()
ELSE()
IF(NOT Steam_FIND_QUIETLY)
MESSAGE(STATUS "Warning: Unable to find Steam!")
ENDIF()
ENDIF()

View file

@ -258,6 +258,7 @@ MACRO(NL_SETUP_DEFAULT_OPTIONS)
OPTION(WITH_NELNS "Build NeL Network Services." OFF) OPTION(WITH_NELNS "Build NeL Network Services." OFF)
OPTION(WITH_RYZOM "Build Ryzom Core." ON ) OPTION(WITH_RYZOM "Build Ryzom Core." ON )
OPTION(WITH_SNOWBALLS "Build Snowballs." OFF) OPTION(WITH_SNOWBALLS "Build Snowballs." OFF)
OPTION(WITH_TOOLS "Build Tools" OFF)
ENDMACRO(NL_SETUP_DEFAULT_OPTIONS) ENDMACRO(NL_SETUP_DEFAULT_OPTIONS)
MACRO(NL_SETUP_NEL_DEFAULT_OPTIONS) MACRO(NL_SETUP_NEL_DEFAULT_OPTIONS)
@ -1083,15 +1084,15 @@ MACRO(SETUP_EXTERNAL)
IF(APPLE) IF(APPLE)
IF(WITH_STATIC_EXTERNAL) IF(WITH_STATIC_EXTERNAL)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a) SET(CMAKE_FIND_LIBRARY_SUFFIXES .a)
ELSE(WITH_STATIC_EXTERNAL) ELSE()
SET(CMAKE_FIND_LIBRARY_SUFFIXES .dylib .so .a) SET(CMAKE_FIND_LIBRARY_SUFFIXES .dylib .so .a)
ENDIF(WITH_STATIC_EXTERNAL) ENDIF()
ELSE(APPLE) ELSE(APPLE)
IF(WITH_STATIC_EXTERNAL) IF(WITH_STATIC_EXTERNAL)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a .so) SET(CMAKE_FIND_LIBRARY_SUFFIXES .a .so)
ELSE(WITH_STATIC_EXTERNAL) ELSE()
SET(CMAKE_FIND_LIBRARY_SUFFIXES .so .a) SET(CMAKE_FIND_LIBRARY_SUFFIXES .so .a)
ENDIF(WITH_STATIC_EXTERNAL) ENDIF()
ENDIF(APPLE) ENDIF(APPLE)
ENDIF(WIN32) ENDIF(WIN32)

View file

@ -336,6 +336,10 @@ void itoaInt64 (sint64 number, char *str, sint64 base = 10);
std::string bytesToHumanReadable (const std::string &bytes); std::string bytesToHumanReadable (const std::string &bytes);
std::string bytesToHumanReadable (uint64 bytes); std::string bytesToHumanReadable (uint64 bytes);
/// Convert a number in bytes into a string that is easily readable by an human, for example 105123 -> "102kb"
/// Using units array as string: 0 => B, 1 => KiB, 2 => MiB, 3 => GiB, etc...
std::string bytesToHumanReadableUnits (uint64 bytes, const std::vector<std::string> &units);
/// Convert a human readable into a bytes, for example "102kb" -> 105123 /// Convert a human readable into a bytes, for example "102kb" -> 105123
uint32 humanReadableToBytes (const std::string &str); uint32 humanReadableToBytes (const std::string &str);

View file

@ -230,7 +230,7 @@ public:
/** Get application directory. /** Get application directory.
* \return directory where applications should write files. * \return directory where applications should write files.
*/ */
std::string getApplicationDirectory(const std::string &appName = ""); std::string getApplicationDirectory(const std::string &appName = "", bool local = false);
/** Get a temporary directory. /** Get a temporary directory.
* \return temporary directory where applications should write files. * \return temporary directory where applications should write files.
@ -540,7 +540,7 @@ public:
/** Get application directory. /** Get application directory.
* \return directory where applications should write files. * \return directory where applications should write files.
*/ */
static std::string getApplicationDirectory(const std::string &appName = ""); static std::string getApplicationDirectory(const std::string &appName = "", bool local = false);
/** Get a temporary directory. /** Get a temporary directory.
* \return temporary directory where applications should write files. * \return temporary directory where applications should write files.

View file

@ -246,27 +246,38 @@ inline bool fromString(const std::string &str, bool &val)
{ {
if (str.length() == 1) if (str.length() == 1)
{ {
if (str[0] == '1') const char c = str[0];
switch(c)
{ {
case '1':
case 't':
case 'T':
case 'y':
case 'Y':
val = true; val = true;
} break;
else if (str[0] == '0')
{ case '0':
case 'f':
case 'F':
case 'n':
case 'N':
val = false; val = false;
} break;
else
{ default:
val = false; val = false;
return false; return false;
} }
} }
else else
{ {
if (str == "true") if (str == "true" || str == "yes")
{ {
val = true; val = true;
} }
else if (str == "false") else if (str == "false" || str == "no")
{ {
val = false; val = false;
} }

View file

@ -715,7 +715,7 @@ SOURCE_GROUP(Stereo FILES
NL_TARGET_LIB(nel3d ${HEADERS} ${SRC}) NL_TARGET_LIB(nel3d ${HEADERS} ${SRC})
INCLUDE_DIRECTORIES(BEFORE ${FREETYPE_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${LIBVR_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${LIBVR_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(nel3d nelmisc ${FREETYPE_LIBRARIES} ${LIBOVR_LIBRARIES} ${LIBVR_LIBRARY}) TARGET_LINK_LIBRARIES(nel3d nelmisc ${FREETYPE_LIBRARIES} ${LIBOVR_LIBRARIES} ${LIBVR_LIBRARY})

View file

@ -383,6 +383,25 @@ string bytesToHumanReadable (uint64 bytes)
return toString ("%" NL_I64 "u %s", res, divTable[div]); return toString ("%" NL_I64 "u %s", res, divTable[div]);
} }
std::string bytesToHumanReadableUnits (uint64 bytes, const std::vector<std::string> &units)
{
if (units.empty()) return "";
uint div = 0;
uint last = units.size()-1;
uint64 res = bytes;
uint64 newres = res;
for(;;)
{
newres /= 1024;
if(newres < 8 || div > 3 || div == last)
break;
++div;
res = newres;
}
return toString ("%" NL_I64 "u %s", res, units[div].c_str());
}
uint32 humanReadableToBytes (const string &str) uint32 humanReadableToBytes (const string &str)
{ {
uint32 res; uint32 res;
@ -394,7 +413,8 @@ uint32 humanReadableToBytes (const string &str)
if(str[0]<'0' || str[0]>'9') if(str[0]<'0' || str[0]>'9')
return 0; return 0;
res = atoi (str.c_str()); if (!fromString(str, res))
return 0;
if(str[str.size()-1] == 'B') if(str[str.size()-1] == 'B')
{ {
@ -404,12 +424,30 @@ uint32 humanReadableToBytes (const string &str)
// there's no break and it's **normal** // there's no break and it's **normal**
switch (str[str.size()-2]) switch (str[str.size()-2])
{ {
// kB/KB, MB, GB and TB are 1000 multiples
case 'T': res *= 1000;
case 'G': res *= 1000;
case 'M': res *= 1000;
case 'k': res *= 1000; break; // kilo symbol should be a lowercase K
case 'K': res *= 1000; break;
case 'i':
{
// KiB, MiB, GiB and TiB are 1024 multiples
if (str.size()<4)
return res;
switch (str[str.size()-3])
{
case 'T': res *= 1024;
case 'G': res *= 1024; case 'G': res *= 1024;
case 'M': res *= 1024; case 'M': res *= 1024;
case 'K': res *= 1024; case 'K': res *= 1024;
default: ; default: ;
} }
} }
default: ;
}
}
return res; return res;
} }
@ -694,8 +732,22 @@ bool launchProgram(const std::string &programName, const std::string &arguments,
SetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, NULL ); SetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, NULL );
} }
string arg = " " + arguments; const char *sProgramName = programName.c_str();
BOOL res = CreateProcessA(programName.c_str(), (char*)arg.c_str(), NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
std::string args;
// a .bat file must have first parameter to NULL and use 2nd parameter to pass filename
if (CFile::getExtension(programName) == "bat")
{
sProgramName = NULL;
args = "\"" + programName + "\" " + arguments;
}
else
{
args = arguments;
}
BOOL res = CreateProcessA(sProgramName, (char*)args.c_str(), NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
if (res) if (res)
{ {
@ -716,26 +768,14 @@ bool launchProgram(const std::string &programName, const std::string &arguments,
} }
#elif defined(NL_OS_MAC) #elif defined(NL_OS_MAC)
std::string command;
if (CFile::getExtension(programName) == "app")
{
// we need to open bundles with "open" command // we need to open bundles with "open" command
command = NLMISC::toString("open \"%s\"", programName.c_str()); std::string command = NLMISC::toString("open \"%s\"", programName.c_str());
// append arguments if any // append arguments if any
if (!arguments.empty()) if (!arguments.empty())
{ {
command += NLMISC::toString(" --args %s", arguments.c_str()); command += NLMISC::toString(" --args %s", arguments.c_str());
} }
}
else
{
command = programName;
// append arguments if any
if (!arguments.empty()) command += " " + arguments;
}
int res = system(command.c_str()); int res = system(command.c_str());
@ -838,8 +878,22 @@ sint launchProgramAndWaitForResult(const std::string &programName, const std::st
SetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, NULL ); SetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, NULL );
} }
string arg = " " + arguments; const char *sProgramName = programName.c_str();
BOOL ok = CreateProcessA(programName.c_str(), (char*)arg.c_str(), NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
std::string args;
// a .bat file must have first parameter to NULL and use 2nd parameter to pass filename
if (CFile::getExtension(programName) == "bat")
{
sProgramName = NULL;
args = "\"" + programName + "\" " + arguments;
}
else
{
args = arguments;
}
BOOL ok = CreateProcessA(sProgramName, (char*)args.c_str(), NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
if (ok) if (ok)
{ {

View file

@ -260,7 +260,7 @@ void CLog::displayString (const char *str)
TempArgs.FileName = _FileName; TempArgs.FileName = _FileName;
TempArgs.Line = _Line; TempArgs.Line = _Line;
TempArgs.FuncName = _FuncName; TempArgs.FuncName = _FuncName;
TempArgs.CallstackAndLog = ""; TempArgs.CallstackAndLog.clear();
TempString = str; TempString = str;
} }
@ -281,7 +281,7 @@ void CLog::displayString (const char *str)
localargs.FileName = _FileName; localargs.FileName = _FileName;
localargs.Line = _Line; localargs.Line = _Line;
localargs.FuncName = _FuncName; localargs.FuncName = _FuncName;
localargs.CallstackAndLog = ""; localargs.CallstackAndLog.clear();
disp = str; disp = str;
args = &localargs; args = &localargs;
@ -314,7 +314,7 @@ void CLog::displayString (const char *str)
(*idi)->display( *args, disp ); (*idi)->display( *args, disp );
} }
} }
TempString = ""; TempString.clear();
unsetPosition(); unsetPosition();
} }

View file

@ -1777,19 +1777,29 @@ std::string CFileContainer::getWindowsDirectory()
#endif #endif
} }
std::string CPath::getApplicationDirectory(const std::string &appName) std::string CPath::getApplicationDirectory(const std::string &appName, bool local)
{ {
return getInstance()->_FileContainer.getApplicationDirectory(appName); return getInstance()->_FileContainer.getApplicationDirectory(appName, local);
} }
std::string CFileContainer::getApplicationDirectory(const std::string &appName) std::string CFileContainer::getApplicationDirectory(const std::string &appName, bool local)
{ {
static std::string appPath; static std::string appPaths[2];
std::string &appPath = appPaths[local ? 1 : 0];
if (appPath.empty()) if (appPath.empty())
{ {
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
wchar_t buffer[MAX_PATH]; wchar_t buffer[MAX_PATH];
#ifdef CSIDL_LOCAL_APPDATA
if (local)
{
SHGetSpecialFolderPathW(NULL, buffer, CSIDL_LOCAL_APPDATA, TRUE);
}
else
#endif
{
SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, TRUE); SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, TRUE);
}
appPath = CPath::standardizePath(ucstring((ucchar*)buffer).toUtf8()); appPath = CPath::standardizePath(ucstring((ucchar*)buffer).toUtf8());
#elif defined(NL_OS_MAC) #elif defined(NL_OS_MAC)
appPath = CPath::standardizePath(getenv("HOME")); appPath = CPath::standardizePath(getenv("HOME"));
@ -2568,13 +2578,13 @@ std::string CPath::makePathAbsolute( const std::string &relativePath, const std:
{ {
absolutePath = relativePath; absolutePath = relativePath;
} }
#else else
// Unix filesystem absolute path #endif
// Unix filesystem absolute path (works also under Windows)
if (relativePath[0] == '/') if (relativePath[0] == '/')
{ {
absolutePath = relativePath; absolutePath = relativePath;
} }
#endif
else else
{ {
// Add a slash to the directory if necessary. // Add a slash to the directory if necessary.
@ -2600,14 +2610,15 @@ std::string CPath::makePathAbsolute( const std::string &relativePath, const std:
// Now build the new absolute path // Now build the new absolute path
absolutePath += relativePath; absolutePath += relativePath;
absolutePath = standardizePath(absolutePath, true);
} }
absolutePath = standardizePath(absolutePath, true);
if (simplify) if (simplify)
{ {
// split all components path to manage parent directories // split all components path to manage parent directories
std::vector<std::string> tokens; std::vector<std::string> tokens;
explode(absolutePath, std::string("/"), tokens, true); explode(absolutePath, std::string("/"), tokens, false);
std::vector<std::string> directoryParts; std::vector<std::string> directoryParts;
@ -2639,7 +2650,10 @@ std::string CPath::makePathAbsolute( const std::string &relativePath, const std:
// rebuild the whole absolute path // rebuild the whole absolute path
for(uint i = 1, len = directoryParts.size(); i < len; ++i) for(uint i = 1, len = directoryParts.size(); i < len; ++i)
{
if (!directoryParts[i].empty())
absolutePath += "/" + directoryParts[i]; absolutePath += "/" + directoryParts[i];
}
// add trailing slash // add trailing slash
absolutePath += "/"; absolutePath += "/";

View file

@ -555,7 +555,7 @@ string CSheetId::toString(bool ifNotFoundUseNumericId) const
} }
else else
{ {
return NLMISC::toString( "<Sheet %d not found in sheet_id.bin>", _Id.Id ); return NLMISC::toString( "<Sheet %u not found in sheet_id.bin>", _Id.Id );
} }
} }

View file

@ -136,7 +136,7 @@ else:
needUpdateBnp = needUpdateDirNoSubdirFile(log, sourcePath, targetBnp) needUpdateBnp = needUpdateDirNoSubdirFile(log, sourcePath, targetBnp)
if (needUpdateBnp): if (needUpdateBnp):
printLog(log, "BNP " + targetBnp) printLog(log, "BNP " + targetBnp)
subprocess.call([ BnpMake, "/p", sourcePath, targetPath ] + package[1]) subprocess.call([ BnpMake, "-p", sourcePath, "-o", targetBnp ] + package[1][1:])
else: else:
printLog(log, "SKIP " + targetBnp) printLog(log, "SKIP " + targetBnp)
printLog(log, "") printLog(log, "")

View file

@ -134,8 +134,8 @@ int main(int argc, char **argv)
args.addArg("u", "unpack", "", "Unpack the BNP file to a directory"); args.addArg("u", "unpack", "", "Unpack the BNP file to a directory");
args.addArg("l", "list", "", "List the files contained in the BNP file"); args.addArg("l", "list", "", "List the files contained in the BNP file");
args.addArg("o", "output", "destination", "Output directory or file"); args.addArg("o", "output", "destination", "Output directory or file");
args.addArg("i", "if", "wildcard", "Add the file if it matches the wilcard (at least one 'if' conditions must be met for a file to be adding)"); args.addArg("i", "if", "wildcard", "Add the file if it matches the wilcard (at least one 'if' conditions must be met for a file to be adding)", false);
args.addArg("n", "ifnot", "wildcard", "Add the file if it doesn't match the wilcard (all the 'ifnot' conditions must be met for a file to be adding)"); args.addArg("n", "ifnot", "wildcard", "Add the file if it doesn't match the wilcard (all the 'ifnot' conditions must be met for a file to be adding)", false);
args.addAdditionalArg("input", "Input directory or BNP file depending on command"); args.addAdditionalArg("input", "Input directory or BNP file depending on command");
if (!args.parse(argc, argv)) return 1; if (!args.parse(argc, argv)) return 1;

View file

@ -114,6 +114,20 @@ int main(int argc, char *argv[])
// init Nel context // init Nel context
new NLMISC::CApplicationContext; new NLMISC::CApplicationContext;
// disable nldebug messages in logs in Release
#ifdef NL_RELEASE
NLMISC::DisableNLDebug = true;
#endif
NLMISC::createDebug(NULL);
#ifndef NL_DEBUG
NLMISC::INelContext::getInstance().getDebugLog()->removeDisplayer("DEFAULT_SD");
NLMISC::INelContext::getInstance().getInfoLog()->removeDisplayer("DEFAULT_SD");
NLMISC::INelContext::getInstance().getWarningLog()->removeDisplayer("DEFAULT_SD");
NLMISC::INelContext::getInstance().getErrorLog()->removeDisplayer("DEFAULT_SD");
#endif // NL_DEBUG
bool noerrors = false; bool noerrors = false;
try try

View file

@ -19,6 +19,7 @@
#include "ut_misc_co_task.h" #include "ut_misc_co_task.h"
#include "ut_misc_command.h" #include "ut_misc_command.h"
#include "ut_misc_common.h"
#include "ut_misc_config_file.h" #include "ut_misc_config_file.h"
#include "ut_misc_debug.h" #include "ut_misc_debug.h"
#include "ut_misc_dynlibload.h" #include "ut_misc_dynlibload.h"
@ -38,6 +39,7 @@ struct CUTMisc : public Test::Suite
{ {
add(auto_ptr<Test::Suite>(new CUTMiscCoTask)); add(auto_ptr<Test::Suite>(new CUTMiscCoTask));
add(auto_ptr<Test::Suite>(new CUTMiscCommand)); add(auto_ptr<Test::Suite>(new CUTMiscCommand));
add(auto_ptr<Test::Suite>(new CUTMiscCommon));
add(auto_ptr<Test::Suite>(new CUTMiscConfigFile)); add(auto_ptr<Test::Suite>(new CUTMiscConfigFile));
add(auto_ptr<Test::Suite>(new CUTMiscDebug)); add(auto_ptr<Test::Suite>(new CUTMiscDebug));
add(auto_ptr<Test::Suite>(new CUTMiscDynLibLoad)); add(auto_ptr<Test::Suite>(new CUTMiscDynLibLoad));

View file

@ -0,0 +1,171 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef UT_MISC_COMMON
#define UT_MISC_COMMON
#include <limits>
#include <nel/misc/common.h>
struct CUTMiscCommon : public Test::Suite
{
CUTMiscCommon()
{
TEST_ADD(CUTMiscCommon::bytesToHumanReadableUnits);
TEST_ADD(CUTMiscCommon::humanReadableToBytes);
// Add a line here when adding a new test METHOD
}
void bytesToHumanReadableUnits()
{
std::vector<std::string> units;
std::string res;
// no unit, returns an empty string
res = NLMISC::bytesToHumanReadableUnits(0, units);
TEST_ASSERT(res.empty());
// support bytes
units.push_back("B");
// 0 bytes
res = NLMISC::bytesToHumanReadableUnits(0, units);
TEST_ASSERT(res == "0 B");
// 1000 bytes in B
res = NLMISC::bytesToHumanReadableUnits(1000, units);
TEST_ASSERT(res == "1000 B");
// 1024 bytes in B
res = NLMISC::bytesToHumanReadableUnits(1024, units);
TEST_ASSERT(res == "1024 B");
// support kibibytes
units.push_back("KiB");
// 1000 bytes in B or KiB
res = NLMISC::bytesToHumanReadableUnits(1000, units);
TEST_ASSERT(res == "1000 B");
// 1024 bytes in B or KiB
res = NLMISC::bytesToHumanReadableUnits(1024, units);
TEST_ASSERT(res == "1024 B");
// 1 MB in B or KiB
res = NLMISC::bytesToHumanReadableUnits(1000 * 1000, units);
TEST_ASSERT(res == "976 KiB");
// 1 MiB in B or KiB
res = NLMISC::bytesToHumanReadableUnits(1024 * 1024, units);
TEST_ASSERT(res == "1024 KiB");
// 1 GB in B or KiB
res = NLMISC::bytesToHumanReadableUnits(1000 * 1000 * 1000, units);
TEST_ASSERT(res == "976562 KiB");
// 1 GiB in B or KiB
res = NLMISC::bytesToHumanReadableUnits(1024 * 1024 * 1024, units);
TEST_ASSERT(res == "1048576 KiB");
// support mebibytes
units.push_back("MiB");
// 1 GB in B, KiB or MiB
res = NLMISC::bytesToHumanReadableUnits(1000 * 1000 * 1000, units);
TEST_ASSERT(res == "953 MiB");
// 1 GiB in B, KiB or MiB
res = NLMISC::bytesToHumanReadableUnits(1024 * 1024 * 1024, units);
TEST_ASSERT(res == "1024 MiB");
}
void humanReadableToBytes()
{
uint64 bytes = 0;
// kiB is a wrong unit
bytes = NLMISC::humanReadableToBytes("1kiB");
TEST_ASSERT(bytes == 1);
// 1 kibibyte
bytes = NLMISC::humanReadableToBytes("1KiB");
TEST_ASSERT(bytes == 1024);
// 1 mebibyte
bytes = NLMISC::humanReadableToBytes("1MiB");
TEST_ASSERT(bytes == 1024*1024);
// 1 kilobyte
bytes = NLMISC::humanReadableToBytes("1KB");
TEST_ASSERT(bytes == 1000);
// 1 kilobyte
bytes = NLMISC::humanReadableToBytes("1kB");
TEST_ASSERT(bytes == 1000);
// 1 megabyte
bytes = NLMISC::humanReadableToBytes("1MB");
TEST_ASSERT(bytes == 1000*1000);
// 1 byte
bytes = NLMISC::humanReadableToBytes("1B");
TEST_ASSERT(bytes == 1);
// 1 byte
bytes = NLMISC::humanReadableToBytes("1");
TEST_ASSERT(bytes == 1);
// kiB is a wrong unit
bytes = NLMISC::humanReadableToBytes("1 kiB");
TEST_ASSERT(bytes == 1);
// 1 kibibyte
bytes = NLMISC::humanReadableToBytes("1 KiB");
TEST_ASSERT(bytes == 1024);
// 1 mebibyte
bytes = NLMISC::humanReadableToBytes("1 MiB");
TEST_ASSERT(bytes == 1024*1024);
// 1 kilobyte
bytes = NLMISC::humanReadableToBytes("1 KB");
TEST_ASSERT(bytes == 1000);
// 1 kilobyte
bytes = NLMISC::humanReadableToBytes("1 kB");
TEST_ASSERT(bytes == 1000);
// 1 megabyte
bytes = NLMISC::humanReadableToBytes("1 MB");
TEST_ASSERT(bytes == 1000*1000);
// 1 byte
bytes = NLMISC::humanReadableToBytes("1 B");
TEST_ASSERT(bytes == 1);
// not a number
bytes = NLMISC::humanReadableToBytes("AB");
TEST_ASSERT(bytes == 0);
// not a positive number
bytes = NLMISC::humanReadableToBytes("-1 B");
TEST_ASSERT(bytes == 0);
}
};
#endif

View file

@ -444,11 +444,13 @@ struct CUTMiscStringCommon : public Test::Suite
// min limit -1, unable to compare with minimum value because no lower type // min limit -1, unable to compare with minimum value because no lower type
ret = NLMISC::fromString("-9223372036854775809", val); ret = NLMISC::fromString("-9223372036854775809", val);
TEST_ASSERT(ret && val == std::numeric_limits<sint64>::max()); // with GCC, it returns min, with VC++ it returns max
TEST_ASSERT(ret && (val == std::numeric_limits<sint64>::max() || std::numeric_limits<sint64>::min()));
// max limit +1, unable to compare with maximum value because no higher type // max limit +1, unable to compare with maximum value because no higher type
ret = NLMISC::fromString("9223372036854775808", val); ret = NLMISC::fromString("9223372036854775808", val);
TEST_ASSERT(ret && val == std::numeric_limits<sint64>::min()); // with GCC, it returns max with VC++ it returns min
TEST_ASSERT(ret && (val == std::numeric_limits<sint64>::min() || std::numeric_limits<sint64>::max()));
// with period // with period
ret = NLMISC::fromString("1.2", val); ret = NLMISC::fromString("1.2", val);
@ -508,7 +510,8 @@ struct CUTMiscStringCommon : public Test::Suite
// max limit +1, unable to compare with maximum value because no higher type // max limit +1, unable to compare with maximum value because no higher type
ret = NLMISC::fromString("18446744073709551616", val); ret = NLMISC::fromString("18446744073709551616", val);
TEST_ASSERT(ret && val == std::numeric_limits<uint64>::min()); // with GCC, it returns max with VC++ it returns min
TEST_ASSERT(ret && (val == std::numeric_limits<uint64>::min() || val == std::numeric_limits<uint64>::max()));
// with period // with period
ret = NLMISC::fromString("1.2", val); ret = NLMISC::fromString("1.2", val);
@ -682,60 +685,59 @@ struct CUTMiscStringCommon : public Test::Suite
// tests for bool // tests for bool
bool val; bool val;
// true value // true values
val = false;
ret = NLMISC::fromString("1", val); ret = NLMISC::fromString("1", val);
TEST_ASSERT(val); TEST_ASSERT(ret && val);
TEST_ASSERT_MSG(ret, "should succeed");
val = false; ret = NLMISC::fromString("t", val);
NLMISC::fromString("t", val); TEST_ASSERT(ret && val);
TEST_ASSERT(val);
val = false; ret = NLMISC::fromString("y", val);
NLMISC::fromString("y", val); TEST_ASSERT(ret && val);
TEST_ASSERT(val);
val = false; ret = NLMISC::fromString("T", val);
NLMISC::fromString("T", val); TEST_ASSERT(ret && val);
TEST_ASSERT(val);
val = false; ret = NLMISC::fromString("Y", val);
NLMISC::fromString("Y", val); TEST_ASSERT(ret && val);
TEST_ASSERT(val);
val = true; ret = NLMISC::fromString("true", val);
TEST_ASSERT(ret && val);
ret = NLMISC::fromString("yes", val);
TEST_ASSERT(ret && val);
// false values
ret = NLMISC::fromString("0", val); ret = NLMISC::fromString("0", val);
TEST_ASSERT(!val); TEST_ASSERT(ret && !val);
TEST_ASSERT_MSG(ret, "should succeed");
val = true; ret = NLMISC::fromString("f", val);
NLMISC::fromString("f", val); TEST_ASSERT(ret && !val);
TEST_ASSERT(!val);
val = true; ret = NLMISC::fromString("n", val);
NLMISC::fromString("n", val); TEST_ASSERT(ret && !val);
TEST_ASSERT(!val);
val = true; ret = NLMISC::fromString("F", val);
NLMISC::fromString("F", val); TEST_ASSERT(ret && !val);
TEST_ASSERT(!val);
val = true; ret = NLMISC::fromString("N", val);
NLMISC::fromString("N", val); TEST_ASSERT(ret && !val);
TEST_ASSERT(!val);
ret = NLMISC::fromString("false", val);
TEST_ASSERT(ret && !val);
ret = NLMISC::fromString("no", val);
TEST_ASSERT(ret && !val);
// wrong values
ret = NLMISC::fromString("YES", val);
TEST_ASSERT(!ret && !val);
ret = NLMISC::fromString("foo", val);
TEST_ASSERT(!ret && !val);
// bad character
ret = NLMISC::fromString("a", val); ret = NLMISC::fromString("a", val);
TEST_ASSERT_MSG(!ret, "should not succeed"); TEST_ASSERT(!ret && !val);
val = true;
NLMISC::fromString("a", val);
TEST_ASSERT_MSG(val, "should not modify the value");
val = false;
NLMISC::fromString("a", val);
TEST_ASSERT_MSG(!val, "should not modify the value");
} }
}; };

View file

@ -3,7 +3,6 @@ ADD_SUBDIRECTORY(src)
IF(WITH_RYZOM_CLIENT) IF(WITH_RYZOM_CLIENT)
#ADD_SUBDIRECTORY(data) #ADD_SUBDIRECTORY(data)
#ADD_SUBDIRECTORY(patcher)
IF(UNIX AND NOT APPLE) IF(UNIX AND NOT APPLE)
ADD_SUBDIRECTORY(unix) ADD_SUBDIRECTORY(unix)

View file

@ -265,7 +265,7 @@
fontsize="10" fontsize="10"
line_maxw="182" line_maxw="182"
shadow="true" shadow="true"
hardtext="No File..." /> hardtext="uiNoFiles" />
</group> </group>
</group> </group>
<tree node="mp3_player" /> <tree node="mp3_player" />

View file

@ -183,7 +183,7 @@
posref="BL BL" posref="BL BL"
scale="true" scale="true"
y="4" y="4"
w="110" w="130"
h="2" h="2"
texture="W_line_hor2.tga" /> texture="W_line_hor2.tga" />
<view type="text" <view type="text"
@ -202,7 +202,7 @@
posref="MM MM" posref="MM MM"
x="0" x="0"
y="-1" y="-1"
w="110" w="130"
h="8" h="8"
vertical="false" vertical="false"
align="L" align="L"
@ -246,7 +246,7 @@
posref="BL BL" posref="BL BL"
scale="true" scale="true"
y="4" y="4"
w="110" w="130"
h="2" h="2"
texture="W_line_hor2.tga" /> texture="W_line_hor2.tga" />
<view type="text" <view type="text"
@ -265,7 +265,7 @@
posref="MM MM" posref="MM MM"
x="0" x="0"
y="-1" y="-1"
w="110" w="130"
h="8" h="8"
vertical="false" vertical="false"
align="L" align="L"
@ -3441,7 +3441,7 @@
widget="sbint" widget="sbint"
link="UI:SAVE:CHAT:FONT_SIZE" link="UI:SAVE:CHAT:FONT_SIZE"
min="9" min="9"
max="14" max="20"
realtime="true" /> realtime="true" />
<param ui="entity_colors:cc_user:c" <param ui="entity_colors:cc_user:c"
type="db" type="db"

View file

@ -361,11 +361,11 @@ on_enter="leave_modal" options="no_bordure" mouse_pos="false" exit_key_pushed="t
fontsize="10" shadow="true" hardtext="uiOnPatchOpt" /> fontsize="10" shadow="true" hardtext="uiOnPatchOpt" />
<group id="global_patch" w="382" h="22" posparent="global_win" posref="MM MM" > <group id="global_patch" w="382" h="22" posparent="global_win" posref="MM MM" >
<view type="text" id="name" posref="BL BL" fontsize="12" x="2" y="0" color="135 243 28 255" shadow="true" hardtext="TOTAL PATCH" /> <view type="text" id="name" posref="BL BL" fontsize="12" x="2" y="0" color="135 243 28 255" shadow="true" hardtext="uiTotalPatch" />
<view type="text" id="size" posref="BR BR" fontsize="12" x="-8" y="0" color="135 243 28 255" shadow="true" hardtext="...Kbs" /> <view type="text" id="size" posref="BR BR" fontsize="12" x="-8" y="0" color="135 243 28 255" shadow="true" hardtext="...Kbs" />
</group> </group>
<group id="nonopt_patch" w="382" h="22" posparent="nonopt_win" posref="MM MM" > <group id="nonopt_patch" w="382" h="22" posparent="nonopt_win" posref="MM MM" >
<view type="text" id="name" posref="BL BL" fontsize="12" x="2" y="0" color="135 243 28 255" shadow="true" hardtext="NON OPTIONAL FILES" /> <view type="text" id="name" posref="BL BL" fontsize="12" x="2" y="0" color="135 243 28 255" shadow="true" hardtext="uiRequiredFiles" />
<view type="text" id="size" posref="BR BR" fontsize="12" x="-8" y="0" color="135 243 28 255" shadow="true" hardtext="...Kbs" /> <view type="text" id="size" posref="BR BR" fontsize="12" x="-8" y="0" color="135 243 28 255" shadow="true" hardtext="...Kbs" />
</group> </group>

View file

@ -1,14 +1,15 @@
# Need clientsheets lib for sheets packer tool # Need clientsheets lib for sheets packer tool
ADD_SUBDIRECTORY(client_sheets) ADD_SUBDIRECTORY(client_sheets)
IF(WITH_RYZOM_CLIENT) # Need seven_zip lib for patch_gen tool
# These are Windows/MFC apps
SET(SEVENZIP_LIBRARY "ryzom_sevenzip")
ADD_SUBDIRECTORY(seven_zip) ADD_SUBDIRECTORY(seven_zip)
IF(WITH_RYZOM_CLIENT)
# Patch should never be enabled on Steam # Patch should never be enabled on Steam
IF(WITH_RYZOM_PATCH AND NOT WITH_RYZOM_STEAM) IF(WITH_RYZOM_STEAM)
ADD_DEFINITIONS(-DRZ_USE_STEAM)
FIND_PACKAGE(Steam)
ELSEIF(WITH_RYZOM_PATCH)
ADD_DEFINITIONS(-DRZ_USE_PATCH) ADD_DEFINITIONS(-DRZ_USE_PATCH)
IF(WITH_RYZOM_CUSTOM_PATCH_SERVER) IF(WITH_RYZOM_CUSTOM_PATCH_SERVER)
@ -115,6 +116,15 @@ IF(WITH_RYZOM_CLIENT)
ENDIF() ENDIF()
ENDIF() ENDIF()
IF(WITH_RYZOM_STEAM AND STEAM_RUNTIME)
ADD_CUSTOM_COMMAND(TARGET ryzom_client POST_BUILD COMMAND cp -p ${STEAM_RUNTIME} ${RYZOM_CONTENTS_DIR}/MacOS)
IF(CODESIGN_ALLOCATE AND APPLE_CERTIFICATE)
ADD_CUSTOM_COMMAND(TARGET ryzom_client POST_BUILD COMMAND CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign --no-strict -fs "${APPLE_CERTIFICATE}" "${RYZOM_CONTENTS_DIR}/MacOS/${STEAM_RUNTIMENAME}" COMMENT "Signing Steam client runtime...")
ENDIF()
ENDIF()
IF(CODESIGN_ALLOCATE AND APPLE_CERTIFICATE) IF(CODESIGN_ALLOCATE AND APPLE_CERTIFICATE)
ADD_CUSTOM_COMMAND(TARGET khanat_client POST_BUILD COMMAND CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign -fs "${APPLE_CERTIFICATE}" "${RYZOM_OUTPUT_DIR}" COMMENT "Signing Ryzom bundle...") ADD_CUSTOM_COMMAND(TARGET khanat_client POST_BUILD COMMAND CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign -fs "${APPLE_CERTIFICATE}" "${RYZOM_OUTPUT_DIR}" COMMENT "Signing Ryzom bundle...")
ENDIF() ENDIF()
@ -129,6 +139,10 @@ IF(WITH_RYZOM_CLIENT)
${ZLIB_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
) )
IF(STEAM_FOUND)
INCLUDE_DIRECTORIES(${STEAM_INCLUDE_DIRS})
ENDIF()
TARGET_LINK_LIBRARIES(khanat_client TARGET_LINK_LIBRARIES(khanat_client
nelmisc nelmisc
nelnet nelnet
@ -137,13 +151,13 @@ IF(WITH_RYZOM_CLIENT)
nel3d nel3d
nelgui nelgui
nelsound nelsound
ryzom_sevenzip
ryzom_clientsheets ryzom_clientsheets
ryzom_gameshare ryzom_gameshare
nelpacs nelpacs
${LUA_LIBRARIES} ${LUA_LIBRARIES}
${LUABIND_LIBRARIES} ${LUABIND_LIBRARIES}
${CURL_LIBRARIES} ${CURL_LIBRARIES}
${SEVENZIP_LIBRARY}
) )
ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS})

View file

@ -62,6 +62,10 @@
#include "client_cfg.h" #include "client_cfg.h"
#include "far_tp.h" #include "far_tp.h"
#ifdef RZ_USE_STEAM
#include "steam_client.h"
#endif
/////////// ///////////
// USING // // USING //
/////////// ///////////
@ -319,6 +323,13 @@ int main(int argc, char **argv)
prelogInit(); prelogInit();
RYZOM_CATCH("Pre-Login Init") RYZOM_CATCH("Pre-Login Init")
#ifdef RZ_USE_STEAM
CSteamClient steamClient;
if (steamClient.init())
LoginCustomParameters = "&steam_auth_session_ticket=" + steamClient.getAuthSessionTicket();
#endif
// Log the client and choose from shard // Log the client and choose from shard
RYZOM_TRY("Login") RYZOM_TRY("Login")
if (!ClientCfg.Local && (ClientCfg.TestBrowser || ClientCfg.FSHost.empty())) if (!ClientCfg.Local && (ClientCfg.TestBrowser || ClientCfg.FSHost.empty()))

View file

@ -659,7 +659,7 @@ static void addPaths(IProgressCallback &progress, const std::vector<std::string>
std::vector<std::string> directoryPrefixes; std::vector<std::string> directoryPrefixes;
// current directory has priority everywhere // current directory has priority everywhere
directoryPrefixes.push_back(""); directoryPrefixes.push_back(CPath::standardizePath(CPath::getCurrentPath()));
#if defined(NL_OS_WINDOWS) #if defined(NL_OS_WINDOWS)
// check in same directory as executable // check in same directory as executable
@ -678,12 +678,9 @@ static void addPaths(IProgressCallback &progress, const std::vector<std::string>
if (CFile::isDirectory(getRyzomSharePrefix())) directoryPrefixes.push_back(CPath::standardizePath(getRyzomSharePrefix())); if (CFile::isDirectory(getRyzomSharePrefix())) directoryPrefixes.push_back(CPath::standardizePath(getRyzomSharePrefix()));
#endif #endif
std::vector<std::string> directoriesToProcess; std::map<std::string, sint> directoriesToProcess;
// reserve maximum memory space for all combinations // first pass, build a map with all existing directories to process in second pass
directoriesToProcess.reserve(directoryPrefixes.size() * paths.size());
// first pass, build a vector with all existing directories to process in second pass
for (uint j = 0; j < directoryPrefixes.size(); j++) for (uint j = 0; j < directoryPrefixes.size(); j++)
{ {
std::string directoryPrefix = directoryPrefixes[j]; std::string directoryPrefix = directoryPrefixes[j];
@ -698,15 +695,17 @@ static void addPaths(IProgressCallback &progress, const std::vector<std::string>
// only process existing directories // only process existing directories
if (CFile::isExists(directory)) if (CFile::isExists(directory))
directoriesToProcess.push_back(directory); directoriesToProcess[directory] = 1;
} }
} }
uint total = (uint)directoriesToProcess.size(); uint total = (uint)directoriesToProcess.size();
uint current = 0, next = 0; uint current = 0, next = 0;
std::map<std::string, sint>::const_iterator it = directoriesToProcess.begin(), iend = directoriesToProcess.end();
// second pass, add search paths // second pass, add search paths
for (uint i = 0, len = directoriesToProcess.size(); i < len; ++i) while (it != iend)
{ {
// update next progress value // update next progress value
++next; ++next;
@ -717,9 +716,11 @@ static void addPaths(IProgressCallback &progress, const std::vector<std::string>
// next is current value // next is current value
current = next; current = next;
CPath::addSearchPath(directoriesToProcess[i], recurse, false, &progress); CPath::addSearchPath(it->first, recurse, false, &progress);
progress.popCropedValues(); progress.popCropedValues();
++it;
} }
} }

View file

@ -112,7 +112,7 @@ bool InitMouseWithCursor (bool hardware)
} }
else if (width != 0 && height != 0) else if (width != 0 && height != 0)
{ {
nlwarning("mouse pos %u, %u", x, y); nlwarning("Mouse pos %f, %f", x, y);
Driver->setMousePos(x / width, y / height); Driver->setMousePos(x / width, y / height);
} }
} }

View file

@ -77,7 +77,7 @@ extern bool SetMousePosFirstTime;
vector<CShard> Shards; vector<CShard> Shards;
string LoginLogin, LoginPassword, ClientApp, Salt; string LoginLogin, LoginPassword, ClientApp, Salt, LoginCustomParameters;
uint32 LoginShardId = 0xFFFFFFFF; uint32 LoginShardId = 0xFFFFFFFF;
@ -1169,7 +1169,7 @@ void onlogin(bool vanishScreen = true)
// Check the login/pass // Check the login/pass
// main menu page for r2mode // main menu page for r2mode
string res = checkLogin(LoginLogin, LoginPassword, ClientApp); string res = checkLogin(LoginLogin, LoginPassword, ClientApp, LoginCustomParameters);
if (res.empty()) if (res.empty())
{ {
// if not in auto login, push login ok event // if not in auto login, push login ok event
@ -2738,7 +2738,7 @@ REGISTER_ACTION_HANDLER (CAHOnBackToLogin, "on_back_to_login");
// *************************************************************************** // ***************************************************************************
string checkLogin(const string &login, const string &password, const string &clientApp) string checkLogin(const string &login, const string &password, const string &clientApp, const std::string &customParameters)
{ {
CPatchManager *pPM = CPatchManager::getInstance(); CPatchManager *pPM = CPatchManager::getInstance();
Shards.clear(); Shards.clear();
@ -2795,7 +2795,7 @@ string checkLogin(const string &login, const string &password, const string &cli
{ {
// R2 login sequence // R2 login sequence
std::string cryptedPassword = CCrypt::crypt(password, Salt); std::string cryptedPassword = CCrypt::crypt(password, Salt);
if(!HttpClient.sendGet(ClientCfg.ConfigFile.getVar("StartupPage").asString()+"?cmd=login&login="+login+"&password="+cryptedPassword+"&clientApplication="+clientApp+"&cp=1"+"&lg="+ClientCfg.LanguageCode)) if(!HttpClient.sendGet(ClientCfg.ConfigFile.getVar("StartupPage").asString()+"?cmd=login&login="+login+"&password="+cryptedPassword+"&clientApplication="+clientApp+"&cp=1"+"&lg="+ClientCfg.LanguageCode+customParameters))
return "Can't send (error code 2)"; return "Can't send (error code 2)";
// the response should contains the result code and the cookie value // the response should contains the result code and the cookie value

View file

@ -46,7 +46,7 @@ struct CShard
std::string EmergencyPatchURL; std::string EmergencyPatchURL;
}; };
extern std::string LoginLogin, LoginPassword; extern std::string LoginLogin, LoginPassword, LoginCustomParameters;
extern uint32 LoginShardId; extern uint32 LoginShardId;
@ -54,7 +54,7 @@ extern uint32 AvailablePatchs;
std::string checkLogin(const std::string &login, const std::string &password, const std::string &clientApp); std::string checkLogin(const std::string &login, const std::string &password, const std::string &clientApp, const std::string &customParameters = "");
std::string selectShard(uint32 shardId, std::string &cookie, std::string &addr); std::string selectShard(uint32 shardId, std::string &cookie, std::string &addr);
std::string getBGDownloaderCommandLine(); std::string getBGDownloaderCommandLine();

View file

@ -47,6 +47,7 @@
#include "nel/misc/sha1.h" #include "nel/misc/sha1.h"
#include "nel/misc/big_file.h" #include "nel/misc/big_file.h"
#include "nel/misc/i18n.h" #include "nel/misc/i18n.h"
#include "nel/misc/cmd_args.h"
#include "game_share/bg_downloader_msg.h" #include "game_share/bg_downloader_msg.h"
@ -54,6 +55,7 @@
#include "login.h" #include "login.h"
#include "user_agent.h" #include "user_agent.h"
#include "seven_zip/seven_zip.h"
#ifndef RY_BG_DOWNLOADER #ifndef RY_BG_DOWNLOADER
#include "client_cfg.h" #include "client_cfg.h"
@ -88,6 +90,8 @@ extern string R2ServerVersion;
std::string TheTmpInstallDirectory = "patch/client_install"; std::string TheTmpInstallDirectory = "patch/client_install";
#endif #endif
extern NLMISC::CCmdArgs Args;
// **************************************************************************** // ****************************************************************************
// **************************************************************************** // ****************************************************************************
// **************************************************************************** // ****************************************************************************
@ -119,8 +123,16 @@ CPatchManager::CPatchManager() : State("t_state"), DataScanState("t_data_scan_st
UpdateBatchFilename = "updt_nl.sh"; UpdateBatchFilename = "updt_nl.sh";
#endif #endif
// use current directory by default // use application directory by default
setClientRootPath("./"); std::string rootPath = Args.getProgramPath();
if (!CFile::fileExists(rootPath + "client_default.cfg"))
{
// use current directory
rootPath = CPath::getCurrentPath();
}
setClientRootPath(rootPath);
VerboseLog = true; VerboseLog = true;
@ -707,7 +719,7 @@ void CPatchManager::stopPatchThread()
// **************************************************************************** // ****************************************************************************
void CPatchManager::deleteBatchFile() void CPatchManager::deleteBatchFile()
{ {
deleteFile(UpdateBatchFilename, false, false); deleteFile(ClientRootPath + UpdateBatchFilename, false, false);
} }
// **************************************************************************** // ****************************************************************************
@ -715,29 +727,12 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool
{ {
uint nblab = 0; uint nblab = 0;
FILE *fp = NULL; std::string content;
if (useBatchFile)
{
deleteBatchFile();
fp = fopen (UpdateBatchFilename.c_str(), "wt");
if (fp == 0)
{
string err = toString("Can't open file '%s' for writing: code=%d %s (error code 29)", UpdateBatchFilename.c_str(), errno, strerror(errno));
throw Exception (err);
}
//use bat if windows if not use sh
#ifdef NL_OS_WINDOWS
fprintf(fp, "@echo off\n");
#else
fprintf(fp, "#!/bin/sh\n");
#endif
}
// Unpack files with category ExtractPath non empty // Unpack files with category ExtractPath non empty
const CBNPCategorySet &rDescCats = descFile.getCategories(); const CBNPCategorySet &rDescCats = descFile.getCategories();
OptionalCat.clear(); OptionalCat.clear();
for (uint32 i = 0; i < rDescCats.categoryCount(); ++i) for (uint32 i = 0; i < rDescCats.categoryCount(); ++i)
{ {
// For all optional categories check if there is a 'file to patch' in it // For all optional categories check if there is a 'file to patch' in it
@ -757,11 +752,6 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool
} }
catch(...) catch(...)
{ {
if (useBatchFile)
{
fclose(fp);
}
throw; throw;
} }
@ -770,11 +760,6 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool
// TODO: handle exception? // TODO: handle exception?
string err = toString("Error unpacking %s", rFilename.c_str()); string err = toString("Error unpacking %s", rFilename.c_str());
if (useBatchFile)
{
fclose(fp);
}
throw Exception (err); throw Exception (err);
} }
else else
@ -786,39 +771,41 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool
NLMISC::CFile::createDirectoryTree(DstPath); NLMISC::CFile::createDirectoryTree(DstPath);
// this file must be moved // this file must be moved
if (useBatchFile)
{
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
SrcPath = CPath::standardizeDosPath(SrcPath); SrcPath = CPath::standardizeDosPath(SrcPath);
DstPath = CPath::standardizeDosPath(DstPath); DstPath = CPath::standardizeDosPath(DstPath);
#else
SrcPath = CPath::standardizePath(SrcPath);
DstPath = CPath::standardizePath(DstPath);
#endif #endif
}
std::string SrcName = SrcPath + vFilenames[fff]; std::string SrcName = SrcPath + vFilenames[fff];
std::string DstName = DstPath + vFilenames[fff]; std::string DstName = DstPath + vFilenames[fff];
if (useBatchFile) bool succeeded = false;
if (!useBatchFile)
{
// don't check result, because it's possible the olk file doesn't exist
CFile::deleteFile(DstName);
// try to move it, if fails move it later in a script
if (CFile::moveFile(DstName, SrcName))
succeeded = true;
}
// if we didn't succeed to delete or move the file, create a batch file anyway
if (!succeeded)
{ {
// write windows .bat format else write sh format // write windows .bat format else write sh format
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
fprintf(fp, ":loop%u\n", nblab); content += toString(":loop%u\n", nblab);
fprintf(fp, "attrib -r -a -s -h %s\n", DstName.c_str()); content += toString("attrib -r -a -s -h \"%s\"\n", DstName.c_str());
fprintf(fp, "del %s\n", DstName.c_str()); content += toString("del \"%s\"\n", DstName.c_str());
fprintf(fp, "if exist %s goto loop%u\n", DstName.c_str(), nblab); content += toString("if exist \"%s\" goto loop%u\n", DstName.c_str(), nblab);
fprintf(fp, "move %s %s\n", SrcName.c_str(), DstPath.c_str()); content += toString("move \"%s\" \"%s\"\n", SrcName.c_str(), DstPath.c_str());
#else #else
fprintf(fp, "rm -rf %s\n", DstName.c_str()); content += toString("rm -rf \"%s\"\n", DstName.c_str());
fprintf(fp, "mv %s %s\n", SrcName.c_str(), DstPath.c_str()); content += toString("mv %s \"%s\"\n", SrcName.c_str(), DstPath.c_str());
#endif #endif
} }
else
{
deleteFile(DstName);
CFile::moveFile(DstName, SrcName);
}
nblab++; nblab++;
} }
@ -826,58 +813,86 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool
} }
} }
std::string patchDirectory = CPath::standardizeDosPath(ClientRootPath + "patch");
// Finalize batch file // Finalize batch file
if (NLMISC::CFile::isExists("patch") && NLMISC::CFile::isDirectory("patch")) if (NLMISC::CFile::isExists(patchDirectory) && NLMISC::CFile::isDirectory(patchDirectory))
{ {
#ifdef NL_OS_WINDOWS std::string patchContent;
if (useBatchFile)
{
fprintf(fp, ":looppatch\n");
}
#endif
vector<string> vFileList; vector<string> vFileList;
CPath::getPathContent ("patch", false, false, true, vFileList, NULL, false); CPath::getPathContent (patchDirectory, false, false, true, vFileList, NULL, false);
for(uint32 i = 0; i < vFileList.size(); ++i) for(uint32 i = 0; i < vFileList.size(); ++i)
{ {
if (useBatchFile) bool succeeded = false;
if (!useBatchFile)
{
if (CFile::deleteFile(vFileList[i]))
succeeded = true;
}
// if we didn't succeed to delete, create a batch file anyway
if (!succeeded)
{ {
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
fprintf(fp, "del %s\n", CPath::standardizeDosPath(vFileList[i]).c_str()); patchContent += toString("del \"%s\"\n", CPath::standardizeDosPath(vFileList[i]).c_str());
#else #else
fprintf(fp, "rm -f %s\n", CPath::standardizePath(vFileList[i]).c_str()); patchContent += toString("rm -f \"%s\"\n", CPath::standardizePath(vFileList[i]).c_str());
#endif
}
}
if (!patchContent.empty())
{
#ifdef NL_OS_WINDOWS
content += toString(":looppatch\n");
content += patchContent;
content += toString("rd /Q /S \"" + patchDirectory + "\"\n");
content += toString("if exist \"" + patchDirectory + "\" goto looppatch\n");
#else
content += toString("rm -rf \"" + patchDirectory + "\"\n");
#endif #endif
} }
else else
{ {
CFile::deleteFile(vFileList[i]); CFile::deleteDirectory(patchDirectory);
} }
} }
if (useBatchFile) if (!content.empty())
{ {
deleteBatchFile();
std::string batchFilename = ClientRootPath + UpdateBatchFilename;
FILE *fp = fopen (batchFilename.c_str(), "wt");
if (fp == NULL)
{
string err = toString("Can't open file '%s' for writing: code=%d %s (error code 29)", batchFilename.c_str(), errno, strerror(errno));
throw Exception (err);
}
//use bat if windows if not use sh
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
fprintf(fp, "rd /Q /S patch\n"); fprintf(fp, "@echo off\n");
fprintf(fp, "if exist patch goto looppatch\n");
#else #else
fprintf(fp, "rm -rf patch\n"); fprintf(fp, "#!/bin/sh\n");
#endif #endif
}
else
{
CFile::deleteDirectory("patch");
}
}
if (useBatchFile) // append content of script
{ fprintf(fp, content.c_str());
if (wantRyzomRestart) if (wantRyzomRestart)
{ {
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
fprintf(fp, "start %s %%1 %%2 %%3\n", RyzomFilename.c_str()); fprintf(fp, "start \"\" \"%s\" %%1 %%2 %%3\n", CPath::standardizeDosPath(RyzomFilename).c_str());
#else #else
fprintf(fp, "%s $1 $2 $3\n", RyzomFilename.c_str()); fprintf(fp, "\"%s\" $1 $2 $3\n", RyzomFilename.c_str());
#endif #endif
} }
@ -886,11 +901,11 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool
fclose(fp); fclose(fp);
if (diskFull) if (diskFull)
{ {
throw NLMISC::EDiskFullError(UpdateBatchFilename.c_str()); throw NLMISC::EDiskFullError(batchFilename.c_str());
} }
if (writeError) if (writeError)
{ {
throw NLMISC::EWriteError(UpdateBatchFilename.c_str()); throw NLMISC::EWriteError(batchFilename.c_str());
} }
} }
} }
@ -902,93 +917,44 @@ void CPatchManager::executeBatchFile()
extern void quitCrashReport (); extern void quitCrashReport ();
quitCrashReport (); quitCrashReport ();
#ifdef NL_OS_WINDOWS
// Launch the batch file
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; // SW_SHOW
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
string strCmdLine;
bool r2Mode = false; bool r2Mode = false;
#ifndef RY_BG_DOWNLOADER #ifndef RY_BG_DOWNLOADER
r2Mode = ClientCfg.R2Mode; r2Mode = ClientCfg.R2Mode;
#endif #endif
if (r2Mode)
std::string batchFilename;
#ifdef NL_OS_WINDOWS
batchFilename = CPath::standardizeDosPath(ClientRootPath);
#else
batchFilename = ClientRootPath;
#endif
batchFilename += UpdateBatchFilename;
#ifdef NL_OS_UNIX
// make script executable under UNIX
chmod(batchFilename.c_str(), S_IRWXU);
#endif
std::string arguments = LoginLogin + " " + LoginPassword;
if (!r2Mode)
{ {
strCmdLine = UpdateBatchFilename + " " + LoginLogin + " " + LoginPassword; arguments += " " + toString(LoginShardId);
}
if (launchProgram(batchFilename, arguments, false))
{
exit(0);
} }
else else
{
strCmdLine = UpdateBatchFilename + " " + LoginLogin + " " + LoginPassword + " " + toString(LoginShardId);
}
if( !CreateProcess( NULL, // No module name (use command line).
(char*)strCmdLine.c_str(), // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{ {
// error occurs during the launch // error occurs during the launch
string str = toString("Can't execute '%s': code=%d %s (error code 30)", UpdateBatchFilename.c_str(), errno, strerror(errno)); string str = toString("Can't execute '%s': code=%d %s (error code 30)", batchFilename.c_str(), errno, strerror(errno));
throw Exception (str); throw Exception (str);
} }
// Close process and thread handles.
// CloseHandle( pi.hProcess );
// CloseHandle( pi.hThread );
#else
// Start the child process.
bool r2Mode = false;
#ifndef RY_BG_DOWNLOADER
r2Mode = ClientCfg.R2Mode;
#endif
string strCmdLine;
strCmdLine = "./" + UpdateBatchFilename;
chmod(strCmdLine.c_str(), S_IRWXU);
if (r2Mode)
{
if (execl(strCmdLine.c_str(), strCmdLine.c_str(), LoginLogin.c_str(), LoginPassword.c_str(), (char *) NULL) == -1)
{
int errsv = errno;
nlerror("Execl Error: %d %s", errsv, strCmdLine.c_str());
}
else
{
nlinfo("Ran batch file r2Mode Success");
}
}
else
{
if (execl(strCmdLine.c_str(), strCmdLine.c_str(), LoginLogin.c_str(), LoginPassword.c_str(), toString(LoginShardId).c_str(), (char *) NULL) == -1)
{
int errsv = errno;
nlerror("Execl r2mode Error: %d %s", errsv, strCmdLine.c_str());
}
else
{
nlinfo("Ran batch file Success");
}
}
#endif
// exit(0);
} }
// **************************************************************************** // ****************************************************************************
@ -1155,9 +1121,9 @@ void CPatchManager::readDescFile(sint32 nVersion)
std::string unpackTo = category.getUnpackTo(); std::string unpackTo = category.getUnpackTo();
if (unpackTo.substr(0, 2) == "./") if (unpackTo.substr(0, 1) == ".")
{ {
unpackTo = ClientRootPath + unpackTo.substr(2); unpackTo = CPath::makePathAbsolute(unpackTo, ClientRootPath, true);
category.setUnpackTo(unpackTo); category.setUnpackTo(unpackTo);
} }
} }
@ -1827,7 +1793,7 @@ void CPatchManager::MyPatchingCB::progress(float f)
{ {
CPatchManager *pPM = CPatchManager::getInstance(); CPatchManager *pPM = CPatchManager::getInstance();
double p = 100.0*f; double p = 100.0*f;
ucstring sTranslate = CI18N::get("uiApplyingDelta") + toString(" %s (%5.02f %%)", patchFilename.c_str(), p); ucstring sTranslate = CI18N::get("uiApplyingDelta") + toString(" %s (%5.02f %%)", CFile::getFilename(patchFilename).c_str(), p);
pPM->setState(false, sTranslate); pPM->setState(false, sTranslate);
} }
@ -2355,7 +2321,6 @@ void CPatchThread::run()
ucstring sTranslate; ucstring sTranslate;
try try
{ {
// First do all ref files // First do all ref files
// ---------------------- // ----------------------
@ -2428,7 +2393,6 @@ void CPatchThread::run()
pPM->deleteFile(pPM->UpdateBatchFilename, false, false); pPM->deleteFile(pPM->UpdateBatchFilename, false, false);
} }
if (!bErr) if (!bErr)
{ {
sTranslate = CI18N::get("uiPatchEndNoErr"); sTranslate = CI18N::get("uiPatchEndNoErr");
@ -2438,6 +2402,7 @@ void CPatchThread::run()
// Set a more explicit error message // Set a more explicit error message
pPM->setErrorMessage(sTranslate); pPM->setErrorMessage(sTranslate);
} }
PatchOk = !bErr; PatchOk = !bErr;
Ended = true; Ended = true;
} }
@ -2625,7 +2590,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP)
// try to unpack the file // try to unpack the file
try try
{ {
if (!CPatchManager::unpackLZMA(pPM->ClientPatchPath+lzmaFile, OutFilename+".tmp")) if (!unpackLZMA(pPM->ClientPatchPath+lzmaFile, OutFilename+".tmp"))
{ {
// fallback to standard patch method // fallback to standard patch method
usePatchFile = true; usePatchFile = true;
@ -2746,7 +2711,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP)
string OutFilename = pPM->ClientPatchPath + rFTP.FileName + ".tmp__" + toString(j); string OutFilename = pPM->ClientPatchPath + rFTP.FileName + ".tmp__" + toString(j);
sTranslate = CI18N::get("uiApplyingDelta") + " " + PatchName; sTranslate = CI18N::get("uiApplyingDelta") + " " + CFile::getFilename(PatchName);
pPM->setState(true, sTranslate); pPM->setState(true, sTranslate);
xDeltaPatch(PatchName, SourceNameXD, OutFilename); xDeltaPatch(PatchName, SourceNameXD, OutFilename);
@ -3087,7 +3052,7 @@ bool CPatchManager::download(const std::string& patchFullname, const std::string
&& patchName.substr(patchName.size() - zsStrLength) == zsStr) && patchName.substr(patchName.size() - zsStrLength) == zsStr)
{ {
std::string outFilename = patchName.substr(0, patchName.size() - zsStrLength); std::string outFilename = patchName.substr(0, patchName.size() - zsStrLength);
CPatchManager::unpack7Zip(patchName, outFilename); unpack7Zip(patchName, outFilename);
pPM->deleteFile(patchName); pPM->deleteFile(patchName);
pPM->renameFile(outFilename, sourceFullname); pPM->renameFile(outFilename, sourceFullname);
} }
@ -3449,7 +3414,7 @@ void CInstallThread::run()
std::string outFilename = patchName.substr(0, patchName.size() - zsStrLength); std::string outFilename = patchName.substr(0, patchName.size() - zsStrLength);
std::string localOutFilename = CPath::standardizeDosPath(outFilename); std::string localOutFilename = CPath::standardizeDosPath(outFilename);
if ( CPatchManager::unpackLZMA(patchName, localOutFilename) ) if ( unpackLZMA(patchName, localOutFilename) )
{ {
pPM->deleteFile(patchName); pPM->deleteFile(patchName);
pPM->renameFile(outFilename, sourceName); pPM->renameFile(outFilename, sourceName);

View file

@ -331,10 +331,6 @@ private:
void clearDataScanLog(); void clearDataScanLog();
static void getCorruptedFileInfo(const SFileToPatch &ftp, ucstring &sTranslate); static void getCorruptedFileInfo(const SFileToPatch &ftp, ucstring &sTranslate);
// utility func to decompress a monofile 7zip archive
static bool unpack7Zip(const std::string &sevenZipFile, const std::string &destFileName);
// utility func to decompress a single LZMA packed file
static bool unpackLZMA(const std::string &sevenZipFile, const std::string &destFileName);
static bool downloadAndUnpack(const std::string& patchPath, const std::string& sourceFilename, const std::string& extractPath, const std::string& tmpDirectory, uint32 timestamp); static bool downloadAndUnpack(const std::string& patchPath, const std::string& sourceFilename, const std::string& extractPath, const std::string& tmpDirectory, uint32 timestamp);
// Forward message to Installation Software // Forward message to Installation Software
void onFileInstallFinished(); void onFileInstallFinished();

View file

@ -5,7 +5,7 @@ FILE(GLOB LIB_SRC *.cpp *.h)
LIST(REMOVE_ITEM LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/7zMain.cpp) LIST(REMOVE_ITEM LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/7zMain.cpp)
NL_TARGET_LIB(ryzom_sevenzip ${LIB_SRC}) NL_TARGET_LIB(ryzom_sevenzip ${LIB_SRC})
# TARGET_LINK_LIBRARIES(ryzom_sevenzip ${PLATFORM_LINKFLAGS}) TARGET_LINK_LIBRARIES(ryzom_sevenzip nelmisc)
NL_DEFAULT_PROPS(ryzom_sevenzip "Ryzom, Library: Seven Zip") NL_DEFAULT_PROPS(ryzom_sevenzip "Ryzom, Library: Seven Zip")
NL_ADD_RUNTIME_FLAGS(ryzom_sevenzip) NL_ADD_RUNTIME_FLAGS(ryzom_sevenzip)
NL_ADD_LIB_SUFFIX(ryzom_sevenzip) NL_ADD_LIB_SUFFIX(ryzom_sevenzip)
@ -14,11 +14,11 @@ ADD_DEFINITIONS(-DUNICODE -D_UNICODE -D_7ZIP_PPMD_SUPPPORT)
IF(WITH_PCH) IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(ryzom_sevenzip ${CMAKE_CURRENT_SOURCE_DIR}/Precomp.h ${CMAKE_CURRENT_SOURCE_DIR}/Precomp.cpp) ADD_NATIVE_PRECOMPILED_HEADER(ryzom_sevenzip ${CMAKE_CURRENT_SOURCE_DIR}/Precomp.h ${CMAKE_CURRENT_SOURCE_DIR}/Precomp.cpp)
ENDIF(WITH_PCH) ENDIF()
IF((WITH_INSTALL_LIBRARIES AND WITH_STATIC) OR NOT WITH_STATIC) IF((WITH_INSTALL_LIBRARIES AND WITH_STATIC) OR NOT WITH_STATIC)
INSTALL(TARGETS ryzom_sevenzip LIBRARY DESTINATION ${RYZOM_LIB_PREFIX} ARCHIVE DESTINATION ${RYZOM_LIB_PREFIX} COMPONENT libraries) INSTALL(TARGETS ryzom_sevenzip LIBRARY DESTINATION ${RYZOM_LIB_PREFIX} ARCHIVE DESTINATION ${RYZOM_LIB_PREFIX} COMPONENT libraries)
ENDIF((WITH_INSTALL_LIBRARIES AND WITH_STATIC) OR NOT WITH_STATIC) ENDIF()
IF(WITH_RYZOM_TOOLS) IF(WITH_RYZOM_TOOLS)
ADD_EXECUTABLE(7zDec ${CMAKE_CURRENT_SOURCE_DIR}/7zMain.cpp) ADD_EXECUTABLE(7zDec ${CMAKE_CURRENT_SOURCE_DIR}/7zMain.cpp)
@ -28,4 +28,4 @@ IF(WITH_RYZOM_TOOLS)
NL_ADD_RUNTIME_FLAGS(7zDec) NL_ADD_RUNTIME_FLAGS(7zDec)
INSTALL(TARGETS 7zDec RUNTIME DESTINATION ${RYZOM_BIN_PREFIX} COMPONENT tools) INSTALL(TARGETS 7zDec RUNTIME DESTINATION ${RYZOM_BIN_PREFIX} COMPONENT tools)
ENDIF(WITH_RYZOM_TOOLS) ENDIF()

View file

@ -0,0 +1,357 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "seven_zip.h"
#include "nel/misc/types_nl.h"
#include "nel/misc/file.h"
#include "nel/misc/path.h"
#include "7z.h"
#include "7zAlloc.h"
#include "7zCrc.h"
#include "7zVersion.h"
#include "LzmaLib.h"
#include <memory>
//
// Namespaces
//
using namespace std;
using namespace NLMISC;
/// Input stream class for 7zip archive
class CNel7ZipInStream : public ISeekInStream
{
NLMISC::IStream *_Stream;
public:
/// Constructor, only allow file stream because 7zip will 'seek' in the stream
CNel7ZipInStream(NLMISC::IStream *s)
: _Stream(s)
{
Read = readFunc;
Seek = seekFunc;
}
// the read function called by 7zip to read data
static SRes readFunc(void *object, void *buffer, size_t *size)
{
try
{
CNel7ZipInStream *me = (CNel7ZipInStream*)object;
uint len = (uint)*size;
me->_Stream->serialBuffer((uint8*)buffer, len);
return SZ_OK;
}
catch (...)
{
return SZ_ERROR_READ;
}
}
// the seek function called by seven zip to seek inside stream
static SRes seekFunc(void *object, Int64 *pos, ESzSeek origin)
{
try
{
CNel7ZipInStream *me = (CNel7ZipInStream*)object;
sint32 offset = (sint32)*pos;
bool ret = me->_Stream->seek(offset, (NLMISC::IStream::TSeekOrigin)origin);
if (ret)
{
*pos = (Int64)me->_Stream->getPos();
return SZ_OK;
}
}
catch (...)
{
}
return SZ_ERROR_READ;
}
};
bool unpack7Zip(const std::string &sevenZipFile, const std::string &destFileName)
{
nlinfo("Uncompressing 7zip archive '%s' to '%s'", sevenZipFile.c_str(), destFileName.c_str());
// init seven zip
ISzAlloc allocImp;
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
ISzAlloc allocTempImp;
allocTempImp.Alloc = SzAllocTemp;
allocTempImp.Free = SzFreeTemp;
// wrap file in a CIFile
CIFile input(sevenZipFile);
CNel7ZipInStream inStr(&input);
CLookToRead lookStream;
lookStream.realStream = &inStr;
LookToRead_CreateVTable(&lookStream, False);
LookToRead_Init(&lookStream);
CrcGenerateTable();
CSzArEx db;
SzArEx_Init(&db);
// unpack the file using the 7zip API
SRes res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if (res != SZ_OK)
{
nlerror("Failed to open archive file %s", sevenZipFile.c_str());
return false;
}
if (db.NumFiles != 1)
{
nlerror("Seven zip archive with more than 1 file are unsupported");
return false;
}
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
size_t offset;
size_t outSizeProcessed = 0;
// get the first file
res = SzArEx_Extract(&db, &lookStream.s, 0,
&blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
// get the length of first file
size_t nameLen = SzArEx_GetFileNameUtf16(&db, 0, NULL);
ucstring filename;
filename.resize(nameLen);
// write filename into ucstring
SzArEx_GetFileNameUtf16(&db, 0, &filename[0]);
// write the extracted file
FILE *outputHandle = fopen(destFileName.c_str(), "wb+");
if (outputHandle == 0)
{
nlerror("Can not open output file '%s'", destFileName.c_str());
return false;
}
UInt32 processedSize = (UInt32)fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle);
if (processedSize != outSizeProcessed)
{
nlerror("Failed to write %u char to output file '%s'", outSizeProcessed-processedSize, destFileName.c_str());
return false;
}
fclose(outputHandle);
IAlloc_Free(&allocImp, outBuffer);
// free 7z context
SzArEx_Free(&db, &allocImp);
// ok, all is fine, file is unpacked
return true;
}
bool unpackLZMA(const std::string &lzmaFile, const std::string &destFileName)
{
nldebug("unpackLZMA: decompress LZMA file '%s' to '%s", lzmaFile.c_str(), destFileName.c_str());
// open input file
CIFile inStream(lzmaFile);
uint32 inSize = inStream.getFileSize();
if (inSize < LZMA_PROPS_SIZE + 8)
{
nlwarning("unpackLZMA: Invalid file size, too small file '%s'", lzmaFile.c_str());
return false;
}
// allocate input buffer for props
auto_ptr<uint8> propsBuffer = auto_ptr<uint8>(new uint8[LZMA_PROPS_SIZE]);
// size of LZMA content
inSize -= LZMA_PROPS_SIZE + 8;
// allocate input buffer for lzma data
auto_ptr<uint8> inBuffer = auto_ptr<uint8>(new uint8[inSize]);
uint64 fileSize = 0;
try
{
// read props
inStream.serialBuffer(propsBuffer.get(), LZMA_PROPS_SIZE);
// read uncompressed size
inStream.serial(fileSize);
// read lzma content
inStream.serialBuffer(inBuffer.get(), inSize);
}
catch(const EReadError &e)
{
nlwarning("unpackLZMA: Error while reading '%s': %s", lzmaFile.c_str(), e.what());
return false;
}
// allocate the output buffer
auto_ptr<uint8> outBuffer = auto_ptr<uint8>(new uint8[fileSize]);
// in and out file sizes
SizeT outProcessed = (SizeT)fileSize;
SizeT inProcessed = (SizeT)inSize;
// decompress the file in memory
sint res = LzmaUncompress(outBuffer.get(), &outProcessed, inBuffer.get(), &inProcessed, propsBuffer.get(), LZMA_PROPS_SIZE);
if (res != 0 || outProcessed != fileSize)
{
nlwarning("unpackLZMA: Failed to decode lzma file '%s' with status %d", lzmaFile.c_str(), res);
return false;
}
// store on output buffer
COFile outStream(destFileName);
try
{
// write content
outStream.serialBuffer(outBuffer.get(), (uint)fileSize);
}
catch(const EFile &e)
{
nlwarning("unpackLZMA: Error while writing '%s': %s", destFileName.c_str(), e.what());
CFile::deleteFile(destFileName);
return false;
}
return true;
}
bool packLZMA(const std::string &srcFileName, const std::string &lzmaFileName)
{
nldebug("packLZMA: compress '%s' to LZMA file '%s", srcFileName.c_str(), lzmaFileName.c_str());
// open file
CIFile inStream(srcFileName);
size_t inSize = inStream.getFileSize();
// file empty
if (!inSize)
{
nlwarning("packLZMA: File '%s' not found or empty", srcFileName.c_str());
return false;
}
// allocate input buffer
auto_ptr<uint8> inBuffer = auto_ptr<uint8>(new uint8[inSize]);
try
{
// read file in buffer
inStream.serialBuffer(inBuffer.get(), inSize);
}
catch(const EReadError &e)
{
nlwarning("packLZMA: Error while reading '%s': %s", srcFileName.c_str(), e.what());
return false;
}
// allocate output buffer
size_t outSize = (11 * inSize / 10) + 65536; // worst case = 1.1 * size + 64K
auto_ptr<uint8> outBuffer = auto_ptr<uint8>(new uint8[outSize]);
// allocate buffer for props
size_t outPropsSize = LZMA_PROPS_SIZE;
auto_ptr<uint8> outProps = auto_ptr<uint8>(new uint8[outPropsSize]);
// compress with best compression and other default settings
sint res = LzmaCompress(outBuffer.get(), &outSize, inBuffer.get(), inSize, outProps.get(), &outPropsSize, 9, 1 << 24, 3, 0, 2, 32, 1);
switch(res)
{
case SZ_OK:
{
// store on output buffer
COFile outStream(lzmaFileName);
// unable to create file
if (!outStream.isOpen())
{
nlwarning("packLZMA: Unable to create '%s'", srcFileName.c_str());
return false;
}
try
{
// write props
outStream.serialBuffer(outProps.get(), (uint)outPropsSize);
// write uncompressed size
uint64 uncompressSize = inSize;
outStream.serial(uncompressSize);
// write content
outStream.serialBuffer(outBuffer.get(), (uint)outSize);
}
catch(const EFile &e)
{
nlwarning("packLZMA: Error while writing '%s': %s", lzmaFileName.c_str(), e.what());
CFile::deleteFile(lzmaFileName);
return false;
}
return true;
}
case SZ_ERROR_MEM:
nlwarning("packLZMA: Memory allocation error while compressing '%s' (input buffer size: %u, output buffer size: %u)", srcFileName.c_str(), (uint)inSize, (uint)outSize);
break;
case SZ_ERROR_PARAM:
nlwarning("packLZMA: Incorrect parameter while compressing '%s'", srcFileName.c_str());
break;
case SZ_ERROR_OUTPUT_EOF:
nlwarning("packLZMA: Output buffer overflow while compressing '%s' (input buffer size: %u, output buffer size: %u)", srcFileName.c_str(), (uint)inSize, (uint)outSize);
break;
case SZ_ERROR_THREAD:
nlwarning("packLZMA: Errors in multithreading functions (only for Mt version)");
break;
default:
nlwarning("packLZMA: Unknown error (%d) while compressing '%s'", res, srcFileName.c_str());
}
return false;
}

View file

@ -0,0 +1,31 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef SEVEN_ZIP_H
#define SEVEN_ZIP_H
#include <string>
// utility func to decompress a monofile 7zip archive
bool unpack7Zip(const std::string &sevenZipFileName, const std::string &destFileName);
// utility func to decompress a single LZMA packed file
bool unpackLZMA(const std::string &lzmaFileName, const std::string &destFileName);
// utility func to compress a single file to LZMA packed file
bool packLZMA(const std::string &srcFileName, const std::string &lzmaFileName);
#endif

View file

@ -0,0 +1,358 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#ifdef RZ_USE_STEAM
#include "steam_client.h"
#include <steam_api.h>
// prototypes definitions for Steam API functions we'll call
typedef bool (__cdecl *SteamAPI_InitFuncPtr)();
typedef void (__cdecl *SteamAPI_RegisterCallbackFuncPtr)(class CCallbackBase *pCallback, int iCallback);
typedef void (__cdecl *SteamAPI_RunCallbacksFuncPtr)();
typedef void (__cdecl *SteamAPI_ShutdownFuncPtr)();
typedef void (__cdecl *SteamAPI_UnregisterCallbackFuncPtr)(class CCallbackBase *pCallback);
typedef ISteamUtils* (__cdecl *SteamUtilsFuncPtr)();
typedef ISteamUser* (__cdecl *SteamUserFuncPtr)();
typedef ISteamFriends* (__cdecl *SteamFriendsFuncPtr)();
// macros to simplify dynamic functions loading
#define NL_DECLARE_SYMBOL(symbol) symbol##FuncPtr nl##symbol = NULL
#define NL_LOAD_SYMBOL(symbol) nl##symbol = (symbol##FuncPtr)NLMISC::nlGetSymbolAddress(_Handle, #symbol)
NL_DECLARE_SYMBOL(SteamAPI_Init);
NL_DECLARE_SYMBOL(SteamFriends);
NL_DECLARE_SYMBOL(SteamUser);
NL_DECLARE_SYMBOL(SteamUtils);
NL_DECLARE_SYMBOL(SteamAPI_RegisterCallback);
NL_DECLARE_SYMBOL(SteamAPI_UnregisterCallback);
NL_DECLARE_SYMBOL(SteamAPI_RunCallbacks);
NL_DECLARE_SYMBOL(SteamAPI_Shutdown);
// taken from steam_api.h, we needed to change it to use our dynamically loaded functions
// Declares a callback member function plus a helper member variable which
// registers the callback on object creation and unregisters on destruction.
// The optional fourth 'var' param exists only for backwards-compatibility
// and can be ignored.
#define NL_STEAM_CALLBACK( thisclass, func, .../*callback_type, [deprecated] var*/ ) \
_NL_STEAM_CALLBACK_SELECT( ( __VA_ARGS__, 4, 3 ), ( /**/, thisclass, func, __VA_ARGS__ ) )
//-----------------------------------------------------------------------------
// The following macros are implementation details, not intended for public use
//-----------------------------------------------------------------------------
#define _NL_STEAM_CALLBACK_AUTO_HOOK( thisclass, func, param )
#define _NL_STEAM_CALLBACK_HELPER( _1, _2, SELECTED, ... ) _NL_STEAM_CALLBACK_##SELECTED
#define _NL_STEAM_CALLBACK_SELECT( X, Y ) _NL_STEAM_CALLBACK_HELPER X Y
#define _NL_STEAM_CALLBACK_3( extra_code, thisclass, func, param ) \
struct CCallbackInternal_ ## func : private CSteamCallbackImpl< sizeof( param ) > { \
CCallbackInternal_ ## func () { extra_code nlSteamAPI_RegisterCallback( this, param::k_iCallback ); } \
CCallbackInternal_ ## func ( const CCallbackInternal_ ## func & ) { extra_code nlSteamAPI_RegisterCallback( this, param::k_iCallback ); } \
CCallbackInternal_ ## func & operator=( const CCallbackInternal_ ## func & ) { return *this; } \
private: virtual void Run( void *pvParam ) { _NL_STEAM_CALLBACK_AUTO_HOOK( thisclass, func, param ) \
thisclass *pOuter = reinterpret_cast<thisclass*>( reinterpret_cast<char*>(this) - offsetof( thisclass, m_steamcallback_ ## func ) ); \
pOuter->func( reinterpret_cast<param*>( pvParam ) ); \
} \
} m_steamcallback_ ## func ; void func( param *pParam )
#define _NL_STEAM_CALLBACK_4( _, thisclass, func, param, var ) \
CSteamCallback< thisclass, param > var; void func( param *pParam )
//-----------------------------------------------------------------------------
// Purpose: templated base for callbacks - internal implementation detail
//-----------------------------------------------------------------------------
template< int sizeof_P >
class CSteamCallbackImpl : protected CCallbackBase
{
public:
~CSteamCallbackImpl() { if ( m_nCallbackFlags & k_ECallbackFlagsRegistered ) nlSteamAPI_UnregisterCallback( this ); }
void SetGameserverFlag() { m_nCallbackFlags |= k_ECallbackFlagsGameServer; }
protected:
virtual void Run( void *pvParam ) = 0;
virtual void Run( void *pvParam, bool /*bIOFailure*/, SteamAPICall_t /*hSteamAPICall*/ ) { Run( pvParam ); }
virtual int GetCallbackSizeBytes() { return sizeof_P; }
};
//-----------------------------------------------------------------------------
// Purpose: maps a steam callback to a class member function
// template params: T = local class, P = parameter struct,
// bGameserver = listen for gameserver callbacks instead of client callbacks
//-----------------------------------------------------------------------------
template< class T, class P, bool bGameserver = false >
class CSteamCallback : public CSteamCallbackImpl< sizeof( P ) >
{
public:
typedef void (T::*func_t)(P*);
// NOTE: If you can't provide the correct parameters at construction time, you should
// use the CCallbackManual callback object (STEAM_CALLBACK_MANUAL macro) instead.
CSteamCallback( T *pObj, func_t func ) : m_pObj( NULL ), m_Func( NULL )
{
if ( bGameserver )
{
this->SetGameserverFlag();
}
Register( pObj, func );
}
// manual registration of the callback
void Register( T *pObj, func_t func )
{
if ( !pObj || !func )
return;
if ( this->m_nCallbackFlags & CCallbackBase::k_ECallbackFlagsRegistered )
Unregister();
m_pObj = pObj;
m_Func = func;
// SteamAPI_RegisterCallback sets k_ECallbackFlagsRegistered
nlSteamAPI_RegisterCallback( this, P::k_iCallback );
}
void Unregister()
{
// SteamAPI_UnregisterCallback removes k_ECallbackFlagsRegistered
nlSteamAPI_UnregisterCallback( this );
}
protected:
virtual void Run( void *pvParam )
{
(m_pObj->*m_Func)( (P *)pvParam );
}
T *m_pObj;
func_t m_Func;
};
// listener called by Steam when AuthSessionTicket is available
class CAuthSessionTicketListener
{
public:
CAuthSessionTicketListener():_AuthSessionTicketResponse(this, &CAuthSessionTicketListener::OnAuthSessionTicketResponse)
{
_AuthSessionTicketHandle = 0;
_AuthSessionTicketSize = 0;
_AuthSessionTicketCallbackCalled = false;
_AuthSessionTicketCallbackError = false;;
_AuthSessionTicketCallbackTimeout = false;
}
// wait until a ticket is available or return if no ticket received after specified ms
bool waitTicket(uint32 ms)
{
// call Steam method
_AuthSessionTicketHandle = nlSteamUser()->GetAuthSessionTicket(_AuthSessionTicketData, sizeof(_AuthSessionTicketData), &_AuthSessionTicketSize);
nldebug("GetAuthSessionTicket returned %u bytes, handle %u", _AuthSessionTicketSize, _AuthSessionTicketHandle);
nlinfo("Waiting for Steam GetAuthSessionTicket callback...");
// define expiration time
NLMISC::TTime expirationTime = NLMISC::CTime::getLocalTime() + ms;
// wait until callback method is called or expiration
while(!_AuthSessionTicketCallbackCalled && !_AuthSessionTicketCallbackTimeout)
{
// call registered callbacks
nlSteamAPI_RunCallbacks();
// check if expired
if (NLMISC::CTime::getLocalTime() > expirationTime)
_AuthSessionTicketCallbackTimeout = true;
}
// expired
if (_AuthSessionTicketCallbackTimeout)
{
nlwarning("GetAuthSessionTicket callback never called");
return false;
}
nlinfo("GetAuthSessionTicket called");
// got an error
if (_AuthSessionTicketCallbackError)
{
nlwarning("GetAuthSessionTicket callback returned error");
return false;
}
return true;
}
// return ticket if available in hexadecimal
std::string getTicket() const
{
// if expired or error, ticket is not available
if (!_AuthSessionTicketCallbackCalled || _AuthSessionTicketCallbackError || _AuthSessionTicketCallbackTimeout) return "";
std::string authSessionTicket;
// optimize string by allocating the final string size
authSessionTicket.reserve(_AuthSessionTicketSize*2);
// convert buffer to hexadecimal string
for (uint32 i = 0; i < _AuthSessionTicketSize; ++i)
{
authSessionTicket += NLMISC::toString("%02x", _AuthSessionTicketData[i]);
}
return authSessionTicket;
}
private:
// ticket handle
HAuthTicket _AuthSessionTicketHandle;
// buffer of ticket data
uint8 _AuthSessionTicketData[1024];
// size of buffer
uint32 _AuthSessionTicketSize;
// different states of callback
bool _AuthSessionTicketCallbackCalled;
bool _AuthSessionTicketCallbackError;
bool _AuthSessionTicketCallbackTimeout;
// callback declaration
NL_STEAM_CALLBACK(CAuthSessionTicketListener, OnAuthSessionTicketResponse, GetAuthSessionTicketResponse_t, _AuthSessionTicketResponse);
};
// method called by Steam
void CAuthSessionTicketListener::OnAuthSessionTicketResponse(GetAuthSessionTicketResponse_t *inCallback)
{
_AuthSessionTicketCallbackCalled = true;
if (inCallback->m_eResult != k_EResultOK)
{
_AuthSessionTicketCallbackError = true;
}
}
CSteamClient::CSteamClient():_Handle(NULL), _Initialized(false)
{
}
CSteamClient::~CSteamClient()
{
release();
}
bool CSteamClient::init()
{
std::string filename;
#if defined(NL_OS_WIN64)
filename = "steam_api64.dll";
#elif defined(NL_OS_WINDOWS)
filename = "steam_api.dll";
#elif defined(NL_OS_MAC)
filename = "libsteam_api.dylib";
#else
filename = "libsteam_api.so";
#endif
// try to load library
_Handle = NLMISC::nlLoadLibrary(filename);
if (!_Handle)
{
nlwarning("Unable to load Steam client");
return false;
}
NL_LOAD_SYMBOL(SteamAPI_Init);
// check if function was found
if (!nlSteamAPI_Init)
{
nlwarning("Unable to get a pointer on SteamAPI_Init");
return false;
}
// initialize Steam API
if (!nlSteamAPI_Init())
{
nlwarning("Unable to initialize Steam client");
return false;
}
_Initialized = true;
// load more functions
NL_LOAD_SYMBOL(SteamFriends);
NL_LOAD_SYMBOL(SteamUser);
NL_LOAD_SYMBOL(SteamUtils);
NL_LOAD_SYMBOL(SteamAPI_Shutdown);
bool loggedOn = nlSteamUser()->BLoggedOn();
nlinfo("Steam AppID: %u", nlSteamUtils()->GetAppID());
nlinfo("Steam login: %s", nlSteamFriends()->GetPersonaName());
nlinfo("Steam user logged: %s", loggedOn ? "yes":"no");
// don't need to continue, if not connected
if (!loggedOn) return false;
// load symbols used by AuthSessionTicket
NL_LOAD_SYMBOL(SteamAPI_RegisterCallback);
NL_LOAD_SYMBOL(SteamAPI_UnregisterCallback);
NL_LOAD_SYMBOL(SteamAPI_RunCallbacks);
CAuthSessionTicketListener listener;
// wait 5 seconds to get ticket
if (!listener.waitTicket(5000)) return false;
// save ticket
_AuthSessionTicket = listener.getTicket();
nldebug("Auth ticket: %s", _AuthSessionTicket.c_str());
return true;
}
bool CSteamClient::release()
{
if (!_Handle) return false;
if (_Initialized)
{
// only shutdown Steam if initialized
nlSteamAPI_Shutdown();
_Initialized = false;
}
// free Steam library from memory
bool res = NLMISC::nlFreeLibrary(_Handle);
_Handle = NULL;
return res;
}
#endif

View file

@ -0,0 +1,65 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CL_STEAM_CLIENT_H
#define CL_STEAM_CLIENT_H
#include "nel/misc/types_nl.h"
#include "nel/misc/dynloadlib.h"
/**
* Steam API helper to be able to call Steam functions/methods without linking to any library.
* The library is dynamically loaded and is optional.
*
* \author Cedric 'Kervala' OCHS
* \date 2016
*/
class CSteamClient
{
public:
CSteamClient();
~CSteamClient();
/**
* Dynamically load Steam client library and functions pointers.
* Also retrieve authentication session ticket if available.
* If no authentication session ticket retrieved, returns false.
*/
bool init();
/**
* Shutdown Steam client and unload library.
*/
bool release();
/**
* Return the authentication session ticket if available.
*/
std::string getAuthSessionTicket() const { return _AuthSessionTicket; }
private:
// handle on Steam DLL
NLMISC::NL_LIB_HANDLE _Handle;
// true if succeeded to initialize (must call shutdown)
bool _Initialized;
// the retrieved authentication session ticket
std::string _AuthSessionTicket;
};
#endif

View file

@ -3,7 +3,6 @@ FILE(GLOB SRC main.cpp
${CMAKE_SOURCE_DIR}/ryzom/client/src/user_agent.cpp ${CMAKE_SOURCE_DIR}/ryzom/client/src/user_agent.cpp
${CMAKE_SOURCE_DIR}/ryzom/client/src/client_cfg.cpp ${CMAKE_SOURCE_DIR}/ryzom/client/src/client_cfg.cpp
${CMAKE_SOURCE_DIR}/ryzom/client/src/login_patch.cpp ${CMAKE_SOURCE_DIR}/ryzom/client/src/login_patch.cpp
${CMAKE_SOURCE_DIR}/ryzom/client/src/login_patch_seven_zip.cpp
${CMAKE_SOURCE_DIR}/ryzom/client/src/login_xdelta.cpp ${CMAKE_SOURCE_DIR}/ryzom/client/src/login_xdelta.cpp
${CMAKE_SOURCE_DIR}/ryzom/client/src/stdpch.cpp ${CMAKE_SOURCE_DIR}/ryzom/client/src/stdpch.cpp
${CMAKE_SOURCE_DIR}/ryzom/client/src/stdpch.h ${CMAKE_SOURCE_DIR}/ryzom/client/src/stdpch.h
@ -17,6 +16,7 @@ ADD_EXECUTABLE(khanat_client_patcher ${SRC})
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${LIBXML2_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}
${CURL_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/ryzom/client/src ${CMAKE_SOURCE_DIR}/ryzom/client/src
) )

View file

@ -1,6 +1,10 @@
#include "stdpch.h" #include "stdpch.h"
#include "login_patch.h" #include "login_patch.h"
#include "client_cfg.h" #include "client_cfg.h"
#include "user_agent.h"
#include "nel/misc/cmd_args.h"
#include <locale.h> #include <locale.h>
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
@ -28,7 +32,8 @@ string VersionName;
string LoginLogin, LoginPassword; string LoginLogin, LoginPassword;
uint32 LoginShardId = 0xFFFFFFFF; uint32 LoginShardId = 0xFFFFFFFF;
bool useUtf8 = false; CCmdArgs Args;
bool useEsc = false; bool useEsc = false;
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
@ -38,9 +43,6 @@ sint attributes = 0;
std::string convert(const ucstring &str) std::string convert(const ucstring &str)
{ {
if (useUtf8)
return str.toUtf8();
return str.toString(); return str.toString();
} }
@ -91,29 +93,13 @@ void printDownload(const std::string &str)
// temporary modified string // temporary modified string
std::string nstr = str; std::string nstr = str;
uint length = 0; uint length = (uint)nstr.length();
if (useUtf8)
{
ucstring ucstr;
ucstr.fromUtf8(nstr);
length = (uint)ucstr.length();
if (length > maxLength)
{
ucstr = ucstr.luabind_substr(length - maxLength + 3);
nstr = std::string("...") + ucstr.toUtf8();
length = maxLength;
}
}
else
{
length = (uint)nstr.length();
if (length > maxLength) if (length > maxLength)
{ {
nstr = std::string("...") + nstr.substr(length - maxLength + 3); nstr = std::string("...") + nstr.substr(length - maxLength + 3);
length = maxLength; length = maxLength;
} }
}
// add padding with spaces // add padding with spaces
memset(spaces, ' ', maxLength); memset(spaces, ' ', maxLength);
@ -142,11 +128,65 @@ void printDownload(const std::string &str)
fflush(stdout); fflush(stdout);
} }
// hardcoded english translations to not depends on external files
struct CClientPatcherTranslations : public NLMISC::CI18N::ILoadProxy
{
virtual void loadStringFile(const std::string &filename, ucstring &text)
{
text.fromUtf8(
"TheSagaOfRyzom [Ryzom]\n"
"uiErrPatchApply [Error: Patch process ended but the patch has not been successfully applied.]\n"
"uiErrChecking [Error: Patch files failed - checking.]\n"
"uiKb [KiB]\n"
"uiMb [MiB]\n"
"uiLoginGetFile [Getting File:]\n"
"uiDLWithCurl [Downloading File With Curl:]\n"
"uiDecompressing [Decompressing File:]\n"
"uiCheckInt [Checking Integrity:]\n"
"uiNoVersionFound [No Version Found]\n"
"uiVersionFound [Version Found:]\n"
"uiApplyingDelta [Applying Delta:]\n"
"uiClientVersion [Client Version]\n"
"uiServerVersion [Server Version]\n"
"uiCheckingFile [Checking File]\n"
"uiNeededPatches [Required Patches:]\n"
"uiCheckInBNP [Checking inside BNP:]\n"
"uiSHA1Diff [Force BNP Unpacking: checksums do not correspond:]\n"
"uiCheckEndNoErr [Checking file ended with no errors]\n"
"uiCheckEndWithErr [Checking file ended with errors:]\n"
"uiPatchEndNoErr [Patching file ended with no errors]\n"
"uiPatchEndWithErr [Patch failed!]\n"
"uiPatchDiskFull [Disk full!]\n"
"uiPatchWriteError [Disk write error! (disk full?)]\n"
"uiProcessing [Processing file:]\n"
"uiUnpack [BNP Unpacking:]\n"
"uiUnpackErrHead [Cannot read bnp header:]\n"
"uiChangeDate [Changing the mod date:]\n"
"uiChgDateErr [Cannot change file time:]\n"
"uiNowDate [Now the date is:]\n"
"uiSetAttrib [Set file attributes:]\n"
"uiAttribErr [Cannot have read/write access:]\n"
"uiDelFile [Delete file:]\n"
"uiDelErr [Cannot delete file:]\n"
"uiDelNoFile [Delete file (no file)]\n"
"uiRenameFile [Rename File:]\n"
"uiRenameErr [Cannot rename file:]\n"
);
}
};
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// init the Nel context // init the Nel context
CApplicationContext appContext; CApplicationContext appContext;
Args.setVersion(getDisplayVersion());
Args.setDescription("Ryzom client");
Args.addArg("c", "config", "id", "Use this configuration to determine what directory to use by default");
if (!Args.parse(argc, argv)) return 1;
// create logs in temporary directory // create logs in temporary directory
createDebug(CPath::getTemporaryDirectory().c_str(), true, true); createDebug(CPath::getTemporaryDirectory().c_str(), true, true);
@ -177,11 +217,6 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
// check if console supports utf-8
std::string lang = toLower(std::string(setlocale(LC_CTYPE, "")));
useUtf8 = (lang.find("utf8") != string::npos || lang.find("utf-8") != string::npos);
lang = lang.substr(0, 2);
// check if console supports colors // check if console supports colors
std::string term = toLower(std::string(getenv("TERM") ? getenv("TERM"):"")); std::string term = toLower(std::string(getenv("TERM") ? getenv("TERM"):""));
useEsc = (term.find("xterm") != string::npos || term.find("linux") != string::npos); useEsc = (term.find("xterm") != string::npos || term.find("linux") != string::npos);
@ -209,70 +244,23 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
// set default paths // allocate translations proxy
std::string dataPath = "./data/"; CClientPatcherTranslations *trans = new CClientPatcherTranslations();
std::string rootPath = "./";
// use custom data path if specified // use proxy
if (!ClientCfg.DataPath.empty()) CI18N::setLoadProxy(trans);
{
dataPath = CPath::standardizePath(ClientCfg.DataPath.front());
string::size_type pos = dataPath.rfind('/', dataPath.length()-2);
if (pos != string::npos)
rootPath = dataPath.substr(0, pos+1);
}
std::string unpackPath = CPath::standardizePath(rootPath + "unpack"); // load english translations
CI18N::load("en");
// check if user can write in data directory // now translations are read, we don't need it anymore
if (!CFile::isExists(unpackPath)) delete trans;
{
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(NLMISC::expandEnvironmentVariables(ClientCfg.PreDataPath[i]), true, false);
}
}
// add more search paths if translation is not found
if (!CPath::exists(lang + ".uxt"))
{
CPath::addSearchPath("patcher", true, false);
#ifdef RYZOM_SHARE_PREFIX
CPath::addSearchPath(RYZOM_SHARE_PREFIX"/patcher", true, false);
#endif
}
// load translation
CI18N::load(lang);
printf("Checking %s files to patch...\n", convert(CI18N::get("TheSagaOfRyzom")).c_str()); printf("Checking %s files to patch...\n", convert(CI18N::get("TheSagaOfRyzom")).c_str());
// 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);
// use PatchUrl // use PatchUrl
vector<string> patchURLs; vector<string> patchURLs;
pPM->init(patchURLs, ClientCfg.PatchUrl, ClientCfg.PatchVersion); pPM->init(patchURLs, ClientCfg.PatchUrl, ClientCfg.PatchVersion);
@ -385,6 +373,8 @@ int main(int argc, char *argv[])
printError(convert(CI18N::get("uiErrPatchApply")) + " " + error); printError(convert(CI18N::get("uiErrPatchApply")) + " " + error);
return 1; return 1;
} }
pPM->executeBatchFile();
} }
/* /*

View file

@ -4,6 +4,7 @@ FILE(GLOB SRC *.cpp *.h)
ADD_LIBRARY(georges_dll SHARED ${SRC} georges_edit.rc) ADD_LIBRARY(georges_dll SHARED ${SRC} georges_edit.rc)
INCLUDE_DIRECTORIES(${NEL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${NEL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(georges_dll nelmisc nelgeorges) TARGET_LINK_LIBRARIES(georges_dll nelmisc nelgeorges)
NL_DEFAULT_PROPS(georges_dll "Ryzom, Tools, Georges: Georges Dll") NL_DEFAULT_PROPS(georges_dll "Ryzom, Tools, Georges: Georges Dll")

View file

@ -8,6 +8,8 @@ SET(CMAKE_MFC_FLAG 2)
ADD_EXECUTABLE(world_editor WIN32 ${SRC} world_editor.rc) ADD_EXECUTABLE(world_editor WIN32 ${SRC} world_editor.rc)
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
SOURCE_GROUP(Resources FILES world_editor.rc) SOURCE_GROUP(Resources FILES world_editor.rc)
TARGET_LINK_LIBRARIES(world_editor TARGET_LINK_LIBRARIES(world_editor

View file

@ -110,6 +110,7 @@
extern bool DontUse3D; extern bool DontUse3D;
#include <libxml/parser.h>
//{{AFX_INSERT_LOCATION}} //{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line. // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

View file

@ -1,13 +1,15 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/ryzom/client/src/seven_zip)
SET(MAIN_SRC patch_gen_common.cpp patch_gen_main.cpp patch_gen_main.h) SET(MAIN_SRC patch_gen_common.cpp patch_gen_main.cpp patch_gen_main.h)
SET(SERVICE_SRC patch_gen_common.cpp patch_gen_service.cpp patch_gen_service.h) SET(SERVICE_SRC patch_gen_common.cpp patch_gen_service.cpp patch_gen_service.h)
ADD_EXECUTABLE(patch_gen ${MAIN_SRC}) ADD_EXECUTABLE(patch_gen ${MAIN_SRC})
TARGET_LINK_LIBRARIES(patch_gen ryzom_gameshare nelmisc nelnet nelligo nelgeorges) TARGET_LINK_LIBRARIES(patch_gen ryzom_sevenzip ryzom_gameshare nelmisc nelnet nelligo nelgeorges)
NL_DEFAULT_PROPS(patch_gen "Ryzom, Tools: Patch Generator") NL_DEFAULT_PROPS(patch_gen "Ryzom, Tools: Patch Generator")
NL_ADD_RUNTIME_FLAGS(patch_gen) NL_ADD_RUNTIME_FLAGS(patch_gen)
ADD_EXECUTABLE(patch_gen_service WIN32 ${SERVICE_SRC}) ADD_EXECUTABLE(patch_gen_service WIN32 ${SERVICE_SRC})
TARGET_LINK_LIBRARIES(patch_gen_service ryzom_gameshare nelmisc nelnet nelligo nelgeorges) TARGET_LINK_LIBRARIES(patch_gen_service ryzom_sevenzip ryzom_gameshare nelmisc nelnet nelligo nelgeorges)
NL_DEFAULT_PROPS(patch_gen_service "Ryzom, Tools: Patch Generator Service") NL_DEFAULT_PROPS(patch_gen_service "Ryzom, Tools: Patch Generator Service")
NL_ADD_RUNTIME_FLAGS(patch_gen_service) NL_ADD_RUNTIME_FLAGS(patch_gen_service)

View file

@ -27,6 +27,7 @@
#include "nel/misc/command.h" #include "nel/misc/command.h"
#include "nel/misc/sstring.h" #include "nel/misc/sstring.h"
#include "game_share/singleton_registry.h" #include "game_share/singleton_registry.h"
#include "seven_zip.h"
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
@ -74,37 +75,16 @@ void ApplyPatch(const std::string& srcFileName,const std::string& destFileName,c
#endif // NL_OS_WINDOWS #endif // NL_OS_WINDOWS
} }
void GenerateLZMA(const std::string sourceFile, const std::string &outputFile) void GenerateLZMA(const std::string &sourceFile, const std::string &outputFile)
{ {
{ {
// old syntax incompatible with new versions nlinfo("Compressing %s to %s using LZMA...", sourceFile.c_str(), outputFile.c_str());
std::string cmd = "lzma e";
cmd += " " + sourceFile + " " + outputFile;
nlinfo("Executing system command: %s", cmd.c_str());
} }
#ifdef NL_OS_WINDOWS
_spawnlp(_P_WAIT, "lzma.exe","lzma.exe", "e", sourceFile.c_str(), outputFile.c_str(), NULL);
#else // NL_OS_WINDOWS
// new lzma only supports one file name on command line, so make a copy
CFile::copyFile(outputFile, sourceFile);
// new lzma syntax, -z = compress, -9 = best compression if (!packLZMA(sourceFile, outputFile))
std::string cmd = NLMISC::toString("lzma -z -9 %s", outputFile.c_str());
sint error = system(cmd.c_str());
if (error)
{ {
nlwarning("'%s' failed with error code %d", cmd.c_str(), error); nlwarning("LZMA compress failed");
CFile::deleteFile(outputFile);
} }
else
{
// lzma always append a .lzma extension, so rename compressed file to wanted one
CFile::moveFile(outputFile, outputFile + ".lzma");
}
#endif // NL_OS_WINDOWS
} }

View file

@ -1417,11 +1417,11 @@ uiErrPatchApply [Fehler : Patchprozess beendet, aber der Patch konnte nicht erfo
// INDEX 353 // INDEX 353
uiErrChecking [Fehler : Patchdateien versagen - Überprüfung.] uiErrChecking [Fehler : Patchdateien versagen - Überprüfung.]
// HASH_VALUE 40D0242C40D0242C // HASH_VALUE 8E9280411622E45F
// INDEX 354 // INDEX 354
uiKb [KB] uiKb [KB]
// HASH_VALUE 4050243440502434 // HASH_VALUE 90B288459762EC61
// INDEX 355 // INDEX 355
uiMb [MB] uiMb [MB]
@ -27271,3 +27271,11 @@ uiRadarUseCamera [Radar folgt der Kamera-Rotation.]
// INDEX 6466 // INDEX 6466
uittRadarUseCamera [Wenn aktiviert, wird die Kamera-Rotation für die Radar-Ansicht eingeschaltet.] uittRadarUseCamera [Wenn aktiviert, wird die Kamera-Rotation für die Radar-Ansicht eingeschaltet.]
// HASH_VALUE 82A1901C06A3F72E
// INDEX 6467
uiTotalPatch [GESAMTER PATCH]
// HASH_VALUE D091B40C4890BC25
// INDEX 6468
uiRequiredFiles [BENÖTIGTE DATEIEN]

View file

@ -1415,13 +1415,13 @@ uiErrPatchApply [Error: Patch process ended but the patch has not been successfu
// INDEX 353 // INDEX 353
uiErrChecking [Error: Patch files failed - checking.] uiErrChecking [Error: Patch files failed - checking.]
// HASH_VALUE 40D0242C40D0242C // HASH_VALUE 8E9280411622E45F
// INDEX 354 // INDEX 354
uiKb [KB] uiKb [KiB]
// HASH_VALUE 4050243440502434 // HASH_VALUE 90B288459762EC61
// INDEX 355 // INDEX 355
uiMb [MB] uiMb [MiB]
// HASH_VALUE 9FA5A06DD895B637 // HASH_VALUE 9FA5A06DD895B637
// INDEX 356 // INDEX 356
@ -27237,3 +27237,27 @@ uiRadarUseCamera [Radar follows camera rotation]
// INDEX 6466 // INDEX 6466
uittRadarUseCamera [If checked, use camera rotation for radar view.] uittRadarUseCamera [If checked, use camera rotation for radar view.]
// HASH_VALUE 82A1901C06A3F72E
// INDEX 6467
uiTotalPatch [TOTAL PATCH]
// HASH_VALUE D091B40C4890BC25
// INDEX 6468
uiRequiredFiles [REQUIRED FILES]
// HASH_VALUE 8C42E02F0C01D422
// INDEX 6469
uiLodValue [NORMAL]
// HASH_VALUE 6878DC2CC23A6CB6
// INDEX 6470
uiDebugProfileFillRate [Profile Fillrate]
// HASH_VALUE 0F54678C93B4CBF6
// INDEX 6471
uiFixedMissionEntry_Mainland_Unknwown [Main land / Unknown]
// HASH_VALUE CAB123089C80B66B
// INDEX 6472
uiNoFiles [No Files...]

View file

@ -1416,13 +1416,13 @@ uiErrPatchApply [Error: Proceso de Parcheado finalize pero el parche no ha sido
// INDEX 353 // INDEX 353
uiErrChecking [Error: Archivos del Parcheado han fallado - revisando.] uiErrChecking [Error: Archivos del Parcheado han fallado - revisando.]
// HASH_VALUE 40D0242C40D0242C // HASH_VALUE 8E9280411622E45F
// INDEX 354 // INDEX 354
uiKb [KB] uiKb [KiB]
// HASH_VALUE 4050243440502434 // HASH_VALUE 90B288459762EC61
// INDEX 355 // INDEX 355
uiMb [MB] uiMb [MiB]
// HASH_VALUE 9FA5A06DD895B637 // HASH_VALUE 9FA5A06DD895B637
// INDEX 356 // INDEX 356
@ -27297,3 +27297,11 @@ uiRadarUseCamera [El radar sigue la rotación de la cámara]
// INDEX 6466 // INDEX 6466
uittRadarUseCamera [Si marcado, usar la rotación de cámara para la vista de radar.] uittRadarUseCamera [Si marcado, usar la rotación de cámara para la vista de radar.]
// HASH_VALUE 82A1901C06A3F72E
// INDEX 6467
uiTotalPatch [PARCHE TOTAL]
// HASH_VALUE D091B40C4890BC25
// INDEX 6468
uiRequiredFiles [ARCHIVOS NECESARIOS]

File diff suppressed because it is too large Load diff

View file

@ -1445,13 +1445,13 @@ uiErrPatchApply [Error : Patch process ended but the patch has not been successf
// INDEX 353 // INDEX 353
uiErrChecking [Error : Checking for patch files failed] uiErrChecking [Error : Checking for patch files failed]
// HASH_VALUE 40D0242C40D0242C // HASH_VALUE 8E9280411622E45F
// INDEX 354 // INDEX 354
uiKb [KB] uiKb [KiB]
// HASH_VALUE 4050243440502434 // HASH_VALUE 90B288459762EC61
// INDEX 355 // INDEX 355
uiMb [MB] uiMb [MiB]
// HASH_VALUE 9FA5A06DD895B637 // HASH_VALUE 9FA5A06DD895B637
// INDEX 356 // INDEX 356
@ -27455,3 +27455,27 @@ uiRadarUseCamera [Radar follows camera rotation]
// INDEX 6466 // INDEX 6466
uittRadarUseCamera [If checked, use camera rotation for radar view.] uittRadarUseCamera [If checked, use camera rotation for radar view.]
// HASH_VALUE 82A1901C06A3F72E
// INDEX 6467
uiTotalPatch [TOTAL PATCH]
// HASH_VALUE D091B40C4890BC25
// INDEX 6468
uiRequiredFiles [REQUIRED FILES]
// HASH_VALUE 8C42E02F0C01D422
// INDEX 6469
uiLodValue [NORMAL]
// HASH_VALUE 6878DC2CC23A6CB6
// INDEX 6470
uiDebugProfileFillRate [Profile Fillrate]
// HASH_VALUE 0F54678C93B4CBF6
// INDEX 6471
uiFixedMissionEntry_Mainland_Unknwown [Main land / Unknown]
// HASH_VALUE CAB123089C80B66B
// INDEX 6472
uiNoFiles [No Files...]

View file

@ -753,9 +753,9 @@ uiErrPatchApply [Error : Patch process ended but the patch has not been successf
uiErrChecking [Error : Checking for patch files failed] uiErrChecking [Error : Checking for patch files failed]
uiKb [KB] uiKb [KiB]
uiMb [MB] uiMb [MiB]
uiLoginGetFile [Getting File :] uiLoginGetFile [Getting File :]
uiDLFailed [Download from emergency server failed, patching is aborted] uiDLFailed [Download from emergency server failed, patching is aborted]
@ -13454,3 +13454,13 @@ uiShowClock12h [Use 12-hour clock]
uittShowClock12h [If checked, use 12-hour clock in compass and in chat messages.] uittShowClock12h [If checked, use 12-hour clock in compass and in chat messages.]
uiRadarUseCamera [Radar follows camera rotation] uiRadarUseCamera [Radar follows camera rotation]
uittRadarUseCamera [If checked, use camera rotation for radar view.] uittRadarUseCamera [If checked, use camera rotation for radar view.]
uiTotalPatch [TOTAL PATCH]
uiRequiredFiles [REQUIRED FILES]
// default value for LOD in login screen
uiLodValue [NORMAL]
// option displayed in keys configuration (Debug section)
uiDebugProfileFillRate [Profile Fillrate]
// displayed in mission window when continent is unknown
uiFixedMissionEntry_Mainland_Unknwown [Main land / Unknown]
// displayed when no files are playing in MP3 player
uiNoFiles [No Files...]

1
code/tool/CMakeLists.txt Normal file
View file

@ -0,0 +1 @@
ADD_SUBDIRECTORY(bin2c)

View file

@ -0,0 +1,8 @@
FILE(GLOB SRC *.cpp *.h)
ADD_EXECUTABLE(bin2c ${SRC})
NL_DEFAULT_PROPS(bin2c "Tools: bin2c")
NL_ADD_RUNTIME_FLAGS(bin2c)
INSTALL(TARGETS bin2c RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools)

View file

@ -14,9 +14,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// bin2c.cpp : Defines the entry point for the console application.
//
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -25,22 +22,55 @@ int main(int argc, char* argv[])
{ {
if (argc<2) if (argc<2)
{ {
printf ("bin2c [filename.bin] [filename.c]\n"); printf ("bin2c <filename.bin> [filename.c]\n");
} }
else else
{ {
char sDir[256]; // path and filename but without extension
char sPath[256]; char sPathWithoutExtension[256];
// basename of file
char sName[256]; char sName[256];
char sExt[256];
_splitpath (argv[1], sDir, sPath, sName, sExt); // copy fullpath from command-line
strcpy(sPathWithoutExtension, argv[1]);
char *tmpExt = strrchr(sPathWithoutExtension, '.');
// remove extension
if (tmpExt) *tmpExt = 0;
// look for last directory separator
const char *tmpName1 = strrchr(sPathWithoutExtension, '/');
#ifdef _WIN32
const char *tmpName2 = strrchr(sPathWithoutExtension, '\\');
#else
const char *tmpName2 = NULL;
#endif
// take last separator
const char *tmpName = tmpName1 > tmpName2 ? tmpName1:tmpName2;
// keep only path
if (tmpName)
{
// computes position in path
size_t pos = tmpName - sPathWithoutExtension;
// copy basename
strcpy(sName, sPathWithoutExtension+pos+1);
}
char sOutput[256]; char sOutput[256];
if (argc>2) if (argc>2)
{
strcpy (sOutput, argv[2]); strcpy (sOutput, argv[2]);
}
else else
{ {
_makepath (sOutput, sDir, sPath, sName, ".cpp"); strcpy(sOutput, sPathWithoutExtension);
strcat(sOutput, ".cpp");
} }
FILE *pIn=fopen( argv[1], "rb"); FILE *pIn=fopen( argv[1], "rb");