Refactor IPlatformEnvironment (#5590)

This commit is contained in:
Ted John 2017-06-11 12:53:37 +01:00 committed by GitHub
parent b563d26ffe
commit 0d8f9d6618
15 changed files with 184 additions and 146 deletions

View File

@ -17,6 +17,7 @@
#include <openrct2/audio/AudioContext.h>
#include <openrct2/Context.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/PlatformEnvironment.h>
#include <openrct2/ui/UiContext.h>
#include "audio/AudioContext.h"
#include "Ui.h"
@ -49,9 +50,10 @@ int main(int argc, char * * argv)
else
{
// Run OpenRCT2 with a UI context
auto env = CreatePlatformEnvironment();
auto audioContext = CreateAudioContext();
auto uiContext = CreateUiContext();
auto context = CreateContext(audioContext, uiContext);
auto uiContext = CreateUiContext(env);
auto context = CreateContext(env, audioContext, uiContext);
context->RunOpenRCT2(argc, argv);

View File

@ -59,7 +59,8 @@ class UiContext final : public IUiContext
private:
constexpr static uint32 TOUCH_DOUBLE_TIMEOUT = 300;
IPlatformUiContext * const _platformUiContext;
IPlatformEnvironment * const _env;
IPlatformUiContext * const _platformUiContext;
CursorRepository _cursorRepository;
@ -84,14 +85,18 @@ private:
float _gestureRadius = 0;
public:
UiContext()
: _platformUiContext(CreatePlatformUiContext())
UiContext(IPlatformEnvironment * env)
: _env(env),
_platformUiContext(CreatePlatformUiContext())
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
SDLException::Throw("SDL_Init(SDL_INIT_VIDEO)");
}
_cursorRepository.LoadCursors();
// Temporary to prevent warning, will be used for keyboard shortcuts
UNUSED(_env);
}
~UiContext() override
@ -690,7 +695,7 @@ private:
}
};
IUiContext * OpenRCT2::Ui::CreateUiContext()
IUiContext * OpenRCT2::Ui::CreateUiContext(IPlatformEnvironment * env)
{
return new UiContext();
return new UiContext(env);
}

View File

@ -24,6 +24,7 @@ struct SDL_Window;
namespace OpenRCT2
{
interface IContext;
interface IPlatformEnvironment;
namespace Ui
{
@ -41,7 +42,7 @@ namespace OpenRCT2
virtual std::string ShowDirectoryDialog(SDL_Window * window, const std::string &title) abstract;
};
IUiContext * CreateUiContext();
IUiContext * CreateUiContext(IPlatformEnvironment * env);
IPlatformUiContext * CreatePlatformUiContext();
}
}

View File

@ -70,11 +70,11 @@ namespace OpenRCT2
constexpr static uint32 UPDATE_TIME_MS = 25;
// Dependencies
IAudioContext * const _audioContext = nullptr;
IUiContext * const _uiContext = nullptr;
IPlatformEnvironment * const _env = nullptr;
IAudioContext * const _audioContext = nullptr;
IUiContext * const _uiContext = nullptr;
// Services
IPlatformEnvironment * _env = nullptr;
IObjectRepository * _objectRepository = nullptr;
ITrackDesignRepository * _trackDesignRepository = nullptr;
IScenarioRepository * _scenarioRepository = nullptr;
@ -93,8 +93,9 @@ namespace OpenRCT2
static Context * Instance;
public:
Context(IAudioContext * audioContext, IUiContext * uiContext)
: _audioContext(audioContext),
Context(IPlatformEnvironment * env, IAudioContext * audioContext, IUiContext * uiContext)
: _env(env),
_audioContext(audioContext),
_uiContext(uiContext)
{
Instance = this;
@ -151,13 +152,6 @@ namespace OpenRCT2
crash_init();
// Sets up the environment OpenRCT2 is running in, e.g. directory paths
_env = SetupEnvironment();
if (_env == nullptr)
{
return false;
}
if (!rct2_interop_setup_segment())
{
log_fatal("Unable to load RCT2 data sector");
@ -237,64 +231,6 @@ namespace OpenRCT2
}
private:
IPlatformEnvironment * SetupEnvironment()
{
utf8 userPath[MAX_PATH];
platform_resolve_openrct_data_path();
platform_resolve_user_data_path();
platform_get_user_directory(userPath, NULL, sizeof(userPath));
if (!platform_ensure_directory_exists(userPath))
{
Console::Error::WriteLine("Could not create user directory (do you have write access to your documents folder?)");
return nullptr;
}
platform_get_exe_path(gExePath, sizeof(gExePath));
log_verbose("Setting exe path to %s", gExePath);
config_set_defaults();
if (!config_open_default())
{
if (!config_find_or_browse_install_directory())
{
gConfigGeneral.last_run_version = String::Duplicate(OPENRCT2_VERSION);
config_save_default();
utf8 path[MAX_PATH];
config_get_default_path(path, sizeof(path));
Console::Error::WriteLine("An RCT2 install directory must be specified! Please edit \"game_path\" in %s.", path);
return nullptr;
}
config_save_default();
}
if (!rct2_init_directories())
{
return nullptr;
}
if (!rct2_startup_checks())
{
return nullptr;
}
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 = CreatePlatformEnvironment(basePaths);
// 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());
return env;
}
/**
* Launches the game, after command line arguments have been parsed and processed.
*/
@ -564,18 +500,20 @@ namespace OpenRCT2
class PlainContext final : public Context
{
std::unique_ptr<IAudioContext> _audioContext;
std::unique_ptr<IUiContext> _uiContext;
std::unique_ptr<IPlatformEnvironment> _env;
std::unique_ptr<IAudioContext> _audioContext;
std::unique_ptr<IUiContext> _uiContext;
public:
PlainContext()
: PlainContext(CreateDummyAudioContext(), CreateDummyUiContext())
: PlainContext(CreatePlatformEnvironment(), CreateDummyAudioContext(), CreateDummyUiContext())
{
}
PlainContext(IAudioContext * audioContext, IUiContext * uiContext)
: Context(audioContext, uiContext)
PlainContext(IPlatformEnvironment * env, IAudioContext * audioContext, IUiContext * uiContext)
: Context(env, audioContext, uiContext)
{
_env = std::unique_ptr<IPlatformEnvironment>(env);
_audioContext = std::unique_ptr<IAudioContext>(audioContext);
_uiContext = std::unique_ptr<IUiContext>(uiContext);
}
@ -588,9 +526,9 @@ namespace OpenRCT2
return new PlainContext();
}
IContext * CreateContext(Audio::IAudioContext * audioContext, IUiContext * uiContext)
IContext * CreateContext(IPlatformEnvironment * env, Audio::IAudioContext * audioContext, IUiContext * uiContext)
{
return new Context(audioContext, uiContext);
return new Context(env, audioContext, uiContext);
}
IContext * GetContext()

View File

@ -59,6 +59,8 @@ enum
namespace OpenRCT2
{
interface IPlatformEnvironment;
namespace Audio
{
interface IAudioContext;
@ -86,7 +88,7 @@ namespace OpenRCT2
};
IContext * CreateContext();
IContext * CreateContext(Audio::IAudioContext * audioContext, Ui::IUiContext * uiContext);
IContext * CreateContext(IPlatformEnvironment * env, Audio::IAudioContext * audioContext, Ui::IUiContext * uiContext);
IContext * GetContext();
}

View File

@ -14,17 +14,24 @@
*****************************************************************************/
#pragma endregion
#include "config/Config.h"
#include "core/Console.hpp"
#include "core/Exception.hpp"
#include "core/Guard.hpp"
#include "core/Path.hpp"
#include "core/String.hpp"
#include "OpenRCT2.h"
#include "PlatformEnvironment.h"
#include "Version.h"
extern "C"
{
#include "platform/platform.h"
#include "rct2.h"
}
using namespace OpenRCT2;
class PlatformEnvironment final : public IPlatformEnvironment
{
private:
@ -84,11 +91,69 @@ private:
static const char * FileNames[];
};
IPlatformEnvironment * CreatePlatformEnvironment(DIRBASE_VALUES basePaths)
IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment(DIRBASE_VALUES basePaths)
{
return new PlatformEnvironment(basePaths);
}
IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment()
{
utf8 userPath[MAX_PATH];
platform_resolve_openrct_data_path();
platform_resolve_user_data_path();
platform_get_user_directory(userPath, NULL, sizeof(userPath));
if (!platform_ensure_directory_exists(userPath))
{
Console::Error::WriteLine("Could not create user directory (do you have write access to your documents folder?)");
return nullptr;
}
platform_get_exe_path(gExePath, sizeof(gExePath));
log_verbose("Setting exe path to %s", gExePath);
config_set_defaults();
if (!config_open_default())
{
if (!config_find_or_browse_install_directory())
{
gConfigGeneral.last_run_version = String::Duplicate(OPENRCT2_VERSION);
config_save_default();
utf8 path[MAX_PATH];
config_get_default_path(path, sizeof(path));
Console::Error::WriteLine("An RCT2 install directory must be specified! Please edit \"game_path\" in %s.", path);
return nullptr;
}
config_save_default();
}
if (!rct2_init_directories())
{
return nullptr;
}
if (!rct2_startup_checks())
{
return nullptr;
}
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);
// 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());
return env;
}
const char * PlatformEnvironment::DirectoryNamesRCT2[] =
{
"Data", // DATA

View File

@ -19,58 +19,62 @@
#include <string>
#include "common.h"
enum class DIRBASE : sint32
namespace OpenRCT2
{
RCT1, // Base directory for original RollerCoaster Tycoon 1 content.
RCT2, // Base directory for original RollerCoaster Tycoon 2 content.
OPENRCT2, // Base directory for OpenRCT2 installation.
USER, // Base directory for OpenRCT2 user content.
};
constexpr sint32 DIRBASE_COUNT = 4;
using DIRBASE_VALUES = std::string[DIRBASE_COUNT];
enum class DIRBASE : sint32
{
RCT1, // Base directory for original RollerCoaster Tycoon 1 content.
RCT2, // Base directory for original RollerCoaster Tycoon 2 content.
OPENRCT2, // Base directory for OpenRCT2 installation.
USER, // Base directory for OpenRCT2 user content.
};
constexpr sint32 DIRBASE_COUNT = 4;
using DIRBASE_VALUES = std::string[DIRBASE_COUNT];
enum class DIRID
{
DATA, // Contains g1.dat, music etc.
LANDSCAPE, // Contains scenario editor landscapes (SC6).
LANGUAGE, // Contains language packs.
LOG_CHAT, // Contains chat logs.
LOG_SERVER, // Contains server logs.
NETWORK_KEY, // Contains the user's public and private keys.
OBJECT, // Contains objects.
SAVE, // Contains saved games (SV6).
SCENARIO, // Contains scenarios (SC6).
SCREENSHOT, // Contains screenshots.
SEQUENCE, // Contains title sequences.
SHADER, // Contains OpenGL shaders.
THEME, // Contains interface themes.
TRACK, // Contains track designs.
};
enum class DIRID
{
DATA, // Contains g1.dat, music etc.
LANDSCAPE, // Contains scenario editor landscapes (SC6).
LANGUAGE, // Contains language packs.
LOG_CHAT, // Contains chat logs.
LOG_SERVER, // Contains server logs.
NETWORK_KEY, // Contains the user's public and private keys.
OBJECT, // Contains objects.
SAVE, // Contains saved games (SV6).
SCENARIO, // Contains scenarios (SC6).
SCREENSHOT, // Contains screenshots.
SEQUENCE, // Contains title sequences.
SHADER, // Contains OpenGL shaders.
THEME, // Contains interface themes.
TRACK, // Contains track designs.
};
enum class PATHID
{
CONFIG, // Main configuration (config.ini).
CONFIG_KEYBOARD, // Keyboard shortcuts. (hotkeys.cfg)
CACHE_OBJECTS, // Object repository cache (objects.idx).
CACHE_TRACKS, // Track repository cache (tracks.idx).
NETWORK_GROUPS, // Server groups with permissions (groups.json).
NETWORK_SERVERS, // Saved servers (servers.cfg).
NETWORK_USERS, // Users and their groups (users.json).
SCORES, // Scenario scores (highscores.dat).
SCORES_LEGACY, // Scenario scores, legacy (scores.dat).
SCORES_RCT2, // Scenario scores, rct2 (\Saved Games\scores.dat).
};
enum class PATHID
{
CONFIG, // Main configuration (config.ini).
CONFIG_KEYBOARD, // Keyboard shortcuts. (hotkeys.cfg)
CACHE_OBJECTS, // Object repository cache (objects.idx).
CACHE_TRACKS, // Track repository cache (tracks.idx).
NETWORK_GROUPS, // Server groups with permissions (groups.json).
NETWORK_SERVERS, // Saved servers (servers.cfg).
NETWORK_USERS, // Users and their groups (users.json).
SCORES, // Scenario scores (highscores.dat).
SCORES_LEGACY, // Scenario scores, legacy (scores.dat).
SCORES_RCT2, // Scenario scores, rct2 (\Saved Games\scores.dat).
};
/**
* Interface for retrieving paths and other environment related things.
*/
interface IPlatformEnvironment
{
virtual ~IPlatformEnvironment() = default;
/**
* Interface for retrieving paths and other environment related things.
*/
interface IPlatformEnvironment
{
virtual ~IPlatformEnvironment() = default;
virtual std::string GetDirectoryPath(DIRBASE base) const abstract;
virtual std::string GetDirectoryPath(DIRBASE base, DIRID did) const abstract;
virtual std::string GetFilePath(PATHID pathid) const abstract;
};
virtual std::string GetDirectoryPath(DIRBASE base) const abstract;
virtual std::string GetDirectoryPath(DIRBASE base, DIRID did) const abstract;
virtual std::string GetFilePath(PATHID pathid) const abstract;
};
IPlatformEnvironment * CreatePlatformEnvironment(DIRBASE_VALUES basePaths);
IPlatformEnvironment * CreatePlatformEnvironment(DIRBASE_VALUES basePaths);
IPlatformEnvironment * CreatePlatformEnvironment();
}

View File

@ -74,6 +74,8 @@ extern "C" {
#pragma comment(lib, "Ws2_32.lib")
using namespace OpenRCT2;
Network gNetwork;
enum {

View File

@ -85,15 +85,19 @@ enum {
NETWORK_TICK_FLAG_CHECKSUMS = 1 << 0,
};
interface IPlatformEnvironment;
struct ObjectRepositoryItem;
struct ObjectRepositoryItem;
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
class Network
{
public:
Network();
~Network();
void SetEnvironment(IPlatformEnvironment * env);
void SetEnvironment(OpenRCT2::IPlatformEnvironment * env);
bool Init();
void Close();
bool BeginClient(const char* host, uint16 port);
@ -231,7 +235,7 @@ private:
std::string _chatLogFilenameFormat = "%Y%m%d-%H%M%S.txt";
std::string _serverLogPath;
std::string _serverLogFilenameFormat = "-%Y%m%d-%H%M%S.txt";
IPlatformEnvironment * _env;
OpenRCT2::IPlatformEnvironment * _env;
void UpdateServer();
void UpdateClient();

View File

@ -53,6 +53,8 @@ extern "C"
#include "../util/util.h"
}
using namespace OpenRCT2;
constexpr uint16 OBJECT_REPOSITORY_VERSION = 10;
#pragma pack(push, 1)

View File

@ -32,9 +32,12 @@ extern "C"
#endif
#ifdef __cplusplus
interface IPlatformEnvironment;
interface IStream;
class Object;
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
#else
typedef struct Object Object;
#endif
@ -87,7 +90,7 @@ interface IObjectRepository
virtual void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem *> &objects) abstract;
};
IObjectRepository * CreateObjectRepository(IPlatformEnvironment * env);
IObjectRepository * CreateObjectRepository(OpenRCT2::IPlatformEnvironment * env);
IObjectRepository * GetObjectRepository();
bool IsObjectCustom(const ObjectRepositoryItem * object);

View File

@ -36,6 +36,8 @@ extern "C"
#include "track_design.h"
}
using namespace OpenRCT2;
#pragma pack(push, 1)
struct TrackRepositoryHeader
{

View File

@ -28,7 +28,10 @@ typedef struct track_design_file_ref
#include <string>
interface IPlatformEnvironment;
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
interface ITrackDesignRepository
{
@ -46,7 +49,7 @@ interface ITrackDesignRepository
virtual std::string Install(const std::string &path) abstract;
};
ITrackDesignRepository * CreateTrackDesignRepository(IPlatformEnvironment * env);
ITrackDesignRepository * CreateTrackDesignRepository(OpenRCT2::IPlatformEnvironment * env);
ITrackDesignRepository * GetTrackDesignRepository();
#endif

View File

@ -39,6 +39,8 @@ extern "C"
#include "scenario.h"
}
using namespace OpenRCT2;
static sint32 ScenarioCategoryCompare(sint32 categoryA, sint32 categoryB)
{
if (categoryA == categoryB) return 0;

View File

@ -56,7 +56,10 @@ typedef struct scenario_index_entry
#ifdef __cplusplus
interface IPlatformEnvironment;
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
interface IScenarioRepository
{
@ -75,7 +78,7 @@ interface IScenarioRepository
virtual bool TryRecordHighscore(const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) abstract;
};
IScenarioRepository * CreateScenarioRepository(IPlatformEnvironment * env);
IScenarioRepository * CreateScenarioRepository(OpenRCT2::IPlatformEnvironment * env);
IScenarioRepository * GetScenarioRepository();
#endif