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.
*****************************************************************************/
#include "BannerObject.h"
#include "../core/IStream.hpp"
#include "../drawing/Drawing.h"
#include "../localisation/Language.h"
#include "../object/Object.h"
#include "../object/ObjectRepository.h"
#include "BannerObject.h"
#include "ObjectJsonHelpers.h"
#include "ObjectList.h"
void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
void BannerObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{
stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.banner.scrolling_mode = stream->ReadValue<uint8_t>();
@ -47,9 +48,9 @@ void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
if (item != nullptr)
{
auto objectEntry = &item->ObjectEntry;
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_CUSTOM)
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_CUSTOM)
{
auto scgPathX = Object::GetScgPathXHeader();
SetPrimarySceneryGroup(&scgPathX);
@ -73,7 +74,7 @@ void BannerObject::Unload()
_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 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);
}
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");
_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.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
{ "hasPrimaryColour", BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR }});
_legacyType.banner.flags
= ObjectJsonHelpers::GetFlags<uint8_t>(properties, { { "hasPrimaryColour", BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR } });
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));

View File

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

View File

@ -7,14 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "EntranceObject.h"
#include "../core/IStream.hpp"
#include "../core/String.hpp"
#include "../drawing/Drawing.h"
#include "../localisation/Localisation.h"
#include "EntranceObject.h"
#include "ObjectJsonHelpers.h"
void EntranceObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
void EntranceObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{
stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.scrolling_mode = stream->ReadValue<uint8_t>();
@ -48,18 +49,18 @@ void EntranceObject::Unload()
_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 y = height / 2;
uint32_t imageId = _legacyType.image_id;
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);
}
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");
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));

View File

@ -9,9 +9,8 @@
#pragma once
#include "Object.h"
#include "../world/Entrance.h"
#include "Object.h"
class EntranceObject final : public Object
{
@ -19,14 +18,20 @@ private:
rct_entrance_type _legacyType = {};
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 ReadJson(IReadObjectContext * context, const json_t * root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() 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.
*****************************************************************************/
#include <unordered_map>
#include "FootpathItemObject.h"
#include "../core/IStream.hpp"
#include "../drawing/Drawing.h"
#include "../interface/Cursors.h"
#include "../localisation/Localisation.h"
#include "../object/Object.h"
#include "../object/ObjectRepository.h"
#include "ObjectList.h"
#include "FootpathItemObject.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);
_legacyType.path_bit.flags = stream->ReadValue<uint16_t>();
@ -50,9 +52,8 @@ void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stre
if (item != nullptr)
{
auto sourceGame = object_entry_get_source_game(&item->ObjectEntry);
if (sourceGame == OBJECT_SOURCE_WACKY_WORLDS ||
sourceGame == OBJECT_SOURCE_TIME_TWISTER ||
sourceGame == OBJECT_SOURCE_CUSTOM)
if (sourceGame == OBJECT_SOURCE_WACKY_WORLDS || sourceGame == OBJECT_SOURCE_TIME_TWISTER
|| sourceGame == OBJECT_SOURCE_CUSTOM)
{
auto scgPathX = Object::GetScgPathXHeader();
SetPrimarySceneryGroup(&scgPathX);
@ -78,40 +79,46 @@ void FootpathItemObject::Unload()
_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 y = height / 2;
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 == "bin") 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;
if (s == "lamp")
return PATH_BIT_DRAW_TYPE_LIGHTS;
if (s == "bin")
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;
}
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");
_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"));
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
// Flags
_legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, {
{ "isBin", PATH_BIT_FLAG_IS_BIN },
{ "isBench", PATH_BIT_FLAG_IS_BENCH },
{ "isBreakable", PATH_BIT_FLAG_BREAKABLE },
{ "isLamp", PATH_BIT_FLAG_LAMP },
{ "isJumpingFountainWater", PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER },
{ "isJumpingFountainSnow", PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW },
{ "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }});
_legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags<uint16_t>(
properties,
{ { "isBin", PATH_BIT_FLAG_IS_BIN },
{ "isBench", PATH_BIT_FLAG_IS_BENCH },
{ "isBreakable", PATH_BIT_FLAG_BREAKABLE },
{ "isLamp", PATH_BIT_FLAG_LAMP },
{ "isJumpingFountainWater", PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER },
{ "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
// flags are inverted in this code base.

View File

@ -9,24 +9,29 @@
#pragma once
#include "SceneryObject.h"
#include "../world/Scenery.h"
#include "SceneryObject.h"
class FootpathItemObject final : public SceneryObject
{
private:
rct_scenery_entry _legacyType = {};
rct_scenery_entry _legacyType = {};
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 ReadJson(IReadObjectContext * context, const json_t * root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() 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.
*****************************************************************************/
#include "FootpathObject.h"
#include "../core/IStream.hpp"
#include "../drawing/Drawing.h"
#include "../localisation/Language.h"
#include "../world/Footpath.h"
#include "FootpathObject.h"
#include "ObjectJsonHelpers.h"
void FootpathObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
void FootpathObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{
stream->Seek(10, STREAM_SEEK_CURRENT);
_legacyType.support_type = stream->ReadValue<uint8_t>();
@ -49,7 +50,7 @@ void FootpathObject::Unload()
_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 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);
}
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;
else /* if (s == "box") */ return FOOTPATH_ENTRY_SUPPORT_TYPE_BOX;
if (s == "pole")
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");
_legacyType.support_type = ParseSupportType(ObjectJsonHelpers::GetString(json_object_get(properties, "supportType")));
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
// Flags
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
{ "hasSupportImages", FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE },
{ "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE },
{ "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } });
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
properties,
{ { "hasSupportImages", FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE },
{ "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE },
{ "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } });
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());

View File

@ -9,9 +9,8 @@
#pragma once
#include "Object.h"
#include "../world/Footpath.h"
#include "Object.h"
class FootpathObject final : public Object
{
@ -19,14 +18,20 @@ private:
rct_footpath_entry _legacyType = {};
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 ReadJson(IReadObjectContext * context, const json_t * root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() 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.
*****************************************************************************/
#include "ImageTable.h"
#include "../OpenRCT2.h"
#include "../core/IStream.hpp"
#include "Object.h"
#include <algorithm>
#include <memory>
#include <stdexcept>
#include "../core/IStream.hpp"
#include "../OpenRCT2.h"
#include "ImageTable.h"
#include "Object.h"
ImageTable::~ImageTable()
{
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)
{
@ -88,14 +90,14 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream)
_data = std::move(data);
_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.");
throw;
}
}
void ImageTable::AddImage(const rct_g1_element * g1)
void ImageTable::AddImage(const rct_g1_element* g1)
{
rct_g1_element newg1 = *g1;
auto length = g1_calculate_data_size(g1);

View File

@ -9,28 +9,35 @@
#pragma once
#include <memory>
#include <vector>
#include "../common.h"
#include "../drawing/Drawing.h"
#include <memory>
#include <vector>
interface IReadObjectContext;
interface IStream;
class ImageTable
{
private:
std::unique_ptr<uint8_t[]> _data;
std::unique_ptr<uint8_t[]> _data;
std::vector<rct_g1_element> _entries;
public:
ImageTable() = default;
ImageTable(const ImageTable &) = delete;
ImageTable & operator=(const ImageTable &) = delete;
ImageTable(const ImageTable&) = delete;
ImageTable& operator=(const ImageTable&) = delete;
~ImageTable();
void Read(IReadObjectContext * context, IStream * stream);
const rct_g1_element * GetImages() const { return _entries.data(); }
uint32_t GetCount() const { return (uint32_t)_entries.size(); }
void AddImage(const rct_g1_element * g1);
void Read(IReadObjectContext* context, IStream* stream);
const rct_g1_element* GetImages() const
{
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
#include <algorithm>
#include "LargeSceneryObject.h"
#include "../core/IStream.hpp"
#include "../core/Memory.hpp"
#include "../core/Util.hpp"
@ -17,10 +18,11 @@
#include "../interface/Cursors.h"
#include "../localisation/Language.h"
#include "../world/Location.hpp"
#include "LargeSceneryObject.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);
_legacyType.large_scenery.tool_id = stream->ReadValue<uint8_t>();
@ -97,7 +99,7 @@ void LargeSceneryObject::Unload()
_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 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);
}
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>();
while (stream->ReadValue<uint16_t>() != 0xFFFF)
@ -119,25 +121,25 @@ std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadTiles(IStream * stre
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");
_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.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
auto jScrollingMode = json_object_get(properties, "scrollingMode");
_legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ?
json_integer_value(jScrollingMode) :
-1;
_legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ? json_integer_value(jScrollingMode) : -1;
// Flags
_legacyType.large_scenery.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
{ "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
{ "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
{ "isAnimated", LARGE_SCENERY_FLAG_ANIMATED },
{ "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC } });
_legacyType.large_scenery.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
properties,
{ { "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
{ "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
{ "isAnimated", LARGE_SCENERY_FLAG_ANIMATED },
{ "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC } });
// 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());
}
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;
size_t index;
const json_t * jTile;
const json_t* jTile;
json_array_foreach(jTiles, index, jTile)
{
rct_large_scenery_tile tile = {};
@ -203,7 +205,7 @@ std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadJsonTiles(const json
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>();
@ -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->num_images = json_integer_value(json_object_get(j3dFont, "numImages"));
font->flags = ObjectJsonHelpers::GetFlags<uint8_t>(j3dFont, {
{ "isVertical", LARGE_SCENERY_TEXT_FLAG_VERTICAL },
{ "isTwoLine", LARGE_SCENERY_TEXT_FLAG_TWO_LINE } });
font->flags = ObjectJsonHelpers::GetFlags<uint8_t>(
j3dFont, { { "isVertical", LARGE_SCENERY_TEXT_FLAG_VERTICAL }, { "isTwoLine", LARGE_SCENERY_TEXT_FLAG_TWO_LINE } });
auto jGlyphs = json_object_get(j3dFont, "glyphs");
if (jGlyphs != nullptr)
@ -232,11 +233,11 @@ std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const
return font;
}
std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t * jOffsets)
std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t* jOffsets)
{
std::vector<LocationXY16> offsets;
size_t index;
const json_t * jOffset;
const json_t* jOffset;
json_array_foreach(jOffsets, index, jOffset)
{
LocationXY16 offset = {};
@ -247,11 +248,11 @@ std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t * jOf
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;
size_t index;
const json_t * jGlyph;
const json_t* jGlyph;
json_array_foreach(jGlpyhs, index, jGlyph)
{
rct_large_scenery_text_glyph glyph;

View File

@ -9,36 +9,43 @@
#pragma once
#include <memory>
#include <vector>
#include "../world/Location.hpp"
#include "../world/Scenery.h"
#include "SceneryObject.h"
#include <memory>
#include <vector>
class LargeSceneryObject final : public SceneryObject
{
private:
rct_scenery_entry _legacyType = {};
uint32_t _baseImageId = 0;
std::vector<rct_large_scenery_tile> _tiles;
rct_scenery_entry _legacyType = {};
uint32_t _baseImageId = 0;
std::vector<rct_large_scenery_tile> _tiles;
std::unique_ptr<rct_large_scenery_text> _3dFont;
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 ReadJson(IReadObjectContext * context, const json_t * root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() 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:
static std::vector<rct_large_scenery_tile> ReadTiles(IStream * stream);
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::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_tile> ReadTiles(IStream* stream);
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::vector<LocationXY16> ReadJsonOffsets(const json_t* jOffsets);
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.
*****************************************************************************/
#include <algorithm>
#include "Object.h"
#include "../core/Memory.hpp"
#include "../core/String.hpp"
#include "../localisation/Language.h"
#include "../localisation/StringIds.h"
#include "Object.h"
#include "ObjectLimits.h"
Object::Object(const rct_object_entry &entry)
#include <algorithm>
Object::Object(const rct_object_entry& entry)
{
_objectEntry = entry;
@ -48,10 +50,10 @@ Object::~Object()
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);
const utf8 * result = nullptr;
const utf8* result = nullptr;
if (stringId != STR_NONE)
{
result = language_get_string(stringId);
@ -102,8 +104,7 @@ void Object::SetSourceGame(const uint8_t sourceGame)
bool Object::IsRCT1Object()
{
static const char _rct1Objects[][9] =
{
static const char _rct1Objects[][9] = {
"CLIFT1 ",
"MONO1 ",
"MONO2 ",
@ -405,8 +406,7 @@ bool Object::IsRCT1Object()
bool Object::IsAAObject()
{
static const char _aaObjects[][9] =
{
static const char _aaObjects[][9] = {
// Rides / vehicles / stalls
"BMFL ",
"BMRB ",
@ -521,8 +521,7 @@ bool Object::IsAAObject()
bool Object::IsLLObject()
{
static const char _llObjects[][9] =
{
static const char _llObjects[][9] = {
// Rides / vehicles / stalls
"AML1 ",
"ARRT2 ",
@ -650,8 +649,7 @@ bool Object::IsLLObject()
bool Object::IsOpenRCT2OfficialObject()
{
static const char _openRCT2OfficialObjects[][9] =
{
static const char _openRCT2OfficialObjects[][9] = {
// Offical extended scenery set
"XXBBBR01",
"TTRFTL02",
@ -698,10 +696,9 @@ bool Object::IsOpenRCT2OfficialObject()
return false;
}
#ifdef __WARN_SUGGEST_FINAL_METHODS__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
#endif
std::string Object::GetName() const
@ -715,5 +712,5 @@ std::string Object::GetName(int32_t language) const
}
#ifdef __WARN_SUGGEST_FINAL_METHODS__
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif

View File

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

View File

@ -7,6 +7,9 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "ObjectFactory.h"
#include "../OpenRCT2.h"
#include "../core/Console.hpp"
#include "../core/File.h"
#include "../core/FileStream.hpp"
@ -16,7 +19,6 @@
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../core/Zip.h"
#include "../OpenRCT2.h"
#include "../rct12/SawyerChunkReader.h"
#include "BannerObject.h"
#include "EntranceObject.h"
@ -26,7 +28,6 @@
#include "Object.h"
#include "ObjectLimits.h"
#include "ObjectList.h"
#include "ObjectFactory.h"
#include "RideObject.h"
#include "SceneryGroupObject.h"
#include "SmallSceneryObject.h"
@ -79,27 +80,33 @@ class ReadObjectContext : public IReadObjectContext
{
private:
IObjectRepository& _objectRepository;
const IFileDataRetriever * _fileDataRetriever;
const IFileDataRetriever* _fileDataRetriever;
std::string _objectName;
bool _loadImages;
bool _loadImages;
std::string _basePath;
bool _wasWarning = false;
bool _wasError = false;
bool _wasWarning = false;
bool _wasError = false;
public:
bool WasWarning() const { return _wasWarning; }
bool WasError() const { return _wasError; }
bool WasWarning() const
{
return _wasWarning;
}
bool WasError() const
{
return _wasError;
}
ReadObjectContext(
IObjectRepository& objectRepository,
const std::string &objectName,
const std::string& objectName,
bool loadImages,
const IFileDataRetriever * fileDataRetriever)
: _objectRepository(objectRepository),
_fileDataRetriever(fileDataRetriever),
_objectName(objectName),
_loadImages(loadImages)
const IFileDataRetriever* fileDataRetriever)
: _objectRepository(objectRepository)
, _fileDataRetriever(fileDataRetriever)
, _objectName(objectName)
, _loadImages(loadImages)
{
}
@ -145,30 +152,31 @@ public:
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
{
object->ReadLegacy(context, stream);
}
catch (const IOException &)
catch (const IOException&)
{
// TODO check that ex is really EOF and not some other error
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);
}
}
Object * CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8 * path)
Object* CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8* path)
{
log_verbose("CreateObjectFromLegacyFile(..., \"%s\")", path);
Object * result = nullptr;
Object* result = nullptr;
try
{
auto fs = FileStream(path, FILE_MODE_OPEN);
@ -192,7 +200,7 @@ namespace ObjectFactory
throw std::runtime_error("Object has errors");
}
}
catch (const std::exception &)
catch (const std::exception&)
{
delete result;
result = nullptr;
@ -200,12 +208,13 @@ namespace ObjectFactory
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(data, GUARD_LINE);
Object * result = CreateObject(*entry);
Object* result = CreateObject(*entry);
if (result != nullptr)
{
utf8 objectName[DAT_NAME_LENGTH + 1];
@ -224,68 +233,79 @@ namespace ObjectFactory
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);
switch (objectType) {
case OBJECT_TYPE_RIDE:
result = new RideObject(entry);
break;
case OBJECT_TYPE_SMALL_SCENERY:
result = new SmallSceneryObject(entry);
break;
case OBJECT_TYPE_LARGE_SCENERY:
result = new LargeSceneryObject(entry);
break;
case OBJECT_TYPE_WALLS:
result = new WallObject(entry);
break;
case OBJECT_TYPE_BANNERS:
result = new BannerObject(entry);
break;
case OBJECT_TYPE_PATHS:
result = new FootpathObject(entry);
break;
case OBJECT_TYPE_PATH_BITS:
result = new FootpathItemObject(entry);
break;
case OBJECT_TYPE_SCENERY_GROUP:
result = new SceneryGroupObject(entry);
break;
case OBJECT_TYPE_PARK_ENTRANCE:
result = new EntranceObject(entry);
break;
case OBJECT_TYPE_WATER:
result = new WaterObject(entry);
break;
case OBJECT_TYPE_SCENARIO_TEXT:
result = new StexObject(entry);
break;
default:
throw std::runtime_error("Invalid object type");
switch (objectType)
{
case OBJECT_TYPE_RIDE:
result = new RideObject(entry);
break;
case OBJECT_TYPE_SMALL_SCENERY:
result = new SmallSceneryObject(entry);
break;
case OBJECT_TYPE_LARGE_SCENERY:
result = new LargeSceneryObject(entry);
break;
case OBJECT_TYPE_WALLS:
result = new WallObject(entry);
break;
case OBJECT_TYPE_BANNERS:
result = new BannerObject(entry);
break;
case OBJECT_TYPE_PATHS:
result = new FootpathObject(entry);
break;
case OBJECT_TYPE_PATH_BITS:
result = new FootpathItemObject(entry);
break;
case OBJECT_TYPE_SCENERY_GROUP:
result = new SceneryGroupObject(entry);
break;
case OBJECT_TYPE_PARK_ENTRANCE:
result = new EntranceObject(entry);
break;
case OBJECT_TYPE_WATER:
result = new WaterObject(entry);
break;
case OBJECT_TYPE_SCENARIO_TEXT:
result = new StexObject(entry);
break;
default:
throw std::runtime_error("Invalid object type");
}
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 == "footpath") return OBJECT_TYPE_PATHS;
if (s == "footpath_banner") return OBJECT_TYPE_BANNERS;
if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS;
if (s == "scenery_small") 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;
if (s == "ride")
return OBJECT_TYPE_RIDE;
if (s == "footpath")
return OBJECT_TYPE_PATHS;
if (s == "footpath_banner")
return OBJECT_TYPE_BANNERS;
if (s == "footpath_item")
return OBJECT_TYPE_PATH_BITS;
if (s == "scenery_small")
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;
}
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
{
auto archive = Zip::Open(path, ZIP_ACCESS::READ);
@ -296,7 +316,7 @@ namespace ObjectFactory
}
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)
{
throw JsonException(&jsonLoadError);
@ -315,11 +335,11 @@ namespace ObjectFactory
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());
Object * result = nullptr;
Object* result = nullptr;
try
{
auto jRoot = Json::ReadFromFile(path.c_str());
@ -327,7 +347,7 @@ namespace ObjectFactory
result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
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());
@ -337,11 +357,12 @@ namespace ObjectFactory
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(...)");
Object * result = nullptr;
Object* result = nullptr;
auto jObjectType = json_object_get(jRoot, "objectType");
if (json_is_string(jObjectType))
{
@ -373,4 +394,4 @@ namespace ObjectFactory
}
return result;
}
}
} // namespace ObjectFactory

View File

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

View File

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

View File

@ -9,16 +9,16 @@
#pragma once
#define MAX_RIDE_OBJECTS 128
#define MAX_RIDE_OBJECTS 128
#define MAX_SMALL_SCENERY_OBJECTS 252
#define MAX_LARGE_SCENERY_OBJECTS 128
#define MAX_WALL_SCENERY_OBJECTS 128
#define MAX_BANNER_OBJECTS 32
#define MAX_PATH_OBJECTS 16
#define MAX_PATH_ADDITION_OBJECTS 15
#define MAX_SCENERY_GROUP_OBJECTS 19
#define MAX_PARK_ENTRANCE_OBJECTS 1
#define MAX_WATER_OBJECTS 1
#define MAX_SCENARIO_TEXT_OBJECTS 1
#define MAX_WALL_SCENERY_OBJECTS 128
#define MAX_BANNER_OBJECTS 32
#define MAX_PATH_OBJECTS 16
#define MAX_PATH_ADDITION_OBJECTS 15
#define MAX_SCENERY_GROUP_OBJECTS 19
#define MAX_PARK_ENTRANCE_OBJECTS 1
#define MAX_WATER_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.
*****************************************************************************/
#include <cstring>
#include "ObjectList.h"
#include "../Context.h"
#include "../Game.h"
#include "../core/Math.hpp"
#include "../core/Util.hpp"
#include "../Game.h"
#include "../object/Object.h"
#include "ObjectList.h"
#include "ObjectRepository.h"
#include "ObjectManager.h"
#include "../util/SawyerCoding.h"
#include "../util/Util.h"
#include "ObjectManager.h"
#include "ObjectRepository.h"
#include <cstring>
// 98DA00
// clang-format off
@ -52,23 +53,25 @@ int32_t object_entry_group_encoding[] = {
};
// 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;
memcpy(&a, (uint8_t *)entry, 8);
memcpy(&b, (uint8_t *)entry + 8, 8);
memcpy(&a, (uint8_t*)entry, 8);
memcpy(&b, (uint8_t*)entry + 8, 8);
if (a == 0xFFFFFFFFFFFFFFFF && b == 0xFFFFFFFFFFFFFFFF) return true;
if (a == 0 && b == 0) return true;
if (a == 0xFFFFFFFFFFFFFFFF && b == 0xFFFFFFFFFFFFFFFF)
return true;
if (a == 0 && b == 0)
return true;
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);
}
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;
}
@ -88,7 +91,7 @@ void object_create_identifier_name(char* string_buffer, size_t size, const rct_o
* bl = entry_index
* 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);
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;
}
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;
for (size_t groupCount : object_entry_group_counts)
{
if (index >= groupCount) {
if (index >= groupCount)
{
index -= groupCount;
objectType++;
} else {
}
else
{
break;
}
}
if (outObjectType != nullptr) *outObjectType = objectType;
if (outEntryIndex != nullptr) *outEntryIndex = (uint8_t)index;
if (outObjectType != nullptr)
*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;
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);
}
void * get_loaded_object_chunk(size_t index)
void* get_loaded_object_chunk(size_t index)
{
uint8_t objectType, entryIndex;
get_type_entry_index(index, &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);
memcpy(buffer, entry->name, bufferSize - 1);
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;
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];
}
void * result = nullptr;
void* result = nullptr;
auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objectMgr->GetLoadedObject(objectIndex);
if (obj != nullptr)
@ -170,9 +178,9 @@ void * object_entry_get_chunk(int32_t objectType, size_t index)
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 obj = objectMgr->GetLoadedObject(objectType, index);
if (obj != nullptr)

View File

@ -17,8 +17,8 @@
#include "../world/Water.h"
#include "ObjectLimits.h"
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);
void * get_loaded_object_chunk(size_t index);
uint8_t object_entry_get_type(const rct_object_entry * objectEntry);
uint8_t object_entry_get_source_game(const rct_object_entry * objectEntry);
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);
void* get_loaded_object_chunk(size_t index);
uint8_t object_entry_get_type(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.
*****************************************************************************/
#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 <array>
#include <memory>
#include <mutex>
#include <thread>
#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
{
private:
std::shared_ptr<IObjectRepository> _objectRepository;
std::vector<Object *> _loadedObjects;
std::vector<Object*> _loadedObjects;
public:
explicit ObjectManager(std::shared_ptr<IObjectRepository> objectRepository)
@ -52,7 +53,7 @@ public:
UnloadAll();
}
Object * GetLoadedObject(size_t index) override
Object* GetLoadedObject(size_t index) override
{
if (index >= _loadedObjects.size())
{
@ -61,7 +62,7 @@ public:
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])
{
@ -75,10 +76,10 @@ public:
return GetLoadedObject(objectIndex);
}
Object * GetLoadedObject(const rct_object_entry * entry) override
Object* GetLoadedObject(const rct_object_entry* entry) override
{
Object * loadedObject = nullptr;
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry);
Object* loadedObject = nullptr;
const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
if (ori != nullptr)
{
loadedObject = ori->LoadedObject;
@ -86,7 +87,7 @@ public:
return loadedObject;
}
uint8_t GetLoadedObjectEntryIndex(const Object * object) override
uint8_t GetLoadedObjectEntryIndex(const Object* object) override
{
uint8_t result = UINT8_MAX;
size_t index = GetLoadedObjectIndex(object);
@ -97,10 +98,10 @@ public:
return result;
}
Object * LoadObject(const rct_object_entry * entry) override
Object* LoadObject(const rct_object_entry* entry) override
{
Object * loadedObject = nullptr;
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry);
Object* loadedObject = nullptr;
const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
if (ori != nullptr)
{
loadedObject = ori->LoadedObject;
@ -127,7 +128,7 @@ public:
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
auto requiredObjects = GetRequiredObjects(entries, count);
@ -143,7 +144,7 @@ public:
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:
// - FindObject for every entry which is a dictionary lookup
@ -152,11 +153,11 @@ public:
size_t numObjectsUnloaded = 0;
for (size_t i = 0; i < count; i++)
{
const rct_object_entry * entry = &entries[i];
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry);
const rct_object_entry* entry = &entries[i];
const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
if (ori != nullptr)
{
Object * loadedObject = ori->LoadedObject;
Object* loadedObject = ori->LoadedObject;
if (loadedObject != nullptr)
{
UnloadObject(loadedObject);
@ -196,16 +197,14 @@ public:
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();
for (size_t i = 0; i < numObjects; i++)
{
const ObjectRepositoryItem * item = &_objectRepository->GetObjects()[i];
if (item->LoadedObject != nullptr &&
item->LoadedObject->GetLegacyData() != nullptr &&
IsObjectCustom(item))
const ObjectRepositoryItem* item = &_objectRepository->GetObjects()[i];
if (item->LoadedObject != nullptr && item->LoadedObject->GetLegacyData() != nullptr && IsObjectCustom(item))
{
objects.push_back(item);
}
@ -219,31 +218,31 @@ public:
// 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))
{
case OBJECT_SOURCE_RCT1:
return STR_SCENARIO_CATEGORY_RCT1;
case OBJECT_SOURCE_ADDED_ATTRACTIONS:
return STR_SCENARIO_CATEGORY_RCT1_AA;
case OBJECT_SOURCE_LOOPY_LANDSCAPES:
return STR_SCENARIO_CATEGORY_RCT1_LL;
case OBJECT_SOURCE_RCT2:
return STR_ROLLERCOASTER_TYCOON_2_DROPDOWN;
case OBJECT_SOURCE_WACKY_WORLDS:
return STR_OBJECT_FILTER_WW;
case OBJECT_SOURCE_TIME_TWISTER:
return STR_OBJECT_FILTER_TT;
case OBJECT_SOURCE_OPENRCT2_OFFICIAL:
return STR_OBJECT_FILTER_OPENRCT2_OFFICIAL;
default:
return STR_OBJECT_FILTER_CUSTOM;
case OBJECT_SOURCE_RCT1:
return STR_SCENARIO_CATEGORY_RCT1;
case OBJECT_SOURCE_ADDED_ATTRACTIONS:
return STR_SCENARIO_CATEGORY_RCT1_AA;
case OBJECT_SOURCE_LOOPY_LANDSCAPES:
return STR_SCENARIO_CATEGORY_RCT1_LL;
case OBJECT_SOURCE_RCT2:
return STR_ROLLERCOASTER_TYCOON_2_DROPDOWN;
case OBJECT_SOURCE_WACKY_WORLDS:
return STR_OBJECT_FILTER_WW;
case OBJECT_SOURCE_TIME_TWISTER:
return STR_OBJECT_FILTER_TT;
case OBJECT_SOURCE_OPENRCT2_OFFICIAL:
return STR_OBJECT_FILTER_OPENRCT2_OFFICIAL;
default:
return STR_OBJECT_FILTER_CUSTOM;
}
}
private:
Object * LoadObject(const std::string &name)
Object* LoadObject(const std::string& name)
{
rct_object_entry entry{};
std::copy_n(name.c_str(), 8, entry.name);
@ -269,7 +268,7 @@ private:
return -1;
}
size_t GetLoadedObjectIndex(const Object * object)
size_t GetLoadedObjectIndex(const Object* object)
{
Guard::ArgumentNotNull(object, GUARD_LINE);
@ -282,7 +281,7 @@ private:
return result;
}
void SetNewLoadedObjectList(const std::vector<Object *> &newLoadedObjects)
void SetNewLoadedObjectList(const std::vector<Object*>& newLoadedObjects)
{
if (newLoadedObjects.size() == 0)
{
@ -295,12 +294,12 @@ private:
_loadedObjects = newLoadedObjects;
}
void UnloadObject(Object * object)
void UnloadObject(Object* object)
{
if (object != nullptr)
{
// 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)
{
_objectRepository->UnregisterLoadedObject(ori, object);
@ -308,7 +307,7 @@ private:
// 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
for (auto &obj : _loadedObjects)
for (auto& obj : _loadedObjects)
{
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
auto exceptSet = std::unordered_set<Object *>();
auto exceptSet = std::unordered_set<Object*>();
for (auto object : newLoadedObjects)
{
if (object != nullptr)
@ -358,32 +357,33 @@ private:
{
if (loadedObject != nullptr)
{
rct_scenery_entry * sceneryEntry;
switch (loadedObject->GetObjectType()) {
case OBJECT_TYPE_SMALL_SCENERY:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_LARGE_SCENERY:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_WALLS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_BANNERS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_PATH_BITS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_SCENERY_GROUP:
auto sgObject = dynamic_cast<SceneryGroupObject *>(loadedObject);
sgObject->UpdateEntryIndexes();
break;
rct_scenery_entry* sceneryEntry;
switch (loadedObject->GetObjectType())
{
case OBJECT_TYPE_SMALL_SCENERY:
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_LARGE_SCENERY:
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_WALLS:
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_BANNERS:
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_PATH_BITS:
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_SCENERY_GROUP:
auto sgObject = dynamic_cast<SceneryGroupObject*>(loadedObject);
sgObject->UpdateEntryIndexes();
break;
}
}
}
@ -393,11 +393,11 @@ private:
window_close_by_class(WC_SCENERY);
}
uint8_t GetPrimarySceneryGroupEntryIndex(Object * loadedObject)
uint8_t GetPrimarySceneryGroupEntryIndex(Object* loadedObject)
{
auto sceneryObject = dynamic_cast<SceneryObject *>(loadedObject);
const rct_object_entry * primarySGEntry = sceneryObject->GetPrimarySceneryGroup();
Object * sgObject = GetLoadedObject(primarySGEntry);
auto sceneryObject = dynamic_cast<SceneryObject*>(loadedObject);
const rct_object_entry* primarySGEntry = sceneryObject->GetPrimarySceneryGroup();
Object* sgObject = GetLoadedObject(primarySGEntry);
uint8_t entryIndex = 255;
if (sgObject != nullptr)
@ -409,21 +409,21 @@ private:
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;
strncpy(duplicate->name, original->name, 8);
duplicate->flags = original->flags;
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;
invalidEntries.reserve(OBJECT_ENTRY_COUNT);
for (int32_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
{
auto entry = entries[i];
const ObjectRepositoryItem * ori = nullptr;
const ObjectRepositoryItem* ori = nullptr;
if (object_entry_is_empty(&entry))
{
entry = {};
@ -447,7 +447,7 @@ private:
}
else
{
Object * loadedObject = nullptr;
Object* loadedObject = nullptr;
loadedObject = ori->LoadedObject;
if (loadedObject == nullptr)
{
@ -464,15 +464,15 @@ private:
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;
for (size_t i = 0; i < count; i++)
{
const rct_object_entry * entry = &entries[i];
const ObjectRepositoryItem * ori = nullptr;
const rct_object_entry* entry = &entries[i];
const ObjectRepositoryItem* ori = nullptr;
if (!object_entry_is_empty(entry))
{
ori = _objectRepository->FindObject(entry);
@ -493,8 +493,7 @@ private:
return requiredObjects;
}
template<typename T, typename TFunc>
static void ParallelFor(const std::vector<T>& items, TFunc func)
template<typename T, typename TFunc> static void ParallelFor(const std::vector<T>& items, TFunc func)
{
auto partitions = std::thread::hardware_concurrency();
auto partitionSize = (items.size() + (partitions - 1)) / partitions;
@ -504,8 +503,7 @@ private:
auto begin = n * partitionSize;
auto end = std::min(items.size(), begin + partitionSize);
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++)
{
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 *> loadedObjects;
std::vector<Object*> objects;
std::vector<Object*> loadedObjects;
std::vector<rct_object_entry> badObjects;
objects.resize(OBJECT_ENTRY_COUNT);
loadedObjects.reserve(OBJECT_ENTRY_COUNT);
// Read objects
std::mutex commonMutex;
ParallelFor(
requiredObjects,
[this, &commonMutex, requiredObjects, &objects, &badObjects, &loadedObjects](size_t i)
ParallelFor(requiredObjects, [this, &commonMutex, requiredObjects, &objects, &badObjects, &loadedObjects](size_t i) {
auto ori = requiredObjects[i];
Object* loadedObject = nullptr;
if (ori != nullptr)
{
auto ori = requiredObjects[i];
Object * loadedObject = nullptr;
if (ori != nullptr)
loadedObject = ori->LoadedObject;
if (loadedObject == nullptr)
{
loadedObject = ori->LoadedObject;
loadedObject = _objectRepository->LoadObject(ori);
if (loadedObject == nullptr)
{
loadedObject = _objectRepository->LoadObject(ori);
if (loadedObject == nullptr)
{
std::lock_guard<std::mutex> guard(commonMutex);
badObjects.push_back(ori->ObjectEntry);
ReportObjectLoadProblem(&ori->ObjectEntry);
}
else
{
std::lock_guard<std::mutex> guard(commonMutex);
loadedObjects.push_back(loadedObject);
// Connect the ori to the registered object
_objectRepository->RegisterLoadedObject(ori, loadedObject);
}
std::lock_guard<std::mutex> guard(commonMutex);
badObjects.push_back(ori->ObjectEntry);
ReportObjectLoadProblem(&ori->ObjectEntry);
}
else
{
std::lock_guard<std::mutex> guard(commonMutex);
loadedObjects.push_back(loadedObject);
// Connect the ori to the registered object
_objectRepository->RegisterLoadedObject(ori, loadedObject);
}
}
objects[i] = loadedObject;
});
}
objects[i] = loadedObject;
});
// Load objects
for (auto obj : loadedObjects)
@ -583,9 +578,9 @@ private:
return objects;
}
Object * GetOrLoadObject(const ObjectRepositoryItem * ori)
Object* GetOrLoadObject(const ObjectRepositoryItem* ori)
{
Object * loadedObject = ori->LoadedObject;
Object* loadedObject = ori->LoadedObject;
if (loadedObject == nullptr)
{
// Try to load object
@ -606,14 +601,14 @@ private:
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 };
std::copy_n(entry->name, DAT_NAME_LENGTH, 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 };
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);
}
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();
Object * loadedObject = objectManager->GetLoadedObject(index);
return (void *)loadedObject;
Object* loadedObject = objectManager->GetLoadedObject(index);
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();
Object * loadedObject = objectManager->GetLoadedObject(entry);
return (void *)loadedObject;
Object* loadedObject = objectManager->GetLoadedObject(entry);
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();
const Object * object = static_cast<const Object *>(loadedObject);
const Object* object = static_cast<const Object*>(loadedObject);
uint8_t entryIndex = objectManager->GetLoadedObjectEntryIndex(object);
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();
Object * loadedObject = objectManager->LoadObject(entry);
return (void *)loadedObject;
Object* loadedObject = objectManager->LoadObject(entry);
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();
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);
}

View File

@ -9,41 +9,44 @@
#pragma once
#include <vector>
#include "../common.h"
#include "../object/Object.h"
interface IObjectRepository;
class Object;
struct ObjectRepositoryItem;
#include <vector>
interface IObjectRepository;
class Object;
struct ObjectRepositoryItem;
interface IObjectManager
{
virtual ~IObjectManager() { }
virtual ~IObjectManager()
{
}
virtual Object * GetLoadedObject(size_t index) abstract;
virtual Object * GetLoadedObject(int32_t objectType, size_t index) abstract;
virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract;
virtual uint8_t GetLoadedObjectEntryIndex(const Object * object) abstract;
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) abstract;
virtual Object* GetLoadedObject(size_t index) abstract;
virtual Object* GetLoadedObject(int32_t objectType, size_t index) abstract;
virtual Object* GetLoadedObject(const rct_object_entry* entry) abstract;
virtual uint8_t GetLoadedObjectEntryIndex(const Object* object) abstract;
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry* entries) abstract;
virtual Object * LoadObject(const rct_object_entry * entry) abstract;
virtual void LoadObjects(const rct_object_entry * entries, size_t count) abstract;
virtual void LoadDefaultObjects() abstract;
virtual void UnloadObjects(const rct_object_entry * entries, size_t count) abstract;
virtual void UnloadAll() abstract;
virtual Object* LoadObject(const rct_object_entry* entry) abstract;
virtual void LoadObjects(const rct_object_entry* entries, size_t count) abstract;
virtual void LoadDefaultObjects() abstract;
virtual void UnloadObjects(const rct_object_entry* entries, size_t count) abstract;
virtual void UnloadAll() 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);
void * object_manager_get_loaded_object_by_index(size_t index);
void * object_manager_get_loaded_object(const rct_object_entry * entry);
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_unload_objects(const rct_object_entry * entries, size_t count);
void object_manager_unload_all_objects();
rct_string_id object_manager_get_source_game_string(const rct_object_entry * entry);
void* object_manager_get_loaded_object_by_index(size_t index);
void* object_manager_get_loaded_object(const rct_object_entry* entry);
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_unload_objects(const rct_object_entry* entries, size_t count);
void object_manager_unload_all_objects();
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.
*****************************************************************************/
#include <algorithm>
#include <memory>
#include <unordered_map>
#include <vector>
#include "ObjectRepository.h"
#include "../common.h"
#include "../Context.h"
#include "../PlatformEnvironment.h"
#include "../common.h"
#include "../config/Config.h"
#include "../core/Console.hpp"
#include "../core/FileIndex.hpp"
#include "../core/FileStream.hpp"
@ -23,31 +22,32 @@
#include "../core/MemoryStream.h"
#include "../core/Path.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/LocalisationService.h"
#include "../object/Object.h"
#include "ObjectList.h"
#include "../platform/platform.h"
#include "../rct12/SawyerChunkReader.h"
#include "../rct12/SawyerChunkWriter.h"
#include "../scenario/ScenarioRepository.h"
#include "../util/SawyerCoding.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;
struct ObjectEntryHash
{
size_t operator()(const rct_object_entry &entry) const
size_t operator()(const rct_object_entry& entry) const
{
uint32_t hash = 5381;
for (auto i : entry.name)
@ -60,7 +60,7 @@ struct ObjectEntryHash
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;
}
@ -78,23 +78,23 @@ private:
IObjectRepository& _objectRepository;
public:
explicit ObjectFileIndex(IObjectRepository& objectRepository, const IPlatformEnvironment& env) :
FileIndex("object index",
MAGIC_NUMBER,
VERSION,
env.GetFilePath(PATHID::CACHE_OBJECTS),
std::string(PATTERN),
std::vector<std::string>({
env.GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT),
env.GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) })),
_objectRepository(objectRepository)
explicit ObjectFileIndex(IObjectRepository& objectRepository, const IPlatformEnvironment& env)
: FileIndex(
"object index",
MAGIC_NUMBER,
VERSION,
env.GetFilePath(PATHID::CACHE_OBJECTS),
std::string(PATTERN),
std::vector<std::string>({ env.GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT),
env.GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) }))
, _objectRepository(objectRepository)
{
}
public:
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);
if (String::Equals(extension, ".json", true))
{
@ -122,36 +122,37 @@ public:
}
protected:
void Serialise(IStream * stream, const ObjectRepositoryItem &item) const override
void Serialise(IStream* stream, const ObjectRepositoryItem& item) const override
{
stream->WriteValue(item.ObjectEntry);
stream->WriteString(item.Path);
stream->WriteString(item.Name);
switch (object_entry_get_type(&item.ObjectEntry)) {
case OBJECT_TYPE_RIDE:
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]);
}
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.RideGroupIndex);
break;
case OBJECT_TYPE_SCENERY_GROUP:
stream->WriteValue<uint16_t>((uint16_t)item.SceneryGroupInfo.Entries.size());
for (const auto& entry : item.SceneryGroupInfo.Entries)
{
stream->WriteValue<rct_object_entry>(entry);
}
break;
switch (object_entry_get_type(&item.ObjectEntry))
{
case OBJECT_TYPE_RIDE:
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]);
}
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.RideGroupIndex);
break;
case OBJECT_TYPE_SCENERY_GROUP:
stream->WriteValue<uint16_t>((uint16_t)item.SceneryGroupInfo.Entries.size());
for (const auto& entry : item.SceneryGroupInfo.Entries)
{
stream->WriteValue<rct_object_entry>(entry);
}
break;
}
}
ObjectRepositoryItem Deserialise(IStream * stream) const override
ObjectRepositoryItem Deserialise(IStream* stream) const override
{
ObjectRepositoryItem item;
@ -159,20 +160,21 @@ protected:
item.Path = stream->ReadStdString();
item.Name = stream->ReadStdString();
switch (object_entry_get_type(&item.ObjectEntry)) {
case OBJECT_TYPE_RIDE:
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>();
}
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
{
item.RideInfo.RideType[i] = stream->ReadValue<uint8_t>();
}
item.RideInfo.RideGroupIndex = stream->ReadValue<uint8_t>();
break;
case OBJECT_TYPE_SCENERY_GROUP:
switch (object_entry_get_type(&item.ObjectEntry))
{
case OBJECT_TYPE_RIDE:
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>();
}
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
{
item.RideInfo.RideType[i] = stream->ReadValue<uint8_t>();
}
item.RideInfo.RideGroupIndex = stream->ReadValue<uint8_t>();
break;
case OBJECT_TYPE_SCENERY_GROUP:
{
auto numEntries = stream->ReadValue<uint16_t>();
item.SceneryGroupInfo.Entries = std::vector<rct_object_entry>(numEntries);
@ -187,11 +189,9 @@ protected:
}
private:
bool IsTrackReadOnly(const std::string &path) const
bool IsTrackReadOnly(const std::string& path) const
{
return
String::StartsWith(path, SearchPaths[0]) ||
String::StartsWith(path, SearchPaths[1]);
return String::StartsWith(path, SearchPaths[0]) || String::StartsWith(path, SearchPaths[1]);
}
};
@ -204,8 +204,8 @@ class ObjectRepository final : public IObjectRepository
public:
explicit ObjectRepository(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env),
_fileIndex(*this, *env)
: _env(env)
, _fileIndex(*this, *env)
{
}
@ -234,12 +234,12 @@ public:
return _items.size();
}
const ObjectRepositoryItem * GetObjects() const override
const ObjectRepositoryItem* GetObjects() const override
{
return _items.data();
}
const ObjectRepositoryItem * FindObject(const utf8 * name) const override
const ObjectRepositoryItem* FindObject(const utf8* name) const override
{
rct_object_entry entry = {};
utf8 entryName[9] = { ' ' };
@ -254,7 +254,7 @@ public:
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);
if (kvp != _itemMap.end())
@ -264,7 +264,7 @@ public:
return nullptr;
}
Object * LoadObject(const ObjectRepositoryItem * ori) override
Object* LoadObject(const ObjectRepositoryItem* ori) override
{
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);
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)
{
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];
object_entry_get_name_fixed(objectName, sizeof(objectName), objectEntry);
// 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)
{
Console::Error::WriteLine("[%s] Unable to export object.", objectName);
@ -322,14 +322,14 @@ public:
SaveObject(path, objectEntry, data, dataSize);
ScanObject(path);
}
catch (const std::exception &)
catch (const std::exception&)
{
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);
@ -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());
for (const auto &object : objects)
for (const auto& object : objects)
{
Guard::ArgumentNotNull(object);
@ -375,9 +375,7 @@ private:
void SortItems()
{
std::sort(_items.begin(), _items.end(), [](const ObjectRepositoryItem &a,
const ObjectRepositoryItem &b) -> bool
{
std::sort(_items.begin(), _items.end(), [](const ObjectRepositoryItem& a, const ObjectRepositoryItem& b) -> bool {
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;
for (auto item : items)
@ -412,7 +410,7 @@ private:
}
}
bool AddItem(const ObjectRepositoryItem &item)
bool AddItem(const ObjectRepositoryItem& item)
{
auto conflict = FindObject(&item.ObjectEntry);
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 result = _fileIndex.Create(language, path);
@ -443,10 +441,8 @@ private:
}
}
static void SaveObject(const utf8 * path,
const rct_object_entry * entry,
const void * data, size_t dataSize,
bool fixChecksum = true)
static void
SaveObject(const utf8* path, const rct_object_entry* entry, const void* data, size_t dataSize, bool fixChecksum = true)
{
if (fixChecksum)
{
@ -460,14 +456,14 @@ private:
// 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
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
size_t newDataSize = dataSize + extraBytesCount;
uint8_t * newData = Memory::Allocate<uint8_t>(newDataSize);
uint8_t * newDataSaltOffset = newData + dataSize;
std::copy_n((const uint8_t *)data, dataSize, newData);
std::copy_n((const uint8_t *)extraBytes, extraBytesCount, newDataSaltOffset);
uint8_t* newData = Memory::Allocate<uint8_t>(newDataSize);
uint8_t* newDataSaltOffset = newData + dataSize;
std::copy_n((const uint8_t*)data, dataSize, newData);
std::copy_n((const uint8_t*)extraBytes, extraBytesCount, newDataSaltOffset);
try
{
@ -487,7 +483,7 @@ private:
Memory::Free(newData);
Memory::Free(extraBytes);
}
catch (const std::exception &)
catch (const std::exception&)
{
Memory::Free(newData);
Memory::Free(extraBytes);
@ -502,8 +498,8 @@ private:
sawyercoding_chunk_header chunkHeader;
chunkHeader.encoding = object_entry_group_encoding[objectType];
chunkHeader.length = (uint32_t)dataSize;
uint8_t * encodedDataBuffer = Memory::Allocate<uint8_t>(0x600000);
size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (uint8_t *)data, chunkHeader);
uint8_t* encodedDataBuffer = Memory::Allocate<uint8_t>(0x600000);
size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (uint8_t*)data, chunkHeader);
// Save to file
try
@ -514,18 +510,19 @@ private:
Memory::Free(encodedDataBuffer);
}
catch (const std::exception &)
catch (const std::exception&)
{
Memory::Free(encodedDataBuffer);
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
uint8_t * salt = Memory::Allocate<uint8_t>(11);
if (outSize != nullptr) *outSize = 11;
uint8_t* salt = Memory::Allocate<uint8_t>(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
// The bitwise rotation compensates for the rotation performed during the checksum calculation*/
@ -550,7 +547,7 @@ private:
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 };
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());
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)
{
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);
}
bool IsObjectCustom(const ObjectRepositoryItem * object)
bool IsObjectCustom(const ObjectRepositoryItem* object)
{
Guard::ArgumentNotNull(object);
@ -624,9 +621,9 @@ bool IsObjectCustom(const ObjectRepositoryItem * object)
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 item = objRepo->FindObject(entry);
if (item != nullptr)
@ -647,11 +644,11 @@ void object_list_load()
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();
const ObjectRepositoryItem * ori = objRepository->FindObject(objectEntry);
const ObjectRepositoryItem* ori = objRepository->FindObject(objectEntry);
if (ori != nullptr)
{
object = objRepository->LoadObject(ori);
@ -660,10 +657,10 @@ void * object_repository_load_object(const rct_object_entry * objectEntry)
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];
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)
{
auto objectRepository = GetContext()->GetObjectRepository();
const ObjectRepositoryItem * ori = objectRepository->FindObject(stexObjectEntry);
const ObjectRepositoryItem* ori = objectRepository->FindObject(stexObjectEntry);
if (ori != nullptr)
{
Object * object = objectRepository->LoadObject(ori);
Object* object = objectRepository->LoadObject(ori);
if (object != nullptr)
{
auto stexObject = static_cast<StexObject*>(object);
@ -709,41 +706,41 @@ size_t object_repository_get_items_count()
return objectRepository->GetNumObjects();
}
const ObjectRepositoryItem * object_repository_get_items()
const ObjectRepositoryItem* object_repository_get_items()
{
auto objectRepository = GetContext()->GetObjectRepository();
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();
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();
return objectRepository->FindObject(name);
}
void object_delete(void * object)
void object_delete(void* object)
{
if (object != nullptr)
{
Object * baseObject = static_cast<Object *>(object);
Object* baseObject = static_cast<Object*>(object);
baseObject->Unload();
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);
}
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 ((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;
}
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;
checksum ^= entryBytePtr[0];
@ -790,7 +787,7 @@ int32_t object_calculate_checksum(const rct_object_entry * entry, const void * d
checksum = rol32(checksum, 11);
}
uint8_t * dataBytes = (uint8_t *)data;
uint8_t* dataBytes = (uint8_t*)data;
const size_t dataLength32 = dataLength - (dataLength & 31);
for (size_t i = 0; i < 32; i++)
{

View File

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

View File

@ -9,50 +9,57 @@
#pragma once
#include <vector>
#include "../ride/Ride.h"
#include "Object.h"
#include <vector>
class RideObject final : public Object
{
private:
rct_ride_entry _legacyType = {};
vehicle_colour_preset_list _presetColours = {};
std::vector<int8_t> _peepLoadingPositions[MAX_VEHICLES_PER_RIDE_ENTRY];
std::vector<std::array<sLocationXY8, 3> > _peepLoadingWaypoints[MAX_VEHICLES_PER_RIDE_ENTRY];
rct_ride_entry _legacyType = {};
vehicle_colour_preset_list _presetColours = {};
std::vector<int8_t> _peepLoadingPositions[MAX_VEHICLES_PER_RIDE_ENTRY];
std::vector<std::array<sLocationXY8, 3>> _peepLoadingWaypoints[MAX_VEHICLES_PER_RIDE_ENTRY];
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 ReadLegacy(IReadObjectContext * context, IStream * stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void Load() 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 GetCapacity() const;
void SetRepositoryItem(ObjectRepositoryItem * item) const override;
void SetRepositoryItem(ObjectRepositoryItem* item) const override;
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);
std::vector<rct_ride_entry_vehicle> ReadJsonCars(const json_t * jCars);
rct_ride_entry_vehicle ReadJsonCar(const json_t * jCar);
vehicle_colour_preset_list ReadJsonCarColours(const json_t * jCarColours);
std::vector<vehicle_colour> ReadJsonColourConfiguration(const json_t * jColourConfig);
void ReadJsonVehicleInfo(IReadObjectContext* context, const json_t* properties);
std::vector<rct_ride_entry_vehicle> ReadJsonCars(const json_t* jCars);
rct_ride_entry_vehicle ReadJsonCar(const json_t* jCar);
vehicle_colour_preset_list ReadJsonCarColours(const json_t* jCarColours);
std::vector<vehicle_colour> ReadJsonColourConfiguration(const json_t* jColourConfig);
static uint8_t CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry);
static uint8_t CalculateNumHorizontalFrames(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 bool IsRideTypeShopOrFacility(uint8_t rideType);
static uint8_t ParseRideType(const std::string &s);
static uint8_t ParseRideCategory(const std::string &s);
static uint8_t ParseShopItem(const std::string &s);
static colour_t ParseColour(const std::string &s);
static uint8_t ParseRideType(const std::string& s);
static uint8_t ParseRideCategory(const std::string& s);
static uint8_t ParseShopItem(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
#include <unordered_map>
#include "SceneryGroupObject.h"
#include "../Context.h"
#include "../core/IStream.hpp"
#include "../core/Memory.hpp"
@ -20,11 +21,12 @@
#include "ObjectJsonHelpers.h"
#include "ObjectManager.h"
#include "ObjectRepository.h"
#include "SceneryGroupObject.h"
#include <unordered_map>
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(0x80 * 2, STREAM_SEEK_CURRENT);
@ -56,7 +58,7 @@ void SceneryGroupObject::Unload()
_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 y = height / 2;
@ -72,23 +74,37 @@ void SceneryGroupObject::UpdateEntryIndexes()
auto objectManager = context->GetObjectManager();
_legacyType.entry_count = 0;
for (const auto &objectEntry : _items)
for (const auto& objectEntry : _items)
{
auto ori = objectRepository->FindObject(&objectEntry);
if (ori == nullptr) continue;
if (ori->LoadedObject == nullptr) continue;
if (ori == nullptr)
continue;
if (ori->LoadedObject == nullptr)
continue;
uint16_t sceneryEntry = objectManager->GetLoadedObjectEntryIndex(ori->LoadedObject);
Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE);
auto objectType = ori->ObjectEntry.flags & 0x0F;
switch (objectType) {
case OBJECT_TYPE_SMALL_SCENERY: break;
case OBJECT_TYPE_PATH_BITS: sceneryEntry |= 0x100; 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;
switch (objectType)
{
case OBJECT_TYPE_SMALL_SCENERY:
break;
case OBJECT_TYPE_PATH_BITS:
sceneryEntry |= 0x100;
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)
{
@ -98,12 +114,12 @@ void SceneryGroupObject::UpdateEntryIndexes()
}
}
void SceneryGroupObject::SetRepositoryItem(ObjectRepositoryItem * item) const
void SceneryGroupObject::SetRepositoryItem(ObjectRepositoryItem* item) const
{
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>();
while (stream->ReadValue<uint8_t>() != 0xFF)
@ -115,7 +131,7 @@ std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream * stream)
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");
_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());
}
uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostumes)
uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t* jCostumes)
{
uint32_t costumes = 0;
auto szCostumes = ObjectJsonHelpers::GetJsonStringArray(jCostumes);
@ -152,27 +168,38 @@ uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostume
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 == "tiger") return ENTERTAINER_COSTUME_TIGER;
if (s == "elephant") return ENTERTAINER_COSTUME_ELEPHANT;
if (s == "roman") return ENTERTAINER_COSTUME_ROMAN;
if (s == "gorilla") return ENTERTAINER_COSTUME_GORILLA;
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;
if (s == "panda")
return ENTERTAINER_COSTUME_PANDA;
if (s == "tiger")
return ENTERTAINER_COSTUME_TIGER;
if (s == "elephant")
return ENTERTAINER_COSTUME_ELEPHANT;
if (s == "roman")
return ENTERTAINER_COSTUME_ROMAN;
if (s == "gorilla")
return ENTERTAINER_COSTUME_GORILLA;
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;
}
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;
size_t index;
json_t * jEntry;
json_t* jEntry;
json_array_foreach(jEntries, index, jEntry)
{
auto entryId = json_string_value(jEntry);

View File

@ -9,36 +9,43 @@
#pragma once
#include <vector>
#include "../world/Scenery.h"
#include "Object.h"
#include <vector>
struct ObjectRepositoryItem;
class SceneryGroupObject final : public Object
{
private:
rct_scenery_group_entry _legacyType = {};
std::vector<rct_object_entry> _items;
rct_scenery_group_entry _legacyType = {};
std::vector<rct_object_entry> _items;
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 ReadJson(IReadObjectContext * context, const json_t * root) override;
void* GetLegacyData() 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 Unload() override;
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:
static std::vector<rct_object_entry> ReadItems(IStream * stream);
static uint32_t ReadJsonEntertainerCostumes(const json_t * jCostumes);
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> ReadItems(IStream* stream);
static uint32_t ReadJsonEntertainerCostumes(const json_t* jCostumes);
static uint32_t ParseEntertainerCostume(const std::string& s);
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.
*****************************************************************************/
#include "ObjectJsonHelpers.h"
#include "SceneryObject.h"
void SceneryObject::SetPrimarySceneryGroup(const std::string &s)
#include "ObjectJsonHelpers.h"
void SceneryObject::SetPrimarySceneryGroup(const std::string& s)
{
if (!s.empty())
{

View File

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

View File

@ -9,6 +9,8 @@
#pragma warning(disable : 4706) // assignment within conditional expression
#include "SmallSceneryObject.h"
#include "../core/IStream.hpp"
#include "../core/Math.hpp"
#include "../core/Memory.hpp"
@ -18,10 +20,9 @@
#include "../localisation/Language.h"
#include "../world/Scenery.h"
#include "../world/SmallScenery.h"
#include "SmallSceneryObject.h"
#include "ObjectJsonHelpers.h"
void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
void SmallSceneryObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{
stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.small_scenery.flags = stream->ReadValue<uint32_t>();
@ -88,7 +89,7 @@ void SmallSceneryObject::Unload()
_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;
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);
y = std::min(y, height - 16);
if ((scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_FULL_TILE)) &&
(scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_VOFFSET_CENTRE)))
if ((scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_FULL_TILE))
&& (scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_VOFFSET_CENTRE)))
{
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;
auto data = std::vector<uint8_t>();
@ -228,12 +229,13 @@ rct_object_entry SmallSceneryObject::GetScgAbstrHeader()
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");
_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.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
_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"));
// Flags
_legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags<uint32_t>(properties, {
{ "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE },
{ "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE },
{ "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE },
{ "isAnimated", SMALL_SCENERY_FLAG_ANIMATED },
{ "canWither", SMALL_SCENERY_FLAG_CAN_WITHER },
{ "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED },
{ "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG },
{ "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS },
{ "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 },
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 },
{ "isClock", SMALL_SCENERY_FLAG_IS_CLOCK },
{ "SMALL_SCENERY_FLAG_SWAMP_GOO", SMALL_SCENERY_FLAG_SWAMP_GOO },
{ "SMALL_SCENERY_FLAG17", SMALL_SCENERY_FLAG17 },
{ "isStackable", SMALL_SCENERY_FLAG_STACKABLE },
{ "prohibitWalls", SMALL_SCENERY_FLAG_NO_WALLS },
{ "hasSecondaryColour", SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
{ "hasNoSupports", SMALL_SCENERY_FLAG_NO_SUPPORTS },
{ "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED },
{ "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG },
{ "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP },
{ "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS },
{ "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } });
_legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags<uint32_t>(
properties,
{ { "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE },
{ "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE },
{ "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE },
{ "isAnimated", SMALL_SCENERY_FLAG_ANIMATED },
{ "canWither", SMALL_SCENERY_FLAG_CAN_WITHER },
{ "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED },
{ "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG },
{ "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS },
{ "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 },
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 },
{ "isClock", SMALL_SCENERY_FLAG_IS_CLOCK },
{ "SMALL_SCENERY_FLAG_SWAMP_GOO", SMALL_SCENERY_FLAG_SWAMP_GOO },
{ "SMALL_SCENERY_FLAG17", SMALL_SCENERY_FLAG17 },
{ "isStackable", SMALL_SCENERY_FLAG_STACKABLE },
{ "prohibitWalls", SMALL_SCENERY_FLAG_NO_WALLS },
{ "hasSecondaryColour", SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
{ "hasNoSupports", SMALL_SCENERY_FLAG_NO_SUPPORTS },
{ "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED },
{ "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG },
{ "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP },
{ "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS },
{ "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } });
// Determine shape flags from a shape string
auto shape = ObjectJsonHelpers::GetString(properties, "shape");
@ -305,11 +308,11 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r
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;
size_t index;
const json_t * jOffset;
const json_t* jOffset;
json_array_foreach(jFrameOffsets, index, jOffset)
{
offsets.push_back(json_integer_value(jOffset));

View File

@ -9,31 +9,38 @@
#pragma once
#include <vector>
#include "../world/Scenery.h"
#include "SceneryObject.h"
#include <vector>
class SmallSceneryObject final : public SceneryObject
{
private:
rct_scenery_entry _legacyType = {};
std::vector<uint8_t> _frameOffsets;
rct_scenery_entry _legacyType = {};
std::vector<uint8_t> _frameOffsets;
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 ReadJson(IReadObjectContext * context, const json_t * root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() 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:
static std::vector<uint8_t> ReadFrameOffsets(IStream * stream);
static std::vector<uint8_t> ReadJsonFrameOffsets(const json_t * jFrameOffsets);
static std::vector<uint8_t> ReadFrameOffsets(IStream* stream);
static std::vector<uint8_t> ReadJsonFrameOffsets(const json_t* jFrameOffsets);
void PerformFixes();
rct_object_entry GetScgPiratHeader();
rct_object_entry GetScgMineHeader();

View File

@ -7,12 +7,12 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "../core/IStream.hpp"
#include "StexObject.h"
#include "../core/IStream.hpp"
#include "../localisation/Localisation.h"
void StexObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
void StexObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
{
stream->Seek(6, STREAM_SEEK_CURRENT);
_legacyType.var_06 = stream->ReadValue<uint8_t>();
@ -42,7 +42,7 @@ void StexObject::Unload()
_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)
int32_t x = width / 2;

View File

@ -9,9 +9,8 @@
#pragma once
#include "Object.h"
#include "../scenario/Scenario.h"
#include "Object.h"
class StexObject final : public Object
{
@ -19,15 +18,21 @@ private:
rct_stex_entry _legacyType = {};
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 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;

View File

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

View File

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

View File

@ -7,14 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "WallObject.h"
#include "../core/IStream.hpp"
#include "../drawing/Drawing.h"
#include "../interface/Cursors.h"
#include "../localisation/Language.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);
_legacyType.wall.tool_id = stream->ReadValue<uint8_t>();
@ -55,7 +56,7 @@ void WallObject::Unload()
_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 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");
_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.price = json_integer_value(json_object_get(properties, "price"));
auto jScrollingMode = json_object_get(properties, "scrollingMode");
_legacyType.wall.scrolling_mode = jScrollingMode != nullptr ?
json_integer_value(jScrollingMode) :
-1;
_legacyType.wall.scrolling_mode = jScrollingMode != nullptr ? json_integer_value(jScrollingMode) : -1;
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
// Flags
_legacyType.wall.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
{ "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR },
{ "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR },
{ "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR },
{ "hasGlass", WALL_SCENERY_HAS_GLASS },
{ "isBanner", WALL_SCENERY_IS_BANNER },
{ "isDoor", WALL_SCENERY_IS_DOOR },
{ "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION }});
_legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
{ "isOpaque", WALL_SCENERY_2_IS_OPAQUE },
{ "isAnimated", WALL_SCENERY_2_ANIMATED }});
_legacyType.wall.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
properties,
{ { "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR },
{ "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR },
{ "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR },
{ "hasGlass", WALL_SCENERY_HAS_GLASS },
{ "isBanner", WALL_SCENERY_IS_BANNER },
{ "isDoor", WALL_SCENERY_IS_DOOR },
{ "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION } });
_legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags<uint8_t>(
properties, { { "isOpaque", WALL_SCENERY_2_IS_OPAQUE }, { "isAnimated", WALL_SCENERY_2_ANIMATED } });
// HACK To avoid 'negated' properties in JSON, handle this separately until
// 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.
if (!(_legacyType.wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR))
{
if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) ||
(_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR))
if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR)
|| (_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR))
{
_legacyType.wall.flags2 |= WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR;
}

View File

@ -9,24 +9,29 @@
#pragma once
#include "SceneryObject.h"
#include "../world/Scenery.h"
#include "SceneryObject.h"
class WallObject final : public SceneryObject
{
private:
rct_scenery_entry _legacyType = {};
rct_scenery_entry _legacyType = {};
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 ReadJson(IReadObjectContext * context, const json_t * root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() 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
#include <memory>
#include "WaterObject.h"
#include "../OpenRCT2.h"
#include "../core/IStream.hpp"
#include "../localisation/Language.h"
#include "../localisation/StringIds.h"
#include "../OpenRCT2.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);
_legacyType.flags = stream->ReadValue<uint16_t>();
@ -45,7 +47,7 @@ void WaterObject::Unload()
_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)
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)
{
auto properties = json_object_get(root, "properties");
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, {
{ "allowDucks", WATER_FLAGS_ALLOW_DUCKS }});
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, { { "allowDucks", WATER_FLAGS_ALLOW_DUCKS } });
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
// Images which are actually palette data
static const char * paletteNames[] =
{
"general",
"waves-0",
"waves-1",
"waves-2",
"sparkles-0",
"sparkles-1",
"sparkles-2"
};
static const char* paletteNames[]
= { "general", "waves-0", "waves-1", "waves-2", "sparkles-0", "sparkles-1", "sparkles-2" };
for (auto paletteName : paletteNames)
{
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 jColours = json_object_get(jPalette, "colours");
@ -96,7 +89,7 @@ void WaterObject::ReadJsonPalette(const json_t * jPalette)
size_t dataIndex = 0;
size_t index;
const json_t * jColour;
const json_t* jColour;
json_array_foreach(jColours, index, 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.flags = G1_FLAG_PALETTE;
auto &imageTable = GetImageTable();
auto& imageTable = GetImageTable();
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 g = 0;

View File

@ -9,28 +9,35 @@
#pragma once
#include <tuple>
#include "../world/Water.h"
#include "Object.h"
#include <tuple>
class WaterObject final : public Object
{
private:
rct_water_type _legacyType = {};
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 ReadLegacy(IReadObjectContext * context, IStream * stream) override;
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
void Load() 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:
void ReadJsonPalette(const json_t * jPalette);
uint32_t ParseColour(const std::string &s) const;
void ReadJsonPalette(const json_t* jPalette);
uint32_t ParseColour(const std::string& s) const;
};