1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-26 08:14:38 +01:00

Merge pull request #6748 from IntelOrca/fix/2410

Refactor logic for resolving base paths
This commit is contained in:
Ted John
2017-12-02 19:08:43 +00:00
committed by GitHub
24 changed files with 504 additions and 246 deletions

View File

@@ -117,6 +117,12 @@
4CB832A71EFBDCCE00B88761 /* land_tool.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB832A51EFBDCCE00B88761 /* land_tool.c */; };
4CB832AB1EFFB8D100B88761 /* ttf_sdlport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB832A81EFFB8D100B88761 /* ttf_sdlport.c */; };
4CB832AC1EFFB8D100B88761 /* ttf.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB832A91EFFB8D100B88761 /* ttf.c */; };
4CE462431FD1612C0001CD98 /* android.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462421FD1612B0001CD98 /* android.c */; };
4CE462451FD161360001CD98 /* Platform.Android.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462441FD161360001CD98 /* Platform.Android.cpp */; };
4CE4624A1FD1613D0001CD98 /* Platform.Linux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462461FD1613D0001CD98 /* Platform.Linux.cpp */; };
4CE4624B1FD1613D0001CD98 /* Platform.macOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462471FD1613D0001CD98 /* Platform.macOS.cpp */; };
4CE4624C1FD1613D0001CD98 /* Platform.Posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462481FD1613D0001CD98 /* Platform.Posix.cpp */; };
4CE4624D1FD1613D0001CD98 /* Platform.Win32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */; };
4CF788C01F1B787700C611BF /* Painter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF788BE1F1B787700C611BF /* Painter.cpp */; };
4CFBCD5E1F27CD8000D74FB6 /* SmallScenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFBCD5D1F27CD8000D74FB6 /* SmallScenery.cpp */; };
4CFE4E801F90A3F1005243C2 /* Peep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E7B1F90A3F1005243C2 /* Peep.cpp */; };
@@ -392,7 +398,6 @@
F76C86A31EC4E88400FA49E2 /* Crash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C845A1EC4E7CC00FA49E2 /* Crash.cpp */; };
F76C86A51EC4E88400FA49E2 /* linux.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C845C1EC4E7CC00FA49E2 /* linux.c */; };
F76C86A61EC4E88400FA49E2 /* macos.m in Sources */ = {isa = PBXBuildFile; fileRef = F76C845D1EC4E7CC00FA49E2 /* macos.m */; };
F76C86A81EC4E88400FA49E2 /* Platform2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C845F1EC4E7CC00FA49E2 /* Platform2.cpp */; };
F76C86AA1EC4E88400FA49E2 /* posix.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C84611EC4E7CC00FA49E2 /* posix.c */; };
F76C86AB1EC4E88400FA49E2 /* shared.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C84621EC4E7CC00FA49E2 /* shared.c */; };
F76C86AC1EC4E88400FA49E2 /* windows.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C84631EC4E7CC00FA49E2 /* windows.c */; };
@@ -728,6 +733,12 @@
4CB832A81EFFB8D100B88761 /* ttf_sdlport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttf_sdlport.c; sourceTree = "<group>"; };
4CB832A91EFFB8D100B88761 /* ttf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttf.c; sourceTree = "<group>"; };
4CB832AA1EFFB8D100B88761 /* ttf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttf.h; sourceTree = "<group>"; };
4CE462421FD1612B0001CD98 /* android.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = android.c; sourceTree = "<group>"; };
4CE462441FD161360001CD98 /* Platform.Android.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Android.cpp; sourceTree = "<group>"; };
4CE462461FD1613D0001CD98 /* Platform.Linux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Linux.cpp; sourceTree = "<group>"; };
4CE462471FD1613D0001CD98 /* Platform.macOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.macOS.cpp; sourceTree = "<group>"; };
4CE462481FD1613D0001CD98 /* Platform.Posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Posix.cpp; sourceTree = "<group>"; };
4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Win32.cpp; sourceTree = "<group>"; };
4CF788BE1F1B787700C611BF /* Painter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Painter.cpp; sourceTree = "<group>"; };
4CF788BF1F1B787700C611BF /* Painter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Painter.h; sourceTree = "<group>"; };
4CFBCD5D1F27CD8000D74FB6 /* SmallScenery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmallScenery.cpp; sourceTree = "<group>"; };
@@ -1286,7 +1297,6 @@
F76C845C1EC4E7CC00FA49E2 /* linux.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = linux.c; sourceTree = "<group>"; };
F76C845D1EC4E7CC00FA49E2 /* macos.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = macos.m; sourceTree = "<group>"; };
F76C845E1EC4E7CC00FA49E2 /* platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = "<group>"; };
F76C845F1EC4E7CC00FA49E2 /* Platform2.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Platform2.cpp; sourceTree = "<group>"; };
F76C84601EC4E7CC00FA49E2 /* Platform2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Platform2.h; sourceTree = "<group>"; };
F76C84611EC4E7CC00FA49E2 /* posix.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = posix.c; sourceTree = "<group>"; };
F76C84621EC4E7CC00FA49E2 /* shared.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = shared.c; sourceTree = "<group>"; };
@@ -2250,12 +2260,17 @@
F76C84591EC4E7CC00FA49E2 /* platform */ = {
isa = PBXGroup;
children = (
4CE462421FD1612B0001CD98 /* android.c */,
F76C845A1EC4E7CC00FA49E2 /* Crash.cpp */,
F76C845B1EC4E7CC00FA49E2 /* crash.h */,
F76C845C1EC4E7CC00FA49E2 /* linux.c */,
F76C845D1EC4E7CC00FA49E2 /* macos.m */,
4CE462441FD161360001CD98 /* Platform.Android.cpp */,
F76C845E1EC4E7CC00FA49E2 /* platform.h */,
F76C845F1EC4E7CC00FA49E2 /* Platform2.cpp */,
4CE462461FD1613D0001CD98 /* Platform.Linux.cpp */,
4CE462471FD1613D0001CD98 /* Platform.macOS.cpp */,
4CE462481FD1613D0001CD98 /* Platform.Posix.cpp */,
4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */,
F76C84601EC4E7CC00FA49E2 /* Platform2.h */,
F76C84611EC4E7CC00FA49E2 /* posix.c */,
F76C84621EC4E7CC00FA49E2 /* shared.c */,
@@ -3185,6 +3200,7 @@
C666EE6B1F37ACB10061AA04 /* About.cpp in Sources */,
C666ED771F33DBB20061AA04 /* ShortcutKeys.cpp in Sources */,
4C93F1AA1F8B748900A9330D /* SubmarineRide.cpp in Sources */,
4CE462451FD161360001CD98 /* Platform.Android.cpp in Sources */,
C666EE6C1F37ACB10061AA04 /* Changelog.cpp in Sources */,
4C93F1441F8B744400A9330D /* InvertedRollerCoaster.cpp in Sources */,
C64644FC1F3FA4120026AC2D /* Footpath.cpp in Sources */,
@@ -3199,6 +3215,8 @@
4CB832AB1EFFB8D100B88761 /* ttf_sdlport.c in Sources */,
C654DF371F69C0430040F43D /* Sign.cpp in Sources */,
4C93F1751F8B745700A9330D /* MiniHelicopters.cpp in Sources */,
4CE462431FD1612C0001CD98 /* android.c in Sources */,
4CE4624B1FD1613D0001CD98 /* Platform.macOS.cpp in Sources */,
4C93F1501F8B744400A9330D /* SideFrictionRollerCoaster.cpp in Sources */,
4C93F13D1F8B744400A9330D /* CompactInvertedCoaster.cpp in Sources */,
C67CCD681FBBD138004FAE4C /* EditorMain.cpp in Sources */,
@@ -3206,6 +3224,7 @@
C6E415511FAFD6DC00D4A52A /* RideConstruction.cpp in Sources */,
C685E51B1F8907850090598F /* Guest.cpp in Sources */,
C64644F91F3FA4120026AC2D /* EditorInventionsList.cpp in Sources */,
4CE4624C1FD1613D0001CD98 /* Platform.Posix.cpp in Sources */,
C6D2BEE61F9BAACE008B557C /* TrackList.cpp in Sources */,
4C93F1AB1F8B748900A9330D /* WaterCoaster.cpp in Sources */,
4C93F16D1F8B745700A9330D /* Dodgems.cpp in Sources */,
@@ -3253,6 +3272,7 @@
C666EE771F37ACB10061AA04 /* SavePrompt.cpp in Sources */,
4C93F16C1F8B745700A9330D /* CrookedHouse.cpp in Sources */,
4C93F18A1F8B747A00A9330D /* Enterprise.cpp in Sources */,
4CE4624A1FD1613D0001CD98 /* Platform.Linux.cpp in Sources */,
C654DF391F69C0430040F43D /* TitleCommandEditor.cpp in Sources */,
4C93F13B1F8B744400A9330D /* BobsleighCoaster.cpp in Sources */,
4C93F1701F8B745700A9330D /* GhostTrain.cpp in Sources */,
@@ -3264,6 +3284,7 @@
F76C88811EC5324E00FA49E2 /* DrawLineShader.cpp in Sources */,
4C93F13A1F8B744400A9330D /* AirPoweredVerticalCoaster.cpp in Sources */,
4C93F1421F8B744400A9330D /* InvertedHairpinCoaster.cpp in Sources */,
4CE4624D1FD1613D0001CD98 /* Platform.Win32.cpp in Sources */,
C67CCD661FBBCFDB004FAE4C /* EditorBottomToolbar.cpp in Sources */,
C666EE731F37ACB10061AA04 /* MusicCredits.cpp in Sources */,
4C93F1511F8B744400A9330D /* StandUpRollerCoaster.cpp in Sources */,
@@ -3471,7 +3492,6 @@
F76C86A31EC4E88400FA49E2 /* Crash.cpp in Sources */,
F76C86A51EC4E88400FA49E2 /* linux.c in Sources */,
F76C86A61EC4E88400FA49E2 /* macos.m in Sources */,
F76C86A81EC4E88400FA49E2 /* Platform2.cpp in Sources */,
F76C86AA1EC4E88400FA49E2 /* posix.c in Sources */,
F76C86AB1EC4E88400FA49E2 /* shared.c in Sources */,
F76C86AC1EC4E88400FA49E2 /* windows.c in Sources */,

View File

@@ -158,6 +158,11 @@ namespace OpenRCT2
return _uiContext;
}
IPlatformEnvironment * GetPlatformEnvironment() override
{
return _env;
}
sint32 RunOpenRCT2(int argc, const char * * argv) override
{
if (Initialise())
@@ -1133,4 +1138,19 @@ extern "C"
{
return GetContext()->GetUiContext()->SetClipboardText(target);
}
/**
* This function is deprecated.
* Use IPlatformEnvironment instad.
*/
void platform_get_user_directory(utf8 * outPath, const utf8 * subDirectory, size_t outSize)
{
auto env = GetContext()->GetPlatformEnvironment();
auto path = env->GetDirectoryPath(DIRBASE::USER);
if (!String::IsNullOrEmpty(subDirectory))
{
path = Path::Combine(path, subDirectory);
}
String::Set(outPath, outSize, path.c_str());
}
}

View File

@@ -94,6 +94,7 @@ namespace OpenRCT2
virtual Audio::IAudioContext * GetAudioContext() abstract;
virtual Ui::IUiContext * GetUiContext() abstract;
virtual IPlatformEnvironment * GetPlatformEnvironment() abstract;
virtual sint32 RunOpenRCT2(int argc, const char * * argv) abstract;

View File

@@ -21,11 +21,11 @@
#include "core/Path.hpp"
#include "core/String.hpp"
#include "OpenRCT2.h"
#include "platform/platform.h"
#include "platform/Platform2.h"
#include "PlatformEnvironment.h"
#include "Version.h"
#include "platform/platform.h"
using namespace OpenRCT2;
class PlatformEnvironment final : public IPlatformEnvironment
@@ -36,7 +36,7 @@ private:
public:
PlatformEnvironment(DIRBASE_VALUES basePaths)
{
for (sint32 i = 0; i < 4; i++)
for (sint32 i = 0; i < DIRBASE_COUNT; i++)
{
_basePath[i] = basePaths[i];
}
@@ -59,6 +59,7 @@ public:
break;
case DIRBASE::OPENRCT2:
case DIRBASE::USER:
case DIRBASE::CONFIG:
directoryName = DirectoryNamesOpenRCT2[(size_t)did];
break;
}
@@ -68,21 +69,10 @@ public:
std::string GetFilePath(PATHID pathid) const override
{
const utf8 * fileName = FileNames[(size_t)pathid];
const utf8 * basePath = _basePath[(size_t)DIRBASE::USER].c_str();
if (pathid == PATHID::MP_DAT)
{
basePath = _basePath[(size_t)DIRBASE::RCT1].c_str();
}
else if (pathid == PATHID::SCORES_RCT2)
{
basePath = _basePath[(size_t)DIRBASE::RCT2].c_str();
}
utf8 path[260];
String::Set(path, sizeof(path), basePath);
Path::Append(path, sizeof(path), fileName);
return std::string(path);
auto dirbase = GetDefaultBaseDirectory(pathid);
auto basePath = GetDirectoryPath(dirbase);
auto fileName = FileNames[(size_t)pathid];
return Path::Combine(basePath, fileName);
}
void SetBasePath(DIRBASE base, const std::string &path) override
@@ -94,6 +84,31 @@ private:
static const char * DirectoryNamesRCT2[];
static const char * DirectoryNamesOpenRCT2[];
static const char * FileNames[];
static DIRBASE GetDefaultBaseDirectory(PATHID pathid)
{
switch (pathid)
{
case PATHID::CONFIG:
case PATHID::CONFIG_KEYBOARD:
return DIRBASE::CONFIG;
case PATHID::CACHE_OBJECTS:
case PATHID::CACHE_TRACKS:
case PATHID::CACHE_SCENARIOS:
return DIRBASE::CACHE;
case PATHID::MP_DAT:
return DIRBASE::RCT1;
case PATHID::SCORES_RCT2:
return DIRBASE::RCT2;
case PATHID::NETWORK_GROUPS:
case PATHID::NETWORK_SERVERS:
case PATHID::NETWORK_USERS:
case PATHID::SCORES:
case PATHID::SCORES_LEGACY:
default:
return DIRBASE::USER;
}
}
};
IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment(DIRBASE_VALUES basePaths)
@@ -101,42 +116,61 @@ IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment(DIRBASE_VALUES basePa
return new PlatformEnvironment(basePaths);
}
static std::string GetOpenRCT2DirectoryName()
{
#if defined(__ANDROID__)
return "openrct2-user";
#else
return "OpenRCT2";
#endif
}
IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment()
{
utf8 userPath[MAX_PATH];
platform_resolve_openrct_data_path();
platform_resolve_user_data_path();
platform_get_user_directory(userPath, nullptr, sizeof(userPath));
if (!platform_ensure_directory_exists(userPath))
{
Console::Error::WriteLine("Could not create user directory '%s' (do you have write access to your documents folder?)", userPath);
return nullptr;
}
platform_get_exe_path(gExePath, sizeof(gExePath));
log_verbose("Setting exe path to %s", gExePath);
auto subDirectory = GetOpenRCT2DirectoryName();
// Set default paths
std::string basePaths[DIRBASE_COUNT];
basePaths[(size_t)DIRBASE::OPENRCT2] = Platform::GetInstallPath();
basePaths[(size_t)DIRBASE::USER] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_DATA), subDirectory);
basePaths[(size_t)DIRBASE::CONFIG] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CONFIG), subDirectory);
basePaths[(size_t)DIRBASE::CACHE] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CACHE), subDirectory);
// Override paths that have been specified via the command line
if (!String::IsNullOrEmpty(gCustomRCT2DataPath))
{
basePaths[(size_t)DIRBASE::RCT2] = gCustomRCT2DataPath;
}
if (!String::IsNullOrEmpty(gCustomOpenrctDataPath))
{
basePaths[(size_t)DIRBASE::OPENRCT2] = gCustomOpenrctDataPath;
}
if (!String::IsNullOrEmpty(gCustomUserDataPath))
{
basePaths[(size_t)DIRBASE::USER] = gCustomUserDataPath;
basePaths[(size_t)DIRBASE::CONFIG] = gCustomUserDataPath;
basePaths[(size_t)DIRBASE::CACHE] = gCustomUserDataPath;
}
auto env = OpenRCT2::CreatePlatformEnvironment(basePaths);
// Now load the config so we can get the RCT1 and RCT2 paths
auto configPath = env->GetFilePath(PATHID::CONFIG);
config_set_defaults();
if (!config_open_default())
if (!config_open(configPath.c_str()))
{
config_save_default();
config_save(configPath.c_str());
}
utf8 path[260];
std::string basePaths[4];
basePaths[(size_t)DIRBASE::RCT1] = String::ToStd(gConfigGeneral.rct1_path);
basePaths[(size_t)DIRBASE::RCT2] = String::ToStd(gConfigGeneral.rct2_path);
platform_get_openrct_data_path(path, sizeof(path));
basePaths[(size_t)DIRBASE::OPENRCT2] = std::string(path);
platform_get_user_directory(path, nullptr, sizeof(path));
basePaths[(size_t)DIRBASE::USER] = std::string(path);
IPlatformEnvironment * env = OpenRCT2::CreatePlatformEnvironment(basePaths);
env->SetBasePath(DIRBASE::RCT1, String::ToStd(gConfigGeneral.rct1_path));
env->SetBasePath(DIRBASE::RCT2, String::ToStd(gConfigGeneral.rct2_path));
// Log base paths
log_verbose("DIRBASE::RCT1 : %s", env->GetDirectoryPath(DIRBASE::RCT1).c_str());
log_verbose("DIRBASE::RCT2 : %s", env->GetDirectoryPath(DIRBASE::RCT2).c_str());
log_verbose("DIRBASE::OPENRCT2: %s", env->GetDirectoryPath(DIRBASE::OPENRCT2).c_str());
log_verbose("DIRBASE::USER : %s", env->GetDirectoryPath(DIRBASE::USER).c_str());
log_verbose("DIRBASE::CONFIG : %s", env->GetDirectoryPath(DIRBASE::CONFIG).c_str());
log_verbose("DIRBASE::CACHE : %s", env->GetDirectoryPath(DIRBASE::CACHE).c_str());
return env;
}

View File

@@ -29,8 +29,10 @@ namespace OpenRCT2
RCT2, // Base directory for original RollerCoaster Tycoon 2 content.
OPENRCT2, // Base directory for OpenRCT2 installation.
USER, // Base directory for OpenRCT2 user content.
CONFIG, // Base directory for OpenRCT2 configuration.
CACHE, // Base directory for OpenRCT2 cache files.
};
constexpr sint32 DIRBASE_COUNT = 4;
constexpr sint32 DIRBASE_COUNT = 6;
using DIRBASE_VALUES = std::string[DIRBASE_COUNT];
enum class DIRID

View File

@@ -361,20 +361,13 @@ static exitcode_t HandleCommandSetRCT2(CommandLineArgEnumerator * enumerator)
return EXITCODE_FAIL;
}
// Check user path that will contain the config
utf8 userPath[MAX_PATH];
platform_resolve_user_data_path();
platform_get_user_directory(userPath, nullptr, sizeof(userPath));
if (!platform_ensure_directory_exists(userPath)) {
Console::Error::WriteLine("Unable to access or create directory '%s'.", userPath);
return EXITCODE_FAIL;
}
// Update RCT2 path in config
auto env = OpenRCT2::CreatePlatformEnvironment();
auto configPath = env->GetFilePath(OpenRCT2::PATHID::CONFIG);
config_set_defaults();
config_open_default();
config_open(configPath.c_str());
String::DiscardDuplicate(&gConfigGeneral.rct2_path, path);
if (config_save_default())
if (config_save(configPath.c_str()))
{
Console::WriteFormat("Updating RCT2 path to '%s'.", path);
Console::WriteLine();

View File

@@ -27,6 +27,7 @@
#include "../interface/window.h"
#include "../network/network.h"
#include "../OpenRCT2.h"
#include "../PlatformEnvironment.h"
#include "../ui/UiContext.h"
#include "Config.h"
#include "IniReader.hpp"
@@ -665,7 +666,12 @@ extern "C"
}
config_release();
return Config::ReadFile(path);
auto result = Config::ReadFile(path);
if (result)
{
currency_load_custom_currency_config();
}
return result;
}
bool config_save(const utf8 * path)
@@ -707,18 +713,6 @@ extern "C"
Path::Append(outPath, size, "config.ini");
}
bool config_open_default()
{
utf8 path[MAX_PATH];
config_get_default_path(path, sizeof(path));
if (config_open(path))
{
currency_load_custom_currency_config();
return true;
}
return false;
}
bool config_save_default()
{
utf8 path[MAX_PATH];

View File

@@ -251,7 +251,6 @@ extern "C"
void config_get_default_path(utf8 *outPath, size_t size);
void config_set_defaults();
void config_release();
bool config_open_default();
bool config_save_default();
bool config_find_or_browse_install_directory();
#ifdef __cplusplus

View File

@@ -253,6 +253,7 @@ private:
try
{
log_verbose("FileIndex:Writing index: '%s'", _indexPath.c_str());
Path::CreateDirectory(Path::GetDirectory(_indexPath));
auto fs = FileStream(_indexPath, FILE_MODE_WRITE);
// Write header

View File

@@ -79,6 +79,11 @@ namespace Path
return buffer;
}
void CreateDirectory(const std::string &path)
{
platform_ensure_directory_exists(path.c_str());
}
std::string GetFileName(const std::string &path)
{
return GetFileName(path.c_str());

View File

@@ -33,6 +33,7 @@ namespace Path
std::string GetDirectory(const std::string &path);
utf8 * GetDirectory(const utf8 * path);
utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path);
void CreateDirectory(const std::string &path);
std::string GetFileName(const std::string &path);
const utf8 * GetFileName(const utf8 * path);
std::string GetFileNameWithoutExtension(const std::string &path);

View File

@@ -14,14 +14,26 @@
*****************************************************************************/
#pragma endregion
#include "Platform2.h"
#ifdef __ANDROID__
#include "platform.h"
#include "Platform2.h"
namespace Platform
{
uint32 GetTicks()
std::string GetFolderPath(SPECIAL_FOLDER folder)
{
return platform_get_ticks();
// Android builds currently only read from /sdcard/openrct2*
switch (folder)
{
case SPECIAL_FOLDER::USER_CACHE:
case SPECIAL_FOLDER::USER_CONFIG:
case SPECIAL_FOLDER::USER_DATA:
case SPECIAL_FOLDER::USER_HOME:
return "/sdcard";
default:
return std::string();
}
}
}
#endif

View File

@@ -0,0 +1,44 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#ifdef __linux__
#include <pwd.h>
#include "../core/Path.hpp"
#include "Platform2.h"
namespace Platform
{
std::string GetFolderPath(SPECIAL_FOLDER folder)
{
switch (folder)
{
case SPECIAL_FOLDER::USER_CACHE:
case SPECIAL_FOLDER::USER_CONFIG:
case SPECIAL_FOLDER::USER_DATA:
{
auto home = GetFolderPath(SPECIAL_FOLDER::USER_HOME);
return Path::Combine(home, ".config");
}
case SPECIAL_FOLDER::USER_HOME:
return GetHomePath();
default:
return std::string();
}
}
}
#endif

View File

@@ -0,0 +1,87 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
#include <cstring>
#include <pwd.h>
#include <stdlib.h>
#include "../core/String.hpp"
#include "Platform2.h"
#include "platform.h"
namespace Platform
{
uint32 GetTicks()
{
return platform_get_ticks();
}
std::string GetEnvironmentVariable(const std::string &name)
{
return String::ToStd(getenv(name.c_str()));
}
std::string GetEnvironmentPath(const char * name)
{
auto value = getenv(name);
if (value == nullptr)
{
return std::string();
}
else
{
auto colon = std::strchr(value, ':');
if (colon == nullptr)
{
return std::string(value);
}
else
{
return std::string(value, colon);
}
}
}
std::string GetHomePath()
{
std::string path;
auto pw = getpwuid(getuid());
if (pw != nullptr)
{
path = pw->pw_dir;
}
else
{
path = GetEnvironmentVariable("HOME");
}
if (path.empty())
{
path = "/";
}
return path;
}
std::string GetInstallPath()
{
utf8 path[MAX_PATH];
platform_resolve_openrct_data_path();
platform_get_openrct_data_path(path, sizeof(path));
return path;
}
}
#endif

View File

@@ -0,0 +1,149 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlobj.h>
#undef GetEnvironmentVariable
#if !defined(__MINGW32__) && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING))
#define __USE_SHGETKNOWNFOLDERPATH__
#endif
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../core/Util.hpp"
#include "Platform2.h"
#include "platform.h"
namespace Platform
{
uint32 GetTicks()
{
return platform_get_ticks();
}
std::string GetEnvironmentVariable(const std::string &name)
{
std::wstring result;
auto wname = String::ToUtf16(name);
wchar_t wvalue[256];
auto valueSize = GetEnvironmentVariableW(wname.c_str(), wvalue, (DWORD)Util::CountOf(wvalue));
if (valueSize < Util::CountOf(wvalue))
{
result = wvalue;
}
else
{
auto wlvalue = new wchar_t[valueSize];
GetEnvironmentVariableW(wname.c_str(), wlvalue, valueSize);
result = wlvalue;
delete[] wlvalue;
}
return String::ToUtf8(result);
}
static std::string GetHomePathViaEnvironment()
{
std::string result;
auto homedrive = GetEnvironmentVariable("HOMEDRIVE");
auto homepath = GetEnvironmentVariable("HOMEPATH");
if (!homedrive.empty() && !homepath.empty())
{
result = Path::Combine(homedrive, homepath);
}
return result;
}
#ifdef __USE_SHGETKNOWNFOLDERPATH__
static std::string WIN32_GetKnownFolderPath(REFKNOWNFOLDERID rfid)
{
std::string path;
wchar_t * wpath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(rfid, KF_FLAG_CREATE, nullptr, &wpath)))
{
path = String::ToUtf8(std::wstring(wpath));
}
CoTaskMemFree(wpath);
return path;
}
#else
static std::string WIN32_GetFolderPath(int nFolder)
{
std::string path;
wchar_t wpath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(nullptr, nFolder | CSIDL_FLAG_CREATE, nullptr, 0, wpath)))
{
path = String::ToUtf8(std::wstring(wpath));
}
return path;
}
#endif
std::string GetFolderPath(SPECIAL_FOLDER folder)
{
switch (folder)
{
// We currently store everything under Documents/OpenRCT2
case SPECIAL_FOLDER::USER_CACHE:
case SPECIAL_FOLDER::USER_CONFIG:
case SPECIAL_FOLDER::USER_DATA:
{
#ifdef __USE_SHGETKNOWNFOLDERPATH__
auto path = WIN32_GetKnownFolderPath(FOLDERID_Documents);
#else
auto path = WIN32_GetFolderPath(CSIDL_PERSONAL);
#endif
if (path.empty())
{
path = GetFolderPath(SPECIAL_FOLDER::USER_HOME);
}
return path;
}
case SPECIAL_FOLDER::USER_HOME:
{
#ifdef __USE_SHGETKNOWNFOLDERPATH__
auto path = WIN32_GetKnownFolderPath(FOLDERID_Profile);
#else
auto path = WIN32_GetFolderPath(CSIDL_PROFILE);
#endif
if (path.empty())
{
path = GetHomePathViaEnvironment();
if (path.empty())
{
path = "C:\\";
}
}
return path;
}
default:
return std::string();
}
}
std::string GetInstallPath()
{
utf8 path[MAX_PATH];
platform_resolve_openrct_data_path();
platform_get_openrct_data_path(path, sizeof(path));
return path;
}
}
#endif

View File

@@ -0,0 +1,44 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#if defined(__APPLE__) && defined(__MACH__)
#include "../core/Path.hpp"
#include "Platform2.h"
namespace Platform
{
std::string GetFolderPath(SPECIAL_FOLDER folder)
{
// macOS stores everything in ~/Library/Application Support/OpenRCT2
switch (folder)
{
case SPECIAL_FOLDER::USER_CACHE:
case SPECIAL_FOLDER::USER_CONFIG:
case SPECIAL_FOLDER::USER_DATA:
{
auto home = GetFolderPath(SPECIAL_FOLDER::USER_HOME);
return Path::Combine(home, "Library/Application Support");
}
case SPECIAL_FOLDER::USER_HOME:
return GetHomePath();
default:
return std::string();
}
}
}
#endif

View File

@@ -18,11 +18,28 @@
#ifdef __cplusplus
#include <string>
#include "../common.h"
enum class SPECIAL_FOLDER
{
USER_CACHE,
USER_CONFIG,
USER_DATA,
USER_HOME,
};
namespace Platform
{
uint32 GetTicks();
std::string GetEnvironmentVariable(const std::string &name);
std::string GetFolderPath(SPECIAL_FOLDER folder);
std::string GetInstallPath();
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
std::string GetEnvironmentPath(const char * name);
std::string GetHomePath();
#endif
}
#endif

View File

@@ -29,10 +29,6 @@ void platform_get_exe_path(utf8 *outPath, size_t outSize)
safe_strcpy(outPath, "/sdcard/openrct2", outSize);
}
void platform_posix_sub_user_data_path(char *buffer, size_t size, const char *homedir) {
safe_strcpy(buffer, "/sdcard/openrct2-user/", size);
}
#ifndef NO_TTF
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
{

View File

@@ -78,36 +78,6 @@ void platform_get_exe_path(utf8 *outPath, size_t outSize)
safe_strcpy(outPath, exePath, outSize);
}
/**
* Default directory fallback is:
* - (command line argument)
* - $XDG_CONFIG_HOME/OpenRCT2
* - /home/[uid]/.config/OpenRCT2
*/
void platform_posix_sub_user_data_path(char *buffer, size_t size, const char *homedir) {
const char *configdir = getenv("XDG_CONFIG_HOME");
log_verbose("configdir = '%s'", configdir);
if (configdir == NULL)
{
log_verbose("configdir was null, used getuid, now is = '%s'", homedir);
if (homedir == NULL)
{
log_fatal("Couldn't find user data directory");
exit(-1);
return;
}
safe_strcpy(buffer, homedir, size);
safe_strcat_path(buffer, ".config", size);
}
else
{
safe_strcpy(buffer, configdir, size);
}
safe_strcat_path(buffer, "OpenRCT2", size);
path_end_with_separator(buffer, size);
}
/**
* Default directory fallback is:
* - (command line argument)

View File

@@ -56,26 +56,6 @@ void platform_get_exe_path(utf8 *outPath, size_t outSize)
safe_strcpy(outPath, exePath, outSize);
}
/**
* Default directory fallback is:
* - (command line argument)
* - ~/Library/Application Support/OpenRCT2
*/
void platform_posix_sub_user_data_path(char *buffer, size_t size, const char *homedir) {
if (homedir == NULL)
{
log_fatal("Couldn't find user data directory");
exit(-1);
return;
}
safe_strcpy(buffer, homedir, size);
safe_strcat_path(buffer, "Library", size);
safe_strcat_path(buffer, "Application Support", size);
safe_strcat_path(buffer, "OpenRCT2", size);
path_end_with_separator(buffer, size);
}
/**
* Default directory fallback is:
* - (command line argument)

View File

@@ -120,7 +120,6 @@ bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath);
bool platform_file_delete(const utf8 *path);
uint32 platform_get_ticks();
void platform_sleep(uint32 ms);
void platform_resolve_user_data_path();
void platform_resolve_openrct_data_path();
void platform_get_openrct_data_path(utf8 *outPath, size_t outSize);
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize);
@@ -154,6 +153,7 @@ void core_init();
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#undef CreateDirectory
#undef CreateWindow
#undef GetMessage
@@ -167,7 +167,6 @@ void core_init();
#endif // _WIN32
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__ANDROID__)
void platform_posix_sub_user_data_path(char *buffer, size_t size, const char *homedir);
void platform_posix_sub_resolve_openrct_data_path(utf8 *out, size_t size);
#endif

View File

@@ -683,54 +683,6 @@ static wchar_t *regular_to_wchar(const char* src)
return w_buffer;
}
/**
* Default directory fallback is:
* - (command line argument)
* - <platform dependent>
*/
void platform_resolve_user_data_path()
{
if (gCustomUserDataPath[0] != 0) {
if (!platform_ensure_directory_exists(gCustomUserDataPath)) {
log_error("Failed to create directory \"%s\", make sure you have permissions.", gCustomUserDataPath);
return;
}
char *path;
if ((path = realpath(gCustomUserDataPath, NULL)) == NULL) {
log_error("Could not resolve path \"%s\"", gCustomUserDataPath);
return;
}
safe_strcpy(_userDataDirectoryPath, path, MAX_PATH);
free(path);
// Ensure path ends with separator
path_end_with_separator(_userDataDirectoryPath, MAX_PATH);
log_verbose("User data path resolved to: %s", _userDataDirectoryPath);
if (!platform_directory_exists(_userDataDirectoryPath)) {
log_error("Custom user data directory %s does not exist", _userDataDirectoryPath);
}
return;
}
char buffer[MAX_PATH];
log_verbose("buffer = '%s'", buffer);
const char *homedir = getpwuid(getuid())->pw_dir;
platform_posix_sub_user_data_path(buffer, MAX_PATH, homedir);
log_verbose("OpenRCT2 user data directory = '%s'", buffer);
sint32 len = strnlen(buffer, MAX_PATH);
wchar_t *w_buffer = regular_to_wchar(buffer);
w_buffer[len] = '\0';
utf8 *path = widechar_to_utf8(w_buffer);
free(w_buffer);
safe_strcpy(_userDataDirectoryPath, path, MAX_PATH);
free(path);
log_verbose("User data path resolved to: %s", _userDataDirectoryPath);
}
void platform_get_openrct_data_path(utf8 *outPath, size_t outSize)
{
safe_strcpy(outPath, _openrctDataDirectoryPath, outSize);
@@ -778,25 +730,6 @@ void platform_resolve_openrct_data_path()
log_verbose("Trying to use OpenRCT2 data in %s", _openrctDataDirectoryPath);
}
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize)
{
char buffer[MAX_PATH];
safe_strcpy(buffer, _userDataDirectoryPath, sizeof(buffer));
if (subDirectory != NULL && subDirectory[0] != 0) {
log_verbose("adding subDirectory '%s'", subDirectory);
safe_strcat_path(buffer, subDirectory, sizeof(buffer));
path_end_with_separator(buffer, sizeof(buffer));
}
sint32 len = strnlen(buffer, MAX_PATH);
wchar_t *w_buffer = regular_to_wchar(buffer);
w_buffer[len] = '\0';
utf8 *path = widechar_to_utf8(w_buffer);
free(w_buffer);
safe_strcpy(outPath, path, outSize);
free(path);
log_verbose("outPath + subDirectory = '%s'", buffer);
}
time_t platform_file_get_modified_time(const utf8* path){
struct stat buf;
if (stat(path, &buf) == 0) {

View File

@@ -48,7 +48,6 @@
// The name of the mutex used to prevent multiple instances of the game from running
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
static utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
static utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 };
#define OPENRCT2_DLL_MODULE_NAME "openrct2.dll"
@@ -460,52 +459,6 @@ void platform_get_changelog_path(utf8 *outPath, size_t outSize)
safe_strcat_path(outPath, "changelog.txt", outSize);
}
/**
* Default directory fallback is:
* - (command line argument)
* - C:\Users\%USERNAME%\OpenRCT2 (as from SHGetFolderPathW)
*/
void platform_resolve_user_data_path()
{
wchar_t wOutPath[MAX_PATH];
if (gCustomUserDataPath[0] != 0) {
wchar_t *customUserDataPathW = utf8_to_widechar(gCustomUserDataPath);
if (GetFullPathNameW(customUserDataPathW, countof(wOutPath), wOutPath, NULL) == 0) {
log_fatal("Unable to resolve path '%s'.", gCustomUserDataPath);
exit(-1);
}
utf8 *outPathTemp = widechar_to_utf8(wOutPath);
safe_strcpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath));
free(outPathTemp);
free(customUserDataPathW);
path_end_with_separator(_userDataDirectoryPath, sizeof(_userDataDirectoryPath));
return;
}
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, wOutPath))) {
utf8 *outPathTemp = widechar_to_utf8(wOutPath);
safe_strcpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath));
free(outPathTemp);
safe_strcat_path(_userDataDirectoryPath, "OpenRCT2", sizeof(_userDataDirectoryPath));
path_end_with_separator(_userDataDirectoryPath, sizeof(_userDataDirectoryPath));
} else {
log_fatal("Unable to resolve user data path.");
exit(-1);
}
}
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize)
{
safe_strcpy(outPath, _userDataDirectoryPath, outSize);
if (subDirectory != NULL && subDirectory[0] != 0) {
safe_strcat_path(outPath, subDirectory, outSize);
path_end_with_separator(outPath, outSize);
}
}
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
{
wchar_t * wSteamPath;

View File

@@ -385,6 +385,10 @@ char *safe_strcat(char *destination, const char *source, size_t size)
char *safe_strcat_path(char *destination, const char *source, size_t size)
{
path_end_with_separator(destination, size);
if (source[0] == *PATH_SEPARATOR)
{
source = source + 1;
}
return safe_strcat(destination, source, size);
}