forked from Mirrors/openclonk
Support loading game data from system path
parent
7c26fc4d8d
commit
9f74506e9b
|
@ -156,6 +156,8 @@ set(OC_CLONK_SOURCES
|
|||
src/config/C4ConfigShareware.cpp
|
||||
src/config/C4ConfigShareware.h
|
||||
src/config/C4Constants.h
|
||||
src/config/C4Reloc.cpp
|
||||
src/config/C4Reloc.h
|
||||
src/config/C4SecurityCertificates.cpp
|
||||
src/config/C4SecurityCertificates.h
|
||||
src/control/C4Control.cpp
|
||||
|
@ -926,6 +928,12 @@ endif()
|
|||
############################################################################
|
||||
# Assemble compiler flags
|
||||
############################################################################
|
||||
if(UNIX)
|
||||
# Don't put this into CMAKE_CXX_FLAGS because otherwise it is cached,
|
||||
# and when the path is changed both the old and new definition appears
|
||||
# in the list of flags.
|
||||
add_definitions("-DOC_SYSTEM_DATA_DIR=\"${CMAKE_INSTALL_PREFIX}/share/openclonk\"")
|
||||
endif()
|
||||
if(OC_CXX_FLAGS)
|
||||
list(REMOVE_DUPLICATES OC_CXX_FLAGS)
|
||||
endif()
|
||||
|
@ -1071,11 +1079,11 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY
|
|||
############################################################################
|
||||
# installation
|
||||
############################################################################
|
||||
|
||||
# Install the icon into share/icons/hicolor/48x48/apps/clonk.png. Do this by
|
||||
# extracting the correct size from oc.ico. Currently this is layer 2 - let's
|
||||
# hope that it stays this way.
|
||||
# TODO: Check for convert at configure step?
|
||||
install(DIRECTORY DESTINATION share/icons/hicolor/48x48/apps)
|
||||
install(CODE "
|
||||
EXECUTE_PROCESS(COMMAND \"convert\" \"${CMAKE_CURRENT_SOURCE_DIR}/src/res/oc.ico[2]\" \"${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/clonk.png\" RESULT_VARIABLE CONVERT_RESULT)
|
||||
IF(NOT \${CONVERT_RESULT} EQUAL 0)
|
||||
|
|
|
@ -36,7 +36,7 @@ GCC_FLAGS =
|
|||
WARNING_FLAGS = -Wall
|
||||
endif
|
||||
|
||||
AM_CXXFLAGS = $(PTHREAD_CFLAGS) $(WINDOWS_CFLAGS) $(WARNING_FLAGS) $(GCC_FLAGS)
|
||||
AM_CXXFLAGS = $(PTHREAD_CFLAGS) $(WINDOWS_CFLAGS) $(WARNING_FLAGS) $(GCC_FLAGS) -DOC_SYSTEM_DATA_DIR=\"${datadir}/openclonk\"
|
||||
|
||||
AM_CFLAGS = -Wall $(GCC_FLAGS)
|
||||
|
||||
|
@ -196,6 +196,8 @@ src/config/C4Config.h \
|
|||
src/config/C4ConfigShareware.cpp \
|
||||
src/config/C4ConfigShareware.h \
|
||||
src/config/C4Constants.h \
|
||||
src/config/C4Reloc.cpp \
|
||||
src/config/C4Reloc.h \
|
||||
src/config/C4SecurityCertificates.cpp \
|
||||
src/config/C4SecurityCertificates.h \
|
||||
src/control/C4Control.cpp \
|
||||
|
|
|
@ -110,8 +110,11 @@ bool C4Application::DoInit(int argc, char * argv[])
|
|||
|
||||
Revision.Ref(C4REVISION);
|
||||
|
||||
// Initialize game data paths
|
||||
Reloc.Init();
|
||||
|
||||
// init system group
|
||||
if (!SystemGroup.Open(C4CFN_System))
|
||||
if (!Reloc.Open(SystemGroup, C4CFN_System))
|
||||
{
|
||||
// Error opening system group - no LogFatal, because it needs language table.
|
||||
// This will *not* use the FatalErrors stack, but this will cause the game
|
||||
|
@ -204,7 +207,7 @@ void C4Application::ParseCommandLine(int argc, char * argv[])
|
|||
|
||||
ClearCommandLine();
|
||||
Game.NetworkActive = false;
|
||||
Config.General.ClearAdditionalDataPaths();
|
||||
Reloc.Init(); // re-init from config
|
||||
isEditor = 2;
|
||||
int c;
|
||||
while (1)
|
||||
|
@ -303,7 +306,7 @@ void C4Application::ParseCommandLine(int argc, char * argv[])
|
|||
// startup start screen
|
||||
case 's': C4Startup::SetStartScreen(optarg); break;
|
||||
// additional read-only data path
|
||||
case 'd': Config.General.AddAdditionalDataPath(optarg); break;
|
||||
case 'd': Reloc.AddPath(optarg); break;
|
||||
// debug options
|
||||
case 'D': Game.DebugPort = atoi(optarg); break;
|
||||
case 'P': Game.DebugPassword = optarg; break;
|
||||
|
@ -345,7 +348,11 @@ void C4Application::ParseCommandLine(int argc, char * argv[])
|
|||
// Scenario file
|
||||
if (SEqualNoCase(GetExtension(szParameter),"c4s"))
|
||||
{
|
||||
Game.SetScenarioFilename(Config.AtDataReadPath(szParameter, true));
|
||||
if(IsGlobalPath(szParameter))
|
||||
Game.SetScenarioFilename(szParameter);
|
||||
else
|
||||
Game.SetScenarioFilename((std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str());
|
||||
|
||||
continue;
|
||||
}
|
||||
if (SEqualNoCase(GetFilename(szParameter),"scenario.txt"))
|
||||
|
@ -356,8 +363,11 @@ void C4Application::ParseCommandLine(int argc, char * argv[])
|
|||
// Player file
|
||||
if (SEqualNoCase(GetExtension(szParameter),"c4p"))
|
||||
{
|
||||
const char *param = Config.AtDataReadPath(szParameter, true);
|
||||
SAddModule(Game.PlayerFilenames,param);
|
||||
if(IsGlobalPath(szParameter))
|
||||
SAddModule(Game.PlayerFilenames, szParameter);
|
||||
else
|
||||
SAddModule(Game.PlayerFilenames, (std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str());
|
||||
|
||||
continue;
|
||||
}
|
||||
// Definition file
|
||||
|
|
|
@ -181,9 +181,14 @@ bool C4Game::OpenScenario()
|
|||
{ LogF("%s: %s", LoadResStr("IDS_PRC_FILENOTFOUND"), (const char *)ScenarioFilename); return false; }
|
||||
}
|
||||
else
|
||||
{
|
||||
// open directly
|
||||
if (!ScenarioFile.Open(ScenarioFilename))
|
||||
if (!Reloc.Open(ScenarioFile, ScenarioFilename))
|
||||
{ LogF("%s: %s", LoadResStr("IDS_PRC_FILENOTFOUND"), (const char *)ScenarioFilename); return false; }
|
||||
}
|
||||
|
||||
// Remember full (absolute) path
|
||||
SCopy(ScenarioFile.GetFullName().getData(), ScenarioFilename, _MAX_PATH);
|
||||
|
||||
// add scenario to group
|
||||
GroupSet.RegisterGroup(ScenarioFile, false, C4GSPrio_Scenario, C4GSCnt_Scenario);
|
||||
|
@ -818,7 +823,7 @@ bool C4Game::InitMaterialTexture()
|
|||
// Find next external material source
|
||||
pMatRes = Game.Parameters.GameRes.iterRes(pMatRes, NRT_Material);
|
||||
if (!pMatRes) break;
|
||||
if (!Mats.Open(pMatRes->getFile()))
|
||||
if (!Reloc.Open(Mats, pMatRes->getFile()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3210,9 +3215,6 @@ const char* C4Game::FoldersWithLocalsDefs(const char *szPath)
|
|||
static char szDefs[10*_MAX_PATH+1];
|
||||
szDefs[0]=0;
|
||||
|
||||
// Get relative path
|
||||
szPath = Config.AtRelativePath(szPath);
|
||||
|
||||
// Scan path for folder names
|
||||
int32_t cnt,iBackslash;
|
||||
char szFoldername[_MAX_PATH+1];
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "StdFile.h"
|
||||
#include "StdResStr2.h"
|
||||
#include "C4Log.h"
|
||||
#include "C4Reloc.h"
|
||||
|
||||
#include "C4PlayerControl.h"
|
||||
|
||||
|
|
|
@ -35,18 +35,20 @@ void C4Extra::Default()
|
|||
void C4Extra::Clear()
|
||||
{
|
||||
// free class members
|
||||
ExtraSysGrp.Close();
|
||||
ExtraUserGrp.Close();
|
||||
for(unsigned int i = 0; i < ExtraGroups.size(); ++i)
|
||||
delete ExtraGroups[i];
|
||||
ExtraGroups.clear();
|
||||
}
|
||||
|
||||
bool C4Extra::InitGroup()
|
||||
{
|
||||
// register extra root into game group set
|
||||
if (ItemExists(Config.AtSystemDataPath(C4CFN_Extra)) && ExtraSysGrp.Open(Config.AtSystemDataPath(C4CFN_Extra)))
|
||||
Game.GroupSet.RegisterGroup(ExtraSysGrp, false, C4GSPrio_ExtraRoot, C4GSCnt_ExtraRoot);
|
||||
// Add user Extra.c4g
|
||||
if (ItemExists(Config.AtUserDataPath(C4CFN_Extra)) && ExtraUserGrp.Open(Config.AtUserDataPath(C4CFN_Extra)))
|
||||
Game.GroupSet.RegisterGroup(ExtraUserGrp, false, C4GSPrio_ExtraRoot, C4GSCnt_ExtraRoot);
|
||||
for(C4Reloc::iterator iter = Reloc.begin(); iter != Reloc.end(); ++iter)
|
||||
{
|
||||
std::auto_ptr<C4Group> pGroup(new C4Group);
|
||||
if(pGroup->Open( (*iter + DirSep + C4CFN_Extra).getData()))
|
||||
ExtraGroups.push_back(pGroup.release());
|
||||
}
|
||||
|
||||
// done, success
|
||||
return true;
|
||||
|
@ -55,15 +57,23 @@ bool C4Extra::InitGroup()
|
|||
bool C4Extra::Init()
|
||||
{
|
||||
// no group: OK
|
||||
if (!ExtraSysGrp.IsOpen() && !ExtraUserGrp.IsOpen()) return true;
|
||||
if (ExtraGroups.empty()) return true;
|
||||
// load from all definitions that are activated
|
||||
// add first definition first, so the priority will be lowest
|
||||
// (according to definition load/overload order)
|
||||
char szSegment[_MAX_PATH+1];
|
||||
bool fAnythingLoaded=false;
|
||||
for (int cseg=0; SCopySegment(Game.DefinitionFilenames,cseg,szSegment,';',_MAX_PATH); cseg++)
|
||||
if (LoadDef(ExtraUserGrp,GetFilename(szSegment)) || LoadDef(ExtraSysGrp,GetFilename(szSegment)))
|
||||
fAnythingLoaded=true;
|
||||
{
|
||||
for(unsigned int i = 0; i < ExtraGroups.size(); ++i)
|
||||
{
|
||||
if(LoadDef(*ExtraGroups[i], GetFilename(szSegment)))
|
||||
{
|
||||
fAnythingLoaded=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// done, success
|
||||
return true;
|
||||
}
|
||||
|
@ -73,7 +83,7 @@ bool C4Extra::LoadDef(C4Group &hGroup, const char *szName)
|
|||
// check if file exists
|
||||
if (!hGroup.FindEntry(szName)) return false;
|
||||
// log that extra group is loaded
|
||||
LogF(LoadResStr("IDS_PRC_LOADEXTRA"), ExtraSysGrp.GetName(), szName);
|
||||
LogF(LoadResStr("IDS_PRC_LOADEXTRA"), hGroup.GetName(), szName);
|
||||
// open and add group to set
|
||||
C4Group *pGrp = new C4Group;
|
||||
if (!pGrp->OpenAsChild(&hGroup, szName)) { Log(LoadResStr("IDS_ERR_FAILURE")); delete pGrp; return false; }
|
||||
|
|
|
@ -33,8 +33,7 @@ public:
|
|||
bool Init(); // init extra group, using scneario presets
|
||||
bool InitGroup(); // open extra group
|
||||
|
||||
C4Group ExtraSysGrp; // extra.c4g root folder
|
||||
C4Group ExtraUserGrp; // extra.c4g root folder
|
||||
std::vector<C4Group*> ExtraGroups; // extra.c4g root folders
|
||||
|
||||
protected:
|
||||
bool LoadDef(C4Group &hGroup, const char *szName); // load preset for definition
|
||||
|
|
|
@ -357,7 +357,7 @@ C4Group *C4GroupSet::RegisterParentFolders(const char *szScenFilename)
|
|||
delete pGroup; return false;
|
||||
}
|
||||
}
|
||||
else if (!pGroup->Open(szParentfolder+iPos))
|
||||
else if (!Reloc.Open(*pGroup, szParentfolder+iPos))
|
||||
{
|
||||
LogFatal(FormatString("%s: %s", LoadResStr("IDS_PRC_FILENOTFOUND"), szParentfolder+iPos).getData());
|
||||
delete pGroup; return false;
|
||||
|
|
|
@ -83,39 +83,58 @@ bool C4Language::Init()
|
|||
}
|
||||
}*/
|
||||
|
||||
// Make sure Language.c4g is unpacked
|
||||
if (ItemExists(C4CFN_Languages))
|
||||
if (!DirectoryExists(C4CFN_Languages))
|
||||
C4Group_UnpackDirectory(C4CFN_Languages);
|
||||
|
||||
// Look for available language packs in Language.c4g
|
||||
C4Group *pPack;
|
||||
char strPackFilename[_MAX_FNAME + 1], strEntry[_MAX_FNAME + 1];
|
||||
//Log("Registering languages...");
|
||||
if (PackDirectory.Open(C4CFN_Languages))
|
||||
while (PackDirectory.FindNextEntry("*.c4g", strEntry))
|
||||
// Make sure Language.c4g is unpacked (TODO: This won't work properly if Language.c4g is in system data path)
|
||||
// Assume for now that Language.c4g is either at a writable location or unpacked already.
|
||||
// TODO: Use all Language.c4gs that we find, and merge them.
|
||||
// TODO: Use gettext instead?
|
||||
StdStrBuf langPath;
|
||||
C4Reloc::iterator iter;
|
||||
for(iter = Reloc.begin(); iter != Reloc.end(); ++iter)
|
||||
{
|
||||
langPath.Copy(*iter + DirSep + C4CFN_Languages);
|
||||
if(ItemExists(langPath.getData()))
|
||||
{
|
||||
sprintf(strPackFilename, "%s" DirSep "%s", C4CFN_Languages, strEntry);
|
||||
pPack = new C4Group();
|
||||
if (pPack->Open(strPackFilename))
|
||||
if(DirectoryExists(langPath.getData()))
|
||||
break;
|
||||
if(C4Group_UnpackDirectory(langPath.getData()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Break if no language.c4g found
|
||||
if(iter != Reloc.end())
|
||||
{
|
||||
// Look for available language packs in Language.c4g
|
||||
C4Group *pPack;
|
||||
char strPackFilename[_MAX_FNAME + 1], strEntry[_MAX_FNAME + 1];
|
||||
//Log("Registering languages...");
|
||||
if (PackDirectory.Open(langPath.getData()))
|
||||
{
|
||||
while (PackDirectory.FindNextEntry("*.c4g", strEntry))
|
||||
{
|
||||
//sprintf(strLog, " %s...", strPackFilename); Log(strLog);
|
||||
Packs.RegisterGroup(*pPack, true, C4GSCnt_Language, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//sprintf(strLog, "Could not open language pack %s...", strPackFilename); Log(strLog);
|
||||
delete pPack;
|
||||
sprintf(strPackFilename, "%s" DirSep "%s", C4CFN_Languages, strEntry);
|
||||
pPack = new C4Group();
|
||||
if (pPack->Open(strPackFilename))
|
||||
{
|
||||
//sprintf(strLog, " %s...", strPackFilename); Log(strLog);
|
||||
Packs.RegisterGroup(*pPack, true, C4GSCnt_Language, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//sprintf(strLog, "Could not open language pack %s...", strPackFilename); Log(strLog);
|
||||
delete pPack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log
|
||||
//sprintf(strLog, "%d external language packs registered.", GetPackCount()); Log(strLog);
|
||||
// Log
|
||||
//sprintf(strLog, "%d external language packs registered.", GetPackCount()); Log(strLog);
|
||||
|
||||
// Now create a pack group for each language pack (these pack groups are child groups
|
||||
// that browse along each pack to access requested data)
|
||||
for (int iPack = 0; (pPack = Packs.GetGroup(iPack)); iPack++)
|
||||
PackGroups.RegisterGroup(*(new C4Group), true, C4GSPrio_Base, C4GSCnt_Language);
|
||||
// Now create a pack group for each language pack (these pack groups are child groups
|
||||
// that browse along each pack to access requested data)
|
||||
for (int iPack = 0; (pPack = Packs.GetGroup(iPack)); iPack++)
|
||||
PackGroups.RegisterGroup(*(new C4Group), true, C4GSPrio_Base, C4GSCnt_Language);
|
||||
}
|
||||
|
||||
// Load language infos by scanning string tables (the engine doesn't really need this at the moment)
|
||||
InitInfos();
|
||||
|
@ -339,7 +358,7 @@ void C4Language::InitInfos()
|
|||
{
|
||||
C4Group hGroup;
|
||||
// First, look in System.c4g
|
||||
if (hGroup.Open(C4CFN_System))
|
||||
if (Reloc.Open(hGroup, C4CFN_System))
|
||||
{
|
||||
LoadInfos(hGroup);
|
||||
hGroup.Close();
|
||||
|
@ -436,7 +455,7 @@ bool C4Language::InitStringTable(const char *strCode)
|
|||
{
|
||||
C4Group hGroup;
|
||||
// First, look in System.c4g
|
||||
if (hGroup.Open(C4CFN_System))
|
||||
if (Reloc.Open(hGroup, C4CFN_System))
|
||||
{
|
||||
if (LoadStringTable(hGroup, strCode))
|
||||
{ hGroup.Close(); return true; }
|
||||
|
|
|
@ -479,8 +479,14 @@ void C4ConfigGeneral::DeterminePaths(bool forceWorkingDirectory)
|
|||
SCopy(GetWorkingDirectory(),SystemDataPath);
|
||||
AppendBackslash(SystemDataPath);
|
||||
#elif defined(__linux__)
|
||||
// FIXME: Where to put this?
|
||||
SCopy(ExePath,SystemDataPath);
|
||||
|
||||
#ifdef OC_SYSTEM_DATA_DIR
|
||||
SCopy(OC_SYSTEM_DATA_DIR, SystemDataPath);
|
||||
AppendBackslash(SystemDataPath);
|
||||
#else
|
||||
#error Please define OC_SYSTEM_DATA_DIR!
|
||||
//SCopy(ExePath,SystemDataPath);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Find user-specific data path
|
||||
|
@ -540,21 +546,7 @@ void C4ConfigGeneral::AdoptOldSettings()
|
|||
}
|
||||
}
|
||||
|
||||
void C4ConfigGeneral::ClearAdditionalDataPaths()
|
||||
{
|
||||
for (PathList::iterator it = AdditionalDataPaths.begin(); it != AdditionalDataPaths.end(); ++it)
|
||||
delete[] *it;
|
||||
AdditionalDataPaths.clear();
|
||||
}
|
||||
|
||||
void C4ConfigGeneral::AddAdditionalDataPath(const char *szPath)
|
||||
{
|
||||
char *clone = new char[SLen(szPath)+1];
|
||||
SCopy(szPath,clone);
|
||||
AdditionalDataPaths.push_back(clone);
|
||||
}
|
||||
|
||||
char AtPathFilename[_MAX_PATH+1];
|
||||
static char AtPathFilename[_MAX_PATH+1];
|
||||
|
||||
const char* C4Config::AtExePath(const char *szFilename)
|
||||
{
|
||||
|
@ -660,54 +652,6 @@ void C4ConfigControls::ResetKeys()
|
|||
StdCompilerNull Comp; Comp.Compile(mkParAdapt(*this, true));
|
||||
}
|
||||
|
||||
const char* C4Config::AtDataReadPath(const char *szFilename, bool fPreferWorkdir)
|
||||
{
|
||||
if (IsGlobalPath(szFilename)) return szFilename;
|
||||
StdCopyStrBuf sfn(szFilename);
|
||||
do
|
||||
{
|
||||
const char *path = AtDataReadPathCore(sfn.getData(), fPreferWorkdir);
|
||||
if (path)
|
||||
{
|
||||
if (path != AtPathFilename) SCopy(path,AtPathFilename);
|
||||
AtPathFilename[_MAX_PATH] = '\0';
|
||||
AppendBackslash(AtPathFilename);
|
||||
SAppend(szFilename,AtPathFilename,_MAX_PATH);
|
||||
return AtPathFilename;
|
||||
}
|
||||
}
|
||||
while (TruncatePath(sfn.getMData()));
|
||||
return szFilename;
|
||||
}
|
||||
|
||||
const char* C4Config::AtDataReadPathCore(const char *szFilename, bool fPreferWorkdir)
|
||||
{
|
||||
if (fPreferWorkdir && FileExists(szFilename))
|
||||
{
|
||||
SCopy(GetWorkingDirectory(),AtPathFilename,_MAX_PATH-1);
|
||||
return AtPathFilename;
|
||||
}
|
||||
// Check extra data paths
|
||||
for (C4ConfigGeneral::PathList::iterator it = General.AdditionalDataPaths.begin();
|
||||
it != General.AdditionalDataPaths.end();
|
||||
++it)
|
||||
{
|
||||
SCopy(*it, AtPathFilename, _MAX_PATH-1);
|
||||
AppendBackslash(AtPathFilename);
|
||||
SAppend(szFilename,AtPathFilename,_MAX_PATH);
|
||||
if (FileExists(AtPathFilename))
|
||||
return *it;
|
||||
}
|
||||
if (FileExists(AtUserDataPath(szFilename))) return General.UserDataPath;
|
||||
if (FileExists(AtSystemDataPath(szFilename))) return General.SystemDataPath;
|
||||
if (!fPreferWorkdir && FileExists(szFilename))
|
||||
{
|
||||
SCopy(GetWorkingDirectory(),AtPathFilename,_MAX_PATH-1);
|
||||
return AtPathFilename;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* C4Config::AtUserDataRelativePath(const char *szFilename)
|
||||
{
|
||||
// Specified file is located in UserDataPath: return relative path
|
||||
|
|
|
@ -68,9 +68,6 @@ public:
|
|||
bool FirstStart;
|
||||
bool UserPortraitsWritten; // set when default portraits have been copied to the UserPath (this is only done once)
|
||||
|
||||
// Additional paths to read data from (prioritized lower than UserDataPath/SystemDataPath)
|
||||
typedef std::list<const char *> PathList;
|
||||
PathList AdditionalDataPaths;
|
||||
public:
|
||||
static int GetLanguageSequence(const char *strSource, char *strTarget);
|
||||
void DefaultLanguage();
|
||||
|
@ -78,9 +75,6 @@ public:
|
|||
void AdoptOldSettings();
|
||||
void DeterminePaths(bool forceWorkingDirectory);
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
void AddAdditionalDataPath(const char *szPath);
|
||||
void ClearAdditionalDataPaths();
|
||||
~C4ConfigGeneral() { ClearAdditionalDataPaths(); }
|
||||
|
||||
private:
|
||||
struct
|
||||
|
@ -292,7 +286,6 @@ public:
|
|||
const char *AtSystemDataPath(const char *szFilename);
|
||||
const char *AtSystemDataRelativePath(const char *szFilename);
|
||||
const char *AtRelativePath(const char *szFilename); // Returns ASDRP or AUDRP depending on location
|
||||
const char *AtDataReadPath(const char *szFilename, bool fPreferWorkdir = false);
|
||||
const char *GetRegistrationData(const char* strField) { return ""; }
|
||||
void ForceRelativePath(StdStrBuf *sFilename); // try AtRelativePath; force GetC4Filename if not possible
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
@ -303,8 +296,6 @@ public:
|
|||
void GetConfigFileName(StdStrBuf &filename, bool forceWorkingDirectory, const char *szConfigFile);
|
||||
|
||||
static void ExpandEnvironmentVariables(char *strPath, size_t iMaxLen);
|
||||
private:
|
||||
const char *AtDataReadPathCore(const char *szFilename, bool fPreferWorkdir = false);
|
||||
};
|
||||
|
||||
#include <C4ConfigShareware.h>
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 2011 Armin Burgmeier
|
||||
*
|
||||
* Portions might be copyrighted by other authors who have contributed
|
||||
* to OpenClonk.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
* See isc_license.txt for full license and disclaimer.
|
||||
*
|
||||
* "Clonk" is a registered trademark of Matthes Bender.
|
||||
* See clonk_trademark_license.txt for full license.
|
||||
*/
|
||||
|
||||
#include <C4Include.h>
|
||||
#include <C4Reloc.h>
|
||||
|
||||
C4Reloc Reloc; // singleton
|
||||
|
||||
void C4Reloc::Init()
|
||||
{
|
||||
Paths.clear();
|
||||
|
||||
// TODO: On Linux, we might not always want to have ExePath (= working directory)
|
||||
// here. It's handy for development so that we can easily run the engine in planet/
|
||||
// but for distribution it might make sense to disable it.
|
||||
// TODO: We might also want to add ExePath/planet if it exists, so that we don't
|
||||
// need to run the engine in planet/.
|
||||
AddPath(Config.General.ExePath);
|
||||
AddPath(Config.General.UserDataPath);
|
||||
AddPath(Config.General.SystemDataPath);
|
||||
}
|
||||
|
||||
bool C4Reloc::AddPath(const char* path)
|
||||
{
|
||||
if(!IsGlobalPath(path))
|
||||
return false;
|
||||
|
||||
if(std::find(Paths.begin(), Paths.end(), path) != Paths.end())
|
||||
return false;
|
||||
|
||||
Paths.push_back(StdCopyStrBuf(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
C4Reloc::iterator C4Reloc::begin() const
|
||||
{
|
||||
return Paths.begin();
|
||||
}
|
||||
|
||||
C4Reloc::iterator C4Reloc::end() const
|
||||
{
|
||||
return Paths.end();
|
||||
}
|
||||
|
||||
bool C4Reloc::Open(C4Group& hGroup, const char* filename) const
|
||||
{
|
||||
if(IsGlobalPath(filename)) return hGroup.Open(filename);
|
||||
|
||||
for(iterator iter = begin(); iter != end(); ++iter)
|
||||
if(hGroup.Open((*iter + DirSep + filename).getData()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool C4Reloc::LocateItem(const char* filename, StdStrBuf& str) const
|
||||
{
|
||||
if(IsGlobalPath(filename))
|
||||
{
|
||||
str.Copy(filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
for(iterator iter = begin(); iter != end(); ++iter)
|
||||
{
|
||||
str.Copy(*iter + DirSep + filename);
|
||||
if(ItemExists(str.getData()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 2011 Armin Burgmeier
|
||||
*
|
||||
* Portions might be copyrighted by other authors who have contributed
|
||||
* to OpenClonk.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
* See isc_license.txt for full license and disclaimer.
|
||||
*
|
||||
* "Clonk" is a registered trademark of Matthes Bender.
|
||||
* See clonk_trademark_license.txt for full license.
|
||||
*/
|
||||
|
||||
#ifndef C4RELOC_H
|
||||
#define C4RELOC_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
class C4Reloc
|
||||
{
|
||||
public:
|
||||
typedef std::vector<StdCopyStrBuf> PathList;
|
||||
typedef PathList::const_iterator iterator;
|
||||
|
||||
// Can also be used for re-init, drops custom paths added with AddPath.
|
||||
// Make sure to call after Config.Load.
|
||||
void Init();
|
||||
|
||||
bool AddPath(const char* path);
|
||||
|
||||
iterator begin() const;
|
||||
iterator end() const;
|
||||
|
||||
bool Open(C4Group& hGroup, const char* filename) const;
|
||||
bool LocateItem(const char* filename, StdStrBuf& str) const;
|
||||
private:
|
||||
C4Reloc::PathList Paths;
|
||||
};
|
||||
|
||||
extern C4Reloc Reloc;
|
||||
|
||||
#endif // C4RELOC_H
|
|
@ -667,35 +667,40 @@ C4ControlJoinPlayer::C4ControlJoinPlayer(const char *szFilename, int32_t iAtClie
|
|||
idInfo(iIDInfo), fByRes(false)
|
||||
{
|
||||
// load from file if filename is given - which may not be the case for script players
|
||||
if (szFilename)
|
||||
StdStrBuf filename;
|
||||
if (szFilename && Reloc.LocateItem(szFilename, filename))
|
||||
{
|
||||
StdStrBuf filename_buf;
|
||||
const char *filename = Config.AtDataReadPath(szFilename);
|
||||
bool file_is_temp = false;
|
||||
if (DirectoryExists(filename))
|
||||
if (DirectoryExists(filename.getData()))
|
||||
{
|
||||
// the player file is unpacked - temp pack and read
|
||||
filename_buf.Copy(Config.AtTempPath(GetFilenameOnly(filename)));
|
||||
StdStrBuf filename_buf;
|
||||
filename_buf.Copy(Config.AtTempPath(GetFilenameOnly(filename.getData())));
|
||||
MakeTempFilename(&filename_buf);
|
||||
if (C4Group_PackDirectoryTo(filename, filename_buf.getData()))
|
||||
if (C4Group_PackDirectoryTo(filename.getData(), filename_buf.getData()))
|
||||
{
|
||||
filename = filename_buf.getData();
|
||||
filename = filename_buf;
|
||||
file_is_temp = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// pack failed
|
||||
LogF("[!]Error packing player file %s to %s for join: Pack failed.", filename, filename_buf.getData());
|
||||
LogF("[!]Error packing player file %s to %s for join: Pack failed.", filename.getData(), filename_buf.getData());
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
bool fSuccess = PlrData.LoadFromFile(filename);
|
||||
bool fSuccess = PlrData.LoadFromFile(filename.getData());
|
||||
if (!fSuccess)
|
||||
{
|
||||
LogF("[!]Error loading player file from %s.", filename.getData());
|
||||
assert(false);
|
||||
LogF("[!]Error loading player file from %s.", filename);
|
||||
}
|
||||
if (file_is_temp) EraseFile(filename);
|
||||
if (file_is_temp) EraseFile(filename.getData());
|
||||
}
|
||||
else
|
||||
{
|
||||
LogF("[!]Error loading player file from %s.", szFilename ? szFilename : "(null)");
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,11 +77,9 @@ bool C4PlayerInfo::LoadFromLocalFile(const char *szFilename)
|
|||
assert(!Game.C4S.Head.Replay);
|
||||
// clear previous
|
||||
Clear();
|
||||
// find (possibly overridden) filename
|
||||
szFilename = Config.AtDataReadPath(szFilename);
|
||||
// open player file group
|
||||
C4Group Grp;
|
||||
if (!Grp.Open(szFilename)) return false;
|
||||
if (!Reloc.Open(Grp, szFilename)) return false;
|
||||
|
||||
// read core
|
||||
C4PlayerInfoCore C4P;
|
||||
|
|
|
@ -821,7 +821,7 @@ int32_t C4DefList::Load(const char *szSearch,
|
|||
|
||||
// Load from specified file
|
||||
C4Group hGroup;
|
||||
if (!hGroup.Open(Config.AtDataReadPath(szSearch)))
|
||||
if (!Reloc.Open(hGroup, szSearch))
|
||||
{
|
||||
// Specified file not found (failure)
|
||||
LogFatal(FormatString(LoadResStr("IDS_PRC_DEFNOTFOUND"),szSearch).getData());
|
||||
|
|
|
@ -238,10 +238,6 @@ bool C4Player::Init(int32_t iNumber, int32_t iAtClient, const char *szAtClientNa
|
|||
}
|
||||
// Status init
|
||||
Status=PS_Normal;
|
||||
if (szFilename)
|
||||
SCopy(Config.AtDataReadPath(szFilename),Filename);
|
||||
else
|
||||
*Filename='\0';
|
||||
Number = iNumber;
|
||||
ID = pInfo->GetID();
|
||||
Team = pInfo->GetTeam();
|
||||
|
@ -250,14 +246,14 @@ bool C4Player::Init(int32_t iNumber, int32_t iAtClient, const char *szAtClientNa
|
|||
// At client
|
||||
AtClient=iAtClient; SCopy(szAtClientName,AtClientName,C4MaxTitle);
|
||||
|
||||
if (Filename)
|
||||
if (szFilename)
|
||||
{
|
||||
// Load core & crew info list
|
||||
// do not load portraits for remote players
|
||||
// this will prevent portraits from being shown for "remotely controlled"-Clonks of other players
|
||||
bool fLoadPortraits = (AtClient==C4ClientIDUnknown) || SEqualNoCase(AtClientName, Game.Clients.getLocalName());
|
||||
// fLoadPortraits = true
|
||||
if (!Load(Filename, !fScenarioInit, fLoadPortraits)) return false;
|
||||
if (!Load(szFilename, !fScenarioInit, fLoadPortraits)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -984,7 +980,7 @@ bool C4Player::Load(const char *szFilename, bool fSavegame, bool fLoadPortraits)
|
|||
{
|
||||
C4Group hGroup;
|
||||
// Open group
|
||||
if (!hGroup.Open(szFilename)) return false;
|
||||
if (!Reloc.Open(hGroup, szFilename)) return false;
|
||||
// Load core
|
||||
if (!C4PlayerInfoCore::Load(hGroup))
|
||||
{ hGroup.Close(); return false; }
|
||||
|
|
|
@ -569,10 +569,10 @@ C4PortraitSelDlg::C4PortraitSelDlg(C4FileSel_BaseCB *pSelCallback, bool fSetPict
|
|||
char path[_MAX_PATH+1];
|
||||
// add common picture locations
|
||||
StdStrBuf strLocation;
|
||||
SCopy(Config.AtUserDataPath(""), path, _MAX_PATH); TruncateBackslash(path);
|
||||
SCopy(Config.General.UserDataPath, path, _MAX_PATH); TruncateBackslash(path);
|
||||
strLocation.Format("%s %s", C4ENGINECAPTION, LoadResStr("IDS_TEXT_USERPATH"));
|
||||
AddLocation(strLocation.getData(), path);
|
||||
SCopy(Config.AtSystemDataPath(""), path, _MAX_PATH); TruncateBackslash(path);
|
||||
SCopy(Config.General.SystemDataPath, path, _MAX_PATH); TruncateBackslash(path);
|
||||
strLocation.Format("%s %s", C4ENGINECAPTION, LoadResStr("IDS_TEXT_PROGRAMDIRECTORY"));
|
||||
AddCheckedLocation(strLocation.getData(), Config.General.ExePath);
|
||||
#ifdef _WIN32
|
||||
|
@ -653,7 +653,7 @@ bool C4PortraitSelDlg::SelectPortrait(C4GUI::Screen *pOnScreen, StdStrBuf *pSele
|
|||
{
|
||||
Log("Copying default portraits to user path...");
|
||||
C4Group hGroup;
|
||||
if (hGroup.Open(Config.AtSystemDataPath(C4CFN_Graphics)))
|
||||
if (Reloc.Open(hGroup, C4CFN_Graphics))
|
||||
{
|
||||
hGroup.Extract("Portrait1.png", Config.AtUserDataPath("Clonk.png"));
|
||||
hGroup.Close();
|
||||
|
|
|
@ -73,7 +73,7 @@ bool C4LoaderScreen::Init(const char *szLoaderSpec)
|
|||
{
|
||||
// open it
|
||||
GfxGrp.Close();
|
||||
if (!GfxGrp.Open(Config.AtSystemDataPath(C4CFN_Graphics)))
|
||||
if (!Reloc.Open(GfxGrp, C4CFN_Graphics))
|
||||
{
|
||||
LogFatal(FormatString(LoadResStr("IDS_PRC_NOGFXFILE"),C4CFN_Graphics,GfxGrp.GetError()).getData());
|
||||
return false;
|
||||
|
|
|
@ -73,7 +73,7 @@ static bool GetPortrait(char **ppBytes, size_t *ipSize)
|
|||
C4Group GfxGroup;
|
||||
int iCount;
|
||||
StdStrBuf EntryName;
|
||||
if (!GfxGroup.Open(Config.AtSystemDataPath(C4CFN_Graphics))) return false;
|
||||
if (!Reloc.Open(GfxGroup, C4CFN_Graphics)) return false;
|
||||
if ((iCount = GfxGroup.EntryCount("Portrait*.png")) < 1) return false;
|
||||
EntryName.Format("Portrait%d.png", SafeRandom(iCount) + 1);
|
||||
if (!GfxGroup.LoadEntry(EntryName.getData(), ppBytes, ipSize)) return false;
|
||||
|
@ -1245,7 +1245,7 @@ C4StartupPlrPropertiesDlg::C4StartupPlrPropertiesDlg(C4StartupPlrSelDlg::PlayerL
|
|||
// Set initial portrait and bigicon
|
||||
C4Group hGroup;
|
||||
StdStrBuf strPortrait; strPortrait.Format("Portrait%d.png", 1 + Random(5));
|
||||
if (hGroup.Open(Config.AtSystemDataPath(C4CFN_Graphics)))
|
||||
if (Reloc.Open(hGroup, C4CFN_Graphics))
|
||||
{
|
||||
hGroup.Extract(strPortrait.getData(), Config.AtTempPath("Portrait.png"));
|
||||
hGroup.Close();
|
||||
|
|
|
@ -1044,7 +1044,7 @@ bool C4ScenarioListLoader::RegularFolder::DoLoadContents(C4ScenarioListLoader *p
|
|||
ClearChildren();
|
||||
// regular folders must exist and not be within group!
|
||||
assert(!pFromGrp);
|
||||
if (sFilename[0])
|
||||
if (sFilename.getData() && sFilename[0])
|
||||
Merge(sFilename.getData());
|
||||
|
||||
// get number of entries, to estimate progress
|
||||
|
@ -1167,7 +1167,10 @@ bool C4ScenarioListLoader::Load(const StdStrBuf &sRootFolder)
|
|||
if (!BeginActivity(true)) return false;
|
||||
if (pRootFolder) { delete pRootFolder; pRootFolder = NULL; }
|
||||
pCurrFolder = pRootFolder = new RegularFolder(NULL);
|
||||
pRootFolder->Merge(Config.General.UserDataPath);
|
||||
// Load regular game data if no explicit path specified
|
||||
if(!sRootFolder.getData())
|
||||
for(C4Reloc::iterator iter = Reloc.begin(); iter != Reloc.end(); ++iter)
|
||||
pRootFolder->Merge(iter->getData());
|
||||
bool fSuccess = pRootFolder->LoadContents(this, NULL, &sRootFolder, false, false);
|
||||
EndActivity();
|
||||
return fSuccess;
|
||||
|
@ -1438,7 +1441,7 @@ void C4StartupScenSelDlg::OnShown()
|
|||
// init file list
|
||||
fIsInitialLoading = true;
|
||||
if (!pScenLoader) pScenLoader = new C4ScenarioListLoader();
|
||||
pScenLoader->Load(StdStrBuf(Config.General.ExePath));
|
||||
pScenLoader->Load(StdStrBuf()); //Config.General.ExePath));
|
||||
UpdateList();
|
||||
UpdateSelection();
|
||||
fIsInitialLoading = false;
|
||||
|
|
|
@ -318,7 +318,7 @@ bool C4GraphicsResource::RegisterGlobalGraphics()
|
|||
// The cleanest alternative would be to reinit all the fonts whenever a scenario is reloaded
|
||||
// FIXME: Test whether vector fonts from a scenario are correctly reloaded
|
||||
C4Group *pMainGfxGrp = new C4Group();
|
||||
if (!pMainGfxGrp->Open(C4CFN_Graphics) || !Files.RegisterGroup(*pMainGfxGrp, true, C4GSPrio_Base, C4GSCnt_Graphics, 1))
|
||||
if (!Reloc.Open(*pMainGfxGrp, C4CFN_Graphics) || !Files.RegisterGroup(*pMainGfxGrp, true, C4GSPrio_Base, C4GSCnt_Graphics, 1))
|
||||
{
|
||||
// error
|
||||
LogFatal(FormatString(LoadResStr("IDS_PRC_NOGFXFILE"),C4CFN_Graphics,pMainGfxGrp->GetError()).getData());
|
||||
|
|
|
@ -386,20 +386,21 @@ bool C4Network2Res::SetByFile(const char *strFilePath, bool fTemp, C4Network2Res
|
|||
SCopy(strFilePath, szFile, sizeof(szFile)-1);
|
||||
// group?
|
||||
C4Group Grp;
|
||||
if (Grp.Open(strFilePath))
|
||||
if (Reloc.Open(Grp, strFilePath))
|
||||
return SetByGroup(&Grp, fTemp, eType, iResID, szResName, fSilent);
|
||||
// so it needs to be a file
|
||||
if (!FileExists(szFile))
|
||||
StdStrBuf szFullFile;
|
||||
if (!Reloc.LocateItem(szFile, szFullFile))
|
||||
{ if (!fSilent) LogF("SetByFile: file %s not found!", strFilePath); return false; }
|
||||
// calc checksum
|
||||
uint32_t iCRC32;
|
||||
if (!C4Group_GetFileCRC(szFile, &iCRC32)) return false;
|
||||
if (!C4Group_GetFileCRC(szFullFile.getData(), &iCRC32)) return false;
|
||||
#ifdef C4NET2RES_DEBUG_LOG
|
||||
// log
|
||||
LogSilentF("Network: Resource: complete %d:%s is file %s (%s)", iResID, szResName, szFile, fTemp ? "temp" : "static");
|
||||
#endif
|
||||
// set core
|
||||
Core.Set(eType, iResID, szResName, iCRC32);
|
||||
Core.Set(eType, iResID, Config.AtRelativePath(szFullFile.getData()), iCRC32);
|
||||
// set own data
|
||||
fDirty = true;
|
||||
fTempFile = fTemp;
|
||||
|
|
|
@ -447,7 +447,7 @@ bool C4SoundSystem::Init()
|
|||
ClearEffects();
|
||||
// Open sound file
|
||||
if (!SoundFile.IsOpen())
|
||||
if (!SoundFile.Open(Config.AtSystemDataPath(C4CFN_Sound))) return false;
|
||||
if (!Reloc.Open(SoundFile, C4CFN_Sound)) return false;
|
||||
#ifdef HAVE_LIBSDL_MIXER
|
||||
Mix_AllocateChannels(C4MaxSoundInstances);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue