clang-format object

This commit is contained in:
clang-format 2018-06-22 23:03:20 +02:00 committed by Hielke Morsink
parent e32189fd98
commit a6a12af1ec
42 changed files with 1452 additions and 1283 deletions

View File

@ -7,16 +7,17 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "BannerObject.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../object/Object.h" #include "../object/Object.h"
#include "../object/ObjectRepository.h" #include "../object/ObjectRepository.h"
#include "BannerObject.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
#include "ObjectList.h" #include "ObjectList.h"
void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void BannerObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.banner.scrolling_mode = stream->ReadValue<uint8_t>(); _legacyType.banner.scrolling_mode = stream->ReadValue<uint8_t>();
@ -47,9 +48,9 @@ void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
if (item != nullptr) if (item != nullptr)
{ {
auto objectEntry = &item->ObjectEntry; auto objectEntry = &item->ObjectEntry;
if (object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_WACKY_WORLDS || if (object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_WACKY_WORLDS
object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_TIME_TWISTER || || object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_TIME_TWISTER
object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_CUSTOM) || object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_CUSTOM)
{ {
auto scgPathX = Object::GetScgPathXHeader(); auto scgPathX = Object::GetScgPathXHeader();
SetPrimarySceneryGroup(&scgPathX); SetPrimarySceneryGroup(&scgPathX);
@ -73,7 +74,7 @@ void BannerObject::Unload()
_legacyType.image = 0; _legacyType.image = 0;
} }
void BannerObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void BannerObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
int32_t x = width / 2; int32_t x = width / 2;
int32_t y = height / 2; int32_t y = height / 2;
@ -83,14 +84,14 @@ void BannerObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t h
gfx_draw_sprite(dpi, imageId + 1, x - 12, y + 8, 0); gfx_draw_sprite(dpi, imageId + 1, x - 12, y + 8, 0);
} }
void BannerObject::ReadJson(IReadObjectContext * context, const json_t * root) void BannerObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.banner.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); _legacyType.banner.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
_legacyType.banner.price = json_integer_value(json_object_get(properties, "price")); _legacyType.banner.price = json_integer_value(json_object_get(properties, "price"));
_legacyType.banner.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, { _legacyType.banner.flags
{ "hasPrimaryColour", BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR }}); = ObjectJsonHelpers::GetFlags<uint8_t>(properties, { { "hasPrimaryColour", BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR } });
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));

View File

@ -9,24 +9,29 @@
#pragma once #pragma once
#include "SceneryObject.h"
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "SceneryObject.h"
class BannerObject final : public SceneryObject class BannerObject final : public SceneryObject
{ {
private: private:
rct_scenery_entry _legacyType = {}; rct_scenery_entry _legacyType = {};
public: public:
explicit BannerObject(const rct_object_entry &entry) : SceneryObject(entry) { } explicit BannerObject(const rct_object_entry& entry)
: SceneryObject(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
}; };

View File

@ -8,50 +8,49 @@
*****************************************************************************/ *****************************************************************************/
#include "DefaultObjects.h" #include "DefaultObjects.h"
#include "Object.h" #include "Object.h"
/** rct2: 0x0098DA74 */ /** rct2: 0x0098DA74 */
const rct_object_entry RequiredSelectedObjects[7] = const rct_object_entry RequiredSelectedObjects[7] = {
{
// Objects that are always required // Objects that are always required
{ 0x00000087, { "SCGTREES" } }, // Scenery: Trees { 0x00000087, { "SCGTREES" } }, // Scenery: Trees
{ 0x00000087, { "SCGSHRUB" } }, // Scenery: Shrubs and Ornaments { 0x00000087, { "SCGSHRUB" } }, // Scenery: Shrubs and Ornaments
{ 0x00000087, { "SCGGARDN" } }, // Scenery: Gardens { 0x00000087, { "SCGGARDN" } }, // Scenery: Gardens
{ 0x00000087, { "SCGFENCE" } }, // Scenery: Fences and Walls { 0x00000087, { "SCGFENCE" } }, // Scenery: Fences and Walls
{ 0x00000087, { "SCGWALLS" } }, // Scenery: Walls and Roofs { 0x00000087, { "SCGWALLS" } }, // Scenery: Walls and Roofs
{ 0x00000087, { "SCGPATHX" } }, // Scenery: Signs and Items for Footpaths { 0x00000087, { "SCGPATHX" } }, // Scenery: Signs and Items for Footpaths
{ 0x00000085, { "TARMAC " } }, // Footpath: Tarmac { 0x00000085, { "TARMAC " } }, // Footpath: Tarmac
}; };
const rct_object_entry DefaultSelectedObjects[26] = const rct_object_entry DefaultSelectedObjects[26] = {
{
// An initial default selection // An initial default selection
{ 0x00000080, { "TWIST1 " } }, // Ride: Twist { 0x00000080, { "TWIST1 " } }, // Ride: Twist
{ 0x00000080, { "PTCT1 " } }, // Ride: Wooden Roller Coaster (Wooden Roller Coaster Trains) { 0x00000080, { "PTCT1 " } }, // Ride: Wooden Roller Coaster (Wooden Roller Coaster Trains)
{ 0x00000080, { "ZLDB " } }, // Ride: Junior Roller Coaster (Ladybird Trains) { 0x00000080, { "ZLDB " } }, // Ride: Junior Roller Coaster (Ladybird Trains)
{ 0x00000080, { "LFB1 " } }, // Ride: Log Flume { 0x00000080, { "LFB1 " } }, // Ride: Log Flume
{ 0x00000080, { "VCR " } }, // Ride: Vintage Cars { 0x00000080, { "VCR " } }, // Ride: Vintage Cars
{ 0x00000080, { "MGR1 " } }, // Ride: Merry-Go-Round { 0x00000080, { "MGR1 " } }, // Ride: Merry-Go-Round
{ 0x00000080, { "TLT1 " } }, // Ride: Restroom { 0x00000080, { "TLT1 " } }, // Ride: Restroom
{ 0x00000080, { "ATM1 " } }, // Ride: Cash Machine { 0x00000080, { "ATM1 " } }, // Ride: Cash Machine
{ 0x00000080, { "FAID1 " } }, // Ride: First Aid Room { 0x00000080, { "FAID1 " } }, // Ride: First Aid Room
{ 0x00000080, { "INFOK " } }, // Ride: Information Kiosk { 0x00000080, { "INFOK " } }, // Ride: Information Kiosk
{ 0x00000080, { "DRNKS " } }, // Ride: Drinks Stall { 0x00000080, { "DRNKS " } }, // Ride: Drinks Stall
{ 0x00000080, { "CNDYF " } }, // Ride: Candyfloss Stall { 0x00000080, { "CNDYF " } }, // Ride: Candyfloss Stall
{ 0x00000080, { "BURGB " } }, // Ride: Burger Bar { 0x00000080, { "BURGB " } }, // Ride: Burger Bar
{ 0x00000080, { "BALLN " } }, // Ride: Balloon Stall { 0x00000080, { "BALLN " } }, // Ride: Balloon Stall
{ 0x00000080, { "ARRT1 " } }, // Ride: Corkscrew Roller Coaster { 0x00000080, { "ARRT1 " } }, // Ride: Corkscrew Roller Coaster
{ 0x00000080, { "RBOAT " } }, // Ride: Rowing Boats { 0x00000080, { "RBOAT " } }, // Ride: Rowing Boats
{ 0x00000088, { "PKENT1 " } }, // Park Entrance: Traditional Park Entrance { 0x00000088, { "PKENT1 " } }, // Park Entrance: Traditional Park Entrance
{ 0x00000089, { "WTRCYAN " } }, // Water: Natural Water { 0x00000089, { "WTRCYAN " } }, // Water: Natural Water
{ 0x00000085, { "TARMACB " } }, // Footpath: Brown Tarmac Footpath { 0x00000085, { "TARMACB " } }, // Footpath: Brown Tarmac Footpath
{ 0x00000085, { "PATHSPCE" } }, // Footpath: Space Style Footpath { 0x00000085, { "PATHSPCE" } }, // Footpath: Space Style Footpath
{ 0x00000085, { "PATHDIRT" } }, // Footpath: Dirt Footpath { 0x00000085, { "PATHDIRT" } }, // Footpath: Dirt Footpath
{ 0x00000085, { "PATHCRZY" } }, // Footpath: Crazy Paving Footpath { 0x00000085, { "PATHCRZY" } }, // Footpath: Crazy Paving Footpath
{ 0x00000085, { "PATHASH " } }, // Footpath: Ash Footpath { 0x00000085, { "PATHASH " } }, // Footpath: Ash Footpath
// The following are for all random map generation features to work out the box // The following are for all random map generation features to work out the box
{ 0x00000087, { "SCGJUNGL" } }, // Jungle Theming { 0x00000087, { "SCGJUNGL" } }, // Jungle Theming
{ 0x00000087, { "SCGSNOW " } }, // Snow and Ice Theming { 0x00000087, { "SCGSNOW " } }, // Snow and Ice Theming
{ 0x00000087, { "SCGWATER" } } // Water Feature Theming { 0x00000087, { "SCGWATER" } } // Water Feature Theming
}; };

View File

@ -7,14 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "EntranceObject.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../localisation/Localisation.h" #include "../localisation/Localisation.h"
#include "EntranceObject.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
void EntranceObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void EntranceObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.scrolling_mode = stream->ReadValue<uint8_t>(); _legacyType.scrolling_mode = stream->ReadValue<uint8_t>();
@ -48,18 +49,18 @@ void EntranceObject::Unload()
_legacyType.image_id = 0; _legacyType.image_id = 0;
} }
void EntranceObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void EntranceObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
int32_t x = width / 2; int32_t x = width / 2;
int32_t y = height / 2; int32_t y = height / 2;
uint32_t imageId = _legacyType.image_id; uint32_t imageId = _legacyType.image_id;
gfx_draw_sprite(dpi, imageId + 1, x - 32, y + 14, 0); gfx_draw_sprite(dpi, imageId + 1, x - 32, y + 14, 0);
gfx_draw_sprite(dpi, imageId + 0, x + 0, y + 28, 0); gfx_draw_sprite(dpi, imageId + 0, x + 0, y + 28, 0);
gfx_draw_sprite(dpi, imageId + 2, x + 32, y + 44, 0); gfx_draw_sprite(dpi, imageId + 2, x + 32, y + 44, 0);
} }
void EntranceObject::ReadJson(IReadObjectContext * context, const json_t * root) void EntranceObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));

View File

@ -9,9 +9,8 @@
#pragma once #pragma once
#include "Object.h"
#include "../world/Entrance.h" #include "../world/Entrance.h"
#include "Object.h"
class EntranceObject final : public Object class EntranceObject final : public Object
{ {
@ -19,14 +18,20 @@ private:
rct_entrance_type _legacyType = {}; rct_entrance_type _legacyType = {};
public: public:
explicit EntranceObject(const rct_object_entry &entry) : Object(entry) { } explicit EntranceObject(const rct_object_entry& entry)
: Object(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
}; };

View File

@ -7,18 +7,20 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <unordered_map> #include "FootpathItemObject.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../interface/Cursors.h" #include "../interface/Cursors.h"
#include "../localisation/Localisation.h" #include "../localisation/Localisation.h"
#include "../object/Object.h" #include "../object/Object.h"
#include "../object/ObjectRepository.h" #include "../object/ObjectRepository.h"
#include "ObjectList.h"
#include "FootpathItemObject.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
#include "ObjectList.h"
void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stream) #include <unordered_map>
void FootpathItemObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.path_bit.flags = stream->ReadValue<uint16_t>(); _legacyType.path_bit.flags = stream->ReadValue<uint16_t>();
@ -50,9 +52,8 @@ void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stre
if (item != nullptr) if (item != nullptr)
{ {
auto sourceGame = object_entry_get_source_game(&item->ObjectEntry); auto sourceGame = object_entry_get_source_game(&item->ObjectEntry);
if (sourceGame == OBJECT_SOURCE_WACKY_WORLDS || if (sourceGame == OBJECT_SOURCE_WACKY_WORLDS || sourceGame == OBJECT_SOURCE_TIME_TWISTER
sourceGame == OBJECT_SOURCE_TIME_TWISTER || || sourceGame == OBJECT_SOURCE_CUSTOM)
sourceGame == OBJECT_SOURCE_CUSTOM)
{ {
auto scgPathX = Object::GetScgPathXHeader(); auto scgPathX = Object::GetScgPathXHeader();
SetPrimarySceneryGroup(&scgPathX); SetPrimarySceneryGroup(&scgPathX);
@ -78,40 +79,46 @@ void FootpathItemObject::Unload()
_legacyType.image = 0; _legacyType.image = 0;
} }
void FootpathItemObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void FootpathItemObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
int32_t x = width / 2; int32_t x = width / 2;
int32_t y = height / 2; int32_t y = height / 2;
gfx_draw_sprite(dpi, _legacyType.image, x - 22, y - 24, 0); gfx_draw_sprite(dpi, _legacyType.image, x - 22, y - 24, 0);
} }
static uint8_t ParseDrawType(const std::string &s) static uint8_t ParseDrawType(const std::string& s)
{ {
if (s == "lamp") return PATH_BIT_DRAW_TYPE_LIGHTS; if (s == "lamp")
if (s == "bin") return PATH_BIT_DRAW_TYPE_BINS; return PATH_BIT_DRAW_TYPE_LIGHTS;
if (s == "bench") return PATH_BIT_DRAW_TYPE_BENCHES; if (s == "bin")
if (s == "fountain") return PATH_BIT_DRAW_TYPE_JUMPING_FOUNTAINS; return PATH_BIT_DRAW_TYPE_BINS;
if (s == "bench")
return PATH_BIT_DRAW_TYPE_BENCHES;
if (s == "fountain")
return PATH_BIT_DRAW_TYPE_JUMPING_FOUNTAINS;
return PATH_BIT_DRAW_TYPE_LIGHTS; return PATH_BIT_DRAW_TYPE_LIGHTS;
} }
void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * root) void FootpathItemObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(properties, "renderAs")); _legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(properties, "renderAs"));
_legacyType.path_bit.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_LAMPPOST_DOWN); _legacyType.path_bit.tool_id
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_LAMPPOST_DOWN);
_legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price")); _legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price"));
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
// Flags // Flags
_legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, { _legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags<uint16_t>(
{ "isBin", PATH_BIT_FLAG_IS_BIN }, properties,
{ "isBench", PATH_BIT_FLAG_IS_BENCH }, { { "isBin", PATH_BIT_FLAG_IS_BIN },
{ "isBreakable", PATH_BIT_FLAG_BREAKABLE }, { "isBench", PATH_BIT_FLAG_IS_BENCH },
{ "isLamp", PATH_BIT_FLAG_LAMP }, { "isBreakable", PATH_BIT_FLAG_BREAKABLE },
{ "isJumpingFountainWater", PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER }, { "isLamp", PATH_BIT_FLAG_LAMP },
{ "isJumpingFountainSnow", PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW }, { "isJumpingFountainWater", PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER },
{ "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }}); { "isJumpingFountainSnow", PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW },
{ "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN } });
// HACK To avoid 'negated' properties in JSON, handle these separately until // HACK To avoid 'negated' properties in JSON, handle these separately until
// flags are inverted in this code base. // flags are inverted in this code base.

View File

@ -9,24 +9,29 @@
#pragma once #pragma once
#include "SceneryObject.h"
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "SceneryObject.h"
class FootpathItemObject final : public SceneryObject class FootpathItemObject final : public SceneryObject
{ {
private: private:
rct_scenery_entry _legacyType = {}; rct_scenery_entry _legacyType = {};
public: public:
explicit FootpathItemObject(const rct_object_entry &entry) : SceneryObject(entry) { } explicit FootpathItemObject(const rct_object_entry& entry)
: SceneryObject(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
}; };

View File

@ -7,14 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "FootpathObject.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../world/Footpath.h" #include "../world/Footpath.h"
#include "FootpathObject.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
void FootpathObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void FootpathObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(10, STREAM_SEEK_CURRENT); stream->Seek(10, STREAM_SEEK_CURRENT);
_legacyType.support_type = stream->ReadValue<uint8_t>(); _legacyType.support_type = stream->ReadValue<uint8_t>();
@ -49,7 +50,7 @@ void FootpathObject::Unload()
_legacyType.image = 0; _legacyType.image = 0;
} }
void FootpathObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void FootpathObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
int32_t x = width / 2; int32_t x = width / 2;
int32_t y = height / 2; int32_t y = height / 2;
@ -57,23 +58,26 @@ void FootpathObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t
gfx_draw_sprite(dpi, _legacyType.image + 72, x + 4, y - 17, 0); gfx_draw_sprite(dpi, _legacyType.image + 72, x + 4, y - 17, 0);
} }
static uint8_t ParseSupportType(const std::string &s) static uint8_t ParseSupportType(const std::string& s)
{ {
if (s == "pole") return FOOTPATH_ENTRY_SUPPORT_TYPE_POLE; if (s == "pole")
else /* if (s == "box") */ return FOOTPATH_ENTRY_SUPPORT_TYPE_BOX; return FOOTPATH_ENTRY_SUPPORT_TYPE_POLE;
else /* if (s == "box") */
return FOOTPATH_ENTRY_SUPPORT_TYPE_BOX;
} }
void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) void FootpathObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.support_type = ParseSupportType(ObjectJsonHelpers::GetString(json_object_get(properties, "supportType"))); _legacyType.support_type = ParseSupportType(ObjectJsonHelpers::GetString(json_object_get(properties, "supportType")));
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
// Flags // Flags
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, { _legacyType.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
{ "hasSupportImages", FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE }, properties,
{ "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE }, { { "hasSupportImages", FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE },
{ "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } }); { "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE },
{ "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } });
ObjectJsonHelpers::LoadStrings(root, GetStringTable()); ObjectJsonHelpers::LoadStrings(root, GetStringTable());
ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); ObjectJsonHelpers::LoadImages(context, root, GetImageTable());

View File

@ -9,9 +9,8 @@
#pragma once #pragma once
#include "Object.h"
#include "../world/Footpath.h" #include "../world/Footpath.h"
#include "Object.h"
class FootpathObject final : public Object class FootpathObject final : public Object
{ {
@ -19,14 +18,20 @@ private:
rct_footpath_entry _legacyType = {}; rct_footpath_entry _legacyType = {};
public: public:
explicit FootpathObject(const rct_object_entry &entry) : Object(entry) { } explicit FootpathObject(const rct_object_entry& entry)
: Object(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
}; };

View File

@ -7,26 +7,28 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "ImageTable.h"
#include "../OpenRCT2.h"
#include "../core/IStream.hpp"
#include "Object.h"
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
#include "../core/IStream.hpp"
#include "../OpenRCT2.h"
#include "ImageTable.h"
#include "Object.h"
ImageTable::~ImageTable() ImageTable::~ImageTable()
{ {
if (_data == nullptr) if (_data == nullptr)
{ {
for (auto &entry : _entries) for (auto& entry : _entries)
{ {
delete [] entry.offset; delete[] entry.offset;
} }
} }
} }
void ImageTable::Read(IReadObjectContext * context, IStream * stream) void ImageTable::Read(IReadObjectContext* context, IStream* stream)
{ {
if (gOpenRCT2NoGraphics) if (gOpenRCT2NoGraphics)
{ {
@ -88,14 +90,14 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream)
_data = std::move(data); _data = std::move(data);
_entries.insert(_entries.end(), newEntries.begin(), newEntries.end()); _entries.insert(_entries.end(), newEntries.begin(), newEntries.end());
} }
catch (const std::exception &) catch (const std::exception&)
{ {
context->LogError(OBJECT_ERROR_BAD_IMAGE_TABLE, "Bad image table."); context->LogError(OBJECT_ERROR_BAD_IMAGE_TABLE, "Bad image table.");
throw; throw;
} }
} }
void ImageTable::AddImage(const rct_g1_element * g1) void ImageTable::AddImage(const rct_g1_element* g1)
{ {
rct_g1_element newg1 = *g1; rct_g1_element newg1 = *g1;
auto length = g1_calculate_data_size(g1); auto length = g1_calculate_data_size(g1);

View File

@ -9,28 +9,35 @@
#pragma once #pragma once
#include <memory>
#include <vector>
#include "../common.h" #include "../common.h"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include <memory>
#include <vector>
interface IReadObjectContext; interface IReadObjectContext;
interface IStream; interface IStream;
class ImageTable class ImageTable
{ {
private: private:
std::unique_ptr<uint8_t[]> _data; std::unique_ptr<uint8_t[]> _data;
std::vector<rct_g1_element> _entries; std::vector<rct_g1_element> _entries;
public: public:
ImageTable() = default; ImageTable() = default;
ImageTable(const ImageTable &) = delete; ImageTable(const ImageTable&) = delete;
ImageTable & operator=(const ImageTable &) = delete; ImageTable& operator=(const ImageTable&) = delete;
~ImageTable(); ~ImageTable();
void Read(IReadObjectContext * context, IStream * stream); void Read(IReadObjectContext* context, IStream* stream);
const rct_g1_element * GetImages() const { return _entries.data(); } const rct_g1_element* GetImages() const
uint32_t GetCount() const { return (uint32_t)_entries.size(); } {
void AddImage(const rct_g1_element * g1); return _entries.data();
}
uint32_t GetCount() const
{
return (uint32_t)_entries.size();
}
void AddImage(const rct_g1_element* g1);
}; };

View File

@ -9,7 +9,8 @@
#pragma warning(disable : 4706) // assignment within conditional expression #pragma warning(disable : 4706) // assignment within conditional expression
#include <algorithm> #include "LargeSceneryObject.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../core/Memory.hpp" #include "../core/Memory.hpp"
#include "../core/Util.hpp" #include "../core/Util.hpp"
@ -17,10 +18,11 @@
#include "../interface/Cursors.h" #include "../interface/Cursors.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../world/Location.hpp" #include "../world/Location.hpp"
#include "LargeSceneryObject.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
void LargeSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream) #include <algorithm>
void LargeSceneryObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.large_scenery.tool_id = stream->ReadValue<uint8_t>(); _legacyType.large_scenery.tool_id = stream->ReadValue<uint8_t>();
@ -97,7 +99,7 @@ void LargeSceneryObject::Unload()
_legacyType.image = 0; _legacyType.image = 0;
} }
void LargeSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void LargeSceneryObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
int32_t x = width / 2; int32_t x = width / 2;
int32_t y = (height / 2) - 39; int32_t y = (height / 2) - 39;
@ -106,7 +108,7 @@ void LargeSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int
gfx_draw_sprite(dpi, imageId, x, y, 0); gfx_draw_sprite(dpi, imageId, x, y, 0);
} }
std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadTiles(IStream * stream) std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadTiles(IStream* stream)
{ {
auto tiles = std::vector<rct_large_scenery_tile>(); auto tiles = std::vector<rct_large_scenery_tile>();
while (stream->ReadValue<uint16_t>() != 0xFFFF) while (stream->ReadValue<uint16_t>() != 0xFFFF)
@ -119,25 +121,25 @@ std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadTiles(IStream * stre
return tiles; return tiles;
} }
void LargeSceneryObject::ReadJson(IReadObjectContext * context, const json_t * root) void LargeSceneryObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.large_scenery.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN); _legacyType.large_scenery.tool_id
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN);
_legacyType.large_scenery.price = json_integer_value(json_object_get(properties, "price")); _legacyType.large_scenery.price = json_integer_value(json_object_get(properties, "price"));
_legacyType.large_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice")); _legacyType.large_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
auto jScrollingMode = json_object_get(properties, "scrollingMode"); auto jScrollingMode = json_object_get(properties, "scrollingMode");
_legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ? _legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ? json_integer_value(jScrollingMode) : -1;
json_integer_value(jScrollingMode) :
-1;
// Flags // Flags
_legacyType.large_scenery.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, { _legacyType.large_scenery.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
{ "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR }, properties,
{ "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR }, { { "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
{ "isAnimated", LARGE_SCENERY_FLAG_ANIMATED }, { "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
{ "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC } }); { "isAnimated", LARGE_SCENERY_FLAG_ANIMATED },
{ "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC } });
// Tiles // Tiles
auto jTiles = json_object_get(properties, "tiles"); auto jTiles = json_object_get(properties, "tiles");
@ -160,11 +162,11 @@ void LargeSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r
ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
} }
std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadJsonTiles(const json_t * jTiles) std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadJsonTiles(const json_t* jTiles)
{ {
std::vector<rct_large_scenery_tile> tiles; std::vector<rct_large_scenery_tile> tiles;
size_t index; size_t index;
const json_t * jTile; const json_t* jTile;
json_array_foreach(jTiles, index, jTile) json_array_foreach(jTiles, index, jTile)
{ {
rct_large_scenery_tile tile = {}; rct_large_scenery_tile tile = {};
@ -203,7 +205,7 @@ std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadJsonTiles(const json
return tiles; return tiles;
} }
std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const json_t * j3dFont) std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const json_t* j3dFont)
{ {
auto font = std::make_unique<rct_large_scenery_text>(); auto font = std::make_unique<rct_large_scenery_text>();
@ -217,9 +219,8 @@ std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const
font->max_width = json_integer_value(json_object_get(j3dFont, "maxWidth")); font->max_width = json_integer_value(json_object_get(j3dFont, "maxWidth"));
font->num_images = json_integer_value(json_object_get(j3dFont, "numImages")); font->num_images = json_integer_value(json_object_get(j3dFont, "numImages"));
font->flags = ObjectJsonHelpers::GetFlags<uint8_t>(j3dFont, { font->flags = ObjectJsonHelpers::GetFlags<uint8_t>(
{ "isVertical", LARGE_SCENERY_TEXT_FLAG_VERTICAL }, j3dFont, { { "isVertical", LARGE_SCENERY_TEXT_FLAG_VERTICAL }, { "isTwoLine", LARGE_SCENERY_TEXT_FLAG_TWO_LINE } });
{ "isTwoLine", LARGE_SCENERY_TEXT_FLAG_TWO_LINE } });
auto jGlyphs = json_object_get(j3dFont, "glyphs"); auto jGlyphs = json_object_get(j3dFont, "glyphs");
if (jGlyphs != nullptr) if (jGlyphs != nullptr)
@ -232,11 +233,11 @@ std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const
return font; return font;
} }
std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t * jOffsets) std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t* jOffsets)
{ {
std::vector<LocationXY16> offsets; std::vector<LocationXY16> offsets;
size_t index; size_t index;
const json_t * jOffset; const json_t* jOffset;
json_array_foreach(jOffsets, index, jOffset) json_array_foreach(jOffsets, index, jOffset)
{ {
LocationXY16 offset = {}; LocationXY16 offset = {};
@ -247,11 +248,11 @@ std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t * jOf
return offsets; return offsets;
} }
std::vector<rct_large_scenery_text_glyph> LargeSceneryObject::ReadJsonGlyphs(const json_t * jGlpyhs) std::vector<rct_large_scenery_text_glyph> LargeSceneryObject::ReadJsonGlyphs(const json_t* jGlpyhs)
{ {
std::vector<rct_large_scenery_text_glyph> glyphs; std::vector<rct_large_scenery_text_glyph> glyphs;
size_t index; size_t index;
const json_t * jGlyph; const json_t* jGlyph;
json_array_foreach(jGlpyhs, index, jGlyph) json_array_foreach(jGlpyhs, index, jGlyph)
{ {
rct_large_scenery_text_glyph glyph; rct_large_scenery_text_glyph glyph;

View File

@ -9,36 +9,43 @@
#pragma once #pragma once
#include <memory>
#include <vector>
#include "../world/Location.hpp" #include "../world/Location.hpp"
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "SceneryObject.h" #include "SceneryObject.h"
#include <memory>
#include <vector>
class LargeSceneryObject final : public SceneryObject class LargeSceneryObject final : public SceneryObject
{ {
private: private:
rct_scenery_entry _legacyType = {}; rct_scenery_entry _legacyType = {};
uint32_t _baseImageId = 0; uint32_t _baseImageId = 0;
std::vector<rct_large_scenery_tile> _tiles; std::vector<rct_large_scenery_tile> _tiles;
std::unique_ptr<rct_large_scenery_text> _3dFont; std::unique_ptr<rct_large_scenery_text> _3dFont;
public: public:
explicit LargeSceneryObject(const rct_object_entry &entry) : SceneryObject(entry) { } explicit LargeSceneryObject(const rct_object_entry& entry)
: SceneryObject(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
private: private:
static std::vector<rct_large_scenery_tile> ReadTiles(IStream * stream); static std::vector<rct_large_scenery_tile> ReadTiles(IStream* stream);
static std::vector<rct_large_scenery_tile> ReadJsonTiles(const json_t * jTiles); static std::vector<rct_large_scenery_tile> ReadJsonTiles(const json_t* jTiles);
static std::unique_ptr<rct_large_scenery_text> ReadJson3dFont(const json_t * j3dFont); static std::unique_ptr<rct_large_scenery_text> ReadJson3dFont(const json_t* j3dFont);
static std::vector<LocationXY16> ReadJsonOffsets(const json_t * jOffsets); static std::vector<LocationXY16> ReadJsonOffsets(const json_t* jOffsets);
static std::vector<rct_large_scenery_text_glyph> ReadJsonGlyphs(const json_t * jGlpyhs); static std::vector<rct_large_scenery_text_glyph> ReadJsonGlyphs(const json_t* jGlpyhs);
}; };

View File

@ -7,15 +7,17 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <algorithm> #include "Object.h"
#include "../core/Memory.hpp" #include "../core/Memory.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../localisation/StringIds.h" #include "../localisation/StringIds.h"
#include "Object.h"
#include "ObjectLimits.h" #include "ObjectLimits.h"
Object::Object(const rct_object_entry &entry) #include <algorithm>
Object::Object(const rct_object_entry& entry)
{ {
_objectEntry = entry; _objectEntry = entry;
@ -48,10 +50,10 @@ Object::~Object()
std::string Object::GetOverrideString(uint8_t index) const std::string Object::GetOverrideString(uint8_t index) const
{ {
const char * identifier = GetIdentifier(); const char* identifier = GetIdentifier();
rct_string_id stringId = language_get_object_override_string_id(identifier, index); rct_string_id stringId = language_get_object_override_string_id(identifier, index);
const utf8 * result = nullptr; const utf8* result = nullptr;
if (stringId != STR_NONE) if (stringId != STR_NONE)
{ {
result = language_get_string(stringId); result = language_get_string(stringId);
@ -102,8 +104,7 @@ void Object::SetSourceGame(const uint8_t sourceGame)
bool Object::IsRCT1Object() bool Object::IsRCT1Object()
{ {
static const char _rct1Objects[][9] = static const char _rct1Objects[][9] = {
{
"CLIFT1 ", "CLIFT1 ",
"MONO1 ", "MONO1 ",
"MONO2 ", "MONO2 ",
@ -405,8 +406,7 @@ bool Object::IsRCT1Object()
bool Object::IsAAObject() bool Object::IsAAObject()
{ {
static const char _aaObjects[][9] = static const char _aaObjects[][9] = {
{
// Rides / vehicles / stalls // Rides / vehicles / stalls
"BMFL ", "BMFL ",
"BMRB ", "BMRB ",
@ -521,8 +521,7 @@ bool Object::IsAAObject()
bool Object::IsLLObject() bool Object::IsLLObject()
{ {
static const char _llObjects[][9] = static const char _llObjects[][9] = {
{
// Rides / vehicles / stalls // Rides / vehicles / stalls
"AML1 ", "AML1 ",
"ARRT2 ", "ARRT2 ",
@ -650,8 +649,7 @@ bool Object::IsLLObject()
bool Object::IsOpenRCT2OfficialObject() bool Object::IsOpenRCT2OfficialObject()
{ {
static const char _openRCT2OfficialObjects[][9] = static const char _openRCT2OfficialObjects[][9] = {
{
// Offical extended scenery set // Offical extended scenery set
"XXBBBR01", "XXBBBR01",
"TTRFTL02", "TTRFTL02",
@ -698,10 +696,9 @@ bool Object::IsOpenRCT2OfficialObject()
return false; return false;
} }
#ifdef __WARN_SUGGEST_FINAL_METHODS__ #ifdef __WARN_SUGGEST_FINAL_METHODS__
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-final-methods" #pragma GCC diagnostic ignored "-Wsuggest-final-methods"
#endif #endif
std::string Object::GetName() const std::string Object::GetName() const
@ -715,5 +712,5 @@ std::string Object::GetName(int32_t language) const
} }
#ifdef __WARN_SUGGEST_FINAL_METHODS__ #ifdef __WARN_SUGGEST_FINAL_METHODS__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif

View File

@ -9,13 +9,14 @@
#pragma once #pragma once
#include <string_view>
#include <vector>
#include "../common.h" #include "../common.h"
#include "../core/Json.hpp" #include "../core/Json.hpp"
#include "ImageTable.h" #include "ImageTable.h"
#include "StringTable.h" #include "StringTable.h"
#include <string_view>
#include <vector>
// First 0xF of rct_object_entry->flags // First 0xF of rct_object_entry->flags
enum OBJECT_TYPE enum OBJECT_TYPE
{ {
@ -30,7 +31,7 @@ enum OBJECT_TYPE
OBJECT_TYPE_PARK_ENTRANCE, OBJECT_TYPE_PARK_ENTRANCE,
OBJECT_TYPE_WATER, OBJECT_TYPE_WATER,
OBJECT_TYPE_SCENARIO_TEXT, OBJECT_TYPE_SCENARIO_TEXT,
OBJECT_TYPE_COUNT OBJECT_TYPE_COUNT
}; };
@ -68,20 +69,24 @@ enum OBJECT_SOURCE_GAME
* Object entry structure. * Object entry structure.
* size: 0x10 * size: 0x10
*/ */
struct rct_object_entry { struct rct_object_entry
union { {
union
{
uint8_t end_flag; // needed not to read past allocated buffer. uint8_t end_flag; // needed not to read past allocated buffer.
uint32_t flags; uint32_t flags;
}; };
union { union
{
char nameWOC[12]; char nameWOC[12];
struct { struct
{
char name[8]; char name[8];
uint32_t checksum; uint32_t checksum;
}; };
}; };
void SetName(const char * value) void SetName(const char* value)
{ {
auto src = value; auto src = value;
for (size_t i = 0; i < sizeof(name); i++) for (size_t i = 0; i < sizeof(name); i++)
@ -97,22 +102,26 @@ struct rct_object_entry {
}; };
assert_struct_size(rct_object_entry, 0x10); assert_struct_size(rct_object_entry, 0x10);
struct rct_object_entry_group { struct rct_object_entry_group
void **chunks; {
rct_object_entry *entries; void** chunks;
rct_object_entry* entries;
}; };
#ifdef PLATFORM_32BIT #ifdef PLATFORM_32BIT
assert_struct_size(rct_object_entry_group, 8); assert_struct_size(rct_object_entry_group, 8);
#endif #endif
struct rct_ride_filters { struct rct_ride_filters
{
uint8_t category[2]; uint8_t category[2];
uint8_t ride_type; uint8_t ride_type;
}; };
assert_struct_size(rct_ride_filters, 3); assert_struct_size(rct_ride_filters, 3);
struct rct_object_filters { struct rct_object_filters
union { {
union
{
rct_ride_filters ride; rct_ride_filters ride;
}; };
}; };
@ -121,8 +130,8 @@ assert_struct_size(rct_object_filters, 3);
interface IObjectRepository; interface IObjectRepository;
interface IStream; interface IStream;
struct ObjectRepositoryItem; struct ObjectRepositoryItem;
struct rct_drawpixelinfo; struct rct_drawpixelinfo;
interface IReadObjectContext interface IReadObjectContext
{ {
@ -132,69 +141,95 @@ interface IReadObjectContext
virtual bool ShouldLoadImages() abstract; virtual bool ShouldLoadImages() abstract;
virtual std::vector<uint8_t> GetData(const std::string_view& path) abstract; virtual std::vector<uint8_t> GetData(const std::string_view& path) abstract;
virtual void LogWarning(uint32_t code, const utf8 * text) abstract; virtual void LogWarning(uint32_t code, const utf8* text) abstract;
virtual void LogError(uint32_t code, const utf8 * text) abstract; virtual void LogError(uint32_t code, const utf8* text) abstract;
}; };
#ifdef __WARN_SUGGEST_FINAL_TYPES__ #ifdef __WARN_SUGGEST_FINAL_TYPES__
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-final-types" #pragma GCC diagnostic ignored "-Wsuggest-final-types"
#pragma GCC diagnostic ignored "-Wsuggest-final-methods" #pragma GCC diagnostic ignored "-Wsuggest-final-methods"
#endif #endif
class Object class Object
{ {
private: private:
char * _identifier; char* _identifier;
rct_object_entry _objectEntry{}; rct_object_entry _objectEntry{};
StringTable _stringTable; StringTable _stringTable;
ImageTable _imageTable; ImageTable _imageTable;
protected: protected:
StringTable & GetStringTable() { return _stringTable; } StringTable& GetStringTable()
const StringTable & GetStringTable() const { return _stringTable; } {
ImageTable & GetImageTable() { return _imageTable; } return _stringTable;
}
const StringTable& GetStringTable() const
{
return _stringTable;
}
ImageTable& GetImageTable()
{
return _imageTable;
}
std::string GetOverrideString(uint8_t index) const; std::string GetOverrideString(uint8_t index) const;
std::string GetString(uint8_t index) const; std::string GetString(uint8_t index) const;
std::string GetString(int32_t language, uint8_t index) const; std::string GetString(int32_t language, uint8_t index) const;
void SetSourceGame(const uint8_t sourceGame); void SetSourceGame(const uint8_t sourceGame);
bool IsRCT1Object(); bool IsRCT1Object();
bool IsAAObject(); bool IsAAObject();
bool IsLLObject(); bool IsLLObject();
bool IsOpenRCT2OfficialObject(); bool IsOpenRCT2OfficialObject();
public: public:
explicit Object(const rct_object_entry &entry); explicit Object(const rct_object_entry& entry);
virtual ~Object(); virtual ~Object();
// Legacy data structures // Legacy data structures
const char * GetIdentifier() const { return _identifier; } const char* GetIdentifier() const
const rct_object_entry * GetObjectEntry() const { return &_objectEntry; } {
virtual void * GetLegacyData() abstract; return _identifier;
}
const rct_object_entry* GetObjectEntry() const
{
return &_objectEntry;
}
virtual void* GetLegacyData() abstract;
virtual void ReadJson(IReadObjectContext * /*context*/, const json_t * /*root*/) { } virtual void ReadJson(IReadObjectContext* /*context*/, const json_t* /*root*/)
virtual void ReadLegacy(IReadObjectContext * context, IStream * stream) abstract; {
}
virtual void ReadLegacy(IReadObjectContext* context, IStream* stream) abstract;
virtual void Load() abstract; virtual void Load() abstract;
virtual void Unload() abstract; virtual void Unload() abstract;
virtual void DrawPreview(rct_drawpixelinfo * /*dpi*/, int32_t /*width*/, int32_t /*height*/) const { } virtual void DrawPreview(rct_drawpixelinfo* /*dpi*/, int32_t /*width*/, int32_t /*height*/) const
{
}
virtual uint8_t GetObjectType() const final { return _objectEntry.flags & 0x0F; } virtual uint8_t GetObjectType() const final
virtual std::string GetName() const; {
virtual std::string GetName(int32_t language) const; return _objectEntry.flags & 0x0F;
}
virtual std::string GetName() const;
virtual std::string GetName(int32_t language) const;
virtual void SetRepositoryItem(ObjectRepositoryItem * /*item*/) const { } virtual void SetRepositoryItem(ObjectRepositoryItem* /*item*/) const
{
}
const ImageTable & GetImageTable() const { return _imageTable; } const ImageTable& GetImageTable() const
{
return _imageTable;
}
rct_object_entry GetScgWallsHeader(); rct_object_entry GetScgWallsHeader();
rct_object_entry GetScgPathXHeader(); rct_object_entry GetScgPathXHeader();
rct_object_entry CreateHeader(const char name[9], uint32_t flags, uint32_t checksum); rct_object_entry CreateHeader(const char name[9], uint32_t flags, uint32_t checksum);
}; };
#ifdef __WARN_SUGGEST_FINAL_TYPES__ #ifdef __WARN_SUGGEST_FINAL_TYPES__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
enum OBJECT_ERROR : uint32_t enum OBJECT_ERROR : uint32_t
@ -213,15 +248,15 @@ extern int32_t object_entry_group_encoding[];
void object_list_load(); void object_list_load();
bool object_entry_is_empty(const rct_object_entry *entry); bool object_entry_is_empty(const rct_object_entry* entry);
bool object_entry_compare(const rct_object_entry *a, const rct_object_entry *b); bool object_entry_compare(const rct_object_entry* a, const rct_object_entry* b);
int32_t object_calculate_checksum(const rct_object_entry * entry, const void * data, size_t dataLength); int32_t object_calculate_checksum(const rct_object_entry* entry, const void* data, size_t dataLength);
bool find_object_in_entry_group(const rct_object_entry* entry, uint8_t* entry_type, uint8_t* entry_index); bool find_object_in_entry_group(const rct_object_entry* entry, uint8_t* entry_type, uint8_t* entry_index);
void object_create_identifier_name(char* string_buffer, size_t size, const rct_object_entry* object); void object_create_identifier_name(char* string_buffer, size_t size, const rct_object_entry* object);
const rct_object_entry * object_list_find(rct_object_entry *entry); const rct_object_entry* object_list_find(rct_object_entry* entry);
void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry); void object_entry_get_name_fixed(utf8* buffer, size_t bufferSize, const rct_object_entry* entry);
void * object_entry_get_chunk(int32_t objectType, size_t index); void* object_entry_get_chunk(int32_t objectType, size_t index);
const rct_object_entry * object_entry_get_entry(int32_t objectType, size_t index); const rct_object_entry* object_entry_get_entry(int32_t objectType, size_t index);

View File

@ -7,6 +7,9 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "ObjectFactory.h"
#include "../OpenRCT2.h"
#include "../core/Console.hpp" #include "../core/Console.hpp"
#include "../core/File.h" #include "../core/File.h"
#include "../core/FileStream.hpp" #include "../core/FileStream.hpp"
@ -16,7 +19,6 @@
#include "../core/Path.hpp" #include "../core/Path.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../core/Zip.h" #include "../core/Zip.h"
#include "../OpenRCT2.h"
#include "../rct12/SawyerChunkReader.h" #include "../rct12/SawyerChunkReader.h"
#include "BannerObject.h" #include "BannerObject.h"
#include "EntranceObject.h" #include "EntranceObject.h"
@ -26,7 +28,6 @@
#include "Object.h" #include "Object.h"
#include "ObjectLimits.h" #include "ObjectLimits.h"
#include "ObjectList.h" #include "ObjectList.h"
#include "ObjectFactory.h"
#include "RideObject.h" #include "RideObject.h"
#include "SceneryGroupObject.h" #include "SceneryGroupObject.h"
#include "SmallSceneryObject.h" #include "SmallSceneryObject.h"
@ -79,27 +80,33 @@ class ReadObjectContext : public IReadObjectContext
{ {
private: private:
IObjectRepository& _objectRepository; IObjectRepository& _objectRepository;
const IFileDataRetriever * _fileDataRetriever; const IFileDataRetriever* _fileDataRetriever;
std::string _objectName; std::string _objectName;
bool _loadImages; bool _loadImages;
std::string _basePath; std::string _basePath;
bool _wasWarning = false; bool _wasWarning = false;
bool _wasError = false; bool _wasError = false;
public: public:
bool WasWarning() const { return _wasWarning; } bool WasWarning() const
bool WasError() const { return _wasError; } {
return _wasWarning;
}
bool WasError() const
{
return _wasError;
}
ReadObjectContext( ReadObjectContext(
IObjectRepository& objectRepository, IObjectRepository& objectRepository,
const std::string &objectName, const std::string& objectName,
bool loadImages, bool loadImages,
const IFileDataRetriever * fileDataRetriever) const IFileDataRetriever* fileDataRetriever)
: _objectRepository(objectRepository), : _objectRepository(objectRepository)
_fileDataRetriever(fileDataRetriever), , _fileDataRetriever(fileDataRetriever)
_objectName(objectName), , _objectName(objectName)
_loadImages(loadImages) , _loadImages(loadImages)
{ {
} }
@ -145,30 +152,31 @@ public:
namespace ObjectFactory namespace ObjectFactory
{ {
static Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const IFileDataRetriever * fileRetriever); static Object*
CreateObjectFromJson(IObjectRepository& objectRepository, const json_t* jRoot, const IFileDataRetriever* fileRetriever);
static void ReadObjectLegacy(Object * object, IReadObjectContext * context, IStream * stream) static void ReadObjectLegacy(Object* object, IReadObjectContext* context, IStream* stream)
{ {
try try
{ {
object->ReadLegacy(context, stream); object->ReadLegacy(context, stream);
} }
catch (const IOException &) catch (const IOException&)
{ {
// TODO check that ex is really EOF and not some other error // TODO check that ex is really EOF and not some other error
context->LogError(OBJECT_ERROR_UNEXPECTED_EOF, "Unexpectedly reached end of file."); context->LogError(OBJECT_ERROR_UNEXPECTED_EOF, "Unexpectedly reached end of file.");
} }
catch (const std::exception &) catch (const std::exception&)
{ {
context->LogError(OBJECT_ERROR_UNKNOWN, nullptr); context->LogError(OBJECT_ERROR_UNKNOWN, nullptr);
} }
} }
Object * CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8 * path) Object* CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8* path)
{ {
log_verbose("CreateObjectFromLegacyFile(..., \"%s\")", path); log_verbose("CreateObjectFromLegacyFile(..., \"%s\")", path);
Object * result = nullptr; Object* result = nullptr;
try try
{ {
auto fs = FileStream(path, FILE_MODE_OPEN); auto fs = FileStream(path, FILE_MODE_OPEN);
@ -192,7 +200,7 @@ namespace ObjectFactory
throw std::runtime_error("Object has errors"); throw std::runtime_error("Object has errors");
} }
} }
catch (const std::exception &) catch (const std::exception&)
{ {
delete result; delete result;
result = nullptr; result = nullptr;
@ -200,12 +208,13 @@ namespace ObjectFactory
return result; return result;
} }
Object * CreateObjectFromLegacyData(IObjectRepository& objectRepository, const rct_object_entry * entry, const void * data, size_t dataSize) Object* CreateObjectFromLegacyData(
IObjectRepository& objectRepository, const rct_object_entry* entry, const void* data, size_t dataSize)
{ {
Guard::ArgumentNotNull(entry, GUARD_LINE); Guard::ArgumentNotNull(entry, GUARD_LINE);
Guard::ArgumentNotNull(data, GUARD_LINE); Guard::ArgumentNotNull(data, GUARD_LINE);
Object * result = CreateObject(*entry); Object* result = CreateObject(*entry);
if (result != nullptr) if (result != nullptr)
{ {
utf8 objectName[DAT_NAME_LENGTH + 1]; utf8 objectName[DAT_NAME_LENGTH + 1];
@ -224,68 +233,79 @@ namespace ObjectFactory
return result; return result;
} }
Object * CreateObject(const rct_object_entry &entry) Object* CreateObject(const rct_object_entry& entry)
{ {
Object * result; Object* result;
uint8_t objectType = object_entry_get_type(&entry); uint8_t objectType = object_entry_get_type(&entry);
switch (objectType) { switch (objectType)
case OBJECT_TYPE_RIDE: {
result = new RideObject(entry); case OBJECT_TYPE_RIDE:
break; result = new RideObject(entry);
case OBJECT_TYPE_SMALL_SCENERY: break;
result = new SmallSceneryObject(entry); case OBJECT_TYPE_SMALL_SCENERY:
break; result = new SmallSceneryObject(entry);
case OBJECT_TYPE_LARGE_SCENERY: break;
result = new LargeSceneryObject(entry); case OBJECT_TYPE_LARGE_SCENERY:
break; result = new LargeSceneryObject(entry);
case OBJECT_TYPE_WALLS: break;
result = new WallObject(entry); case OBJECT_TYPE_WALLS:
break; result = new WallObject(entry);
case OBJECT_TYPE_BANNERS: break;
result = new BannerObject(entry); case OBJECT_TYPE_BANNERS:
break; result = new BannerObject(entry);
case OBJECT_TYPE_PATHS: break;
result = new FootpathObject(entry); case OBJECT_TYPE_PATHS:
break; result = new FootpathObject(entry);
case OBJECT_TYPE_PATH_BITS: break;
result = new FootpathItemObject(entry); case OBJECT_TYPE_PATH_BITS:
break; result = new FootpathItemObject(entry);
case OBJECT_TYPE_SCENERY_GROUP: break;
result = new SceneryGroupObject(entry); case OBJECT_TYPE_SCENERY_GROUP:
break; result = new SceneryGroupObject(entry);
case OBJECT_TYPE_PARK_ENTRANCE: break;
result = new EntranceObject(entry); case OBJECT_TYPE_PARK_ENTRANCE:
break; result = new EntranceObject(entry);
case OBJECT_TYPE_WATER: break;
result = new WaterObject(entry); case OBJECT_TYPE_WATER:
break; result = new WaterObject(entry);
case OBJECT_TYPE_SCENARIO_TEXT: break;
result = new StexObject(entry); case OBJECT_TYPE_SCENARIO_TEXT:
break; result = new StexObject(entry);
default: break;
throw std::runtime_error("Invalid object type"); default:
throw std::runtime_error("Invalid object type");
} }
return result; return result;
} }
static uint8_t ParseObjectType(const std::string &s) static uint8_t ParseObjectType(const std::string& s)
{ {
if (s == "ride") return OBJECT_TYPE_RIDE; if (s == "ride")
if (s == "footpath") return OBJECT_TYPE_PATHS; return OBJECT_TYPE_RIDE;
if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath")
if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; return OBJECT_TYPE_PATHS;
if (s == "scenery_small") return OBJECT_TYPE_SMALL_SCENERY; if (s == "footpath_banner")
if (s == "scenery_large") return OBJECT_TYPE_LARGE_SCENERY; return OBJECT_TYPE_BANNERS;
if (s == "scenery_wall") return OBJECT_TYPE_WALLS; if (s == "footpath_item")
if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP; return OBJECT_TYPE_PATH_BITS;
if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; if (s == "scenery_small")
if (s == "water") return OBJECT_TYPE_WATER; return OBJECT_TYPE_SMALL_SCENERY;
if (s == "scenery_large")
return OBJECT_TYPE_LARGE_SCENERY;
if (s == "scenery_wall")
return OBJECT_TYPE_WALLS;
if (s == "scenery_group")
return OBJECT_TYPE_SCENERY_GROUP;
if (s == "park_entrance")
return OBJECT_TYPE_PARK_ENTRANCE;
if (s == "water")
return OBJECT_TYPE_WATER;
return 0xFF; return 0xFF;
} }
Object * CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path) Object* CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path)
{ {
Object * result = nullptr; Object* result = nullptr;
try try
{ {
auto archive = Zip::Open(path, ZIP_ACCESS::READ); auto archive = Zip::Open(path, ZIP_ACCESS::READ);
@ -296,7 +316,7 @@ namespace ObjectFactory
} }
json_error_t jsonLoadError; json_error_t jsonLoadError;
auto jRoot = json_loadb((const char *)jsonBytes.data(), jsonBytes.size(), 0, &jsonLoadError); auto jRoot = json_loadb((const char*)jsonBytes.data(), jsonBytes.size(), 0, &jsonLoadError);
if (jRoot == nullptr) if (jRoot == nullptr)
{ {
throw JsonException(&jsonLoadError); throw JsonException(&jsonLoadError);
@ -315,11 +335,11 @@ namespace ObjectFactory
return result; return result;
} }
Object * CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string &path) Object* CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string& path)
{ {
log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str()); log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str());
Object * result = nullptr; Object* result = nullptr;
try try
{ {
auto jRoot = Json::ReadFromFile(path.c_str()); auto jRoot = Json::ReadFromFile(path.c_str());
@ -327,7 +347,7 @@ namespace ObjectFactory
result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever); result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
json_decref(jRoot); json_decref(jRoot);
} }
catch (const std::runtime_error &err) catch (const std::runtime_error& err)
{ {
Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), err.what()); Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), err.what());
@ -337,11 +357,12 @@ namespace ObjectFactory
return result; return result;
} }
Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const IFileDataRetriever * fileRetriever) Object*
CreateObjectFromJson(IObjectRepository& objectRepository, const json_t* jRoot, const IFileDataRetriever* fileRetriever)
{ {
log_verbose("CreateObjectFromJson(...)"); log_verbose("CreateObjectFromJson(...)");
Object * result = nullptr; Object* result = nullptr;
auto jObjectType = json_object_get(jRoot, "objectType"); auto jObjectType = json_object_get(jRoot, "objectType");
if (json_is_string(jObjectType)) if (json_is_string(jObjectType))
{ {
@ -373,4 +394,4 @@ namespace ObjectFactory
} }
return result; return result;
} }
} } // namespace ObjectFactory

View File

@ -9,19 +9,21 @@
#pragma once #pragma once
#include <string_view>
#include "../common.h" #include "../common.h"
#include <string_view>
interface IObjectRepository; interface IObjectRepository;
class Object; class Object;
struct rct_object_entry; struct rct_object_entry;
namespace ObjectFactory namespace ObjectFactory
{ {
Object * CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8 * path); Object* CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8* path);
Object * CreateObjectFromLegacyData(IObjectRepository& objectRepository, const rct_object_entry * entry, const void * data, size_t dataSize); Object* CreateObjectFromLegacyData(
Object * CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path); IObjectRepository& objectRepository, const rct_object_entry* entry, const void* data, size_t dataSize);
Object * CreateObject(const rct_object_entry &entry); Object* CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path);
Object* CreateObject(const rct_object_entry& entry);
Object * CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string &path); Object* CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string& path);
} } // namespace ObjectFactory

View File

@ -9,10 +9,10 @@
#pragma warning(disable : 4706) // assignment within conditional expression #pragma warning(disable : 4706) // assignment within conditional expression
#include <cstdlib> #include "ObjectJsonHelpers.h"
#include <cstring>
#include <unordered_map>
#include "../Context.h" #include "../Context.h"
#include "../PlatformEnvironment.h"
#include "../core/File.h" #include "../core/File.h"
#include "../core/FileScanner.h" #include "../core/FileScanner.h"
#include "../core/Math.hpp" #include "../core/Math.hpp"
@ -22,48 +22,43 @@
#include "../drawing/ImageImporter.h" #include "../drawing/ImageImporter.h"
#include "../interface/Cursors.h" #include "../interface/Cursors.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../PlatformEnvironment.h"
#include "../sprites.h" #include "../sprites.h"
#include "Object.h" #include "Object.h"
#include "ObjectFactory.h" #include "ObjectFactory.h"
#include "ObjectJsonHelpers.h"
#include <cstdlib>
#include <cstring>
#include <unordered_map>
using namespace OpenRCT2; using namespace OpenRCT2;
using namespace OpenRCT2::Drawing; using namespace OpenRCT2::Drawing;
namespace ObjectJsonHelpers namespace ObjectJsonHelpers
{ {
bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue) bool GetBoolean(const json_t* obj, const std::string& name, bool defaultValue)
{ {
auto value = json_object_get(obj, name.c_str()); auto value = json_object_get(obj, name.c_str());
return json_is_boolean(value) ? return json_is_boolean(value) ? json_boolean_value(value) : defaultValue;
json_boolean_value(value) :
defaultValue;
} }
std::string GetString(const json_t * value) std::string GetString(const json_t* value)
{ {
return json_is_string(value) ? return json_is_string(value) ? std::string(json_string_value(value)) : std::string();
std::string(json_string_value(value)) :
std::string();
} }
std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue) std::string GetString(const json_t* obj, const std::string& name, const std::string& defaultValue)
{ {
auto value = json_object_get(obj, name.c_str()); auto value = json_object_get(obj, name.c_str());
return json_is_string(value) ? return json_is_string(value) ? json_string_value(value) : defaultValue;
json_string_value(value) :
defaultValue;
} }
int32_t GetInteger(const json_t * obj, const std::string &name, const int32_t &defaultValue) int32_t GetInteger(const json_t* obj, const std::string& name, const int32_t& defaultValue)
{ {
auto value = json_object_get(obj, name.c_str()); auto value = json_object_get(obj, name.c_str());
if (json_is_integer(value)) if (json_is_integer(value))
{ {
int64_t val = json_integer_value(value); int64_t val = json_integer_value(value);
if (val >= std::numeric_limits<int32_t>::min() && if (val >= std::numeric_limits<int32_t>::min() && val <= std::numeric_limits<int32_t>::max())
val <= std::numeric_limits<int32_t>::max())
{ {
return static_cast<int32_t>(val); return static_cast<int32_t>(val);
} }
@ -71,15 +66,13 @@ namespace ObjectJsonHelpers
return defaultValue; return defaultValue;
} }
float GetFloat(const json_t * obj, const std::string &name, const float &defaultValue) float GetFloat(const json_t* obj, const std::string& name, const float& defaultValue)
{ {
auto value = json_object_get(obj, name.c_str()); auto value = json_object_get(obj, name.c_str());
return json_is_number(value) ? return json_is_number(value) ? json_number_value(value) : defaultValue;
json_number_value(value) :
defaultValue;
} }
std::vector<std::string> GetJsonStringArray(const json_t * arr) std::vector<std::string> GetJsonStringArray(const json_t* arr)
{ {
std::vector<std::string> result; std::vector<std::string> result;
if (json_is_array(arr)) if (json_is_array(arr))
@ -99,7 +92,7 @@ namespace ObjectJsonHelpers
return result; return result;
} }
std::vector<int32_t> GetJsonIntegerArray(const json_t * arr) std::vector<int32_t> GetJsonIntegerArray(const json_t* arr)
{ {
std::vector<int32_t> result; std::vector<int32_t> result;
if (json_is_array(arr)) if (json_is_array(arr))
@ -119,46 +112,43 @@ namespace ObjectJsonHelpers
return result; return result;
} }
uint8_t ParseCursor(const std::string &s, uint8_t defaultValue) uint8_t ParseCursor(const std::string& s, uint8_t defaultValue)
{ {
static const std::unordered_map<std::string, uint8_t> LookupTable static const std::unordered_map<std::string, uint8_t> LookupTable{
{ { "CURSOR_BLANK", CURSOR_BLANK },
{ "CURSOR_BLANK", CURSOR_BLANK }, { "CURSOR_UP_ARROW", CURSOR_UP_ARROW },
{ "CURSOR_UP_ARROW", CURSOR_UP_ARROW }, { "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW },
{ "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW }, { "CURSOR_HAND_POINT", CURSOR_HAND_POINT },
{ "CURSOR_HAND_POINT", CURSOR_HAND_POINT }, { "CURSOR_ZZZ", CURSOR_ZZZ },
{ "CURSOR_ZZZ", CURSOR_ZZZ },
{ "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS }, { "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS },
{ "CURSOR_PICKER", CURSOR_PICKER }, { "CURSOR_PICKER", CURSOR_PICKER },
{ "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN }, { "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN },
{ "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN }, { "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN },
{ "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN }, { "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN },
{ "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN }, { "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN },
{ "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR }, { "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR },
{ "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN }, { "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN },
{ "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN }, { "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN },
{ "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN }, { "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN },
{ "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN }, { "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN },
{ "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN }, { "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN },
{ "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN }, { "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN },
{ "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN }, { "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN },
{ "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN }, { "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN },
{ "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN }, { "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN },
{ "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN }, { "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN },
{ "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN }, { "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN },
{ "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN }, { "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN },
{ "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN }, { "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN },
{ "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED }, { "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED },
{ "CURSOR_ARROW", CURSOR_ARROW }, { "CURSOR_ARROW", CURSOR_ARROW },
}; };
auto result = LookupTable.find(s); auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? return (result != LookupTable.end()) ? result->second : defaultValue;
result->second :
defaultValue;
} }
rct_object_entry ParseObjectEntry(const std::string & s) rct_object_entry ParseObjectEntry(const std::string& s)
{ {
rct_object_entry entry = {}; rct_object_entry entry = {};
std::fill_n(entry.name, sizeof(entry.name), ' '); std::fill_n(entry.name, sizeof(entry.name), ' ');
@ -170,7 +160,7 @@ namespace ObjectJsonHelpers
static std::vector<int32_t> ParseRange(std::string s) static std::vector<int32_t> ParseRange(std::string s)
{ {
// Currently only supports [###] or [###..###] // Currently only supports [###] or [###..###]
std::vector<int32_t> result = { }; std::vector<int32_t> result = {};
if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']') if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']')
{ {
s = s.substr(1, s.length() - 2); s = s.substr(1, s.length() - 2);
@ -202,7 +192,7 @@ namespace ObjectJsonHelpers
return result; return result;
} }
static std::string FindLegacyObject(const std::string &name) static std::string FindLegacyObject(const std::string& name)
{ {
const auto env = GetContext()->GetPlatformEnvironment(); const auto env = GetContext()->GetPlatformEnvironment();
auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT);
@ -225,14 +215,15 @@ namespace ObjectJsonHelpers
return objectPath; return objectPath;
} }
static std::vector<rct_g1_element> LoadObjectImages(IReadObjectContext * context, const std::string &name, const std::vector<int32_t> &range) static std::vector<rct_g1_element>
LoadObjectImages(IReadObjectContext* context, const std::string& name, const std::vector<int32_t>& range)
{ {
std::vector<rct_g1_element> result; std::vector<rct_g1_element> result;
auto objectPath = FindLegacyObject(name); auto objectPath = FindLegacyObject(name);
auto obj = ObjectFactory::CreateObjectFromLegacyFile(context->GetObjectRepository(), objectPath.c_str()); auto obj = ObjectFactory::CreateObjectFromLegacyFile(context->GetObjectRepository(), objectPath.c_str());
if (obj != nullptr) if (obj != nullptr)
{ {
auto &imgTable = static_cast<const Object *>(obj)->GetImageTable(); auto& imgTable = static_cast<const Object*>(obj)->GetImageTable();
auto numImages = (int32_t)imgTable.GetCount(); auto numImages = (int32_t)imgTable.GetCount();
auto images = imgTable.GetImages(); auto images = imgTable.GetImages();
size_t placeHoldersAdded = 0; size_t placeHoldersAdded = 0;
@ -240,10 +231,10 @@ namespace ObjectJsonHelpers
{ {
if (i >= 0 && i < numImages) if (i >= 0 && i < numImages)
{ {
auto &objg1 = images[i]; auto& objg1 = images[i];
auto length = g1_calculate_data_size(&objg1); auto length = g1_calculate_data_size(&objg1);
auto g1 = objg1; auto g1 = objg1;
g1.offset = (uint8_t *)std::malloc(length); g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, objg1.offset, length); std::memcpy(g1.offset, objg1.offset, length);
result.push_back(g1); result.push_back(g1);
} }
@ -272,7 +263,7 @@ namespace ObjectJsonHelpers
return result; return result;
} }
static std::vector<rct_g1_element> ParseImages(IReadObjectContext * context, std::string s) static std::vector<rct_g1_element> ParseImages(IReadObjectContext* context, std::string s)
{ {
std::vector<rct_g1_element> result; std::vector<rct_g1_element> result;
if (s.empty()) if (s.empty())
@ -289,10 +280,10 @@ namespace ObjectJsonHelpers
{ {
for (auto i : range) for (auto i : range)
{ {
auto &csg1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i); auto& csg1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i);
auto length = g1_calculate_data_size(&csg1); auto length = g1_calculate_data_size(&csg1);
auto g1 = csg1; auto g1 = csg1;
g1.offset = (uint8_t *)std::malloc(length); g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, csg1.offset, length); std::memcpy(g1.offset, csg1.offset, length);
result.push_back(g1); result.push_back(g1);
} }
@ -316,7 +307,7 @@ namespace ObjectJsonHelpers
{ {
auto length = g1_calculate_data_size(og1); auto length = g1_calculate_data_size(og1);
auto g1 = *og1; auto g1 = *og1;
g1.offset = (uint8_t *)std::malloc(length); g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, og1->offset, length); std::memcpy(g1.offset, og1->offset, length);
result.push_back(g1); result.push_back(g1);
} }
@ -359,7 +350,7 @@ namespace ObjectJsonHelpers
return result; return result;
} }
static std::vector<rct_g1_element> ParseImages(IReadObjectContext * context, json_t * el) static std::vector<rct_g1_element> ParseImages(IReadObjectContext* context, json_t* el)
{ {
auto path = GetString(el, "path"); auto path = GetString(el, "path");
auto x = GetInteger(el, "x"); auto x = GetInteger(el, "x");
@ -395,27 +386,31 @@ namespace ObjectJsonHelpers
return result; return result;
} }
static uint8_t ParseStringId(const std::string &s) static uint8_t ParseStringId(const std::string& s)
{ {
if (s == "name") return OBJ_STRING_ID_NAME; if (s == "name")
if (s == "description") return OBJ_STRING_ID_DESCRIPTION; return OBJ_STRING_ID_NAME;
if (s == "capacity") return OBJ_STRING_ID_CAPACITY; if (s == "description")
if (s == "vehicleName") return OBJ_STRING_ID_VEHICLE_NAME; return OBJ_STRING_ID_DESCRIPTION;
if (s == "capacity")
return OBJ_STRING_ID_CAPACITY;
if (s == "vehicleName")
return OBJ_STRING_ID_VEHICLE_NAME;
return OBJ_STRING_ID_UNKNOWN; return OBJ_STRING_ID_UNKNOWN;
} }
void LoadStrings(const json_t * root, StringTable &stringTable) void LoadStrings(const json_t* root, StringTable& stringTable)
{ {
auto jsonStrings = json_object_get(root, "strings"); auto jsonStrings = json_object_get(root, "strings");
const char * key; const char* key;
json_t * jlanguages; json_t* jlanguages;
json_object_foreach(jsonStrings, key, jlanguages) json_object_foreach(jsonStrings, key, jlanguages)
{ {
auto stringId = ParseStringId(key); auto stringId = ParseStringId(key);
if (stringId != OBJ_STRING_ID_UNKNOWN) if (stringId != OBJ_STRING_ID_UNKNOWN)
{ {
const char * locale; const char* locale;
json_t * jstring; json_t* jstring;
json_object_foreach(jlanguages, locale, jstring) json_object_foreach(jlanguages, locale, jstring)
{ {
auto langId = language_get_id_from_locale(locale); auto langId = language_get_id_from_locale(locale);
@ -430,13 +425,13 @@ namespace ObjectJsonHelpers
stringTable.Sort(); stringTable.Sort();
} }
void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable) void LoadImages(IReadObjectContext* context, const json_t* root, ImageTable& imageTable)
{ {
if (context->ShouldLoadImages()) if (context->ShouldLoadImages())
{ {
auto jsonImages = json_object_get(root, "images"); auto jsonImages = json_object_get(root, "images");
size_t i; size_t i;
json_t * el; json_t* el;
json_array_foreach(jsonImages, i, el) json_array_foreach(jsonImages, i, el)
{ {
std::vector<rct_g1_element> images; std::vector<rct_g1_element> images;
@ -449,7 +444,7 @@ namespace ObjectJsonHelpers
{ {
images = ParseImages(context, el); images = ParseImages(context, el);
} }
for (const auto &g1 : images) for (const auto& g1 : images)
{ {
imageTable.AddImage(&g1); imageTable.AddImage(&g1);
std::free(g1.offset); std::free(g1.offset);

View File

@ -9,10 +9,6 @@
#pragma once #pragma once
#include <initializer_list>
#include <string>
#include <utility>
#include <vector>
#include "../common.h" #include "../common.h"
#include "../core/Json.hpp" #include "../core/Json.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
@ -20,25 +16,29 @@
#include "ImageTable.h" #include "ImageTable.h"
#include "StringTable.h" #include "StringTable.h"
#include <initializer_list>
#include <string>
#include <utility>
#include <vector>
namespace ObjectJsonHelpers namespace ObjectJsonHelpers
{ {
bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); bool GetBoolean(const json_t* obj, const std::string& name, bool defaultValue = false);
std::string GetString(const json_t * value); std::string GetString(const json_t* value);
std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue = ""); std::string GetString(const json_t* obj, const std::string& name, const std::string& defaultValue = "");
int32_t GetInteger(const json_t * obj, const std::string &name, const int32_t &defaultValue = 0); int32_t GetInteger(const json_t* obj, const std::string& name, const int32_t& defaultValue = 0);
float GetFloat(const json_t * obj, const std::string &name, const float &defaultValue = 0); float GetFloat(const json_t* obj, const std::string& name, const float& defaultValue = 0);
std::vector<std::string> GetJsonStringArray(const json_t * arr); std::vector<std::string> GetJsonStringArray(const json_t* arr);
std::vector<int32_t> GetJsonIntegerArray(const json_t * arr); std::vector<int32_t> GetJsonIntegerArray(const json_t* arr);
uint8_t ParseCursor(const std::string &s, uint8_t defaultValue); uint8_t ParseCursor(const std::string& s, uint8_t defaultValue);
rct_object_entry ParseObjectEntry(const std::string & s); rct_object_entry ParseObjectEntry(const std::string& s);
void LoadStrings(const json_t * root, StringTable &stringTable); void LoadStrings(const json_t* root, StringTable& stringTable);
void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable); void LoadImages(IReadObjectContext* context, const json_t* root, ImageTable& imageTable);
template<typename T> template<typename T> static T GetFlags(const json_t* obj, std::initializer_list<std::pair<std::string, T>> list)
static T GetFlags(const json_t * obj, std::initializer_list<std::pair<std::string, T>> list)
{ {
T flags = 0; T flags = 0;
for (const auto &item : list) for (const auto& item : list)
{ {
if (GetBoolean(obj, item.first)) if (GetBoolean(obj, item.first))
{ {

View File

@ -9,16 +9,16 @@
#pragma once #pragma once
#define MAX_RIDE_OBJECTS 128 #define MAX_RIDE_OBJECTS 128
#define MAX_SMALL_SCENERY_OBJECTS 252 #define MAX_SMALL_SCENERY_OBJECTS 252
#define MAX_LARGE_SCENERY_OBJECTS 128 #define MAX_LARGE_SCENERY_OBJECTS 128
#define MAX_WALL_SCENERY_OBJECTS 128 #define MAX_WALL_SCENERY_OBJECTS 128
#define MAX_BANNER_OBJECTS 32 #define MAX_BANNER_OBJECTS 32
#define MAX_PATH_OBJECTS 16 #define MAX_PATH_OBJECTS 16
#define MAX_PATH_ADDITION_OBJECTS 15 #define MAX_PATH_ADDITION_OBJECTS 15
#define MAX_SCENERY_GROUP_OBJECTS 19 #define MAX_SCENERY_GROUP_OBJECTS 19
#define MAX_PARK_ENTRANCE_OBJECTS 1 #define MAX_PARK_ENTRANCE_OBJECTS 1
#define MAX_WATER_OBJECTS 1 #define MAX_WATER_OBJECTS 1
#define MAX_SCENARIO_TEXT_OBJECTS 1 #define MAX_SCENARIO_TEXT_OBJECTS 1
#define DAT_NAME_LENGTH 8 #define DAT_NAME_LENGTH 8

View File

@ -7,18 +7,19 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <cstring> #include "ObjectList.h"
#include "../Context.h" #include "../Context.h"
#include "../Game.h"
#include "../core/Math.hpp" #include "../core/Math.hpp"
#include "../core/Util.hpp" #include "../core/Util.hpp"
#include "../Game.h"
#include "../object/Object.h" #include "../object/Object.h"
#include "ObjectList.h"
#include "ObjectRepository.h"
#include "ObjectManager.h"
#include "../util/SawyerCoding.h" #include "../util/SawyerCoding.h"
#include "../util/Util.h" #include "../util/Util.h"
#include "ObjectManager.h"
#include "ObjectRepository.h"
#include <cstring>
// 98DA00 // 98DA00
// clang-format off // clang-format off
@ -52,23 +53,25 @@ int32_t object_entry_group_encoding[] = {
}; };
// clang-format on // clang-format on
bool object_entry_is_empty(const rct_object_entry *entry) bool object_entry_is_empty(const rct_object_entry* entry)
{ {
uint64_t a, b; uint64_t a, b;
memcpy(&a, (uint8_t *)entry, 8); memcpy(&a, (uint8_t*)entry, 8);
memcpy(&b, (uint8_t *)entry + 8, 8); memcpy(&b, (uint8_t*)entry + 8, 8);
if (a == 0xFFFFFFFFFFFFFFFF && b == 0xFFFFFFFFFFFFFFFF) return true; if (a == 0xFFFFFFFFFFFFFFFF && b == 0xFFFFFFFFFFFFFFFF)
if (a == 0 && b == 0) return true; return true;
if (a == 0 && b == 0)
return true;
return false; return false;
} }
uint8_t object_entry_get_type(const rct_object_entry * objectEntry) uint8_t object_entry_get_type(const rct_object_entry* objectEntry)
{ {
return (objectEntry->flags & 0x0F); return (objectEntry->flags & 0x0F);
} }
uint8_t object_entry_get_source_game(const rct_object_entry * objectEntry) uint8_t object_entry_get_source_game(const rct_object_entry* objectEntry)
{ {
return (objectEntry->flags & 0xF0) >> 4; return (objectEntry->flags & 0xF0) >> 4;
} }
@ -88,7 +91,7 @@ void object_create_identifier_name(char* string_buffer, size_t size, const rct_o
* bl = entry_index * bl = entry_index
* ecx = entry_type * ecx = entry_type
*/ */
bool find_object_in_entry_group(const rct_object_entry * entry, uint8_t * entry_type, uint8_t * entry_index) bool find_object_in_entry_group(const rct_object_entry* entry, uint8_t* entry_type, uint8_t* entry_index)
{ {
int32_t objectType = object_entry_get_type(entry); int32_t objectType = object_entry_get_type(entry);
if (objectType >= OBJECT_TYPE_COUNT) if (objectType >= OBJECT_TYPE_COUNT)
@ -113,24 +116,29 @@ bool find_object_in_entry_group(const rct_object_entry * entry, uint8_t * entry_
return false; return false;
} }
void get_type_entry_index(size_t index, uint8_t * outObjectType, uint8_t * outEntryIndex) void get_type_entry_index(size_t index, uint8_t* outObjectType, uint8_t* outEntryIndex)
{ {
uint8_t objectType = OBJECT_TYPE_RIDE; uint8_t objectType = OBJECT_TYPE_RIDE;
for (size_t groupCount : object_entry_group_counts) for (size_t groupCount : object_entry_group_counts)
{ {
if (index >= groupCount) { if (index >= groupCount)
{
index -= groupCount; index -= groupCount;
objectType++; objectType++;
} else { }
else
{
break; break;
} }
} }
if (outObjectType != nullptr) *outObjectType = objectType; if (outObjectType != nullptr)
if (outEntryIndex != nullptr) *outEntryIndex = (uint8_t)index; *outObjectType = objectType;
if (outEntryIndex != nullptr)
*outEntryIndex = (uint8_t)index;
} }
const rct_object_entry * get_loaded_object_entry(size_t index) const rct_object_entry* get_loaded_object_entry(size_t index)
{ {
uint8_t objectType, entryIndex; uint8_t objectType, entryIndex;
get_type_entry_index(index, &objectType, &entryIndex); get_type_entry_index(index, &objectType, &entryIndex);
@ -138,21 +146,21 @@ const rct_object_entry * get_loaded_object_entry(size_t index)
return object_entry_get_entry(objectType, entryIndex); return object_entry_get_entry(objectType, entryIndex);
} }
void * get_loaded_object_chunk(size_t index) void* get_loaded_object_chunk(size_t index)
{ {
uint8_t objectType, entryIndex; uint8_t objectType, entryIndex;
get_type_entry_index(index, &objectType, &entryIndex); get_type_entry_index(index, &objectType, &entryIndex);
return object_entry_get_chunk(objectType, entryIndex); return object_entry_get_chunk(objectType, entryIndex);
} }
void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry) void object_entry_get_name_fixed(utf8* buffer, size_t bufferSize, const rct_object_entry* entry)
{ {
bufferSize = std::min((size_t)DAT_NAME_LENGTH + 1, bufferSize); bufferSize = std::min((size_t)DAT_NAME_LENGTH + 1, bufferSize);
memcpy(buffer, entry->name, bufferSize - 1); memcpy(buffer, entry->name, bufferSize - 1);
buffer[bufferSize - 1] = 0; buffer[bufferSize - 1] = 0;
} }
void * object_entry_get_chunk(int32_t objectType, size_t index) void* object_entry_get_chunk(int32_t objectType, size_t index)
{ {
size_t objectIndex = index; size_t objectIndex = index;
for (int32_t i = 0; i < objectType; i++) for (int32_t i = 0; i < objectType; i++)
@ -160,7 +168,7 @@ void * object_entry_get_chunk(int32_t objectType, size_t index)
objectIndex += object_entry_group_counts[i]; objectIndex += object_entry_group_counts[i];
} }
void * result = nullptr; void* result = nullptr;
auto objectMgr = OpenRCT2::GetContext()->GetObjectManager(); auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objectMgr->GetLoadedObject(objectIndex); auto obj = objectMgr->GetLoadedObject(objectIndex);
if (obj != nullptr) if (obj != nullptr)
@ -170,9 +178,9 @@ void * object_entry_get_chunk(int32_t objectType, size_t index)
return result; return result;
} }
const rct_object_entry * object_entry_get_entry(int32_t objectType, size_t index) const rct_object_entry* object_entry_get_entry(int32_t objectType, size_t index)
{ {
const rct_object_entry * result = nullptr; const rct_object_entry* result = nullptr;
auto objectMgr = OpenRCT2::GetContext()->GetObjectManager(); auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objectMgr->GetLoadedObject(objectType, index); auto obj = objectMgr->GetLoadedObject(objectType, index);
if (obj != nullptr) if (obj != nullptr)

View File

@ -17,8 +17,8 @@
#include "../world/Water.h" #include "../world/Water.h"
#include "ObjectLimits.h" #include "ObjectLimits.h"
void get_type_entry_index(size_t index, uint8_t * outObjectType, uint8_t * outEntryIndex); void get_type_entry_index(size_t index, uint8_t* outObjectType, uint8_t* outEntryIndex);
const rct_object_entry * get_loaded_object_entry(size_t index); const rct_object_entry* get_loaded_object_entry(size_t index);
void * get_loaded_object_chunk(size_t index); void* get_loaded_object_chunk(size_t index);
uint8_t object_entry_get_type(const rct_object_entry * objectEntry); uint8_t object_entry_get_type(const rct_object_entry* objectEntry);
uint8_t object_entry_get_source_game(const rct_object_entry * objectEntry); uint8_t object_entry_get_source_game(const rct_object_entry* objectEntry);

View File

@ -7,33 +7,34 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "ObjectManager.h"
#include "../Context.h"
#include "../ParkImporter.h"
#include "../core/Console.hpp"
#include "../core/Memory.hpp"
#include "../localisation/StringIds.h"
#include "FootpathItemObject.h"
#include "LargeSceneryObject.h"
#include "Object.h"
#include "ObjectList.h"
#include "ObjectRepository.h"
#include "SceneryGroupObject.h"
#include "SmallSceneryObject.h"
#include "WallObject.h"
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <unordered_set> #include <unordered_set>
#include "../Context.h"
#include "../core/Console.hpp"
#include "../core/Memory.hpp"
#include "../localisation/StringIds.h"
#include "../ParkImporter.h"
#include "FootpathItemObject.h"
#include "LargeSceneryObject.h"
#include "Object.h"
#include "ObjectManager.h"
#include "ObjectRepository.h"
#include "SceneryGroupObject.h"
#include "SmallSceneryObject.h"
#include "WallObject.h"
#include "ObjectList.h"
class ObjectManager final : public IObjectManager class ObjectManager final : public IObjectManager
{ {
private: private:
std::shared_ptr<IObjectRepository> _objectRepository; std::shared_ptr<IObjectRepository> _objectRepository;
std::vector<Object *> _loadedObjects; std::vector<Object*> _loadedObjects;
public: public:
explicit ObjectManager(std::shared_ptr<IObjectRepository> objectRepository) explicit ObjectManager(std::shared_ptr<IObjectRepository> objectRepository)
@ -52,7 +53,7 @@ public:
UnloadAll(); UnloadAll();
} }
Object * GetLoadedObject(size_t index) override Object* GetLoadedObject(size_t index) override
{ {
if (index >= _loadedObjects.size()) if (index >= _loadedObjects.size())
{ {
@ -61,7 +62,7 @@ public:
return _loadedObjects[index]; return _loadedObjects[index];
} }
Object * GetLoadedObject(int32_t objectType, size_t index) override Object* GetLoadedObject(int32_t objectType, size_t index) override
{ {
if (index >= (size_t)object_entry_group_counts[objectType]) if (index >= (size_t)object_entry_group_counts[objectType])
{ {
@ -75,10 +76,10 @@ public:
return GetLoadedObject(objectIndex); return GetLoadedObject(objectIndex);
} }
Object * GetLoadedObject(const rct_object_entry * entry) override Object* GetLoadedObject(const rct_object_entry* entry) override
{ {
Object * loadedObject = nullptr; Object* loadedObject = nullptr;
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry); const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
if (ori != nullptr) if (ori != nullptr)
{ {
loadedObject = ori->LoadedObject; loadedObject = ori->LoadedObject;
@ -86,7 +87,7 @@ public:
return loadedObject; return loadedObject;
} }
uint8_t GetLoadedObjectEntryIndex(const Object * object) override uint8_t GetLoadedObjectEntryIndex(const Object* object) override
{ {
uint8_t result = UINT8_MAX; uint8_t result = UINT8_MAX;
size_t index = GetLoadedObjectIndex(object); size_t index = GetLoadedObjectIndex(object);
@ -97,10 +98,10 @@ public:
return result; return result;
} }
Object * LoadObject(const rct_object_entry * entry) override Object* LoadObject(const rct_object_entry* entry) override
{ {
Object * loadedObject = nullptr; Object* loadedObject = nullptr;
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry); const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
if (ori != nullptr) if (ori != nullptr)
{ {
loadedObject = ori->LoadedObject; loadedObject = ori->LoadedObject;
@ -127,7 +128,7 @@ public:
return loadedObject; return loadedObject;
} }
void LoadObjects(const rct_object_entry * entries, size_t count) override void LoadObjects(const rct_object_entry* entries, size_t count) override
{ {
// Find all the required objects // Find all the required objects
auto requiredObjects = GetRequiredObjects(entries, count); auto requiredObjects = GetRequiredObjects(entries, count);
@ -143,7 +144,7 @@ public:
log_verbose("%u / %u new objects loaded", numNewLoadedObjects, requiredObjects.size()); log_verbose("%u / %u new objects loaded", numNewLoadedObjects, requiredObjects.size());
} }
void UnloadObjects(const rct_object_entry * entries, size_t count) override void UnloadObjects(const rct_object_entry* entries, size_t count) override
{ {
// TODO there are two performance issues here: // TODO there are two performance issues here:
// - FindObject for every entry which is a dictionary lookup // - FindObject for every entry which is a dictionary lookup
@ -152,11 +153,11 @@ public:
size_t numObjectsUnloaded = 0; size_t numObjectsUnloaded = 0;
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
{ {
const rct_object_entry * entry = &entries[i]; const rct_object_entry* entry = &entries[i];
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry); const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
if (ori != nullptr) if (ori != nullptr)
{ {
Object * loadedObject = ori->LoadedObject; Object* loadedObject = ori->LoadedObject;
if (loadedObject != nullptr) if (loadedObject != nullptr)
{ {
UnloadObject(loadedObject); UnloadObject(loadedObject);
@ -196,16 +197,14 @@ public:
ResetTypeToRideEntryIndexMap(); ResetTypeToRideEntryIndexMap();
} }
std::vector<const ObjectRepositoryItem *> GetPackableObjects() override std::vector<const ObjectRepositoryItem*> GetPackableObjects() override
{ {
std::vector<const ObjectRepositoryItem *> objects; std::vector<const ObjectRepositoryItem*> objects;
size_t numObjects = _objectRepository->GetNumObjects(); size_t numObjects = _objectRepository->GetNumObjects();
for (size_t i = 0; i < numObjects; i++) for (size_t i = 0; i < numObjects; i++)
{ {
const ObjectRepositoryItem * item = &_objectRepository->GetObjects()[i]; const ObjectRepositoryItem* item = &_objectRepository->GetObjects()[i];
if (item->LoadedObject != nullptr && if (item->LoadedObject != nullptr && item->LoadedObject->GetLegacyData() != nullptr && IsObjectCustom(item))
item->LoadedObject->GetLegacyData() != nullptr &&
IsObjectCustom(item))
{ {
objects.push_back(item); objects.push_back(item);
} }
@ -219,31 +218,31 @@ public:
// loaded RCT1 and RCT2 save files. // loaded RCT1 and RCT2 save files.
} }
static rct_string_id GetObjectSourceGameString(const rct_object_entry * entry) static rct_string_id GetObjectSourceGameString(const rct_object_entry* entry)
{ {
switch (object_entry_get_source_game(entry)) switch (object_entry_get_source_game(entry))
{ {
case OBJECT_SOURCE_RCT1: case OBJECT_SOURCE_RCT1:
return STR_SCENARIO_CATEGORY_RCT1; return STR_SCENARIO_CATEGORY_RCT1;
case OBJECT_SOURCE_ADDED_ATTRACTIONS: case OBJECT_SOURCE_ADDED_ATTRACTIONS:
return STR_SCENARIO_CATEGORY_RCT1_AA; return STR_SCENARIO_CATEGORY_RCT1_AA;
case OBJECT_SOURCE_LOOPY_LANDSCAPES: case OBJECT_SOURCE_LOOPY_LANDSCAPES:
return STR_SCENARIO_CATEGORY_RCT1_LL; return STR_SCENARIO_CATEGORY_RCT1_LL;
case OBJECT_SOURCE_RCT2: case OBJECT_SOURCE_RCT2:
return STR_ROLLERCOASTER_TYCOON_2_DROPDOWN; return STR_ROLLERCOASTER_TYCOON_2_DROPDOWN;
case OBJECT_SOURCE_WACKY_WORLDS: case OBJECT_SOURCE_WACKY_WORLDS:
return STR_OBJECT_FILTER_WW; return STR_OBJECT_FILTER_WW;
case OBJECT_SOURCE_TIME_TWISTER: case OBJECT_SOURCE_TIME_TWISTER:
return STR_OBJECT_FILTER_TT; return STR_OBJECT_FILTER_TT;
case OBJECT_SOURCE_OPENRCT2_OFFICIAL: case OBJECT_SOURCE_OPENRCT2_OFFICIAL:
return STR_OBJECT_FILTER_OPENRCT2_OFFICIAL; return STR_OBJECT_FILTER_OPENRCT2_OFFICIAL;
default: default:
return STR_OBJECT_FILTER_CUSTOM; return STR_OBJECT_FILTER_CUSTOM;
} }
} }
private: private:
Object * LoadObject(const std::string &name) Object* LoadObject(const std::string& name)
{ {
rct_object_entry entry{}; rct_object_entry entry{};
std::copy_n(name.c_str(), 8, entry.name); std::copy_n(name.c_str(), 8, entry.name);
@ -269,7 +268,7 @@ private:
return -1; return -1;
} }
size_t GetLoadedObjectIndex(const Object * object) size_t GetLoadedObjectIndex(const Object* object)
{ {
Guard::ArgumentNotNull(object, GUARD_LINE); Guard::ArgumentNotNull(object, GUARD_LINE);
@ -282,7 +281,7 @@ private:
return result; return result;
} }
void SetNewLoadedObjectList(const std::vector<Object *> &newLoadedObjects) void SetNewLoadedObjectList(const std::vector<Object*>& newLoadedObjects)
{ {
if (newLoadedObjects.size() == 0) if (newLoadedObjects.size() == 0)
{ {
@ -295,12 +294,12 @@ private:
_loadedObjects = newLoadedObjects; _loadedObjects = newLoadedObjects;
} }
void UnloadObject(Object * object) void UnloadObject(Object* object)
{ {
if (object != nullptr) if (object != nullptr)
{ {
// TODO try to prevent doing a repository search // TODO try to prevent doing a repository search
const ObjectRepositoryItem * ori = _objectRepository->FindObject(object->GetObjectEntry()); const ObjectRepositoryItem* ori = _objectRepository->FindObject(object->GetObjectEntry());
if (ori != nullptr) if (ori != nullptr)
{ {
_objectRepository->UnregisterLoadedObject(ori, object); _objectRepository->UnregisterLoadedObject(ori, object);
@ -308,7 +307,7 @@ private:
// Because it's possible to have the same loaded object for multiple // Because it's possible to have the same loaded object for multiple
// slots, we have to make sure find and set all of them to nullptr // slots, we have to make sure find and set all of them to nullptr
for (auto &obj : _loadedObjects) for (auto& obj : _loadedObjects)
{ {
if (obj == object) if (obj == object)
{ {
@ -321,10 +320,10 @@ private:
} }
} }
void UnloadObjectsExcept(const std::vector<Object *> &newLoadedObjects) void UnloadObjectsExcept(const std::vector<Object*>& newLoadedObjects)
{ {
// Build a hash set for quick checking // Build a hash set for quick checking
auto exceptSet = std::unordered_set<Object *>(); auto exceptSet = std::unordered_set<Object*>();
for (auto object : newLoadedObjects) for (auto object : newLoadedObjects)
{ {
if (object != nullptr) if (object != nullptr)
@ -358,32 +357,33 @@ private:
{ {
if (loadedObject != nullptr) if (loadedObject != nullptr)
{ {
rct_scenery_entry * sceneryEntry; rct_scenery_entry* sceneryEntry;
switch (loadedObject->GetObjectType()) { switch (loadedObject->GetObjectType())
case OBJECT_TYPE_SMALL_SCENERY: {
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); case OBJECT_TYPE_SMALL_SCENERY:
sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
break; sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
case OBJECT_TYPE_LARGE_SCENERY: break;
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); case OBJECT_TYPE_LARGE_SCENERY:
sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
break; sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
case OBJECT_TYPE_WALLS: break;
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); case OBJECT_TYPE_WALLS:
sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
break; sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
case OBJECT_TYPE_BANNERS: break;
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); case OBJECT_TYPE_BANNERS:
sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
break; sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
case OBJECT_TYPE_PATH_BITS: break;
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); case OBJECT_TYPE_PATH_BITS:
sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
break; sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
case OBJECT_TYPE_SCENERY_GROUP: break;
auto sgObject = dynamic_cast<SceneryGroupObject *>(loadedObject); case OBJECT_TYPE_SCENERY_GROUP:
sgObject->UpdateEntryIndexes(); auto sgObject = dynamic_cast<SceneryGroupObject*>(loadedObject);
break; sgObject->UpdateEntryIndexes();
break;
} }
} }
} }
@ -393,11 +393,11 @@ private:
window_close_by_class(WC_SCENERY); window_close_by_class(WC_SCENERY);
} }
uint8_t GetPrimarySceneryGroupEntryIndex(Object * loadedObject) uint8_t GetPrimarySceneryGroupEntryIndex(Object* loadedObject)
{ {
auto sceneryObject = dynamic_cast<SceneryObject *>(loadedObject); auto sceneryObject = dynamic_cast<SceneryObject*>(loadedObject);
const rct_object_entry * primarySGEntry = sceneryObject->GetPrimarySceneryGroup(); const rct_object_entry* primarySGEntry = sceneryObject->GetPrimarySceneryGroup();
Object * sgObject = GetLoadedObject(primarySGEntry); Object* sgObject = GetLoadedObject(primarySGEntry);
uint8_t entryIndex = 255; uint8_t entryIndex = 255;
if (sgObject != nullptr) if (sgObject != nullptr)
@ -409,21 +409,21 @@ private:
rct_object_entry* DuplicateObjectEntry(const rct_object_entry* original) rct_object_entry* DuplicateObjectEntry(const rct_object_entry* original)
{ {
rct_object_entry * duplicate = Memory::Allocate<rct_object_entry>(sizeof(rct_object_entry)); rct_object_entry* duplicate = Memory::Allocate<rct_object_entry>(sizeof(rct_object_entry));
duplicate->checksum = original->checksum; duplicate->checksum = original->checksum;
strncpy(duplicate->name, original->name, 8); strncpy(duplicate->name, original->name, 8);
duplicate->flags = original->flags; duplicate->flags = original->flags;
return duplicate; return duplicate;
} }
std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) override std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry* entries) override
{ {
std::vector<rct_object_entry> invalidEntries; std::vector<rct_object_entry> invalidEntries;
invalidEntries.reserve(OBJECT_ENTRY_COUNT); invalidEntries.reserve(OBJECT_ENTRY_COUNT);
for (int32_t i = 0; i < OBJECT_ENTRY_COUNT; i++) for (int32_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
{ {
auto entry = entries[i]; auto entry = entries[i];
const ObjectRepositoryItem * ori = nullptr; const ObjectRepositoryItem* ori = nullptr;
if (object_entry_is_empty(&entry)) if (object_entry_is_empty(&entry))
{ {
entry = {}; entry = {};
@ -447,7 +447,7 @@ private:
} }
else else
{ {
Object * loadedObject = nullptr; Object* loadedObject = nullptr;
loadedObject = ori->LoadedObject; loadedObject = ori->LoadedObject;
if (loadedObject == nullptr) if (loadedObject == nullptr)
{ {
@ -464,15 +464,15 @@ private:
return invalidEntries; return invalidEntries;
} }
std::vector<const ObjectRepositoryItem *> GetRequiredObjects(const rct_object_entry * entries, size_t count) std::vector<const ObjectRepositoryItem*> GetRequiredObjects(const rct_object_entry* entries, size_t count)
{ {
std::vector<const ObjectRepositoryItem *> requiredObjects; std::vector<const ObjectRepositoryItem*> requiredObjects;
std::vector<rct_object_entry> missingObjects; std::vector<rct_object_entry> missingObjects;
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
{ {
const rct_object_entry * entry = &entries[i]; const rct_object_entry* entry = &entries[i];
const ObjectRepositoryItem * ori = nullptr; const ObjectRepositoryItem* ori = nullptr;
if (!object_entry_is_empty(entry)) if (!object_entry_is_empty(entry))
{ {
ori = _objectRepository->FindObject(entry); ori = _objectRepository->FindObject(entry);
@ -493,8 +493,7 @@ private:
return requiredObjects; return requiredObjects;
} }
template<typename T, typename TFunc> template<typename T, typename TFunc> static void ParallelFor(const std::vector<T>& items, TFunc func)
static void ParallelFor(const std::vector<T>& items, TFunc func)
{ {
auto partitions = std::thread::hardware_concurrency(); auto partitions = std::thread::hardware_concurrency();
auto partitionSize = (items.size() + (partitions - 1)) / partitions; auto partitionSize = (items.size() + (partitions - 1)) / partitions;
@ -504,8 +503,7 @@ private:
auto begin = n * partitionSize; auto begin = n * partitionSize;
auto end = std::min(items.size(), begin + partitionSize); auto end = std::min(items.size(), begin + partitionSize);
threads.emplace_back( threads.emplace_back(
[func](size_t pbegin, size_t pend) [func](size_t pbegin, size_t pend) {
{
for (size_t i = pbegin; i < pend; i++) for (size_t i = pbegin; i < pend; i++)
{ {
func(i); func(i);
@ -520,45 +518,42 @@ private:
} }
} }
std::vector<Object *> LoadObjects(std::vector<const ObjectRepositoryItem *> &requiredObjects, size_t * outNewObjectsLoaded) std::vector<Object*> LoadObjects(std::vector<const ObjectRepositoryItem*>& requiredObjects, size_t* outNewObjectsLoaded)
{ {
std::vector<Object *> objects; std::vector<Object*> objects;
std::vector<Object *> loadedObjects; std::vector<Object*> loadedObjects;
std::vector<rct_object_entry> badObjects; std::vector<rct_object_entry> badObjects;
objects.resize(OBJECT_ENTRY_COUNT); objects.resize(OBJECT_ENTRY_COUNT);
loadedObjects.reserve(OBJECT_ENTRY_COUNT); loadedObjects.reserve(OBJECT_ENTRY_COUNT);
// Read objects // Read objects
std::mutex commonMutex; std::mutex commonMutex;
ParallelFor( ParallelFor(requiredObjects, [this, &commonMutex, requiredObjects, &objects, &badObjects, &loadedObjects](size_t i) {
requiredObjects, auto ori = requiredObjects[i];
[this, &commonMutex, requiredObjects, &objects, &badObjects, &loadedObjects](size_t i) Object* loadedObject = nullptr;
if (ori != nullptr)
{ {
auto ori = requiredObjects[i]; loadedObject = ori->LoadedObject;
Object * loadedObject = nullptr; if (loadedObject == nullptr)
if (ori != nullptr)
{ {
loadedObject = ori->LoadedObject; loadedObject = _objectRepository->LoadObject(ori);
if (loadedObject == nullptr) if (loadedObject == nullptr)
{ {
loadedObject = _objectRepository->LoadObject(ori); std::lock_guard<std::mutex> guard(commonMutex);
if (loadedObject == nullptr) badObjects.push_back(ori->ObjectEntry);
{ ReportObjectLoadProblem(&ori->ObjectEntry);
std::lock_guard<std::mutex> guard(commonMutex); }
badObjects.push_back(ori->ObjectEntry); else
ReportObjectLoadProblem(&ori->ObjectEntry); {
} std::lock_guard<std::mutex> guard(commonMutex);
else loadedObjects.push_back(loadedObject);
{ // Connect the ori to the registered object
std::lock_guard<std::mutex> guard(commonMutex); _objectRepository->RegisterLoadedObject(ori, loadedObject);
loadedObjects.push_back(loadedObject);
// Connect the ori to the registered object
_objectRepository->RegisterLoadedObject(ori, loadedObject);
}
} }
} }
objects[i] = loadedObject; }
}); objects[i] = loadedObject;
});
// Load objects // Load objects
for (auto obj : loadedObjects) for (auto obj : loadedObjects)
@ -583,9 +578,9 @@ private:
return objects; return objects;
} }
Object * GetOrLoadObject(const ObjectRepositoryItem * ori) Object* GetOrLoadObject(const ObjectRepositoryItem* ori)
{ {
Object * loadedObject = ori->LoadedObject; Object* loadedObject = ori->LoadedObject;
if (loadedObject == nullptr) if (loadedObject == nullptr)
{ {
// Try to load object // Try to load object
@ -606,14 +601,14 @@ private:
reset_type_to_ride_entry_index_map(*this); reset_type_to_ride_entry_index_map(*this);
} }
static void ReportMissingObject(const rct_object_entry * entry) static void ReportMissingObject(const rct_object_entry* entry)
{ {
utf8 objName[DAT_NAME_LENGTH + 1] = { 0 }; utf8 objName[DAT_NAME_LENGTH + 1] = { 0 };
std::copy_n(entry->name, DAT_NAME_LENGTH, objName); std::copy_n(entry->name, DAT_NAME_LENGTH, objName);
Console::Error::WriteLine("[%s] Object not found.", objName); Console::Error::WriteLine("[%s] Object not found.", objName);
} }
void ReportObjectLoadProblem(const rct_object_entry * entry) void ReportObjectLoadProblem(const rct_object_entry* entry)
{ {
utf8 objName[DAT_NAME_LENGTH + 1] = { 0 }; utf8 objName[DAT_NAME_LENGTH + 1] = { 0 };
std::copy_n(entry->name, DAT_NAME_LENGTH, objName); std::copy_n(entry->name, DAT_NAME_LENGTH, objName);
@ -637,36 +632,36 @@ std::unique_ptr<IObjectManager> CreateObjectManager(std::shared_ptr<IObjectRepos
return std::make_unique<ObjectManager>(objectRepository); return std::make_unique<ObjectManager>(objectRepository);
} }
void * object_manager_get_loaded_object_by_index(size_t index) void* object_manager_get_loaded_object_by_index(size_t index)
{ {
auto objectManager = OpenRCT2::GetContext()->GetObjectManager(); auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
Object * loadedObject = objectManager->GetLoadedObject(index); Object* loadedObject = objectManager->GetLoadedObject(index);
return (void *)loadedObject; return (void*)loadedObject;
} }
void * object_manager_get_loaded_object(const rct_object_entry * entry) void* object_manager_get_loaded_object(const rct_object_entry* entry)
{ {
auto objectManager = OpenRCT2::GetContext()->GetObjectManager(); auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
Object * loadedObject = objectManager->GetLoadedObject(entry); Object* loadedObject = objectManager->GetLoadedObject(entry);
return (void *)loadedObject; return (void*)loadedObject;
} }
uint8_t object_manager_get_loaded_object_entry_index(const void * loadedObject) uint8_t object_manager_get_loaded_object_entry_index(const void* loadedObject)
{ {
auto objectManager = OpenRCT2::GetContext()->GetObjectManager(); auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
const Object * object = static_cast<const Object *>(loadedObject); const Object* object = static_cast<const Object*>(loadedObject);
uint8_t entryIndex = objectManager->GetLoadedObjectEntryIndex(object); uint8_t entryIndex = objectManager->GetLoadedObjectEntryIndex(object);
return entryIndex; return entryIndex;
} }
void * object_manager_load_object(const rct_object_entry * entry) void* object_manager_load_object(const rct_object_entry* entry)
{ {
auto objectManager = OpenRCT2::GetContext()->GetObjectManager(); auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
Object * loadedObject = objectManager->LoadObject(entry); Object* loadedObject = objectManager->LoadObject(entry);
return (void *)loadedObject; return (void*)loadedObject;
} }
void object_manager_unload_objects(const rct_object_entry * entries, size_t count) void object_manager_unload_objects(const rct_object_entry* entries, size_t count)
{ {
auto objectManager = OpenRCT2::GetContext()->GetObjectManager(); auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
objectManager->UnloadObjects(entries, count); objectManager->UnloadObjects(entries, count);
@ -681,7 +676,7 @@ void object_manager_unload_all_objects()
} }
} }
rct_string_id object_manager_get_source_game_string(const rct_object_entry * entry) rct_string_id object_manager_get_source_game_string(const rct_object_entry* entry)
{ {
return ObjectManager::GetObjectSourceGameString(entry); return ObjectManager::GetObjectSourceGameString(entry);
} }

View File

@ -9,41 +9,44 @@
#pragma once #pragma once
#include <vector>
#include "../common.h" #include "../common.h"
#include "../object/Object.h" #include "../object/Object.h"
interface IObjectRepository; #include <vector>
class Object;
struct ObjectRepositoryItem; interface IObjectRepository;
class Object;
struct ObjectRepositoryItem;
interface IObjectManager interface IObjectManager
{ {
virtual ~IObjectManager() { } virtual ~IObjectManager()
{
}
virtual Object * GetLoadedObject(size_t index) abstract; virtual Object* GetLoadedObject(size_t index) abstract;
virtual Object * GetLoadedObject(int32_t objectType, size_t index) abstract; virtual Object* GetLoadedObject(int32_t objectType, size_t index) abstract;
virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract; virtual Object* GetLoadedObject(const rct_object_entry* entry) abstract;
virtual uint8_t GetLoadedObjectEntryIndex(const Object * object) abstract; virtual uint8_t GetLoadedObjectEntryIndex(const Object* object) abstract;
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) abstract; virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry* entries) abstract;
virtual Object * LoadObject(const rct_object_entry * entry) abstract; virtual Object* LoadObject(const rct_object_entry* entry) abstract;
virtual void LoadObjects(const rct_object_entry * entries, size_t count) abstract; virtual void LoadObjects(const rct_object_entry* entries, size_t count) abstract;
virtual void LoadDefaultObjects() abstract; virtual void LoadDefaultObjects() abstract;
virtual void UnloadObjects(const rct_object_entry * entries, size_t count) abstract; virtual void UnloadObjects(const rct_object_entry* entries, size_t count) abstract;
virtual void UnloadAll() abstract; virtual void UnloadAll() abstract;
virtual void ResetObjects() abstract; virtual void ResetObjects() abstract;
virtual std::vector<const ObjectRepositoryItem *> GetPackableObjects() abstract; virtual std::vector<const ObjectRepositoryItem*> GetPackableObjects() abstract;
}; };
std::unique_ptr<IObjectManager> CreateObjectManager(std::shared_ptr<IObjectRepository> objectRepository); std::unique_ptr<IObjectManager> CreateObjectManager(std::shared_ptr<IObjectRepository> objectRepository);
void * object_manager_get_loaded_object_by_index(size_t index); void* object_manager_get_loaded_object_by_index(size_t index);
void * object_manager_get_loaded_object(const rct_object_entry * entry); void* object_manager_get_loaded_object(const rct_object_entry* entry);
uint8_t object_manager_get_loaded_object_entry_index(const void * loadedObject); uint8_t object_manager_get_loaded_object_entry_index(const void* loadedObject);
void * object_manager_load_object(const rct_object_entry * entry); void* object_manager_load_object(const rct_object_entry* entry);
void object_manager_unload_objects(const rct_object_entry * entries, size_t count); void object_manager_unload_objects(const rct_object_entry* entries, size_t count);
void object_manager_unload_all_objects(); void object_manager_unload_all_objects();
rct_string_id object_manager_get_source_game_string(const rct_object_entry * entry); rct_string_id object_manager_get_source_game_string(const rct_object_entry* entry);

View File

@ -7,13 +7,12 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <algorithm> #include "ObjectRepository.h"
#include <memory>
#include <unordered_map>
#include <vector>
#include "../common.h"
#include "../Context.h" #include "../Context.h"
#include "../PlatformEnvironment.h"
#include "../common.h"
#include "../config/Config.h"
#include "../core/Console.hpp" #include "../core/Console.hpp"
#include "../core/FileIndex.hpp" #include "../core/FileIndex.hpp"
#include "../core/FileStream.hpp" #include "../core/FileStream.hpp"
@ -23,31 +22,32 @@
#include "../core/MemoryStream.h" #include "../core/MemoryStream.h"
#include "../core/Path.hpp" #include "../core/Path.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../PlatformEnvironment.h"
#include "../rct12/SawyerChunkReader.h"
#include "../rct12/SawyerChunkWriter.h"
#include "../scenario/ScenarioRepository.h"
#include "Object.h"
#include "ObjectFactory.h"
#include "ObjectManager.h"
#include "ObjectRepository.h"
#include "RideObject.h"
#include "StexObject.h"
#include "../config/Config.h"
#include "../localisation/Localisation.h" #include "../localisation/Localisation.h"
#include "../localisation/LocalisationService.h" #include "../localisation/LocalisationService.h"
#include "../object/Object.h" #include "../object/Object.h"
#include "ObjectList.h"
#include "../platform/platform.h" #include "../platform/platform.h"
#include "../rct12/SawyerChunkReader.h"
#include "../rct12/SawyerChunkWriter.h"
#include "../scenario/ScenarioRepository.h"
#include "../util/SawyerCoding.h" #include "../util/SawyerCoding.h"
#include "../util/Util.h" #include "../util/Util.h"
#include "Object.h"
#include "ObjectFactory.h"
#include "ObjectList.h"
#include "ObjectManager.h"
#include "RideObject.h"
#include "StexObject.h"
#include <algorithm>
#include <memory>
#include <unordered_map>
#include <vector>
using namespace OpenRCT2; using namespace OpenRCT2;
struct ObjectEntryHash struct ObjectEntryHash
{ {
size_t operator()(const rct_object_entry &entry) const size_t operator()(const rct_object_entry& entry) const
{ {
uint32_t hash = 5381; uint32_t hash = 5381;
for (auto i : entry.name) for (auto i : entry.name)
@ -60,7 +60,7 @@ struct ObjectEntryHash
struct ObjectEntryEqual struct ObjectEntryEqual
{ {
bool operator()(const rct_object_entry &lhs, const rct_object_entry &rhs) const bool operator()(const rct_object_entry& lhs, const rct_object_entry& rhs) const
{ {
return memcmp(&lhs.name, &rhs.name, 8) == 0; return memcmp(&lhs.name, &rhs.name, 8) == 0;
} }
@ -78,23 +78,23 @@ private:
IObjectRepository& _objectRepository; IObjectRepository& _objectRepository;
public: public:
explicit ObjectFileIndex(IObjectRepository& objectRepository, const IPlatformEnvironment& env) : explicit ObjectFileIndex(IObjectRepository& objectRepository, const IPlatformEnvironment& env)
FileIndex("object index", : FileIndex(
MAGIC_NUMBER, "object index",
VERSION, MAGIC_NUMBER,
env.GetFilePath(PATHID::CACHE_OBJECTS), VERSION,
std::string(PATTERN), env.GetFilePath(PATHID::CACHE_OBJECTS),
std::vector<std::string>({ std::string(PATTERN),
env.GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT), std::vector<std::string>({ env.GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT),
env.GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) })), env.GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) }))
_objectRepository(objectRepository) , _objectRepository(objectRepository)
{ {
} }
public: public:
std::tuple<bool, ObjectRepositoryItem> Create([[maybe_unused]] int32_t language, const std::string& path) const override std::tuple<bool, ObjectRepositoryItem> Create([[maybe_unused]] int32_t language, const std::string& path) const override
{ {
Object * object = nullptr; Object* object = nullptr;
auto extension = Path::GetExtension(path); auto extension = Path::GetExtension(path);
if (String::Equals(extension, ".json", true)) if (String::Equals(extension, ".json", true))
{ {
@ -122,36 +122,37 @@ public:
} }
protected: protected:
void Serialise(IStream * stream, const ObjectRepositoryItem &item) const override void Serialise(IStream* stream, const ObjectRepositoryItem& item) const override
{ {
stream->WriteValue(item.ObjectEntry); stream->WriteValue(item.ObjectEntry);
stream->WriteString(item.Path); stream->WriteString(item.Path);
stream->WriteString(item.Name); stream->WriteString(item.Name);
switch (object_entry_get_type(&item.ObjectEntry)) { switch (object_entry_get_type(&item.ObjectEntry))
case OBJECT_TYPE_RIDE: {
stream->WriteValue<uint8_t>(item.RideInfo.RideFlags); case OBJECT_TYPE_RIDE:
for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++) stream->WriteValue<uint8_t>(item.RideInfo.RideFlags);
{ for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++)
stream->WriteValue<uint8_t>(item.RideInfo.RideCategory[i]); {
} stream->WriteValue<uint8_t>(item.RideInfo.RideCategory[i]);
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) }
{ for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
stream->WriteValue<uint8_t>(item.RideInfo.RideType[i]); {
} stream->WriteValue<uint8_t>(item.RideInfo.RideType[i]);
stream->WriteValue<uint8_t>(item.RideInfo.RideGroupIndex); }
break; stream->WriteValue<uint8_t>(item.RideInfo.RideGroupIndex);
case OBJECT_TYPE_SCENERY_GROUP: break;
stream->WriteValue<uint16_t>((uint16_t)item.SceneryGroupInfo.Entries.size()); case OBJECT_TYPE_SCENERY_GROUP:
for (const auto& entry : item.SceneryGroupInfo.Entries) stream->WriteValue<uint16_t>((uint16_t)item.SceneryGroupInfo.Entries.size());
{ for (const auto& entry : item.SceneryGroupInfo.Entries)
stream->WriteValue<rct_object_entry>(entry); {
} stream->WriteValue<rct_object_entry>(entry);
break; }
break;
} }
} }
ObjectRepositoryItem Deserialise(IStream * stream) const override ObjectRepositoryItem Deserialise(IStream* stream) const override
{ {
ObjectRepositoryItem item; ObjectRepositoryItem item;
@ -159,20 +160,21 @@ protected:
item.Path = stream->ReadStdString(); item.Path = stream->ReadStdString();
item.Name = stream->ReadStdString(); item.Name = stream->ReadStdString();
switch (object_entry_get_type(&item.ObjectEntry)) { switch (object_entry_get_type(&item.ObjectEntry))
case OBJECT_TYPE_RIDE: {
item.RideInfo.RideFlags = stream->ReadValue<uint8_t>(); case OBJECT_TYPE_RIDE:
for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++) item.RideInfo.RideFlags = stream->ReadValue<uint8_t>();
{ for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++)
item.RideInfo.RideCategory[i] = stream->ReadValue<uint8_t>(); {
} item.RideInfo.RideCategory[i] = stream->ReadValue<uint8_t>();
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) }
{ for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
item.RideInfo.RideType[i] = stream->ReadValue<uint8_t>(); {
} item.RideInfo.RideType[i] = stream->ReadValue<uint8_t>();
item.RideInfo.RideGroupIndex = stream->ReadValue<uint8_t>(); }
break; item.RideInfo.RideGroupIndex = stream->ReadValue<uint8_t>();
case OBJECT_TYPE_SCENERY_GROUP: break;
case OBJECT_TYPE_SCENERY_GROUP:
{ {
auto numEntries = stream->ReadValue<uint16_t>(); auto numEntries = stream->ReadValue<uint16_t>();
item.SceneryGroupInfo.Entries = std::vector<rct_object_entry>(numEntries); item.SceneryGroupInfo.Entries = std::vector<rct_object_entry>(numEntries);
@ -187,11 +189,9 @@ protected:
} }
private: private:
bool IsTrackReadOnly(const std::string &path) const bool IsTrackReadOnly(const std::string& path) const
{ {
return return String::StartsWith(path, SearchPaths[0]) || String::StartsWith(path, SearchPaths[1]);
String::StartsWith(path, SearchPaths[0]) ||
String::StartsWith(path, SearchPaths[1]);
} }
}; };
@ -204,8 +204,8 @@ class ObjectRepository final : public IObjectRepository
public: public:
explicit ObjectRepository(const std::shared_ptr<IPlatformEnvironment>& env) explicit ObjectRepository(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env), : _env(env)
_fileIndex(*this, *env) , _fileIndex(*this, *env)
{ {
} }
@ -234,12 +234,12 @@ public:
return _items.size(); return _items.size();
} }
const ObjectRepositoryItem * GetObjects() const override const ObjectRepositoryItem* GetObjects() const override
{ {
return _items.data(); return _items.data();
} }
const ObjectRepositoryItem * FindObject(const utf8 * name) const override const ObjectRepositoryItem* FindObject(const utf8* name) const override
{ {
rct_object_entry entry = {}; rct_object_entry entry = {};
utf8 entryName[9] = { ' ' }; utf8 entryName[9] = { ' ' };
@ -254,7 +254,7 @@ public:
return nullptr; return nullptr;
} }
const ObjectRepositoryItem * FindObject(const rct_object_entry * objectEntry) const override final const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const override final
{ {
auto kvp = _itemMap.find(*objectEntry); auto kvp = _itemMap.find(*objectEntry);
if (kvp != _itemMap.end()) if (kvp != _itemMap.end())
@ -264,7 +264,7 @@ public:
return nullptr; return nullptr;
} }
Object * LoadObject(const ObjectRepositoryItem * ori) override Object* LoadObject(const ObjectRepositoryItem* ori) override
{ {
Guard::ArgumentNotNull(ori, GUARD_LINE); Guard::ArgumentNotNull(ori, GUARD_LINE);
@ -283,30 +283,30 @@ public:
} }
} }
void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override void RegisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) override
{ {
ObjectRepositoryItem * item = &_items[ori->Id]; ObjectRepositoryItem* item = &_items[ori->Id];
Guard::Assert(item->LoadedObject == nullptr, GUARD_LINE); Guard::Assert(item->LoadedObject == nullptr, GUARD_LINE);
item->LoadedObject = object; item->LoadedObject = object;
} }
void UnregisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override void UnregisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) override
{ {
ObjectRepositoryItem * item = &_items[ori->Id]; ObjectRepositoryItem* item = &_items[ori->Id];
if (item->LoadedObject == object) if (item->LoadedObject == object)
{ {
item->LoadedObject = nullptr; item->LoadedObject = nullptr;
} }
} }
void AddObject(const rct_object_entry * objectEntry, const void * data, size_t dataSize) override void AddObject(const rct_object_entry* objectEntry, const void* data, size_t dataSize) override
{ {
utf8 objectName[9]; utf8 objectName[9];
object_entry_get_name_fixed(objectName, sizeof(objectName), objectEntry); object_entry_get_name_fixed(objectName, sizeof(objectName), objectEntry);
// Check that the object is loadable before writing it // Check that the object is loadable before writing it
Object * object = ObjectFactory::CreateObjectFromLegacyData(*this, objectEntry, data, dataSize); Object* object = ObjectFactory::CreateObjectFromLegacyData(*this, objectEntry, data, dataSize);
if (object == nullptr) if (object == nullptr)
{ {
Console::Error::WriteLine("[%s] Unable to export object.", objectName); Console::Error::WriteLine("[%s] Unable to export object.", objectName);
@ -322,14 +322,14 @@ public:
SaveObject(path, objectEntry, data, dataSize); SaveObject(path, objectEntry, data, dataSize);
ScanObject(path); ScanObject(path);
} }
catch (const std::exception &) catch (const std::exception&)
{ {
Console::Error::WriteLine("Failed saving object: [%s] to '%s'.", objectName, path); Console::Error::WriteLine("Failed saving object: [%s] to '%s'.", objectName, path);
} }
} }
} }
void ExportPackedObject(IStream * stream) override void ExportPackedObject(IStream* stream) override
{ {
auto chunkReader = SawyerChunkReader(stream); auto chunkReader = SawyerChunkReader(stream);
@ -347,10 +347,10 @@ public:
} }
} }
void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem *> &objects) override void WritePackedObjects(IStream* stream, std::vector<const ObjectRepositoryItem*>& objects) override
{ {
log_verbose("packing %u objects", objects.size()); log_verbose("packing %u objects", objects.size());
for (const auto &object : objects) for (const auto& object : objects)
{ {
Guard::ArgumentNotNull(object); Guard::ArgumentNotNull(object);
@ -375,9 +375,7 @@ private:
void SortItems() void SortItems()
{ {
std::sort(_items.begin(), _items.end(), [](const ObjectRepositoryItem &a, std::sort(_items.begin(), _items.end(), [](const ObjectRepositoryItem& a, const ObjectRepositoryItem& b) -> bool {
const ObjectRepositoryItem &b) -> bool
{
return String::Compare(a.Name, b.Name) < 0; return String::Compare(a.Name, b.Name) < 0;
}); });
@ -396,7 +394,7 @@ private:
} }
} }
void AddItems(const std::vector<ObjectRepositoryItem> &items) void AddItems(const std::vector<ObjectRepositoryItem>& items)
{ {
size_t numConflicts = 0; size_t numConflicts = 0;
for (auto item : items) for (auto item : items)
@ -412,7 +410,7 @@ private:
} }
} }
bool AddItem(const ObjectRepositoryItem &item) bool AddItem(const ObjectRepositoryItem& item)
{ {
auto conflict = FindObject(&item.ObjectEntry); auto conflict = FindObject(&item.ObjectEntry);
if (conflict == nullptr) if (conflict == nullptr)
@ -432,7 +430,7 @@ private:
} }
} }
void ScanObject(const std::string &path) void ScanObject(const std::string& path)
{ {
auto language = LocalisationService_GetCurrentLanguage(); auto language = LocalisationService_GetCurrentLanguage();
auto result = _fileIndex.Create(language, path); auto result = _fileIndex.Create(language, path);
@ -443,10 +441,8 @@ private:
} }
} }
static void SaveObject(const utf8 * path, static void
const rct_object_entry * entry, SaveObject(const utf8* path, const rct_object_entry* entry, const void* data, size_t dataSize, bool fixChecksum = true)
const void * data, size_t dataSize,
bool fixChecksum = true)
{ {
if (fixChecksum) if (fixChecksum)
{ {
@ -460,14 +456,14 @@ private:
// Calculate the value of extra bytes that can be appended to the data so that the // Calculate the value of extra bytes that can be appended to the data so that the
// data is then valid for the object's checksum // data is then valid for the object's checksum
size_t extraBytesCount = 0; size_t extraBytesCount = 0;
void * extraBytes = CalculateExtraBytesToFixChecksum(realChecksum, entry->checksum, &extraBytesCount); void* extraBytes = CalculateExtraBytesToFixChecksum(realChecksum, entry->checksum, &extraBytesCount);
// Create new data blob with appended bytes // Create new data blob with appended bytes
size_t newDataSize = dataSize + extraBytesCount; size_t newDataSize = dataSize + extraBytesCount;
uint8_t * newData = Memory::Allocate<uint8_t>(newDataSize); uint8_t* newData = Memory::Allocate<uint8_t>(newDataSize);
uint8_t * newDataSaltOffset = newData + dataSize; uint8_t* newDataSaltOffset = newData + dataSize;
std::copy_n((const uint8_t *)data, dataSize, newData); std::copy_n((const uint8_t*)data, dataSize, newData);
std::copy_n((const uint8_t *)extraBytes, extraBytesCount, newDataSaltOffset); std::copy_n((const uint8_t*)extraBytes, extraBytesCount, newDataSaltOffset);
try try
{ {
@ -487,7 +483,7 @@ private:
Memory::Free(newData); Memory::Free(newData);
Memory::Free(extraBytes); Memory::Free(extraBytes);
} }
catch (const std::exception &) catch (const std::exception&)
{ {
Memory::Free(newData); Memory::Free(newData);
Memory::Free(extraBytes); Memory::Free(extraBytes);
@ -502,8 +498,8 @@ private:
sawyercoding_chunk_header chunkHeader; sawyercoding_chunk_header chunkHeader;
chunkHeader.encoding = object_entry_group_encoding[objectType]; chunkHeader.encoding = object_entry_group_encoding[objectType];
chunkHeader.length = (uint32_t)dataSize; chunkHeader.length = (uint32_t)dataSize;
uint8_t * encodedDataBuffer = Memory::Allocate<uint8_t>(0x600000); uint8_t* encodedDataBuffer = Memory::Allocate<uint8_t>(0x600000);
size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (uint8_t *)data, chunkHeader); size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (uint8_t*)data, chunkHeader);
// Save to file // Save to file
try try
@ -514,18 +510,19 @@ private:
Memory::Free(encodedDataBuffer); Memory::Free(encodedDataBuffer);
} }
catch (const std::exception &) catch (const std::exception&)
{ {
Memory::Free(encodedDataBuffer); Memory::Free(encodedDataBuffer);
throw; throw;
} }
} }
static void * CalculateExtraBytesToFixChecksum(int32_t currentChecksum, int32_t targetChecksum, size_t * outSize) static void* CalculateExtraBytesToFixChecksum(int32_t currentChecksum, int32_t targetChecksum, size_t* outSize)
{ {
// Allocate 11 extra bytes to manipulate the checksum // Allocate 11 extra bytes to manipulate the checksum
uint8_t * salt = Memory::Allocate<uint8_t>(11); uint8_t* salt = Memory::Allocate<uint8_t>(11);
if (outSize != nullptr) *outSize = 11; if (outSize != nullptr)
*outSize = 11;
// Next work out which bits need to be flipped to make the current checksum match the one in the file // Next work out which bits need to be flipped to make the current checksum match the one in the file
// The bitwise rotation compensates for the rotation performed during the checksum calculation*/ // The bitwise rotation compensates for the rotation performed during the checksum calculation*/
@ -550,7 +547,7 @@ private:
return salt; return salt;
} }
void GetPathForNewObject(utf8 * buffer, size_t bufferSize, const char * name) void GetPathForNewObject(utf8* buffer, size_t bufferSize, const char* name)
{ {
char normalisedName[9] = { 0 }; char normalisedName[9] = { 0 };
for (int32_t i = 0; i < 8; i++) for (int32_t i = 0; i < 8; i++)
@ -565,7 +562,7 @@ private:
} }
} }
const std::string &userObjPath = _env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT); const std::string& userObjPath = _env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT);
String::Set(buffer, bufferSize, userObjPath.c_str()); String::Set(buffer, bufferSize, userObjPath.c_str());
platform_ensure_directory_exists(buffer); platform_ensure_directory_exists(buffer);
@ -586,9 +583,9 @@ private:
} }
} }
void WritePackedObject(IStream * stream, const rct_object_entry * entry) void WritePackedObject(IStream* stream, const rct_object_entry* entry)
{ {
const ObjectRepositoryItem * item = FindObject(entry); const ObjectRepositoryItem* item = FindObject(entry);
if (item == nullptr) if (item == nullptr)
{ {
throw std::runtime_error(String::StdFormat("Unable to find object '%.8s'", entry->name)); throw std::runtime_error(String::StdFormat("Unable to find object '%.8s'", entry->name));
@ -616,7 +613,7 @@ std::unique_ptr<IObjectRepository> CreateObjectRepository(const std::shared_ptr<
return std::make_unique<ObjectRepository>(env); return std::make_unique<ObjectRepository>(env);
} }
bool IsObjectCustom(const ObjectRepositoryItem * object) bool IsObjectCustom(const ObjectRepositoryItem* object)
{ {
Guard::ArgumentNotNull(object); Guard::ArgumentNotNull(object);
@ -624,9 +621,9 @@ bool IsObjectCustom(const ObjectRepositoryItem * object)
return !(object->ObjectEntry.flags & 0xF0); return !(object->ObjectEntry.flags & 0xF0);
} }
const rct_object_entry * object_list_find(rct_object_entry * entry) const rct_object_entry* object_list_find(rct_object_entry* entry)
{ {
const rct_object_entry * result = nullptr; const rct_object_entry* result = nullptr;
auto objRepo = GetContext()->GetObjectRepository(); auto objRepo = GetContext()->GetObjectRepository();
auto item = objRepo->FindObject(entry); auto item = objRepo->FindObject(entry);
if (item != nullptr) if (item != nullptr)
@ -647,11 +644,11 @@ void object_list_load()
objectManager->UnloadAll(); objectManager->UnloadAll();
} }
void * object_repository_load_object(const rct_object_entry * objectEntry) void* object_repository_load_object(const rct_object_entry* objectEntry)
{ {
Object * object = nullptr; Object* object = nullptr;
auto objRepository = GetContext()->GetObjectRepository(); auto objRepository = GetContext()->GetObjectRepository();
const ObjectRepositoryItem * ori = objRepository->FindObject(objectEntry); const ObjectRepositoryItem* ori = objRepository->FindObject(objectEntry);
if (ori != nullptr) if (ori != nullptr)
{ {
object = objRepository->LoadObject(ori); object = objRepository->LoadObject(ori);
@ -660,10 +657,10 @@ void * object_repository_load_object(const rct_object_entry * objectEntry)
object->Load(); object->Load();
} }
} }
return (void *)object; return (void*)object;
} }
void scenario_translate(scenario_index_entry * scenarioEntry, const rct_object_entry * stexObjectEntry) void scenario_translate(scenario_index_entry* scenarioEntry, const rct_object_entry* stexObjectEntry)
{ {
rct_string_id localisedStringIds[3]; rct_string_id localisedStringIds[3];
if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds)) if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds))
@ -683,10 +680,10 @@ void scenario_translate(scenario_index_entry * scenarioEntry, const rct_object_e
if ((stexObjectEntry->flags & 0xFF) != 255) if ((stexObjectEntry->flags & 0xFF) != 255)
{ {
auto objectRepository = GetContext()->GetObjectRepository(); auto objectRepository = GetContext()->GetObjectRepository();
const ObjectRepositoryItem * ori = objectRepository->FindObject(stexObjectEntry); const ObjectRepositoryItem* ori = objectRepository->FindObject(stexObjectEntry);
if (ori != nullptr) if (ori != nullptr)
{ {
Object * object = objectRepository->LoadObject(ori); Object* object = objectRepository->LoadObject(ori);
if (object != nullptr) if (object != nullptr)
{ {
auto stexObject = static_cast<StexObject*>(object); auto stexObject = static_cast<StexObject*>(object);
@ -709,41 +706,41 @@ size_t object_repository_get_items_count()
return objectRepository->GetNumObjects(); return objectRepository->GetNumObjects();
} }
const ObjectRepositoryItem * object_repository_get_items() const ObjectRepositoryItem* object_repository_get_items()
{ {
auto objectRepository = GetContext()->GetObjectRepository(); auto objectRepository = GetContext()->GetObjectRepository();
return objectRepository->GetObjects(); return objectRepository->GetObjects();
} }
const ObjectRepositoryItem * object_repository_find_object_by_entry(const rct_object_entry * entry) const ObjectRepositoryItem* object_repository_find_object_by_entry(const rct_object_entry* entry)
{ {
auto objectRepository = GetContext()->GetObjectRepository(); auto objectRepository = GetContext()->GetObjectRepository();
return objectRepository->FindObject(entry); return objectRepository->FindObject(entry);
} }
const ObjectRepositoryItem * object_repository_find_object_by_name(const char * name) const ObjectRepositoryItem* object_repository_find_object_by_name(const char* name)
{ {
auto objectRepository = GetContext()->GetObjectRepository(); auto objectRepository = GetContext()->GetObjectRepository();
return objectRepository->FindObject(name); return objectRepository->FindObject(name);
} }
void object_delete(void * object) void object_delete(void* object)
{ {
if (object != nullptr) if (object != nullptr)
{ {
Object * baseObject = static_cast<Object *>(object); Object* baseObject = static_cast<Object*>(object);
baseObject->Unload(); baseObject->Unload();
delete baseObject; delete baseObject;
} }
} }
void object_draw_preview(const void * object, rct_drawpixelinfo * dpi, int32_t width, int32_t height) void object_draw_preview(const void* object, rct_drawpixelinfo* dpi, int32_t width, int32_t height)
{ {
const Object * baseObject = static_cast<const Object *>(object); const Object* baseObject = static_cast<const Object*>(object);
baseObject->DrawPreview(dpi, width, height); baseObject->DrawPreview(dpi, width, height);
} }
bool object_entry_compare(const rct_object_entry * a, const rct_object_entry * b) bool object_entry_compare(const rct_object_entry* a, const rct_object_entry* b)
{ {
// If an official object don't bother checking checksum // If an official object don't bother checking checksum
if ((a->flags & 0xF0) || (b->flags & 0xF0)) if ((a->flags & 0xF0) || (b->flags & 0xF0))
@ -777,9 +774,9 @@ bool object_entry_compare(const rct_object_entry * a, const rct_object_entry * b
return true; return true;
} }
int32_t object_calculate_checksum(const rct_object_entry * entry, const void * data, size_t dataLength) int32_t object_calculate_checksum(const rct_object_entry* entry, const void* data, size_t dataLength)
{ {
const uint8_t * entryBytePtr = (uint8_t *)entry; const uint8_t* entryBytePtr = (uint8_t*)entry;
uint32_t checksum = 0xF369A75B; uint32_t checksum = 0xF369A75B;
checksum ^= entryBytePtr[0]; checksum ^= entryBytePtr[0];
@ -790,7 +787,7 @@ int32_t object_calculate_checksum(const rct_object_entry * entry, const void * d
checksum = rol32(checksum, 11); checksum = rol32(checksum, 11);
} }
uint8_t * dataBytes = (uint8_t *)data; uint8_t* dataBytes = (uint8_t*)data;
const size_t dataLength32 = dataLength - (dataLength & 31); const size_t dataLength32 = dataLength - (dataLength & 31);
for (size_t i = 0; i < 32; i++) for (size_t i = 0; i < 32; i++)
{ {

View File

@ -9,14 +9,15 @@
#pragma once #pragma once
#include <memory>
#include <vector>
#include "../common.h" #include "../common.h"
#include "../object/Object.h" #include "../object/Object.h"
#include "../ride/Ride.h" #include "../ride/Ride.h"
interface IStream; #include <memory>
class Object; #include <vector>
interface IStream;
class Object;
namespace OpenRCT2 namespace OpenRCT2
{ {
interface IPlatformEnvironment; interface IPlatformEnvironment;
@ -31,17 +32,17 @@ struct rct_drawpixelinfo;
struct ObjectRepositoryItem struct ObjectRepositoryItem
{ {
size_t Id; size_t Id;
rct_object_entry ObjectEntry; rct_object_entry ObjectEntry;
std::string Path; std::string Path;
std::string Name; std::string Name;
Object * LoadedObject{}; Object* LoadedObject{};
struct struct
{ {
uint8_t RideFlags; uint8_t RideFlags;
uint8_t RideCategory[MAX_CATEGORIES_PER_RIDE]; uint8_t RideCategory[MAX_CATEGORIES_PER_RIDE];
uint8_t RideType[MAX_RIDE_TYPES_PER_RIDE_ENTRY]; uint8_t RideType[MAX_RIDE_TYPES_PER_RIDE_ENTRY];
uint8_t RideGroupIndex; uint8_t RideGroupIndex;
} RideInfo; } RideInfo;
struct struct
{ {
@ -53,34 +54,32 @@ interface IObjectRepository
{ {
virtual ~IObjectRepository() = default; virtual ~IObjectRepository() = default;
virtual void LoadOrConstruct(int32_t language) abstract; virtual void LoadOrConstruct(int32_t language) abstract;
virtual void Construct(int32_t language) abstract; virtual void Construct(int32_t language) abstract;
virtual size_t GetNumObjects() const abstract; virtual size_t GetNumObjects() const abstract;
virtual const ObjectRepositoryItem * GetObjects() const abstract; virtual const ObjectRepositoryItem* GetObjects() const abstract;
virtual const ObjectRepositoryItem * FindObject(const utf8 * name) const abstract; virtual const ObjectRepositoryItem* FindObject(const utf8* name) const abstract;
virtual const ObjectRepositoryItem * FindObject(const rct_object_entry * objectEntry) const abstract; virtual const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const abstract;
virtual Object * LoadObject(const ObjectRepositoryItem * ori) abstract; virtual Object* LoadObject(const ObjectRepositoryItem* ori) abstract;
virtual void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) abstract; virtual void RegisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) abstract;
virtual void UnregisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) abstract; virtual void UnregisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) abstract;
virtual void AddObject(const rct_object_entry * objectEntry, virtual void AddObject(const rct_object_entry* objectEntry, const void* data, size_t dataSize) abstract;
const void * data,
size_t dataSize) abstract;
virtual void ExportPackedObject(IStream * stream) abstract; virtual void ExportPackedObject(IStream * stream) abstract;
virtual void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem *> &objects) abstract; virtual void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem*> & objects) abstract;
}; };
std::unique_ptr<IObjectRepository> CreateObjectRepository(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env); std::unique_ptr<IObjectRepository> CreateObjectRepository(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
bool IsObjectCustom(const ObjectRepositoryItem * object); bool IsObjectCustom(const ObjectRepositoryItem* object);
size_t object_repository_get_items_count(); size_t object_repository_get_items_count();
const ObjectRepositoryItem * object_repository_get_items(); const ObjectRepositoryItem* object_repository_get_items();
const ObjectRepositoryItem * object_repository_find_object_by_entry(const rct_object_entry * entry); const ObjectRepositoryItem* object_repository_find_object_by_entry(const rct_object_entry* entry);
const ObjectRepositoryItem * object_repository_find_object_by_name(const char * name); const ObjectRepositoryItem* object_repository_find_object_by_name(const char* name);
void * object_repository_load_object(const rct_object_entry * objectEntry); void* object_repository_load_object(const rct_object_entry* objectEntry);
void object_delete(void * object); void object_delete(void* object);
void object_draw_preview(const void * object, rct_drawpixelinfo * dpi, int32_t width, int32_t height); void object_draw_preview(const void* object, rct_drawpixelinfo* dpi, int32_t width, int32_t height);

View File

@ -9,32 +9,34 @@
#pragma warning(disable : 4706) // assignment within conditional expression #pragma warning(disable : 4706) // assignment within conditional expression
#include <algorithm> #include "RideObject.h"
#include <unordered_map>
#include "../OpenRCT2.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../core/Math.hpp" #include "../core/Math.hpp"
#include "../core/Memory.hpp" #include "../core/Memory.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../core/Util.hpp" #include "../core/Util.hpp"
#include "../ride/RideGroupManager.h"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../rct2/RCT2.h" #include "../rct2/RCT2.h"
#include "../ride/Ride.h" #include "../ride/Ride.h"
#include "../ride/RideGroupManager.h"
#include "../ride/ShopItem.h" #include "../ride/ShopItem.h"
#include "../ride/Track.h" #include "../ride/Track.h"
#include "../OpenRCT2.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
#include "ObjectRepository.h" #include "ObjectRepository.h"
#include "RideObject.h"
#include <algorithm>
#include <unordered_map>
using namespace OpenRCT2; using namespace OpenRCT2;
void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void RideObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(8, STREAM_SEEK_CURRENT); stream->Seek(8, STREAM_SEEK_CURRENT);
_legacyType.flags = stream->ReadValue<uint32_t>(); _legacyType.flags = stream->ReadValue<uint32_t>();
for (auto &rideType : _legacyType.ride_type) for (auto& rideType : _legacyType.ride_type)
{ {
rideType = stream->ReadValue<uint8_t>(); rideType = stream->ReadValue<uint8_t>();
} }
@ -49,7 +51,7 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
_legacyType.rear_vehicle = stream->ReadValue<uint8_t>(); _legacyType.rear_vehicle = stream->ReadValue<uint8_t>();
_legacyType.third_vehicle = stream->ReadValue<uint8_t>(); _legacyType.third_vehicle = stream->ReadValue<uint8_t>();
_legacyType.pad_019 = stream->ReadValue<uint8_t>(); _legacyType.pad_019 = stream->ReadValue<uint8_t>();
for (auto &vehicleEntry : _legacyType.vehicles) for (auto& vehicleEntry : _legacyType.vehicles)
{ {
ReadLegacyVehicle(context, stream, &vehicleEntry); ReadLegacyVehicle(context, stream, &vehicleEntry);
} }
@ -95,7 +97,7 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
{ {
numPeepLoadingPositions = stream->ReadValue<uint16_t>(); numPeepLoadingPositions = stream->ReadValue<uint16_t>();
} }
if (_legacyType.vehicles[i].flags & VEHICLE_ENTRY_FLAG_LOADING_WAYPOINTS) if (_legacyType.vehicles[i].flags & VEHICLE_ENTRY_FLAG_LOADING_WAYPOINTS)
{ {
_legacyType.vehicles[i].peep_loading_waypoint_segments = stream->ReadValue<int8_t>() == 0 ? 0 : 4; _legacyType.vehicles[i].peep_loading_waypoint_segments = stream->ReadValue<int8_t>() == 0 ? 0 : 4;
@ -161,15 +163,15 @@ void RideObject::Load()
int32_t cur_vehicle_images_offset = _legacyType.images_offset + MAX_RIDE_TYPES_PER_RIDE_ENTRY; int32_t cur_vehicle_images_offset = _legacyType.images_offset + MAX_RIDE_TYPES_PER_RIDE_ENTRY;
for (int32_t i = 0; i < RCT2_MAX_VEHICLES_PER_RIDE_ENTRY; i++) for (int32_t i = 0; i < RCT2_MAX_VEHICLES_PER_RIDE_ENTRY; i++)
{ {
rct_ride_entry_vehicle * vehicleEntry = &_legacyType.vehicles[i]; rct_ride_entry_vehicle* vehicleEntry = &_legacyType.vehicles[i];
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT) if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT)
{ {
// RCT2 calculates num_vertical_frames and num_horizontal_frames and overwrites these properties on the vehicle entry. // RCT2 calculates num_vertical_frames and num_horizontal_frames and overwrites these properties on the vehicle
// Immediately afterwards, the two were multiplied in order to calculate base_num_frames and were never used again. // entry. Immediately afterwards, the two were multiplied in order to calculate base_num_frames and were never used
// This has been changed to use the calculation results directly - // again. This has been changed to use the calculation results directly - num_vertical_frames and
// num_vertical_frames and num_horizontal_frames are no longer set on the vehicle entry. // num_horizontal_frames are no longer set on the vehicle entry. 0x6DE946
// 0x6DE946 vehicleEntry->base_num_frames
vehicleEntry->base_num_frames = CalculateNumVerticalFrames(vehicleEntry) * CalculateNumHorizontalFrames(vehicleEntry); = CalculateNumVerticalFrames(vehicleEntry) * CalculateNumHorizontalFrames(vehicleEntry);
vehicleEntry->base_image_id = cur_vehicle_images_offset; vehicleEntry->base_image_id = cur_vehicle_images_offset;
int32_t image_index = vehicleEntry->base_image_id; int32_t image_index = vehicleEntry->base_image_id;
@ -177,8 +179,10 @@ void RideObject::Load()
{ {
int32_t b = vehicleEntry->base_num_frames * 32; int32_t b = vehicleEntry->base_num_frames * 32;
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_11) b /= 2; if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_11)
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_15) b /= 8; b /= 2;
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_15)
b /= 8;
image_index += b; image_index += b;
@ -305,7 +309,8 @@ void RideObject::Load()
num_images *= 2; num_images *= 2;
} }
if (!gOpenRCT2NoGraphics) { if (!gOpenRCT2NoGraphics)
{
set_vehicle_type_image_max_sizes(vehicleEntry, num_images); set_vehicle_type_image_max_sizes(vehicleEntry, num_images);
} }
} }
@ -361,7 +366,7 @@ std::string RideObject::GetCapacity() const
return GetString(OBJ_STRING_ID_CAPACITY); return GetString(OBJ_STRING_ID_CAPACITY);
} }
void RideObject::SetRepositoryItem(ObjectRepositoryItem * item) const void RideObject::SetRepositoryItem(ObjectRepositoryItem* item) const
{ {
for (int32_t i = 0; i < RCT2_MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) for (int32_t i = 0; i < RCT2_MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
{ {
@ -381,14 +386,14 @@ void RideObject::SetRepositoryItem(ObjectRepositoryItem * item) const
// Determines the ride group. Will fall back to 0 if there is none found. // Determines the ride group. Will fall back to 0 if there is none found.
uint8_t rideGroupIndex = 0; uint8_t rideGroupIndex = 0;
const RideGroup * rideGroup = RideGroupManager::GetRideGroup(rideTypeIdx, &_legacyType); const RideGroup* rideGroup = RideGroupManager::GetRideGroup(rideTypeIdx, &_legacyType);
// If the ride group is nullptr, the track type does not have ride groups. // If the ride group is nullptr, the track type does not have ride groups.
if (rideGroup != nullptr) if (rideGroup != nullptr)
{ {
for (uint8_t i = rideGroupIndex + 1; i < MAX_RIDE_GROUPS_PER_RIDE_TYPE; i++) for (uint8_t i = rideGroupIndex + 1; i < MAX_RIDE_GROUPS_PER_RIDE_TYPE; i++)
{ {
const RideGroup * irg = RideGroupManager::RideGroupFind(rideTypeIdx, i); const RideGroup* irg = RideGroupManager::RideGroupFind(rideTypeIdx, i);
if (irg != nullptr) if (irg != nullptr)
{ {
@ -437,7 +442,7 @@ void RideObject::ReadLegacyVehicle(
stream->Seek(4, STREAM_SEEK_CURRENT); stream->Seek(4, STREAM_SEEK_CURRENT);
} }
uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry) uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle* vehicleEntry)
{ {
// 0x6DE90B // 0x6DE90B
uint8_t numVerticalFrames; uint8_t numVerticalFrames;
@ -449,7 +454,8 @@ uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle * ve
{ {
if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES)) if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES))
{ {
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION && vehicleEntry->animation != VEHICLE_ENTRY_ANIMATION_OBSERVATION_TOWER) if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION
&& vehicleEntry->animation != VEHICLE_ENTRY_ANIMATION_OBSERVATION_TOWER)
{ {
if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS)) if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS))
{ {
@ -474,7 +480,7 @@ uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle * ve
return numVerticalFrames; return numVerticalFrames;
} }
uint8_t RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * vehicleEntry) uint8_t RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle* vehicleEntry)
{ {
uint8_t numHorizontalFrames; uint8_t numHorizontalFrames;
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SWINGING) if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SWINGING)
@ -507,7 +513,7 @@ uint8_t RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle *
return numHorizontalFrames; return numHorizontalFrames;
} }
void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) void RideObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
@ -547,7 +553,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root)
if (IsRideTypeShopOrFacility(_legacyType.ride_type[0])) if (IsRideTypeShopOrFacility(_legacyType.ride_type[0]))
{ {
// Standard car info for a shop // Standard car info for a shop
auto &car = _legacyType.vehicles[0]; auto& car = _legacyType.vehicles[0];
car.spacing = 544; car.spacing = 544;
car.sprite_flags = VEHICLE_SPRITE_FLAG_FLAT; car.sprite_flags = VEHICLE_SPRITE_FLAG_FLAT;
car.sprite_width = 1; car.sprite_width = 1;
@ -620,19 +626,20 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root)
_presetColours = ReadJsonCarColours(json_object_get(properties, "carColours")); _presetColours = ReadJsonCarColours(json_object_get(properties, "carColours"));
} }
_legacyType.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(properties, { _legacyType.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(
{ "noInversions", RIDE_ENTRY_FLAG_NO_INVERSIONS }, properties,
{ "noBanking", RIDE_ENTRY_FLAG_NO_BANKED_TRACK }, { { "noInversions", RIDE_ENTRY_FLAG_NO_INVERSIONS },
{ "playDepartSound", RIDE_ENTRY_FLAG_PLAY_DEPART_SOUND }, { "noBanking", RIDE_ENTRY_FLAG_NO_BANKED_TRACK },
// Skipping "disallowWandering", no vehicle sets this flag. { "playDepartSound", RIDE_ENTRY_FLAG_PLAY_DEPART_SOUND },
{ "playSplashSound", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND }, // Skipping "disallowWandering", no vehicle sets this flag.
{ "playSplashSoundSlide", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND_SLIDE }, { "playSplashSound", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND },
{ "hasShelter", RIDE_ENTRY_FLAG_COVERED_RIDE }, { "playSplashSoundSlide", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND_SLIDE },
{ "limitAirTimeBonus", RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS }, { "hasShelter", RIDE_ENTRY_FLAG_COVERED_RIDE },
{ "disableBreakdown", RIDE_ENTRY_FLAG_CANNOT_BREAK_DOWN }, { "limitAirTimeBonus", RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS },
// Skipping noDoorsOverTrack, moved to ride groups. { "disableBreakdown", RIDE_ENTRY_FLAG_CANNOT_BREAK_DOWN },
{ "noCollisionCrashes", RIDE_ENTRY_FLAG_DISABLE_COLLISION_CRASHES }, // Skipping noDoorsOverTrack, moved to ride groups.
{ "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB } }); { "noCollisionCrashes", RIDE_ENTRY_FLAG_DISABLE_COLLISION_CRASHES },
{ "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB } });
ObjectJsonHelpers::LoadStrings(root, GetStringTable()); ObjectJsonHelpers::LoadStrings(root, GetStringTable());
ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
@ -696,13 +703,13 @@ void RideObject::ReadJsonVehicleInfo([[maybe_unused]] IReadObjectContext* contex
} }
} }
std::vector<rct_ride_entry_vehicle> RideObject::ReadJsonCars(const json_t * jCars) std::vector<rct_ride_entry_vehicle> RideObject::ReadJsonCars(const json_t* jCars)
{ {
std::vector<rct_ride_entry_vehicle> cars; std::vector<rct_ride_entry_vehicle> cars;
if (json_is_array(jCars)) if (json_is_array(jCars))
{ {
json_t * jCar; json_t* jCar;
size_t index; size_t index;
json_array_foreach(jCars, index, jCar) json_array_foreach(jCars, index, jCar)
{ {
@ -718,7 +725,7 @@ std::vector<rct_ride_entry_vehicle> RideObject::ReadJsonCars(const json_t * jCar
return cars; return cars;
} }
rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t* jCar)
{ {
rct_ride_entry_vehicle car = {}; rct_ride_entry_vehicle car = {};
car.rotation_frame_mask = ObjectJsonHelpers::GetInteger(jCar, "rotationFrameMask"); car.rotation_frame_mask = ObjectJsonHelpers::GetInteger(jCar, "rotationFrameMask");
@ -771,15 +778,15 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar)
auto numSegments = ObjectJsonHelpers::GetInteger(jCar, "numSegments"); auto numSegments = ObjectJsonHelpers::GetInteger(jCar, "numSegments");
car.peep_loading_waypoint_segments = numSegments; car.peep_loading_waypoint_segments = numSegments;
size_t i; size_t i;
json_t * route; json_t* route;
json_array_foreach(jLoadingWaypoints, i, route) json_array_foreach(jLoadingWaypoints, i, route)
{ {
if (json_is_array(route)) if (json_is_array(route))
{ {
size_t j; size_t j;
json_t * waypoint; json_t* waypoint;
std::array<sLocationXY8, 3> entry; std::array<sLocationXY8, 3> entry;
json_array_foreach(route, j, waypoint) json_array_foreach(route, j, waypoint)
{ {
@ -797,60 +804,62 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar)
} }
auto jFrames = json_object_get(jCar, "frames"); auto jFrames = json_object_get(jCar, "frames");
car.sprite_flags = ObjectJsonHelpers::GetFlags<uint16_t>(jFrames, { car.sprite_flags = ObjectJsonHelpers::GetFlags<uint16_t>(
{ "flat", VEHICLE_SPRITE_FLAG_FLAT }, jFrames,
{ "gentleSlopes", VEHICLE_SPRITE_FLAG_GENTLE_SLOPES }, { { "flat", VEHICLE_SPRITE_FLAG_FLAT },
{ "steepSlopes", VEHICLE_SPRITE_FLAG_STEEP_SLOPES }, { "gentleSlopes", VEHICLE_SPRITE_FLAG_GENTLE_SLOPES },
{ "verticalSlopes", VEHICLE_SPRITE_FLAG_VERTICAL_SLOPES }, { "steepSlopes", VEHICLE_SPRITE_FLAG_STEEP_SLOPES },
{ "diagonalSlopes", VEHICLE_SPRITE_FLAG_DIAGONAL_SLOPES }, { "verticalSlopes", VEHICLE_SPRITE_FLAG_VERTICAL_SLOPES },
{ "flatBanked", VEHICLE_SPRITE_FLAG_FLAT_BANKED }, { "diagonalSlopes", VEHICLE_SPRITE_FLAG_DIAGONAL_SLOPES },
{ "inlineTwists", VEHICLE_SPRITE_FLAG_INLINE_TWISTS }, { "flatBanked", VEHICLE_SPRITE_FLAG_FLAT_BANKED },
{ "flatToGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_BANKED_TRANSITIONS }, { "inlineTwists", VEHICLE_SPRITE_FLAG_INLINE_TWISTS },
{ "diagonalGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_DIAGONAL_GENTLE_SLOPE_BANKED_TRANSITIONS }, { "flatToGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_BANKED_TRANSITIONS },
{ "gentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TRANSITIONS }, { "diagonalGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_DIAGONAL_GENTLE_SLOPE_BANKED_TRANSITIONS },
{ "gentleSlopeBankedTurns", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TURNS }, { "gentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TRANSITIONS },
{ "flatToGentleSlopeWhileBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS }, { "gentleSlopeBankedTurns", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TURNS },
{ "corkscrews", VEHICLE_SPRITE_FLAG_CORKSCREWS }, { "flatToGentleSlopeWhileBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS },
{ "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION }, { "corkscrews", VEHICLE_SPRITE_FLAG_CORKSCREWS },
{ "curvedLiftHill", VEHICLE_SPRITE_FLAG_CURVED_LIFT_HILL }, { "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION },
{ "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } }); { "curvedLiftHill", VEHICLE_SPRITE_FLAG_CURVED_LIFT_HILL },
{ "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } });
car.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(jCar, { car.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(
{ "VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY", VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY }, jCar,
{ "VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS", VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS }, { { "VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY", VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY },
{ "VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH", VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH }, { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS", VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS },
{ "VEHICLE_ENTRY_FLAG_MINI_GOLF", VEHICLE_ENTRY_FLAG_MINI_GOLF }, { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH", VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH },
{ "VEHICLE_ENTRY_FLAG_4", VEHICLE_ENTRY_FLAG_4 }, { "VEHICLE_ENTRY_FLAG_MINI_GOLF", VEHICLE_ENTRY_FLAG_MINI_GOLF },
{ "VEHICLE_ENTRY_FLAG_5", VEHICLE_ENTRY_FLAG_5 }, { "VEHICLE_ENTRY_FLAG_4", VEHICLE_ENTRY_FLAG_4 },
{ "VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET", VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET }, { "VEHICLE_ENTRY_FLAG_5", VEHICLE_ENTRY_FLAG_5 },
{ "VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS", VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS }, { "VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET", VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET },
{ "VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED", VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED }, { "VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS", VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS },
{ "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2 }, { "VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED", VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED },
{ "VEHICLE_ENTRY_FLAG_10", VEHICLE_ENTRY_FLAG_10 }, { "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2 },
{ "VEHICLE_ENTRY_FLAG_11", VEHICLE_ENTRY_FLAG_11 }, { "VEHICLE_ENTRY_FLAG_10", VEHICLE_ENTRY_FLAG_10 },
{ "VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES", VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES }, { "VEHICLE_ENTRY_FLAG_11", VEHICLE_ENTRY_FLAG_11 },
{ "VEHICLE_ENTRY_FLAG_13", VEHICLE_ENTRY_FLAG_13 }, { "VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES", VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES },
{ "VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES", VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES }, { "VEHICLE_ENTRY_FLAG_13", VEHICLE_ENTRY_FLAG_13 },
{ "VEHICLE_ENTRY_FLAG_LIFT", VEHICLE_ENTRY_FLAG_LIFT }, { "VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES", VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES },
{ "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1 }, { "VEHICLE_ENTRY_FLAG_LIFT", VEHICLE_ENTRY_FLAG_LIFT },
{ "VEHICLE_ENTRY_FLAG_SWINGING", VEHICLE_ENTRY_FLAG_SWINGING }, { "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1 },
{ "VEHICLE_ENTRY_FLAG_SPINNING", VEHICLE_ENTRY_FLAG_SPINNING }, { "VEHICLE_ENTRY_FLAG_SWINGING", VEHICLE_ENTRY_FLAG_SWINGING },
{ "VEHICLE_ENTRY_FLAG_POWERED", VEHICLE_ENTRY_FLAG_POWERED }, { "VEHICLE_ENTRY_FLAG_SPINNING", VEHICLE_ENTRY_FLAG_SPINNING },
{ "VEHICLE_ENTRY_FLAG_RIDERS_SCREAM", VEHICLE_ENTRY_FLAG_RIDERS_SCREAM }, { "VEHICLE_ENTRY_FLAG_POWERED", VEHICLE_ENTRY_FLAG_POWERED },
{ "VEHICLE_ENTRY_FLAG_21", VEHICLE_ENTRY_FLAG_21 }, { "VEHICLE_ENTRY_FLAG_RIDERS_SCREAM", VEHICLE_ENTRY_FLAG_RIDERS_SCREAM },
{ "VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION", VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION }, { "VEHICLE_ENTRY_FLAG_21", VEHICLE_ENTRY_FLAG_21 },
{ "VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION", VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION }, { "VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION", VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION },
{ "VEHICLE_ENTRY_FLAG_RIDER_ANIMATION", VEHICLE_ENTRY_FLAG_RIDER_ANIMATION }, { "VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION", VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION },
{ "VEHICLE_ENTRY_FLAG_25", VEHICLE_ENTRY_FLAG_25 }, { "VEHICLE_ENTRY_FLAG_RIDER_ANIMATION", VEHICLE_ENTRY_FLAG_RIDER_ANIMATION },
{ "VEHICLE_ENTRY_FLAG_SLIDE_SWING", VEHICLE_ENTRY_FLAG_SLIDE_SWING }, { "VEHICLE_ENTRY_FLAG_25", VEHICLE_ENTRY_FLAG_25 },
{ "VEHICLE_ENTRY_FLAG_CHAIRLIFT", VEHICLE_ENTRY_FLAG_CHAIRLIFT }, { "VEHICLE_ENTRY_FLAG_SLIDE_SWING", VEHICLE_ENTRY_FLAG_SLIDE_SWING },
{ "VEHICLE_ENTRY_FLAG_WATER_RIDE", VEHICLE_ENTRY_FLAG_WATER_RIDE }, { "VEHICLE_ENTRY_FLAG_CHAIRLIFT", VEHICLE_ENTRY_FLAG_CHAIRLIFT },
{ "VEHICLE_ENTRY_FLAG_GO_KART", VEHICLE_ENTRY_FLAG_GO_KART }, { "VEHICLE_ENTRY_FLAG_WATER_RIDE", VEHICLE_ENTRY_FLAG_WATER_RIDE },
{ "VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT", VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT } }); { "VEHICLE_ENTRY_FLAG_GO_KART", VEHICLE_ENTRY_FLAG_GO_KART },
{ "VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT", VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT } });
return car; return car;
} }
vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t * jCarColours) vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t* jCarColours)
{ {
// The JSON supports multiple configurations of per car colours, but // The JSON supports multiple configurations of per car colours, but
// the ride entry structure currently doesn't allow for it. Assume that // the ride entry structure currently doesn't allow for it. Assume that
@ -873,7 +882,7 @@ vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t * jCarCol
// Read first colour for each config // Read first colour for each config
vehicle_colour_preset_list list = {}; vehicle_colour_preset_list list = {};
size_t index; size_t index;
const json_t * jConfiguration; const json_t* jConfiguration;
json_array_foreach(jCarColours, index, jConfiguration) json_array_foreach(jCarColours, index, jConfiguration)
{ {
auto config = ReadJsonColourConfiguration(jConfiguration); auto config = ReadJsonColourConfiguration(jConfiguration);
@ -892,11 +901,11 @@ vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t * jCarCol
return list; return list;
} }
std::vector<vehicle_colour> RideObject::ReadJsonColourConfiguration(const json_t * jColourConfig) std::vector<vehicle_colour> RideObject::ReadJsonColourConfiguration(const json_t* jColourConfig)
{ {
std::vector<vehicle_colour> config; std::vector<vehicle_colour> config;
size_t index; size_t index;
const json_t * jColours; const json_t* jColours;
json_array_foreach(jColourConfig, index, jColours) json_array_foreach(jColourConfig, index, jColours)
{ {
vehicle_colour carColour = {}; vehicle_colour carColour = {};
@ -924,178 +933,168 @@ bool RideObject::IsRideTypeShopOrFacility(uint8_t rideType)
{ {
switch (rideType) switch (rideType)
{ {
case RIDE_TYPE_TOILETS: case RIDE_TYPE_TOILETS:
case RIDE_TYPE_SHOP: case RIDE_TYPE_SHOP:
case RIDE_TYPE_DRINK_STALL: case RIDE_TYPE_DRINK_STALL:
case RIDE_TYPE_FOOD_STALL: case RIDE_TYPE_FOOD_STALL:
case RIDE_TYPE_INFORMATION_KIOSK: case RIDE_TYPE_INFORMATION_KIOSK:
case RIDE_TYPE_CASH_MACHINE: case RIDE_TYPE_CASH_MACHINE:
case RIDE_TYPE_FIRST_AID: case RIDE_TYPE_FIRST_AID:
return true; return true;
default: default:
return false; return false;
} }
} }
uint8_t RideObject::ParseRideType(const std::string &s) uint8_t RideObject::ParseRideType(const std::string& s)
{ {
static const std::unordered_map<std::string, uint8_t> LookupTable static const std::unordered_map<std::string, uint8_t> LookupTable{
{ { "spiral_rc", RIDE_TYPE_SPIRAL_ROLLER_COASTER },
{ "spiral_rc", RIDE_TYPE_SPIRAL_ROLLER_COASTER }, { "stand_up_rc", RIDE_TYPE_STAND_UP_ROLLER_COASTER },
{ "stand_up_rc", RIDE_TYPE_STAND_UP_ROLLER_COASTER }, { "suspended_swinging_rc", RIDE_TYPE_SUSPENDED_SWINGING_COASTER },
{ "suspended_swinging_rc", RIDE_TYPE_SUSPENDED_SWINGING_COASTER }, { "inverted_rc", RIDE_TYPE_INVERTED_ROLLER_COASTER },
{ "inverted_rc", RIDE_TYPE_INVERTED_ROLLER_COASTER }, { "junior_rc", RIDE_TYPE_JUNIOR_ROLLER_COASTER },
{ "junior_rc", RIDE_TYPE_JUNIOR_ROLLER_COASTER }, { "miniature_railway", RIDE_TYPE_MINIATURE_RAILWAY },
{ "miniature_railway", RIDE_TYPE_MINIATURE_RAILWAY }, { "monorail", RIDE_TYPE_MONORAIL },
{ "monorail", RIDE_TYPE_MONORAIL }, { "mini_suspended_rc", RIDE_TYPE_MINI_SUSPENDED_COASTER },
{ "mini_suspended_rc", RIDE_TYPE_MINI_SUSPENDED_COASTER }, { "boat_hire", RIDE_TYPE_BOAT_HIRE },
{ "boat_hire", RIDE_TYPE_BOAT_HIRE }, { "wooden_wild_mouse", RIDE_TYPE_WOODEN_WILD_MOUSE },
{ "wooden_wild_mouse", RIDE_TYPE_WOODEN_WILD_MOUSE }, { "steeplechase", RIDE_TYPE_STEEPLECHASE },
{ "steeplechase", RIDE_TYPE_STEEPLECHASE }, { "car_ride", RIDE_TYPE_CAR_RIDE },
{ "car_ride", RIDE_TYPE_CAR_RIDE }, { "launched_freefall", RIDE_TYPE_LAUNCHED_FREEFALL },
{ "launched_freefall", RIDE_TYPE_LAUNCHED_FREEFALL }, { "bobsleigh_rc", RIDE_TYPE_BOBSLEIGH_COASTER },
{ "bobsleigh_rc", RIDE_TYPE_BOBSLEIGH_COASTER }, { "observation_tower", RIDE_TYPE_OBSERVATION_TOWER },
{ "observation_tower", RIDE_TYPE_OBSERVATION_TOWER }, { "looping_rc", RIDE_TYPE_LOOPING_ROLLER_COASTER },
{ "looping_rc", RIDE_TYPE_LOOPING_ROLLER_COASTER }, { "dinghy_slide", RIDE_TYPE_DINGHY_SLIDE },
{ "dinghy_slide", RIDE_TYPE_DINGHY_SLIDE }, { "mine_train_rc", RIDE_TYPE_MINE_TRAIN_COASTER },
{ "mine_train_rc", RIDE_TYPE_MINE_TRAIN_COASTER }, { "chairlift", RIDE_TYPE_CHAIRLIFT },
{ "chairlift", RIDE_TYPE_CHAIRLIFT }, { "corkscrew_rc", RIDE_TYPE_CORKSCREW_ROLLER_COASTER },
{ "corkscrew_rc", RIDE_TYPE_CORKSCREW_ROLLER_COASTER }, { "maze", RIDE_TYPE_MAZE },
{ "maze", RIDE_TYPE_MAZE }, { "spiral_slide", RIDE_TYPE_SPIRAL_SLIDE },
{ "spiral_slide", RIDE_TYPE_SPIRAL_SLIDE }, { "go_karts", RIDE_TYPE_GO_KARTS },
{ "go_karts", RIDE_TYPE_GO_KARTS }, { "log_flume", RIDE_TYPE_LOG_FLUME },
{ "log_flume", RIDE_TYPE_LOG_FLUME }, { "river_rapids", RIDE_TYPE_RIVER_RAPIDS },
{ "river_rapids", RIDE_TYPE_RIVER_RAPIDS }, { "dodgems", RIDE_TYPE_DODGEMS },
{ "dodgems", RIDE_TYPE_DODGEMS }, { "swinging_ship", RIDE_TYPE_SWINGING_SHIP },
{ "swinging_ship", RIDE_TYPE_SWINGING_SHIP }, { "swinging_inverter_ship", RIDE_TYPE_SWINGING_INVERTER_SHIP },
{ "swinging_inverter_ship", RIDE_TYPE_SWINGING_INVERTER_SHIP }, { "food_stall", RIDE_TYPE_FOOD_STALL },
{ "food_stall", RIDE_TYPE_FOOD_STALL }, { "drink_stall", RIDE_TYPE_DRINK_STALL },
{ "drink_stall", RIDE_TYPE_DRINK_STALL }, { "shop", RIDE_TYPE_SHOP },
{ "shop", RIDE_TYPE_SHOP }, { "merry_go_round", RIDE_TYPE_MERRY_GO_ROUND },
{ "merry_go_round", RIDE_TYPE_MERRY_GO_ROUND }, { "information_kiosk", RIDE_TYPE_INFORMATION_KIOSK },
{ "information_kiosk", RIDE_TYPE_INFORMATION_KIOSK }, { "toilets", RIDE_TYPE_TOILETS },
{ "toilets", RIDE_TYPE_TOILETS }, { "ferris_wheel", RIDE_TYPE_FERRIS_WHEEL },
{ "ferris_wheel", RIDE_TYPE_FERRIS_WHEEL }, { "motion_simulator", RIDE_TYPE_MOTION_SIMULATOR },
{ "motion_simulator", RIDE_TYPE_MOTION_SIMULATOR }, { "3d_cinema", RIDE_TYPE_3D_CINEMA },
{ "3d_cinema", RIDE_TYPE_3D_CINEMA }, { "top_spin", RIDE_TYPE_TOP_SPIN },
{ "top_spin", RIDE_TYPE_TOP_SPIN }, { "space_rings", RIDE_TYPE_SPACE_RINGS },
{ "space_rings", RIDE_TYPE_SPACE_RINGS }, { "reverse_freefall_rc", RIDE_TYPE_REVERSE_FREEFALL_COASTER },
{ "reverse_freefall_rc", RIDE_TYPE_REVERSE_FREEFALL_COASTER }, { "lift", RIDE_TYPE_LIFT },
{ "lift", RIDE_TYPE_LIFT }, { "vertical_drop_rc", RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER },
{ "vertical_drop_rc", RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER }, { "cash_machine", RIDE_TYPE_CASH_MACHINE },
{ "cash_machine", RIDE_TYPE_CASH_MACHINE }, { "twist", RIDE_TYPE_TWIST },
{ "twist", RIDE_TYPE_TWIST }, { "haunted_house", RIDE_TYPE_HAUNTED_HOUSE },
{ "haunted_house", RIDE_TYPE_HAUNTED_HOUSE }, { "first_aid", RIDE_TYPE_FIRST_AID },
{ "first_aid", RIDE_TYPE_FIRST_AID }, { "circus", RIDE_TYPE_CIRCUS },
{ "circus", RIDE_TYPE_CIRCUS }, { "ghost_train", RIDE_TYPE_GHOST_TRAIN },
{ "ghost_train", RIDE_TYPE_GHOST_TRAIN }, { "twister_rc", RIDE_TYPE_TWISTER_ROLLER_COASTER },
{ "twister_rc", RIDE_TYPE_TWISTER_ROLLER_COASTER }, { "wooden_rc", RIDE_TYPE_WOODEN_ROLLER_COASTER },
{ "wooden_rc", RIDE_TYPE_WOODEN_ROLLER_COASTER }, { "side_friction_rc", RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER },
{ "side_friction_rc", RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER }, { "steel_wild_mouse", RIDE_TYPE_STEEL_WILD_MOUSE },
{ "steel_wild_mouse", RIDE_TYPE_STEEL_WILD_MOUSE }, { "multi_dimension_rc", RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER },
{ "multi_dimension_rc", RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER }, { "flying_rc", RIDE_TYPE_FLYING_ROLLER_COASTER },
{ "flying_rc", RIDE_TYPE_FLYING_ROLLER_COASTER }, { "virginia_reel", RIDE_TYPE_VIRGINIA_REEL },
{ "virginia_reel", RIDE_TYPE_VIRGINIA_REEL }, { "splash_boats", RIDE_TYPE_SPLASH_BOATS },
{ "splash_boats", RIDE_TYPE_SPLASH_BOATS }, { "mini_helicopters", RIDE_TYPE_MINI_HELICOPTERS },
{ "mini_helicopters", RIDE_TYPE_MINI_HELICOPTERS }, { "lay_down_rc", RIDE_TYPE_LAY_DOWN_ROLLER_COASTER },
{ "lay_down_rc", RIDE_TYPE_LAY_DOWN_ROLLER_COASTER }, { "suspended_monorail", RIDE_TYPE_SUSPENDED_MONORAIL },
{ "suspended_monorail", RIDE_TYPE_SUSPENDED_MONORAIL }, { "reverser_rc", RIDE_TYPE_REVERSER_ROLLER_COASTER },
{ "reverser_rc", RIDE_TYPE_REVERSER_ROLLER_COASTER }, { "heartline_twister_rc", RIDE_TYPE_HEARTLINE_TWISTER_COASTER },
{ "heartline_twister_rc", RIDE_TYPE_HEARTLINE_TWISTER_COASTER }, { "mini_golf", RIDE_TYPE_MINI_GOLF },
{ "mini_golf", RIDE_TYPE_MINI_GOLF }, { "giga_rc", RIDE_TYPE_GIGA_COASTER },
{ "giga_rc", RIDE_TYPE_GIGA_COASTER }, { "roto_drop", RIDE_TYPE_ROTO_DROP },
{ "roto_drop", RIDE_TYPE_ROTO_DROP }, { "flying_saucers", RIDE_TYPE_FLYING_SAUCERS },
{ "flying_saucers", RIDE_TYPE_FLYING_SAUCERS }, { "crooked_house", RIDE_TYPE_CROOKED_HOUSE },
{ "crooked_house", RIDE_TYPE_CROOKED_HOUSE }, { "monorail_cycles", RIDE_TYPE_MONORAIL_CYCLES },
{ "monorail_cycles", RIDE_TYPE_MONORAIL_CYCLES }, { "compact_inverted_rc", RIDE_TYPE_COMPACT_INVERTED_COASTER },
{ "compact_inverted_rc", RIDE_TYPE_COMPACT_INVERTED_COASTER }, { "water_coaster", RIDE_TYPE_WATER_COASTER },
{ "water_coaster", RIDE_TYPE_WATER_COASTER }, { "air_powered_vertical_rc", RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER },
{ "air_powered_vertical_rc", RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER }, { "inverted_hairpin_rc", RIDE_TYPE_INVERTED_HAIRPIN_COASTER },
{ "inverted_hairpin_rc", RIDE_TYPE_INVERTED_HAIRPIN_COASTER }, { "magic_carpet", RIDE_TYPE_MAGIC_CARPET },
{ "magic_carpet", RIDE_TYPE_MAGIC_CARPET }, { "submarine_ride", RIDE_TYPE_SUBMARINE_RIDE },
{ "submarine_ride", RIDE_TYPE_SUBMARINE_RIDE }, { "river_rafts", RIDE_TYPE_RIVER_RAFTS },
{ "river_rafts", RIDE_TYPE_RIVER_RAFTS }, { "enterprise", RIDE_TYPE_ENTERPRISE },
{ "enterprise", RIDE_TYPE_ENTERPRISE }, { "inverted_impulse_rc", RIDE_TYPE_INVERTED_IMPULSE_COASTER },
{ "inverted_impulse_rc", RIDE_TYPE_INVERTED_IMPULSE_COASTER }, { "mini_rc", RIDE_TYPE_MINI_ROLLER_COASTER },
{ "mini_rc", RIDE_TYPE_MINI_ROLLER_COASTER }, { "mine_ride", RIDE_TYPE_MINE_RIDE },
{ "mine_ride", RIDE_TYPE_MINE_RIDE }, { "lim_launched_rc", RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER },
{ "lim_launched_rc", RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER },
}; };
auto result = LookupTable.find(s); auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? return (result != LookupTable.end()) ? result->second : RIDE_TYPE_NULL;
result->second :
RIDE_TYPE_NULL;
} }
uint8_t RideObject::ParseRideCategory(const std::string &s) uint8_t RideObject::ParseRideCategory(const std::string& s)
{ {
static const std::unordered_map<std::string, uint8_t> LookupTable static const std::unordered_map<std::string, uint8_t> LookupTable{
{ { "transport", RIDE_CATEGORY_TRANSPORT },
{ "transport", RIDE_CATEGORY_TRANSPORT }, { "gentle", RIDE_CATEGORY_GENTLE },
{ "gentle", RIDE_CATEGORY_GENTLE }, { "rollercoaster", RIDE_CATEGORY_ROLLERCOASTER },
{ "rollercoaster", RIDE_CATEGORY_ROLLERCOASTER }, { "thrill", RIDE_CATEGORY_THRILL },
{ "thrill", RIDE_CATEGORY_THRILL }, { "water", RIDE_CATEGORY_WATER },
{ "water", RIDE_CATEGORY_WATER }, { "stall", RIDE_CATEGORY_SHOP },
{ "stall", RIDE_CATEGORY_SHOP },
}; };
auto result = LookupTable.find(s); auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? return (result != LookupTable.end()) ? result->second : RIDE_CATEGORY_TRANSPORT;
result->second :
RIDE_CATEGORY_TRANSPORT;
} }
uint8_t RideObject::ParseShopItem(const std::string &s) uint8_t RideObject::ParseShopItem(const std::string& s)
{ {
static const std::unordered_map<std::string, uint8_t> LookupTable static const std::unordered_map<std::string, uint8_t> LookupTable{
{ { "burger", SHOP_ITEM_BURGER },
{ "burger", SHOP_ITEM_BURGER }, { "chips", SHOP_ITEM_CHIPS },
{ "chips", SHOP_ITEM_CHIPS }, { "ice_cream", SHOP_ITEM_ICE_CREAM },
{ "ice_cream", SHOP_ITEM_ICE_CREAM }, { "candyfloss", SHOP_ITEM_CANDYFLOSS },
{ "candyfloss", SHOP_ITEM_CANDYFLOSS }, { "pizza", SHOP_ITEM_PIZZA },
{ "pizza", SHOP_ITEM_PIZZA }, { "popcorn", SHOP_ITEM_POPCORN },
{ "popcorn", SHOP_ITEM_POPCORN }, { "hot_dog", SHOP_ITEM_HOT_DOG },
{ "hot_dog", SHOP_ITEM_HOT_DOG }, { "tentacle", SHOP_ITEM_TENTACLE },
{ "tentacle", SHOP_ITEM_TENTACLE }, { "toffee_apple", SHOP_ITEM_TOFFEE_APPLE },
{ "toffee_apple", SHOP_ITEM_TOFFEE_APPLE }, { "doughnut", SHOP_ITEM_DOUGHNUT },
{ "doughnut", SHOP_ITEM_DOUGHNUT }, { "chicken", SHOP_ITEM_CHICKEN },
{ "chicken", SHOP_ITEM_CHICKEN }, { "pretzel", SHOP_ITEM_PRETZEL },
{ "pretzel", SHOP_ITEM_PRETZEL }, { "funnel_cake", SHOP_ITEM_FUNNEL_CAKE },
{ "funnel_cake", SHOP_ITEM_FUNNEL_CAKE }, { "beef_noodles", SHOP_ITEM_BEEF_NOODLES },
{ "beef_noodles", SHOP_ITEM_BEEF_NOODLES },
{ "fried_rice_noodles", SHOP_ITEM_FRIED_RICE_NOODLES }, { "fried_rice_noodles", SHOP_ITEM_FRIED_RICE_NOODLES },
{ "wonton_soup", SHOP_ITEM_WONTON_SOUP }, { "wonton_soup", SHOP_ITEM_WONTON_SOUP },
{ "meatball_soup", SHOP_ITEM_MEATBALL_SOUP }, { "meatball_soup", SHOP_ITEM_MEATBALL_SOUP },
{ "sub_sandwich", SHOP_ITEM_SUB_SANDWICH }, { "sub_sandwich", SHOP_ITEM_SUB_SANDWICH },
{ "cookie", SHOP_ITEM_COOKIE }, { "cookie", SHOP_ITEM_COOKIE },
{ "roast_sausage", SHOP_ITEM_ROAST_SAUSAGE }, { "roast_sausage", SHOP_ITEM_ROAST_SAUSAGE },
{ "drink", SHOP_ITEM_DRINK }, { "drink", SHOP_ITEM_DRINK },
{ "coffee", SHOP_ITEM_COFFEE }, { "coffee", SHOP_ITEM_COFFEE },
{ "lemonade", SHOP_ITEM_LEMONADE }, { "lemonade", SHOP_ITEM_LEMONADE },
{ "chocolate", SHOP_ITEM_CHOCOLATE }, { "chocolate", SHOP_ITEM_CHOCOLATE },
{ "iced_tea", SHOP_ITEM_ICED_TEA }, { "iced_tea", SHOP_ITEM_ICED_TEA },
{ "fruit_juice", SHOP_ITEM_FRUIT_JUICE }, { "fruit_juice", SHOP_ITEM_FRUIT_JUICE },
{ "soybean_milk", SHOP_ITEM_SOYBEAN_MILK }, { "soybean_milk", SHOP_ITEM_SOYBEAN_MILK },
{ "sujeonggwa", SHOP_ITEM_SUJEONGGWA }, { "sujeonggwa", SHOP_ITEM_SUJEONGGWA },
{ "balloon", SHOP_ITEM_BALLOON }, { "balloon", SHOP_ITEM_BALLOON },
{ "toy", SHOP_ITEM_TOY }, { "toy", SHOP_ITEM_TOY },
{ "map", SHOP_ITEM_MAP }, { "map", SHOP_ITEM_MAP },
{ "photo", SHOP_ITEM_PHOTO }, { "photo", SHOP_ITEM_PHOTO },
{ "umbrella", SHOP_ITEM_UMBRELLA }, { "umbrella", SHOP_ITEM_UMBRELLA },
{ "voucher", SHOP_ITEM_VOUCHER }, { "voucher", SHOP_ITEM_VOUCHER },
{ "hat", SHOP_ITEM_HAT }, { "hat", SHOP_ITEM_HAT },
{ "tshirt", SHOP_ITEM_TSHIRT }, { "tshirt", SHOP_ITEM_TSHIRT },
{ "sunglasses", SHOP_ITEM_SUNGLASSES }, { "sunglasses", SHOP_ITEM_SUNGLASSES },
}; };
auto result = LookupTable.find(s); auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? return (result != LookupTable.end()) ? result->second : SHOP_ITEM_NONE;
result->second :
SHOP_ITEM_NONE;
} }
colour_t RideObject::ParseColour(const std::string &s) colour_t RideObject::ParseColour(const std::string& s)
{ {
static const std::unordered_map<std::string, colour_t> LookupTable static const std::unordered_map<std::string, colour_t> LookupTable{
{
{ "black", COLOUR_BLACK }, { "black", COLOUR_BLACK },
{ "grey", COLOUR_GREY }, { "grey", COLOUR_GREY },
{ "white", COLOUR_WHITE }, { "white", COLOUR_WHITE },
@ -1130,7 +1129,5 @@ colour_t RideObject::ParseColour(const std::string &s)
{ "light_pink", COLOUR_LIGHT_PINK }, { "light_pink", COLOUR_LIGHT_PINK },
}; };
auto result = LookupTable.find(s); auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? return (result != LookupTable.end()) ? result->second : COLOUR_BLACK;
result->second :
COLOUR_BLACK;
} }

View File

@ -9,50 +9,57 @@
#pragma once #pragma once
#include <vector>
#include "../ride/Ride.h" #include "../ride/Ride.h"
#include "Object.h" #include "Object.h"
#include <vector>
class RideObject final : public Object class RideObject final : public Object
{ {
private: private:
rct_ride_entry _legacyType = {}; rct_ride_entry _legacyType = {};
vehicle_colour_preset_list _presetColours = {}; vehicle_colour_preset_list _presetColours = {};
std::vector<int8_t> _peepLoadingPositions[MAX_VEHICLES_PER_RIDE_ENTRY]; std::vector<int8_t> _peepLoadingPositions[MAX_VEHICLES_PER_RIDE_ENTRY];
std::vector<std::array<sLocationXY8, 3> > _peepLoadingWaypoints[MAX_VEHICLES_PER_RIDE_ENTRY]; std::vector<std::array<sLocationXY8, 3>> _peepLoadingWaypoints[MAX_VEHICLES_PER_RIDE_ENTRY];
public: public:
explicit RideObject(const rct_object_entry &entry) : Object(entry) { } explicit RideObject(const rct_object_entry& entry)
: Object(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
std::string GetDescription() const; std::string GetDescription() const;
std::string GetCapacity() const; std::string GetCapacity() const;
void SetRepositoryItem(ObjectRepositoryItem * item) const override; void SetRepositoryItem(ObjectRepositoryItem* item) const override;
private: private:
void ReadLegacyVehicle(IReadObjectContext * context, IStream * stream, rct_ride_entry_vehicle * vehicle); void ReadLegacyVehicle(IReadObjectContext* context, IStream* stream, rct_ride_entry_vehicle* vehicle);
void ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties); void ReadJsonVehicleInfo(IReadObjectContext* context, const json_t* properties);
std::vector<rct_ride_entry_vehicle> ReadJsonCars(const json_t * jCars); std::vector<rct_ride_entry_vehicle> ReadJsonCars(const json_t* jCars);
rct_ride_entry_vehicle ReadJsonCar(const json_t * jCar); rct_ride_entry_vehicle ReadJsonCar(const json_t* jCar);
vehicle_colour_preset_list ReadJsonCarColours(const json_t * jCarColours); vehicle_colour_preset_list ReadJsonCarColours(const json_t* jCarColours);
std::vector<vehicle_colour> ReadJsonColourConfiguration(const json_t * jColourConfig); std::vector<vehicle_colour> ReadJsonColourConfiguration(const json_t* jColourConfig);
static uint8_t CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry); static uint8_t CalculateNumVerticalFrames(const rct_ride_entry_vehicle* vehicleEntry);
static uint8_t CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * vehicleEntry); static uint8_t CalculateNumHorizontalFrames(const rct_ride_entry_vehicle* vehicleEntry);
static bool IsRideTypeShopOrFacility(uint8_t rideType); static bool IsRideTypeShopOrFacility(uint8_t rideType);
static uint8_t ParseRideType(const std::string &s); static uint8_t ParseRideType(const std::string& s);
static uint8_t ParseRideCategory(const std::string &s); static uint8_t ParseRideCategory(const std::string& s);
static uint8_t ParseShopItem(const std::string &s); static uint8_t ParseShopItem(const std::string& s);
static colour_t ParseColour(const std::string &s); static colour_t ParseColour(const std::string& s);
}; };

View File

@ -9,7 +9,8 @@
#pragma warning(disable : 4706) // assignment within conditional expression #pragma warning(disable : 4706) // assignment within conditional expression
#include <unordered_map> #include "SceneryGroupObject.h"
#include "../Context.h" #include "../Context.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../core/Memory.hpp" #include "../core/Memory.hpp"
@ -20,11 +21,12 @@
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
#include "ObjectManager.h" #include "ObjectManager.h"
#include "ObjectRepository.h" #include "ObjectRepository.h"
#include "SceneryGroupObject.h"
#include <unordered_map>
using namespace OpenRCT2; using namespace OpenRCT2;
void SceneryGroupObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void SceneryGroupObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
stream->Seek(0x80 * 2, STREAM_SEEK_CURRENT); stream->Seek(0x80 * 2, STREAM_SEEK_CURRENT);
@ -56,7 +58,7 @@ void SceneryGroupObject::Unload()
_legacyType.image = 0; _legacyType.image = 0;
} }
void SceneryGroupObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void SceneryGroupObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
int32_t x = width / 2; int32_t x = width / 2;
int32_t y = height / 2; int32_t y = height / 2;
@ -72,23 +74,37 @@ void SceneryGroupObject::UpdateEntryIndexes()
auto objectManager = context->GetObjectManager(); auto objectManager = context->GetObjectManager();
_legacyType.entry_count = 0; _legacyType.entry_count = 0;
for (const auto &objectEntry : _items) for (const auto& objectEntry : _items)
{ {
auto ori = objectRepository->FindObject(&objectEntry); auto ori = objectRepository->FindObject(&objectEntry);
if (ori == nullptr) continue; if (ori == nullptr)
if (ori->LoadedObject == nullptr) continue; continue;
if (ori->LoadedObject == nullptr)
continue;
uint16_t sceneryEntry = objectManager->GetLoadedObjectEntryIndex(ori->LoadedObject); uint16_t sceneryEntry = objectManager->GetLoadedObjectEntryIndex(ori->LoadedObject);
Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE); Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE);
auto objectType = ori->ObjectEntry.flags & 0x0F; auto objectType = ori->ObjectEntry.flags & 0x0F;
switch (objectType) { switch (objectType)
case OBJECT_TYPE_SMALL_SCENERY: break; {
case OBJECT_TYPE_PATH_BITS: sceneryEntry |= 0x100; break; case OBJECT_TYPE_SMALL_SCENERY:
case OBJECT_TYPE_WALLS: sceneryEntry |= 0x200; break; break;
case OBJECT_TYPE_LARGE_SCENERY: sceneryEntry |= 0x300; break; case OBJECT_TYPE_PATH_BITS:
case OBJECT_TYPE_BANNERS: sceneryEntry |= 0x400; break; sceneryEntry |= 0x100;
default: sceneryEntry = 0xFFFF; break; break;
case OBJECT_TYPE_WALLS:
sceneryEntry |= 0x200;
break;
case OBJECT_TYPE_LARGE_SCENERY:
sceneryEntry |= 0x300;
break;
case OBJECT_TYPE_BANNERS:
sceneryEntry |= 0x400;
break;
default:
sceneryEntry = 0xFFFF;
break;
} }
if (sceneryEntry != 0xFFFF) if (sceneryEntry != 0xFFFF)
{ {
@ -98,12 +114,12 @@ void SceneryGroupObject::UpdateEntryIndexes()
} }
} }
void SceneryGroupObject::SetRepositoryItem(ObjectRepositoryItem * item) const void SceneryGroupObject::SetRepositoryItem(ObjectRepositoryItem* item) const
{ {
item->SceneryGroupInfo.Entries = _items; item->SceneryGroupInfo.Entries = _items;
} }
std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream * stream) std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream* stream)
{ {
auto items = std::vector<rct_object_entry>(); auto items = std::vector<rct_object_entry>();
while (stream->ReadValue<uint8_t>() != 0xFF) while (stream->ReadValue<uint8_t>() != 0xFF)
@ -115,7 +131,7 @@ std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream * stream)
return items; return items;
} }
void SceneryGroupObject::ReadJson(IReadObjectContext * context, const json_t * root) void SceneryGroupObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.priority = json_integer_value(json_object_get(properties, "priority")); _legacyType.priority = json_integer_value(json_object_get(properties, "priority"));
@ -137,7 +153,7 @@ void SceneryGroupObject::ReadJson(IReadObjectContext * context, const json_t * r
ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
} }
uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostumes) uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t* jCostumes)
{ {
uint32_t costumes = 0; uint32_t costumes = 0;
auto szCostumes = ObjectJsonHelpers::GetJsonStringArray(jCostumes); auto szCostumes = ObjectJsonHelpers::GetJsonStringArray(jCostumes);
@ -152,27 +168,38 @@ uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostume
return costumes; return costumes;
} }
uint32_t SceneryGroupObject::ParseEntertainerCostume(const std::string &s) uint32_t SceneryGroupObject::ParseEntertainerCostume(const std::string& s)
{ {
if (s == "panda") return ENTERTAINER_COSTUME_PANDA; if (s == "panda")
if (s == "tiger") return ENTERTAINER_COSTUME_TIGER; return ENTERTAINER_COSTUME_PANDA;
if (s == "elephant") return ENTERTAINER_COSTUME_ELEPHANT; if (s == "tiger")
if (s == "roman") return ENTERTAINER_COSTUME_ROMAN; return ENTERTAINER_COSTUME_TIGER;
if (s == "gorilla") return ENTERTAINER_COSTUME_GORILLA; if (s == "elephant")
if (s == "snowman") return ENTERTAINER_COSTUME_SNOWMAN; return ENTERTAINER_COSTUME_ELEPHANT;
if (s == "knight") return ENTERTAINER_COSTUME_KNIGHT; if (s == "roman")
if (s == "astronaut") return ENTERTAINER_COSTUME_ASTRONAUT; return ENTERTAINER_COSTUME_ROMAN;
if (s == "bandit") return ENTERTAINER_COSTUME_BANDIT; if (s == "gorilla")
if (s == "sheriff") return ENTERTAINER_COSTUME_SHERIFF; return ENTERTAINER_COSTUME_GORILLA;
if (s == "pirate") return ENTERTAINER_COSTUME_PIRATE; if (s == "snowman")
return ENTERTAINER_COSTUME_SNOWMAN;
if (s == "knight")
return ENTERTAINER_COSTUME_KNIGHT;
if (s == "astronaut")
return ENTERTAINER_COSTUME_ASTRONAUT;
if (s == "bandit")
return ENTERTAINER_COSTUME_BANDIT;
if (s == "sheriff")
return ENTERTAINER_COSTUME_SHERIFF;
if (s == "pirate")
return ENTERTAINER_COSTUME_PIRATE;
return ENTERTAINER_COSTUME_PANDA; return ENTERTAINER_COSTUME_PANDA;
} }
std::vector<rct_object_entry> SceneryGroupObject::ReadJsonEntries(const json_t * jEntries) std::vector<rct_object_entry> SceneryGroupObject::ReadJsonEntries(const json_t* jEntries)
{ {
std::vector<rct_object_entry> entries; std::vector<rct_object_entry> entries;
size_t index; size_t index;
json_t * jEntry; json_t* jEntry;
json_array_foreach(jEntries, index, jEntry) json_array_foreach(jEntries, index, jEntry)
{ {
auto entryId = json_string_value(jEntry); auto entryId = json_string_value(jEntry);

View File

@ -9,36 +9,43 @@
#pragma once #pragma once
#include <vector>
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "Object.h" #include "Object.h"
#include <vector>
struct ObjectRepositoryItem; struct ObjectRepositoryItem;
class SceneryGroupObject final : public Object class SceneryGroupObject final : public Object
{ {
private: private:
rct_scenery_group_entry _legacyType = {}; rct_scenery_group_entry _legacyType = {};
std::vector<rct_object_entry> _items; std::vector<rct_object_entry> _items;
public: public:
explicit SceneryGroupObject(const rct_object_entry &entry) : Object(entry) { } explicit SceneryGroupObject(const rct_object_entry& entry)
: Object(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
void ReadJson(IReadObjectContext * context, const json_t * root) override; {
return &_legacyType;
}
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void UpdateEntryIndexes(); void UpdateEntryIndexes();
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
void SetRepositoryItem(ObjectRepositoryItem * item) const override; void SetRepositoryItem(ObjectRepositoryItem* item) const override;
private: private:
static std::vector<rct_object_entry> ReadItems(IStream * stream); static std::vector<rct_object_entry> ReadItems(IStream* stream);
static uint32_t ReadJsonEntertainerCostumes(const json_t * jCostumes); static uint32_t ReadJsonEntertainerCostumes(const json_t* jCostumes);
static uint32_t ParseEntertainerCostume(const std::string &s); static uint32_t ParseEntertainerCostume(const std::string& s);
static std::vector<rct_object_entry> ReadJsonEntries(const json_t * jEntries); static std::vector<rct_object_entry> ReadJsonEntries(const json_t* jEntries);
}; };

View File

@ -7,10 +7,11 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "ObjectJsonHelpers.h"
#include "SceneryObject.h" #include "SceneryObject.h"
void SceneryObject::SetPrimarySceneryGroup(const std::string &s) #include "ObjectJsonHelpers.h"
void SceneryObject::SetPrimarySceneryGroup(const std::string& s)
{ {
if (!s.empty()) if (!s.empty())
{ {

View File

@ -9,21 +9,31 @@
#pragma once #pragma once
#include <string>
#include "Object.h" #include "Object.h"
#include <string>
class SceneryObject : public Object class SceneryObject : public Object
{ {
private: private:
rct_object_entry _primarySceneryGroupEntry = { }; rct_object_entry _primarySceneryGroupEntry = {};
public: public:
explicit SceneryObject(const rct_object_entry &entry) : Object(entry) { } explicit SceneryObject(const rct_object_entry& entry)
: Object(entry)
{
}
virtual ~SceneryObject() = default; virtual ~SceneryObject() = default;
const rct_object_entry * GetPrimarySceneryGroup() { return &_primarySceneryGroupEntry; } const rct_object_entry* GetPrimarySceneryGroup()
{
return &_primarySceneryGroupEntry;
}
protected: protected:
void SetPrimarySceneryGroup(const rct_object_entry * entry) { _primarySceneryGroupEntry = *entry; } void SetPrimarySceneryGroup(const rct_object_entry* entry)
void SetPrimarySceneryGroup(const std::string &s); {
_primarySceneryGroupEntry = *entry;
}
void SetPrimarySceneryGroup(const std::string& s);
}; };

View File

@ -9,6 +9,8 @@
#pragma warning(disable : 4706) // assignment within conditional expression #pragma warning(disable : 4706) // assignment within conditional expression
#include "SmallSceneryObject.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../core/Math.hpp" #include "../core/Math.hpp"
#include "../core/Memory.hpp" #include "../core/Memory.hpp"
@ -18,10 +20,9 @@
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "../world/SmallScenery.h" #include "../world/SmallScenery.h"
#include "SmallSceneryObject.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void SmallSceneryObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.small_scenery.flags = stream->ReadValue<uint32_t>(); _legacyType.small_scenery.flags = stream->ReadValue<uint32_t>();
@ -88,7 +89,7 @@ void SmallSceneryObject::Unload()
_legacyType.image = 0; _legacyType.image = 0;
} }
void SmallSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void SmallSceneryObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
uint32_t imageId = _legacyType.image; uint32_t imageId = _legacyType.image;
if (scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR)) if (scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
@ -104,8 +105,8 @@ void SmallSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int
int32_t y = (height / 2) + (_legacyType.small_scenery.height / 2); int32_t y = (height / 2) + (_legacyType.small_scenery.height / 2);
y = std::min(y, height - 16); y = std::min(y, height - 16);
if ((scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_FULL_TILE)) && if ((scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_FULL_TILE))
(scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_VOFFSET_CENTRE))) && (scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_VOFFSET_CENTRE)))
{ {
y -= 12; y -= 12;
} }
@ -133,7 +134,7 @@ void SmallSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int
} }
} }
std::vector<uint8_t> SmallSceneryObject::ReadFrameOffsets(IStream * stream) std::vector<uint8_t> SmallSceneryObject::ReadFrameOffsets(IStream* stream)
{ {
uint8_t frameOffset; uint8_t frameOffset;
auto data = std::vector<uint8_t>(); auto data = std::vector<uint8_t>();
@ -228,12 +229,13 @@ rct_object_entry SmallSceneryObject::GetScgAbstrHeader()
return Object::CreateHeader("SCGABSTR", 207140231, 932253451); return Object::CreateHeader("SCGABSTR", 207140231, 932253451);
} }
void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * root) void SmallSceneryObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.small_scenery.height = json_integer_value(json_object_get(properties, "height")); _legacyType.small_scenery.height = json_integer_value(json_object_get(properties, "height"));
_legacyType.small_scenery.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN); _legacyType.small_scenery.tool_id
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN);
_legacyType.small_scenery.price = json_integer_value(json_object_get(properties, "price")); _legacyType.small_scenery.price = json_integer_value(json_object_get(properties, "price"));
_legacyType.small_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice")); _legacyType.small_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
_legacyType.small_scenery.animation_delay = json_integer_value(json_object_get(properties, "animationDelay")); _legacyType.small_scenery.animation_delay = json_integer_value(json_object_get(properties, "animationDelay"));
@ -241,30 +243,31 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r
_legacyType.small_scenery.num_frames = json_integer_value(json_object_get(properties, "numFrames")); _legacyType.small_scenery.num_frames = json_integer_value(json_object_get(properties, "numFrames"));
// Flags // Flags
_legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags<uint32_t>(properties, { _legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags<uint32_t>(
{ "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE }, properties,
{ "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE }, { { "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE },
{ "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE }, { "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE },
{ "isAnimated", SMALL_SCENERY_FLAG_ANIMATED }, { "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE },
{ "canWither", SMALL_SCENERY_FLAG_CAN_WITHER }, { "isAnimated", SMALL_SCENERY_FLAG_ANIMATED },
{ "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED }, { "canWither", SMALL_SCENERY_FLAG_CAN_WITHER },
{ "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG }, { "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED },
{ "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS }, { "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG },
{ "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR }, { "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS },
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 }, { "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 }, { "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 },
{ "isClock", SMALL_SCENERY_FLAG_IS_CLOCK }, { "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 },
{ "SMALL_SCENERY_FLAG_SWAMP_GOO", SMALL_SCENERY_FLAG_SWAMP_GOO }, { "isClock", SMALL_SCENERY_FLAG_IS_CLOCK },
{ "SMALL_SCENERY_FLAG17", SMALL_SCENERY_FLAG17 }, { "SMALL_SCENERY_FLAG_SWAMP_GOO", SMALL_SCENERY_FLAG_SWAMP_GOO },
{ "isStackable", SMALL_SCENERY_FLAG_STACKABLE }, { "SMALL_SCENERY_FLAG17", SMALL_SCENERY_FLAG17 },
{ "prohibitWalls", SMALL_SCENERY_FLAG_NO_WALLS }, { "isStackable", SMALL_SCENERY_FLAG_STACKABLE },
{ "hasSecondaryColour", SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR }, { "prohibitWalls", SMALL_SCENERY_FLAG_NO_WALLS },
{ "hasNoSupports", SMALL_SCENERY_FLAG_NO_SUPPORTS }, { "hasSecondaryColour", SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
{ "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED }, { "hasNoSupports", SMALL_SCENERY_FLAG_NO_SUPPORTS },
{ "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG }, { "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED },
{ "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP }, { "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG },
{ "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS }, { "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP },
{ "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } }); { "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS },
{ "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } });
// Determine shape flags from a shape string // Determine shape flags from a shape string
auto shape = ObjectJsonHelpers::GetString(properties, "shape"); auto shape = ObjectJsonHelpers::GetString(properties, "shape");
@ -305,11 +308,11 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r
ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
} }
std::vector<uint8_t> SmallSceneryObject::ReadJsonFrameOffsets(const json_t * jFrameOffsets) std::vector<uint8_t> SmallSceneryObject::ReadJsonFrameOffsets(const json_t* jFrameOffsets)
{ {
std::vector<uint8_t> offsets; std::vector<uint8_t> offsets;
size_t index; size_t index;
const json_t * jOffset; const json_t* jOffset;
json_array_foreach(jFrameOffsets, index, jOffset) json_array_foreach(jFrameOffsets, index, jOffset)
{ {
offsets.push_back(json_integer_value(jOffset)); offsets.push_back(json_integer_value(jOffset));

View File

@ -9,31 +9,38 @@
#pragma once #pragma once
#include <vector>
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "SceneryObject.h" #include "SceneryObject.h"
#include <vector>
class SmallSceneryObject final : public SceneryObject class SmallSceneryObject final : public SceneryObject
{ {
private: private:
rct_scenery_entry _legacyType = {}; rct_scenery_entry _legacyType = {};
std::vector<uint8_t> _frameOffsets; std::vector<uint8_t> _frameOffsets;
public: public:
explicit SmallSceneryObject(const rct_object_entry &entry) : SceneryObject(entry) { } explicit SmallSceneryObject(const rct_object_entry& entry)
: SceneryObject(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
private: private:
static std::vector<uint8_t> ReadFrameOffsets(IStream * stream); static std::vector<uint8_t> ReadFrameOffsets(IStream* stream);
static std::vector<uint8_t> ReadJsonFrameOffsets(const json_t * jFrameOffsets); static std::vector<uint8_t> ReadJsonFrameOffsets(const json_t* jFrameOffsets);
void PerformFixes(); void PerformFixes();
rct_object_entry GetScgPiratHeader(); rct_object_entry GetScgPiratHeader();
rct_object_entry GetScgMineHeader(); rct_object_entry GetScgMineHeader();

View File

@ -7,12 +7,12 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "../core/IStream.hpp"
#include "StexObject.h" #include "StexObject.h"
#include "../core/IStream.hpp"
#include "../localisation/Localisation.h" #include "../localisation/Localisation.h"
void StexObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void StexObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.var_06 = stream->ReadValue<uint8_t>(); _legacyType.var_06 = stream->ReadValue<uint8_t>();
@ -42,7 +42,7 @@ void StexObject::Unload()
_legacyType.details = 0; _legacyType.details = 0;
} }
void StexObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void StexObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
// Write (no image) // Write (no image)
int32_t x = width / 2; int32_t x = width / 2;

View File

@ -9,9 +9,8 @@
#pragma once #pragma once
#include "Object.h"
#include "../scenario/Scenario.h" #include "../scenario/Scenario.h"
#include "Object.h"
class StexObject final : public Object class StexObject final : public Object
{ {
@ -19,15 +18,21 @@ private:
rct_stex_entry _legacyType = {}; rct_stex_entry _legacyType = {};
public: public:
explicit StexObject(const rct_object_entry &entry) : Object(entry) { } explicit StexObject(const rct_object_entry& entry)
: Object(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
std::string GetName() const override; std::string GetName() const override;

View File

@ -7,17 +7,18 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <algorithm> #include "StringTable.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../localisation/LanguagePack.h" #include "../localisation/LanguagePack.h"
#include "../localisation/LocalisationService.h" #include "../localisation/LocalisationService.h"
#include "Object.h" #include "Object.h"
#include "StringTable.h"
static constexpr const uint8_t RCT2ToOpenRCT2LanguageId[] = #include <algorithm>
{
static constexpr const uint8_t RCT2ToOpenRCT2LanguageId[] = {
LANGUAGE_ENGLISH_UK, LANGUAGE_ENGLISH_UK,
LANGUAGE_ENGLISH_US, LANGUAGE_ENGLISH_US,
LANGUAGE_FRENCH, LANGUAGE_FRENCH,
@ -34,7 +35,7 @@ static constexpr const uint8_t RCT2ToOpenRCT2LanguageId[] =
LANGUAGE_PORTUGUESE_BR, LANGUAGE_PORTUGUESE_BR,
}; };
static bool StringIsBlank(const utf8 * str) static bool StringIsBlank(const utf8* str)
{ {
for (auto ch = str; *ch != '\0'; ch++) for (auto ch = str; *ch != '\0'; ch++)
{ {
@ -46,18 +47,16 @@ static bool StringIsBlank(const utf8 * str)
return true; return true;
} }
void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8_t id) void StringTable::Read(IReadObjectContext* context, IStream* stream, uint8_t id)
{ {
try try
{ {
RCT2LanguageId rct2LanguageId; RCT2LanguageId rct2LanguageId;
while ((rct2LanguageId = (RCT2LanguageId)stream->ReadValue<uint8_t>()) != RCT2_LANGUAGE_ID_END) while ((rct2LanguageId = (RCT2LanguageId)stream->ReadValue<uint8_t>()) != RCT2_LANGUAGE_ID_END)
{ {
uint8_t languageId = uint8_t languageId = (rct2LanguageId <= RCT2_LANGUAGE_ID_PORTUGUESE) ? RCT2ToOpenRCT2LanguageId[rct2LanguageId]
(rct2LanguageId <= RCT2_LANGUAGE_ID_PORTUGUESE) ? : LANGUAGE_UNDEFINED;
RCT2ToOpenRCT2LanguageId[rct2LanguageId] : StringTableEntry entry{};
LANGUAGE_UNDEFINED;
StringTableEntry entry { };
entry.Id = id; entry.Id = id;
entry.LanguageId = languageId; entry.LanguageId = languageId;
@ -74,7 +73,7 @@ void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8_t i
_strings.push_back(entry); _strings.push_back(entry);
} }
} }
catch (const std::exception &) catch (const std::exception&)
{ {
context->LogError(OBJECT_ERROR_BAD_STRING_TABLE, "Bad string table."); context->LogError(OBJECT_ERROR_BAD_STRING_TABLE, "Bad string table.");
throw; throw;
@ -84,7 +83,7 @@ void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8_t i
std::string StringTable::GetString(uint8_t id) const std::string StringTable::GetString(uint8_t id) const
{ {
for (auto &string : _strings) for (auto& string : _strings)
{ {
if (string.Id == id) if (string.Id == id)
{ {
@ -96,7 +95,7 @@ std::string StringTable::GetString(uint8_t id) const
std::string StringTable::GetString(uint8_t language, uint8_t id) const std::string StringTable::GetString(uint8_t language, uint8_t id) const
{ {
for (auto &string : _strings) for (auto& string : _strings)
{ {
if (string.LanguageId == language && string.Id == id) if (string.LanguageId == language && string.Id == id)
{ {
@ -106,7 +105,7 @@ std::string StringTable::GetString(uint8_t language, uint8_t id) const
return std::string(); return std::string();
} }
void StringTable::SetString(uint8_t id, uint8_t language, const std::string &text) void StringTable::SetString(uint8_t id, uint8_t language, const std::string& text)
{ {
StringTableEntry entry; StringTableEntry entry;
entry.Id = id; entry.Id = id;
@ -118,8 +117,7 @@ void StringTable::SetString(uint8_t id, uint8_t language, const std::string &tex
void StringTable::Sort() void StringTable::Sort()
{ {
auto targetLanguage = LocalisationService_GetCurrentLanguage(); auto targetLanguage = LocalisationService_GetCurrentLanguage();
std::sort(_strings.begin(), _strings.end(), [targetLanguage](const StringTableEntry &a, const StringTableEntry &b) -> bool std::sort(_strings.begin(), _strings.end(), [targetLanguage](const StringTableEntry& a, const StringTableEntry& b) -> bool {
{
if (a.Id == b.Id) if (a.Id == b.Id)
{ {
if (a.LanguageId == b.LanguageId) if (a.LanguageId == b.LanguageId)

View File

@ -9,11 +9,12 @@
#pragma once #pragma once
#include <string>
#include <vector>
#include "../common.h" #include "../common.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include <string>
#include <vector>
interface IReadObjectContext; interface IReadObjectContext;
interface IStream; interface IStream;
@ -31,8 +32,8 @@ enum OBJ_STRING_ID : uint8_t
struct StringTableEntry struct StringTableEntry
{ {
uint8_t Id = OBJ_STRING_ID_UNKNOWN; uint8_t Id = OBJ_STRING_ID_UNKNOWN;
uint8_t LanguageId = LANGUAGE_UNDEFINED; uint8_t LanguageId = LANGUAGE_UNDEFINED;
std::string Text; std::string Text;
}; };
@ -43,12 +44,12 @@ private:
public: public:
StringTable() = default; StringTable() = default;
StringTable(const StringTable &) = delete; StringTable(const StringTable&) = delete;
StringTable & operator=(const StringTable &) = delete; StringTable& operator=(const StringTable&) = delete;
void Read(IReadObjectContext * context, IStream * stream, uint8_t id); void Read(IReadObjectContext* context, IStream* stream, uint8_t id);
void Sort(); void Sort();
std::string GetString(uint8_t id) const; std::string GetString(uint8_t id) const;
std::string GetString(uint8_t language, uint8_t id) const; std::string GetString(uint8_t language, uint8_t id) const;
void SetString(uint8_t id, uint8_t language, const std::string &text); void SetString(uint8_t id, uint8_t language, const std::string& text);
}; };

View File

@ -7,14 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "WallObject.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../interface/Cursors.h" #include "../interface/Cursors.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
#include "WallObject.h"
void WallObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void WallObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(6, STREAM_SEEK_CURRENT); stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.wall.tool_id = stream->ReadValue<uint8_t>(); _legacyType.wall.tool_id = stream->ReadValue<uint8_t>();
@ -55,7 +56,7 @@ void WallObject::Unload()
_legacyType.image = 0; _legacyType.image = 0;
} }
void WallObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void WallObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
int32_t x = width / 2; int32_t x = width / 2;
int32_t y = height / 2; int32_t y = height / 2;
@ -83,33 +84,32 @@ void WallObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t hei
} }
} }
void WallObject::ReadJson(IReadObjectContext * context, const json_t * root) void WallObject::ReadJson(IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.wall.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_FENCE_DOWN); _legacyType.wall.tool_id
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_FENCE_DOWN);
_legacyType.wall.height = json_integer_value(json_object_get(properties, "height")); _legacyType.wall.height = json_integer_value(json_object_get(properties, "height"));
_legacyType.wall.price = json_integer_value(json_object_get(properties, "price")); _legacyType.wall.price = json_integer_value(json_object_get(properties, "price"));
auto jScrollingMode = json_object_get(properties, "scrollingMode"); auto jScrollingMode = json_object_get(properties, "scrollingMode");
_legacyType.wall.scrolling_mode = jScrollingMode != nullptr ? _legacyType.wall.scrolling_mode = jScrollingMode != nullptr ? json_integer_value(jScrollingMode) : -1;
json_integer_value(jScrollingMode) :
-1;
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
// Flags // Flags
_legacyType.wall.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, { _legacyType.wall.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
{ "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR }, properties,
{ "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR }, { { "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR },
{ "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR }, { "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR },
{ "hasGlass", WALL_SCENERY_HAS_GLASS }, { "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR },
{ "isBanner", WALL_SCENERY_IS_BANNER }, { "hasGlass", WALL_SCENERY_HAS_GLASS },
{ "isDoor", WALL_SCENERY_IS_DOOR }, { "isBanner", WALL_SCENERY_IS_BANNER },
{ "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION }}); { "isDoor", WALL_SCENERY_IS_DOOR },
_legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags<uint8_t>(properties, { { "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION } });
{ "isOpaque", WALL_SCENERY_2_IS_OPAQUE }, _legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags<uint8_t>(
{ "isAnimated", WALL_SCENERY_2_ANIMATED }}); properties, { { "isOpaque", WALL_SCENERY_2_IS_OPAQUE }, { "isAnimated", WALL_SCENERY_2_ANIMATED } });
// HACK To avoid 'negated' properties in JSON, handle this separately until // HACK To avoid 'negated' properties in JSON, handle this separately until
// flag is inverted in this code base. // flag is inverted in this code base.
@ -122,8 +122,8 @@ void WallObject::ReadJson(IReadObjectContext * context, const json_t * root)
// JSON and handle this on load. We should change code base in future to reflect the JSON. // JSON and handle this on load. We should change code base in future to reflect the JSON.
if (!(_legacyType.wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)) if (!(_legacyType.wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR))
{ {
if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) || if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR)
(_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR)) || (_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR))
{ {
_legacyType.wall.flags2 |= WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR; _legacyType.wall.flags2 |= WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR;
} }

View File

@ -9,24 +9,29 @@
#pragma once #pragma once
#include "SceneryObject.h"
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "SceneryObject.h"
class WallObject final : public SceneryObject class WallObject final : public SceneryObject
{ {
private: private:
rct_scenery_entry _legacyType = {}; rct_scenery_entry _legacyType = {};
public: public:
explicit WallObject(const rct_object_entry &entry) : SceneryObject(entry) { } explicit WallObject(const rct_object_entry& entry)
: SceneryObject(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
}; };

View File

@ -9,15 +9,17 @@
#pragma warning(disable : 4706) // assignment within conditional expression #pragma warning(disable : 4706) // assignment within conditional expression
#include <memory> #include "WaterObject.h"
#include "../OpenRCT2.h"
#include "../core/IStream.hpp" #include "../core/IStream.hpp"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../localisation/StringIds.h" #include "../localisation/StringIds.h"
#include "../OpenRCT2.h"
#include "ObjectJsonHelpers.h" #include "ObjectJsonHelpers.h"
#include "WaterObject.h"
void WaterObject::ReadLegacy(IReadObjectContext * context, IStream * stream) #include <memory>
void WaterObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{ {
stream->Seek(14, STREAM_SEEK_CURRENT); stream->Seek(14, STREAM_SEEK_CURRENT);
_legacyType.flags = stream->ReadValue<uint16_t>(); _legacyType.flags = stream->ReadValue<uint16_t>();
@ -45,7 +47,7 @@ void WaterObject::Unload()
_legacyType.string_idx = 0; _legacyType.string_idx = 0;
} }
void WaterObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const void WaterObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{ {
// Write (no image) // Write (no image)
int32_t x = width / 2; int32_t x = width / 2;
@ -56,22 +58,13 @@ void WaterObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t he
void WaterObject::ReadJson([[maybe_unused]] IReadObjectContext* context, const json_t* root) void WaterObject::ReadJson([[maybe_unused]] IReadObjectContext* context, const json_t* root)
{ {
auto properties = json_object_get(root, "properties"); auto properties = json_object_get(root, "properties");
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, { _legacyType.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, { { "allowDucks", WATER_FLAGS_ALLOW_DUCKS } });
{ "allowDucks", WATER_FLAGS_ALLOW_DUCKS }});
ObjectJsonHelpers::LoadStrings(root, GetStringTable()); ObjectJsonHelpers::LoadStrings(root, GetStringTable());
// Images which are actually palette data // Images which are actually palette data
static const char * paletteNames[] = static const char* paletteNames[]
{ = { "general", "waves-0", "waves-1", "waves-2", "sparkles-0", "sparkles-1", "sparkles-2" };
"general",
"waves-0",
"waves-1",
"waves-2",
"sparkles-0",
"sparkles-1",
"sparkles-2"
};
for (auto paletteName : paletteNames) for (auto paletteName : paletteNames)
{ {
auto jPalettes = json_object_get(properties, "palettes"); auto jPalettes = json_object_get(properties, "palettes");
@ -86,7 +79,7 @@ void WaterObject::ReadJson([[maybe_unused]] IReadObjectContext* context, const j
} }
} }
void WaterObject::ReadJsonPalette(const json_t * jPalette) void WaterObject::ReadJsonPalette(const json_t* jPalette)
{ {
auto paletteStartIndex = json_integer_value(json_object_get(jPalette, "index")); auto paletteStartIndex = json_integer_value(json_object_get(jPalette, "index"));
auto jColours = json_object_get(jPalette, "colours"); auto jColours = json_object_get(jPalette, "colours");
@ -96,7 +89,7 @@ void WaterObject::ReadJsonPalette(const json_t * jPalette)
size_t dataIndex = 0; size_t dataIndex = 0;
size_t index; size_t index;
const json_t * jColour; const json_t* jColour;
json_array_foreach(jColours, index, jColour) json_array_foreach(jColours, index, jColour)
{ {
auto szColour = json_string_value(jColour); auto szColour = json_string_value(jColour);
@ -116,11 +109,11 @@ void WaterObject::ReadJsonPalette(const json_t * jPalette)
g1.x_offset = (int16_t)paletteStartIndex; g1.x_offset = (int16_t)paletteStartIndex;
g1.flags = G1_FLAG_PALETTE; g1.flags = G1_FLAG_PALETTE;
auto &imageTable = GetImageTable(); auto& imageTable = GetImageTable();
imageTable.AddImage(&g1); imageTable.AddImage(&g1);
} }
uint32_t WaterObject::ParseColour(const std::string &s) const uint32_t WaterObject::ParseColour(const std::string& s) const
{ {
uint8_t r = 0; uint8_t r = 0;
uint8_t g = 0; uint8_t g = 0;

View File

@ -9,28 +9,35 @@
#pragma once #pragma once
#include <tuple>
#include "../world/Water.h" #include "../world/Water.h"
#include "Object.h" #include "Object.h"
#include <tuple>
class WaterObject final : public Object class WaterObject final : public Object
{ {
private: private:
rct_water_type _legacyType = {}; rct_water_type _legacyType = {};
public: public:
explicit WaterObject(const rct_object_entry &entry) : Object(entry) { } explicit WaterObject(const rct_object_entry& entry)
: Object(entry)
{
}
void * GetLegacyData() override { return &_legacyType; } void* GetLegacyData() override
{
return &_legacyType;
}
void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadJson(IReadObjectContext* context, const json_t* root) override;
void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void Load() override; void Load() override;
void Unload() override; void Unload() override;
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
private: private:
void ReadJsonPalette(const json_t * jPalette); void ReadJsonPalette(const json_t* jPalette);
uint32_t ParseColour(const std::string &s) const; uint32_t ParseColour(const std::string& s) const;
}; };