Refactor load park result

Use a C++ struct and pass that to C.
This commit is contained in:
Ted John 2017-07-01 01:26:23 +01:00
parent d75295b027
commit ddb96ec267
20 changed files with 257 additions and 219 deletions

View File

@ -21,6 +21,65 @@
#include "object/ObjectRepository.h"
#include "ParkImporter.h"
ParkLoadResult::ParkLoadResult(PARK_LOAD_ERROR error)
: Error(error)
{
}
ParkLoadResult::ParkLoadResult(PARK_LOAD_ERROR error, const std::vector<rct_object_entry> &missingObjects)
: Error(error),
MissingObjects(missingObjects)
{
}
ParkLoadResult ParkLoadResult::CreateOK()
{
return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_OK);
}
ParkLoadResult ParkLoadResult::CreateInvalidExtension()
{
return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_INVALID_EXTENSION);
}
ParkLoadResult ParkLoadResult::CreateMissingObjects(const std::vector<rct_object_entry> &missingObjects)
{
return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_MISSING_OBJECTS, missingObjects);
}
ParkLoadResult ParkLoadResult::CreateUnknown()
{
return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_UNKNOWN);
}
extern "C"
{
PARK_LOAD_ERROR ParkLoadResult_GetError(const ParkLoadResult * t)
{
return t->Error;
}
size_t ParkLoadResult_GetMissingObjectsCount(const ParkLoadResult * t)
{
return t->MissingObjects.size();
}
const rct_object_entry * ParkLoadResult_GetMissingObjects(const ParkLoadResult * t)
{
return t->MissingObjects.data();
}
void ParkLoadResult_Delete(ParkLoadResult * t)
{
delete t;
}
ParkLoadResult * ParkLoadResult_CreateInvalidExtension()
{
return new ParkLoadResult(ParkLoadResult::CreateInvalidExtension());
}
}
namespace ParkImporter
{
IParkImporter * Create(const std::string &hintPath)

View File

@ -22,20 +22,45 @@
extern "C"
{
#endif
#include "park_load_result_types.h"
#include "object.h"
#ifdef __cplusplus
}
#endif
typedef enum PARK_LOAD_ERROR
{
PARK_LOAD_ERROR_OK,
PARK_LOAD_ERROR_MISSING_OBJECTS,
PARK_LOAD_ERROR_INVALID_EXTENSION,
PARK_LOAD_ERROR_UNKNOWN = 255
} PARK_LOAD_ERROR;
#ifdef __cplusplus
#include <string>
#include <vector>
#include "scenario/ScenarioRepository.h"
interface IObjectManager;
interface IObjectRepository;
interface IStream;
struct ParkLoadResult final
{
public:
const PARK_LOAD_ERROR Error;
const std::vector<rct_object_entry> MissingObjects;
static ParkLoadResult CreateOK();
static ParkLoadResult CreateInvalidExtension();
static ParkLoadResult CreateMissingObjects(const std::vector<rct_object_entry> &missingObjects);
static ParkLoadResult CreateUnknown();
private:
ParkLoadResult(PARK_LOAD_ERROR error);
ParkLoadResult(PARK_LOAD_ERROR error, const std::vector<rct_object_entry> &missingObjects);
};
/**
* Interface to import scenarios and saved games.
*/
@ -43,10 +68,12 @@ interface IParkImporter
{
public:
virtual ~IParkImporter() = default;
virtual park_load_result * Load(const utf8 * path) abstract;
virtual park_load_result * LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) abstract;
virtual park_load_result * LoadScenario(const utf8 * path, bool skipObjectCheck = false) abstract;
virtual park_load_result * LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) abstract;
virtual ParkLoadResult Load(const utf8 * path) abstract;
virtual ParkLoadResult LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) abstract;
virtual ParkLoadResult LoadScenario(const utf8 * path, bool skipObjectCheck = false) abstract;
virtual ParkLoadResult LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) abstract;
virtual void Import() abstract;
virtual bool GetDetails(scenario_index_entry * dst) abstract;
};
@ -61,6 +88,10 @@ namespace ParkImporter
bool ExtensionIsScenario(const std::string &extension);
}
#else
typedef struct ParkLoadResult ParkLoadResult;
#endif
#ifdef __cplusplus
@ -70,6 +101,11 @@ extern "C"
void park_importer_load_from_stream(void * stream, const utf8 * hintPath);
bool park_importer_extension_is_scenario(const utf8 * extension);
PARK_LOAD_ERROR ParkLoadResult_GetError(const ParkLoadResult * t);
size_t ParkLoadResult_GetMissingObjectsCount(const ParkLoadResult * t);
const rct_object_entry * ParkLoadResult_GetMissingObjects(const ParkLoadResult * t);
void ParkLoadResult_Delete(ParkLoadResult * t);
ParkLoadResult * ParkLoadResult_CreateInvalidExtension();
#ifdef __cplusplus
}
#endif

View File

@ -31,6 +31,7 @@
#include "platform/platform.h"
#include "rct1.h"
#include "ride/ride.h"
#include "ParkImporter.h"
#include "scenario/scenario.h"
#include "util/sawyercoding.h"
#include "util/util.h"
@ -261,16 +262,18 @@ static sint32 editor_load_landscape_from_sc4(const char *path)
*/
static sint32 editor_read_s6(const char *path)
{
park_load_result* loadResult = { 0 };
ParkLoadResult * loadResult = NULL;
const char *extension = path_get_extension(path);
if (_stricmp(extension, ".sc6") == 0) {
loadResult = scenario_load(path);
} else if (_stricmp(extension, ".sv6") == 0) {
loadResult = game_load_sv6_path(path);
}
if (loadResult->error != PARK_LOAD_ERROR_NONE) {
if (ParkLoadResult_GetError(loadResult) != PARK_LOAD_ERROR_OK) {
ParkLoadResult_Delete(loadResult);
return 0;
}
ParkLoadResult_Delete(loadResult);
editor_clear_map_for_editing(true);

View File

@ -33,6 +33,7 @@
#include "network/network.h"
#include "object.h"
#include "OpenRCT2.h"
#include "ParkImporter.h"
#include "peep/peep.h"
#include "peep/staff.h"
#include "platform/platform.h"
@ -1094,15 +1095,16 @@ bool game_load_save(const utf8 *path)
safe_strcpy(gScenarioSavePath, path, MAX_PATH);
uint32 extension_type = get_file_extension_type(path);
park_load_result* result = {0};
ParkLoadResult * result = NULL;
bool load_success = false;
if (extension_type == FILE_EXTENSION_SV6) {
result = game_load_sv6_path(path);
load_success = (result->error == PARK_LOAD_ERROR_NONE);
load_success = (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK);
if (load_success)
gFirstTimeSaving = false;
} else if (extension_type == FILE_EXTENSION_SV4) {
load_success = rct1_load_saved_game(path);
result = rct1_load_saved_game(path);
load_success = (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK);
if (load_success)
gFirstTimeSaving = true;
}
@ -1126,20 +1128,20 @@ bool game_load_save(const utf8 *path)
}
}
void handle_park_load_failure(park_load_result* result, const utf8* path)
void handle_park_load_failure(const ParkLoadResult * result, const utf8 * path)
{
if (result->error == PARK_LOAD_ERROR_BAD_OBJECTS)
if (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_MISSING_OBJECTS)
{
// The path needs to be duplicated as it's a const here
// which the window function doesn't like
window_object_load_error_open(strndup(path, strnlen(path, MAX_PATH)), result->object_validity);
}
else if (result->error != PARK_LOAD_ERROR_NONE) {
window_object_load_error_open(strndup(path, strnlen(path, MAX_PATH)),
ParkLoadResult_GetMissingObjectsCount(result),
ParkLoadResult_GetMissingObjects(result));
} else if (ParkLoadResult_GetError(result) != PARK_LOAD_ERROR_OK) {
// If loading the SV6 or SV4 failed for a reason other than invalid objects
// the current park state will be corrupted so just go back to the title screen.
title_load();
}
SafeFree(result);
}
void game_load_init()
@ -1378,7 +1380,6 @@ void rct2_exit()
bool game_load_save_or_scenario(const utf8 * path)
{
park_load_result* result;
uint32 extension = get_file_extension_type(path);
switch (extension) {
case FILE_EXTENSION_SV4:
@ -1386,8 +1387,12 @@ bool game_load_save_or_scenario(const utf8 * path)
return game_load_save(path);
case FILE_EXTENSION_SC4:
case FILE_EXTENSION_SC6:
result = scenario_load_and_play_from_path(path);
return (result->error == PARK_LOAD_ERROR_NONE);
{
ParkLoadResult * result = scenario_load_and_play_from_path(path);
bool success = (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK);
ParkLoadResult_Delete(result);
return success;
}
}
return false;
}

View File

@ -20,7 +20,6 @@
#include "rct2/addresses.h"
#include "common.h"
#include "scenario/scenario.h"
#include "park_load_result_types.h"
enum GAME_COMMAND {
GAME_COMMAND_SET_RIDE_APPEARANCE,
@ -171,7 +170,7 @@ sint32 game_do_command_p(sint32 command, sint32 *eax, sint32 *ebx, sint32 *ecx,
void game_log_multiplayer_command(int command, int *eax, int* ebx, int* ecx, int* edx, int* edi, int* ebp);
void game_load_or_quit_no_save_prompt();
park_load_result * game_load_sv6_path(const char * path);
ParkLoadResult * game_load_sv6_path(const char * path);
bool game_load_save(const utf8 *path);
void game_load_init();
void game_pause_toggle(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp);
@ -180,7 +179,7 @@ bool game_is_paused();
bool game_is_not_paused();
void save_game();
void save_game_as();
void handle_park_load_failure(park_load_result* result, const utf8* path);
void handle_park_load_failure(const ParkLoadResult * result, const utf8 * path);
void rct2_exit();
void rct2_exit_reason(rct_string_id title, rct_string_id body);
void game_autosave();

View File

@ -767,7 +767,7 @@ rct_window *window_mapgen_open();
rct_window *window_loadsave_open(sint32 type, char *defaultName);
rct_window *window_changelog_open();
void window_debug_paint_open();
rct_window *window_object_load_error_open(utf8* path, object_validity_result* result);
rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects, const rct_object_entry * missingObjects);
rct_window * window_editor_main_open();
void window_editor_bottom_toolbar_open();

View File

@ -447,10 +447,10 @@ private:
return duplicate;
}
object_validity_result* GetInvalidObjects(const rct_object_entry * entries) override
std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) override
{
uint16 invalidObjectCount = 0;
rct_object_entry * * invalidEntries = Memory::AllocateArray<rct_object_entry *>(OBJECT_ENTRY_COUNT);
std::vector<rct_object_entry> invalidEntries;
invalidEntries.reserve(OBJECT_ENTRY_COUNT);
for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++)
{
const rct_object_entry * entry = &entries[i];
@ -460,7 +460,7 @@ private:
ori = _objectRepository->FindObject(entry);
if (ori == nullptr)
{
invalidEntries[invalidObjectCount++] = DuplicateObjectEntry(entry);
invalidEntries.push_back(*entry);
}
else
{
@ -471,16 +471,14 @@ private:
loadedObject = _objectRepository->LoadObject(ori);
if (loadedObject == nullptr)
{
invalidEntries[invalidObjectCount++] = DuplicateObjectEntry(entry);
invalidEntries.push_back(*entry);
}
delete loadedObject;
}
}
}
}
object_validity_result* result = Memory::Allocate<object_validity_result>(sizeof(object_validity_result));
result->invalid_object_count = invalidObjectCount;
result->invalid_objects = invalidEntries;
return result;
return invalidEntries;
}
bool GetRequiredObjects(const rct_object_entry * entries,

View File

@ -27,7 +27,6 @@ extern "C"
{
#endif
#include "../object.h"
#include "../park_load_result_types.h"
#ifdef __cplusplus
}
#endif
@ -42,10 +41,10 @@ interface IObjectManager
{
virtual ~IObjectManager() { }
virtual Object * GetLoadedObject(size_t index) abstract;
virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract;
virtual uint8 GetLoadedObjectEntryIndex(const Object * object) abstract;
virtual object_validity_result* GetInvalidObjects(const rct_object_entry * entries) abstract;
virtual Object * GetLoadedObject(size_t index) abstract;
virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract;
virtual uint8 GetLoadedObjectEntryIndex(const Object * object) abstract;
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) abstract;
virtual Object * LoadObject(const rct_object_entry * entry) abstract;
virtual bool LoadObjects(const rct_object_entry * entries, size_t count) abstract;

View File

@ -1,40 +0,0 @@
#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
#ifndef _PARK_LOAD_RESULT_H_
#define _PARK_LOAD_RESULT_H_
#include "object.h"
enum PARK_LOAD_ERROR {
PARK_LOAD_ERROR_NONE,
PARK_LOAD_ERROR_BAD_OBJECTS,
PARK_LOAD_ERROR_INVALID_EXTENSION,
PARK_LOAD_ERROR_UNKNOWN = 255
};
typedef struct object_validity_result
{
uint16 invalid_object_count;
rct_object_entry * * invalid_objects;
} object_validity_result;
typedef struct park_load_result {
uint8 error;
object_validity_result* object_validity;
} park_load_result;
#endif

View File

@ -20,7 +20,6 @@
#include "management/award.h"
#include "management/news_item.h"
#include "management/research.h"
#include "park_load_result_types.h"
#include "rct12.h"
#include "rct2.h"
#include "ride/ride.h"
@ -35,6 +34,8 @@
#define RCT1_MAX_RIDES_IN_PARK 128
#define RCT1_RESEARCH_FLAGS_SEPARATOR 0xFF
typedef struct ParkLoadResult ParkLoadResult;
#pragma pack(push, 1)
typedef struct rct1_entrance {
uint16 x;
@ -1210,8 +1211,8 @@ extern const uint8 gRideCategories[RIDE_TYPE_COUNT];
sint32 vehicle_preference_compare(uint8 rideType, const char * a, const char * b);
bool rideTypeShouldLoseSeparateFlag(const rct_ride_entry *rideEntry);
park_load_result * rct1_load_saved_game(const char *path);
park_load_result * rct1_load_scenario(const char *path);
ParkLoadResult * rct1_load_saved_game(const char *path);
ParkLoadResult * rct1_load_scenario(const char *path);
colour_t rct1_get_colour(colour_t colour);

View File

@ -26,6 +26,7 @@
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../core/Util.hpp"
#include "../object/Object.h"
#include "../object/ObjectManager.h"
#include "../object/ObjectRepository.h"
#include "../ParkImporter.h"
@ -126,7 +127,7 @@ private:
uint8 _researchRideTypeUsed[128];
public:
park_load_result* Load(const utf8 * path) override
ParkLoadResult Load(const utf8 * path) override
{
const utf8 * extension = Path::GetExtension(path);
if (String::Equals(extension, ".sc4", true))
@ -143,27 +144,24 @@ public:
}
}
park_load_result* LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override
ParkLoadResult LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override
{
auto fs = FileStream(path, FILE_MODE_OPEN);
park_load_result* result = LoadFromStream(&fs, false, skipObjectCheck);
auto result = LoadFromStream(&fs, false, skipObjectCheck);
_s4Path = path;
return result;
}
park_load_result* LoadScenario(const utf8 * path, bool skipObjectCheck = false) override
ParkLoadResult LoadScenario(const utf8 * path, bool skipObjectCheck = false) override
{
auto fs = FileStream(path, FILE_MODE_OPEN);
park_load_result* result = LoadFromStream(&fs, true, skipObjectCheck);
auto result = LoadFromStream(&fs, true, skipObjectCheck);
_s4Path = path;
return result;
}
park_load_result* LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override
ParkLoadResult LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override
{
park_load_result* result = Memory::Allocate<park_load_result>(sizeof(park_load_result));
result->error = PARK_LOAD_ERROR_NONE;
size_t dataSize = stream->GetLength() - stream->GetPosition();
std::unique_ptr<uint8> data = std::unique_ptr<uint8>(stream->ReadArray<uint8>(dataSize));
std::unique_ptr<uint8> decodedData = std::unique_ptr<uint8>(Memory::Allocate<uint8>(sizeof(rct1_s4)));
@ -188,12 +186,11 @@ public:
{
InitialiseEntryMaps();
CreateAvailableObjectMappings();
object_validity_result* object_result = GetInvalidObjects();
result->object_validity = object_result;
if (object_result->invalid_object_count > 0)
auto missingObjects = GetInvalidObjects();
if (missingObjects.size() > 0)
{
result->error = PARK_LOAD_ERROR_BAD_OBJECTS;
return ParkLoadResult::CreateMissingObjects(missingObjects);
}
}
}
@ -201,7 +198,7 @@ public:
{
throw Exception("Unable to decode park.");
}
return result;
return ParkLoadResult::CreateOK();
}
void Import() override
@ -1751,22 +1748,16 @@ private:
}
}
object_validity_result* GetInvalidObjects()
std::vector<rct_object_entry> GetInvalidObjects()
{
object_validity_result* result = Memory::Allocate<object_validity_result>(sizeof(object_validity_result));
uint16 invalidObjectCount = 0;
rct_object_entry * * invalidEntries = Memory::AllocateArray<rct_object_entry *>(OBJECT_ENTRY_COUNT);
result->invalid_object_count = invalidObjectCount;
result->invalid_objects = invalidEntries;
GetInvalidObjects(OBJECT_TYPE_RIDE, _rideEntries.GetEntries(), *result);
GetInvalidObjects(OBJECT_TYPE_SMALL_SCENERY, _smallSceneryEntries.GetEntries(), *result);
GetInvalidObjects(OBJECT_TYPE_LARGE_SCENERY, _largeSceneryEntries.GetEntries(), *result);
GetInvalidObjects(OBJECT_TYPE_WALLS, _wallEntries.GetEntries(), *result);
GetInvalidObjects(OBJECT_TYPE_PATHS, _pathEntries.GetEntries(), *result);
GetInvalidObjects(OBJECT_TYPE_PATH_BITS, _pathAdditionEntries.GetEntries(), *result);
GetInvalidObjects(OBJECT_TYPE_SCENERY_SETS, _sceneryGroupEntries.GetEntries(), *result);
std::vector<rct_object_entry> missingObjects;
GetInvalidObjects(OBJECT_TYPE_RIDE, _rideEntries.GetEntries(), missingObjects);
GetInvalidObjects(OBJECT_TYPE_SMALL_SCENERY, _smallSceneryEntries.GetEntries(), missingObjects);
GetInvalidObjects(OBJECT_TYPE_LARGE_SCENERY, _largeSceneryEntries.GetEntries(), missingObjects);
GetInvalidObjects(OBJECT_TYPE_WALLS, _wallEntries.GetEntries(), missingObjects);
GetInvalidObjects(OBJECT_TYPE_PATHS, _pathEntries.GetEntries(), missingObjects);
GetInvalidObjects(OBJECT_TYPE_PATH_BITS, _pathAdditionEntries.GetEntries(), missingObjects);
GetInvalidObjects(OBJECT_TYPE_SCENERY_SETS, _sceneryGroupEntries.GetEntries(), missingObjects);
GetInvalidObjects(OBJECT_TYPE_BANNERS, std::vector<const char *>({
"BN1 ",
"BN2 ",
@ -1777,14 +1768,13 @@ private:
"BN7 ",
"BN8 ",
"BN9 "
}), *result);
GetInvalidObjects(OBJECT_TYPE_PARK_ENTRANCE, std::vector<const char *>({ "PKENT1 " }), *result);
GetInvalidObjects(OBJECT_TYPE_WATER, _waterEntry.GetEntries(), *result);
return result;
}), missingObjects);
GetInvalidObjects(OBJECT_TYPE_PARK_ENTRANCE, std::vector<const char *>({ "PKENT1 " }), missingObjects);
GetInvalidObjects(OBJECT_TYPE_WATER, _waterEntry.GetEntries(), missingObjects);
return missingObjects;
}
void GetInvalidObjects(uint8 objectType, const std::vector<const char *> &entries, object_validity_result &result)
void GetInvalidObjects(uint8 objectType, const std::vector<const char *> &entries, std::vector<rct_object_entry> &missingObjects)
{
IObjectRepository * objectRepository = GetObjectRepository();
for (const char * objectName : entries)
@ -1794,26 +1784,19 @@ private:
Memory::Copy(entry.name, objectName, 8);
entry.checksum = 0;
const ObjectRepositoryItem * ori = nullptr;
ori = objectRepository->FindObject(&entry);
const ObjectRepositoryItem * ori = objectRepository->FindObject(&entry);
if (ori == nullptr)
{
rct_object_entry * invalid_entry = Memory::Allocate<rct_object_entry>(sizeof(rct_object_entry));
invalid_entry->flags = entry.flags;
Memory::Copy(invalid_entry->name, objectName, 8);
result.invalid_objects[result.invalid_object_count++] = invalid_entry;
missingObjects.push_back(entry);
}
else
{
Object * object = objectRepository->LoadObject(ori);
if (object == nullptr && objectType != OBJECT_TYPE_SCENERY_SETS)
{
rct_object_entry * invalid_entry = Memory::Allocate<rct_object_entry>(sizeof(rct_object_entry));
invalid_entry->flags = entry.flags;
Memory::Copy(invalid_entry->name, objectName, 8);
result.invalid_objects[result.invalid_object_count++] = invalid_entry;
missingObjects.push_back(entry);
}
SafeFree(object);
delete object;
}
}
}
@ -2661,46 +2644,43 @@ IParkImporter * ParkImporter::CreateS4()
/////////////////////////////////////////
extern "C"
{
park_load_result* rct1_load_saved_game(const utf8 * path)
ParkLoadResult * rct1_load_saved_game(const utf8 * path)
{
park_load_result* result = {};
auto s4Importer = new S4Importer();
ParkLoadResult * result = nullptr;
auto s4Importer = std::make_unique<S4Importer>();
try
{
result = s4Importer->LoadSavedGame(path);
if (result->error == PARK_LOAD_ERROR_NONE)
result = new ParkLoadResult(s4Importer->LoadSavedGame(path));
if (result->Error == PARK_LOAD_ERROR_OK)
{
s4Importer->Import();
}
} catch (const Exception &)
{
result = {};
result->error = PARK_LOAD_ERROR_UNKNOWN;
}
delete s4Importer;
catch (const Exception &)
{
delete result;
result = new ParkLoadResult(ParkLoadResult::CreateUnknown());
}
return result;
}
park_load_result* rct1_load_scenario(const utf8 * path)
ParkLoadResult * rct1_load_scenario(const utf8 * path)
{
park_load_result* result = {};
auto s4Importer = new S4Importer();
ParkLoadResult * result = nullptr;
auto s4Importer = std::make_unique<S4Importer>();
try
{
result = s4Importer->LoadSavedGame(path);
if (result->error == PARK_LOAD_ERROR_NONE)
result = new ParkLoadResult(s4Importer->LoadSavedGame(path));
if (result->Error == PARK_LOAD_ERROR_OK)
{
s4Importer->Import();
}
} catch (const Exception &)
{
result = {};
result->error = PARK_LOAD_ERROR_UNKNOWN;
}
delete s4Importer;
catch (const Exception &)
{
delete result;
result = new ParkLoadResult(ParkLoadResult::CreateUnknown());
}
return result;
}

View File

@ -38,6 +38,7 @@
#include "object.h"
#include "object/ObjectManager.h"
#include "OpenRCT2.h"
#include "ParkImporter.h"
#include "peep/staff.h"
#include "platform/platform.h"
#include "rct1.h"
@ -339,12 +340,13 @@ bool rct2_open_file(const char *path)
}
} else if (_stricmp(extension, "sc6") == 0) {
// TODO scenario install
park_load_result *result = scenario_load_and_play_from_path(path);
if (result->error == PARK_LOAD_ERROR_NONE) {
ParkLoadResult * result = scenario_load_and_play_from_path(path);
if (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK) {
ParkLoadResult_Delete(result);
return true;
}
else {
} else {
handle_park_load_failure(result, path);
ParkLoadResult_Delete(result);
return false;
}
} else if (_stricmp(extension, "td6") == 0 || _stricmp(extension, "td4") == 0) {

View File

@ -81,7 +81,7 @@ public:
Memory::Set(&_s6, 0, sizeof(_s6));
}
park_load_result* Load(const utf8 * path) override
ParkLoadResult Load(const utf8 * path) override
{
const utf8 * extension = Path::GetExtension(path);
if (String::Equals(extension, ".sc6", true))
@ -98,29 +98,24 @@ public:
}
}
park_load_result* LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override
ParkLoadResult LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override
{
auto fs = FileStream(path, FILE_MODE_OPEN);
park_load_result* result = LoadFromStream(&fs, false, skipObjectCheck);
auto result = LoadFromStream(&fs, false, skipObjectCheck);
_s6Path = path;
return result;
}
park_load_result* LoadScenario(const utf8 * path, bool skipObjectCheck = false) override
ParkLoadResult LoadScenario(const utf8 * path, bool skipObjectCheck = false) override
{
auto fs = FileStream(path, FILE_MODE_OPEN);
park_load_result* result = LoadFromStream(&fs, true, skipObjectCheck);
auto result = LoadFromStream(&fs, true, skipObjectCheck);
_s6Path = path;
return result;
}
park_load_result* LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override
ParkLoadResult LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override
{
park_load_result* result = Memory::Allocate<park_load_result>(sizeof(park_load_result));
result->error = PARK_LOAD_ERROR_UNKNOWN;
if (isScenario && !gConfigGeneral.allow_loading_with_incorrect_checksum && !SawyerEncoding::ValidateChecksum(stream))
{
throw IOException("Invalid checksum.");
@ -175,18 +170,12 @@ public:
chunkReader.ReadChunk(&_s6.next_free_map_element_pointer_index, 3048816);
}
object_validity_result* object_result = _objectManager->GetInvalidObjects(_s6.objects);
result->object_validity = object_result;
if (object_result->invalid_object_count > 0)
auto missingObjects = _objectManager->GetInvalidObjects(_s6.objects);
if (missingObjects.size() > 0)
{
result->error = PARK_LOAD_ERROR_BAD_OBJECTS;
return ParkLoadResult::CreateMissingObjects(missingObjects);
}
else
{
result->error = PARK_LOAD_ERROR_NONE;
}
return result;
return ParkLoadResult::CreateOK();
}
bool GetDetails(scenario_index_entry * dst) override
@ -439,17 +428,17 @@ IParkImporter * ParkImporter::CreateS6(IObjectRepository * objectRepository, IOb
extern "C"
{
park_load_result* game_load_sv6_path(const char * path)
ParkLoadResult * game_load_sv6_path(const char * path)
{
park_load_result* result = {};
ParkLoadResult * result = nullptr;
auto s6Importer = new S6Importer(GetObjectRepository(), GetObjectManager());
try
{
result = s6Importer->LoadSavedGame(path);
result = new ParkLoadResult(s6Importer->LoadSavedGame(path));
// We mustn't import if there's something
// wrong with the park data
if (result->error == PARK_LOAD_ERROR_NONE)
if (result->Error == PARK_LOAD_ERROR_OK)
{
s6Importer->Import();
@ -474,7 +463,11 @@ extern "C"
}
delete s6Importer;
if (result->error == PARK_LOAD_ERROR_NONE)
if (result == nullptr)
{
result = new ParkLoadResult(ParkLoadResult::CreateUnknown());
}
if (result->Error == PARK_LOAD_ERROR_OK)
{
gScreenAge = 0;
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;
@ -487,14 +480,14 @@ extern "C"
* rct2: 0x00676053
* scenario (ebx)
*/
park_load_result* scenario_load(const char * path)
ParkLoadResult * scenario_load(const char * path)
{
park_load_result* result = {};
ParkLoadResult * result = nullptr;
auto s6Importer = new S6Importer(GetObjectRepository(), GetObjectManager());
try
{
result = s6Importer->LoadScenario(path);
if (result->error == PARK_LOAD_ERROR_NONE)
result = new ParkLoadResult(s6Importer->LoadScenario(path));
if (result->Error == PARK_LOAD_ERROR_OK)
{
s6Importer->Import();
@ -518,7 +511,12 @@ extern "C"
gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA;
}
delete s6Importer;
if (result->error != PARK_LOAD_ERROR_NONE)
if (result == nullptr)
{
result = new ParkLoadResult(ParkLoadResult::CreateUnknown());
}
if (result->Error != PARK_LOAD_ERROR_OK)
{
gScreenAge = 0;
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;

View File

@ -30,6 +30,7 @@
#include "../object.h"
#include "../object_list.h"
#include "../OpenRCT2.h"
#include "../ParkImporter.h"
#include "../peep/staff.h"
#include "../platform/platform.h"
#include "../rct1.h"
@ -88,28 +89,24 @@ money32 gScenarioCompanyValueRecord;
static sint32 scenario_create_ducks();
static void scenario_objective_check();
park_load_result* scenario_load_and_play_from_path(const char *path)
ParkLoadResult * scenario_load_and_play_from_path(const char * path)
{
window_close_construction_windows();
uint32 extension = get_file_extension_type(path);
park_load_result* result = malloc(sizeof(park_load_result));
ParkLoadResult * result = NULL;
if (extension == FILE_EXTENSION_SC6) {
result = scenario_load(path);
if (result->error != PARK_LOAD_ERROR_NONE)
{
if (ParkLoadResult_GetError(result) != PARK_LOAD_ERROR_OK) {
return result;
}
}
else if (extension == FILE_EXTENSION_SC4) {
} else if (extension == FILE_EXTENSION_SC4) {
result = rct1_load_scenario(path);
if (result->error != PARK_LOAD_ERROR_NONE)
{
if (ParkLoadResult_GetError(result) != PARK_LOAD_ERROR_OK) {
return result;
}
}
else {
result->error = PARK_LOAD_ERROR_INVALID_EXTENSION;
} else {
result = ParkLoadResult_CreateInvalidExtension();
return result;
}

View File

@ -21,7 +21,6 @@
#include "../management/finance.h"
#include "../management/research.h"
#include "../object.h"
#include "../park_load_result_types.h"
#include "../rct12.h"
#include "../rct2.h"
#include "../rct2/addresses.h"
@ -32,6 +31,8 @@
#include "../world/map_animation.h"
#include "../world/sprite.h"
typedef struct ParkLoadResult ParkLoadResult;
#pragma pack(push, 1)
/**
* SV6/SC6 header chunk
@ -390,8 +391,8 @@ extern uint32 gLastAutoSaveUpdate;
extern const char *_scenarioFileName;
park_load_result *scenario_load(const char *path);
park_load_result *scenario_load_and_play_from_path(const char *path);
ParkLoadResult * scenario_load(const char *path);
ParkLoadResult * scenario_load_and_play_from_path(const char *path);
void scenario_begin();
void scenario_update();

View File

@ -19,7 +19,6 @@
#include <time.h>
#include "../common.h"
#include "../park_load_result_types.h"
sint32 squaredmetres_to_squaredfeet(sint32 squaredMetres);
sint32 metres_to_feet(sint32 metres);

View File

@ -21,7 +21,6 @@
#include "../object.h"
#include "../platform/platform.h"
#include "../sprites.h"
#include "../util/util.h"
enum WINDOW_OBJECT_LOAD_ERROR_WIDGET_IDX {
WIDX_BACKGROUND,
@ -91,7 +90,7 @@ static rct_window_event_list window_object_load_error_events = {
window_object_load_error_scrollpaint
};
rct_object_entry * * invalid_entries = NULL;
rct_object_entry * invalid_entries = NULL;
sint32 highlighted_index = -1;
utf8* file_path = NULL;
@ -168,20 +167,20 @@ static utf8* combine_object_names(rct_window *w)
for (uint16 i = 0; i < w->no_list_items; i++) {
cur_len += (8 + line_sep_len);
assert(cur_len < buffer_len);
strncat(buffer, invalid_entries[i]->name, 8);
strncat(buffer, invalid_entries[i].name, 8);
strncat(buffer, PLATFORM_NEWLINE, line_sep_len);
}
return buffer;
}
rct_window *window_object_load_error_open(utf8* path, object_validity_result* result)
rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects, const rct_object_entry * missingObjects)
{
rct_window* window;
invalid_entries = result->invalid_objects;
size_t missingObjectsSize = numMissingObjects * sizeof(rct_object_entry);
invalid_entries = malloc(missingObjectsSize);
memcpy(invalid_entries, missingObjects, missingObjectsSize);
// Check if window is already open
window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR);
rct_window * window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR);
if (window == NULL) {
window = window_create_centred(
WW,
@ -201,7 +200,7 @@ rct_window *window_object_load_error_open(utf8* path, object_validity_result* re
}
// Refresh list items and path
window->no_list_items = result->invalid_object_count;
window->no_list_items = (uint16)numMissingObjects;
file_path = path;
window_invalidate(window);
@ -232,7 +231,7 @@ static void window_object_load_error_mouseup(rct_window *w, rct_widgetindex widg
break;
case WIDX_COPY_CURRENT:
if (w->selected_list_item > -1) {
selected_name = strndup(invalid_entries[w->selected_list_item]->name, 8);
selected_name = strndup(invalid_entries[w->selected_list_item].name, 8);
platform_place_string_on_clipboard(selected_name);
SafeFree(selected_name);
}
@ -296,7 +295,6 @@ static void window_object_load_error_paint(rct_window *w, rct_drawpixelinfo *dpi
static void window_object_load_error_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex)
{
gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ColourMapA[w->colours[1]].mid_light);
const sint32 list_width = w->widgets[WIDX_SCROLL].right - w->widgets[WIDX_SCROLL].left;
@ -317,12 +315,10 @@ static void window_object_load_error_scrollpaint(rct_window *w, rct_drawpixelinf
gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000);
// Draw the actual object entry's name...
gfx_draw_string(dpi, strndup(invalid_entries[i]->name, 8), COLOUR_DARK_GREEN, 5, y);
gfx_draw_string(dpi, strndup(invalid_entries[i].name, 8), COLOUR_DARK_GREEN, 5, y);
// ... and type
rct_string_id type = get_object_type_string(invalid_entries[i]);
rct_string_id type = get_object_type_string(&invalid_entries[i]);
gfx_draw_string_left(dpi, type, NULL, COLOUR_DARK_GREEN, (WW - 5) / 3 + 1, y);
}
}

View File

@ -21,6 +21,7 @@
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../network/network.h"
#include "../ParkImporter.h"
#include "../platform/platform.h"
#include "../sprites.h"
#include "../title/TitleScreen.h"
@ -165,14 +166,14 @@ static void window_server_start_close(rct_window *w)
static void window_server_start_scenarioselect_callback(const utf8 *path)
{
park_load_result* result;
network_set_password(_password);
result = scenario_load_and_play_from_path(path);
if (result->error == PARK_LOAD_ERROR_NONE) {
ParkLoadResult * result = scenario_load_and_play_from_path(path);
if (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK) {
network_begin_server(gConfigNetwork.default_port, gConfigNetwork.listen_address);
} else {
handle_park_load_failure(result, path);
}
ParkLoadResult_Delete(result);
}
static void window_server_start_loadsave_callback(sint32 result, const utf8 * path)

View File

@ -22,6 +22,7 @@
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../ParkImporter.h"
#include "../sprites.h"
#include "../title/TitleScreen.h"
#include "../util/util.h"
@ -129,8 +130,9 @@ void window_title_menu_open()
static void window_title_menu_scenarioselect_callback(const utf8 *path)
{
park_load_result *result = scenario_load_and_play_from_path(path);
ParkLoadResult * result = scenario_load_and_play_from_path(path);
handle_park_load_failure(result, path);
ParkLoadResult_Delete(result);
}
static void window_title_menu_mouseup(rct_window *w, rct_widgetindex widgetIndex)

View File

@ -30,6 +30,7 @@
#include "../localisation/localisation.h"
#include "../network/network.h"
#include "../network/twitch.h"
#include "../ParkImporter.h"
#include "../peep/staff.h"
#include "../scenario/scenario.h"
#include "../sprites.h"
@ -519,8 +520,9 @@ static void window_top_toolbar_mousedown(rct_widgetindex widgetIndex, rct_window
static void window_top_toolbar_scenarioselect_callback(const utf8 *path)
{
park_load_result *result = scenario_load_and_play_from_path(path);
ParkLoadResult * result = scenario_load_and_play_from_path(path);
handle_park_load_failure(result, path);
ParkLoadResult_Delete(result);
}
/**