mirror of https://github.com/OpenRCT2/OpenRCT2.git
clang-format object
This commit is contained in:
parent
e32189fd98
commit
a6a12af1ec
|
@ -7,16 +7,17 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "BannerObject.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../object/Object.h"
|
#include "../object/Object.h"
|
||||||
#include "../object/ObjectRepository.h"
|
#include "../object/ObjectRepository.h"
|
||||||
#include "BannerObject.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
#include "ObjectList.h"
|
#include "ObjectList.h"
|
||||||
|
|
||||||
void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void BannerObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.banner.scrolling_mode = stream->ReadValue<uint8_t>();
|
_legacyType.banner.scrolling_mode = stream->ReadValue<uint8_t>();
|
||||||
|
@ -47,9 +48,9 @@ void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
||||||
if (item != nullptr)
|
if (item != nullptr)
|
||||||
{
|
{
|
||||||
auto objectEntry = &item->ObjectEntry;
|
auto objectEntry = &item->ObjectEntry;
|
||||||
if (object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_WACKY_WORLDS ||
|
if (object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_WACKY_WORLDS
|
||||||
object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_TIME_TWISTER ||
|
|| object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_TIME_TWISTER
|
||||||
object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_CUSTOM)
|
|| object_entry_get_source_game(objectEntry) == OBJECT_SOURCE_CUSTOM)
|
||||||
{
|
{
|
||||||
auto scgPathX = Object::GetScgPathXHeader();
|
auto scgPathX = Object::GetScgPathXHeader();
|
||||||
SetPrimarySceneryGroup(&scgPathX);
|
SetPrimarySceneryGroup(&scgPathX);
|
||||||
|
@ -73,7 +74,7 @@ void BannerObject::Unload()
|
||||||
_legacyType.image = 0;
|
_legacyType.image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BannerObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void BannerObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
int32_t y = height / 2;
|
int32_t y = height / 2;
|
||||||
|
@ -83,14 +84,14 @@ void BannerObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t h
|
||||||
gfx_draw_sprite(dpi, imageId + 1, x - 12, y + 8, 0);
|
gfx_draw_sprite(dpi, imageId + 1, x - 12, y + 8, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BannerObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void BannerObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
|
|
||||||
_legacyType.banner.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
|
_legacyType.banner.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
|
||||||
_legacyType.banner.price = json_integer_value(json_object_get(properties, "price"));
|
_legacyType.banner.price = json_integer_value(json_object_get(properties, "price"));
|
||||||
_legacyType.banner.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
|
_legacyType.banner.flags
|
||||||
{ "hasPrimaryColour", BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR }});
|
= ObjectJsonHelpers::GetFlags<uint8_t>(properties, { { "hasPrimaryColour", BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR } });
|
||||||
|
|
||||||
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
|
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
|
||||||
|
|
||||||
|
|
|
@ -9,24 +9,29 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SceneryObject.h"
|
|
||||||
|
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
|
#include "SceneryObject.h"
|
||||||
|
|
||||||
class BannerObject final : public SceneryObject
|
class BannerObject final : public SceneryObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_scenery_entry _legacyType = {};
|
rct_scenery_entry _legacyType = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BannerObject(const rct_object_entry &entry) : SceneryObject(entry) { }
|
explicit BannerObject(const rct_object_entry& entry)
|
||||||
|
: SceneryObject(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,50 +8,49 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "DefaultObjects.h"
|
#include "DefaultObjects.h"
|
||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
|
||||||
/** rct2: 0x0098DA74 */
|
/** rct2: 0x0098DA74 */
|
||||||
const rct_object_entry RequiredSelectedObjects[7] =
|
const rct_object_entry RequiredSelectedObjects[7] = {
|
||||||
{
|
|
||||||
// Objects that are always required
|
// Objects that are always required
|
||||||
{ 0x00000087, { "SCGTREES" } }, // Scenery: Trees
|
{ 0x00000087, { "SCGTREES" } }, // Scenery: Trees
|
||||||
{ 0x00000087, { "SCGSHRUB" } }, // Scenery: Shrubs and Ornaments
|
{ 0x00000087, { "SCGSHRUB" } }, // Scenery: Shrubs and Ornaments
|
||||||
{ 0x00000087, { "SCGGARDN" } }, // Scenery: Gardens
|
{ 0x00000087, { "SCGGARDN" } }, // Scenery: Gardens
|
||||||
{ 0x00000087, { "SCGFENCE" } }, // Scenery: Fences and Walls
|
{ 0x00000087, { "SCGFENCE" } }, // Scenery: Fences and Walls
|
||||||
{ 0x00000087, { "SCGWALLS" } }, // Scenery: Walls and Roofs
|
{ 0x00000087, { "SCGWALLS" } }, // Scenery: Walls and Roofs
|
||||||
{ 0x00000087, { "SCGPATHX" } }, // Scenery: Signs and Items for Footpaths
|
{ 0x00000087, { "SCGPATHX" } }, // Scenery: Signs and Items for Footpaths
|
||||||
{ 0x00000085, { "TARMAC " } }, // Footpath: Tarmac
|
{ 0x00000085, { "TARMAC " } }, // Footpath: Tarmac
|
||||||
};
|
};
|
||||||
|
|
||||||
const rct_object_entry DefaultSelectedObjects[26] =
|
const rct_object_entry DefaultSelectedObjects[26] = {
|
||||||
{
|
|
||||||
// An initial default selection
|
// An initial default selection
|
||||||
{ 0x00000080, { "TWIST1 " } }, // Ride: Twist
|
{ 0x00000080, { "TWIST1 " } }, // Ride: Twist
|
||||||
{ 0x00000080, { "PTCT1 " } }, // Ride: Wooden Roller Coaster (Wooden Roller Coaster Trains)
|
{ 0x00000080, { "PTCT1 " } }, // Ride: Wooden Roller Coaster (Wooden Roller Coaster Trains)
|
||||||
{ 0x00000080, { "ZLDB " } }, // Ride: Junior Roller Coaster (Ladybird Trains)
|
{ 0x00000080, { "ZLDB " } }, // Ride: Junior Roller Coaster (Ladybird Trains)
|
||||||
{ 0x00000080, { "LFB1 " } }, // Ride: Log Flume
|
{ 0x00000080, { "LFB1 " } }, // Ride: Log Flume
|
||||||
{ 0x00000080, { "VCR " } }, // Ride: Vintage Cars
|
{ 0x00000080, { "VCR " } }, // Ride: Vintage Cars
|
||||||
{ 0x00000080, { "MGR1 " } }, // Ride: Merry-Go-Round
|
{ 0x00000080, { "MGR1 " } }, // Ride: Merry-Go-Round
|
||||||
{ 0x00000080, { "TLT1 " } }, // Ride: Restroom
|
{ 0x00000080, { "TLT1 " } }, // Ride: Restroom
|
||||||
{ 0x00000080, { "ATM1 " } }, // Ride: Cash Machine
|
{ 0x00000080, { "ATM1 " } }, // Ride: Cash Machine
|
||||||
{ 0x00000080, { "FAID1 " } }, // Ride: First Aid Room
|
{ 0x00000080, { "FAID1 " } }, // Ride: First Aid Room
|
||||||
{ 0x00000080, { "INFOK " } }, // Ride: Information Kiosk
|
{ 0x00000080, { "INFOK " } }, // Ride: Information Kiosk
|
||||||
{ 0x00000080, { "DRNKS " } }, // Ride: Drinks Stall
|
{ 0x00000080, { "DRNKS " } }, // Ride: Drinks Stall
|
||||||
{ 0x00000080, { "CNDYF " } }, // Ride: Candyfloss Stall
|
{ 0x00000080, { "CNDYF " } }, // Ride: Candyfloss Stall
|
||||||
{ 0x00000080, { "BURGB " } }, // Ride: Burger Bar
|
{ 0x00000080, { "BURGB " } }, // Ride: Burger Bar
|
||||||
{ 0x00000080, { "BALLN " } }, // Ride: Balloon Stall
|
{ 0x00000080, { "BALLN " } }, // Ride: Balloon Stall
|
||||||
{ 0x00000080, { "ARRT1 " } }, // Ride: Corkscrew Roller Coaster
|
{ 0x00000080, { "ARRT1 " } }, // Ride: Corkscrew Roller Coaster
|
||||||
{ 0x00000080, { "RBOAT " } }, // Ride: Rowing Boats
|
{ 0x00000080, { "RBOAT " } }, // Ride: Rowing Boats
|
||||||
{ 0x00000088, { "PKENT1 " } }, // Park Entrance: Traditional Park Entrance
|
{ 0x00000088, { "PKENT1 " } }, // Park Entrance: Traditional Park Entrance
|
||||||
{ 0x00000089, { "WTRCYAN " } }, // Water: Natural Water
|
{ 0x00000089, { "WTRCYAN " } }, // Water: Natural Water
|
||||||
{ 0x00000085, { "TARMACB " } }, // Footpath: Brown Tarmac Footpath
|
{ 0x00000085, { "TARMACB " } }, // Footpath: Brown Tarmac Footpath
|
||||||
{ 0x00000085, { "PATHSPCE" } }, // Footpath: Space Style Footpath
|
{ 0x00000085, { "PATHSPCE" } }, // Footpath: Space Style Footpath
|
||||||
{ 0x00000085, { "PATHDIRT" } }, // Footpath: Dirt Footpath
|
{ 0x00000085, { "PATHDIRT" } }, // Footpath: Dirt Footpath
|
||||||
{ 0x00000085, { "PATHCRZY" } }, // Footpath: Crazy Paving Footpath
|
{ 0x00000085, { "PATHCRZY" } }, // Footpath: Crazy Paving Footpath
|
||||||
{ 0x00000085, { "PATHASH " } }, // Footpath: Ash Footpath
|
{ 0x00000085, { "PATHASH " } }, // Footpath: Ash Footpath
|
||||||
|
|
||||||
// The following are for all random map generation features to work out the box
|
// The following are for all random map generation features to work out the box
|
||||||
{ 0x00000087, { "SCGJUNGL" } }, // Jungle Theming
|
{ 0x00000087, { "SCGJUNGL" } }, // Jungle Theming
|
||||||
{ 0x00000087, { "SCGSNOW " } }, // Snow and Ice Theming
|
{ 0x00000087, { "SCGSNOW " } }, // Snow and Ice Theming
|
||||||
{ 0x00000087, { "SCGWATER" } } // Water Feature Theming
|
{ 0x00000087, { "SCGWATER" } } // Water Feature Theming
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,14 +7,15 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "EntranceObject.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
#include "../localisation/Localisation.h"
|
#include "../localisation/Localisation.h"
|
||||||
#include "EntranceObject.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
|
|
||||||
void EntranceObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void EntranceObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.scrolling_mode = stream->ReadValue<uint8_t>();
|
_legacyType.scrolling_mode = stream->ReadValue<uint8_t>();
|
||||||
|
@ -48,18 +49,18 @@ void EntranceObject::Unload()
|
||||||
_legacyType.image_id = 0;
|
_legacyType.image_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntranceObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void EntranceObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
int32_t y = height / 2;
|
int32_t y = height / 2;
|
||||||
|
|
||||||
uint32_t imageId = _legacyType.image_id;
|
uint32_t imageId = _legacyType.image_id;
|
||||||
gfx_draw_sprite(dpi, imageId + 1, x - 32, y + 14, 0);
|
gfx_draw_sprite(dpi, imageId + 1, x - 32, y + 14, 0);
|
||||||
gfx_draw_sprite(dpi, imageId + 0, x + 0, y + 28, 0);
|
gfx_draw_sprite(dpi, imageId + 0, x + 0, y + 28, 0);
|
||||||
gfx_draw_sprite(dpi, imageId + 2, x + 32, y + 44, 0);
|
gfx_draw_sprite(dpi, imageId + 2, x + 32, y + 44, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntranceObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void EntranceObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
|
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Object.h"
|
|
||||||
|
|
||||||
#include "../world/Entrance.h"
|
#include "../world/Entrance.h"
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
class EntranceObject final : public Object
|
class EntranceObject final : public Object
|
||||||
{
|
{
|
||||||
|
@ -19,14 +18,20 @@ private:
|
||||||
rct_entrance_type _legacyType = {};
|
rct_entrance_type _legacyType = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EntranceObject(const rct_object_entry &entry) : Object(entry) { }
|
explicit EntranceObject(const rct_object_entry& entry)
|
||||||
|
: Object(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,18 +7,20 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <unordered_map>
|
#include "FootpathItemObject.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
#include "../interface/Cursors.h"
|
#include "../interface/Cursors.h"
|
||||||
#include "../localisation/Localisation.h"
|
#include "../localisation/Localisation.h"
|
||||||
#include "../object/Object.h"
|
#include "../object/Object.h"
|
||||||
#include "../object/ObjectRepository.h"
|
#include "../object/ObjectRepository.h"
|
||||||
#include "ObjectList.h"
|
|
||||||
#include "FootpathItemObject.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
|
#include "ObjectList.h"
|
||||||
|
|
||||||
void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
#include <unordered_map>
|
||||||
|
|
||||||
|
void FootpathItemObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.path_bit.flags = stream->ReadValue<uint16_t>();
|
_legacyType.path_bit.flags = stream->ReadValue<uint16_t>();
|
||||||
|
@ -50,9 +52,8 @@ void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stre
|
||||||
if (item != nullptr)
|
if (item != nullptr)
|
||||||
{
|
{
|
||||||
auto sourceGame = object_entry_get_source_game(&item->ObjectEntry);
|
auto sourceGame = object_entry_get_source_game(&item->ObjectEntry);
|
||||||
if (sourceGame == OBJECT_SOURCE_WACKY_WORLDS ||
|
if (sourceGame == OBJECT_SOURCE_WACKY_WORLDS || sourceGame == OBJECT_SOURCE_TIME_TWISTER
|
||||||
sourceGame == OBJECT_SOURCE_TIME_TWISTER ||
|
|| sourceGame == OBJECT_SOURCE_CUSTOM)
|
||||||
sourceGame == OBJECT_SOURCE_CUSTOM)
|
|
||||||
{
|
{
|
||||||
auto scgPathX = Object::GetScgPathXHeader();
|
auto scgPathX = Object::GetScgPathXHeader();
|
||||||
SetPrimarySceneryGroup(&scgPathX);
|
SetPrimarySceneryGroup(&scgPathX);
|
||||||
|
@ -78,40 +79,46 @@ void FootpathItemObject::Unload()
|
||||||
_legacyType.image = 0;
|
_legacyType.image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FootpathItemObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void FootpathItemObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
int32_t y = height / 2;
|
int32_t y = height / 2;
|
||||||
gfx_draw_sprite(dpi, _legacyType.image, x - 22, y - 24, 0);
|
gfx_draw_sprite(dpi, _legacyType.image, x - 22, y - 24, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ParseDrawType(const std::string &s)
|
static uint8_t ParseDrawType(const std::string& s)
|
||||||
{
|
{
|
||||||
if (s == "lamp") return PATH_BIT_DRAW_TYPE_LIGHTS;
|
if (s == "lamp")
|
||||||
if (s == "bin") return PATH_BIT_DRAW_TYPE_BINS;
|
return PATH_BIT_DRAW_TYPE_LIGHTS;
|
||||||
if (s == "bench") return PATH_BIT_DRAW_TYPE_BENCHES;
|
if (s == "bin")
|
||||||
if (s == "fountain") return PATH_BIT_DRAW_TYPE_JUMPING_FOUNTAINS;
|
return PATH_BIT_DRAW_TYPE_BINS;
|
||||||
|
if (s == "bench")
|
||||||
|
return PATH_BIT_DRAW_TYPE_BENCHES;
|
||||||
|
if (s == "fountain")
|
||||||
|
return PATH_BIT_DRAW_TYPE_JUMPING_FOUNTAINS;
|
||||||
return PATH_BIT_DRAW_TYPE_LIGHTS;
|
return PATH_BIT_DRAW_TYPE_LIGHTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void FootpathItemObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
_legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(properties, "renderAs"));
|
_legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(properties, "renderAs"));
|
||||||
_legacyType.path_bit.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_LAMPPOST_DOWN);
|
_legacyType.path_bit.tool_id
|
||||||
|
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_LAMPPOST_DOWN);
|
||||||
_legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price"));
|
_legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price"));
|
||||||
|
|
||||||
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
|
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
_legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, {
|
_legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags<uint16_t>(
|
||||||
{ "isBin", PATH_BIT_FLAG_IS_BIN },
|
properties,
|
||||||
{ "isBench", PATH_BIT_FLAG_IS_BENCH },
|
{ { "isBin", PATH_BIT_FLAG_IS_BIN },
|
||||||
{ "isBreakable", PATH_BIT_FLAG_BREAKABLE },
|
{ "isBench", PATH_BIT_FLAG_IS_BENCH },
|
||||||
{ "isLamp", PATH_BIT_FLAG_LAMP },
|
{ "isBreakable", PATH_BIT_FLAG_BREAKABLE },
|
||||||
{ "isJumpingFountainWater", PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER },
|
{ "isLamp", PATH_BIT_FLAG_LAMP },
|
||||||
{ "isJumpingFountainSnow", PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW },
|
{ "isJumpingFountainWater", PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER },
|
||||||
{ "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }});
|
{ "isJumpingFountainSnow", PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW },
|
||||||
|
{ "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN } });
|
||||||
|
|
||||||
// HACK To avoid 'negated' properties in JSON, handle these separately until
|
// HACK To avoid 'negated' properties in JSON, handle these separately until
|
||||||
// flags are inverted in this code base.
|
// flags are inverted in this code base.
|
||||||
|
|
|
@ -9,24 +9,29 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SceneryObject.h"
|
|
||||||
|
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
|
#include "SceneryObject.h"
|
||||||
|
|
||||||
class FootpathItemObject final : public SceneryObject
|
class FootpathItemObject final : public SceneryObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_scenery_entry _legacyType = {};
|
rct_scenery_entry _legacyType = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FootpathItemObject(const rct_object_entry &entry) : SceneryObject(entry) { }
|
explicit FootpathItemObject(const rct_object_entry& entry)
|
||||||
|
: SceneryObject(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,14 +7,15 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "FootpathObject.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../world/Footpath.h"
|
#include "../world/Footpath.h"
|
||||||
#include "FootpathObject.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
|
|
||||||
void FootpathObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void FootpathObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(10, STREAM_SEEK_CURRENT);
|
stream->Seek(10, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.support_type = stream->ReadValue<uint8_t>();
|
_legacyType.support_type = stream->ReadValue<uint8_t>();
|
||||||
|
@ -49,7 +50,7 @@ void FootpathObject::Unload()
|
||||||
_legacyType.image = 0;
|
_legacyType.image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FootpathObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void FootpathObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
int32_t y = height / 2;
|
int32_t y = height / 2;
|
||||||
|
@ -57,23 +58,26 @@ void FootpathObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t
|
||||||
gfx_draw_sprite(dpi, _legacyType.image + 72, x + 4, y - 17, 0);
|
gfx_draw_sprite(dpi, _legacyType.image + 72, x + 4, y - 17, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ParseSupportType(const std::string &s)
|
static uint8_t ParseSupportType(const std::string& s)
|
||||||
{
|
{
|
||||||
if (s == "pole") return FOOTPATH_ENTRY_SUPPORT_TYPE_POLE;
|
if (s == "pole")
|
||||||
else /* if (s == "box") */ return FOOTPATH_ENTRY_SUPPORT_TYPE_BOX;
|
return FOOTPATH_ENTRY_SUPPORT_TYPE_POLE;
|
||||||
|
else /* if (s == "box") */
|
||||||
|
return FOOTPATH_ENTRY_SUPPORT_TYPE_BOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void FootpathObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
_legacyType.support_type = ParseSupportType(ObjectJsonHelpers::GetString(json_object_get(properties, "supportType")));
|
_legacyType.support_type = ParseSupportType(ObjectJsonHelpers::GetString(json_object_get(properties, "supportType")));
|
||||||
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
|
_legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode"));
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
|
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
|
||||||
{ "hasSupportImages", FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE },
|
properties,
|
||||||
{ "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE },
|
{ { "hasSupportImages", FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE },
|
||||||
{ "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } });
|
{ "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE },
|
||||||
|
{ "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } });
|
||||||
|
|
||||||
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
|
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
|
||||||
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Object.h"
|
|
||||||
|
|
||||||
#include "../world/Footpath.h"
|
#include "../world/Footpath.h"
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
class FootpathObject final : public Object
|
class FootpathObject final : public Object
|
||||||
{
|
{
|
||||||
|
@ -19,14 +18,20 @@ private:
|
||||||
rct_footpath_entry _legacyType = {};
|
rct_footpath_entry _legacyType = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FootpathObject(const rct_object_entry &entry) : Object(entry) { }
|
explicit FootpathObject(const rct_object_entry& entry)
|
||||||
|
: Object(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,26 +7,28 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "ImageTable.h"
|
||||||
|
|
||||||
|
#include "../OpenRCT2.h"
|
||||||
|
#include "../core/IStream.hpp"
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "../core/IStream.hpp"
|
|
||||||
#include "../OpenRCT2.h"
|
|
||||||
#include "ImageTable.h"
|
|
||||||
#include "Object.h"
|
|
||||||
|
|
||||||
ImageTable::~ImageTable()
|
ImageTable::~ImageTable()
|
||||||
{
|
{
|
||||||
if (_data == nullptr)
|
if (_data == nullptr)
|
||||||
{
|
{
|
||||||
for (auto &entry : _entries)
|
for (auto& entry : _entries)
|
||||||
{
|
{
|
||||||
delete [] entry.offset;
|
delete[] entry.offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageTable::Read(IReadObjectContext * context, IStream * stream)
|
void ImageTable::Read(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
if (gOpenRCT2NoGraphics)
|
if (gOpenRCT2NoGraphics)
|
||||||
{
|
{
|
||||||
|
@ -88,14 +90,14 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream)
|
||||||
_data = std::move(data);
|
_data = std::move(data);
|
||||||
_entries.insert(_entries.end(), newEntries.begin(), newEntries.end());
|
_entries.insert(_entries.end(), newEntries.begin(), newEntries.end());
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
context->LogError(OBJECT_ERROR_BAD_IMAGE_TABLE, "Bad image table.");
|
context->LogError(OBJECT_ERROR_BAD_IMAGE_TABLE, "Bad image table.");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageTable::AddImage(const rct_g1_element * g1)
|
void ImageTable::AddImage(const rct_g1_element* g1)
|
||||||
{
|
{
|
||||||
rct_g1_element newg1 = *g1;
|
rct_g1_element newg1 = *g1;
|
||||||
auto length = g1_calculate_data_size(g1);
|
auto length = g1_calculate_data_size(g1);
|
||||||
|
|
|
@ -9,28 +9,35 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
interface IReadObjectContext;
|
interface IReadObjectContext;
|
||||||
interface IStream;
|
interface IStream;
|
||||||
|
|
||||||
class ImageTable
|
class ImageTable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<uint8_t[]> _data;
|
std::unique_ptr<uint8_t[]> _data;
|
||||||
std::vector<rct_g1_element> _entries;
|
std::vector<rct_g1_element> _entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImageTable() = default;
|
ImageTable() = default;
|
||||||
ImageTable(const ImageTable &) = delete;
|
ImageTable(const ImageTable&) = delete;
|
||||||
ImageTable & operator=(const ImageTable &) = delete;
|
ImageTable& operator=(const ImageTable&) = delete;
|
||||||
~ImageTable();
|
~ImageTable();
|
||||||
|
|
||||||
void Read(IReadObjectContext * context, IStream * stream);
|
void Read(IReadObjectContext* context, IStream* stream);
|
||||||
const rct_g1_element * GetImages() const { return _entries.data(); }
|
const rct_g1_element* GetImages() const
|
||||||
uint32_t GetCount() const { return (uint32_t)_entries.size(); }
|
{
|
||||||
void AddImage(const rct_g1_element * g1);
|
return _entries.data();
|
||||||
|
}
|
||||||
|
uint32_t GetCount() const
|
||||||
|
{
|
||||||
|
return (uint32_t)_entries.size();
|
||||||
|
}
|
||||||
|
void AddImage(const rct_g1_element* g1);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
#pragma warning(disable : 4706) // assignment within conditional expression
|
#pragma warning(disable : 4706) // assignment within conditional expression
|
||||||
|
|
||||||
#include <algorithm>
|
#include "LargeSceneryObject.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../core/Memory.hpp"
|
#include "../core/Memory.hpp"
|
||||||
#include "../core/Util.hpp"
|
#include "../core/Util.hpp"
|
||||||
|
@ -17,10 +18,11 @@
|
||||||
#include "../interface/Cursors.h"
|
#include "../interface/Cursors.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../world/Location.hpp"
|
#include "../world/Location.hpp"
|
||||||
#include "LargeSceneryObject.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
|
|
||||||
void LargeSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
#include <algorithm>
|
||||||
|
|
||||||
|
void LargeSceneryObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.large_scenery.tool_id = stream->ReadValue<uint8_t>();
|
_legacyType.large_scenery.tool_id = stream->ReadValue<uint8_t>();
|
||||||
|
@ -97,7 +99,7 @@ void LargeSceneryObject::Unload()
|
||||||
_legacyType.image = 0;
|
_legacyType.image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LargeSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void LargeSceneryObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
int32_t y = (height / 2) - 39;
|
int32_t y = (height / 2) - 39;
|
||||||
|
@ -106,7 +108,7 @@ void LargeSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int
|
||||||
gfx_draw_sprite(dpi, imageId, x, y, 0);
|
gfx_draw_sprite(dpi, imageId, x, y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadTiles(IStream * stream)
|
std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadTiles(IStream* stream)
|
||||||
{
|
{
|
||||||
auto tiles = std::vector<rct_large_scenery_tile>();
|
auto tiles = std::vector<rct_large_scenery_tile>();
|
||||||
while (stream->ReadValue<uint16_t>() != 0xFFFF)
|
while (stream->ReadValue<uint16_t>() != 0xFFFF)
|
||||||
|
@ -119,25 +121,25 @@ std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadTiles(IStream * stre
|
||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LargeSceneryObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void LargeSceneryObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
|
|
||||||
_legacyType.large_scenery.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN);
|
_legacyType.large_scenery.tool_id
|
||||||
|
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN);
|
||||||
_legacyType.large_scenery.price = json_integer_value(json_object_get(properties, "price"));
|
_legacyType.large_scenery.price = json_integer_value(json_object_get(properties, "price"));
|
||||||
_legacyType.large_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
|
_legacyType.large_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
|
||||||
|
|
||||||
auto jScrollingMode = json_object_get(properties, "scrollingMode");
|
auto jScrollingMode = json_object_get(properties, "scrollingMode");
|
||||||
_legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ?
|
_legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ? json_integer_value(jScrollingMode) : -1;
|
||||||
json_integer_value(jScrollingMode) :
|
|
||||||
-1;
|
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
_legacyType.large_scenery.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
|
_legacyType.large_scenery.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
|
||||||
{ "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
|
properties,
|
||||||
{ "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
|
{ { "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
|
||||||
{ "isAnimated", LARGE_SCENERY_FLAG_ANIMATED },
|
{ "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
|
||||||
{ "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC } });
|
{ "isAnimated", LARGE_SCENERY_FLAG_ANIMATED },
|
||||||
|
{ "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC } });
|
||||||
|
|
||||||
// Tiles
|
// Tiles
|
||||||
auto jTiles = json_object_get(properties, "tiles");
|
auto jTiles = json_object_get(properties, "tiles");
|
||||||
|
@ -160,11 +162,11 @@ void LargeSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r
|
||||||
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadJsonTiles(const json_t * jTiles)
|
std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadJsonTiles(const json_t* jTiles)
|
||||||
{
|
{
|
||||||
std::vector<rct_large_scenery_tile> tiles;
|
std::vector<rct_large_scenery_tile> tiles;
|
||||||
size_t index;
|
size_t index;
|
||||||
const json_t * jTile;
|
const json_t* jTile;
|
||||||
json_array_foreach(jTiles, index, jTile)
|
json_array_foreach(jTiles, index, jTile)
|
||||||
{
|
{
|
||||||
rct_large_scenery_tile tile = {};
|
rct_large_scenery_tile tile = {};
|
||||||
|
@ -203,7 +205,7 @@ std::vector<rct_large_scenery_tile> LargeSceneryObject::ReadJsonTiles(const json
|
||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const json_t * j3dFont)
|
std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const json_t* j3dFont)
|
||||||
{
|
{
|
||||||
auto font = std::make_unique<rct_large_scenery_text>();
|
auto font = std::make_unique<rct_large_scenery_text>();
|
||||||
|
|
||||||
|
@ -217,9 +219,8 @@ std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const
|
||||||
|
|
||||||
font->max_width = json_integer_value(json_object_get(j3dFont, "maxWidth"));
|
font->max_width = json_integer_value(json_object_get(j3dFont, "maxWidth"));
|
||||||
font->num_images = json_integer_value(json_object_get(j3dFont, "numImages"));
|
font->num_images = json_integer_value(json_object_get(j3dFont, "numImages"));
|
||||||
font->flags = ObjectJsonHelpers::GetFlags<uint8_t>(j3dFont, {
|
font->flags = ObjectJsonHelpers::GetFlags<uint8_t>(
|
||||||
{ "isVertical", LARGE_SCENERY_TEXT_FLAG_VERTICAL },
|
j3dFont, { { "isVertical", LARGE_SCENERY_TEXT_FLAG_VERTICAL }, { "isTwoLine", LARGE_SCENERY_TEXT_FLAG_TWO_LINE } });
|
||||||
{ "isTwoLine", LARGE_SCENERY_TEXT_FLAG_TWO_LINE } });
|
|
||||||
|
|
||||||
auto jGlyphs = json_object_get(j3dFont, "glyphs");
|
auto jGlyphs = json_object_get(j3dFont, "glyphs");
|
||||||
if (jGlyphs != nullptr)
|
if (jGlyphs != nullptr)
|
||||||
|
@ -232,11 +233,11 @@ std::unique_ptr<rct_large_scenery_text> LargeSceneryObject::ReadJson3dFont(const
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t * jOffsets)
|
std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t* jOffsets)
|
||||||
{
|
{
|
||||||
std::vector<LocationXY16> offsets;
|
std::vector<LocationXY16> offsets;
|
||||||
size_t index;
|
size_t index;
|
||||||
const json_t * jOffset;
|
const json_t* jOffset;
|
||||||
json_array_foreach(jOffsets, index, jOffset)
|
json_array_foreach(jOffsets, index, jOffset)
|
||||||
{
|
{
|
||||||
LocationXY16 offset = {};
|
LocationXY16 offset = {};
|
||||||
|
@ -247,11 +248,11 @@ std::vector<LocationXY16> LargeSceneryObject::ReadJsonOffsets(const json_t * jOf
|
||||||
return offsets;
|
return offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rct_large_scenery_text_glyph> LargeSceneryObject::ReadJsonGlyphs(const json_t * jGlpyhs)
|
std::vector<rct_large_scenery_text_glyph> LargeSceneryObject::ReadJsonGlyphs(const json_t* jGlpyhs)
|
||||||
{
|
{
|
||||||
std::vector<rct_large_scenery_text_glyph> glyphs;
|
std::vector<rct_large_scenery_text_glyph> glyphs;
|
||||||
size_t index;
|
size_t index;
|
||||||
const json_t * jGlyph;
|
const json_t* jGlyph;
|
||||||
json_array_foreach(jGlpyhs, index, jGlyph)
|
json_array_foreach(jGlpyhs, index, jGlyph)
|
||||||
{
|
{
|
||||||
rct_large_scenery_text_glyph glyph;
|
rct_large_scenery_text_glyph glyph;
|
||||||
|
|
|
@ -9,36 +9,43 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include "../world/Location.hpp"
|
#include "../world/Location.hpp"
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
#include "SceneryObject.h"
|
#include "SceneryObject.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class LargeSceneryObject final : public SceneryObject
|
class LargeSceneryObject final : public SceneryObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_scenery_entry _legacyType = {};
|
rct_scenery_entry _legacyType = {};
|
||||||
uint32_t _baseImageId = 0;
|
uint32_t _baseImageId = 0;
|
||||||
std::vector<rct_large_scenery_tile> _tiles;
|
std::vector<rct_large_scenery_tile> _tiles;
|
||||||
std::unique_ptr<rct_large_scenery_text> _3dFont;
|
std::unique_ptr<rct_large_scenery_text> _3dFont;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LargeSceneryObject(const rct_object_entry &entry) : SceneryObject(entry) { }
|
explicit LargeSceneryObject(const rct_object_entry& entry)
|
||||||
|
: SceneryObject(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<rct_large_scenery_tile> ReadTiles(IStream * stream);
|
static std::vector<rct_large_scenery_tile> ReadTiles(IStream* stream);
|
||||||
static std::vector<rct_large_scenery_tile> ReadJsonTiles(const json_t * jTiles);
|
static std::vector<rct_large_scenery_tile> ReadJsonTiles(const json_t* jTiles);
|
||||||
static std::unique_ptr<rct_large_scenery_text> ReadJson3dFont(const json_t * j3dFont);
|
static std::unique_ptr<rct_large_scenery_text> ReadJson3dFont(const json_t* j3dFont);
|
||||||
static std::vector<LocationXY16> ReadJsonOffsets(const json_t * jOffsets);
|
static std::vector<LocationXY16> ReadJsonOffsets(const json_t* jOffsets);
|
||||||
static std::vector<rct_large_scenery_text_glyph> ReadJsonGlyphs(const json_t * jGlpyhs);
|
static std::vector<rct_large_scenery_text_glyph> ReadJsonGlyphs(const json_t* jGlpyhs);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,15 +7,17 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <algorithm>
|
#include "Object.h"
|
||||||
|
|
||||||
#include "../core/Memory.hpp"
|
#include "../core/Memory.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../localisation/StringIds.h"
|
#include "../localisation/StringIds.h"
|
||||||
#include "Object.h"
|
|
||||||
#include "ObjectLimits.h"
|
#include "ObjectLimits.h"
|
||||||
|
|
||||||
Object::Object(const rct_object_entry &entry)
|
#include <algorithm>
|
||||||
|
|
||||||
|
Object::Object(const rct_object_entry& entry)
|
||||||
{
|
{
|
||||||
_objectEntry = entry;
|
_objectEntry = entry;
|
||||||
|
|
||||||
|
@ -48,10 +50,10 @@ Object::~Object()
|
||||||
|
|
||||||
std::string Object::GetOverrideString(uint8_t index) const
|
std::string Object::GetOverrideString(uint8_t index) const
|
||||||
{
|
{
|
||||||
const char * identifier = GetIdentifier();
|
const char* identifier = GetIdentifier();
|
||||||
rct_string_id stringId = language_get_object_override_string_id(identifier, index);
|
rct_string_id stringId = language_get_object_override_string_id(identifier, index);
|
||||||
|
|
||||||
const utf8 * result = nullptr;
|
const utf8* result = nullptr;
|
||||||
if (stringId != STR_NONE)
|
if (stringId != STR_NONE)
|
||||||
{
|
{
|
||||||
result = language_get_string(stringId);
|
result = language_get_string(stringId);
|
||||||
|
@ -102,8 +104,7 @@ void Object::SetSourceGame(const uint8_t sourceGame)
|
||||||
|
|
||||||
bool Object::IsRCT1Object()
|
bool Object::IsRCT1Object()
|
||||||
{
|
{
|
||||||
static const char _rct1Objects[][9] =
|
static const char _rct1Objects[][9] = {
|
||||||
{
|
|
||||||
"CLIFT1 ",
|
"CLIFT1 ",
|
||||||
"MONO1 ",
|
"MONO1 ",
|
||||||
"MONO2 ",
|
"MONO2 ",
|
||||||
|
@ -405,8 +406,7 @@ bool Object::IsRCT1Object()
|
||||||
|
|
||||||
bool Object::IsAAObject()
|
bool Object::IsAAObject()
|
||||||
{
|
{
|
||||||
static const char _aaObjects[][9] =
|
static const char _aaObjects[][9] = {
|
||||||
{
|
|
||||||
// Rides / vehicles / stalls
|
// Rides / vehicles / stalls
|
||||||
"BMFL ",
|
"BMFL ",
|
||||||
"BMRB ",
|
"BMRB ",
|
||||||
|
@ -521,8 +521,7 @@ bool Object::IsAAObject()
|
||||||
|
|
||||||
bool Object::IsLLObject()
|
bool Object::IsLLObject()
|
||||||
{
|
{
|
||||||
static const char _llObjects[][9] =
|
static const char _llObjects[][9] = {
|
||||||
{
|
|
||||||
// Rides / vehicles / stalls
|
// Rides / vehicles / stalls
|
||||||
"AML1 ",
|
"AML1 ",
|
||||||
"ARRT2 ",
|
"ARRT2 ",
|
||||||
|
@ -650,8 +649,7 @@ bool Object::IsLLObject()
|
||||||
|
|
||||||
bool Object::IsOpenRCT2OfficialObject()
|
bool Object::IsOpenRCT2OfficialObject()
|
||||||
{
|
{
|
||||||
static const char _openRCT2OfficialObjects[][9] =
|
static const char _openRCT2OfficialObjects[][9] = {
|
||||||
{
|
|
||||||
// Offical extended scenery set
|
// Offical extended scenery set
|
||||||
"XXBBBR01",
|
"XXBBBR01",
|
||||||
"TTRFTL02",
|
"TTRFTL02",
|
||||||
|
@ -698,10 +696,9 @@ bool Object::IsOpenRCT2OfficialObject()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __WARN_SUGGEST_FINAL_METHODS__
|
#ifdef __WARN_SUGGEST_FINAL_METHODS__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
|
#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string Object::GetName() const
|
std::string Object::GetName() const
|
||||||
|
@ -715,5 +712,5 @@ std::string Object::GetName(int32_t language) const
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __WARN_SUGGEST_FINAL_METHODS__
|
#ifdef __WARN_SUGGEST_FINAL_METHODS__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include <vector>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../core/Json.hpp"
|
#include "../core/Json.hpp"
|
||||||
#include "ImageTable.h"
|
#include "ImageTable.h"
|
||||||
#include "StringTable.h"
|
#include "StringTable.h"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// First 0xF of rct_object_entry->flags
|
// First 0xF of rct_object_entry->flags
|
||||||
enum OBJECT_TYPE
|
enum OBJECT_TYPE
|
||||||
{
|
{
|
||||||
|
@ -30,7 +31,7 @@ enum OBJECT_TYPE
|
||||||
OBJECT_TYPE_PARK_ENTRANCE,
|
OBJECT_TYPE_PARK_ENTRANCE,
|
||||||
OBJECT_TYPE_WATER,
|
OBJECT_TYPE_WATER,
|
||||||
OBJECT_TYPE_SCENARIO_TEXT,
|
OBJECT_TYPE_SCENARIO_TEXT,
|
||||||
|
|
||||||
OBJECT_TYPE_COUNT
|
OBJECT_TYPE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,20 +69,24 @@ enum OBJECT_SOURCE_GAME
|
||||||
* Object entry structure.
|
* Object entry structure.
|
||||||
* size: 0x10
|
* size: 0x10
|
||||||
*/
|
*/
|
||||||
struct rct_object_entry {
|
struct rct_object_entry
|
||||||
union {
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
uint8_t end_flag; // needed not to read past allocated buffer.
|
uint8_t end_flag; // needed not to read past allocated buffer.
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
};
|
};
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
char nameWOC[12];
|
char nameWOC[12];
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
char name[8];
|
char name[8];
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetName(const char * value)
|
void SetName(const char* value)
|
||||||
{
|
{
|
||||||
auto src = value;
|
auto src = value;
|
||||||
for (size_t i = 0; i < sizeof(name); i++)
|
for (size_t i = 0; i < sizeof(name); i++)
|
||||||
|
@ -97,22 +102,26 @@ struct rct_object_entry {
|
||||||
};
|
};
|
||||||
assert_struct_size(rct_object_entry, 0x10);
|
assert_struct_size(rct_object_entry, 0x10);
|
||||||
|
|
||||||
struct rct_object_entry_group {
|
struct rct_object_entry_group
|
||||||
void **chunks;
|
{
|
||||||
rct_object_entry *entries;
|
void** chunks;
|
||||||
|
rct_object_entry* entries;
|
||||||
};
|
};
|
||||||
#ifdef PLATFORM_32BIT
|
#ifdef PLATFORM_32BIT
|
||||||
assert_struct_size(rct_object_entry_group, 8);
|
assert_struct_size(rct_object_entry_group, 8);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct rct_ride_filters {
|
struct rct_ride_filters
|
||||||
|
{
|
||||||
uint8_t category[2];
|
uint8_t category[2];
|
||||||
uint8_t ride_type;
|
uint8_t ride_type;
|
||||||
};
|
};
|
||||||
assert_struct_size(rct_ride_filters, 3);
|
assert_struct_size(rct_ride_filters, 3);
|
||||||
|
|
||||||
struct rct_object_filters {
|
struct rct_object_filters
|
||||||
union {
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
rct_ride_filters ride;
|
rct_ride_filters ride;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -121,8 +130,8 @@ assert_struct_size(rct_object_filters, 3);
|
||||||
|
|
||||||
interface IObjectRepository;
|
interface IObjectRepository;
|
||||||
interface IStream;
|
interface IStream;
|
||||||
struct ObjectRepositoryItem;
|
struct ObjectRepositoryItem;
|
||||||
struct rct_drawpixelinfo;
|
struct rct_drawpixelinfo;
|
||||||
|
|
||||||
interface IReadObjectContext
|
interface IReadObjectContext
|
||||||
{
|
{
|
||||||
|
@ -132,69 +141,95 @@ interface IReadObjectContext
|
||||||
virtual bool ShouldLoadImages() abstract;
|
virtual bool ShouldLoadImages() abstract;
|
||||||
virtual std::vector<uint8_t> GetData(const std::string_view& path) abstract;
|
virtual std::vector<uint8_t> GetData(const std::string_view& path) abstract;
|
||||||
|
|
||||||
virtual void LogWarning(uint32_t code, const utf8 * text) abstract;
|
virtual void LogWarning(uint32_t code, const utf8* text) abstract;
|
||||||
virtual void LogError(uint32_t code, const utf8 * text) abstract;
|
virtual void LogError(uint32_t code, const utf8* text) abstract;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __WARN_SUGGEST_FINAL_TYPES__
|
#ifdef __WARN_SUGGEST_FINAL_TYPES__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wsuggest-final-types"
|
#pragma GCC diagnostic ignored "-Wsuggest-final-types"
|
||||||
#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
|
#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
|
||||||
#endif
|
#endif
|
||||||
class Object
|
class Object
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
char * _identifier;
|
char* _identifier;
|
||||||
rct_object_entry _objectEntry{};
|
rct_object_entry _objectEntry{};
|
||||||
StringTable _stringTable;
|
StringTable _stringTable;
|
||||||
ImageTable _imageTable;
|
ImageTable _imageTable;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StringTable & GetStringTable() { return _stringTable; }
|
StringTable& GetStringTable()
|
||||||
const StringTable & GetStringTable() const { return _stringTable; }
|
{
|
||||||
ImageTable & GetImageTable() { return _imageTable; }
|
return _stringTable;
|
||||||
|
}
|
||||||
|
const StringTable& GetStringTable() const
|
||||||
|
{
|
||||||
|
return _stringTable;
|
||||||
|
}
|
||||||
|
ImageTable& GetImageTable()
|
||||||
|
{
|
||||||
|
return _imageTable;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetOverrideString(uint8_t index) const;
|
std::string GetOverrideString(uint8_t index) const;
|
||||||
std::string GetString(uint8_t index) const;
|
std::string GetString(uint8_t index) const;
|
||||||
std::string GetString(int32_t language, uint8_t index) const;
|
std::string GetString(int32_t language, uint8_t index) const;
|
||||||
|
|
||||||
void SetSourceGame(const uint8_t sourceGame);
|
void SetSourceGame(const uint8_t sourceGame);
|
||||||
bool IsRCT1Object();
|
bool IsRCT1Object();
|
||||||
bool IsAAObject();
|
bool IsAAObject();
|
||||||
bool IsLLObject();
|
bool IsLLObject();
|
||||||
bool IsOpenRCT2OfficialObject();
|
bool IsOpenRCT2OfficialObject();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Object(const rct_object_entry &entry);
|
explicit Object(const rct_object_entry& entry);
|
||||||
virtual ~Object();
|
virtual ~Object();
|
||||||
|
|
||||||
// Legacy data structures
|
// Legacy data structures
|
||||||
const char * GetIdentifier() const { return _identifier; }
|
const char* GetIdentifier() const
|
||||||
const rct_object_entry * GetObjectEntry() const { return &_objectEntry; }
|
{
|
||||||
virtual void * GetLegacyData() abstract;
|
return _identifier;
|
||||||
|
}
|
||||||
|
const rct_object_entry* GetObjectEntry() const
|
||||||
|
{
|
||||||
|
return &_objectEntry;
|
||||||
|
}
|
||||||
|
virtual void* GetLegacyData() abstract;
|
||||||
|
|
||||||
virtual void ReadJson(IReadObjectContext * /*context*/, const json_t * /*root*/) { }
|
virtual void ReadJson(IReadObjectContext* /*context*/, const json_t* /*root*/)
|
||||||
virtual void ReadLegacy(IReadObjectContext * context, IStream * stream) abstract;
|
{
|
||||||
|
}
|
||||||
|
virtual void ReadLegacy(IReadObjectContext* context, IStream* stream) abstract;
|
||||||
virtual void Load() abstract;
|
virtual void Load() abstract;
|
||||||
virtual void Unload() abstract;
|
virtual void Unload() abstract;
|
||||||
|
|
||||||
virtual void DrawPreview(rct_drawpixelinfo * /*dpi*/, int32_t /*width*/, int32_t /*height*/) const { }
|
virtual void DrawPreview(rct_drawpixelinfo* /*dpi*/, int32_t /*width*/, int32_t /*height*/) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual uint8_t GetObjectType() const final { return _objectEntry.flags & 0x0F; }
|
virtual uint8_t GetObjectType() const final
|
||||||
virtual std::string GetName() const;
|
{
|
||||||
virtual std::string GetName(int32_t language) const;
|
return _objectEntry.flags & 0x0F;
|
||||||
|
}
|
||||||
|
virtual std::string GetName() const;
|
||||||
|
virtual std::string GetName(int32_t language) const;
|
||||||
|
|
||||||
virtual void SetRepositoryItem(ObjectRepositoryItem * /*item*/) const { }
|
virtual void SetRepositoryItem(ObjectRepositoryItem* /*item*/) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const ImageTable & GetImageTable() const { return _imageTable; }
|
const ImageTable& GetImageTable() const
|
||||||
|
{
|
||||||
|
return _imageTable;
|
||||||
|
}
|
||||||
|
|
||||||
rct_object_entry GetScgWallsHeader();
|
rct_object_entry GetScgWallsHeader();
|
||||||
rct_object_entry GetScgPathXHeader();
|
rct_object_entry GetScgPathXHeader();
|
||||||
rct_object_entry CreateHeader(const char name[9], uint32_t flags, uint32_t checksum);
|
rct_object_entry CreateHeader(const char name[9], uint32_t flags, uint32_t checksum);
|
||||||
|
|
||||||
};
|
};
|
||||||
#ifdef __WARN_SUGGEST_FINAL_TYPES__
|
#ifdef __WARN_SUGGEST_FINAL_TYPES__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum OBJECT_ERROR : uint32_t
|
enum OBJECT_ERROR : uint32_t
|
||||||
|
@ -213,15 +248,15 @@ extern int32_t object_entry_group_encoding[];
|
||||||
|
|
||||||
void object_list_load();
|
void object_list_load();
|
||||||
|
|
||||||
bool object_entry_is_empty(const rct_object_entry *entry);
|
bool object_entry_is_empty(const rct_object_entry* entry);
|
||||||
bool object_entry_compare(const rct_object_entry *a, const rct_object_entry *b);
|
bool object_entry_compare(const rct_object_entry* a, const rct_object_entry* b);
|
||||||
int32_t object_calculate_checksum(const rct_object_entry * entry, const void * data, size_t dataLength);
|
int32_t object_calculate_checksum(const rct_object_entry* entry, const void* data, size_t dataLength);
|
||||||
bool find_object_in_entry_group(const rct_object_entry* entry, uint8_t* entry_type, uint8_t* entry_index);
|
bool find_object_in_entry_group(const rct_object_entry* entry, uint8_t* entry_type, uint8_t* entry_index);
|
||||||
void object_create_identifier_name(char* string_buffer, size_t size, const rct_object_entry* object);
|
void object_create_identifier_name(char* string_buffer, size_t size, const rct_object_entry* object);
|
||||||
|
|
||||||
const rct_object_entry * object_list_find(rct_object_entry *entry);
|
const rct_object_entry* object_list_find(rct_object_entry* entry);
|
||||||
|
|
||||||
void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry);
|
void object_entry_get_name_fixed(utf8* buffer, size_t bufferSize, const rct_object_entry* entry);
|
||||||
|
|
||||||
void * object_entry_get_chunk(int32_t objectType, size_t index);
|
void* object_entry_get_chunk(int32_t objectType, size_t index);
|
||||||
const rct_object_entry * object_entry_get_entry(int32_t objectType, size_t index);
|
const rct_object_entry* object_entry_get_entry(int32_t objectType, size_t index);
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "ObjectFactory.h"
|
||||||
|
|
||||||
|
#include "../OpenRCT2.h"
|
||||||
#include "../core/Console.hpp"
|
#include "../core/Console.hpp"
|
||||||
#include "../core/File.h"
|
#include "../core/File.h"
|
||||||
#include "../core/FileStream.hpp"
|
#include "../core/FileStream.hpp"
|
||||||
|
@ -16,7 +19,6 @@
|
||||||
#include "../core/Path.hpp"
|
#include "../core/Path.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
#include "../core/Zip.h"
|
#include "../core/Zip.h"
|
||||||
#include "../OpenRCT2.h"
|
|
||||||
#include "../rct12/SawyerChunkReader.h"
|
#include "../rct12/SawyerChunkReader.h"
|
||||||
#include "BannerObject.h"
|
#include "BannerObject.h"
|
||||||
#include "EntranceObject.h"
|
#include "EntranceObject.h"
|
||||||
|
@ -26,7 +28,6 @@
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "ObjectLimits.h"
|
#include "ObjectLimits.h"
|
||||||
#include "ObjectList.h"
|
#include "ObjectList.h"
|
||||||
#include "ObjectFactory.h"
|
|
||||||
#include "RideObject.h"
|
#include "RideObject.h"
|
||||||
#include "SceneryGroupObject.h"
|
#include "SceneryGroupObject.h"
|
||||||
#include "SmallSceneryObject.h"
|
#include "SmallSceneryObject.h"
|
||||||
|
@ -79,27 +80,33 @@ class ReadObjectContext : public IReadObjectContext
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
IObjectRepository& _objectRepository;
|
IObjectRepository& _objectRepository;
|
||||||
const IFileDataRetriever * _fileDataRetriever;
|
const IFileDataRetriever* _fileDataRetriever;
|
||||||
|
|
||||||
std::string _objectName;
|
std::string _objectName;
|
||||||
bool _loadImages;
|
bool _loadImages;
|
||||||
std::string _basePath;
|
std::string _basePath;
|
||||||
bool _wasWarning = false;
|
bool _wasWarning = false;
|
||||||
bool _wasError = false;
|
bool _wasError = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool WasWarning() const { return _wasWarning; }
|
bool WasWarning() const
|
||||||
bool WasError() const { return _wasError; }
|
{
|
||||||
|
return _wasWarning;
|
||||||
|
}
|
||||||
|
bool WasError() const
|
||||||
|
{
|
||||||
|
return _wasError;
|
||||||
|
}
|
||||||
|
|
||||||
ReadObjectContext(
|
ReadObjectContext(
|
||||||
IObjectRepository& objectRepository,
|
IObjectRepository& objectRepository,
|
||||||
const std::string &objectName,
|
const std::string& objectName,
|
||||||
bool loadImages,
|
bool loadImages,
|
||||||
const IFileDataRetriever * fileDataRetriever)
|
const IFileDataRetriever* fileDataRetriever)
|
||||||
: _objectRepository(objectRepository),
|
: _objectRepository(objectRepository)
|
||||||
_fileDataRetriever(fileDataRetriever),
|
, _fileDataRetriever(fileDataRetriever)
|
||||||
_objectName(objectName),
|
, _objectName(objectName)
|
||||||
_loadImages(loadImages)
|
, _loadImages(loadImages)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,30 +152,31 @@ public:
|
||||||
|
|
||||||
namespace ObjectFactory
|
namespace ObjectFactory
|
||||||
{
|
{
|
||||||
static Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const IFileDataRetriever * fileRetriever);
|
static Object*
|
||||||
|
CreateObjectFromJson(IObjectRepository& objectRepository, const json_t* jRoot, const IFileDataRetriever* fileRetriever);
|
||||||
|
|
||||||
static void ReadObjectLegacy(Object * object, IReadObjectContext * context, IStream * stream)
|
static void ReadObjectLegacy(Object* object, IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
object->ReadLegacy(context, stream);
|
object->ReadLegacy(context, stream);
|
||||||
}
|
}
|
||||||
catch (const IOException &)
|
catch (const IOException&)
|
||||||
{
|
{
|
||||||
// TODO check that ex is really EOF and not some other error
|
// TODO check that ex is really EOF and not some other error
|
||||||
context->LogError(OBJECT_ERROR_UNEXPECTED_EOF, "Unexpectedly reached end of file.");
|
context->LogError(OBJECT_ERROR_UNEXPECTED_EOF, "Unexpectedly reached end of file.");
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
context->LogError(OBJECT_ERROR_UNKNOWN, nullptr);
|
context->LogError(OBJECT_ERROR_UNKNOWN, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8 * path)
|
Object* CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8* path)
|
||||||
{
|
{
|
||||||
log_verbose("CreateObjectFromLegacyFile(..., \"%s\")", path);
|
log_verbose("CreateObjectFromLegacyFile(..., \"%s\")", path);
|
||||||
|
|
||||||
Object * result = nullptr;
|
Object* result = nullptr;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto fs = FileStream(path, FILE_MODE_OPEN);
|
auto fs = FileStream(path, FILE_MODE_OPEN);
|
||||||
|
@ -192,7 +200,7 @@ namespace ObjectFactory
|
||||||
throw std::runtime_error("Object has errors");
|
throw std::runtime_error("Object has errors");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
delete result;
|
delete result;
|
||||||
result = nullptr;
|
result = nullptr;
|
||||||
|
@ -200,12 +208,13 @@ namespace ObjectFactory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * CreateObjectFromLegacyData(IObjectRepository& objectRepository, const rct_object_entry * entry, const void * data, size_t dataSize)
|
Object* CreateObjectFromLegacyData(
|
||||||
|
IObjectRepository& objectRepository, const rct_object_entry* entry, const void* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
Guard::ArgumentNotNull(entry, GUARD_LINE);
|
Guard::ArgumentNotNull(entry, GUARD_LINE);
|
||||||
Guard::ArgumentNotNull(data, GUARD_LINE);
|
Guard::ArgumentNotNull(data, GUARD_LINE);
|
||||||
|
|
||||||
Object * result = CreateObject(*entry);
|
Object* result = CreateObject(*entry);
|
||||||
if (result != nullptr)
|
if (result != nullptr)
|
||||||
{
|
{
|
||||||
utf8 objectName[DAT_NAME_LENGTH + 1];
|
utf8 objectName[DAT_NAME_LENGTH + 1];
|
||||||
|
@ -224,68 +233,79 @@ namespace ObjectFactory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * CreateObject(const rct_object_entry &entry)
|
Object* CreateObject(const rct_object_entry& entry)
|
||||||
{
|
{
|
||||||
Object * result;
|
Object* result;
|
||||||
uint8_t objectType = object_entry_get_type(&entry);
|
uint8_t objectType = object_entry_get_type(&entry);
|
||||||
switch (objectType) {
|
switch (objectType)
|
||||||
case OBJECT_TYPE_RIDE:
|
{
|
||||||
result = new RideObject(entry);
|
case OBJECT_TYPE_RIDE:
|
||||||
break;
|
result = new RideObject(entry);
|
||||||
case OBJECT_TYPE_SMALL_SCENERY:
|
break;
|
||||||
result = new SmallSceneryObject(entry);
|
case OBJECT_TYPE_SMALL_SCENERY:
|
||||||
break;
|
result = new SmallSceneryObject(entry);
|
||||||
case OBJECT_TYPE_LARGE_SCENERY:
|
break;
|
||||||
result = new LargeSceneryObject(entry);
|
case OBJECT_TYPE_LARGE_SCENERY:
|
||||||
break;
|
result = new LargeSceneryObject(entry);
|
||||||
case OBJECT_TYPE_WALLS:
|
break;
|
||||||
result = new WallObject(entry);
|
case OBJECT_TYPE_WALLS:
|
||||||
break;
|
result = new WallObject(entry);
|
||||||
case OBJECT_TYPE_BANNERS:
|
break;
|
||||||
result = new BannerObject(entry);
|
case OBJECT_TYPE_BANNERS:
|
||||||
break;
|
result = new BannerObject(entry);
|
||||||
case OBJECT_TYPE_PATHS:
|
break;
|
||||||
result = new FootpathObject(entry);
|
case OBJECT_TYPE_PATHS:
|
||||||
break;
|
result = new FootpathObject(entry);
|
||||||
case OBJECT_TYPE_PATH_BITS:
|
break;
|
||||||
result = new FootpathItemObject(entry);
|
case OBJECT_TYPE_PATH_BITS:
|
||||||
break;
|
result = new FootpathItemObject(entry);
|
||||||
case OBJECT_TYPE_SCENERY_GROUP:
|
break;
|
||||||
result = new SceneryGroupObject(entry);
|
case OBJECT_TYPE_SCENERY_GROUP:
|
||||||
break;
|
result = new SceneryGroupObject(entry);
|
||||||
case OBJECT_TYPE_PARK_ENTRANCE:
|
break;
|
||||||
result = new EntranceObject(entry);
|
case OBJECT_TYPE_PARK_ENTRANCE:
|
||||||
break;
|
result = new EntranceObject(entry);
|
||||||
case OBJECT_TYPE_WATER:
|
break;
|
||||||
result = new WaterObject(entry);
|
case OBJECT_TYPE_WATER:
|
||||||
break;
|
result = new WaterObject(entry);
|
||||||
case OBJECT_TYPE_SCENARIO_TEXT:
|
break;
|
||||||
result = new StexObject(entry);
|
case OBJECT_TYPE_SCENARIO_TEXT:
|
||||||
break;
|
result = new StexObject(entry);
|
||||||
default:
|
break;
|
||||||
throw std::runtime_error("Invalid object type");
|
default:
|
||||||
|
throw std::runtime_error("Invalid object type");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ParseObjectType(const std::string &s)
|
static uint8_t ParseObjectType(const std::string& s)
|
||||||
{
|
{
|
||||||
if (s == "ride") return OBJECT_TYPE_RIDE;
|
if (s == "ride")
|
||||||
if (s == "footpath") return OBJECT_TYPE_PATHS;
|
return OBJECT_TYPE_RIDE;
|
||||||
if (s == "footpath_banner") return OBJECT_TYPE_BANNERS;
|
if (s == "footpath")
|
||||||
if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS;
|
return OBJECT_TYPE_PATHS;
|
||||||
if (s == "scenery_small") return OBJECT_TYPE_SMALL_SCENERY;
|
if (s == "footpath_banner")
|
||||||
if (s == "scenery_large") return OBJECT_TYPE_LARGE_SCENERY;
|
return OBJECT_TYPE_BANNERS;
|
||||||
if (s == "scenery_wall") return OBJECT_TYPE_WALLS;
|
if (s == "footpath_item")
|
||||||
if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP;
|
return OBJECT_TYPE_PATH_BITS;
|
||||||
if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE;
|
if (s == "scenery_small")
|
||||||
if (s == "water") return OBJECT_TYPE_WATER;
|
return OBJECT_TYPE_SMALL_SCENERY;
|
||||||
|
if (s == "scenery_large")
|
||||||
|
return OBJECT_TYPE_LARGE_SCENERY;
|
||||||
|
if (s == "scenery_wall")
|
||||||
|
return OBJECT_TYPE_WALLS;
|
||||||
|
if (s == "scenery_group")
|
||||||
|
return OBJECT_TYPE_SCENERY_GROUP;
|
||||||
|
if (s == "park_entrance")
|
||||||
|
return OBJECT_TYPE_PARK_ENTRANCE;
|
||||||
|
if (s == "water")
|
||||||
|
return OBJECT_TYPE_WATER;
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path)
|
Object* CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path)
|
||||||
{
|
{
|
||||||
Object * result = nullptr;
|
Object* result = nullptr;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto archive = Zip::Open(path, ZIP_ACCESS::READ);
|
auto archive = Zip::Open(path, ZIP_ACCESS::READ);
|
||||||
|
@ -296,7 +316,7 @@ namespace ObjectFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
json_error_t jsonLoadError;
|
json_error_t jsonLoadError;
|
||||||
auto jRoot = json_loadb((const char *)jsonBytes.data(), jsonBytes.size(), 0, &jsonLoadError);
|
auto jRoot = json_loadb((const char*)jsonBytes.data(), jsonBytes.size(), 0, &jsonLoadError);
|
||||||
if (jRoot == nullptr)
|
if (jRoot == nullptr)
|
||||||
{
|
{
|
||||||
throw JsonException(&jsonLoadError);
|
throw JsonException(&jsonLoadError);
|
||||||
|
@ -315,11 +335,11 @@ namespace ObjectFactory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string &path)
|
Object* CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string& path)
|
||||||
{
|
{
|
||||||
log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str());
|
log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str());
|
||||||
|
|
||||||
Object * result = nullptr;
|
Object* result = nullptr;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto jRoot = Json::ReadFromFile(path.c_str());
|
auto jRoot = Json::ReadFromFile(path.c_str());
|
||||||
|
@ -327,7 +347,7 @@ namespace ObjectFactory
|
||||||
result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
|
result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
|
||||||
json_decref(jRoot);
|
json_decref(jRoot);
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error &err)
|
catch (const std::runtime_error& err)
|
||||||
{
|
{
|
||||||
Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), err.what());
|
Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), err.what());
|
||||||
|
|
||||||
|
@ -337,11 +357,12 @@ namespace ObjectFactory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const IFileDataRetriever * fileRetriever)
|
Object*
|
||||||
|
CreateObjectFromJson(IObjectRepository& objectRepository, const json_t* jRoot, const IFileDataRetriever* fileRetriever)
|
||||||
{
|
{
|
||||||
log_verbose("CreateObjectFromJson(...)");
|
log_verbose("CreateObjectFromJson(...)");
|
||||||
|
|
||||||
Object * result = nullptr;
|
Object* result = nullptr;
|
||||||
auto jObjectType = json_object_get(jRoot, "objectType");
|
auto jObjectType = json_object_get(jRoot, "objectType");
|
||||||
if (json_is_string(jObjectType))
|
if (json_is_string(jObjectType))
|
||||||
{
|
{
|
||||||
|
@ -373,4 +394,4 @@ namespace ObjectFactory
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} // namespace ObjectFactory
|
||||||
|
|
|
@ -9,19 +9,21 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
interface IObjectRepository;
|
interface IObjectRepository;
|
||||||
class Object;
|
class Object;
|
||||||
struct rct_object_entry;
|
struct rct_object_entry;
|
||||||
|
|
||||||
namespace ObjectFactory
|
namespace ObjectFactory
|
||||||
{
|
{
|
||||||
Object * CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8 * path);
|
Object* CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8* path);
|
||||||
Object * CreateObjectFromLegacyData(IObjectRepository& objectRepository, const rct_object_entry * entry, const void * data, size_t dataSize);
|
Object* CreateObjectFromLegacyData(
|
||||||
Object * CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path);
|
IObjectRepository& objectRepository, const rct_object_entry* entry, const void* data, size_t dataSize);
|
||||||
Object * CreateObject(const rct_object_entry &entry);
|
Object* CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path);
|
||||||
|
Object* CreateObject(const rct_object_entry& entry);
|
||||||
|
|
||||||
Object * CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string &path);
|
Object* CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string& path);
|
||||||
}
|
} // namespace ObjectFactory
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
|
|
||||||
#pragma warning(disable : 4706) // assignment within conditional expression
|
#pragma warning(disable : 4706) // assignment within conditional expression
|
||||||
|
|
||||||
#include <cstdlib>
|
#include "ObjectJsonHelpers.h"
|
||||||
#include <cstring>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "../Context.h"
|
#include "../Context.h"
|
||||||
|
#include "../PlatformEnvironment.h"
|
||||||
#include "../core/File.h"
|
#include "../core/File.h"
|
||||||
#include "../core/FileScanner.h"
|
#include "../core/FileScanner.h"
|
||||||
#include "../core/Math.hpp"
|
#include "../core/Math.hpp"
|
||||||
|
@ -22,48 +22,43 @@
|
||||||
#include "../drawing/ImageImporter.h"
|
#include "../drawing/ImageImporter.h"
|
||||||
#include "../interface/Cursors.h"
|
#include "../interface/Cursors.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../PlatformEnvironment.h"
|
|
||||||
#include "../sprites.h"
|
#include "../sprites.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "ObjectFactory.h"
|
#include "ObjectFactory.h"
|
||||||
#include "ObjectJsonHelpers.h"
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace OpenRCT2;
|
using namespace OpenRCT2;
|
||||||
using namespace OpenRCT2::Drawing;
|
using namespace OpenRCT2::Drawing;
|
||||||
|
|
||||||
namespace ObjectJsonHelpers
|
namespace ObjectJsonHelpers
|
||||||
{
|
{
|
||||||
bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue)
|
bool GetBoolean(const json_t* obj, const std::string& name, bool defaultValue)
|
||||||
{
|
{
|
||||||
auto value = json_object_get(obj, name.c_str());
|
auto value = json_object_get(obj, name.c_str());
|
||||||
return json_is_boolean(value) ?
|
return json_is_boolean(value) ? json_boolean_value(value) : defaultValue;
|
||||||
json_boolean_value(value) :
|
|
||||||
defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetString(const json_t * value)
|
std::string GetString(const json_t* value)
|
||||||
{
|
{
|
||||||
return json_is_string(value) ?
|
return json_is_string(value) ? std::string(json_string_value(value)) : std::string();
|
||||||
std::string(json_string_value(value)) :
|
|
||||||
std::string();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue)
|
std::string GetString(const json_t* obj, const std::string& name, const std::string& defaultValue)
|
||||||
{
|
{
|
||||||
auto value = json_object_get(obj, name.c_str());
|
auto value = json_object_get(obj, name.c_str());
|
||||||
return json_is_string(value) ?
|
return json_is_string(value) ? json_string_value(value) : defaultValue;
|
||||||
json_string_value(value) :
|
|
||||||
defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t GetInteger(const json_t * obj, const std::string &name, const int32_t &defaultValue)
|
int32_t GetInteger(const json_t* obj, const std::string& name, const int32_t& defaultValue)
|
||||||
{
|
{
|
||||||
auto value = json_object_get(obj, name.c_str());
|
auto value = json_object_get(obj, name.c_str());
|
||||||
if (json_is_integer(value))
|
if (json_is_integer(value))
|
||||||
{
|
{
|
||||||
int64_t val = json_integer_value(value);
|
int64_t val = json_integer_value(value);
|
||||||
if (val >= std::numeric_limits<int32_t>::min() &&
|
if (val >= std::numeric_limits<int32_t>::min() && val <= std::numeric_limits<int32_t>::max())
|
||||||
val <= std::numeric_limits<int32_t>::max())
|
|
||||||
{
|
{
|
||||||
return static_cast<int32_t>(val);
|
return static_cast<int32_t>(val);
|
||||||
}
|
}
|
||||||
|
@ -71,15 +66,13 @@ namespace ObjectJsonHelpers
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetFloat(const json_t * obj, const std::string &name, const float &defaultValue)
|
float GetFloat(const json_t* obj, const std::string& name, const float& defaultValue)
|
||||||
{
|
{
|
||||||
auto value = json_object_get(obj, name.c_str());
|
auto value = json_object_get(obj, name.c_str());
|
||||||
return json_is_number(value) ?
|
return json_is_number(value) ? json_number_value(value) : defaultValue;
|
||||||
json_number_value(value) :
|
|
||||||
defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetJsonStringArray(const json_t * arr)
|
std::vector<std::string> GetJsonStringArray(const json_t* arr)
|
||||||
{
|
{
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
if (json_is_array(arr))
|
if (json_is_array(arr))
|
||||||
|
@ -99,7 +92,7 @@ namespace ObjectJsonHelpers
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int32_t> GetJsonIntegerArray(const json_t * arr)
|
std::vector<int32_t> GetJsonIntegerArray(const json_t* arr)
|
||||||
{
|
{
|
||||||
std::vector<int32_t> result;
|
std::vector<int32_t> result;
|
||||||
if (json_is_array(arr))
|
if (json_is_array(arr))
|
||||||
|
@ -119,46 +112,43 @@ namespace ObjectJsonHelpers
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ParseCursor(const std::string &s, uint8_t defaultValue)
|
uint8_t ParseCursor(const std::string& s, uint8_t defaultValue)
|
||||||
{
|
{
|
||||||
static const std::unordered_map<std::string, uint8_t> LookupTable
|
static const std::unordered_map<std::string, uint8_t> LookupTable{
|
||||||
{
|
{ "CURSOR_BLANK", CURSOR_BLANK },
|
||||||
{ "CURSOR_BLANK", CURSOR_BLANK },
|
{ "CURSOR_UP_ARROW", CURSOR_UP_ARROW },
|
||||||
{ "CURSOR_UP_ARROW", CURSOR_UP_ARROW },
|
{ "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW },
|
||||||
{ "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW },
|
{ "CURSOR_HAND_POINT", CURSOR_HAND_POINT },
|
||||||
{ "CURSOR_HAND_POINT", CURSOR_HAND_POINT },
|
{ "CURSOR_ZZZ", CURSOR_ZZZ },
|
||||||
{ "CURSOR_ZZZ", CURSOR_ZZZ },
|
|
||||||
{ "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS },
|
{ "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS },
|
||||||
{ "CURSOR_PICKER", CURSOR_PICKER },
|
{ "CURSOR_PICKER", CURSOR_PICKER },
|
||||||
{ "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN },
|
{ "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN },
|
||||||
{ "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN },
|
{ "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN },
|
||||||
{ "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN },
|
{ "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN },
|
||||||
{ "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN },
|
{ "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN },
|
||||||
{ "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR },
|
{ "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR },
|
||||||
{ "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN },
|
{ "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN },
|
||||||
{ "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN },
|
{ "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN },
|
||||||
{ "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN },
|
{ "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN },
|
||||||
{ "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN },
|
{ "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN },
|
||||||
{ "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN },
|
{ "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN },
|
||||||
{ "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN },
|
{ "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN },
|
||||||
{ "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN },
|
{ "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN },
|
||||||
{ "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN },
|
{ "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN },
|
||||||
{ "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN },
|
{ "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN },
|
||||||
{ "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN },
|
{ "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN },
|
||||||
{ "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN },
|
{ "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN },
|
||||||
{ "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN },
|
{ "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN },
|
||||||
{ "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN },
|
{ "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN },
|
||||||
{ "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED },
|
{ "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED },
|
||||||
{ "CURSOR_ARROW", CURSOR_ARROW },
|
{ "CURSOR_ARROW", CURSOR_ARROW },
|
||||||
};
|
};
|
||||||
|
|
||||||
auto result = LookupTable.find(s);
|
auto result = LookupTable.find(s);
|
||||||
return (result != LookupTable.end()) ?
|
return (result != LookupTable.end()) ? result->second : defaultValue;
|
||||||
result->second :
|
|
||||||
defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rct_object_entry ParseObjectEntry(const std::string & s)
|
rct_object_entry ParseObjectEntry(const std::string& s)
|
||||||
{
|
{
|
||||||
rct_object_entry entry = {};
|
rct_object_entry entry = {};
|
||||||
std::fill_n(entry.name, sizeof(entry.name), ' ');
|
std::fill_n(entry.name, sizeof(entry.name), ' ');
|
||||||
|
@ -170,7 +160,7 @@ namespace ObjectJsonHelpers
|
||||||
static std::vector<int32_t> ParseRange(std::string s)
|
static std::vector<int32_t> ParseRange(std::string s)
|
||||||
{
|
{
|
||||||
// Currently only supports [###] or [###..###]
|
// Currently only supports [###] or [###..###]
|
||||||
std::vector<int32_t> result = { };
|
std::vector<int32_t> result = {};
|
||||||
if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']')
|
if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']')
|
||||||
{
|
{
|
||||||
s = s.substr(1, s.length() - 2);
|
s = s.substr(1, s.length() - 2);
|
||||||
|
@ -202,7 +192,7 @@ namespace ObjectJsonHelpers
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string FindLegacyObject(const std::string &name)
|
static std::string FindLegacyObject(const std::string& name)
|
||||||
{
|
{
|
||||||
const auto env = GetContext()->GetPlatformEnvironment();
|
const auto env = GetContext()->GetPlatformEnvironment();
|
||||||
auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT);
|
auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT);
|
||||||
|
@ -225,14 +215,15 @@ namespace ObjectJsonHelpers
|
||||||
return objectPath;
|
return objectPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<rct_g1_element> LoadObjectImages(IReadObjectContext * context, const std::string &name, const std::vector<int32_t> &range)
|
static std::vector<rct_g1_element>
|
||||||
|
LoadObjectImages(IReadObjectContext* context, const std::string& name, const std::vector<int32_t>& range)
|
||||||
{
|
{
|
||||||
std::vector<rct_g1_element> result;
|
std::vector<rct_g1_element> result;
|
||||||
auto objectPath = FindLegacyObject(name);
|
auto objectPath = FindLegacyObject(name);
|
||||||
auto obj = ObjectFactory::CreateObjectFromLegacyFile(context->GetObjectRepository(), objectPath.c_str());
|
auto obj = ObjectFactory::CreateObjectFromLegacyFile(context->GetObjectRepository(), objectPath.c_str());
|
||||||
if (obj != nullptr)
|
if (obj != nullptr)
|
||||||
{
|
{
|
||||||
auto &imgTable = static_cast<const Object *>(obj)->GetImageTable();
|
auto& imgTable = static_cast<const Object*>(obj)->GetImageTable();
|
||||||
auto numImages = (int32_t)imgTable.GetCount();
|
auto numImages = (int32_t)imgTable.GetCount();
|
||||||
auto images = imgTable.GetImages();
|
auto images = imgTable.GetImages();
|
||||||
size_t placeHoldersAdded = 0;
|
size_t placeHoldersAdded = 0;
|
||||||
|
@ -240,10 +231,10 @@ namespace ObjectJsonHelpers
|
||||||
{
|
{
|
||||||
if (i >= 0 && i < numImages)
|
if (i >= 0 && i < numImages)
|
||||||
{
|
{
|
||||||
auto &objg1 = images[i];
|
auto& objg1 = images[i];
|
||||||
auto length = g1_calculate_data_size(&objg1);
|
auto length = g1_calculate_data_size(&objg1);
|
||||||
auto g1 = objg1;
|
auto g1 = objg1;
|
||||||
g1.offset = (uint8_t *)std::malloc(length);
|
g1.offset = (uint8_t*)std::malloc(length);
|
||||||
std::memcpy(g1.offset, objg1.offset, length);
|
std::memcpy(g1.offset, objg1.offset, length);
|
||||||
result.push_back(g1);
|
result.push_back(g1);
|
||||||
}
|
}
|
||||||
|
@ -272,7 +263,7 @@ namespace ObjectJsonHelpers
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<rct_g1_element> ParseImages(IReadObjectContext * context, std::string s)
|
static std::vector<rct_g1_element> ParseImages(IReadObjectContext* context, std::string s)
|
||||||
{
|
{
|
||||||
std::vector<rct_g1_element> result;
|
std::vector<rct_g1_element> result;
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
|
@ -289,10 +280,10 @@ namespace ObjectJsonHelpers
|
||||||
{
|
{
|
||||||
for (auto i : range)
|
for (auto i : range)
|
||||||
{
|
{
|
||||||
auto &csg1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i);
|
auto& csg1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i);
|
||||||
auto length = g1_calculate_data_size(&csg1);
|
auto length = g1_calculate_data_size(&csg1);
|
||||||
auto g1 = csg1;
|
auto g1 = csg1;
|
||||||
g1.offset = (uint8_t *)std::malloc(length);
|
g1.offset = (uint8_t*)std::malloc(length);
|
||||||
std::memcpy(g1.offset, csg1.offset, length);
|
std::memcpy(g1.offset, csg1.offset, length);
|
||||||
result.push_back(g1);
|
result.push_back(g1);
|
||||||
}
|
}
|
||||||
|
@ -316,7 +307,7 @@ namespace ObjectJsonHelpers
|
||||||
{
|
{
|
||||||
auto length = g1_calculate_data_size(og1);
|
auto length = g1_calculate_data_size(og1);
|
||||||
auto g1 = *og1;
|
auto g1 = *og1;
|
||||||
g1.offset = (uint8_t *)std::malloc(length);
|
g1.offset = (uint8_t*)std::malloc(length);
|
||||||
std::memcpy(g1.offset, og1->offset, length);
|
std::memcpy(g1.offset, og1->offset, length);
|
||||||
result.push_back(g1);
|
result.push_back(g1);
|
||||||
}
|
}
|
||||||
|
@ -359,7 +350,7 @@ namespace ObjectJsonHelpers
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<rct_g1_element> ParseImages(IReadObjectContext * context, json_t * el)
|
static std::vector<rct_g1_element> ParseImages(IReadObjectContext* context, json_t* el)
|
||||||
{
|
{
|
||||||
auto path = GetString(el, "path");
|
auto path = GetString(el, "path");
|
||||||
auto x = GetInteger(el, "x");
|
auto x = GetInteger(el, "x");
|
||||||
|
@ -395,27 +386,31 @@ namespace ObjectJsonHelpers
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ParseStringId(const std::string &s)
|
static uint8_t ParseStringId(const std::string& s)
|
||||||
{
|
{
|
||||||
if (s == "name") return OBJ_STRING_ID_NAME;
|
if (s == "name")
|
||||||
if (s == "description") return OBJ_STRING_ID_DESCRIPTION;
|
return OBJ_STRING_ID_NAME;
|
||||||
if (s == "capacity") return OBJ_STRING_ID_CAPACITY;
|
if (s == "description")
|
||||||
if (s == "vehicleName") return OBJ_STRING_ID_VEHICLE_NAME;
|
return OBJ_STRING_ID_DESCRIPTION;
|
||||||
|
if (s == "capacity")
|
||||||
|
return OBJ_STRING_ID_CAPACITY;
|
||||||
|
if (s == "vehicleName")
|
||||||
|
return OBJ_STRING_ID_VEHICLE_NAME;
|
||||||
return OBJ_STRING_ID_UNKNOWN;
|
return OBJ_STRING_ID_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadStrings(const json_t * root, StringTable &stringTable)
|
void LoadStrings(const json_t* root, StringTable& stringTable)
|
||||||
{
|
{
|
||||||
auto jsonStrings = json_object_get(root, "strings");
|
auto jsonStrings = json_object_get(root, "strings");
|
||||||
const char * key;
|
const char* key;
|
||||||
json_t * jlanguages;
|
json_t* jlanguages;
|
||||||
json_object_foreach(jsonStrings, key, jlanguages)
|
json_object_foreach(jsonStrings, key, jlanguages)
|
||||||
{
|
{
|
||||||
auto stringId = ParseStringId(key);
|
auto stringId = ParseStringId(key);
|
||||||
if (stringId != OBJ_STRING_ID_UNKNOWN)
|
if (stringId != OBJ_STRING_ID_UNKNOWN)
|
||||||
{
|
{
|
||||||
const char * locale;
|
const char* locale;
|
||||||
json_t * jstring;
|
json_t* jstring;
|
||||||
json_object_foreach(jlanguages, locale, jstring)
|
json_object_foreach(jlanguages, locale, jstring)
|
||||||
{
|
{
|
||||||
auto langId = language_get_id_from_locale(locale);
|
auto langId = language_get_id_from_locale(locale);
|
||||||
|
@ -430,13 +425,13 @@ namespace ObjectJsonHelpers
|
||||||
stringTable.Sort();
|
stringTable.Sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable)
|
void LoadImages(IReadObjectContext* context, const json_t* root, ImageTable& imageTable)
|
||||||
{
|
{
|
||||||
if (context->ShouldLoadImages())
|
if (context->ShouldLoadImages())
|
||||||
{
|
{
|
||||||
auto jsonImages = json_object_get(root, "images");
|
auto jsonImages = json_object_get(root, "images");
|
||||||
size_t i;
|
size_t i;
|
||||||
json_t * el;
|
json_t* el;
|
||||||
json_array_foreach(jsonImages, i, el)
|
json_array_foreach(jsonImages, i, el)
|
||||||
{
|
{
|
||||||
std::vector<rct_g1_element> images;
|
std::vector<rct_g1_element> images;
|
||||||
|
@ -449,7 +444,7 @@ namespace ObjectJsonHelpers
|
||||||
{
|
{
|
||||||
images = ParseImages(context, el);
|
images = ParseImages(context, el);
|
||||||
}
|
}
|
||||||
for (const auto &g1 : images)
|
for (const auto& g1 : images)
|
||||||
{
|
{
|
||||||
imageTable.AddImage(&g1);
|
imageTable.AddImage(&g1);
|
||||||
std::free(g1.offset);
|
std::free(g1.offset);
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../core/Json.hpp"
|
#include "../core/Json.hpp"
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
|
@ -20,25 +16,29 @@
|
||||||
#include "ImageTable.h"
|
#include "ImageTable.h"
|
||||||
#include "StringTable.h"
|
#include "StringTable.h"
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace ObjectJsonHelpers
|
namespace ObjectJsonHelpers
|
||||||
{
|
{
|
||||||
bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false);
|
bool GetBoolean(const json_t* obj, const std::string& name, bool defaultValue = false);
|
||||||
std::string GetString(const json_t * value);
|
std::string GetString(const json_t* value);
|
||||||
std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue = "");
|
std::string GetString(const json_t* obj, const std::string& name, const std::string& defaultValue = "");
|
||||||
int32_t GetInteger(const json_t * obj, const std::string &name, const int32_t &defaultValue = 0);
|
int32_t GetInteger(const json_t* obj, const std::string& name, const int32_t& defaultValue = 0);
|
||||||
float GetFloat(const json_t * obj, const std::string &name, const float &defaultValue = 0);
|
float GetFloat(const json_t* obj, const std::string& name, const float& defaultValue = 0);
|
||||||
std::vector<std::string> GetJsonStringArray(const json_t * arr);
|
std::vector<std::string> GetJsonStringArray(const json_t* arr);
|
||||||
std::vector<int32_t> GetJsonIntegerArray(const json_t * arr);
|
std::vector<int32_t> GetJsonIntegerArray(const json_t* arr);
|
||||||
uint8_t ParseCursor(const std::string &s, uint8_t defaultValue);
|
uint8_t ParseCursor(const std::string& s, uint8_t defaultValue);
|
||||||
rct_object_entry ParseObjectEntry(const std::string & s);
|
rct_object_entry ParseObjectEntry(const std::string& s);
|
||||||
void LoadStrings(const json_t * root, StringTable &stringTable);
|
void LoadStrings(const json_t* root, StringTable& stringTable);
|
||||||
void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable);
|
void LoadImages(IReadObjectContext* context, const json_t* root, ImageTable& imageTable);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static T GetFlags(const json_t* obj, std::initializer_list<std::pair<std::string, T>> list)
|
||||||
static T GetFlags(const json_t * obj, std::initializer_list<std::pair<std::string, T>> list)
|
|
||||||
{
|
{
|
||||||
T flags = 0;
|
T flags = 0;
|
||||||
for (const auto &item : list)
|
for (const auto& item : list)
|
||||||
{
|
{
|
||||||
if (GetBoolean(obj, item.first))
|
if (GetBoolean(obj, item.first))
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,16 +9,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MAX_RIDE_OBJECTS 128
|
#define MAX_RIDE_OBJECTS 128
|
||||||
#define MAX_SMALL_SCENERY_OBJECTS 252
|
#define MAX_SMALL_SCENERY_OBJECTS 252
|
||||||
#define MAX_LARGE_SCENERY_OBJECTS 128
|
#define MAX_LARGE_SCENERY_OBJECTS 128
|
||||||
#define MAX_WALL_SCENERY_OBJECTS 128
|
#define MAX_WALL_SCENERY_OBJECTS 128
|
||||||
#define MAX_BANNER_OBJECTS 32
|
#define MAX_BANNER_OBJECTS 32
|
||||||
#define MAX_PATH_OBJECTS 16
|
#define MAX_PATH_OBJECTS 16
|
||||||
#define MAX_PATH_ADDITION_OBJECTS 15
|
#define MAX_PATH_ADDITION_OBJECTS 15
|
||||||
#define MAX_SCENERY_GROUP_OBJECTS 19
|
#define MAX_SCENERY_GROUP_OBJECTS 19
|
||||||
#define MAX_PARK_ENTRANCE_OBJECTS 1
|
#define MAX_PARK_ENTRANCE_OBJECTS 1
|
||||||
#define MAX_WATER_OBJECTS 1
|
#define MAX_WATER_OBJECTS 1
|
||||||
#define MAX_SCENARIO_TEXT_OBJECTS 1
|
#define MAX_SCENARIO_TEXT_OBJECTS 1
|
||||||
|
|
||||||
#define DAT_NAME_LENGTH 8
|
#define DAT_NAME_LENGTH 8
|
||||||
|
|
|
@ -7,18 +7,19 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <cstring>
|
#include "ObjectList.h"
|
||||||
|
|
||||||
#include "../Context.h"
|
#include "../Context.h"
|
||||||
|
#include "../Game.h"
|
||||||
#include "../core/Math.hpp"
|
#include "../core/Math.hpp"
|
||||||
#include "../core/Util.hpp"
|
#include "../core/Util.hpp"
|
||||||
#include "../Game.h"
|
|
||||||
#include "../object/Object.h"
|
#include "../object/Object.h"
|
||||||
#include "ObjectList.h"
|
|
||||||
#include "ObjectRepository.h"
|
|
||||||
#include "ObjectManager.h"
|
|
||||||
#include "../util/SawyerCoding.h"
|
#include "../util/SawyerCoding.h"
|
||||||
#include "../util/Util.h"
|
#include "../util/Util.h"
|
||||||
|
#include "ObjectManager.h"
|
||||||
|
#include "ObjectRepository.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
// 98DA00
|
// 98DA00
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
@ -52,23 +53,25 @@ int32_t object_entry_group_encoding[] = {
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
bool object_entry_is_empty(const rct_object_entry *entry)
|
bool object_entry_is_empty(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
uint64_t a, b;
|
uint64_t a, b;
|
||||||
memcpy(&a, (uint8_t *)entry, 8);
|
memcpy(&a, (uint8_t*)entry, 8);
|
||||||
memcpy(&b, (uint8_t *)entry + 8, 8);
|
memcpy(&b, (uint8_t*)entry + 8, 8);
|
||||||
|
|
||||||
if (a == 0xFFFFFFFFFFFFFFFF && b == 0xFFFFFFFFFFFFFFFF) return true;
|
if (a == 0xFFFFFFFFFFFFFFFF && b == 0xFFFFFFFFFFFFFFFF)
|
||||||
if (a == 0 && b == 0) return true;
|
return true;
|
||||||
|
if (a == 0 && b == 0)
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t object_entry_get_type(const rct_object_entry * objectEntry)
|
uint8_t object_entry_get_type(const rct_object_entry* objectEntry)
|
||||||
{
|
{
|
||||||
return (objectEntry->flags & 0x0F);
|
return (objectEntry->flags & 0x0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t object_entry_get_source_game(const rct_object_entry * objectEntry)
|
uint8_t object_entry_get_source_game(const rct_object_entry* objectEntry)
|
||||||
{
|
{
|
||||||
return (objectEntry->flags & 0xF0) >> 4;
|
return (objectEntry->flags & 0xF0) >> 4;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +91,7 @@ void object_create_identifier_name(char* string_buffer, size_t size, const rct_o
|
||||||
* bl = entry_index
|
* bl = entry_index
|
||||||
* ecx = entry_type
|
* ecx = entry_type
|
||||||
*/
|
*/
|
||||||
bool find_object_in_entry_group(const rct_object_entry * entry, uint8_t * entry_type, uint8_t * entry_index)
|
bool find_object_in_entry_group(const rct_object_entry* entry, uint8_t* entry_type, uint8_t* entry_index)
|
||||||
{
|
{
|
||||||
int32_t objectType = object_entry_get_type(entry);
|
int32_t objectType = object_entry_get_type(entry);
|
||||||
if (objectType >= OBJECT_TYPE_COUNT)
|
if (objectType >= OBJECT_TYPE_COUNT)
|
||||||
|
@ -113,24 +116,29 @@ bool find_object_in_entry_group(const rct_object_entry * entry, uint8_t * entry_
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_type_entry_index(size_t index, uint8_t * outObjectType, uint8_t * outEntryIndex)
|
void get_type_entry_index(size_t index, uint8_t* outObjectType, uint8_t* outEntryIndex)
|
||||||
{
|
{
|
||||||
uint8_t objectType = OBJECT_TYPE_RIDE;
|
uint8_t objectType = OBJECT_TYPE_RIDE;
|
||||||
for (size_t groupCount : object_entry_group_counts)
|
for (size_t groupCount : object_entry_group_counts)
|
||||||
{
|
{
|
||||||
if (index >= groupCount) {
|
if (index >= groupCount)
|
||||||
|
{
|
||||||
index -= groupCount;
|
index -= groupCount;
|
||||||
objectType++;
|
objectType++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outObjectType != nullptr) *outObjectType = objectType;
|
if (outObjectType != nullptr)
|
||||||
if (outEntryIndex != nullptr) *outEntryIndex = (uint8_t)index;
|
*outObjectType = objectType;
|
||||||
|
if (outEntryIndex != nullptr)
|
||||||
|
*outEntryIndex = (uint8_t)index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rct_object_entry * get_loaded_object_entry(size_t index)
|
const rct_object_entry* get_loaded_object_entry(size_t index)
|
||||||
{
|
{
|
||||||
uint8_t objectType, entryIndex;
|
uint8_t objectType, entryIndex;
|
||||||
get_type_entry_index(index, &objectType, &entryIndex);
|
get_type_entry_index(index, &objectType, &entryIndex);
|
||||||
|
@ -138,21 +146,21 @@ const rct_object_entry * get_loaded_object_entry(size_t index)
|
||||||
return object_entry_get_entry(objectType, entryIndex);
|
return object_entry_get_entry(objectType, entryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void * get_loaded_object_chunk(size_t index)
|
void* get_loaded_object_chunk(size_t index)
|
||||||
{
|
{
|
||||||
uint8_t objectType, entryIndex;
|
uint8_t objectType, entryIndex;
|
||||||
get_type_entry_index(index, &objectType, &entryIndex);
|
get_type_entry_index(index, &objectType, &entryIndex);
|
||||||
return object_entry_get_chunk(objectType, entryIndex);
|
return object_entry_get_chunk(objectType, entryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry)
|
void object_entry_get_name_fixed(utf8* buffer, size_t bufferSize, const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
bufferSize = std::min((size_t)DAT_NAME_LENGTH + 1, bufferSize);
|
bufferSize = std::min((size_t)DAT_NAME_LENGTH + 1, bufferSize);
|
||||||
memcpy(buffer, entry->name, bufferSize - 1);
|
memcpy(buffer, entry->name, bufferSize - 1);
|
||||||
buffer[bufferSize - 1] = 0;
|
buffer[bufferSize - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * object_entry_get_chunk(int32_t objectType, size_t index)
|
void* object_entry_get_chunk(int32_t objectType, size_t index)
|
||||||
{
|
{
|
||||||
size_t objectIndex = index;
|
size_t objectIndex = index;
|
||||||
for (int32_t i = 0; i < objectType; i++)
|
for (int32_t i = 0; i < objectType; i++)
|
||||||
|
@ -160,7 +168,7 @@ void * object_entry_get_chunk(int32_t objectType, size_t index)
|
||||||
objectIndex += object_entry_group_counts[i];
|
objectIndex += object_entry_group_counts[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void * result = nullptr;
|
void* result = nullptr;
|
||||||
auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
|
auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||||
auto obj = objectMgr->GetLoadedObject(objectIndex);
|
auto obj = objectMgr->GetLoadedObject(objectIndex);
|
||||||
if (obj != nullptr)
|
if (obj != nullptr)
|
||||||
|
@ -170,9 +178,9 @@ void * object_entry_get_chunk(int32_t objectType, size_t index)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rct_object_entry * object_entry_get_entry(int32_t objectType, size_t index)
|
const rct_object_entry* object_entry_get_entry(int32_t objectType, size_t index)
|
||||||
{
|
{
|
||||||
const rct_object_entry * result = nullptr;
|
const rct_object_entry* result = nullptr;
|
||||||
auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
|
auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||||
auto obj = objectMgr->GetLoadedObject(objectType, index);
|
auto obj = objectMgr->GetLoadedObject(objectType, index);
|
||||||
if (obj != nullptr)
|
if (obj != nullptr)
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#include "../world/Water.h"
|
#include "../world/Water.h"
|
||||||
#include "ObjectLimits.h"
|
#include "ObjectLimits.h"
|
||||||
|
|
||||||
void get_type_entry_index(size_t index, uint8_t * outObjectType, uint8_t * outEntryIndex);
|
void get_type_entry_index(size_t index, uint8_t* outObjectType, uint8_t* outEntryIndex);
|
||||||
const rct_object_entry * get_loaded_object_entry(size_t index);
|
const rct_object_entry* get_loaded_object_entry(size_t index);
|
||||||
void * get_loaded_object_chunk(size_t index);
|
void* get_loaded_object_chunk(size_t index);
|
||||||
uint8_t object_entry_get_type(const rct_object_entry * objectEntry);
|
uint8_t object_entry_get_type(const rct_object_entry* objectEntry);
|
||||||
uint8_t object_entry_get_source_game(const rct_object_entry * objectEntry);
|
uint8_t object_entry_get_source_game(const rct_object_entry* objectEntry);
|
||||||
|
|
|
@ -7,33 +7,34 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "ObjectManager.h"
|
||||||
|
|
||||||
|
#include "../Context.h"
|
||||||
|
#include "../ParkImporter.h"
|
||||||
|
#include "../core/Console.hpp"
|
||||||
|
#include "../core/Memory.hpp"
|
||||||
|
#include "../localisation/StringIds.h"
|
||||||
|
#include "FootpathItemObject.h"
|
||||||
|
#include "LargeSceneryObject.h"
|
||||||
|
#include "Object.h"
|
||||||
|
#include "ObjectList.h"
|
||||||
|
#include "ObjectRepository.h"
|
||||||
|
#include "SceneryGroupObject.h"
|
||||||
|
#include "SmallSceneryObject.h"
|
||||||
|
#include "WallObject.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include "../Context.h"
|
|
||||||
#include "../core/Console.hpp"
|
|
||||||
#include "../core/Memory.hpp"
|
|
||||||
#include "../localisation/StringIds.h"
|
|
||||||
#include "../ParkImporter.h"
|
|
||||||
#include "FootpathItemObject.h"
|
|
||||||
#include "LargeSceneryObject.h"
|
|
||||||
#include "Object.h"
|
|
||||||
#include "ObjectManager.h"
|
|
||||||
#include "ObjectRepository.h"
|
|
||||||
#include "SceneryGroupObject.h"
|
|
||||||
#include "SmallSceneryObject.h"
|
|
||||||
#include "WallObject.h"
|
|
||||||
|
|
||||||
#include "ObjectList.h"
|
|
||||||
|
|
||||||
class ObjectManager final : public IObjectManager
|
class ObjectManager final : public IObjectManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<IObjectRepository> _objectRepository;
|
std::shared_ptr<IObjectRepository> _objectRepository;
|
||||||
std::vector<Object *> _loadedObjects;
|
std::vector<Object*> _loadedObjects;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ObjectManager(std::shared_ptr<IObjectRepository> objectRepository)
|
explicit ObjectManager(std::shared_ptr<IObjectRepository> objectRepository)
|
||||||
|
@ -52,7 +53,7 @@ public:
|
||||||
UnloadAll();
|
UnloadAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * GetLoadedObject(size_t index) override
|
Object* GetLoadedObject(size_t index) override
|
||||||
{
|
{
|
||||||
if (index >= _loadedObjects.size())
|
if (index >= _loadedObjects.size())
|
||||||
{
|
{
|
||||||
|
@ -61,7 +62,7 @@ public:
|
||||||
return _loadedObjects[index];
|
return _loadedObjects[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * GetLoadedObject(int32_t objectType, size_t index) override
|
Object* GetLoadedObject(int32_t objectType, size_t index) override
|
||||||
{
|
{
|
||||||
if (index >= (size_t)object_entry_group_counts[objectType])
|
if (index >= (size_t)object_entry_group_counts[objectType])
|
||||||
{
|
{
|
||||||
|
@ -75,10 +76,10 @@ public:
|
||||||
return GetLoadedObject(objectIndex);
|
return GetLoadedObject(objectIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * GetLoadedObject(const rct_object_entry * entry) override
|
Object* GetLoadedObject(const rct_object_entry* entry) override
|
||||||
{
|
{
|
||||||
Object * loadedObject = nullptr;
|
Object* loadedObject = nullptr;
|
||||||
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry);
|
const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
|
||||||
if (ori != nullptr)
|
if (ori != nullptr)
|
||||||
{
|
{
|
||||||
loadedObject = ori->LoadedObject;
|
loadedObject = ori->LoadedObject;
|
||||||
|
@ -86,7 +87,7 @@ public:
|
||||||
return loadedObject;
|
return loadedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GetLoadedObjectEntryIndex(const Object * object) override
|
uint8_t GetLoadedObjectEntryIndex(const Object* object) override
|
||||||
{
|
{
|
||||||
uint8_t result = UINT8_MAX;
|
uint8_t result = UINT8_MAX;
|
||||||
size_t index = GetLoadedObjectIndex(object);
|
size_t index = GetLoadedObjectIndex(object);
|
||||||
|
@ -97,10 +98,10 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * LoadObject(const rct_object_entry * entry) override
|
Object* LoadObject(const rct_object_entry* entry) override
|
||||||
{
|
{
|
||||||
Object * loadedObject = nullptr;
|
Object* loadedObject = nullptr;
|
||||||
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry);
|
const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
|
||||||
if (ori != nullptr)
|
if (ori != nullptr)
|
||||||
{
|
{
|
||||||
loadedObject = ori->LoadedObject;
|
loadedObject = ori->LoadedObject;
|
||||||
|
@ -127,7 +128,7 @@ public:
|
||||||
return loadedObject;
|
return loadedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadObjects(const rct_object_entry * entries, size_t count) override
|
void LoadObjects(const rct_object_entry* entries, size_t count) override
|
||||||
{
|
{
|
||||||
// Find all the required objects
|
// Find all the required objects
|
||||||
auto requiredObjects = GetRequiredObjects(entries, count);
|
auto requiredObjects = GetRequiredObjects(entries, count);
|
||||||
|
@ -143,7 +144,7 @@ public:
|
||||||
log_verbose("%u / %u new objects loaded", numNewLoadedObjects, requiredObjects.size());
|
log_verbose("%u / %u new objects loaded", numNewLoadedObjects, requiredObjects.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnloadObjects(const rct_object_entry * entries, size_t count) override
|
void UnloadObjects(const rct_object_entry* entries, size_t count) override
|
||||||
{
|
{
|
||||||
// TODO there are two performance issues here:
|
// TODO there are two performance issues here:
|
||||||
// - FindObject for every entry which is a dictionary lookup
|
// - FindObject for every entry which is a dictionary lookup
|
||||||
|
@ -152,11 +153,11 @@ public:
|
||||||
size_t numObjectsUnloaded = 0;
|
size_t numObjectsUnloaded = 0;
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
const rct_object_entry * entry = &entries[i];
|
const rct_object_entry* entry = &entries[i];
|
||||||
const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry);
|
const ObjectRepositoryItem* ori = _objectRepository->FindObject(entry);
|
||||||
if (ori != nullptr)
|
if (ori != nullptr)
|
||||||
{
|
{
|
||||||
Object * loadedObject = ori->LoadedObject;
|
Object* loadedObject = ori->LoadedObject;
|
||||||
if (loadedObject != nullptr)
|
if (loadedObject != nullptr)
|
||||||
{
|
{
|
||||||
UnloadObject(loadedObject);
|
UnloadObject(loadedObject);
|
||||||
|
@ -196,16 +197,14 @@ public:
|
||||||
ResetTypeToRideEntryIndexMap();
|
ResetTypeToRideEntryIndexMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const ObjectRepositoryItem *> GetPackableObjects() override
|
std::vector<const ObjectRepositoryItem*> GetPackableObjects() override
|
||||||
{
|
{
|
||||||
std::vector<const ObjectRepositoryItem *> objects;
|
std::vector<const ObjectRepositoryItem*> objects;
|
||||||
size_t numObjects = _objectRepository->GetNumObjects();
|
size_t numObjects = _objectRepository->GetNumObjects();
|
||||||
for (size_t i = 0; i < numObjects; i++)
|
for (size_t i = 0; i < numObjects; i++)
|
||||||
{
|
{
|
||||||
const ObjectRepositoryItem * item = &_objectRepository->GetObjects()[i];
|
const ObjectRepositoryItem* item = &_objectRepository->GetObjects()[i];
|
||||||
if (item->LoadedObject != nullptr &&
|
if (item->LoadedObject != nullptr && item->LoadedObject->GetLegacyData() != nullptr && IsObjectCustom(item))
|
||||||
item->LoadedObject->GetLegacyData() != nullptr &&
|
|
||||||
IsObjectCustom(item))
|
|
||||||
{
|
{
|
||||||
objects.push_back(item);
|
objects.push_back(item);
|
||||||
}
|
}
|
||||||
|
@ -219,31 +218,31 @@ public:
|
||||||
// loaded RCT1 and RCT2 save files.
|
// loaded RCT1 and RCT2 save files.
|
||||||
}
|
}
|
||||||
|
|
||||||
static rct_string_id GetObjectSourceGameString(const rct_object_entry * entry)
|
static rct_string_id GetObjectSourceGameString(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
switch (object_entry_get_source_game(entry))
|
switch (object_entry_get_source_game(entry))
|
||||||
{
|
{
|
||||||
case OBJECT_SOURCE_RCT1:
|
case OBJECT_SOURCE_RCT1:
|
||||||
return STR_SCENARIO_CATEGORY_RCT1;
|
return STR_SCENARIO_CATEGORY_RCT1;
|
||||||
case OBJECT_SOURCE_ADDED_ATTRACTIONS:
|
case OBJECT_SOURCE_ADDED_ATTRACTIONS:
|
||||||
return STR_SCENARIO_CATEGORY_RCT1_AA;
|
return STR_SCENARIO_CATEGORY_RCT1_AA;
|
||||||
case OBJECT_SOURCE_LOOPY_LANDSCAPES:
|
case OBJECT_SOURCE_LOOPY_LANDSCAPES:
|
||||||
return STR_SCENARIO_CATEGORY_RCT1_LL;
|
return STR_SCENARIO_CATEGORY_RCT1_LL;
|
||||||
case OBJECT_SOURCE_RCT2:
|
case OBJECT_SOURCE_RCT2:
|
||||||
return STR_ROLLERCOASTER_TYCOON_2_DROPDOWN;
|
return STR_ROLLERCOASTER_TYCOON_2_DROPDOWN;
|
||||||
case OBJECT_SOURCE_WACKY_WORLDS:
|
case OBJECT_SOURCE_WACKY_WORLDS:
|
||||||
return STR_OBJECT_FILTER_WW;
|
return STR_OBJECT_FILTER_WW;
|
||||||
case OBJECT_SOURCE_TIME_TWISTER:
|
case OBJECT_SOURCE_TIME_TWISTER:
|
||||||
return STR_OBJECT_FILTER_TT;
|
return STR_OBJECT_FILTER_TT;
|
||||||
case OBJECT_SOURCE_OPENRCT2_OFFICIAL:
|
case OBJECT_SOURCE_OPENRCT2_OFFICIAL:
|
||||||
return STR_OBJECT_FILTER_OPENRCT2_OFFICIAL;
|
return STR_OBJECT_FILTER_OPENRCT2_OFFICIAL;
|
||||||
default:
|
default:
|
||||||
return STR_OBJECT_FILTER_CUSTOM;
|
return STR_OBJECT_FILTER_CUSTOM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Object * LoadObject(const std::string &name)
|
Object* LoadObject(const std::string& name)
|
||||||
{
|
{
|
||||||
rct_object_entry entry{};
|
rct_object_entry entry{};
|
||||||
std::copy_n(name.c_str(), 8, entry.name);
|
std::copy_n(name.c_str(), 8, entry.name);
|
||||||
|
@ -269,7 +268,7 @@ private:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetLoadedObjectIndex(const Object * object)
|
size_t GetLoadedObjectIndex(const Object* object)
|
||||||
{
|
{
|
||||||
Guard::ArgumentNotNull(object, GUARD_LINE);
|
Guard::ArgumentNotNull(object, GUARD_LINE);
|
||||||
|
|
||||||
|
@ -282,7 +281,7 @@ private:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNewLoadedObjectList(const std::vector<Object *> &newLoadedObjects)
|
void SetNewLoadedObjectList(const std::vector<Object*>& newLoadedObjects)
|
||||||
{
|
{
|
||||||
if (newLoadedObjects.size() == 0)
|
if (newLoadedObjects.size() == 0)
|
||||||
{
|
{
|
||||||
|
@ -295,12 +294,12 @@ private:
|
||||||
_loadedObjects = newLoadedObjects;
|
_loadedObjects = newLoadedObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnloadObject(Object * object)
|
void UnloadObject(Object* object)
|
||||||
{
|
{
|
||||||
if (object != nullptr)
|
if (object != nullptr)
|
||||||
{
|
{
|
||||||
// TODO try to prevent doing a repository search
|
// TODO try to prevent doing a repository search
|
||||||
const ObjectRepositoryItem * ori = _objectRepository->FindObject(object->GetObjectEntry());
|
const ObjectRepositoryItem* ori = _objectRepository->FindObject(object->GetObjectEntry());
|
||||||
if (ori != nullptr)
|
if (ori != nullptr)
|
||||||
{
|
{
|
||||||
_objectRepository->UnregisterLoadedObject(ori, object);
|
_objectRepository->UnregisterLoadedObject(ori, object);
|
||||||
|
@ -308,7 +307,7 @@ private:
|
||||||
|
|
||||||
// Because it's possible to have the same loaded object for multiple
|
// Because it's possible to have the same loaded object for multiple
|
||||||
// slots, we have to make sure find and set all of them to nullptr
|
// slots, we have to make sure find and set all of them to nullptr
|
||||||
for (auto &obj : _loadedObjects)
|
for (auto& obj : _loadedObjects)
|
||||||
{
|
{
|
||||||
if (obj == object)
|
if (obj == object)
|
||||||
{
|
{
|
||||||
|
@ -321,10 +320,10 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnloadObjectsExcept(const std::vector<Object *> &newLoadedObjects)
|
void UnloadObjectsExcept(const std::vector<Object*>& newLoadedObjects)
|
||||||
{
|
{
|
||||||
// Build a hash set for quick checking
|
// Build a hash set for quick checking
|
||||||
auto exceptSet = std::unordered_set<Object *>();
|
auto exceptSet = std::unordered_set<Object*>();
|
||||||
for (auto object : newLoadedObjects)
|
for (auto object : newLoadedObjects)
|
||||||
{
|
{
|
||||||
if (object != nullptr)
|
if (object != nullptr)
|
||||||
|
@ -358,32 +357,33 @@ private:
|
||||||
{
|
{
|
||||||
if (loadedObject != nullptr)
|
if (loadedObject != nullptr)
|
||||||
{
|
{
|
||||||
rct_scenery_entry * sceneryEntry;
|
rct_scenery_entry* sceneryEntry;
|
||||||
switch (loadedObject->GetObjectType()) {
|
switch (loadedObject->GetObjectType())
|
||||||
case OBJECT_TYPE_SMALL_SCENERY:
|
{
|
||||||
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
|
case OBJECT_TYPE_SMALL_SCENERY:
|
||||||
sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
|
||||||
break;
|
sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
||||||
case OBJECT_TYPE_LARGE_SCENERY:
|
break;
|
||||||
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
|
case OBJECT_TYPE_LARGE_SCENERY:
|
||||||
sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
|
||||||
break;
|
sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
||||||
case OBJECT_TYPE_WALLS:
|
break;
|
||||||
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
|
case OBJECT_TYPE_WALLS:
|
||||||
sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
|
||||||
break;
|
sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
||||||
case OBJECT_TYPE_BANNERS:
|
break;
|
||||||
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
|
case OBJECT_TYPE_BANNERS:
|
||||||
sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
|
||||||
break;
|
sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
||||||
case OBJECT_TYPE_PATH_BITS:
|
break;
|
||||||
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
|
case OBJECT_TYPE_PATH_BITS:
|
||||||
sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
sceneryEntry = (rct_scenery_entry*)loadedObject->GetLegacyData();
|
||||||
break;
|
sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
|
||||||
case OBJECT_TYPE_SCENERY_GROUP:
|
break;
|
||||||
auto sgObject = dynamic_cast<SceneryGroupObject *>(loadedObject);
|
case OBJECT_TYPE_SCENERY_GROUP:
|
||||||
sgObject->UpdateEntryIndexes();
|
auto sgObject = dynamic_cast<SceneryGroupObject*>(loadedObject);
|
||||||
break;
|
sgObject->UpdateEntryIndexes();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,11 +393,11 @@ private:
|
||||||
window_close_by_class(WC_SCENERY);
|
window_close_by_class(WC_SCENERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GetPrimarySceneryGroupEntryIndex(Object * loadedObject)
|
uint8_t GetPrimarySceneryGroupEntryIndex(Object* loadedObject)
|
||||||
{
|
{
|
||||||
auto sceneryObject = dynamic_cast<SceneryObject *>(loadedObject);
|
auto sceneryObject = dynamic_cast<SceneryObject*>(loadedObject);
|
||||||
const rct_object_entry * primarySGEntry = sceneryObject->GetPrimarySceneryGroup();
|
const rct_object_entry* primarySGEntry = sceneryObject->GetPrimarySceneryGroup();
|
||||||
Object * sgObject = GetLoadedObject(primarySGEntry);
|
Object* sgObject = GetLoadedObject(primarySGEntry);
|
||||||
|
|
||||||
uint8_t entryIndex = 255;
|
uint8_t entryIndex = 255;
|
||||||
if (sgObject != nullptr)
|
if (sgObject != nullptr)
|
||||||
|
@ -409,21 +409,21 @@ private:
|
||||||
|
|
||||||
rct_object_entry* DuplicateObjectEntry(const rct_object_entry* original)
|
rct_object_entry* DuplicateObjectEntry(const rct_object_entry* original)
|
||||||
{
|
{
|
||||||
rct_object_entry * duplicate = Memory::Allocate<rct_object_entry>(sizeof(rct_object_entry));
|
rct_object_entry* duplicate = Memory::Allocate<rct_object_entry>(sizeof(rct_object_entry));
|
||||||
duplicate->checksum = original->checksum;
|
duplicate->checksum = original->checksum;
|
||||||
strncpy(duplicate->name, original->name, 8);
|
strncpy(duplicate->name, original->name, 8);
|
||||||
duplicate->flags = original->flags;
|
duplicate->flags = original->flags;
|
||||||
return duplicate;
|
return duplicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) override
|
std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry* entries) override
|
||||||
{
|
{
|
||||||
std::vector<rct_object_entry> invalidEntries;
|
std::vector<rct_object_entry> invalidEntries;
|
||||||
invalidEntries.reserve(OBJECT_ENTRY_COUNT);
|
invalidEntries.reserve(OBJECT_ENTRY_COUNT);
|
||||||
for (int32_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
for (int32_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||||
{
|
{
|
||||||
auto entry = entries[i];
|
auto entry = entries[i];
|
||||||
const ObjectRepositoryItem * ori = nullptr;
|
const ObjectRepositoryItem* ori = nullptr;
|
||||||
if (object_entry_is_empty(&entry))
|
if (object_entry_is_empty(&entry))
|
||||||
{
|
{
|
||||||
entry = {};
|
entry = {};
|
||||||
|
@ -447,7 +447,7 @@ private:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Object * loadedObject = nullptr;
|
Object* loadedObject = nullptr;
|
||||||
loadedObject = ori->LoadedObject;
|
loadedObject = ori->LoadedObject;
|
||||||
if (loadedObject == nullptr)
|
if (loadedObject == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -464,15 +464,15 @@ private:
|
||||||
return invalidEntries;
|
return invalidEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const ObjectRepositoryItem *> GetRequiredObjects(const rct_object_entry * entries, size_t count)
|
std::vector<const ObjectRepositoryItem*> GetRequiredObjects(const rct_object_entry* entries, size_t count)
|
||||||
{
|
{
|
||||||
std::vector<const ObjectRepositoryItem *> requiredObjects;
|
std::vector<const ObjectRepositoryItem*> requiredObjects;
|
||||||
std::vector<rct_object_entry> missingObjects;
|
std::vector<rct_object_entry> missingObjects;
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
const rct_object_entry * entry = &entries[i];
|
const rct_object_entry* entry = &entries[i];
|
||||||
const ObjectRepositoryItem * ori = nullptr;
|
const ObjectRepositoryItem* ori = nullptr;
|
||||||
if (!object_entry_is_empty(entry))
|
if (!object_entry_is_empty(entry))
|
||||||
{
|
{
|
||||||
ori = _objectRepository->FindObject(entry);
|
ori = _objectRepository->FindObject(entry);
|
||||||
|
@ -493,8 +493,7 @@ private:
|
||||||
return requiredObjects;
|
return requiredObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFunc>
|
template<typename T, typename TFunc> static void ParallelFor(const std::vector<T>& items, TFunc func)
|
||||||
static void ParallelFor(const std::vector<T>& items, TFunc func)
|
|
||||||
{
|
{
|
||||||
auto partitions = std::thread::hardware_concurrency();
|
auto partitions = std::thread::hardware_concurrency();
|
||||||
auto partitionSize = (items.size() + (partitions - 1)) / partitions;
|
auto partitionSize = (items.size() + (partitions - 1)) / partitions;
|
||||||
|
@ -504,8 +503,7 @@ private:
|
||||||
auto begin = n * partitionSize;
|
auto begin = n * partitionSize;
|
||||||
auto end = std::min(items.size(), begin + partitionSize);
|
auto end = std::min(items.size(), begin + partitionSize);
|
||||||
threads.emplace_back(
|
threads.emplace_back(
|
||||||
[func](size_t pbegin, size_t pend)
|
[func](size_t pbegin, size_t pend) {
|
||||||
{
|
|
||||||
for (size_t i = pbegin; i < pend; i++)
|
for (size_t i = pbegin; i < pend; i++)
|
||||||
{
|
{
|
||||||
func(i);
|
func(i);
|
||||||
|
@ -520,45 +518,42 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Object *> LoadObjects(std::vector<const ObjectRepositoryItem *> &requiredObjects, size_t * outNewObjectsLoaded)
|
std::vector<Object*> LoadObjects(std::vector<const ObjectRepositoryItem*>& requiredObjects, size_t* outNewObjectsLoaded)
|
||||||
{
|
{
|
||||||
std::vector<Object *> objects;
|
std::vector<Object*> objects;
|
||||||
std::vector<Object *> loadedObjects;
|
std::vector<Object*> loadedObjects;
|
||||||
std::vector<rct_object_entry> badObjects;
|
std::vector<rct_object_entry> badObjects;
|
||||||
objects.resize(OBJECT_ENTRY_COUNT);
|
objects.resize(OBJECT_ENTRY_COUNT);
|
||||||
loadedObjects.reserve(OBJECT_ENTRY_COUNT);
|
loadedObjects.reserve(OBJECT_ENTRY_COUNT);
|
||||||
|
|
||||||
// Read objects
|
// Read objects
|
||||||
std::mutex commonMutex;
|
std::mutex commonMutex;
|
||||||
ParallelFor(
|
ParallelFor(requiredObjects, [this, &commonMutex, requiredObjects, &objects, &badObjects, &loadedObjects](size_t i) {
|
||||||
requiredObjects,
|
auto ori = requiredObjects[i];
|
||||||
[this, &commonMutex, requiredObjects, &objects, &badObjects, &loadedObjects](size_t i)
|
Object* loadedObject = nullptr;
|
||||||
|
if (ori != nullptr)
|
||||||
{
|
{
|
||||||
auto ori = requiredObjects[i];
|
loadedObject = ori->LoadedObject;
|
||||||
Object * loadedObject = nullptr;
|
if (loadedObject == nullptr)
|
||||||
if (ori != nullptr)
|
|
||||||
{
|
{
|
||||||
loadedObject = ori->LoadedObject;
|
loadedObject = _objectRepository->LoadObject(ori);
|
||||||
if (loadedObject == nullptr)
|
if (loadedObject == nullptr)
|
||||||
{
|
{
|
||||||
loadedObject = _objectRepository->LoadObject(ori);
|
std::lock_guard<std::mutex> guard(commonMutex);
|
||||||
if (loadedObject == nullptr)
|
badObjects.push_back(ori->ObjectEntry);
|
||||||
{
|
ReportObjectLoadProblem(&ori->ObjectEntry);
|
||||||
std::lock_guard<std::mutex> guard(commonMutex);
|
}
|
||||||
badObjects.push_back(ori->ObjectEntry);
|
else
|
||||||
ReportObjectLoadProblem(&ori->ObjectEntry);
|
{
|
||||||
}
|
std::lock_guard<std::mutex> guard(commonMutex);
|
||||||
else
|
loadedObjects.push_back(loadedObject);
|
||||||
{
|
// Connect the ori to the registered object
|
||||||
std::lock_guard<std::mutex> guard(commonMutex);
|
_objectRepository->RegisterLoadedObject(ori, loadedObject);
|
||||||
loadedObjects.push_back(loadedObject);
|
|
||||||
// Connect the ori to the registered object
|
|
||||||
_objectRepository->RegisterLoadedObject(ori, loadedObject);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
objects[i] = loadedObject;
|
}
|
||||||
});
|
objects[i] = loadedObject;
|
||||||
|
});
|
||||||
|
|
||||||
// Load objects
|
// Load objects
|
||||||
for (auto obj : loadedObjects)
|
for (auto obj : loadedObjects)
|
||||||
|
@ -583,9 +578,9 @@ private:
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * GetOrLoadObject(const ObjectRepositoryItem * ori)
|
Object* GetOrLoadObject(const ObjectRepositoryItem* ori)
|
||||||
{
|
{
|
||||||
Object * loadedObject = ori->LoadedObject;
|
Object* loadedObject = ori->LoadedObject;
|
||||||
if (loadedObject == nullptr)
|
if (loadedObject == nullptr)
|
||||||
{
|
{
|
||||||
// Try to load object
|
// Try to load object
|
||||||
|
@ -606,14 +601,14 @@ private:
|
||||||
reset_type_to_ride_entry_index_map(*this);
|
reset_type_to_ride_entry_index_map(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReportMissingObject(const rct_object_entry * entry)
|
static void ReportMissingObject(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
utf8 objName[DAT_NAME_LENGTH + 1] = { 0 };
|
utf8 objName[DAT_NAME_LENGTH + 1] = { 0 };
|
||||||
std::copy_n(entry->name, DAT_NAME_LENGTH, objName);
|
std::copy_n(entry->name, DAT_NAME_LENGTH, objName);
|
||||||
Console::Error::WriteLine("[%s] Object not found.", objName);
|
Console::Error::WriteLine("[%s] Object not found.", objName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReportObjectLoadProblem(const rct_object_entry * entry)
|
void ReportObjectLoadProblem(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
utf8 objName[DAT_NAME_LENGTH + 1] = { 0 };
|
utf8 objName[DAT_NAME_LENGTH + 1] = { 0 };
|
||||||
std::copy_n(entry->name, DAT_NAME_LENGTH, objName);
|
std::copy_n(entry->name, DAT_NAME_LENGTH, objName);
|
||||||
|
@ -637,36 +632,36 @@ std::unique_ptr<IObjectManager> CreateObjectManager(std::shared_ptr<IObjectRepos
|
||||||
return std::make_unique<ObjectManager>(objectRepository);
|
return std::make_unique<ObjectManager>(objectRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
void * object_manager_get_loaded_object_by_index(size_t index)
|
void* object_manager_get_loaded_object_by_index(size_t index)
|
||||||
{
|
{
|
||||||
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||||
Object * loadedObject = objectManager->GetLoadedObject(index);
|
Object* loadedObject = objectManager->GetLoadedObject(index);
|
||||||
return (void *)loadedObject;
|
return (void*)loadedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * object_manager_get_loaded_object(const rct_object_entry * entry)
|
void* object_manager_get_loaded_object(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||||
Object * loadedObject = objectManager->GetLoadedObject(entry);
|
Object* loadedObject = objectManager->GetLoadedObject(entry);
|
||||||
return (void *)loadedObject;
|
return (void*)loadedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t object_manager_get_loaded_object_entry_index(const void * loadedObject)
|
uint8_t object_manager_get_loaded_object_entry_index(const void* loadedObject)
|
||||||
{
|
{
|
||||||
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||||
const Object * object = static_cast<const Object *>(loadedObject);
|
const Object* object = static_cast<const Object*>(loadedObject);
|
||||||
uint8_t entryIndex = objectManager->GetLoadedObjectEntryIndex(object);
|
uint8_t entryIndex = objectManager->GetLoadedObjectEntryIndex(object);
|
||||||
return entryIndex;
|
return entryIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * object_manager_load_object(const rct_object_entry * entry)
|
void* object_manager_load_object(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||||
Object * loadedObject = objectManager->LoadObject(entry);
|
Object* loadedObject = objectManager->LoadObject(entry);
|
||||||
return (void *)loadedObject;
|
return (void*)loadedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_manager_unload_objects(const rct_object_entry * entries, size_t count)
|
void object_manager_unload_objects(const rct_object_entry* entries, size_t count)
|
||||||
{
|
{
|
||||||
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
auto objectManager = OpenRCT2::GetContext()->GetObjectManager();
|
||||||
objectManager->UnloadObjects(entries, count);
|
objectManager->UnloadObjects(entries, count);
|
||||||
|
@ -681,7 +676,7 @@ void object_manager_unload_all_objects()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rct_string_id object_manager_get_source_game_string(const rct_object_entry * entry)
|
rct_string_id object_manager_get_source_game_string(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
return ObjectManager::GetObjectSourceGameString(entry);
|
return ObjectManager::GetObjectSourceGameString(entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,41 +9,44 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../object/Object.h"
|
#include "../object/Object.h"
|
||||||
|
|
||||||
interface IObjectRepository;
|
#include <vector>
|
||||||
class Object;
|
|
||||||
struct ObjectRepositoryItem;
|
interface IObjectRepository;
|
||||||
|
class Object;
|
||||||
|
struct ObjectRepositoryItem;
|
||||||
|
|
||||||
interface IObjectManager
|
interface IObjectManager
|
||||||
{
|
{
|
||||||
virtual ~IObjectManager() { }
|
virtual ~IObjectManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual Object * GetLoadedObject(size_t index) abstract;
|
virtual Object* GetLoadedObject(size_t index) abstract;
|
||||||
virtual Object * GetLoadedObject(int32_t objectType, size_t index) abstract;
|
virtual Object* GetLoadedObject(int32_t objectType, size_t index) abstract;
|
||||||
virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract;
|
virtual Object* GetLoadedObject(const rct_object_entry* entry) abstract;
|
||||||
virtual uint8_t GetLoadedObjectEntryIndex(const Object * object) abstract;
|
virtual uint8_t GetLoadedObjectEntryIndex(const Object* object) abstract;
|
||||||
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) abstract;
|
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry* entries) abstract;
|
||||||
|
|
||||||
virtual Object * LoadObject(const rct_object_entry * entry) abstract;
|
virtual Object* LoadObject(const rct_object_entry* entry) abstract;
|
||||||
virtual void LoadObjects(const rct_object_entry * entries, size_t count) abstract;
|
virtual void LoadObjects(const rct_object_entry* entries, size_t count) abstract;
|
||||||
virtual void LoadDefaultObjects() abstract;
|
virtual void LoadDefaultObjects() abstract;
|
||||||
virtual void UnloadObjects(const rct_object_entry * entries, size_t count) abstract;
|
virtual void UnloadObjects(const rct_object_entry* entries, size_t count) abstract;
|
||||||
virtual void UnloadAll() abstract;
|
virtual void UnloadAll() abstract;
|
||||||
|
|
||||||
virtual void ResetObjects() abstract;
|
virtual void ResetObjects() abstract;
|
||||||
|
|
||||||
virtual std::vector<const ObjectRepositoryItem *> GetPackableObjects() abstract;
|
virtual std::vector<const ObjectRepositoryItem*> GetPackableObjects() abstract;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IObjectManager> CreateObjectManager(std::shared_ptr<IObjectRepository> objectRepository);
|
std::unique_ptr<IObjectManager> CreateObjectManager(std::shared_ptr<IObjectRepository> objectRepository);
|
||||||
|
|
||||||
void * object_manager_get_loaded_object_by_index(size_t index);
|
void* object_manager_get_loaded_object_by_index(size_t index);
|
||||||
void * object_manager_get_loaded_object(const rct_object_entry * entry);
|
void* object_manager_get_loaded_object(const rct_object_entry* entry);
|
||||||
uint8_t object_manager_get_loaded_object_entry_index(const void * loadedObject);
|
uint8_t object_manager_get_loaded_object_entry_index(const void* loadedObject);
|
||||||
void * object_manager_load_object(const rct_object_entry * entry);
|
void* object_manager_load_object(const rct_object_entry* entry);
|
||||||
void object_manager_unload_objects(const rct_object_entry * entries, size_t count);
|
void object_manager_unload_objects(const rct_object_entry* entries, size_t count);
|
||||||
void object_manager_unload_all_objects();
|
void object_manager_unload_all_objects();
|
||||||
rct_string_id object_manager_get_source_game_string(const rct_object_entry * entry);
|
rct_string_id object_manager_get_source_game_string(const rct_object_entry* entry);
|
||||||
|
|
|
@ -7,13 +7,12 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <algorithm>
|
#include "ObjectRepository.h"
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "../common.h"
|
|
||||||
#include "../Context.h"
|
#include "../Context.h"
|
||||||
|
#include "../PlatformEnvironment.h"
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../config/Config.h"
|
||||||
#include "../core/Console.hpp"
|
#include "../core/Console.hpp"
|
||||||
#include "../core/FileIndex.hpp"
|
#include "../core/FileIndex.hpp"
|
||||||
#include "../core/FileStream.hpp"
|
#include "../core/FileStream.hpp"
|
||||||
|
@ -23,31 +22,32 @@
|
||||||
#include "../core/MemoryStream.h"
|
#include "../core/MemoryStream.h"
|
||||||
#include "../core/Path.hpp"
|
#include "../core/Path.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
#include "../PlatformEnvironment.h"
|
|
||||||
#include "../rct12/SawyerChunkReader.h"
|
|
||||||
#include "../rct12/SawyerChunkWriter.h"
|
|
||||||
#include "../scenario/ScenarioRepository.h"
|
|
||||||
#include "Object.h"
|
|
||||||
#include "ObjectFactory.h"
|
|
||||||
#include "ObjectManager.h"
|
|
||||||
#include "ObjectRepository.h"
|
|
||||||
#include "RideObject.h"
|
|
||||||
#include "StexObject.h"
|
|
||||||
|
|
||||||
#include "../config/Config.h"
|
|
||||||
#include "../localisation/Localisation.h"
|
#include "../localisation/Localisation.h"
|
||||||
#include "../localisation/LocalisationService.h"
|
#include "../localisation/LocalisationService.h"
|
||||||
#include "../object/Object.h"
|
#include "../object/Object.h"
|
||||||
#include "ObjectList.h"
|
|
||||||
#include "../platform/platform.h"
|
#include "../platform/platform.h"
|
||||||
|
#include "../rct12/SawyerChunkReader.h"
|
||||||
|
#include "../rct12/SawyerChunkWriter.h"
|
||||||
|
#include "../scenario/ScenarioRepository.h"
|
||||||
#include "../util/SawyerCoding.h"
|
#include "../util/SawyerCoding.h"
|
||||||
#include "../util/Util.h"
|
#include "../util/Util.h"
|
||||||
|
#include "Object.h"
|
||||||
|
#include "ObjectFactory.h"
|
||||||
|
#include "ObjectList.h"
|
||||||
|
#include "ObjectManager.h"
|
||||||
|
#include "RideObject.h"
|
||||||
|
#include "StexObject.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace OpenRCT2;
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
struct ObjectEntryHash
|
struct ObjectEntryHash
|
||||||
{
|
{
|
||||||
size_t operator()(const rct_object_entry &entry) const
|
size_t operator()(const rct_object_entry& entry) const
|
||||||
{
|
{
|
||||||
uint32_t hash = 5381;
|
uint32_t hash = 5381;
|
||||||
for (auto i : entry.name)
|
for (auto i : entry.name)
|
||||||
|
@ -60,7 +60,7 @@ struct ObjectEntryHash
|
||||||
|
|
||||||
struct ObjectEntryEqual
|
struct ObjectEntryEqual
|
||||||
{
|
{
|
||||||
bool operator()(const rct_object_entry &lhs, const rct_object_entry &rhs) const
|
bool operator()(const rct_object_entry& lhs, const rct_object_entry& rhs) const
|
||||||
{
|
{
|
||||||
return memcmp(&lhs.name, &rhs.name, 8) == 0;
|
return memcmp(&lhs.name, &rhs.name, 8) == 0;
|
||||||
}
|
}
|
||||||
|
@ -78,23 +78,23 @@ private:
|
||||||
IObjectRepository& _objectRepository;
|
IObjectRepository& _objectRepository;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ObjectFileIndex(IObjectRepository& objectRepository, const IPlatformEnvironment& env) :
|
explicit ObjectFileIndex(IObjectRepository& objectRepository, const IPlatformEnvironment& env)
|
||||||
FileIndex("object index",
|
: FileIndex(
|
||||||
MAGIC_NUMBER,
|
"object index",
|
||||||
VERSION,
|
MAGIC_NUMBER,
|
||||||
env.GetFilePath(PATHID::CACHE_OBJECTS),
|
VERSION,
|
||||||
std::string(PATTERN),
|
env.GetFilePath(PATHID::CACHE_OBJECTS),
|
||||||
std::vector<std::string>({
|
std::string(PATTERN),
|
||||||
env.GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT),
|
std::vector<std::string>({ env.GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT),
|
||||||
env.GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) })),
|
env.GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) }))
|
||||||
_objectRepository(objectRepository)
|
, _objectRepository(objectRepository)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::tuple<bool, ObjectRepositoryItem> Create([[maybe_unused]] int32_t language, const std::string& path) const override
|
std::tuple<bool, ObjectRepositoryItem> Create([[maybe_unused]] int32_t language, const std::string& path) const override
|
||||||
{
|
{
|
||||||
Object * object = nullptr;
|
Object* object = nullptr;
|
||||||
auto extension = Path::GetExtension(path);
|
auto extension = Path::GetExtension(path);
|
||||||
if (String::Equals(extension, ".json", true))
|
if (String::Equals(extension, ".json", true))
|
||||||
{
|
{
|
||||||
|
@ -122,36 +122,37 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Serialise(IStream * stream, const ObjectRepositoryItem &item) const override
|
void Serialise(IStream* stream, const ObjectRepositoryItem& item) const override
|
||||||
{
|
{
|
||||||
stream->WriteValue(item.ObjectEntry);
|
stream->WriteValue(item.ObjectEntry);
|
||||||
stream->WriteString(item.Path);
|
stream->WriteString(item.Path);
|
||||||
stream->WriteString(item.Name);
|
stream->WriteString(item.Name);
|
||||||
|
|
||||||
switch (object_entry_get_type(&item.ObjectEntry)) {
|
switch (object_entry_get_type(&item.ObjectEntry))
|
||||||
case OBJECT_TYPE_RIDE:
|
{
|
||||||
stream->WriteValue<uint8_t>(item.RideInfo.RideFlags);
|
case OBJECT_TYPE_RIDE:
|
||||||
for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++)
|
stream->WriteValue<uint8_t>(item.RideInfo.RideFlags);
|
||||||
{
|
for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++)
|
||||||
stream->WriteValue<uint8_t>(item.RideInfo.RideCategory[i]);
|
{
|
||||||
}
|
stream->WriteValue<uint8_t>(item.RideInfo.RideCategory[i]);
|
||||||
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
|
}
|
||||||
{
|
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
|
||||||
stream->WriteValue<uint8_t>(item.RideInfo.RideType[i]);
|
{
|
||||||
}
|
stream->WriteValue<uint8_t>(item.RideInfo.RideType[i]);
|
||||||
stream->WriteValue<uint8_t>(item.RideInfo.RideGroupIndex);
|
}
|
||||||
break;
|
stream->WriteValue<uint8_t>(item.RideInfo.RideGroupIndex);
|
||||||
case OBJECT_TYPE_SCENERY_GROUP:
|
break;
|
||||||
stream->WriteValue<uint16_t>((uint16_t)item.SceneryGroupInfo.Entries.size());
|
case OBJECT_TYPE_SCENERY_GROUP:
|
||||||
for (const auto& entry : item.SceneryGroupInfo.Entries)
|
stream->WriteValue<uint16_t>((uint16_t)item.SceneryGroupInfo.Entries.size());
|
||||||
{
|
for (const auto& entry : item.SceneryGroupInfo.Entries)
|
||||||
stream->WriteValue<rct_object_entry>(entry);
|
{
|
||||||
}
|
stream->WriteValue<rct_object_entry>(entry);
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectRepositoryItem Deserialise(IStream * stream) const override
|
ObjectRepositoryItem Deserialise(IStream* stream) const override
|
||||||
{
|
{
|
||||||
ObjectRepositoryItem item;
|
ObjectRepositoryItem item;
|
||||||
|
|
||||||
|
@ -159,20 +160,21 @@ protected:
|
||||||
item.Path = stream->ReadStdString();
|
item.Path = stream->ReadStdString();
|
||||||
item.Name = stream->ReadStdString();
|
item.Name = stream->ReadStdString();
|
||||||
|
|
||||||
switch (object_entry_get_type(&item.ObjectEntry)) {
|
switch (object_entry_get_type(&item.ObjectEntry))
|
||||||
case OBJECT_TYPE_RIDE:
|
{
|
||||||
item.RideInfo.RideFlags = stream->ReadValue<uint8_t>();
|
case OBJECT_TYPE_RIDE:
|
||||||
for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++)
|
item.RideInfo.RideFlags = stream->ReadValue<uint8_t>();
|
||||||
{
|
for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++)
|
||||||
item.RideInfo.RideCategory[i] = stream->ReadValue<uint8_t>();
|
{
|
||||||
}
|
item.RideInfo.RideCategory[i] = stream->ReadValue<uint8_t>();
|
||||||
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
|
}
|
||||||
{
|
for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
|
||||||
item.RideInfo.RideType[i] = stream->ReadValue<uint8_t>();
|
{
|
||||||
}
|
item.RideInfo.RideType[i] = stream->ReadValue<uint8_t>();
|
||||||
item.RideInfo.RideGroupIndex = stream->ReadValue<uint8_t>();
|
}
|
||||||
break;
|
item.RideInfo.RideGroupIndex = stream->ReadValue<uint8_t>();
|
||||||
case OBJECT_TYPE_SCENERY_GROUP:
|
break;
|
||||||
|
case OBJECT_TYPE_SCENERY_GROUP:
|
||||||
{
|
{
|
||||||
auto numEntries = stream->ReadValue<uint16_t>();
|
auto numEntries = stream->ReadValue<uint16_t>();
|
||||||
item.SceneryGroupInfo.Entries = std::vector<rct_object_entry>(numEntries);
|
item.SceneryGroupInfo.Entries = std::vector<rct_object_entry>(numEntries);
|
||||||
|
@ -187,11 +189,9 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsTrackReadOnly(const std::string &path) const
|
bool IsTrackReadOnly(const std::string& path) const
|
||||||
{
|
{
|
||||||
return
|
return String::StartsWith(path, SearchPaths[0]) || String::StartsWith(path, SearchPaths[1]);
|
||||||
String::StartsWith(path, SearchPaths[0]) ||
|
|
||||||
String::StartsWith(path, SearchPaths[1]);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -204,8 +204,8 @@ class ObjectRepository final : public IObjectRepository
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ObjectRepository(const std::shared_ptr<IPlatformEnvironment>& env)
|
explicit ObjectRepository(const std::shared_ptr<IPlatformEnvironment>& env)
|
||||||
: _env(env),
|
: _env(env)
|
||||||
_fileIndex(*this, *env)
|
, _fileIndex(*this, *env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,12 +234,12 @@ public:
|
||||||
return _items.size();
|
return _items.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObjectRepositoryItem * GetObjects() const override
|
const ObjectRepositoryItem* GetObjects() const override
|
||||||
{
|
{
|
||||||
return _items.data();
|
return _items.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObjectRepositoryItem * FindObject(const utf8 * name) const override
|
const ObjectRepositoryItem* FindObject(const utf8* name) const override
|
||||||
{
|
{
|
||||||
rct_object_entry entry = {};
|
rct_object_entry entry = {};
|
||||||
utf8 entryName[9] = { ' ' };
|
utf8 entryName[9] = { ' ' };
|
||||||
|
@ -254,7 +254,7 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObjectRepositoryItem * FindObject(const rct_object_entry * objectEntry) const override final
|
const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const override final
|
||||||
{
|
{
|
||||||
auto kvp = _itemMap.find(*objectEntry);
|
auto kvp = _itemMap.find(*objectEntry);
|
||||||
if (kvp != _itemMap.end())
|
if (kvp != _itemMap.end())
|
||||||
|
@ -264,7 +264,7 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object * LoadObject(const ObjectRepositoryItem * ori) override
|
Object* LoadObject(const ObjectRepositoryItem* ori) override
|
||||||
{
|
{
|
||||||
Guard::ArgumentNotNull(ori, GUARD_LINE);
|
Guard::ArgumentNotNull(ori, GUARD_LINE);
|
||||||
|
|
||||||
|
@ -283,30 +283,30 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override
|
void RegisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) override
|
||||||
{
|
{
|
||||||
ObjectRepositoryItem * item = &_items[ori->Id];
|
ObjectRepositoryItem* item = &_items[ori->Id];
|
||||||
|
|
||||||
Guard::Assert(item->LoadedObject == nullptr, GUARD_LINE);
|
Guard::Assert(item->LoadedObject == nullptr, GUARD_LINE);
|
||||||
item->LoadedObject = object;
|
item->LoadedObject = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnregisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override
|
void UnregisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) override
|
||||||
{
|
{
|
||||||
ObjectRepositoryItem * item = &_items[ori->Id];
|
ObjectRepositoryItem* item = &_items[ori->Id];
|
||||||
if (item->LoadedObject == object)
|
if (item->LoadedObject == object)
|
||||||
{
|
{
|
||||||
item->LoadedObject = nullptr;
|
item->LoadedObject = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddObject(const rct_object_entry * objectEntry, const void * data, size_t dataSize) override
|
void AddObject(const rct_object_entry* objectEntry, const void* data, size_t dataSize) override
|
||||||
{
|
{
|
||||||
utf8 objectName[9];
|
utf8 objectName[9];
|
||||||
object_entry_get_name_fixed(objectName, sizeof(objectName), objectEntry);
|
object_entry_get_name_fixed(objectName, sizeof(objectName), objectEntry);
|
||||||
|
|
||||||
// Check that the object is loadable before writing it
|
// Check that the object is loadable before writing it
|
||||||
Object * object = ObjectFactory::CreateObjectFromLegacyData(*this, objectEntry, data, dataSize);
|
Object* object = ObjectFactory::CreateObjectFromLegacyData(*this, objectEntry, data, dataSize);
|
||||||
if (object == nullptr)
|
if (object == nullptr)
|
||||||
{
|
{
|
||||||
Console::Error::WriteLine("[%s] Unable to export object.", objectName);
|
Console::Error::WriteLine("[%s] Unable to export object.", objectName);
|
||||||
|
@ -322,14 +322,14 @@ public:
|
||||||
SaveObject(path, objectEntry, data, dataSize);
|
SaveObject(path, objectEntry, data, dataSize);
|
||||||
ScanObject(path);
|
ScanObject(path);
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
Console::Error::WriteLine("Failed saving object: [%s] to '%s'.", objectName, path);
|
Console::Error::WriteLine("Failed saving object: [%s] to '%s'.", objectName, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportPackedObject(IStream * stream) override
|
void ExportPackedObject(IStream* stream) override
|
||||||
{
|
{
|
||||||
auto chunkReader = SawyerChunkReader(stream);
|
auto chunkReader = SawyerChunkReader(stream);
|
||||||
|
|
||||||
|
@ -347,10 +347,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem *> &objects) override
|
void WritePackedObjects(IStream* stream, std::vector<const ObjectRepositoryItem*>& objects) override
|
||||||
{
|
{
|
||||||
log_verbose("packing %u objects", objects.size());
|
log_verbose("packing %u objects", objects.size());
|
||||||
for (const auto &object : objects)
|
for (const auto& object : objects)
|
||||||
{
|
{
|
||||||
Guard::ArgumentNotNull(object);
|
Guard::ArgumentNotNull(object);
|
||||||
|
|
||||||
|
@ -375,9 +375,7 @@ private:
|
||||||
|
|
||||||
void SortItems()
|
void SortItems()
|
||||||
{
|
{
|
||||||
std::sort(_items.begin(), _items.end(), [](const ObjectRepositoryItem &a,
|
std::sort(_items.begin(), _items.end(), [](const ObjectRepositoryItem& a, const ObjectRepositoryItem& b) -> bool {
|
||||||
const ObjectRepositoryItem &b) -> bool
|
|
||||||
{
|
|
||||||
return String::Compare(a.Name, b.Name) < 0;
|
return String::Compare(a.Name, b.Name) < 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -396,7 +394,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddItems(const std::vector<ObjectRepositoryItem> &items)
|
void AddItems(const std::vector<ObjectRepositoryItem>& items)
|
||||||
{
|
{
|
||||||
size_t numConflicts = 0;
|
size_t numConflicts = 0;
|
||||||
for (auto item : items)
|
for (auto item : items)
|
||||||
|
@ -412,7 +410,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddItem(const ObjectRepositoryItem &item)
|
bool AddItem(const ObjectRepositoryItem& item)
|
||||||
{
|
{
|
||||||
auto conflict = FindObject(&item.ObjectEntry);
|
auto conflict = FindObject(&item.ObjectEntry);
|
||||||
if (conflict == nullptr)
|
if (conflict == nullptr)
|
||||||
|
@ -432,7 +430,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanObject(const std::string &path)
|
void ScanObject(const std::string& path)
|
||||||
{
|
{
|
||||||
auto language = LocalisationService_GetCurrentLanguage();
|
auto language = LocalisationService_GetCurrentLanguage();
|
||||||
auto result = _fileIndex.Create(language, path);
|
auto result = _fileIndex.Create(language, path);
|
||||||
|
@ -443,10 +441,8 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SaveObject(const utf8 * path,
|
static void
|
||||||
const rct_object_entry * entry,
|
SaveObject(const utf8* path, const rct_object_entry* entry, const void* data, size_t dataSize, bool fixChecksum = true)
|
||||||
const void * data, size_t dataSize,
|
|
||||||
bool fixChecksum = true)
|
|
||||||
{
|
{
|
||||||
if (fixChecksum)
|
if (fixChecksum)
|
||||||
{
|
{
|
||||||
|
@ -460,14 +456,14 @@ private:
|
||||||
// Calculate the value of extra bytes that can be appended to the data so that the
|
// Calculate the value of extra bytes that can be appended to the data so that the
|
||||||
// data is then valid for the object's checksum
|
// data is then valid for the object's checksum
|
||||||
size_t extraBytesCount = 0;
|
size_t extraBytesCount = 0;
|
||||||
void * extraBytes = CalculateExtraBytesToFixChecksum(realChecksum, entry->checksum, &extraBytesCount);
|
void* extraBytes = CalculateExtraBytesToFixChecksum(realChecksum, entry->checksum, &extraBytesCount);
|
||||||
|
|
||||||
// Create new data blob with appended bytes
|
// Create new data blob with appended bytes
|
||||||
size_t newDataSize = dataSize + extraBytesCount;
|
size_t newDataSize = dataSize + extraBytesCount;
|
||||||
uint8_t * newData = Memory::Allocate<uint8_t>(newDataSize);
|
uint8_t* newData = Memory::Allocate<uint8_t>(newDataSize);
|
||||||
uint8_t * newDataSaltOffset = newData + dataSize;
|
uint8_t* newDataSaltOffset = newData + dataSize;
|
||||||
std::copy_n((const uint8_t *)data, dataSize, newData);
|
std::copy_n((const uint8_t*)data, dataSize, newData);
|
||||||
std::copy_n((const uint8_t *)extraBytes, extraBytesCount, newDataSaltOffset);
|
std::copy_n((const uint8_t*)extraBytes, extraBytesCount, newDataSaltOffset);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -487,7 +483,7 @@ private:
|
||||||
Memory::Free(newData);
|
Memory::Free(newData);
|
||||||
Memory::Free(extraBytes);
|
Memory::Free(extraBytes);
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
Memory::Free(newData);
|
Memory::Free(newData);
|
||||||
Memory::Free(extraBytes);
|
Memory::Free(extraBytes);
|
||||||
|
@ -502,8 +498,8 @@ private:
|
||||||
sawyercoding_chunk_header chunkHeader;
|
sawyercoding_chunk_header chunkHeader;
|
||||||
chunkHeader.encoding = object_entry_group_encoding[objectType];
|
chunkHeader.encoding = object_entry_group_encoding[objectType];
|
||||||
chunkHeader.length = (uint32_t)dataSize;
|
chunkHeader.length = (uint32_t)dataSize;
|
||||||
uint8_t * encodedDataBuffer = Memory::Allocate<uint8_t>(0x600000);
|
uint8_t* encodedDataBuffer = Memory::Allocate<uint8_t>(0x600000);
|
||||||
size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (uint8_t *)data, chunkHeader);
|
size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (uint8_t*)data, chunkHeader);
|
||||||
|
|
||||||
// Save to file
|
// Save to file
|
||||||
try
|
try
|
||||||
|
@ -514,18 +510,19 @@ private:
|
||||||
|
|
||||||
Memory::Free(encodedDataBuffer);
|
Memory::Free(encodedDataBuffer);
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
Memory::Free(encodedDataBuffer);
|
Memory::Free(encodedDataBuffer);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void * CalculateExtraBytesToFixChecksum(int32_t currentChecksum, int32_t targetChecksum, size_t * outSize)
|
static void* CalculateExtraBytesToFixChecksum(int32_t currentChecksum, int32_t targetChecksum, size_t* outSize)
|
||||||
{
|
{
|
||||||
// Allocate 11 extra bytes to manipulate the checksum
|
// Allocate 11 extra bytes to manipulate the checksum
|
||||||
uint8_t * salt = Memory::Allocate<uint8_t>(11);
|
uint8_t* salt = Memory::Allocate<uint8_t>(11);
|
||||||
if (outSize != nullptr) *outSize = 11;
|
if (outSize != nullptr)
|
||||||
|
*outSize = 11;
|
||||||
|
|
||||||
// Next work out which bits need to be flipped to make the current checksum match the one in the file
|
// Next work out which bits need to be flipped to make the current checksum match the one in the file
|
||||||
// The bitwise rotation compensates for the rotation performed during the checksum calculation*/
|
// The bitwise rotation compensates for the rotation performed during the checksum calculation*/
|
||||||
|
@ -550,7 +547,7 @@ private:
|
||||||
return salt;
|
return salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetPathForNewObject(utf8 * buffer, size_t bufferSize, const char * name)
|
void GetPathForNewObject(utf8* buffer, size_t bufferSize, const char* name)
|
||||||
{
|
{
|
||||||
char normalisedName[9] = { 0 };
|
char normalisedName[9] = { 0 };
|
||||||
for (int32_t i = 0; i < 8; i++)
|
for (int32_t i = 0; i < 8; i++)
|
||||||
|
@ -565,7 +562,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &userObjPath = _env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT);
|
const std::string& userObjPath = _env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT);
|
||||||
String::Set(buffer, bufferSize, userObjPath.c_str());
|
String::Set(buffer, bufferSize, userObjPath.c_str());
|
||||||
platform_ensure_directory_exists(buffer);
|
platform_ensure_directory_exists(buffer);
|
||||||
|
|
||||||
|
@ -586,9 +583,9 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WritePackedObject(IStream * stream, const rct_object_entry * entry)
|
void WritePackedObject(IStream* stream, const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
const ObjectRepositoryItem * item = FindObject(entry);
|
const ObjectRepositoryItem* item = FindObject(entry);
|
||||||
if (item == nullptr)
|
if (item == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(String::StdFormat("Unable to find object '%.8s'", entry->name));
|
throw std::runtime_error(String::StdFormat("Unable to find object '%.8s'", entry->name));
|
||||||
|
@ -616,7 +613,7 @@ std::unique_ptr<IObjectRepository> CreateObjectRepository(const std::shared_ptr<
|
||||||
return std::make_unique<ObjectRepository>(env);
|
return std::make_unique<ObjectRepository>(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsObjectCustom(const ObjectRepositoryItem * object)
|
bool IsObjectCustom(const ObjectRepositoryItem* object)
|
||||||
{
|
{
|
||||||
Guard::ArgumentNotNull(object);
|
Guard::ArgumentNotNull(object);
|
||||||
|
|
||||||
|
@ -624,9 +621,9 @@ bool IsObjectCustom(const ObjectRepositoryItem * object)
|
||||||
return !(object->ObjectEntry.flags & 0xF0);
|
return !(object->ObjectEntry.flags & 0xF0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rct_object_entry * object_list_find(rct_object_entry * entry)
|
const rct_object_entry* object_list_find(rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
const rct_object_entry * result = nullptr;
|
const rct_object_entry* result = nullptr;
|
||||||
auto objRepo = GetContext()->GetObjectRepository();
|
auto objRepo = GetContext()->GetObjectRepository();
|
||||||
auto item = objRepo->FindObject(entry);
|
auto item = objRepo->FindObject(entry);
|
||||||
if (item != nullptr)
|
if (item != nullptr)
|
||||||
|
@ -647,11 +644,11 @@ void object_list_load()
|
||||||
objectManager->UnloadAll();
|
objectManager->UnloadAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void * object_repository_load_object(const rct_object_entry * objectEntry)
|
void* object_repository_load_object(const rct_object_entry* objectEntry)
|
||||||
{
|
{
|
||||||
Object * object = nullptr;
|
Object* object = nullptr;
|
||||||
auto objRepository = GetContext()->GetObjectRepository();
|
auto objRepository = GetContext()->GetObjectRepository();
|
||||||
const ObjectRepositoryItem * ori = objRepository->FindObject(objectEntry);
|
const ObjectRepositoryItem* ori = objRepository->FindObject(objectEntry);
|
||||||
if (ori != nullptr)
|
if (ori != nullptr)
|
||||||
{
|
{
|
||||||
object = objRepository->LoadObject(ori);
|
object = objRepository->LoadObject(ori);
|
||||||
|
@ -660,10 +657,10 @@ void * object_repository_load_object(const rct_object_entry * objectEntry)
|
||||||
object->Load();
|
object->Load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (void *)object;
|
return (void*)object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scenario_translate(scenario_index_entry * scenarioEntry, const rct_object_entry * stexObjectEntry)
|
void scenario_translate(scenario_index_entry* scenarioEntry, const rct_object_entry* stexObjectEntry)
|
||||||
{
|
{
|
||||||
rct_string_id localisedStringIds[3];
|
rct_string_id localisedStringIds[3];
|
||||||
if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds))
|
if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds))
|
||||||
|
@ -683,10 +680,10 @@ void scenario_translate(scenario_index_entry * scenarioEntry, const rct_object_e
|
||||||
if ((stexObjectEntry->flags & 0xFF) != 255)
|
if ((stexObjectEntry->flags & 0xFF) != 255)
|
||||||
{
|
{
|
||||||
auto objectRepository = GetContext()->GetObjectRepository();
|
auto objectRepository = GetContext()->GetObjectRepository();
|
||||||
const ObjectRepositoryItem * ori = objectRepository->FindObject(stexObjectEntry);
|
const ObjectRepositoryItem* ori = objectRepository->FindObject(stexObjectEntry);
|
||||||
if (ori != nullptr)
|
if (ori != nullptr)
|
||||||
{
|
{
|
||||||
Object * object = objectRepository->LoadObject(ori);
|
Object* object = objectRepository->LoadObject(ori);
|
||||||
if (object != nullptr)
|
if (object != nullptr)
|
||||||
{
|
{
|
||||||
auto stexObject = static_cast<StexObject*>(object);
|
auto stexObject = static_cast<StexObject*>(object);
|
||||||
|
@ -709,41 +706,41 @@ size_t object_repository_get_items_count()
|
||||||
return objectRepository->GetNumObjects();
|
return objectRepository->GetNumObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObjectRepositoryItem * object_repository_get_items()
|
const ObjectRepositoryItem* object_repository_get_items()
|
||||||
{
|
{
|
||||||
auto objectRepository = GetContext()->GetObjectRepository();
|
auto objectRepository = GetContext()->GetObjectRepository();
|
||||||
return objectRepository->GetObjects();
|
return objectRepository->GetObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObjectRepositoryItem * object_repository_find_object_by_entry(const rct_object_entry * entry)
|
const ObjectRepositoryItem* object_repository_find_object_by_entry(const rct_object_entry* entry)
|
||||||
{
|
{
|
||||||
auto objectRepository = GetContext()->GetObjectRepository();
|
auto objectRepository = GetContext()->GetObjectRepository();
|
||||||
return objectRepository->FindObject(entry);
|
return objectRepository->FindObject(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObjectRepositoryItem * object_repository_find_object_by_name(const char * name)
|
const ObjectRepositoryItem* object_repository_find_object_by_name(const char* name)
|
||||||
{
|
{
|
||||||
auto objectRepository = GetContext()->GetObjectRepository();
|
auto objectRepository = GetContext()->GetObjectRepository();
|
||||||
return objectRepository->FindObject(name);
|
return objectRepository->FindObject(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_delete(void * object)
|
void object_delete(void* object)
|
||||||
{
|
{
|
||||||
if (object != nullptr)
|
if (object != nullptr)
|
||||||
{
|
{
|
||||||
Object * baseObject = static_cast<Object *>(object);
|
Object* baseObject = static_cast<Object*>(object);
|
||||||
baseObject->Unload();
|
baseObject->Unload();
|
||||||
delete baseObject;
|
delete baseObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_draw_preview(const void * object, rct_drawpixelinfo * dpi, int32_t width, int32_t height)
|
void object_draw_preview(const void* object, rct_drawpixelinfo* dpi, int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
const Object * baseObject = static_cast<const Object *>(object);
|
const Object* baseObject = static_cast<const Object*>(object);
|
||||||
baseObject->DrawPreview(dpi, width, height);
|
baseObject->DrawPreview(dpi, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool object_entry_compare(const rct_object_entry * a, const rct_object_entry * b)
|
bool object_entry_compare(const rct_object_entry* a, const rct_object_entry* b)
|
||||||
{
|
{
|
||||||
// If an official object don't bother checking checksum
|
// If an official object don't bother checking checksum
|
||||||
if ((a->flags & 0xF0) || (b->flags & 0xF0))
|
if ((a->flags & 0xF0) || (b->flags & 0xF0))
|
||||||
|
@ -777,9 +774,9 @@ bool object_entry_compare(const rct_object_entry * a, const rct_object_entry * b
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t object_calculate_checksum(const rct_object_entry * entry, const void * data, size_t dataLength)
|
int32_t object_calculate_checksum(const rct_object_entry* entry, const void* data, size_t dataLength)
|
||||||
{
|
{
|
||||||
const uint8_t * entryBytePtr = (uint8_t *)entry;
|
const uint8_t* entryBytePtr = (uint8_t*)entry;
|
||||||
|
|
||||||
uint32_t checksum = 0xF369A75B;
|
uint32_t checksum = 0xF369A75B;
|
||||||
checksum ^= entryBytePtr[0];
|
checksum ^= entryBytePtr[0];
|
||||||
|
@ -790,7 +787,7 @@ int32_t object_calculate_checksum(const rct_object_entry * entry, const void * d
|
||||||
checksum = rol32(checksum, 11);
|
checksum = rol32(checksum, 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * dataBytes = (uint8_t *)data;
|
uint8_t* dataBytes = (uint8_t*)data;
|
||||||
const size_t dataLength32 = dataLength - (dataLength & 31);
|
const size_t dataLength32 = dataLength - (dataLength & 31);
|
||||||
for (size_t i = 0; i < 32; i++)
|
for (size_t i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,14 +9,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../object/Object.h"
|
#include "../object/Object.h"
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
|
|
||||||
interface IStream;
|
#include <memory>
|
||||||
class Object;
|
#include <vector>
|
||||||
|
|
||||||
|
interface IStream;
|
||||||
|
class Object;
|
||||||
namespace OpenRCT2
|
namespace OpenRCT2
|
||||||
{
|
{
|
||||||
interface IPlatformEnvironment;
|
interface IPlatformEnvironment;
|
||||||
|
@ -31,17 +32,17 @@ struct rct_drawpixelinfo;
|
||||||
|
|
||||||
struct ObjectRepositoryItem
|
struct ObjectRepositoryItem
|
||||||
{
|
{
|
||||||
size_t Id;
|
size_t Id;
|
||||||
rct_object_entry ObjectEntry;
|
rct_object_entry ObjectEntry;
|
||||||
std::string Path;
|
std::string Path;
|
||||||
std::string Name;
|
std::string Name;
|
||||||
Object * LoadedObject{};
|
Object* LoadedObject{};
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t RideFlags;
|
uint8_t RideFlags;
|
||||||
uint8_t RideCategory[MAX_CATEGORIES_PER_RIDE];
|
uint8_t RideCategory[MAX_CATEGORIES_PER_RIDE];
|
||||||
uint8_t RideType[MAX_RIDE_TYPES_PER_RIDE_ENTRY];
|
uint8_t RideType[MAX_RIDE_TYPES_PER_RIDE_ENTRY];
|
||||||
uint8_t RideGroupIndex;
|
uint8_t RideGroupIndex;
|
||||||
} RideInfo;
|
} RideInfo;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -53,34 +54,32 @@ interface IObjectRepository
|
||||||
{
|
{
|
||||||
virtual ~IObjectRepository() = default;
|
virtual ~IObjectRepository() = default;
|
||||||
|
|
||||||
virtual void LoadOrConstruct(int32_t language) abstract;
|
virtual void LoadOrConstruct(int32_t language) abstract;
|
||||||
virtual void Construct(int32_t language) abstract;
|
virtual void Construct(int32_t language) abstract;
|
||||||
virtual size_t GetNumObjects() const abstract;
|
virtual size_t GetNumObjects() const abstract;
|
||||||
virtual const ObjectRepositoryItem * GetObjects() const abstract;
|
virtual const ObjectRepositoryItem* GetObjects() const abstract;
|
||||||
virtual const ObjectRepositoryItem * FindObject(const utf8 * name) const abstract;
|
virtual const ObjectRepositoryItem* FindObject(const utf8* name) const abstract;
|
||||||
virtual const ObjectRepositoryItem * FindObject(const rct_object_entry * objectEntry) const abstract;
|
virtual const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const abstract;
|
||||||
|
|
||||||
virtual Object * LoadObject(const ObjectRepositoryItem * ori) abstract;
|
virtual Object* LoadObject(const ObjectRepositoryItem* ori) abstract;
|
||||||
virtual void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) abstract;
|
virtual void RegisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) abstract;
|
||||||
virtual void UnregisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) abstract;
|
virtual void UnregisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) abstract;
|
||||||
|
|
||||||
virtual void AddObject(const rct_object_entry * objectEntry,
|
virtual void AddObject(const rct_object_entry* objectEntry, const void* data, size_t dataSize) abstract;
|
||||||
const void * data,
|
|
||||||
size_t dataSize) abstract;
|
|
||||||
|
|
||||||
virtual void ExportPackedObject(IStream * stream) abstract;
|
virtual void ExportPackedObject(IStream * stream) abstract;
|
||||||
virtual void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem *> &objects) abstract;
|
virtual void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem*> & objects) abstract;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IObjectRepository> CreateObjectRepository(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
|
std::unique_ptr<IObjectRepository> CreateObjectRepository(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
|
||||||
|
|
||||||
bool IsObjectCustom(const ObjectRepositoryItem * object);
|
bool IsObjectCustom(const ObjectRepositoryItem* object);
|
||||||
|
|
||||||
size_t object_repository_get_items_count();
|
size_t object_repository_get_items_count();
|
||||||
const ObjectRepositoryItem * object_repository_get_items();
|
const ObjectRepositoryItem* object_repository_get_items();
|
||||||
const ObjectRepositoryItem * object_repository_find_object_by_entry(const rct_object_entry * entry);
|
const ObjectRepositoryItem* object_repository_find_object_by_entry(const rct_object_entry* entry);
|
||||||
const ObjectRepositoryItem * object_repository_find_object_by_name(const char * name);
|
const ObjectRepositoryItem* object_repository_find_object_by_name(const char* name);
|
||||||
void * object_repository_load_object(const rct_object_entry * objectEntry);
|
void* object_repository_load_object(const rct_object_entry* objectEntry);
|
||||||
|
|
||||||
void object_delete(void * object);
|
void object_delete(void* object);
|
||||||
void object_draw_preview(const void * object, rct_drawpixelinfo * dpi, int32_t width, int32_t height);
|
void object_draw_preview(const void* object, rct_drawpixelinfo* dpi, int32_t width, int32_t height);
|
||||||
|
|
|
@ -9,32 +9,34 @@
|
||||||
|
|
||||||
#pragma warning(disable : 4706) // assignment within conditional expression
|
#pragma warning(disable : 4706) // assignment within conditional expression
|
||||||
|
|
||||||
#include <algorithm>
|
#include "RideObject.h"
|
||||||
#include <unordered_map>
|
|
||||||
|
#include "../OpenRCT2.h"
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../core/Math.hpp"
|
#include "../core/Math.hpp"
|
||||||
#include "../core/Memory.hpp"
|
#include "../core/Memory.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
#include "../core/Util.hpp"
|
#include "../core/Util.hpp"
|
||||||
#include "../ride/RideGroupManager.h"
|
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../rct2/RCT2.h"
|
#include "../rct2/RCT2.h"
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
|
#include "../ride/RideGroupManager.h"
|
||||||
#include "../ride/ShopItem.h"
|
#include "../ride/ShopItem.h"
|
||||||
#include "../ride/Track.h"
|
#include "../ride/Track.h"
|
||||||
#include "../OpenRCT2.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
#include "ObjectRepository.h"
|
#include "ObjectRepository.h"
|
||||||
#include "RideObject.h"
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace OpenRCT2;
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void RideObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(8, STREAM_SEEK_CURRENT);
|
stream->Seek(8, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.flags = stream->ReadValue<uint32_t>();
|
_legacyType.flags = stream->ReadValue<uint32_t>();
|
||||||
for (auto &rideType : _legacyType.ride_type)
|
for (auto& rideType : _legacyType.ride_type)
|
||||||
{
|
{
|
||||||
rideType = stream->ReadValue<uint8_t>();
|
rideType = stream->ReadValue<uint8_t>();
|
||||||
}
|
}
|
||||||
|
@ -49,7 +51,7 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
||||||
_legacyType.rear_vehicle = stream->ReadValue<uint8_t>();
|
_legacyType.rear_vehicle = stream->ReadValue<uint8_t>();
|
||||||
_legacyType.third_vehicle = stream->ReadValue<uint8_t>();
|
_legacyType.third_vehicle = stream->ReadValue<uint8_t>();
|
||||||
_legacyType.pad_019 = stream->ReadValue<uint8_t>();
|
_legacyType.pad_019 = stream->ReadValue<uint8_t>();
|
||||||
for (auto &vehicleEntry : _legacyType.vehicles)
|
for (auto& vehicleEntry : _legacyType.vehicles)
|
||||||
{
|
{
|
||||||
ReadLegacyVehicle(context, stream, &vehicleEntry);
|
ReadLegacyVehicle(context, stream, &vehicleEntry);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +97,7 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
||||||
{
|
{
|
||||||
numPeepLoadingPositions = stream->ReadValue<uint16_t>();
|
numPeepLoadingPositions = stream->ReadValue<uint16_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_legacyType.vehicles[i].flags & VEHICLE_ENTRY_FLAG_LOADING_WAYPOINTS)
|
if (_legacyType.vehicles[i].flags & VEHICLE_ENTRY_FLAG_LOADING_WAYPOINTS)
|
||||||
{
|
{
|
||||||
_legacyType.vehicles[i].peep_loading_waypoint_segments = stream->ReadValue<int8_t>() == 0 ? 0 : 4;
|
_legacyType.vehicles[i].peep_loading_waypoint_segments = stream->ReadValue<int8_t>() == 0 ? 0 : 4;
|
||||||
|
@ -161,15 +163,15 @@ void RideObject::Load()
|
||||||
int32_t cur_vehicle_images_offset = _legacyType.images_offset + MAX_RIDE_TYPES_PER_RIDE_ENTRY;
|
int32_t cur_vehicle_images_offset = _legacyType.images_offset + MAX_RIDE_TYPES_PER_RIDE_ENTRY;
|
||||||
for (int32_t i = 0; i < RCT2_MAX_VEHICLES_PER_RIDE_ENTRY; i++)
|
for (int32_t i = 0; i < RCT2_MAX_VEHICLES_PER_RIDE_ENTRY; i++)
|
||||||
{
|
{
|
||||||
rct_ride_entry_vehicle * vehicleEntry = &_legacyType.vehicles[i];
|
rct_ride_entry_vehicle* vehicleEntry = &_legacyType.vehicles[i];
|
||||||
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT)
|
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT)
|
||||||
{
|
{
|
||||||
// RCT2 calculates num_vertical_frames and num_horizontal_frames and overwrites these properties on the vehicle entry.
|
// RCT2 calculates num_vertical_frames and num_horizontal_frames and overwrites these properties on the vehicle
|
||||||
// Immediately afterwards, the two were multiplied in order to calculate base_num_frames and were never used again.
|
// entry. Immediately afterwards, the two were multiplied in order to calculate base_num_frames and were never used
|
||||||
// This has been changed to use the calculation results directly -
|
// again. This has been changed to use the calculation results directly - num_vertical_frames and
|
||||||
// num_vertical_frames and num_horizontal_frames are no longer set on the vehicle entry.
|
// num_horizontal_frames are no longer set on the vehicle entry. 0x6DE946
|
||||||
// 0x6DE946
|
vehicleEntry->base_num_frames
|
||||||
vehicleEntry->base_num_frames = CalculateNumVerticalFrames(vehicleEntry) * CalculateNumHorizontalFrames(vehicleEntry);
|
= CalculateNumVerticalFrames(vehicleEntry) * CalculateNumHorizontalFrames(vehicleEntry);
|
||||||
vehicleEntry->base_image_id = cur_vehicle_images_offset;
|
vehicleEntry->base_image_id = cur_vehicle_images_offset;
|
||||||
int32_t image_index = vehicleEntry->base_image_id;
|
int32_t image_index = vehicleEntry->base_image_id;
|
||||||
|
|
||||||
|
@ -177,8 +179,10 @@ void RideObject::Load()
|
||||||
{
|
{
|
||||||
int32_t b = vehicleEntry->base_num_frames * 32;
|
int32_t b = vehicleEntry->base_num_frames * 32;
|
||||||
|
|
||||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_11) b /= 2;
|
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_11)
|
||||||
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_15) b /= 8;
|
b /= 2;
|
||||||
|
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_15)
|
||||||
|
b /= 8;
|
||||||
|
|
||||||
image_index += b;
|
image_index += b;
|
||||||
|
|
||||||
|
@ -305,7 +309,8 @@ void RideObject::Load()
|
||||||
num_images *= 2;
|
num_images *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gOpenRCT2NoGraphics) {
|
if (!gOpenRCT2NoGraphics)
|
||||||
|
{
|
||||||
set_vehicle_type_image_max_sizes(vehicleEntry, num_images);
|
set_vehicle_type_image_max_sizes(vehicleEntry, num_images);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,7 +366,7 @@ std::string RideObject::GetCapacity() const
|
||||||
return GetString(OBJ_STRING_ID_CAPACITY);
|
return GetString(OBJ_STRING_ID_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RideObject::SetRepositoryItem(ObjectRepositoryItem * item) const
|
void RideObject::SetRepositoryItem(ObjectRepositoryItem* item) const
|
||||||
{
|
{
|
||||||
for (int32_t i = 0; i < RCT2_MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
|
for (int32_t i = 0; i < RCT2_MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++)
|
||||||
{
|
{
|
||||||
|
@ -381,14 +386,14 @@ void RideObject::SetRepositoryItem(ObjectRepositoryItem * item) const
|
||||||
// Determines the ride group. Will fall back to 0 if there is none found.
|
// Determines the ride group. Will fall back to 0 if there is none found.
|
||||||
uint8_t rideGroupIndex = 0;
|
uint8_t rideGroupIndex = 0;
|
||||||
|
|
||||||
const RideGroup * rideGroup = RideGroupManager::GetRideGroup(rideTypeIdx, &_legacyType);
|
const RideGroup* rideGroup = RideGroupManager::GetRideGroup(rideTypeIdx, &_legacyType);
|
||||||
|
|
||||||
// If the ride group is nullptr, the track type does not have ride groups.
|
// If the ride group is nullptr, the track type does not have ride groups.
|
||||||
if (rideGroup != nullptr)
|
if (rideGroup != nullptr)
|
||||||
{
|
{
|
||||||
for (uint8_t i = rideGroupIndex + 1; i < MAX_RIDE_GROUPS_PER_RIDE_TYPE; i++)
|
for (uint8_t i = rideGroupIndex + 1; i < MAX_RIDE_GROUPS_PER_RIDE_TYPE; i++)
|
||||||
{
|
{
|
||||||
const RideGroup * irg = RideGroupManager::RideGroupFind(rideTypeIdx, i);
|
const RideGroup* irg = RideGroupManager::RideGroupFind(rideTypeIdx, i);
|
||||||
|
|
||||||
if (irg != nullptr)
|
if (irg != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -437,7 +442,7 @@ void RideObject::ReadLegacyVehicle(
|
||||||
stream->Seek(4, STREAM_SEEK_CURRENT);
|
stream->Seek(4, STREAM_SEEK_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry)
|
uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle* vehicleEntry)
|
||||||
{
|
{
|
||||||
// 0x6DE90B
|
// 0x6DE90B
|
||||||
uint8_t numVerticalFrames;
|
uint8_t numVerticalFrames;
|
||||||
|
@ -449,7 +454,8 @@ uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle * ve
|
||||||
{
|
{
|
||||||
if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES))
|
if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES))
|
||||||
{
|
{
|
||||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION && vehicleEntry->animation != VEHICLE_ENTRY_ANIMATION_OBSERVATION_TOWER)
|
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION
|
||||||
|
&& vehicleEntry->animation != VEHICLE_ENTRY_ANIMATION_OBSERVATION_TOWER)
|
||||||
{
|
{
|
||||||
if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS))
|
if (!(vehicleEntry->flags & VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS))
|
||||||
{
|
{
|
||||||
|
@ -474,7 +480,7 @@ uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle * ve
|
||||||
return numVerticalFrames;
|
return numVerticalFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * vehicleEntry)
|
uint8_t RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle* vehicleEntry)
|
||||||
{
|
{
|
||||||
uint8_t numHorizontalFrames;
|
uint8_t numHorizontalFrames;
|
||||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SWINGING)
|
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SWINGING)
|
||||||
|
@ -507,7 +513,7 @@ uint8_t RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle *
|
||||||
return numHorizontalFrames;
|
return numHorizontalFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RideObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void RideObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
|
|
||||||
|
@ -547,7 +553,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
||||||
if (IsRideTypeShopOrFacility(_legacyType.ride_type[0]))
|
if (IsRideTypeShopOrFacility(_legacyType.ride_type[0]))
|
||||||
{
|
{
|
||||||
// Standard car info for a shop
|
// Standard car info for a shop
|
||||||
auto &car = _legacyType.vehicles[0];
|
auto& car = _legacyType.vehicles[0];
|
||||||
car.spacing = 544;
|
car.spacing = 544;
|
||||||
car.sprite_flags = VEHICLE_SPRITE_FLAG_FLAT;
|
car.sprite_flags = VEHICLE_SPRITE_FLAG_FLAT;
|
||||||
car.sprite_width = 1;
|
car.sprite_width = 1;
|
||||||
|
@ -620,19 +626,20 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
||||||
_presetColours = ReadJsonCarColours(json_object_get(properties, "carColours"));
|
_presetColours = ReadJsonCarColours(json_object_get(properties, "carColours"));
|
||||||
}
|
}
|
||||||
|
|
||||||
_legacyType.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(properties, {
|
_legacyType.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(
|
||||||
{ "noInversions", RIDE_ENTRY_FLAG_NO_INVERSIONS },
|
properties,
|
||||||
{ "noBanking", RIDE_ENTRY_FLAG_NO_BANKED_TRACK },
|
{ { "noInversions", RIDE_ENTRY_FLAG_NO_INVERSIONS },
|
||||||
{ "playDepartSound", RIDE_ENTRY_FLAG_PLAY_DEPART_SOUND },
|
{ "noBanking", RIDE_ENTRY_FLAG_NO_BANKED_TRACK },
|
||||||
// Skipping "disallowWandering", no vehicle sets this flag.
|
{ "playDepartSound", RIDE_ENTRY_FLAG_PLAY_DEPART_SOUND },
|
||||||
{ "playSplashSound", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND },
|
// Skipping "disallowWandering", no vehicle sets this flag.
|
||||||
{ "playSplashSoundSlide", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND_SLIDE },
|
{ "playSplashSound", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND },
|
||||||
{ "hasShelter", RIDE_ENTRY_FLAG_COVERED_RIDE },
|
{ "playSplashSoundSlide", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND_SLIDE },
|
||||||
{ "limitAirTimeBonus", RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS },
|
{ "hasShelter", RIDE_ENTRY_FLAG_COVERED_RIDE },
|
||||||
{ "disableBreakdown", RIDE_ENTRY_FLAG_CANNOT_BREAK_DOWN },
|
{ "limitAirTimeBonus", RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS },
|
||||||
// Skipping noDoorsOverTrack, moved to ride groups.
|
{ "disableBreakdown", RIDE_ENTRY_FLAG_CANNOT_BREAK_DOWN },
|
||||||
{ "noCollisionCrashes", RIDE_ENTRY_FLAG_DISABLE_COLLISION_CRASHES },
|
// Skipping noDoorsOverTrack, moved to ride groups.
|
||||||
{ "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB } });
|
{ "noCollisionCrashes", RIDE_ENTRY_FLAG_DISABLE_COLLISION_CRASHES },
|
||||||
|
{ "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB } });
|
||||||
|
|
||||||
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
|
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
|
||||||
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
||||||
|
@ -696,13 +703,13 @@ void RideObject::ReadJsonVehicleInfo([[maybe_unused]] IReadObjectContext* contex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rct_ride_entry_vehicle> RideObject::ReadJsonCars(const json_t * jCars)
|
std::vector<rct_ride_entry_vehicle> RideObject::ReadJsonCars(const json_t* jCars)
|
||||||
{
|
{
|
||||||
std::vector<rct_ride_entry_vehicle> cars;
|
std::vector<rct_ride_entry_vehicle> cars;
|
||||||
|
|
||||||
if (json_is_array(jCars))
|
if (json_is_array(jCars))
|
||||||
{
|
{
|
||||||
json_t * jCar;
|
json_t* jCar;
|
||||||
size_t index;
|
size_t index;
|
||||||
json_array_foreach(jCars, index, jCar)
|
json_array_foreach(jCars, index, jCar)
|
||||||
{
|
{
|
||||||
|
@ -718,7 +725,7 @@ std::vector<rct_ride_entry_vehicle> RideObject::ReadJsonCars(const json_t * jCar
|
||||||
return cars;
|
return cars;
|
||||||
}
|
}
|
||||||
|
|
||||||
rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar)
|
rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t* jCar)
|
||||||
{
|
{
|
||||||
rct_ride_entry_vehicle car = {};
|
rct_ride_entry_vehicle car = {};
|
||||||
car.rotation_frame_mask = ObjectJsonHelpers::GetInteger(jCar, "rotationFrameMask");
|
car.rotation_frame_mask = ObjectJsonHelpers::GetInteger(jCar, "rotationFrameMask");
|
||||||
|
@ -771,15 +778,15 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar)
|
||||||
|
|
||||||
auto numSegments = ObjectJsonHelpers::GetInteger(jCar, "numSegments");
|
auto numSegments = ObjectJsonHelpers::GetInteger(jCar, "numSegments");
|
||||||
car.peep_loading_waypoint_segments = numSegments;
|
car.peep_loading_waypoint_segments = numSegments;
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
json_t * route;
|
json_t* route;
|
||||||
json_array_foreach(jLoadingWaypoints, i, route)
|
json_array_foreach(jLoadingWaypoints, i, route)
|
||||||
{
|
{
|
||||||
if (json_is_array(route))
|
if (json_is_array(route))
|
||||||
{
|
{
|
||||||
size_t j;
|
size_t j;
|
||||||
json_t * waypoint;
|
json_t* waypoint;
|
||||||
std::array<sLocationXY8, 3> entry;
|
std::array<sLocationXY8, 3> entry;
|
||||||
json_array_foreach(route, j, waypoint)
|
json_array_foreach(route, j, waypoint)
|
||||||
{
|
{
|
||||||
|
@ -797,60 +804,62 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto jFrames = json_object_get(jCar, "frames");
|
auto jFrames = json_object_get(jCar, "frames");
|
||||||
car.sprite_flags = ObjectJsonHelpers::GetFlags<uint16_t>(jFrames, {
|
car.sprite_flags = ObjectJsonHelpers::GetFlags<uint16_t>(
|
||||||
{ "flat", VEHICLE_SPRITE_FLAG_FLAT },
|
jFrames,
|
||||||
{ "gentleSlopes", VEHICLE_SPRITE_FLAG_GENTLE_SLOPES },
|
{ { "flat", VEHICLE_SPRITE_FLAG_FLAT },
|
||||||
{ "steepSlopes", VEHICLE_SPRITE_FLAG_STEEP_SLOPES },
|
{ "gentleSlopes", VEHICLE_SPRITE_FLAG_GENTLE_SLOPES },
|
||||||
{ "verticalSlopes", VEHICLE_SPRITE_FLAG_VERTICAL_SLOPES },
|
{ "steepSlopes", VEHICLE_SPRITE_FLAG_STEEP_SLOPES },
|
||||||
{ "diagonalSlopes", VEHICLE_SPRITE_FLAG_DIAGONAL_SLOPES },
|
{ "verticalSlopes", VEHICLE_SPRITE_FLAG_VERTICAL_SLOPES },
|
||||||
{ "flatBanked", VEHICLE_SPRITE_FLAG_FLAT_BANKED },
|
{ "diagonalSlopes", VEHICLE_SPRITE_FLAG_DIAGONAL_SLOPES },
|
||||||
{ "inlineTwists", VEHICLE_SPRITE_FLAG_INLINE_TWISTS },
|
{ "flatBanked", VEHICLE_SPRITE_FLAG_FLAT_BANKED },
|
||||||
{ "flatToGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_BANKED_TRANSITIONS },
|
{ "inlineTwists", VEHICLE_SPRITE_FLAG_INLINE_TWISTS },
|
||||||
{ "diagonalGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_DIAGONAL_GENTLE_SLOPE_BANKED_TRANSITIONS },
|
{ "flatToGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_BANKED_TRANSITIONS },
|
||||||
{ "gentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TRANSITIONS },
|
{ "diagonalGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_DIAGONAL_GENTLE_SLOPE_BANKED_TRANSITIONS },
|
||||||
{ "gentleSlopeBankedTurns", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TURNS },
|
{ "gentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TRANSITIONS },
|
||||||
{ "flatToGentleSlopeWhileBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS },
|
{ "gentleSlopeBankedTurns", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TURNS },
|
||||||
{ "corkscrews", VEHICLE_SPRITE_FLAG_CORKSCREWS },
|
{ "flatToGentleSlopeWhileBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS },
|
||||||
{ "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION },
|
{ "corkscrews", VEHICLE_SPRITE_FLAG_CORKSCREWS },
|
||||||
{ "curvedLiftHill", VEHICLE_SPRITE_FLAG_CURVED_LIFT_HILL },
|
{ "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION },
|
||||||
{ "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } });
|
{ "curvedLiftHill", VEHICLE_SPRITE_FLAG_CURVED_LIFT_HILL },
|
||||||
|
{ "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } });
|
||||||
|
|
||||||
car.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(jCar, {
|
car.flags |= ObjectJsonHelpers::GetFlags<uint32_t>(
|
||||||
{ "VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY", VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY },
|
jCar,
|
||||||
{ "VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS", VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS },
|
{ { "VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY", VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY },
|
||||||
{ "VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH", VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH },
|
{ "VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS", VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS },
|
||||||
{ "VEHICLE_ENTRY_FLAG_MINI_GOLF", VEHICLE_ENTRY_FLAG_MINI_GOLF },
|
{ "VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH", VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH },
|
||||||
{ "VEHICLE_ENTRY_FLAG_4", VEHICLE_ENTRY_FLAG_4 },
|
{ "VEHICLE_ENTRY_FLAG_MINI_GOLF", VEHICLE_ENTRY_FLAG_MINI_GOLF },
|
||||||
{ "VEHICLE_ENTRY_FLAG_5", VEHICLE_ENTRY_FLAG_5 },
|
{ "VEHICLE_ENTRY_FLAG_4", VEHICLE_ENTRY_FLAG_4 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET", VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET },
|
{ "VEHICLE_ENTRY_FLAG_5", VEHICLE_ENTRY_FLAG_5 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS", VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS },
|
{ "VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET", VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET },
|
||||||
{ "VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED", VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED },
|
{ "VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS", VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS },
|
||||||
{ "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2 },
|
{ "VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED", VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED },
|
||||||
{ "VEHICLE_ENTRY_FLAG_10", VEHICLE_ENTRY_FLAG_10 },
|
{ "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_11", VEHICLE_ENTRY_FLAG_11 },
|
{ "VEHICLE_ENTRY_FLAG_10", VEHICLE_ENTRY_FLAG_10 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES", VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES },
|
{ "VEHICLE_ENTRY_FLAG_11", VEHICLE_ENTRY_FLAG_11 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_13", VEHICLE_ENTRY_FLAG_13 },
|
{ "VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES", VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES },
|
||||||
{ "VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES", VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES },
|
{ "VEHICLE_ENTRY_FLAG_13", VEHICLE_ENTRY_FLAG_13 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_LIFT", VEHICLE_ENTRY_FLAG_LIFT },
|
{ "VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES", VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES },
|
||||||
{ "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1 },
|
{ "VEHICLE_ENTRY_FLAG_LIFT", VEHICLE_ENTRY_FLAG_LIFT },
|
||||||
{ "VEHICLE_ENTRY_FLAG_SWINGING", VEHICLE_ENTRY_FLAG_SWINGING },
|
{ "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_SPINNING", VEHICLE_ENTRY_FLAG_SPINNING },
|
{ "VEHICLE_ENTRY_FLAG_SWINGING", VEHICLE_ENTRY_FLAG_SWINGING },
|
||||||
{ "VEHICLE_ENTRY_FLAG_POWERED", VEHICLE_ENTRY_FLAG_POWERED },
|
{ "VEHICLE_ENTRY_FLAG_SPINNING", VEHICLE_ENTRY_FLAG_SPINNING },
|
||||||
{ "VEHICLE_ENTRY_FLAG_RIDERS_SCREAM", VEHICLE_ENTRY_FLAG_RIDERS_SCREAM },
|
{ "VEHICLE_ENTRY_FLAG_POWERED", VEHICLE_ENTRY_FLAG_POWERED },
|
||||||
{ "VEHICLE_ENTRY_FLAG_21", VEHICLE_ENTRY_FLAG_21 },
|
{ "VEHICLE_ENTRY_FLAG_RIDERS_SCREAM", VEHICLE_ENTRY_FLAG_RIDERS_SCREAM },
|
||||||
{ "VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION", VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION },
|
{ "VEHICLE_ENTRY_FLAG_21", VEHICLE_ENTRY_FLAG_21 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION", VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION },
|
{ "VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION", VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION },
|
||||||
{ "VEHICLE_ENTRY_FLAG_RIDER_ANIMATION", VEHICLE_ENTRY_FLAG_RIDER_ANIMATION },
|
{ "VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION", VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION },
|
||||||
{ "VEHICLE_ENTRY_FLAG_25", VEHICLE_ENTRY_FLAG_25 },
|
{ "VEHICLE_ENTRY_FLAG_RIDER_ANIMATION", VEHICLE_ENTRY_FLAG_RIDER_ANIMATION },
|
||||||
{ "VEHICLE_ENTRY_FLAG_SLIDE_SWING", VEHICLE_ENTRY_FLAG_SLIDE_SWING },
|
{ "VEHICLE_ENTRY_FLAG_25", VEHICLE_ENTRY_FLAG_25 },
|
||||||
{ "VEHICLE_ENTRY_FLAG_CHAIRLIFT", VEHICLE_ENTRY_FLAG_CHAIRLIFT },
|
{ "VEHICLE_ENTRY_FLAG_SLIDE_SWING", VEHICLE_ENTRY_FLAG_SLIDE_SWING },
|
||||||
{ "VEHICLE_ENTRY_FLAG_WATER_RIDE", VEHICLE_ENTRY_FLAG_WATER_RIDE },
|
{ "VEHICLE_ENTRY_FLAG_CHAIRLIFT", VEHICLE_ENTRY_FLAG_CHAIRLIFT },
|
||||||
{ "VEHICLE_ENTRY_FLAG_GO_KART", VEHICLE_ENTRY_FLAG_GO_KART },
|
{ "VEHICLE_ENTRY_FLAG_WATER_RIDE", VEHICLE_ENTRY_FLAG_WATER_RIDE },
|
||||||
{ "VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT", VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT } });
|
{ "VEHICLE_ENTRY_FLAG_GO_KART", VEHICLE_ENTRY_FLAG_GO_KART },
|
||||||
|
{ "VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT", VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT } });
|
||||||
return car;
|
return car;
|
||||||
}
|
}
|
||||||
|
|
||||||
vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t * jCarColours)
|
vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t* jCarColours)
|
||||||
{
|
{
|
||||||
// The JSON supports multiple configurations of per car colours, but
|
// The JSON supports multiple configurations of per car colours, but
|
||||||
// the ride entry structure currently doesn't allow for it. Assume that
|
// the ride entry structure currently doesn't allow for it. Assume that
|
||||||
|
@ -873,7 +882,7 @@ vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t * jCarCol
|
||||||
// Read first colour for each config
|
// Read first colour for each config
|
||||||
vehicle_colour_preset_list list = {};
|
vehicle_colour_preset_list list = {};
|
||||||
size_t index;
|
size_t index;
|
||||||
const json_t * jConfiguration;
|
const json_t* jConfiguration;
|
||||||
json_array_foreach(jCarColours, index, jConfiguration)
|
json_array_foreach(jCarColours, index, jConfiguration)
|
||||||
{
|
{
|
||||||
auto config = ReadJsonColourConfiguration(jConfiguration);
|
auto config = ReadJsonColourConfiguration(jConfiguration);
|
||||||
|
@ -892,11 +901,11 @@ vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t * jCarCol
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<vehicle_colour> RideObject::ReadJsonColourConfiguration(const json_t * jColourConfig)
|
std::vector<vehicle_colour> RideObject::ReadJsonColourConfiguration(const json_t* jColourConfig)
|
||||||
{
|
{
|
||||||
std::vector<vehicle_colour> config;
|
std::vector<vehicle_colour> config;
|
||||||
size_t index;
|
size_t index;
|
||||||
const json_t * jColours;
|
const json_t* jColours;
|
||||||
json_array_foreach(jColourConfig, index, jColours)
|
json_array_foreach(jColourConfig, index, jColours)
|
||||||
{
|
{
|
||||||
vehicle_colour carColour = {};
|
vehicle_colour carColour = {};
|
||||||
|
@ -924,178 +933,168 @@ bool RideObject::IsRideTypeShopOrFacility(uint8_t rideType)
|
||||||
{
|
{
|
||||||
switch (rideType)
|
switch (rideType)
|
||||||
{
|
{
|
||||||
case RIDE_TYPE_TOILETS:
|
case RIDE_TYPE_TOILETS:
|
||||||
case RIDE_TYPE_SHOP:
|
case RIDE_TYPE_SHOP:
|
||||||
case RIDE_TYPE_DRINK_STALL:
|
case RIDE_TYPE_DRINK_STALL:
|
||||||
case RIDE_TYPE_FOOD_STALL:
|
case RIDE_TYPE_FOOD_STALL:
|
||||||
case RIDE_TYPE_INFORMATION_KIOSK:
|
case RIDE_TYPE_INFORMATION_KIOSK:
|
||||||
case RIDE_TYPE_CASH_MACHINE:
|
case RIDE_TYPE_CASH_MACHINE:
|
||||||
case RIDE_TYPE_FIRST_AID:
|
case RIDE_TYPE_FIRST_AID:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t RideObject::ParseRideType(const std::string &s)
|
uint8_t RideObject::ParseRideType(const std::string& s)
|
||||||
{
|
{
|
||||||
static const std::unordered_map<std::string, uint8_t> LookupTable
|
static const std::unordered_map<std::string, uint8_t> LookupTable{
|
||||||
{
|
{ "spiral_rc", RIDE_TYPE_SPIRAL_ROLLER_COASTER },
|
||||||
{ "spiral_rc", RIDE_TYPE_SPIRAL_ROLLER_COASTER },
|
{ "stand_up_rc", RIDE_TYPE_STAND_UP_ROLLER_COASTER },
|
||||||
{ "stand_up_rc", RIDE_TYPE_STAND_UP_ROLLER_COASTER },
|
{ "suspended_swinging_rc", RIDE_TYPE_SUSPENDED_SWINGING_COASTER },
|
||||||
{ "suspended_swinging_rc", RIDE_TYPE_SUSPENDED_SWINGING_COASTER },
|
{ "inverted_rc", RIDE_TYPE_INVERTED_ROLLER_COASTER },
|
||||||
{ "inverted_rc", RIDE_TYPE_INVERTED_ROLLER_COASTER },
|
{ "junior_rc", RIDE_TYPE_JUNIOR_ROLLER_COASTER },
|
||||||
{ "junior_rc", RIDE_TYPE_JUNIOR_ROLLER_COASTER },
|
{ "miniature_railway", RIDE_TYPE_MINIATURE_RAILWAY },
|
||||||
{ "miniature_railway", RIDE_TYPE_MINIATURE_RAILWAY },
|
{ "monorail", RIDE_TYPE_MONORAIL },
|
||||||
{ "monorail", RIDE_TYPE_MONORAIL },
|
{ "mini_suspended_rc", RIDE_TYPE_MINI_SUSPENDED_COASTER },
|
||||||
{ "mini_suspended_rc", RIDE_TYPE_MINI_SUSPENDED_COASTER },
|
{ "boat_hire", RIDE_TYPE_BOAT_HIRE },
|
||||||
{ "boat_hire", RIDE_TYPE_BOAT_HIRE },
|
{ "wooden_wild_mouse", RIDE_TYPE_WOODEN_WILD_MOUSE },
|
||||||
{ "wooden_wild_mouse", RIDE_TYPE_WOODEN_WILD_MOUSE },
|
{ "steeplechase", RIDE_TYPE_STEEPLECHASE },
|
||||||
{ "steeplechase", RIDE_TYPE_STEEPLECHASE },
|
{ "car_ride", RIDE_TYPE_CAR_RIDE },
|
||||||
{ "car_ride", RIDE_TYPE_CAR_RIDE },
|
{ "launched_freefall", RIDE_TYPE_LAUNCHED_FREEFALL },
|
||||||
{ "launched_freefall", RIDE_TYPE_LAUNCHED_FREEFALL },
|
{ "bobsleigh_rc", RIDE_TYPE_BOBSLEIGH_COASTER },
|
||||||
{ "bobsleigh_rc", RIDE_TYPE_BOBSLEIGH_COASTER },
|
{ "observation_tower", RIDE_TYPE_OBSERVATION_TOWER },
|
||||||
{ "observation_tower", RIDE_TYPE_OBSERVATION_TOWER },
|
{ "looping_rc", RIDE_TYPE_LOOPING_ROLLER_COASTER },
|
||||||
{ "looping_rc", RIDE_TYPE_LOOPING_ROLLER_COASTER },
|
{ "dinghy_slide", RIDE_TYPE_DINGHY_SLIDE },
|
||||||
{ "dinghy_slide", RIDE_TYPE_DINGHY_SLIDE },
|
{ "mine_train_rc", RIDE_TYPE_MINE_TRAIN_COASTER },
|
||||||
{ "mine_train_rc", RIDE_TYPE_MINE_TRAIN_COASTER },
|
{ "chairlift", RIDE_TYPE_CHAIRLIFT },
|
||||||
{ "chairlift", RIDE_TYPE_CHAIRLIFT },
|
{ "corkscrew_rc", RIDE_TYPE_CORKSCREW_ROLLER_COASTER },
|
||||||
{ "corkscrew_rc", RIDE_TYPE_CORKSCREW_ROLLER_COASTER },
|
{ "maze", RIDE_TYPE_MAZE },
|
||||||
{ "maze", RIDE_TYPE_MAZE },
|
{ "spiral_slide", RIDE_TYPE_SPIRAL_SLIDE },
|
||||||
{ "spiral_slide", RIDE_TYPE_SPIRAL_SLIDE },
|
{ "go_karts", RIDE_TYPE_GO_KARTS },
|
||||||
{ "go_karts", RIDE_TYPE_GO_KARTS },
|
{ "log_flume", RIDE_TYPE_LOG_FLUME },
|
||||||
{ "log_flume", RIDE_TYPE_LOG_FLUME },
|
{ "river_rapids", RIDE_TYPE_RIVER_RAPIDS },
|
||||||
{ "river_rapids", RIDE_TYPE_RIVER_RAPIDS },
|
{ "dodgems", RIDE_TYPE_DODGEMS },
|
||||||
{ "dodgems", RIDE_TYPE_DODGEMS },
|
{ "swinging_ship", RIDE_TYPE_SWINGING_SHIP },
|
||||||
{ "swinging_ship", RIDE_TYPE_SWINGING_SHIP },
|
{ "swinging_inverter_ship", RIDE_TYPE_SWINGING_INVERTER_SHIP },
|
||||||
{ "swinging_inverter_ship", RIDE_TYPE_SWINGING_INVERTER_SHIP },
|
{ "food_stall", RIDE_TYPE_FOOD_STALL },
|
||||||
{ "food_stall", RIDE_TYPE_FOOD_STALL },
|
{ "drink_stall", RIDE_TYPE_DRINK_STALL },
|
||||||
{ "drink_stall", RIDE_TYPE_DRINK_STALL },
|
{ "shop", RIDE_TYPE_SHOP },
|
||||||
{ "shop", RIDE_TYPE_SHOP },
|
{ "merry_go_round", RIDE_TYPE_MERRY_GO_ROUND },
|
||||||
{ "merry_go_round", RIDE_TYPE_MERRY_GO_ROUND },
|
{ "information_kiosk", RIDE_TYPE_INFORMATION_KIOSK },
|
||||||
{ "information_kiosk", RIDE_TYPE_INFORMATION_KIOSK },
|
{ "toilets", RIDE_TYPE_TOILETS },
|
||||||
{ "toilets", RIDE_TYPE_TOILETS },
|
{ "ferris_wheel", RIDE_TYPE_FERRIS_WHEEL },
|
||||||
{ "ferris_wheel", RIDE_TYPE_FERRIS_WHEEL },
|
{ "motion_simulator", RIDE_TYPE_MOTION_SIMULATOR },
|
||||||
{ "motion_simulator", RIDE_TYPE_MOTION_SIMULATOR },
|
{ "3d_cinema", RIDE_TYPE_3D_CINEMA },
|
||||||
{ "3d_cinema", RIDE_TYPE_3D_CINEMA },
|
{ "top_spin", RIDE_TYPE_TOP_SPIN },
|
||||||
{ "top_spin", RIDE_TYPE_TOP_SPIN },
|
{ "space_rings", RIDE_TYPE_SPACE_RINGS },
|
||||||
{ "space_rings", RIDE_TYPE_SPACE_RINGS },
|
{ "reverse_freefall_rc", RIDE_TYPE_REVERSE_FREEFALL_COASTER },
|
||||||
{ "reverse_freefall_rc", RIDE_TYPE_REVERSE_FREEFALL_COASTER },
|
{ "lift", RIDE_TYPE_LIFT },
|
||||||
{ "lift", RIDE_TYPE_LIFT },
|
{ "vertical_drop_rc", RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER },
|
||||||
{ "vertical_drop_rc", RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER },
|
{ "cash_machine", RIDE_TYPE_CASH_MACHINE },
|
||||||
{ "cash_machine", RIDE_TYPE_CASH_MACHINE },
|
{ "twist", RIDE_TYPE_TWIST },
|
||||||
{ "twist", RIDE_TYPE_TWIST },
|
{ "haunted_house", RIDE_TYPE_HAUNTED_HOUSE },
|
||||||
{ "haunted_house", RIDE_TYPE_HAUNTED_HOUSE },
|
{ "first_aid", RIDE_TYPE_FIRST_AID },
|
||||||
{ "first_aid", RIDE_TYPE_FIRST_AID },
|
{ "circus", RIDE_TYPE_CIRCUS },
|
||||||
{ "circus", RIDE_TYPE_CIRCUS },
|
{ "ghost_train", RIDE_TYPE_GHOST_TRAIN },
|
||||||
{ "ghost_train", RIDE_TYPE_GHOST_TRAIN },
|
{ "twister_rc", RIDE_TYPE_TWISTER_ROLLER_COASTER },
|
||||||
{ "twister_rc", RIDE_TYPE_TWISTER_ROLLER_COASTER },
|
{ "wooden_rc", RIDE_TYPE_WOODEN_ROLLER_COASTER },
|
||||||
{ "wooden_rc", RIDE_TYPE_WOODEN_ROLLER_COASTER },
|
{ "side_friction_rc", RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER },
|
||||||
{ "side_friction_rc", RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER },
|
{ "steel_wild_mouse", RIDE_TYPE_STEEL_WILD_MOUSE },
|
||||||
{ "steel_wild_mouse", RIDE_TYPE_STEEL_WILD_MOUSE },
|
{ "multi_dimension_rc", RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER },
|
||||||
{ "multi_dimension_rc", RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER },
|
{ "flying_rc", RIDE_TYPE_FLYING_ROLLER_COASTER },
|
||||||
{ "flying_rc", RIDE_TYPE_FLYING_ROLLER_COASTER },
|
{ "virginia_reel", RIDE_TYPE_VIRGINIA_REEL },
|
||||||
{ "virginia_reel", RIDE_TYPE_VIRGINIA_REEL },
|
{ "splash_boats", RIDE_TYPE_SPLASH_BOATS },
|
||||||
{ "splash_boats", RIDE_TYPE_SPLASH_BOATS },
|
{ "mini_helicopters", RIDE_TYPE_MINI_HELICOPTERS },
|
||||||
{ "mini_helicopters", RIDE_TYPE_MINI_HELICOPTERS },
|
{ "lay_down_rc", RIDE_TYPE_LAY_DOWN_ROLLER_COASTER },
|
||||||
{ "lay_down_rc", RIDE_TYPE_LAY_DOWN_ROLLER_COASTER },
|
{ "suspended_monorail", RIDE_TYPE_SUSPENDED_MONORAIL },
|
||||||
{ "suspended_monorail", RIDE_TYPE_SUSPENDED_MONORAIL },
|
{ "reverser_rc", RIDE_TYPE_REVERSER_ROLLER_COASTER },
|
||||||
{ "reverser_rc", RIDE_TYPE_REVERSER_ROLLER_COASTER },
|
{ "heartline_twister_rc", RIDE_TYPE_HEARTLINE_TWISTER_COASTER },
|
||||||
{ "heartline_twister_rc", RIDE_TYPE_HEARTLINE_TWISTER_COASTER },
|
{ "mini_golf", RIDE_TYPE_MINI_GOLF },
|
||||||
{ "mini_golf", RIDE_TYPE_MINI_GOLF },
|
{ "giga_rc", RIDE_TYPE_GIGA_COASTER },
|
||||||
{ "giga_rc", RIDE_TYPE_GIGA_COASTER },
|
{ "roto_drop", RIDE_TYPE_ROTO_DROP },
|
||||||
{ "roto_drop", RIDE_TYPE_ROTO_DROP },
|
{ "flying_saucers", RIDE_TYPE_FLYING_SAUCERS },
|
||||||
{ "flying_saucers", RIDE_TYPE_FLYING_SAUCERS },
|
{ "crooked_house", RIDE_TYPE_CROOKED_HOUSE },
|
||||||
{ "crooked_house", RIDE_TYPE_CROOKED_HOUSE },
|
{ "monorail_cycles", RIDE_TYPE_MONORAIL_CYCLES },
|
||||||
{ "monorail_cycles", RIDE_TYPE_MONORAIL_CYCLES },
|
{ "compact_inverted_rc", RIDE_TYPE_COMPACT_INVERTED_COASTER },
|
||||||
{ "compact_inverted_rc", RIDE_TYPE_COMPACT_INVERTED_COASTER },
|
{ "water_coaster", RIDE_TYPE_WATER_COASTER },
|
||||||
{ "water_coaster", RIDE_TYPE_WATER_COASTER },
|
{ "air_powered_vertical_rc", RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER },
|
||||||
{ "air_powered_vertical_rc", RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER },
|
{ "inverted_hairpin_rc", RIDE_TYPE_INVERTED_HAIRPIN_COASTER },
|
||||||
{ "inverted_hairpin_rc", RIDE_TYPE_INVERTED_HAIRPIN_COASTER },
|
{ "magic_carpet", RIDE_TYPE_MAGIC_CARPET },
|
||||||
{ "magic_carpet", RIDE_TYPE_MAGIC_CARPET },
|
{ "submarine_ride", RIDE_TYPE_SUBMARINE_RIDE },
|
||||||
{ "submarine_ride", RIDE_TYPE_SUBMARINE_RIDE },
|
{ "river_rafts", RIDE_TYPE_RIVER_RAFTS },
|
||||||
{ "river_rafts", RIDE_TYPE_RIVER_RAFTS },
|
{ "enterprise", RIDE_TYPE_ENTERPRISE },
|
||||||
{ "enterprise", RIDE_TYPE_ENTERPRISE },
|
{ "inverted_impulse_rc", RIDE_TYPE_INVERTED_IMPULSE_COASTER },
|
||||||
{ "inverted_impulse_rc", RIDE_TYPE_INVERTED_IMPULSE_COASTER },
|
{ "mini_rc", RIDE_TYPE_MINI_ROLLER_COASTER },
|
||||||
{ "mini_rc", RIDE_TYPE_MINI_ROLLER_COASTER },
|
{ "mine_ride", RIDE_TYPE_MINE_RIDE },
|
||||||
{ "mine_ride", RIDE_TYPE_MINE_RIDE },
|
{ "lim_launched_rc", RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER },
|
||||||
{ "lim_launched_rc", RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER },
|
|
||||||
};
|
};
|
||||||
auto result = LookupTable.find(s);
|
auto result = LookupTable.find(s);
|
||||||
return (result != LookupTable.end()) ?
|
return (result != LookupTable.end()) ? result->second : RIDE_TYPE_NULL;
|
||||||
result->second :
|
|
||||||
RIDE_TYPE_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t RideObject::ParseRideCategory(const std::string &s)
|
uint8_t RideObject::ParseRideCategory(const std::string& s)
|
||||||
{
|
{
|
||||||
static const std::unordered_map<std::string, uint8_t> LookupTable
|
static const std::unordered_map<std::string, uint8_t> LookupTable{
|
||||||
{
|
{ "transport", RIDE_CATEGORY_TRANSPORT },
|
||||||
{ "transport", RIDE_CATEGORY_TRANSPORT },
|
{ "gentle", RIDE_CATEGORY_GENTLE },
|
||||||
{ "gentle", RIDE_CATEGORY_GENTLE },
|
{ "rollercoaster", RIDE_CATEGORY_ROLLERCOASTER },
|
||||||
{ "rollercoaster", RIDE_CATEGORY_ROLLERCOASTER },
|
{ "thrill", RIDE_CATEGORY_THRILL },
|
||||||
{ "thrill", RIDE_CATEGORY_THRILL },
|
{ "water", RIDE_CATEGORY_WATER },
|
||||||
{ "water", RIDE_CATEGORY_WATER },
|
{ "stall", RIDE_CATEGORY_SHOP },
|
||||||
{ "stall", RIDE_CATEGORY_SHOP },
|
|
||||||
};
|
};
|
||||||
auto result = LookupTable.find(s);
|
auto result = LookupTable.find(s);
|
||||||
return (result != LookupTable.end()) ?
|
return (result != LookupTable.end()) ? result->second : RIDE_CATEGORY_TRANSPORT;
|
||||||
result->second :
|
|
||||||
RIDE_CATEGORY_TRANSPORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t RideObject::ParseShopItem(const std::string &s)
|
uint8_t RideObject::ParseShopItem(const std::string& s)
|
||||||
{
|
{
|
||||||
static const std::unordered_map<std::string, uint8_t> LookupTable
|
static const std::unordered_map<std::string, uint8_t> LookupTable{
|
||||||
{
|
{ "burger", SHOP_ITEM_BURGER },
|
||||||
{ "burger", SHOP_ITEM_BURGER },
|
{ "chips", SHOP_ITEM_CHIPS },
|
||||||
{ "chips", SHOP_ITEM_CHIPS },
|
{ "ice_cream", SHOP_ITEM_ICE_CREAM },
|
||||||
{ "ice_cream", SHOP_ITEM_ICE_CREAM },
|
{ "candyfloss", SHOP_ITEM_CANDYFLOSS },
|
||||||
{ "candyfloss", SHOP_ITEM_CANDYFLOSS },
|
{ "pizza", SHOP_ITEM_PIZZA },
|
||||||
{ "pizza", SHOP_ITEM_PIZZA },
|
{ "popcorn", SHOP_ITEM_POPCORN },
|
||||||
{ "popcorn", SHOP_ITEM_POPCORN },
|
{ "hot_dog", SHOP_ITEM_HOT_DOG },
|
||||||
{ "hot_dog", SHOP_ITEM_HOT_DOG },
|
{ "tentacle", SHOP_ITEM_TENTACLE },
|
||||||
{ "tentacle", SHOP_ITEM_TENTACLE },
|
{ "toffee_apple", SHOP_ITEM_TOFFEE_APPLE },
|
||||||
{ "toffee_apple", SHOP_ITEM_TOFFEE_APPLE },
|
{ "doughnut", SHOP_ITEM_DOUGHNUT },
|
||||||
{ "doughnut", SHOP_ITEM_DOUGHNUT },
|
{ "chicken", SHOP_ITEM_CHICKEN },
|
||||||
{ "chicken", SHOP_ITEM_CHICKEN },
|
{ "pretzel", SHOP_ITEM_PRETZEL },
|
||||||
{ "pretzel", SHOP_ITEM_PRETZEL },
|
{ "funnel_cake", SHOP_ITEM_FUNNEL_CAKE },
|
||||||
{ "funnel_cake", SHOP_ITEM_FUNNEL_CAKE },
|
{ "beef_noodles", SHOP_ITEM_BEEF_NOODLES },
|
||||||
{ "beef_noodles", SHOP_ITEM_BEEF_NOODLES },
|
|
||||||
{ "fried_rice_noodles", SHOP_ITEM_FRIED_RICE_NOODLES },
|
{ "fried_rice_noodles", SHOP_ITEM_FRIED_RICE_NOODLES },
|
||||||
{ "wonton_soup", SHOP_ITEM_WONTON_SOUP },
|
{ "wonton_soup", SHOP_ITEM_WONTON_SOUP },
|
||||||
{ "meatball_soup", SHOP_ITEM_MEATBALL_SOUP },
|
{ "meatball_soup", SHOP_ITEM_MEATBALL_SOUP },
|
||||||
{ "sub_sandwich", SHOP_ITEM_SUB_SANDWICH },
|
{ "sub_sandwich", SHOP_ITEM_SUB_SANDWICH },
|
||||||
{ "cookie", SHOP_ITEM_COOKIE },
|
{ "cookie", SHOP_ITEM_COOKIE },
|
||||||
{ "roast_sausage", SHOP_ITEM_ROAST_SAUSAGE },
|
{ "roast_sausage", SHOP_ITEM_ROAST_SAUSAGE },
|
||||||
{ "drink", SHOP_ITEM_DRINK },
|
{ "drink", SHOP_ITEM_DRINK },
|
||||||
{ "coffee", SHOP_ITEM_COFFEE },
|
{ "coffee", SHOP_ITEM_COFFEE },
|
||||||
{ "lemonade", SHOP_ITEM_LEMONADE },
|
{ "lemonade", SHOP_ITEM_LEMONADE },
|
||||||
{ "chocolate", SHOP_ITEM_CHOCOLATE },
|
{ "chocolate", SHOP_ITEM_CHOCOLATE },
|
||||||
{ "iced_tea", SHOP_ITEM_ICED_TEA },
|
{ "iced_tea", SHOP_ITEM_ICED_TEA },
|
||||||
{ "fruit_juice", SHOP_ITEM_FRUIT_JUICE },
|
{ "fruit_juice", SHOP_ITEM_FRUIT_JUICE },
|
||||||
{ "soybean_milk", SHOP_ITEM_SOYBEAN_MILK },
|
{ "soybean_milk", SHOP_ITEM_SOYBEAN_MILK },
|
||||||
{ "sujeonggwa", SHOP_ITEM_SUJEONGGWA },
|
{ "sujeonggwa", SHOP_ITEM_SUJEONGGWA },
|
||||||
{ "balloon", SHOP_ITEM_BALLOON },
|
{ "balloon", SHOP_ITEM_BALLOON },
|
||||||
{ "toy", SHOP_ITEM_TOY },
|
{ "toy", SHOP_ITEM_TOY },
|
||||||
{ "map", SHOP_ITEM_MAP },
|
{ "map", SHOP_ITEM_MAP },
|
||||||
{ "photo", SHOP_ITEM_PHOTO },
|
{ "photo", SHOP_ITEM_PHOTO },
|
||||||
{ "umbrella", SHOP_ITEM_UMBRELLA },
|
{ "umbrella", SHOP_ITEM_UMBRELLA },
|
||||||
{ "voucher", SHOP_ITEM_VOUCHER },
|
{ "voucher", SHOP_ITEM_VOUCHER },
|
||||||
{ "hat", SHOP_ITEM_HAT },
|
{ "hat", SHOP_ITEM_HAT },
|
||||||
{ "tshirt", SHOP_ITEM_TSHIRT },
|
{ "tshirt", SHOP_ITEM_TSHIRT },
|
||||||
{ "sunglasses", SHOP_ITEM_SUNGLASSES },
|
{ "sunglasses", SHOP_ITEM_SUNGLASSES },
|
||||||
};
|
};
|
||||||
auto result = LookupTable.find(s);
|
auto result = LookupTable.find(s);
|
||||||
return (result != LookupTable.end()) ?
|
return (result != LookupTable.end()) ? result->second : SHOP_ITEM_NONE;
|
||||||
result->second :
|
|
||||||
SHOP_ITEM_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
colour_t RideObject::ParseColour(const std::string &s)
|
colour_t RideObject::ParseColour(const std::string& s)
|
||||||
{
|
{
|
||||||
static const std::unordered_map<std::string, colour_t> LookupTable
|
static const std::unordered_map<std::string, colour_t> LookupTable{
|
||||||
{
|
|
||||||
{ "black", COLOUR_BLACK },
|
{ "black", COLOUR_BLACK },
|
||||||
{ "grey", COLOUR_GREY },
|
{ "grey", COLOUR_GREY },
|
||||||
{ "white", COLOUR_WHITE },
|
{ "white", COLOUR_WHITE },
|
||||||
|
@ -1130,7 +1129,5 @@ colour_t RideObject::ParseColour(const std::string &s)
|
||||||
{ "light_pink", COLOUR_LIGHT_PINK },
|
{ "light_pink", COLOUR_LIGHT_PINK },
|
||||||
};
|
};
|
||||||
auto result = LookupTable.find(s);
|
auto result = LookupTable.find(s);
|
||||||
return (result != LookupTable.end()) ?
|
return (result != LookupTable.end()) ? result->second : COLOUR_BLACK;
|
||||||
result->second :
|
|
||||||
COLOUR_BLACK;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,50 +9,57 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class RideObject final : public Object
|
class RideObject final : public Object
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_ride_entry _legacyType = {};
|
rct_ride_entry _legacyType = {};
|
||||||
vehicle_colour_preset_list _presetColours = {};
|
vehicle_colour_preset_list _presetColours = {};
|
||||||
std::vector<int8_t> _peepLoadingPositions[MAX_VEHICLES_PER_RIDE_ENTRY];
|
std::vector<int8_t> _peepLoadingPositions[MAX_VEHICLES_PER_RIDE_ENTRY];
|
||||||
std::vector<std::array<sLocationXY8, 3> > _peepLoadingWaypoints[MAX_VEHICLES_PER_RIDE_ENTRY];
|
std::vector<std::array<sLocationXY8, 3>> _peepLoadingWaypoints[MAX_VEHICLES_PER_RIDE_ENTRY];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RideObject(const rct_object_entry &entry) : Object(entry) { }
|
explicit RideObject(const rct_object_entry& entry)
|
||||||
|
: Object(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
|
|
||||||
std::string GetDescription() const;
|
std::string GetDescription() const;
|
||||||
std::string GetCapacity() const;
|
std::string GetCapacity() const;
|
||||||
|
|
||||||
void SetRepositoryItem(ObjectRepositoryItem * item) const override;
|
void SetRepositoryItem(ObjectRepositoryItem* item) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReadLegacyVehicle(IReadObjectContext * context, IStream * stream, rct_ride_entry_vehicle * vehicle);
|
void ReadLegacyVehicle(IReadObjectContext* context, IStream* stream, rct_ride_entry_vehicle* vehicle);
|
||||||
|
|
||||||
void ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties);
|
void ReadJsonVehicleInfo(IReadObjectContext* context, const json_t* properties);
|
||||||
std::vector<rct_ride_entry_vehicle> ReadJsonCars(const json_t * jCars);
|
std::vector<rct_ride_entry_vehicle> ReadJsonCars(const json_t* jCars);
|
||||||
rct_ride_entry_vehicle ReadJsonCar(const json_t * jCar);
|
rct_ride_entry_vehicle ReadJsonCar(const json_t* jCar);
|
||||||
vehicle_colour_preset_list ReadJsonCarColours(const json_t * jCarColours);
|
vehicle_colour_preset_list ReadJsonCarColours(const json_t* jCarColours);
|
||||||
std::vector<vehicle_colour> ReadJsonColourConfiguration(const json_t * jColourConfig);
|
std::vector<vehicle_colour> ReadJsonColourConfiguration(const json_t* jColourConfig);
|
||||||
|
|
||||||
static uint8_t CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry);
|
static uint8_t CalculateNumVerticalFrames(const rct_ride_entry_vehicle* vehicleEntry);
|
||||||
static uint8_t CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * vehicleEntry);
|
static uint8_t CalculateNumHorizontalFrames(const rct_ride_entry_vehicle* vehicleEntry);
|
||||||
|
|
||||||
static bool IsRideTypeShopOrFacility(uint8_t rideType);
|
static bool IsRideTypeShopOrFacility(uint8_t rideType);
|
||||||
static uint8_t ParseRideType(const std::string &s);
|
static uint8_t ParseRideType(const std::string& s);
|
||||||
static uint8_t ParseRideCategory(const std::string &s);
|
static uint8_t ParseRideCategory(const std::string& s);
|
||||||
static uint8_t ParseShopItem(const std::string &s);
|
static uint8_t ParseShopItem(const std::string& s);
|
||||||
static colour_t ParseColour(const std::string &s);
|
static colour_t ParseColour(const std::string& s);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
#pragma warning(disable : 4706) // assignment within conditional expression
|
#pragma warning(disable : 4706) // assignment within conditional expression
|
||||||
|
|
||||||
#include <unordered_map>
|
#include "SceneryGroupObject.h"
|
||||||
|
|
||||||
#include "../Context.h"
|
#include "../Context.h"
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../core/Memory.hpp"
|
#include "../core/Memory.hpp"
|
||||||
|
@ -20,11 +21,12 @@
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
#include "ObjectManager.h"
|
#include "ObjectManager.h"
|
||||||
#include "ObjectRepository.h"
|
#include "ObjectRepository.h"
|
||||||
#include "SceneryGroupObject.h"
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace OpenRCT2;
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
void SceneryGroupObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void SceneryGroupObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
stream->Seek(0x80 * 2, STREAM_SEEK_CURRENT);
|
stream->Seek(0x80 * 2, STREAM_SEEK_CURRENT);
|
||||||
|
@ -56,7 +58,7 @@ void SceneryGroupObject::Unload()
|
||||||
_legacyType.image = 0;
|
_legacyType.image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneryGroupObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void SceneryGroupObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
int32_t y = height / 2;
|
int32_t y = height / 2;
|
||||||
|
@ -72,23 +74,37 @@ void SceneryGroupObject::UpdateEntryIndexes()
|
||||||
auto objectManager = context->GetObjectManager();
|
auto objectManager = context->GetObjectManager();
|
||||||
|
|
||||||
_legacyType.entry_count = 0;
|
_legacyType.entry_count = 0;
|
||||||
for (const auto &objectEntry : _items)
|
for (const auto& objectEntry : _items)
|
||||||
{
|
{
|
||||||
auto ori = objectRepository->FindObject(&objectEntry);
|
auto ori = objectRepository->FindObject(&objectEntry);
|
||||||
if (ori == nullptr) continue;
|
if (ori == nullptr)
|
||||||
if (ori->LoadedObject == nullptr) continue;
|
continue;
|
||||||
|
if (ori->LoadedObject == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
uint16_t sceneryEntry = objectManager->GetLoadedObjectEntryIndex(ori->LoadedObject);
|
uint16_t sceneryEntry = objectManager->GetLoadedObjectEntryIndex(ori->LoadedObject);
|
||||||
Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE);
|
Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE);
|
||||||
|
|
||||||
auto objectType = ori->ObjectEntry.flags & 0x0F;
|
auto objectType = ori->ObjectEntry.flags & 0x0F;
|
||||||
switch (objectType) {
|
switch (objectType)
|
||||||
case OBJECT_TYPE_SMALL_SCENERY: break;
|
{
|
||||||
case OBJECT_TYPE_PATH_BITS: sceneryEntry |= 0x100; break;
|
case OBJECT_TYPE_SMALL_SCENERY:
|
||||||
case OBJECT_TYPE_WALLS: sceneryEntry |= 0x200; break;
|
break;
|
||||||
case OBJECT_TYPE_LARGE_SCENERY: sceneryEntry |= 0x300; break;
|
case OBJECT_TYPE_PATH_BITS:
|
||||||
case OBJECT_TYPE_BANNERS: sceneryEntry |= 0x400; break;
|
sceneryEntry |= 0x100;
|
||||||
default: sceneryEntry = 0xFFFF; break;
|
break;
|
||||||
|
case OBJECT_TYPE_WALLS:
|
||||||
|
sceneryEntry |= 0x200;
|
||||||
|
break;
|
||||||
|
case OBJECT_TYPE_LARGE_SCENERY:
|
||||||
|
sceneryEntry |= 0x300;
|
||||||
|
break;
|
||||||
|
case OBJECT_TYPE_BANNERS:
|
||||||
|
sceneryEntry |= 0x400;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sceneryEntry = 0xFFFF;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (sceneryEntry != 0xFFFF)
|
if (sceneryEntry != 0xFFFF)
|
||||||
{
|
{
|
||||||
|
@ -98,12 +114,12 @@ void SceneryGroupObject::UpdateEntryIndexes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneryGroupObject::SetRepositoryItem(ObjectRepositoryItem * item) const
|
void SceneryGroupObject::SetRepositoryItem(ObjectRepositoryItem* item) const
|
||||||
{
|
{
|
||||||
item->SceneryGroupInfo.Entries = _items;
|
item->SceneryGroupInfo.Entries = _items;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream * stream)
|
std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream* stream)
|
||||||
{
|
{
|
||||||
auto items = std::vector<rct_object_entry>();
|
auto items = std::vector<rct_object_entry>();
|
||||||
while (stream->ReadValue<uint8_t>() != 0xFF)
|
while (stream->ReadValue<uint8_t>() != 0xFF)
|
||||||
|
@ -115,7 +131,7 @@ std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream * stream)
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneryGroupObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void SceneryGroupObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
_legacyType.priority = json_integer_value(json_object_get(properties, "priority"));
|
_legacyType.priority = json_integer_value(json_object_get(properties, "priority"));
|
||||||
|
@ -137,7 +153,7 @@ void SceneryGroupObject::ReadJson(IReadObjectContext * context, const json_t * r
|
||||||
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostumes)
|
uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t* jCostumes)
|
||||||
{
|
{
|
||||||
uint32_t costumes = 0;
|
uint32_t costumes = 0;
|
||||||
auto szCostumes = ObjectJsonHelpers::GetJsonStringArray(jCostumes);
|
auto szCostumes = ObjectJsonHelpers::GetJsonStringArray(jCostumes);
|
||||||
|
@ -152,27 +168,38 @@ uint32_t SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostume
|
||||||
return costumes;
|
return costumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SceneryGroupObject::ParseEntertainerCostume(const std::string &s)
|
uint32_t SceneryGroupObject::ParseEntertainerCostume(const std::string& s)
|
||||||
{
|
{
|
||||||
if (s == "panda") return ENTERTAINER_COSTUME_PANDA;
|
if (s == "panda")
|
||||||
if (s == "tiger") return ENTERTAINER_COSTUME_TIGER;
|
return ENTERTAINER_COSTUME_PANDA;
|
||||||
if (s == "elephant") return ENTERTAINER_COSTUME_ELEPHANT;
|
if (s == "tiger")
|
||||||
if (s == "roman") return ENTERTAINER_COSTUME_ROMAN;
|
return ENTERTAINER_COSTUME_TIGER;
|
||||||
if (s == "gorilla") return ENTERTAINER_COSTUME_GORILLA;
|
if (s == "elephant")
|
||||||
if (s == "snowman") return ENTERTAINER_COSTUME_SNOWMAN;
|
return ENTERTAINER_COSTUME_ELEPHANT;
|
||||||
if (s == "knight") return ENTERTAINER_COSTUME_KNIGHT;
|
if (s == "roman")
|
||||||
if (s == "astronaut") return ENTERTAINER_COSTUME_ASTRONAUT;
|
return ENTERTAINER_COSTUME_ROMAN;
|
||||||
if (s == "bandit") return ENTERTAINER_COSTUME_BANDIT;
|
if (s == "gorilla")
|
||||||
if (s == "sheriff") return ENTERTAINER_COSTUME_SHERIFF;
|
return ENTERTAINER_COSTUME_GORILLA;
|
||||||
if (s == "pirate") return ENTERTAINER_COSTUME_PIRATE;
|
if (s == "snowman")
|
||||||
|
return ENTERTAINER_COSTUME_SNOWMAN;
|
||||||
|
if (s == "knight")
|
||||||
|
return ENTERTAINER_COSTUME_KNIGHT;
|
||||||
|
if (s == "astronaut")
|
||||||
|
return ENTERTAINER_COSTUME_ASTRONAUT;
|
||||||
|
if (s == "bandit")
|
||||||
|
return ENTERTAINER_COSTUME_BANDIT;
|
||||||
|
if (s == "sheriff")
|
||||||
|
return ENTERTAINER_COSTUME_SHERIFF;
|
||||||
|
if (s == "pirate")
|
||||||
|
return ENTERTAINER_COSTUME_PIRATE;
|
||||||
return ENTERTAINER_COSTUME_PANDA;
|
return ENTERTAINER_COSTUME_PANDA;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rct_object_entry> SceneryGroupObject::ReadJsonEntries(const json_t * jEntries)
|
std::vector<rct_object_entry> SceneryGroupObject::ReadJsonEntries(const json_t* jEntries)
|
||||||
{
|
{
|
||||||
std::vector<rct_object_entry> entries;
|
std::vector<rct_object_entry> entries;
|
||||||
size_t index;
|
size_t index;
|
||||||
json_t * jEntry;
|
json_t* jEntry;
|
||||||
json_array_foreach(jEntries, index, jEntry)
|
json_array_foreach(jEntries, index, jEntry)
|
||||||
{
|
{
|
||||||
auto entryId = json_string_value(jEntry);
|
auto entryId = json_string_value(jEntry);
|
||||||
|
|
|
@ -9,36 +9,43 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct ObjectRepositoryItem;
|
struct ObjectRepositoryItem;
|
||||||
|
|
||||||
class SceneryGroupObject final : public Object
|
class SceneryGroupObject final : public Object
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_scenery_group_entry _legacyType = {};
|
rct_scenery_group_entry _legacyType = {};
|
||||||
std::vector<rct_object_entry> _items;
|
std::vector<rct_object_entry> _items;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SceneryGroupObject(const rct_object_entry &entry) : Object(entry) { }
|
explicit SceneryGroupObject(const rct_object_entry& entry)
|
||||||
|
: Object(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
void UpdateEntryIndexes();
|
void UpdateEntryIndexes();
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
|
|
||||||
void SetRepositoryItem(ObjectRepositoryItem * item) const override;
|
void SetRepositoryItem(ObjectRepositoryItem* item) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<rct_object_entry> ReadItems(IStream * stream);
|
static std::vector<rct_object_entry> ReadItems(IStream* stream);
|
||||||
static uint32_t ReadJsonEntertainerCostumes(const json_t * jCostumes);
|
static uint32_t ReadJsonEntertainerCostumes(const json_t* jCostumes);
|
||||||
static uint32_t ParseEntertainerCostume(const std::string &s);
|
static uint32_t ParseEntertainerCostume(const std::string& s);
|
||||||
static std::vector<rct_object_entry> ReadJsonEntries(const json_t * jEntries);
|
static std::vector<rct_object_entry> ReadJsonEntries(const json_t* jEntries);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "ObjectJsonHelpers.h"
|
|
||||||
#include "SceneryObject.h"
|
#include "SceneryObject.h"
|
||||||
|
|
||||||
void SceneryObject::SetPrimarySceneryGroup(const std::string &s)
|
#include "ObjectJsonHelpers.h"
|
||||||
|
|
||||||
|
void SceneryObject::SetPrimarySceneryGroup(const std::string& s)
|
||||||
{
|
{
|
||||||
if (!s.empty())
|
if (!s.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,21 +9,31 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class SceneryObject : public Object
|
class SceneryObject : public Object
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_object_entry _primarySceneryGroupEntry = { };
|
rct_object_entry _primarySceneryGroupEntry = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SceneryObject(const rct_object_entry &entry) : Object(entry) { }
|
explicit SceneryObject(const rct_object_entry& entry)
|
||||||
|
: Object(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
virtual ~SceneryObject() = default;
|
virtual ~SceneryObject() = default;
|
||||||
|
|
||||||
const rct_object_entry * GetPrimarySceneryGroup() { return &_primarySceneryGroupEntry; }
|
const rct_object_entry* GetPrimarySceneryGroup()
|
||||||
|
{
|
||||||
|
return &_primarySceneryGroupEntry;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetPrimarySceneryGroup(const rct_object_entry * entry) { _primarySceneryGroupEntry = *entry; }
|
void SetPrimarySceneryGroup(const rct_object_entry* entry)
|
||||||
void SetPrimarySceneryGroup(const std::string &s);
|
{
|
||||||
|
_primarySceneryGroupEntry = *entry;
|
||||||
|
}
|
||||||
|
void SetPrimarySceneryGroup(const std::string& s);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#pragma warning(disable : 4706) // assignment within conditional expression
|
#pragma warning(disable : 4706) // assignment within conditional expression
|
||||||
|
|
||||||
|
#include "SmallSceneryObject.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../core/Math.hpp"
|
#include "../core/Math.hpp"
|
||||||
#include "../core/Memory.hpp"
|
#include "../core/Memory.hpp"
|
||||||
|
@ -18,10 +20,9 @@
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
#include "../world/SmallScenery.h"
|
#include "../world/SmallScenery.h"
|
||||||
#include "SmallSceneryObject.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
|
|
||||||
void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void SmallSceneryObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.small_scenery.flags = stream->ReadValue<uint32_t>();
|
_legacyType.small_scenery.flags = stream->ReadValue<uint32_t>();
|
||||||
|
@ -88,7 +89,7 @@ void SmallSceneryObject::Unload()
|
||||||
_legacyType.image = 0;
|
_legacyType.image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmallSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void SmallSceneryObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
uint32_t imageId = _legacyType.image;
|
uint32_t imageId = _legacyType.image;
|
||||||
if (scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
|
if (scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
|
||||||
|
@ -104,8 +105,8 @@ void SmallSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int
|
||||||
int32_t y = (height / 2) + (_legacyType.small_scenery.height / 2);
|
int32_t y = (height / 2) + (_legacyType.small_scenery.height / 2);
|
||||||
y = std::min(y, height - 16);
|
y = std::min(y, height - 16);
|
||||||
|
|
||||||
if ((scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_FULL_TILE)) &&
|
if ((scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_FULL_TILE))
|
||||||
(scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_VOFFSET_CENTRE)))
|
&& (scenery_small_entry_has_flag(&_legacyType, SMALL_SCENERY_FLAG_VOFFSET_CENTRE)))
|
||||||
{
|
{
|
||||||
y -= 12;
|
y -= 12;
|
||||||
}
|
}
|
||||||
|
@ -133,7 +134,7 @@ void SmallSceneryObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> SmallSceneryObject::ReadFrameOffsets(IStream * stream)
|
std::vector<uint8_t> SmallSceneryObject::ReadFrameOffsets(IStream* stream)
|
||||||
{
|
{
|
||||||
uint8_t frameOffset;
|
uint8_t frameOffset;
|
||||||
auto data = std::vector<uint8_t>();
|
auto data = std::vector<uint8_t>();
|
||||||
|
@ -228,12 +229,13 @@ rct_object_entry SmallSceneryObject::GetScgAbstrHeader()
|
||||||
return Object::CreateHeader("SCGABSTR", 207140231, 932253451);
|
return Object::CreateHeader("SCGABSTR", 207140231, 932253451);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void SmallSceneryObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
|
|
||||||
_legacyType.small_scenery.height = json_integer_value(json_object_get(properties, "height"));
|
_legacyType.small_scenery.height = json_integer_value(json_object_get(properties, "height"));
|
||||||
_legacyType.small_scenery.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN);
|
_legacyType.small_scenery.tool_id
|
||||||
|
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN);
|
||||||
_legacyType.small_scenery.price = json_integer_value(json_object_get(properties, "price"));
|
_legacyType.small_scenery.price = json_integer_value(json_object_get(properties, "price"));
|
||||||
_legacyType.small_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
|
_legacyType.small_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice"));
|
||||||
_legacyType.small_scenery.animation_delay = json_integer_value(json_object_get(properties, "animationDelay"));
|
_legacyType.small_scenery.animation_delay = json_integer_value(json_object_get(properties, "animationDelay"));
|
||||||
|
@ -241,30 +243,31 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r
|
||||||
_legacyType.small_scenery.num_frames = json_integer_value(json_object_get(properties, "numFrames"));
|
_legacyType.small_scenery.num_frames = json_integer_value(json_object_get(properties, "numFrames"));
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
_legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags<uint32_t>(properties, {
|
_legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags<uint32_t>(
|
||||||
{ "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE },
|
properties,
|
||||||
{ "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE },
|
{ { "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE },
|
||||||
{ "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE },
|
{ "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE },
|
||||||
{ "isAnimated", SMALL_SCENERY_FLAG_ANIMATED },
|
{ "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE },
|
||||||
{ "canWither", SMALL_SCENERY_FLAG_CAN_WITHER },
|
{ "isAnimated", SMALL_SCENERY_FLAG_ANIMATED },
|
||||||
{ "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED },
|
{ "canWither", SMALL_SCENERY_FLAG_CAN_WITHER },
|
||||||
{ "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG },
|
{ "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED },
|
||||||
{ "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS },
|
{ "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG },
|
||||||
{ "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
|
{ "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS },
|
||||||
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 },
|
{ "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
|
||||||
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 },
|
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 },
|
||||||
{ "isClock", SMALL_SCENERY_FLAG_IS_CLOCK },
|
{ "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 },
|
||||||
{ "SMALL_SCENERY_FLAG_SWAMP_GOO", SMALL_SCENERY_FLAG_SWAMP_GOO },
|
{ "isClock", SMALL_SCENERY_FLAG_IS_CLOCK },
|
||||||
{ "SMALL_SCENERY_FLAG17", SMALL_SCENERY_FLAG17 },
|
{ "SMALL_SCENERY_FLAG_SWAMP_GOO", SMALL_SCENERY_FLAG_SWAMP_GOO },
|
||||||
{ "isStackable", SMALL_SCENERY_FLAG_STACKABLE },
|
{ "SMALL_SCENERY_FLAG17", SMALL_SCENERY_FLAG17 },
|
||||||
{ "prohibitWalls", SMALL_SCENERY_FLAG_NO_WALLS },
|
{ "isStackable", SMALL_SCENERY_FLAG_STACKABLE },
|
||||||
{ "hasSecondaryColour", SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
|
{ "prohibitWalls", SMALL_SCENERY_FLAG_NO_WALLS },
|
||||||
{ "hasNoSupports", SMALL_SCENERY_FLAG_NO_SUPPORTS },
|
{ "hasSecondaryColour", SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
|
||||||
{ "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED },
|
{ "hasNoSupports", SMALL_SCENERY_FLAG_NO_SUPPORTS },
|
||||||
{ "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG },
|
{ "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED },
|
||||||
{ "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP },
|
{ "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG },
|
||||||
{ "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS },
|
{ "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP },
|
||||||
{ "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } });
|
{ "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS },
|
||||||
|
{ "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } });
|
||||||
|
|
||||||
// Determine shape flags from a shape string
|
// Determine shape flags from a shape string
|
||||||
auto shape = ObjectJsonHelpers::GetString(properties, "shape");
|
auto shape = ObjectJsonHelpers::GetString(properties, "shape");
|
||||||
|
@ -305,11 +308,11 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r
|
||||||
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> SmallSceneryObject::ReadJsonFrameOffsets(const json_t * jFrameOffsets)
|
std::vector<uint8_t> SmallSceneryObject::ReadJsonFrameOffsets(const json_t* jFrameOffsets)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> offsets;
|
std::vector<uint8_t> offsets;
|
||||||
size_t index;
|
size_t index;
|
||||||
const json_t * jOffset;
|
const json_t* jOffset;
|
||||||
json_array_foreach(jFrameOffsets, index, jOffset)
|
json_array_foreach(jFrameOffsets, index, jOffset)
|
||||||
{
|
{
|
||||||
offsets.push_back(json_integer_value(jOffset));
|
offsets.push_back(json_integer_value(jOffset));
|
||||||
|
|
|
@ -9,31 +9,38 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
#include "SceneryObject.h"
|
#include "SceneryObject.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class SmallSceneryObject final : public SceneryObject
|
class SmallSceneryObject final : public SceneryObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_scenery_entry _legacyType = {};
|
rct_scenery_entry _legacyType = {};
|
||||||
std::vector<uint8_t> _frameOffsets;
|
std::vector<uint8_t> _frameOffsets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SmallSceneryObject(const rct_object_entry &entry) : SceneryObject(entry) { }
|
explicit SmallSceneryObject(const rct_object_entry& entry)
|
||||||
|
: SceneryObject(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<uint8_t> ReadFrameOffsets(IStream * stream);
|
static std::vector<uint8_t> ReadFrameOffsets(IStream* stream);
|
||||||
static std::vector<uint8_t> ReadJsonFrameOffsets(const json_t * jFrameOffsets);
|
static std::vector<uint8_t> ReadJsonFrameOffsets(const json_t* jFrameOffsets);
|
||||||
void PerformFixes();
|
void PerformFixes();
|
||||||
rct_object_entry GetScgPiratHeader();
|
rct_object_entry GetScgPiratHeader();
|
||||||
rct_object_entry GetScgMineHeader();
|
rct_object_entry GetScgMineHeader();
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
|
||||||
#include "StexObject.h"
|
#include "StexObject.h"
|
||||||
|
|
||||||
|
#include "../core/IStream.hpp"
|
||||||
#include "../localisation/Localisation.h"
|
#include "../localisation/Localisation.h"
|
||||||
|
|
||||||
void StexObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void StexObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.var_06 = stream->ReadValue<uint8_t>();
|
_legacyType.var_06 = stream->ReadValue<uint8_t>();
|
||||||
|
@ -42,7 +42,7 @@ void StexObject::Unload()
|
||||||
_legacyType.details = 0;
|
_legacyType.details = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StexObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void StexObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
// Write (no image)
|
// Write (no image)
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Object.h"
|
|
||||||
|
|
||||||
#include "../scenario/Scenario.h"
|
#include "../scenario/Scenario.h"
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
class StexObject final : public Object
|
class StexObject final : public Object
|
||||||
{
|
{
|
||||||
|
@ -19,15 +18,21 @@ private:
|
||||||
rct_stex_entry _legacyType = {};
|
rct_stex_entry _legacyType = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StexObject(const rct_object_entry &entry) : Object(entry) { }
|
explicit StexObject(const rct_object_entry& entry)
|
||||||
|
: Object(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,18 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <algorithm>
|
#include "StringTable.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../localisation/LanguagePack.h"
|
#include "../localisation/LanguagePack.h"
|
||||||
#include "../localisation/LocalisationService.h"
|
#include "../localisation/LocalisationService.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "StringTable.h"
|
|
||||||
|
|
||||||
static constexpr const uint8_t RCT2ToOpenRCT2LanguageId[] =
|
#include <algorithm>
|
||||||
{
|
|
||||||
|
static constexpr const uint8_t RCT2ToOpenRCT2LanguageId[] = {
|
||||||
LANGUAGE_ENGLISH_UK,
|
LANGUAGE_ENGLISH_UK,
|
||||||
LANGUAGE_ENGLISH_US,
|
LANGUAGE_ENGLISH_US,
|
||||||
LANGUAGE_FRENCH,
|
LANGUAGE_FRENCH,
|
||||||
|
@ -34,7 +35,7 @@ static constexpr const uint8_t RCT2ToOpenRCT2LanguageId[] =
|
||||||
LANGUAGE_PORTUGUESE_BR,
|
LANGUAGE_PORTUGUESE_BR,
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool StringIsBlank(const utf8 * str)
|
static bool StringIsBlank(const utf8* str)
|
||||||
{
|
{
|
||||||
for (auto ch = str; *ch != '\0'; ch++)
|
for (auto ch = str; *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
|
@ -46,18 +47,16 @@ static bool StringIsBlank(const utf8 * str)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8_t id)
|
void StringTable::Read(IReadObjectContext* context, IStream* stream, uint8_t id)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RCT2LanguageId rct2LanguageId;
|
RCT2LanguageId rct2LanguageId;
|
||||||
while ((rct2LanguageId = (RCT2LanguageId)stream->ReadValue<uint8_t>()) != RCT2_LANGUAGE_ID_END)
|
while ((rct2LanguageId = (RCT2LanguageId)stream->ReadValue<uint8_t>()) != RCT2_LANGUAGE_ID_END)
|
||||||
{
|
{
|
||||||
uint8_t languageId =
|
uint8_t languageId = (rct2LanguageId <= RCT2_LANGUAGE_ID_PORTUGUESE) ? RCT2ToOpenRCT2LanguageId[rct2LanguageId]
|
||||||
(rct2LanguageId <= RCT2_LANGUAGE_ID_PORTUGUESE) ?
|
: LANGUAGE_UNDEFINED;
|
||||||
RCT2ToOpenRCT2LanguageId[rct2LanguageId] :
|
StringTableEntry entry{};
|
||||||
LANGUAGE_UNDEFINED;
|
|
||||||
StringTableEntry entry { };
|
|
||||||
entry.Id = id;
|
entry.Id = id;
|
||||||
entry.LanguageId = languageId;
|
entry.LanguageId = languageId;
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8_t i
|
||||||
_strings.push_back(entry);
|
_strings.push_back(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
context->LogError(OBJECT_ERROR_BAD_STRING_TABLE, "Bad string table.");
|
context->LogError(OBJECT_ERROR_BAD_STRING_TABLE, "Bad string table.");
|
||||||
throw;
|
throw;
|
||||||
|
@ -84,7 +83,7 @@ void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8_t i
|
||||||
|
|
||||||
std::string StringTable::GetString(uint8_t id) const
|
std::string StringTable::GetString(uint8_t id) const
|
||||||
{
|
{
|
||||||
for (auto &string : _strings)
|
for (auto& string : _strings)
|
||||||
{
|
{
|
||||||
if (string.Id == id)
|
if (string.Id == id)
|
||||||
{
|
{
|
||||||
|
@ -96,7 +95,7 @@ std::string StringTable::GetString(uint8_t id) const
|
||||||
|
|
||||||
std::string StringTable::GetString(uint8_t language, uint8_t id) const
|
std::string StringTable::GetString(uint8_t language, uint8_t id) const
|
||||||
{
|
{
|
||||||
for (auto &string : _strings)
|
for (auto& string : _strings)
|
||||||
{
|
{
|
||||||
if (string.LanguageId == language && string.Id == id)
|
if (string.LanguageId == language && string.Id == id)
|
||||||
{
|
{
|
||||||
|
@ -106,7 +105,7 @@ std::string StringTable::GetString(uint8_t language, uint8_t id) const
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringTable::SetString(uint8_t id, uint8_t language, const std::string &text)
|
void StringTable::SetString(uint8_t id, uint8_t language, const std::string& text)
|
||||||
{
|
{
|
||||||
StringTableEntry entry;
|
StringTableEntry entry;
|
||||||
entry.Id = id;
|
entry.Id = id;
|
||||||
|
@ -118,8 +117,7 @@ void StringTable::SetString(uint8_t id, uint8_t language, const std::string &tex
|
||||||
void StringTable::Sort()
|
void StringTable::Sort()
|
||||||
{
|
{
|
||||||
auto targetLanguage = LocalisationService_GetCurrentLanguage();
|
auto targetLanguage = LocalisationService_GetCurrentLanguage();
|
||||||
std::sort(_strings.begin(), _strings.end(), [targetLanguage](const StringTableEntry &a, const StringTableEntry &b) -> bool
|
std::sort(_strings.begin(), _strings.end(), [targetLanguage](const StringTableEntry& a, const StringTableEntry& b) -> bool {
|
||||||
{
|
|
||||||
if (a.Id == b.Id)
|
if (a.Id == b.Id)
|
||||||
{
|
{
|
||||||
if (a.LanguageId == b.LanguageId)
|
if (a.LanguageId == b.LanguageId)
|
||||||
|
|
|
@ -9,11 +9,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
interface IReadObjectContext;
|
interface IReadObjectContext;
|
||||||
interface IStream;
|
interface IStream;
|
||||||
|
|
||||||
|
@ -31,8 +32,8 @@ enum OBJ_STRING_ID : uint8_t
|
||||||
|
|
||||||
struct StringTableEntry
|
struct StringTableEntry
|
||||||
{
|
{
|
||||||
uint8_t Id = OBJ_STRING_ID_UNKNOWN;
|
uint8_t Id = OBJ_STRING_ID_UNKNOWN;
|
||||||
uint8_t LanguageId = LANGUAGE_UNDEFINED;
|
uint8_t LanguageId = LANGUAGE_UNDEFINED;
|
||||||
std::string Text;
|
std::string Text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,12 +44,12 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringTable() = default;
|
StringTable() = default;
|
||||||
StringTable(const StringTable &) = delete;
|
StringTable(const StringTable&) = delete;
|
||||||
StringTable & operator=(const StringTable &) = delete;
|
StringTable& operator=(const StringTable&) = delete;
|
||||||
|
|
||||||
void Read(IReadObjectContext * context, IStream * stream, uint8_t id);
|
void Read(IReadObjectContext* context, IStream* stream, uint8_t id);
|
||||||
void Sort();
|
void Sort();
|
||||||
std::string GetString(uint8_t id) const;
|
std::string GetString(uint8_t id) const;
|
||||||
std::string GetString(uint8_t language, uint8_t id) const;
|
std::string GetString(uint8_t language, uint8_t id) const;
|
||||||
void SetString(uint8_t id, uint8_t language, const std::string &text);
|
void SetString(uint8_t id, uint8_t language, const std::string& text);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,14 +7,15 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "WallObject.h"
|
||||||
|
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../drawing/Drawing.h"
|
#include "../drawing/Drawing.h"
|
||||||
#include "../interface/Cursors.h"
|
#include "../interface/Cursors.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
#include "WallObject.h"
|
|
||||||
|
|
||||||
void WallObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
void WallObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(6, STREAM_SEEK_CURRENT);
|
stream->Seek(6, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.wall.tool_id = stream->ReadValue<uint8_t>();
|
_legacyType.wall.tool_id = stream->ReadValue<uint8_t>();
|
||||||
|
@ -55,7 +56,7 @@ void WallObject::Unload()
|
||||||
_legacyType.image = 0;
|
_legacyType.image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WallObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void WallObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
int32_t y = height / 2;
|
int32_t y = height / 2;
|
||||||
|
@ -83,33 +84,32 @@ void WallObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t hei
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WallObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
void WallObject::ReadJson(IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
|
|
||||||
_legacyType.wall.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_FENCE_DOWN);
|
_legacyType.wall.tool_id
|
||||||
|
= ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_FENCE_DOWN);
|
||||||
_legacyType.wall.height = json_integer_value(json_object_get(properties, "height"));
|
_legacyType.wall.height = json_integer_value(json_object_get(properties, "height"));
|
||||||
_legacyType.wall.price = json_integer_value(json_object_get(properties, "price"));
|
_legacyType.wall.price = json_integer_value(json_object_get(properties, "price"));
|
||||||
|
|
||||||
auto jScrollingMode = json_object_get(properties, "scrollingMode");
|
auto jScrollingMode = json_object_get(properties, "scrollingMode");
|
||||||
_legacyType.wall.scrolling_mode = jScrollingMode != nullptr ?
|
_legacyType.wall.scrolling_mode = jScrollingMode != nullptr ? json_integer_value(jScrollingMode) : -1;
|
||||||
json_integer_value(jScrollingMode) :
|
|
||||||
-1;
|
|
||||||
|
|
||||||
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
|
SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")));
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
_legacyType.wall.flags = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
|
_legacyType.wall.flags = ObjectJsonHelpers::GetFlags<uint8_t>(
|
||||||
{ "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR },
|
properties,
|
||||||
{ "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR },
|
{ { "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR },
|
||||||
{ "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR },
|
{ "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR },
|
||||||
{ "hasGlass", WALL_SCENERY_HAS_GLASS },
|
{ "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR },
|
||||||
{ "isBanner", WALL_SCENERY_IS_BANNER },
|
{ "hasGlass", WALL_SCENERY_HAS_GLASS },
|
||||||
{ "isDoor", WALL_SCENERY_IS_DOOR },
|
{ "isBanner", WALL_SCENERY_IS_BANNER },
|
||||||
{ "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION }});
|
{ "isDoor", WALL_SCENERY_IS_DOOR },
|
||||||
_legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags<uint8_t>(properties, {
|
{ "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION } });
|
||||||
{ "isOpaque", WALL_SCENERY_2_IS_OPAQUE },
|
_legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags<uint8_t>(
|
||||||
{ "isAnimated", WALL_SCENERY_2_ANIMATED }});
|
properties, { { "isOpaque", WALL_SCENERY_2_IS_OPAQUE }, { "isAnimated", WALL_SCENERY_2_ANIMATED } });
|
||||||
|
|
||||||
// HACK To avoid 'negated' properties in JSON, handle this separately until
|
// HACK To avoid 'negated' properties in JSON, handle this separately until
|
||||||
// flag is inverted in this code base.
|
// flag is inverted in this code base.
|
||||||
|
@ -122,8 +122,8 @@ void WallObject::ReadJson(IReadObjectContext * context, const json_t * root)
|
||||||
// JSON and handle this on load. We should change code base in future to reflect the JSON.
|
// JSON and handle this on load. We should change code base in future to reflect the JSON.
|
||||||
if (!(_legacyType.wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR))
|
if (!(_legacyType.wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR))
|
||||||
{
|
{
|
||||||
if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) ||
|
if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR)
|
||||||
(_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR))
|
|| (_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR))
|
||||||
{
|
{
|
||||||
_legacyType.wall.flags2 |= WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR;
|
_legacyType.wall.flags2 |= WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,24 +9,29 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SceneryObject.h"
|
|
||||||
|
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
|
#include "SceneryObject.h"
|
||||||
|
|
||||||
class WallObject final : public SceneryObject
|
class WallObject final : public SceneryObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_scenery_entry _legacyType = {};
|
rct_scenery_entry _legacyType = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WallObject(const rct_object_entry &entry) : SceneryObject(entry) { }
|
explicit WallObject(const rct_object_entry& entry)
|
||||||
|
: SceneryObject(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,15 +9,17 @@
|
||||||
|
|
||||||
#pragma warning(disable : 4706) // assignment within conditional expression
|
#pragma warning(disable : 4706) // assignment within conditional expression
|
||||||
|
|
||||||
#include <memory>
|
#include "WaterObject.h"
|
||||||
|
|
||||||
|
#include "../OpenRCT2.h"
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../localisation/StringIds.h"
|
#include "../localisation/StringIds.h"
|
||||||
#include "../OpenRCT2.h"
|
|
||||||
#include "ObjectJsonHelpers.h"
|
#include "ObjectJsonHelpers.h"
|
||||||
#include "WaterObject.h"
|
|
||||||
|
|
||||||
void WaterObject::ReadLegacy(IReadObjectContext * context, IStream * stream)
|
#include <memory>
|
||||||
|
|
||||||
|
void WaterObject::ReadLegacy(IReadObjectContext* context, IStream* stream)
|
||||||
{
|
{
|
||||||
stream->Seek(14, STREAM_SEEK_CURRENT);
|
stream->Seek(14, STREAM_SEEK_CURRENT);
|
||||||
_legacyType.flags = stream->ReadValue<uint16_t>();
|
_legacyType.flags = stream->ReadValue<uint16_t>();
|
||||||
|
@ -45,7 +47,7 @@ void WaterObject::Unload()
|
||||||
_legacyType.string_idx = 0;
|
_legacyType.string_idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const
|
void WaterObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||||
{
|
{
|
||||||
// Write (no image)
|
// Write (no image)
|
||||||
int32_t x = width / 2;
|
int32_t x = width / 2;
|
||||||
|
@ -56,22 +58,13 @@ void WaterObject::DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t he
|
||||||
void WaterObject::ReadJson([[maybe_unused]] IReadObjectContext* context, const json_t* root)
|
void WaterObject::ReadJson([[maybe_unused]] IReadObjectContext* context, const json_t* root)
|
||||||
{
|
{
|
||||||
auto properties = json_object_get(root, "properties");
|
auto properties = json_object_get(root, "properties");
|
||||||
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, {
|
_legacyType.flags = ObjectJsonHelpers::GetFlags<uint16_t>(properties, { { "allowDucks", WATER_FLAGS_ALLOW_DUCKS } });
|
||||||
{ "allowDucks", WATER_FLAGS_ALLOW_DUCKS }});
|
|
||||||
|
|
||||||
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
|
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
|
||||||
|
|
||||||
// Images which are actually palette data
|
// Images which are actually palette data
|
||||||
static const char * paletteNames[] =
|
static const char* paletteNames[]
|
||||||
{
|
= { "general", "waves-0", "waves-1", "waves-2", "sparkles-0", "sparkles-1", "sparkles-2" };
|
||||||
"general",
|
|
||||||
"waves-0",
|
|
||||||
"waves-1",
|
|
||||||
"waves-2",
|
|
||||||
"sparkles-0",
|
|
||||||
"sparkles-1",
|
|
||||||
"sparkles-2"
|
|
||||||
};
|
|
||||||
for (auto paletteName : paletteNames)
|
for (auto paletteName : paletteNames)
|
||||||
{
|
{
|
||||||
auto jPalettes = json_object_get(properties, "palettes");
|
auto jPalettes = json_object_get(properties, "palettes");
|
||||||
|
@ -86,7 +79,7 @@ void WaterObject::ReadJson([[maybe_unused]] IReadObjectContext* context, const j
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterObject::ReadJsonPalette(const json_t * jPalette)
|
void WaterObject::ReadJsonPalette(const json_t* jPalette)
|
||||||
{
|
{
|
||||||
auto paletteStartIndex = json_integer_value(json_object_get(jPalette, "index"));
|
auto paletteStartIndex = json_integer_value(json_object_get(jPalette, "index"));
|
||||||
auto jColours = json_object_get(jPalette, "colours");
|
auto jColours = json_object_get(jPalette, "colours");
|
||||||
|
@ -96,7 +89,7 @@ void WaterObject::ReadJsonPalette(const json_t * jPalette)
|
||||||
size_t dataIndex = 0;
|
size_t dataIndex = 0;
|
||||||
|
|
||||||
size_t index;
|
size_t index;
|
||||||
const json_t * jColour;
|
const json_t* jColour;
|
||||||
json_array_foreach(jColours, index, jColour)
|
json_array_foreach(jColours, index, jColour)
|
||||||
{
|
{
|
||||||
auto szColour = json_string_value(jColour);
|
auto szColour = json_string_value(jColour);
|
||||||
|
@ -116,11 +109,11 @@ void WaterObject::ReadJsonPalette(const json_t * jPalette)
|
||||||
g1.x_offset = (int16_t)paletteStartIndex;
|
g1.x_offset = (int16_t)paletteStartIndex;
|
||||||
g1.flags = G1_FLAG_PALETTE;
|
g1.flags = G1_FLAG_PALETTE;
|
||||||
|
|
||||||
auto &imageTable = GetImageTable();
|
auto& imageTable = GetImageTable();
|
||||||
imageTable.AddImage(&g1);
|
imageTable.AddImage(&g1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t WaterObject::ParseColour(const std::string &s) const
|
uint32_t WaterObject::ParseColour(const std::string& s) const
|
||||||
{
|
{
|
||||||
uint8_t r = 0;
|
uint8_t r = 0;
|
||||||
uint8_t g = 0;
|
uint8_t g = 0;
|
||||||
|
|
|
@ -9,28 +9,35 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
#include "../world/Water.h"
|
#include "../world/Water.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
class WaterObject final : public Object
|
class WaterObject final : public Object
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rct_water_type _legacyType = {};
|
rct_water_type _legacyType = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WaterObject(const rct_object_entry &entry) : Object(entry) { }
|
explicit WaterObject(const rct_object_entry& entry)
|
||||||
|
: Object(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void * GetLegacyData() override { return &_legacyType; }
|
void* GetLegacyData() override
|
||||||
|
{
|
||||||
|
return &_legacyType;
|
||||||
|
}
|
||||||
|
|
||||||
void ReadJson(IReadObjectContext * context, const json_t * root) override;
|
void ReadJson(IReadObjectContext* context, const json_t* root) override;
|
||||||
void ReadLegacy(IReadObjectContext * context, IStream * stream) override;
|
void ReadLegacy(IReadObjectContext* context, IStream* stream) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
||||||
void DrawPreview(rct_drawpixelinfo * dpi, int32_t width, int32_t height) const override;
|
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReadJsonPalette(const json_t * jPalette);
|
void ReadJsonPalette(const json_t* jPalette);
|
||||||
uint32_t ParseColour(const std::string &s) const;
|
uint32_t ParseColour(const std::string& s) const;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue