mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #20100 from IntelOrca/plugin/object-manager
Add plugin APIs for the object manager
This commit is contained in:
commit
3edb044685
|
@ -26,6 +26,7 @@
|
||||||
- Feature: [#19446] Add new colour options to colour dropdown.
|
- Feature: [#19446] Add new colour options to colour dropdown.
|
||||||
- Feature: [#19547] Add large sloped turns to hybrid coaster and single rail coaster.
|
- Feature: [#19547] Add large sloped turns to hybrid coaster and single rail coaster.
|
||||||
- Feature: [#19930] Add plugin APIs for research.
|
- Feature: [#19930] Add plugin APIs for research.
|
||||||
|
- Feature: [#19979] Add plugin API for scenery groups.
|
||||||
- Feature: [OpenMusic#25] Added Prehistoric ride music style.
|
- Feature: [OpenMusic#25] Added Prehistoric ride music style.
|
||||||
- Feature: [OpenMusic#26] Fairground Organ style 2 with new recordings from Herman's 35er Voigt (Previously known as Bressingham Voigt).
|
- Feature: [OpenMusic#26] Fairground Organ style 2 with new recordings from Herman's 35er Voigt (Previously known as Bressingham Voigt).
|
||||||
- Feature: [OpenMusic#28] Add Ragtime style 2 ride music.
|
- Feature: [OpenMusic#28] Add Ragtime style 2 ride music.
|
||||||
|
|
|
@ -41,6 +41,10 @@ declare global {
|
||||||
var climate: Climate;
|
var climate: Climate;
|
||||||
/** APIs for performance profiling. */
|
/** APIs for performance profiling. */
|
||||||
var profiler: Profiler;
|
var profiler: Profiler;
|
||||||
|
/**
|
||||||
|
* APIs for getting, loading, and unloading objects.
|
||||||
|
*/
|
||||||
|
var objectManager: ObjectManager;
|
||||||
/**
|
/**
|
||||||
* APIs for creating and editing title sequences.
|
* APIs for creating and editing title sequences.
|
||||||
* These will only be available to clients that are not running headless mode.
|
* These will only be available to clients that are not running headless mode.
|
||||||
|
@ -217,19 +221,40 @@ declare global {
|
||||||
captureImage(options: CaptureOptions): void;
|
captureImage(options: CaptureOptions): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the loaded object at the given index.
|
* @deprecated Use {@link ObjectManager.getObject} instead.
|
||||||
* @param type The object type.
|
|
||||||
* @param index The index.
|
|
||||||
*/
|
*/
|
||||||
getObject(type: ObjectType, index: number): LoadedImageObject;
|
getObject(type: ObjectType, index: number): LoadedImageObject;
|
||||||
getObject(type: "music", index: number): LoadedObject;
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link ObjectManager.getObject} instead.
|
||||||
|
*/
|
||||||
getObject(type: "ride", index: number): RideObject;
|
getObject(type: "ride", index: number): RideObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link ObjectManager.getObject} instead.
|
||||||
|
*/
|
||||||
getObject(type: "small_scenery", index: number): SmallSceneryObject;
|
getObject(type: "small_scenery", index: number): SmallSceneryObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link ObjectManager.getObject} instead.
|
||||||
|
*/
|
||||||
|
getObject(type: "music", index: number): LoadedObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link ObjectManager.getAllObjects} instead.
|
||||||
|
*/
|
||||||
getAllObjects(type: ObjectType): LoadedImageObject[];
|
getAllObjects(type: ObjectType): LoadedImageObject[];
|
||||||
getAllObjects(type: "music"): LoadedObject[];
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link ObjectManager.getAllObjects} instead.
|
||||||
|
*/
|
||||||
getAllObjects(type: "ride"): RideObject[];
|
getAllObjects(type: "ride"): RideObject[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link ObjectManager.getAllObjects} instead.
|
||||||
|
*/
|
||||||
|
getAllObjects(type: "music"): LoadedObject[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link TrackSegment} for the given type.
|
* Gets the {@link TrackSegment} for the given type.
|
||||||
* @param type The track segment type.
|
* @param type The track segment type.
|
||||||
|
@ -1586,10 +1611,80 @@ declare global {
|
||||||
removeElement(index: number): void;
|
removeElement(index: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ObjectSourceGame =
|
||||||
|
"rct1" |
|
||||||
|
"added_attractions" |
|
||||||
|
"loopy_landscapes" |
|
||||||
|
"rct2" |
|
||||||
|
"wacky_worlds" |
|
||||||
|
"time_twister" |
|
||||||
|
"custom" |
|
||||||
|
"openrct2_official";
|
||||||
|
|
||||||
|
type ObjectGeneration = "dat" | "json";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an installed OpenRCT2 object which may or may not be currently loaded into the park.
|
||||||
|
*/
|
||||||
|
interface InstalledObject {
|
||||||
|
/**
|
||||||
|
* The full path of the object file.
|
||||||
|
*/
|
||||||
|
readonly path: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the object is an original .DAT file, or a .parkobj / .json file.
|
||||||
|
*/
|
||||||
|
readonly generation: ObjectGeneration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object type.
|
||||||
|
*/
|
||||||
|
readonly type: ObjectType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The original game or expansion pack this object first appeared in.
|
||||||
|
*/
|
||||||
|
readonly sourceGames: ObjectSourceGame[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unique identifier of the object, e.g. "rct2.burgb".
|
||||||
|
* For legacy DAT objects, the identifier will be in a format similar to "09F55405|DirtGras|B9B19A7F".
|
||||||
|
*/
|
||||||
|
readonly identifier: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The original unique identifier of the object, e.g. "BURGB ".
|
||||||
|
* This may have trailing spaces if the name is shorter than 8 characters.
|
||||||
|
* Only .DAT objects or JSON objects based on .DAT objects will have legacy identifiers.
|
||||||
|
*/
|
||||||
|
readonly legacyIdentifier: string | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object version, e.g. "1.5.2-pre".
|
||||||
|
*/
|
||||||
|
readonly version: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of authors for the object.
|
||||||
|
*/
|
||||||
|
readonly authors: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name in the user's current language.
|
||||||
|
*/
|
||||||
|
readonly name: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the definition of a loaded object (.DAT or .json) such as ride type or scenery item.
|
* Represents the definition of a loaded object (.DAT or .json) such as ride type or scenery item.
|
||||||
*/
|
*/
|
||||||
interface LoadedObject {
|
interface LoadedObject {
|
||||||
|
/**
|
||||||
|
* Gets a reference to the installed object.
|
||||||
|
*/
|
||||||
|
readonly installedObject: InstalledObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object type.
|
* The object type.
|
||||||
*/
|
*/
|
||||||
|
@ -1602,7 +1697,7 @@ declare global {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The unique identifier of the object, e.g. "rct2.burgb".
|
* The unique identifier of the object, e.g. "rct2.burgb".
|
||||||
* Only JSON objects will have an identifier.
|
* For legacy DAT objects, the identifier will be in a format similar to "09F55405|DirtGras|B9B19A7F".
|
||||||
*/
|
*/
|
||||||
readonly identifier: string;
|
readonly identifier: string;
|
||||||
|
|
||||||
|
@ -1752,10 +1847,19 @@ declare global {
|
||||||
readonly numVerticalFramesOverride: number;
|
readonly numVerticalFramesOverride: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SceneryObject extends LoadedImageObject {
|
||||||
|
/**
|
||||||
|
* A list of scenery groups this object belongs to. This may not contain any
|
||||||
|
* scenery groups that contain this object by default. This is typically
|
||||||
|
* used for custom objects to be part of existing scenery groups.
|
||||||
|
*/
|
||||||
|
readonly sceneryGroups: string[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the object definition of a small scenery item such a tree.
|
* Represents the object definition of a small scenery item such a tree.
|
||||||
*/
|
*/
|
||||||
interface SmallSceneryObject extends LoadedImageObject {
|
interface SmallSceneryObject extends SceneryObject {
|
||||||
/**
|
/**
|
||||||
* Raw bit flags that describe characteristics of the scenery item.
|
* Raw bit flags that describe characteristics of the scenery item.
|
||||||
*/
|
*/
|
||||||
|
@ -1777,6 +1881,32 @@ declare global {
|
||||||
readonly removalPrice: number;
|
readonly removalPrice: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LargeSceneryObject extends SceneryObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WallObject extends SceneryObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FootpathAdditionObject extends SceneryObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BannerObject extends SceneryObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the object definition of a scenery group.
|
||||||
|
*/
|
||||||
|
interface SceneryGroupObject extends LoadedImageObject {
|
||||||
|
/**
|
||||||
|
* The scenery items that belong to this scenery group.
|
||||||
|
*/
|
||||||
|
readonly items: string[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a ride or stall within the park.
|
* Represents a ride or stall within the park.
|
||||||
*/
|
*/
|
||||||
|
@ -4588,4 +4718,81 @@ declare global {
|
||||||
readonly parents: number[];
|
readonly parents: number[];
|
||||||
readonly children: number[];
|
readonly children: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ObjectManager {
|
||||||
|
/**
|
||||||
|
* Gets all the objects that are installed and can be loaded into the park.
|
||||||
|
*/
|
||||||
|
readonly installedObjects: InstalledObject[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the installed object with the given identifier, or null
|
||||||
|
* if the object was not found.
|
||||||
|
* @param identifier The object identifier.
|
||||||
|
*/
|
||||||
|
getInstalledObject(identifier: string): InstalledObject | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to load the object into the current park at the given index for the object type.
|
||||||
|
* If an object already exists at the given index, that object will be unloaded and this object
|
||||||
|
* will replace it, providing the object type is the same.
|
||||||
|
* @param identifier The object identifier.
|
||||||
|
* @param index The index to load the object to. If not provided, an empty slot will be used.
|
||||||
|
* @returns The index of the loaded object.
|
||||||
|
*/
|
||||||
|
load(identifier: string, index?: number): LoadedObject | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to load the given objects into the current park, given they are not already loaded.
|
||||||
|
*/
|
||||||
|
load(identifiers: string[]): (LoadedObject | null)[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads the object, if loaded.
|
||||||
|
* @param identifier The object identifier to unload.
|
||||||
|
*/
|
||||||
|
unload(identifier: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads the specified objects, if loaded.
|
||||||
|
* @param identifiers The object identifiers to unload.
|
||||||
|
*/
|
||||||
|
unload(identifiers: string[]): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads the specified object, if loaded.
|
||||||
|
* @param type The object type.
|
||||||
|
* @param index The index of the slot to unload for the given type.
|
||||||
|
*/
|
||||||
|
unload(type: ObjectType, index: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the loaded object at the given index.
|
||||||
|
* @param type The object type.
|
||||||
|
* @param index The index.
|
||||||
|
*/
|
||||||
|
getObject(type: ObjectType, index: number): LoadedObject;
|
||||||
|
getObject(type: "ride", index: number): RideObject;
|
||||||
|
getObject(type: "small_scenery", index: number): SmallSceneryObject;
|
||||||
|
getObject(type: "large_scenery", index: number): LargeSceneryObject;
|
||||||
|
getObject(type: "wall", index: number): WallObject;
|
||||||
|
getObject(type: "footpath_addition", index: number): FootpathAdditionObject;
|
||||||
|
getObject(type: "banner", index: number): BannerObject;
|
||||||
|
getObject(type: "scenery_group", index: number): SceneryGroupObject;
|
||||||
|
getObject(type: "music", index: number): LoadedObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the currently loaded objects for a given object type.
|
||||||
|
* @param type The object type.
|
||||||
|
*/
|
||||||
|
getAllObjects(type: ObjectType): LoadedObject[];
|
||||||
|
getAllObjects(type: "ride"): RideObject[];
|
||||||
|
getAllObjects(type: "small_scenery"): SmallSceneryObject[];
|
||||||
|
getAllObjects(type: "large_scenery"): LargeSceneryObject[];
|
||||||
|
getAllObjects(type: "wall"): WallObject[];
|
||||||
|
getAllObjects(type: "footpath_addition"): FootpathAdditionObject[];
|
||||||
|
getAllObjects(type: "banner"): BannerObject[];
|
||||||
|
getAllObjects(type: "scenery_group"): SceneryGroupObject[];
|
||||||
|
getAllObjects(type: "music"): LoadedObject[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -514,6 +514,8 @@
|
||||||
<ClInclude Include="scripting\bindings\game\ScProfiler.hpp" />
|
<ClInclude Include="scripting\bindings\game\ScProfiler.hpp" />
|
||||||
<ClInclude Include="scripting\bindings\network\ScPlayer.hpp" />
|
<ClInclude Include="scripting\bindings\network\ScPlayer.hpp" />
|
||||||
<ClInclude Include="scripting\bindings\network\ScPlayerGroup.hpp" />
|
<ClInclude Include="scripting\bindings\network\ScPlayerGroup.hpp" />
|
||||||
|
<ClInclude Include="scripting\bindings\object\ScInstalledObject.hpp" />
|
||||||
|
<ClInclude Include="scripting\bindings\object\ScObjectManager.h" />
|
||||||
<ClInclude Include="scripting\bindings\ride\ScRideStation.hpp" />
|
<ClInclude Include="scripting\bindings\ride\ScRideStation.hpp" />
|
||||||
<ClInclude Include="scripting\bindings\ride\ScTrackIterator.h" />
|
<ClInclude Include="scripting\bindings\ride\ScTrackIterator.h" />
|
||||||
<ClInclude Include="scripting\bindings\ride\ScTrackSegment.h" />
|
<ClInclude Include="scripting\bindings\ride\ScTrackSegment.h" />
|
||||||
|
@ -996,6 +998,7 @@
|
||||||
<ClCompile Include="scripting\bindings\network\ScNetwork.cpp" />
|
<ClCompile Include="scripting\bindings\network\ScNetwork.cpp" />
|
||||||
<ClCompile Include="scripting\bindings\network\ScPlayer.cpp" />
|
<ClCompile Include="scripting\bindings\network\ScPlayer.cpp" />
|
||||||
<ClCompile Include="scripting\bindings\network\ScPlayerGroup.cpp" />
|
<ClCompile Include="scripting\bindings\network\ScPlayerGroup.cpp" />
|
||||||
|
<ClCompile Include="scripting\bindings\object\ScObjectManager.cpp" />
|
||||||
<ClCompile Include="scripting\bindings\ride\ScRide.cpp" />
|
<ClCompile Include="scripting\bindings\ride\ScRide.cpp" />
|
||||||
<ClCompile Include="scripting\bindings\ride\ScRideStation.cpp" />
|
<ClCompile Include="scripting\bindings\ride\ScRideStation.cpp" />
|
||||||
<ClCompile Include="scripting\bindings\ride\ScTrackIterator.cpp" />
|
<ClCompile Include="scripting\bindings\ride\ScTrackIterator.cpp" />
|
||||||
|
|
|
@ -80,6 +80,47 @@ std::string_view ObjectEntryDescriptor::GetName() const
|
||||||
return Generation == ObjectGeneration::JSON ? Identifier : Entry.GetName();
|
return Generation == ObjectGeneration::JSON ? Identifier : Entry.GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ObjectEntryDescriptor::ToString() const
|
||||||
|
{
|
||||||
|
if (Generation == ObjectGeneration::DAT)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
std::snprintf(&buffer[0], 9, "%08X", Entry.flags);
|
||||||
|
buffer[8] = '|';
|
||||||
|
std::memcpy(&buffer[9], Entry.name, 8);
|
||||||
|
buffer[17] = '|';
|
||||||
|
std::snprintf(&buffer[18], 9, "%8X", Entry.checksum);
|
||||||
|
return std::string(buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::string(GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ParseHex(std::string_view x)
|
||||||
|
{
|
||||||
|
assert(x.size() != 8);
|
||||||
|
char buffer[9];
|
||||||
|
std::memcpy(buffer, x.data(), 8);
|
||||||
|
buffer[8] = 0;
|
||||||
|
char* endp{};
|
||||||
|
return static_cast<uint32_t>(std::strtol(buffer, &endp, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectEntryDescriptor ObjectEntryDescriptor::Parse(std::string_view identifier)
|
||||||
|
{
|
||||||
|
if (identifier.size() == 26 && identifier[8] == '|' && identifier[17] == '|')
|
||||||
|
{
|
||||||
|
RCTObjectEntry entry{};
|
||||||
|
entry.flags = ParseHex(identifier.substr(0, 8));
|
||||||
|
entry.SetName(identifier.substr(9, 8));
|
||||||
|
entry.checksum = ParseHex(identifier.substr(18));
|
||||||
|
return ObjectEntryDescriptor(entry);
|
||||||
|
}
|
||||||
|
return ObjectEntryDescriptor(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
bool ObjectEntryDescriptor::operator==(const ObjectEntryDescriptor& rhs) const
|
bool ObjectEntryDescriptor::operator==(const ObjectEntryDescriptor& rhs) const
|
||||||
{
|
{
|
||||||
if (Generation != rhs.Generation)
|
if (Generation != rhs.Generation)
|
||||||
|
|
|
@ -139,9 +139,12 @@ struct ObjectEntryDescriptor
|
||||||
bool HasValue() const;
|
bool HasValue() const;
|
||||||
ObjectType GetType() const;
|
ObjectType GetType() const;
|
||||||
std::string_view GetName() const;
|
std::string_view GetName() const;
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
bool operator==(const ObjectEntryDescriptor& rhs) const;
|
bool operator==(const ObjectEntryDescriptor& rhs) const;
|
||||||
bool operator!=(const ObjectEntryDescriptor& rhs) const;
|
bool operator!=(const ObjectEntryDescriptor& rhs) const;
|
||||||
|
|
||||||
|
static ObjectEntryDescriptor Parse(std::string_view identifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IObjectRepository;
|
struct IObjectRepository;
|
||||||
|
|
|
@ -175,6 +175,12 @@ public:
|
||||||
return RepositoryItemToObject(ori);
|
return RepositoryItemToObject(ori);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object* LoadObject(const ObjectEntryDescriptor& descriptor, ObjectEntryIndex slot) override
|
||||||
|
{
|
||||||
|
const ObjectRepositoryItem* ori = _objectRepository.FindObject(descriptor);
|
||||||
|
return RepositoryItemToObject(ori, slot);
|
||||||
|
}
|
||||||
|
|
||||||
void LoadObjects(const ObjectList& objectList) override
|
void LoadObjects(const ObjectList& objectList) override
|
||||||
{
|
{
|
||||||
// Find all the required objects
|
// Find all the required objects
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct IObjectManager
|
||||||
virtual Object* LoadObject(std::string_view identifier) abstract;
|
virtual Object* LoadObject(std::string_view identifier) abstract;
|
||||||
virtual Object* LoadObject(const RCTObjectEntry* entry) abstract;
|
virtual Object* LoadObject(const RCTObjectEntry* entry) abstract;
|
||||||
virtual Object* LoadObject(const ObjectEntryDescriptor& descriptor) abstract;
|
virtual Object* LoadObject(const ObjectEntryDescriptor& descriptor) abstract;
|
||||||
|
virtual Object* LoadObject(const ObjectEntryDescriptor& descriptor, ObjectEntryIndex slot) abstract;
|
||||||
virtual void LoadObjects(const ObjectList& entries) abstract;
|
virtual void LoadObjects(const ObjectList& entries) abstract;
|
||||||
virtual void UnloadObjects(const std::vector<ObjectEntryDescriptor>& entries) abstract;
|
virtual void UnloadObjects(const std::vector<ObjectEntryDescriptor>& entries) abstract;
|
||||||
virtual void UnloadAllTransient() abstract;
|
virtual void UnloadAllTransient() abstract;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "ObjectTypes.h"
|
#include "Object.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -20,3 +20,11 @@ bool ObjectTypeIsIntransient(ObjectType type)
|
||||||
{
|
{
|
||||||
return std::find(IntransientObjectTypes.begin(), IntransientObjectTypes.end(), type) != std::end(IntransientObjectTypes);
|
return std::find(IntransientObjectTypes.begin(), IntransientObjectTypes.end(), type) != std::end(IntransientObjectTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GetObjectTypeLimit(ObjectType type)
|
||||||
|
{
|
||||||
|
auto index = EnumValue(type);
|
||||||
|
if (index >= EnumValue(ObjectType::Count))
|
||||||
|
return 0;
|
||||||
|
return static_cast<size_t>(object_entry_group_counts[index]);
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
@ -78,3 +79,4 @@ constexpr std::array<ObjectType, 2> IntransientObjectTypes = { ObjectType::Scena
|
||||||
|
|
||||||
bool ObjectTypeIsTransient(ObjectType type);
|
bool ObjectTypeIsTransient(ObjectType type);
|
||||||
bool ObjectTypeIsIntransient(ObjectType type);
|
bool ObjectTypeIsIntransient(ObjectType type);
|
||||||
|
size_t GetObjectTypeLimit(ObjectType type);
|
||||||
|
|
|
@ -243,3 +243,8 @@ uint16_t SceneryGroupObject::GetNumIncludedObjects() const
|
||||||
{
|
{
|
||||||
return static_cast<uint16_t>(_items.size());
|
return static_cast<uint16_t>(_items.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<ObjectEntryDescriptor>& SceneryGroupObject::GetItems() const
|
||||||
|
{
|
||||||
|
return _items;
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ public:
|
||||||
void SetRepositoryItem(ObjectRepositoryItem* item) const override;
|
void SetRepositoryItem(ObjectRepositoryItem* item) const override;
|
||||||
|
|
||||||
uint16_t GetNumIncludedObjects() const;
|
uint16_t GetNumIncludedObjects() const;
|
||||||
|
const std::vector<ObjectEntryDescriptor>& GetItems() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<ObjectEntryDescriptor> ReadItems(OpenRCT2::IStream* stream);
|
static std::vector<ObjectEntryDescriptor> ReadItems(OpenRCT2::IStream* stream);
|
||||||
|
|
|
@ -39,7 +39,9 @@
|
||||||
# include "bindings/network/ScPlayer.hpp"
|
# include "bindings/network/ScPlayer.hpp"
|
||||||
# include "bindings/network/ScPlayerGroup.hpp"
|
# include "bindings/network/ScPlayerGroup.hpp"
|
||||||
# include "bindings/network/ScSocket.hpp"
|
# include "bindings/network/ScSocket.hpp"
|
||||||
|
# include "bindings/object/ScInstalledObject.hpp"
|
||||||
# include "bindings/object/ScObject.hpp"
|
# include "bindings/object/ScObject.hpp"
|
||||||
|
# include "bindings/object/ScObjectManager.h"
|
||||||
# include "bindings/ride/ScRide.hpp"
|
# include "bindings/ride/ScRide.hpp"
|
||||||
# include "bindings/ride/ScRideStation.hpp"
|
# include "bindings/ride/ScRideStation.hpp"
|
||||||
# include "bindings/world/ScClimate.hpp"
|
# include "bindings/world/ScClimate.hpp"
|
||||||
|
@ -403,8 +405,16 @@ void ScriptEngine::Initialise()
|
||||||
ScDisposable::Register(ctx);
|
ScDisposable::Register(ctx);
|
||||||
ScMap::Register(ctx);
|
ScMap::Register(ctx);
|
||||||
ScNetwork::Register(ctx);
|
ScNetwork::Register(ctx);
|
||||||
|
ScObjectManager::Register(ctx);
|
||||||
|
ScInstalledObject::Register(ctx);
|
||||||
ScObject::Register(ctx);
|
ScObject::Register(ctx);
|
||||||
|
ScSceneryObject::Register(ctx);
|
||||||
ScSmallSceneryObject::Register(ctx);
|
ScSmallSceneryObject::Register(ctx);
|
||||||
|
ScLargeSceneryObject::Register(ctx);
|
||||||
|
ScWallObject::Register(ctx);
|
||||||
|
ScFootpathAdditionObject::Register(ctx);
|
||||||
|
ScBannerObject::Register(ctx);
|
||||||
|
ScSceneryGroupObject::Register(ctx);
|
||||||
ScPark::Register(ctx);
|
ScPark::Register(ctx);
|
||||||
ScParkMessage::Register(ctx);
|
ScParkMessage::Register(ctx);
|
||||||
ScPlayer::Register(ctx);
|
ScPlayer::Register(ctx);
|
||||||
|
@ -444,6 +454,7 @@ void ScriptEngine::Initialise()
|
||||||
dukglue_register_global(ctx, std::make_shared<ScPark>(ctx), "park");
|
dukglue_register_global(ctx, std::make_shared<ScPark>(ctx), "park");
|
||||||
dukglue_register_global(ctx, std::make_shared<ScProfiler>(ctx), "profiler");
|
dukglue_register_global(ctx, std::make_shared<ScProfiler>(ctx), "profiler");
|
||||||
dukglue_register_global(ctx, std::make_shared<ScScenario>(), "scenario");
|
dukglue_register_global(ctx, std::make_shared<ScScenario>(), "scenario");
|
||||||
|
dukglue_register_global(ctx, std::make_shared<ScObjectManager>(), "objectManager");
|
||||||
|
|
||||||
RegisterConstants();
|
RegisterConstants();
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace OpenRCT2
|
||||||
|
|
||||||
namespace OpenRCT2::Scripting
|
namespace OpenRCT2::Scripting
|
||||||
{
|
{
|
||||||
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 77;
|
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 78;
|
||||||
|
|
||||||
// Versions marking breaking changes.
|
// Versions marking breaking changes.
|
||||||
static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33;
|
static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
# include "../../ScriptEngine.h"
|
# include "../../ScriptEngine.h"
|
||||||
# include "../game/ScConfiguration.hpp"
|
# include "../game/ScConfiguration.hpp"
|
||||||
# include "../game/ScDisposable.hpp"
|
# include "../game/ScDisposable.hpp"
|
||||||
# include "../object/ScObject.hpp"
|
# include "../object/ScObjectManager.h"
|
||||||
# include "../ride/ScTrackSegment.h"
|
# include "../ride/ScTrackSegment.h"
|
||||||
|
|
||||||
# include <cstdio>
|
# include <cstdio>
|
||||||
|
@ -160,64 +160,18 @@ namespace OpenRCT2::Scripting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DukValue CreateScObject(duk_context* ctx, ObjectType type, int32_t index)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case ObjectType::Ride:
|
|
||||||
return GetObjectAsDukValue(ctx, std::make_shared<ScRideObject>(type, index));
|
|
||||||
case ObjectType::SmallScenery:
|
|
||||||
return GetObjectAsDukValue(ctx, std::make_shared<ScSmallSceneryObject>(type, index));
|
|
||||||
default:
|
|
||||||
return GetObjectAsDukValue(ctx, std::make_shared<ScObject>(type, index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DukValue getObject(const std::string& typez, int32_t index) const
|
DukValue getObject(const std::string& typez, int32_t index) const
|
||||||
{
|
{
|
||||||
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
// deprecated function, moved to ObjectManager.getObject.
|
||||||
auto& objManager = GetContext()->GetObjectManager();
|
ScObjectManager objectManager;
|
||||||
|
return objectManager.getObject(typez, index);
|
||||||
auto type = ScObject::StringToObjectType(typez);
|
|
||||||
if (type)
|
|
||||||
{
|
|
||||||
auto obj = objManager.GetLoadedObject(*type, index);
|
|
||||||
if (obj != nullptr)
|
|
||||||
{
|
|
||||||
return CreateScObject(ctx, *type, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
duk_error(ctx, DUK_ERR_ERROR, "Invalid object type.");
|
|
||||||
}
|
|
||||||
return ToDuk(ctx, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DukValue> getAllObjects(const std::string& typez) const
|
std::vector<DukValue> getAllObjects(const std::string& typez) const
|
||||||
{
|
{
|
||||||
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
// deprecated function, moved to ObjectManager.getAllObjects.
|
||||||
auto& objManager = GetContext()->GetObjectManager();
|
ScObjectManager objectManager;
|
||||||
|
return objectManager.getAllObjects(typez);
|
||||||
std::vector<DukValue> result;
|
|
||||||
auto type = ScObject::StringToObjectType(typez);
|
|
||||||
if (type)
|
|
||||||
{
|
|
||||||
auto count = object_entry_group_counts[EnumValue(*type)];
|
|
||||||
for (int32_t i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
auto obj = objManager.GetLoadedObject(*type, i);
|
|
||||||
if (obj != nullptr)
|
|
||||||
{
|
|
||||||
result.push_back(CreateScObject(ctx, *type, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
duk_error(ctx, DUK_ERR_ERROR, "Invalid object type.");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DukValue getTrackSegment(track_type_t type)
|
DukValue getTrackSegment(track_type_t type)
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||||
|
*
|
||||||
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
|
*
|
||||||
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
# include "../../../Context.h"
|
||||||
|
# include "../../../common.h"
|
||||||
|
# include "../../../object/ObjectRepository.h"
|
||||||
|
# include "../../Duktape.hpp"
|
||||||
|
# include "../../ScriptEngine.h"
|
||||||
|
|
||||||
|
# include <optional>
|
||||||
|
|
||||||
|
namespace OpenRCT2::Scripting
|
||||||
|
{
|
||||||
|
inline std::string_view ObjectTypeToString(uint8_t type)
|
||||||
|
{
|
||||||
|
static constexpr std::string_view Types[] = {
|
||||||
|
"ride",
|
||||||
|
"small_scenery",
|
||||||
|
"large_scenery",
|
||||||
|
"wall",
|
||||||
|
"banner",
|
||||||
|
"footpath",
|
||||||
|
"footpath_addition",
|
||||||
|
"scenery_group",
|
||||||
|
"park_entrance",
|
||||||
|
"water",
|
||||||
|
"stex",
|
||||||
|
"terrain_surface",
|
||||||
|
"terrain_edge",
|
||||||
|
"station",
|
||||||
|
"music",
|
||||||
|
"footpath_surface",
|
||||||
|
"footpath_railings",
|
||||||
|
};
|
||||||
|
if (type >= std::size(Types))
|
||||||
|
return "unknown";
|
||||||
|
return Types[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string_view ObjectSourceGameToString(ObjectSourceGame sourceGame)
|
||||||
|
{
|
||||||
|
static constexpr std::string_view values[] = { "custom", "wacky_worlds", "time_twister", "openrct2_official",
|
||||||
|
"rct1", "added_attractions", "loopy_landscapes", "unknown",
|
||||||
|
"rct2" };
|
||||||
|
if (EnumValue(sourceGame) >= std::size(values))
|
||||||
|
return "unknown";
|
||||||
|
return values[EnumValue(sourceGame)];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScInstalledObject
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
size_t _index{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScInstalledObject(size_t index)
|
||||||
|
: _index(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::path_get, nullptr, "path");
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::generation_get, nullptr, "generation");
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::identifier_get, nullptr, "identifier");
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::type_get, nullptr, "type");
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::sourceGames_get, nullptr, "sourceGames");
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::legacyIdentifier_get, nullptr, "legacyIdentifier");
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::authors_get, nullptr, "authors");
|
||||||
|
dukglue_register_property(ctx, &ScInstalledObject::name_get, nullptr, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string path_get() const
|
||||||
|
{
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
return installedObject->Path;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string generation_get() const
|
||||||
|
{
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
if (installedObject->Generation == ObjectGeneration::DAT)
|
||||||
|
return "dat";
|
||||||
|
else
|
||||||
|
return "json";
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> sourceGames_get() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
for (const auto& sourceGame : installedObject->Sources)
|
||||||
|
{
|
||||||
|
result.push_back(std::string(ObjectSourceGameToString(sourceGame)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string type_get() const
|
||||||
|
{
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
return std::string(ObjectTypeToString(EnumValue(installedObject->Type)));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string identifier_get() const
|
||||||
|
{
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
if (installedObject->Generation == ObjectGeneration::DAT)
|
||||||
|
{
|
||||||
|
return ObjectEntryDescriptor(installedObject->ObjectEntry).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return installedObject->Identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
DukValue legacyIdentifier_get() const
|
||||||
|
{
|
||||||
|
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
if (!installedObject->ObjectEntry.IsEmpty())
|
||||||
|
{
|
||||||
|
return ToDuk(ctx, installedObject->ObjectEntry.GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ToDuk(ctx, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> authors_get() const
|
||||||
|
{
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
return installedObject->Authors;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_get() const
|
||||||
|
{
|
||||||
|
auto installedObject = GetInstalledObject();
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
return installedObject->Name;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const ObjectRepositoryItem* GetInstalledObject() const
|
||||||
|
{
|
||||||
|
auto context = GetContext();
|
||||||
|
auto& objectRepository = context->GetObjectRepository();
|
||||||
|
auto numObjects = objectRepository.GetNumObjects();
|
||||||
|
if (_index < numObjects)
|
||||||
|
{
|
||||||
|
auto* objects = objectRepository.GetObjects();
|
||||||
|
return &objects[_index];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace OpenRCT2::Scripting
|
||||||
|
|
||||||
|
#endif
|
|
@ -15,9 +15,11 @@
|
||||||
# include "../../../common.h"
|
# include "../../../common.h"
|
||||||
# include "../../../object/ObjectManager.h"
|
# include "../../../object/ObjectManager.h"
|
||||||
# include "../../../object/RideObject.h"
|
# include "../../../object/RideObject.h"
|
||||||
|
# include "../../../object/SceneryGroupObject.h"
|
||||||
# include "../../../object/SmallSceneryObject.h"
|
# include "../../../object/SmallSceneryObject.h"
|
||||||
# include "../../Duktape.hpp"
|
# include "../../Duktape.hpp"
|
||||||
# include "../../ScriptEngine.h"
|
# include "../../ScriptEngine.h"
|
||||||
|
# include "ScInstalledObject.hpp"
|
||||||
|
|
||||||
# include <memory>
|
# include <memory>
|
||||||
# include <optional>
|
# include <optional>
|
||||||
|
@ -39,6 +41,7 @@ namespace OpenRCT2::Scripting
|
||||||
|
|
||||||
static void Register(duk_context* ctx)
|
static void Register(duk_context* ctx)
|
||||||
{
|
{
|
||||||
|
dukglue_register_property(ctx, &ScObject::installedObject_get, nullptr, "installedObject");
|
||||||
dukglue_register_property(ctx, &ScObject::type_get, nullptr, "type");
|
dukglue_register_property(ctx, &ScObject::type_get, nullptr, "type");
|
||||||
dukglue_register_property(ctx, &ScObject::index_get, nullptr, "index");
|
dukglue_register_property(ctx, &ScObject::index_get, nullptr, "index");
|
||||||
dukglue_register_property(ctx, &ScObject::identifier_get, nullptr, "identifier");
|
dukglue_register_property(ctx, &ScObject::identifier_get, nullptr, "identifier");
|
||||||
|
@ -58,36 +61,25 @@ namespace OpenRCT2::Scripting
|
||||||
return static_cast<ObjectType>(i);
|
return static_cast<ObjectType>(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ObjectType::None;
|
return std::nullopt;
|
||||||
}
|
|
||||||
|
|
||||||
static std::string_view ObjectTypeToString(uint8_t type)
|
|
||||||
{
|
|
||||||
static constexpr std::string_view Types[] = {
|
|
||||||
"ride",
|
|
||||||
"small_scenery",
|
|
||||||
"large_scenery",
|
|
||||||
"wall",
|
|
||||||
"banner",
|
|
||||||
"footpath",
|
|
||||||
"footpath_addition",
|
|
||||||
"scenery_group",
|
|
||||||
"park_entrance",
|
|
||||||
"water",
|
|
||||||
"stex",
|
|
||||||
"terrain_surface",
|
|
||||||
"terrain_edge",
|
|
||||||
"station",
|
|
||||||
"music",
|
|
||||||
"footpath_surface",
|
|
||||||
"footpath_railings",
|
|
||||||
};
|
|
||||||
if (type >= std::size(Types))
|
|
||||||
return "unknown";
|
|
||||||
return Types[type];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::shared_ptr<ScInstalledObject> installedObject_get() const
|
||||||
|
{
|
||||||
|
auto obj = GetObject();
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
auto& objectRepository = GetContext()->GetObjectRepository();
|
||||||
|
auto installedObject = objectRepository.FindObject(obj->GetDescriptor());
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
return std::make_shared<ScInstalledObject>(installedObject->Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::string type_get() const
|
std::string type_get() const
|
||||||
{
|
{
|
||||||
return std::string(ObjectTypeToString(EnumValue(_type)));
|
return std::string(ObjectTypeToString(EnumValue(_type)));
|
||||||
|
@ -102,9 +94,16 @@ namespace OpenRCT2::Scripting
|
||||||
{
|
{
|
||||||
auto obj = GetObject();
|
auto obj = GetObject();
|
||||||
if (obj != nullptr)
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
if (obj->GetGeneration() == ObjectGeneration::DAT)
|
||||||
|
{
|
||||||
|
return obj->GetDescriptor().ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return std::string(obj->GetIdentifier());
|
return std::string(obj->GetIdentifier());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,17 +790,53 @@ namespace OpenRCT2::Scripting
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScSmallSceneryObject : public ScObject
|
class ScSceneryObject : public ScObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScSmallSceneryObject(ObjectType type, int32_t index)
|
ScSceneryObject(ObjectType type, int32_t index)
|
||||||
: ScObject(type, index)
|
: ScObject(type, index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Register(duk_context* ctx)
|
static void Register(duk_context* ctx)
|
||||||
{
|
{
|
||||||
dukglue_set_base_class<ScObject, ScSmallSceneryObject>(ctx);
|
dukglue_set_base_class<ScObject, ScSceneryObject>(ctx);
|
||||||
|
dukglue_register_property(ctx, &ScSceneryObject::sceneryGroups_get, nullptr, "sceneryGroups");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> sceneryGroups_get() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
auto obj = GetObject();
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
auto& scgDescriptor = obj->GetPrimarySceneryGroup();
|
||||||
|
if (scgDescriptor.HasValue())
|
||||||
|
{
|
||||||
|
result.push_back(scgDescriptor.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneryObject* GetObject() const
|
||||||
|
{
|
||||||
|
return static_cast<SceneryObject*>(ScObject::GetObject());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScSmallSceneryObject : public ScSceneryObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScSmallSceneryObject(ObjectType type, int32_t index)
|
||||||
|
: ScSceneryObject(type, index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_set_base_class<ScSceneryObject, ScSmallSceneryObject>(ctx);
|
||||||
dukglue_register_property(ctx, &ScSmallSceneryObject::flags_get, nullptr, "flags");
|
dukglue_register_property(ctx, &ScSmallSceneryObject::flags_get, nullptr, "flags");
|
||||||
dukglue_register_property(ctx, &ScSmallSceneryObject::height_get, nullptr, "height");
|
dukglue_register_property(ctx, &ScSmallSceneryObject::height_get, nullptr, "height");
|
||||||
dukglue_register_property(ctx, &ScSmallSceneryObject::price_get, nullptr, "price");
|
dukglue_register_property(ctx, &ScSmallSceneryObject::price_get, nullptr, "price");
|
||||||
|
@ -865,6 +900,99 @@ namespace OpenRCT2::Scripting
|
||||||
return static_cast<SmallSceneryObject*>(ScObject::GetObject());
|
return static_cast<SmallSceneryObject*>(ScObject::GetObject());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScLargeSceneryObject : public ScSceneryObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScLargeSceneryObject(ObjectType type, int32_t index)
|
||||||
|
: ScSceneryObject(type, index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_set_base_class<ScSceneryObject, ScLargeSceneryObject>(ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScWallObject : public ScSceneryObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScWallObject(ObjectType type, int32_t index)
|
||||||
|
: ScSceneryObject(type, index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_set_base_class<ScSceneryObject, ScWallObject>(ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScFootpathAdditionObject : public ScSceneryObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScFootpathAdditionObject(ObjectType type, int32_t index)
|
||||||
|
: ScSceneryObject(type, index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_set_base_class<ScSceneryObject, ScFootpathAdditionObject>(ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScBannerObject : public ScSceneryObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScBannerObject(ObjectType type, int32_t index)
|
||||||
|
: ScSceneryObject(type, index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_set_base_class<ScSceneryObject, ScBannerObject>(ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScSceneryGroupObject : public ScObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScSceneryGroupObject(ObjectType type, int32_t index)
|
||||||
|
: ScObject(type, index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_set_base_class<ScObject, ScSceneryGroupObject>(ctx);
|
||||||
|
dukglue_register_property(ctx, &ScSceneryGroupObject::items_get, nullptr, "items");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> items_get() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
auto obj = GetObject();
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
auto& items = obj->GetItems();
|
||||||
|
for (const auto& item : items)
|
||||||
|
{
|
||||||
|
result.push_back(item.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SceneryGroupObject* GetObject() const
|
||||||
|
{
|
||||||
|
return static_cast<SceneryGroupObject*>(ScObject::GetObject());
|
||||||
|
}
|
||||||
|
};
|
||||||
} // namespace OpenRCT2::Scripting
|
} // namespace OpenRCT2::Scripting
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,283 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (c) 2014-2023 OpenRCT2 developers
|
||||||
|
*
|
||||||
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
|
*
|
||||||
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
# include "ScObjectManager.h"
|
||||||
|
|
||||||
|
# include "../../../object/ObjectList.h"
|
||||||
|
# include "../../../ride/RideData.h"
|
||||||
|
# include "../../Duktape.hpp"
|
||||||
|
# include "../../ScriptEngine.h"
|
||||||
|
|
||||||
|
using namespace OpenRCT2;
|
||||||
|
using namespace OpenRCT2::Scripting;
|
||||||
|
|
||||||
|
void ScObjectManager::Register(duk_context* ctx)
|
||||||
|
{
|
||||||
|
dukglue_register_property(ctx, &ScObjectManager::installedObjects_get, nullptr, "installedObjects");
|
||||||
|
dukglue_register_method(ctx, &ScObjectManager::load, "load");
|
||||||
|
dukglue_register_method(ctx, &ScObjectManager::unload, "unload");
|
||||||
|
dukglue_register_method(ctx, &ScObjectManager::getObject, "getObject");
|
||||||
|
dukglue_register_method(ctx, &ScObjectManager::getAllObjects, "getAllObjects");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<ScInstalledObject>> ScObjectManager::installedObjects_get() const
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<ScInstalledObject>> result;
|
||||||
|
|
||||||
|
auto context = GetContext();
|
||||||
|
auto& objectManager = context->GetObjectRepository();
|
||||||
|
auto count = objectManager.GetNumObjects();
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
auto installedObject = std::make_shared<ScInstalledObject>(i);
|
||||||
|
result.push_back(installedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DukValue ScObjectManager::load(const DukValue& p1, const DukValue& p2)
|
||||||
|
{
|
||||||
|
auto context = GetContext();
|
||||||
|
auto& scriptEngine = context->GetScriptEngine();
|
||||||
|
auto& objectRepository = context->GetObjectRepository();
|
||||||
|
auto& objectManager = context->GetObjectManager();
|
||||||
|
auto ctx = scriptEngine.GetContext();
|
||||||
|
|
||||||
|
if (p1.is_array())
|
||||||
|
{
|
||||||
|
// load(identifiers)
|
||||||
|
std::vector<ObjectEntryDescriptor> descriptors;
|
||||||
|
for (const auto& item : p1.as_array())
|
||||||
|
{
|
||||||
|
if (item.type() != DukValue::STRING)
|
||||||
|
throw DukException() << "Expected string for 'identifier'.";
|
||||||
|
|
||||||
|
const auto& identifier = item.as_string();
|
||||||
|
descriptors.push_back(ObjectEntryDescriptor::Parse(identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_push_array(ctx);
|
||||||
|
duk_uarridx_t index = 0;
|
||||||
|
for (const auto& descriptor : descriptors)
|
||||||
|
{
|
||||||
|
auto obj = objectManager.LoadObject(descriptor);
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
MarkAsResearched(obj);
|
||||||
|
auto objIndex = objectManager.GetLoadedObjectEntryIndex(obj);
|
||||||
|
auto scLoadedObject = CreateScObject(scriptEngine.GetContext(), obj->GetObjectType(), objIndex);
|
||||||
|
scLoadedObject.push();
|
||||||
|
duk_put_prop_index(ctx, -2, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duk_push_null(ctx);
|
||||||
|
duk_put_prop_index(ctx, -2, index);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
RefreshResearchedItems();
|
||||||
|
return DukValue::take_from_stack(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// load(identifier, index?)
|
||||||
|
if (p1.type() != DukValue::STRING)
|
||||||
|
throw DukException() << "Expected string for 'identifier'.";
|
||||||
|
|
||||||
|
const auto& identifier = p1.as_string();
|
||||||
|
auto descriptor = ObjectEntryDescriptor::Parse(identifier);
|
||||||
|
|
||||||
|
auto installedObject = objectRepository.FindObject(descriptor);
|
||||||
|
if (installedObject != nullptr)
|
||||||
|
{
|
||||||
|
if (p2.type() != DukValue::UNDEFINED)
|
||||||
|
{
|
||||||
|
if (p2.type() != DukValue::NUMBER)
|
||||||
|
throw DukException() << "Expected number for 'index'.";
|
||||||
|
|
||||||
|
auto index = static_cast<size_t>(p2.as_int());
|
||||||
|
auto limit = GetObjectTypeLimit(installedObject->Type);
|
||||||
|
if (index < limit)
|
||||||
|
{
|
||||||
|
auto loadedObject = objectManager.GetLoadedObject(installedObject->Type, index);
|
||||||
|
if (loadedObject != nullptr)
|
||||||
|
{
|
||||||
|
objectManager.UnloadObjects({ loadedObject->GetDescriptor() });
|
||||||
|
}
|
||||||
|
auto obj = objectManager.LoadObject(descriptor, static_cast<ObjectEntryIndex>(index));
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
MarkAsResearched(obj);
|
||||||
|
RefreshResearchedItems();
|
||||||
|
auto objIndex = objectManager.GetLoadedObjectEntryIndex(obj);
|
||||||
|
return CreateScObject(scriptEngine.GetContext(), obj->GetObjectType(), objIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto obj = objectManager.LoadObject(descriptor);
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
MarkAsResearched(obj);
|
||||||
|
RefreshResearchedItems();
|
||||||
|
auto objIndex = objectManager.GetLoadedObjectEntryIndex(obj);
|
||||||
|
return CreateScObject(scriptEngine.GetContext(), obj->GetObjectType(), objIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ToDuk(ctx, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScObjectManager::unload(const DukValue& p1, const DukValue& p2)
|
||||||
|
{
|
||||||
|
auto context = GetContext();
|
||||||
|
auto& objectManager = context->GetObjectManager();
|
||||||
|
|
||||||
|
if (p1.type() == DukValue::STRING)
|
||||||
|
{
|
||||||
|
const auto& szP1 = p1.as_string();
|
||||||
|
auto objType = ScObject::StringToObjectType(szP1);
|
||||||
|
if (objType)
|
||||||
|
{
|
||||||
|
// unload(type, index)
|
||||||
|
if (p2.type() != DukValue::NUMBER)
|
||||||
|
throw DukException() << "'index' is invalid.";
|
||||||
|
|
||||||
|
auto objIndex = p2.as_int();
|
||||||
|
auto obj = objectManager.GetLoadedObject(*objType, objIndex);
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
objectManager.UnloadObjects({ obj->GetDescriptor() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// unload(identifier)
|
||||||
|
objectManager.UnloadObjects({ ObjectEntryDescriptor::Parse(szP1) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p1.is_array())
|
||||||
|
{
|
||||||
|
// unload(identifiers)
|
||||||
|
auto identifiers = p1.as_array();
|
||||||
|
std::vector<ObjectEntryDescriptor> descriptors;
|
||||||
|
for (const auto& identifier : identifiers)
|
||||||
|
{
|
||||||
|
if (identifier.type() == DukValue::STRING)
|
||||||
|
{
|
||||||
|
descriptors.push_back(ObjectEntryDescriptor::Parse(identifier.as_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
objectManager.UnloadObjects(descriptors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DukValue ScObjectManager::getObject(const std::string& typez, int32_t index) const
|
||||||
|
{
|
||||||
|
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
||||||
|
auto& objManager = GetContext()->GetObjectManager();
|
||||||
|
|
||||||
|
auto type = ScObject::StringToObjectType(typez);
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
auto obj = objManager.GetLoadedObject(*type, index);
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
return CreateScObject(ctx, *type, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duk_error(ctx, DUK_ERR_ERROR, "Invalid object type.");
|
||||||
|
}
|
||||||
|
return ToDuk(ctx, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DukValue> ScObjectManager::getAllObjects(const std::string& typez) const
|
||||||
|
{
|
||||||
|
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
||||||
|
auto& objManager = GetContext()->GetObjectManager();
|
||||||
|
|
||||||
|
std::vector<DukValue> result;
|
||||||
|
auto type = ScObject::StringToObjectType(typez);
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
auto count = object_entry_group_counts[EnumValue(*type)];
|
||||||
|
for (int32_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
auto obj = objManager.GetLoadedObject(*type, i);
|
||||||
|
if (obj != nullptr)
|
||||||
|
{
|
||||||
|
result.push_back(CreateScObject(ctx, *type, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duk_error(ctx, DUK_ERR_ERROR, "Invalid object type.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScObjectManager::MarkAsResearched(const Object* object)
|
||||||
|
{
|
||||||
|
// Defaults selected items to researched (if in-game)
|
||||||
|
auto objectType = object->GetObjectType();
|
||||||
|
auto entryIndex = ObjectManagerGetLoadedObjectEntryIndex(object);
|
||||||
|
if (objectType == ObjectType::Ride)
|
||||||
|
{
|
||||||
|
const auto* rideEntry = GetRideEntryByIndex(entryIndex);
|
||||||
|
auto rideType = rideEntry->GetFirstNonNullRideType();
|
||||||
|
auto category = static_cast<ResearchCategory>(GetRideTypeDescriptor(rideType).Category);
|
||||||
|
ResearchInsertRideEntry(rideType, entryIndex, category, true);
|
||||||
|
}
|
||||||
|
else if (objectType == ObjectType::SceneryGroup)
|
||||||
|
{
|
||||||
|
ResearchInsertSceneryGroupEntry(entryIndex, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScObjectManager::RefreshResearchedItems()
|
||||||
|
{
|
||||||
|
// Same thing object selection window and inventions window does
|
||||||
|
gSilentResearch = true;
|
||||||
|
ResearchResetCurrentItem();
|
||||||
|
gSilentResearch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DukValue ScObjectManager::CreateScObject(duk_context* ctx, ObjectType type, int32_t index)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ObjectType::Ride:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScRideObject>(type, index));
|
||||||
|
case ObjectType::SmallScenery:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScSmallSceneryObject>(type, index));
|
||||||
|
case ObjectType::LargeScenery:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScLargeSceneryObject>(type, index));
|
||||||
|
case ObjectType::Walls:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScWallObject>(type, index));
|
||||||
|
case ObjectType::PathBits:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScFootpathAdditionObject>(type, index));
|
||||||
|
case ObjectType::Banners:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScBannerObject>(type, index));
|
||||||
|
case ObjectType::SceneryGroup:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScSceneryGroupObject>(type, index));
|
||||||
|
default:
|
||||||
|
return GetObjectAsDukValue(ctx, std::make_shared<ScObject>(type, index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||||
|
*
|
||||||
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
|
*
|
||||||
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
# include "../../Duktape.hpp"
|
||||||
|
# include "../../ScriptEngine.h"
|
||||||
|
# include "ScInstalledObject.hpp"
|
||||||
|
# include "ScObject.hpp"
|
||||||
|
|
||||||
|
# include <memory>
|
||||||
|
|
||||||
|
namespace OpenRCT2::Scripting
|
||||||
|
{
|
||||||
|
class ScObjectManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Register(duk_context* ctx);
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<ScInstalledObject>> installedObjects_get() const;
|
||||||
|
|
||||||
|
DukValue load(const DukValue& p1, const DukValue& p2);
|
||||||
|
void unload(const DukValue& p1, const DukValue& p2);
|
||||||
|
|
||||||
|
DukValue getObject(const std::string& typez, int32_t index) const;
|
||||||
|
std::vector<DukValue> getAllObjects(const std::string& typez) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void MarkAsResearched(const Object* object);
|
||||||
|
static void RefreshResearchedItems();
|
||||||
|
static DukValue CreateScObject(duk_context* ctx, ObjectType type, int32_t index);
|
||||||
|
};
|
||||||
|
} // namespace OpenRCT2::Scripting
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue