mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Add Support For Extra Modules (#320)
Other mods can now add their own modules by using the API's `QueryBody` and `QuerySystem` methods.
This commit is contained in:
commit
5ba58f2642
5
NewHorizons/External/Configs/PlanetConfig.cs
vendored
5
NewHorizons/External/Configs/PlanetConfig.cs
vendored
@ -169,6 +169,11 @@ namespace NewHorizons.External.Configs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public WaterModule Water;
|
public WaterModule Water;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extra data that may be used by extension mods
|
||||||
|
/// </summary>
|
||||||
|
public object extras;
|
||||||
|
|
||||||
public PlanetConfig()
|
public PlanetConfig()
|
||||||
{
|
{
|
||||||
// Always have to have a base module
|
// Always have to have a base module
|
||||||
|
|||||||
@ -102,6 +102,11 @@ namespace NewHorizons.External.Configs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public CuriosityColorInfo[] curiosities;
|
public CuriosityColorInfo[] curiosities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extra data that may be used by extension mods
|
||||||
|
/// </summary>
|
||||||
|
public object extras;
|
||||||
|
|
||||||
public class NomaiCoordinates
|
public class NomaiCoordinates
|
||||||
{
|
{
|
||||||
[MinLength(2)]
|
[MinLength(2)]
|
||||||
|
|||||||
@ -248,6 +248,16 @@ namespace NewHorizons.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Main.Instance.OnPlanetLoaded?.Invoke(body.Config.name);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.LogError($"Error in event handler for OnPlanetLoaded on body {body.Config.name}: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,22 @@ namespace NewHorizons
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
UnityEvent<string> GetStarSystemLoadedEvent();
|
UnityEvent<string> GetStarSystemLoadedEvent();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An event invoked when NH has finished a planet for a star system.
|
||||||
|
/// Gives the name of the planet that was just loaded.
|
||||||
|
/// </summary>
|
||||||
|
UnityEvent<string> GetBodyLoadedEvent();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses JSONPath to query a body
|
||||||
|
/// </summary>
|
||||||
|
object QueryBody(Type outType, string bodyName, string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses JSONPath to query a system
|
||||||
|
/// </summary>
|
||||||
|
object QuerySystem(Type outType, string path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows you to overwrite the default system. This is where the player is respawned after dying.
|
/// Allows you to overwrite the default system. This is where the player is respawned after dying.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -68,6 +68,7 @@ namespace NewHorizons
|
|||||||
public class StarSystemEvent : UnityEvent<string> { }
|
public class StarSystemEvent : UnityEvent<string> { }
|
||||||
public StarSystemEvent OnChangeStarSystem;
|
public StarSystemEvent OnChangeStarSystem;
|
||||||
public StarSystemEvent OnStarSystemLoaded;
|
public StarSystemEvent OnStarSystemLoaded;
|
||||||
|
public StarSystemEvent OnPlanetLoaded;
|
||||||
|
|
||||||
// For warping to the eye system
|
// For warping to the eye system
|
||||||
private GameObject _ship;
|
private GameObject _ship;
|
||||||
@ -126,7 +127,7 @@ namespace NewHorizons
|
|||||||
|
|
||||||
BodyDict["SolarSystem"] = new List<NewHorizonsBody>();
|
BodyDict["SolarSystem"] = new List<NewHorizonsBody>();
|
||||||
BodyDict["EyeOfTheUniverse"] = new List<NewHorizonsBody>(); // Keep this empty tho fr
|
BodyDict["EyeOfTheUniverse"] = new List<NewHorizonsBody>(); // Keep this empty tho fr
|
||||||
SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(), Instance)
|
SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(), "", Instance)
|
||||||
{
|
{
|
||||||
Config =
|
Config =
|
||||||
{
|
{
|
||||||
@ -142,7 +143,7 @@ namespace NewHorizons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
SystemDict["EyeOfTheUniverse"] = new NewHorizonsSystem("EyeOfTheUniverse", new StarSystemConfig(), Instance)
|
SystemDict["EyeOfTheUniverse"] = new NewHorizonsSystem("EyeOfTheUniverse", new StarSystemConfig(), "", Instance)
|
||||||
{
|
{
|
||||||
Config =
|
Config =
|
||||||
{
|
{
|
||||||
@ -170,6 +171,7 @@ namespace NewHorizons
|
|||||||
|
|
||||||
OnChangeStarSystem = new StarSystemEvent();
|
OnChangeStarSystem = new StarSystemEvent();
|
||||||
OnStarSystemLoaded = new StarSystemEvent();
|
OnStarSystemLoaded = new StarSystemEvent();
|
||||||
|
OnPlanetLoaded = new StarSystemEvent();
|
||||||
|
|
||||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||||
SceneManager.sceneUnloaded += OnSceneUnloaded;
|
SceneManager.sceneUnloaded += OnSceneUnloaded;
|
||||||
@ -515,7 +517,7 @@ namespace NewHorizons
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SystemDict[name] = new NewHorizonsSystem(name, starSystemConfig, mod);
|
SystemDict[name] = new NewHorizonsSystem(name, starSystemConfig, relativePath, mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -616,7 +618,7 @@ namespace NewHorizons
|
|||||||
starSystemConfig.Migrate();
|
starSystemConfig.Migrate();
|
||||||
starSystemConfig.FixCoordinates();
|
starSystemConfig.FixCoordinates();
|
||||||
|
|
||||||
var system = new NewHorizonsSystem(config.starSystem, starSystemConfig, mod);
|
var system = new NewHorizonsSystem(config.starSystem, starSystemConfig, $"", mod);
|
||||||
|
|
||||||
SystemDict.Add(config.starSystem, system);
|
SystemDict.Add(config.starSystem, system);
|
||||||
|
|
||||||
|
|||||||
@ -7,12 +7,15 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using Logger = NewHorizons.Utility.Logger;
|
using Logger = NewHorizons.Utility.Logger;
|
||||||
|
|
||||||
namespace NewHorizons
|
namespace NewHorizons
|
||||||
{
|
{
|
||||||
|
|
||||||
public class NewHorizonsApi : INewHorizons
|
public class NewHorizonsApi : INewHorizons
|
||||||
{
|
{
|
||||||
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
||||||
@ -64,20 +67,10 @@ namespace NewHorizons
|
|||||||
return Main.BodyDict.Values.SelectMany(x => x)?.ToList()?.FirstOrDefault(x => x.Config.name == name)?.Object;
|
return Main.BodyDict.Values.SelectMany(x => x)?.ToList()?.FirstOrDefault(x => x.Config.name == name)?.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCurrentStarSystem()
|
public string GetCurrentStarSystem() => Main.Instance.CurrentStarSystem;
|
||||||
{
|
public UnityEvent<string> GetChangeStarSystemEvent() => Main.Instance.OnChangeStarSystem;
|
||||||
return Main.Instance.CurrentStarSystem;
|
public UnityEvent<string> GetStarSystemLoadedEvent() => Main.Instance.OnStarSystemLoaded;
|
||||||
}
|
public UnityEvent<string> GetBodyLoadedEvent() => Main.Instance.OnPlanetLoaded;
|
||||||
|
|
||||||
public UnityEvent<string> GetChangeStarSystemEvent()
|
|
||||||
{
|
|
||||||
return Main.Instance.OnChangeStarSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnityEvent<string> GetStarSystemLoadedEvent()
|
|
||||||
{
|
|
||||||
return Main.Instance.OnStarSystemLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SetDefaultSystem(string name)
|
public bool SetDefaultSystem(string name)
|
||||||
{
|
{
|
||||||
@ -108,6 +101,42 @@ namespace NewHorizons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static object QueryJson(Type outType, string filePath, string jsonPath)
|
||||||
|
{
|
||||||
|
if (filePath == "") return null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var jsonText = File.ReadAllText(filePath);
|
||||||
|
var jsonData = JObject.Parse(jsonText);
|
||||||
|
return jsonData.SelectToken(jsonPath)?.ToObject(outType);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (JsonException e)
|
||||||
|
{
|
||||||
|
Logger.LogError(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object QueryBody(Type outType, string bodyName, string jsonPath)
|
||||||
|
{
|
||||||
|
var planet = Main.BodyDict[Main.Instance.CurrentStarSystem].Find((b) => b.Config.name == bodyName);
|
||||||
|
return planet == null
|
||||||
|
? null
|
||||||
|
: QueryJson(outType, planet.Mod.ModHelper.Manifest.ModFolderPath + planet.RelativePath, jsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object QuerySystem(Type outType, string jsonPath)
|
||||||
|
{
|
||||||
|
var system = Main.SystemDict[Main.Instance.CurrentStarSystem];
|
||||||
|
return system == null
|
||||||
|
? null
|
||||||
|
: QueryJson(outType, system.Mod.ModHelper.Manifest.ModFolderPath + system.RelativePath, jsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles,
|
public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles,
|
||||||
float scale, bool alignWithNormal)
|
float scale, bool alignWithNormal)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -128,6 +128,13 @@
|
|||||||
"description": "Add water to this planet",
|
"description": "Add water to this planet",
|
||||||
"$ref": "#/definitions/WaterModule"
|
"$ref": "#/definitions/WaterModule"
|
||||||
},
|
},
|
||||||
|
"extras": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Extra data that may be used by extension mods",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
"$schema": {
|
"$schema": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The schema to validate with"
|
"description": "The schema to validate with"
|
||||||
|
|||||||
@ -71,6 +71,13 @@
|
|||||||
"$ref": "#/definitions/CuriosityColorInfo"
|
"$ref": "#/definitions/CuriosityColorInfo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"extras": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Extra data that may be used by extension mods",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
"$schema": {
|
"$schema": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The schema to validate with"
|
"description": "The schema to validate with"
|
||||||
|
|||||||
@ -11,15 +11,17 @@ namespace NewHorizons.Utility
|
|||||||
public class NewHorizonsSystem
|
public class NewHorizonsSystem
|
||||||
{
|
{
|
||||||
public string UniqueID;
|
public string UniqueID;
|
||||||
|
public string RelativePath;
|
||||||
public SpawnModule Spawn = null;
|
public SpawnModule Spawn = null;
|
||||||
public SpawnPoint SpawnPoint = null;
|
public SpawnPoint SpawnPoint = null;
|
||||||
public StarSystemConfig Config;
|
public StarSystemConfig Config;
|
||||||
public IModBehaviour Mod;
|
public IModBehaviour Mod;
|
||||||
|
|
||||||
public NewHorizonsSystem(string uniqueID, StarSystemConfig config, IModBehaviour mod)
|
public NewHorizonsSystem(string uniqueID, StarSystemConfig config, string relativePath, IModBehaviour mod)
|
||||||
{
|
{
|
||||||
UniqueID = uniqueID;
|
UniqueID = uniqueID;
|
||||||
Config = config;
|
Config = config;
|
||||||
|
RelativePath = relativePath;
|
||||||
Mod = mod;
|
Mod = mod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,16 +78,29 @@ public static class SchemaExporter
|
|||||||
{"description", _description}
|
{"description", _description}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_title == "Celestial Body Schema")
|
switch (_title)
|
||||||
{
|
{
|
||||||
schema.Definitions["OrbitModule"].Properties["semiMajorAxis"].Default = 5000f;
|
case "Celestial Body Schema":
|
||||||
|
schema.Definitions["OrbitModule"].Properties["semiMajorAxis"].Default = 5000f;
|
||||||
|
break;
|
||||||
|
case "Star System Schema":
|
||||||
|
schema.Definitions["NomaiCoordinates"].Properties["x"].UniqueItems = true;
|
||||||
|
schema.Definitions["NomaiCoordinates"].Properties["y"].UniqueItems = true;
|
||||||
|
schema.Definitions["NomaiCoordinates"].Properties["z"].UniqueItems = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_title == "Star System Schema")
|
if (_title is "Star System Schema" or "Celestial Body Schema")
|
||||||
{
|
{
|
||||||
schema.Definitions["NomaiCoordinates"].Properties["x"].UniqueItems = true;
|
schema.Properties["extras"] = new JsonSchemaProperty {
|
||||||
schema.Definitions["NomaiCoordinates"].Properties["y"].UniqueItems = true;
|
Type = JsonObjectType.Object,
|
||||||
schema.Definitions["NomaiCoordinates"].Properties["z"].UniqueItems = true;
|
Description = "Extra data that may be used by extension mods",
|
||||||
|
AllowAdditionalProperties = true,
|
||||||
|
AdditionalPropertiesSchema = new JsonSchema
|
||||||
|
{
|
||||||
|
Type = JsonObjectType.Object
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return schema;
|
return schema;
|
||||||
|
|||||||
@ -9,21 +9,99 @@ First create the following interface in your mod:
|
|||||||
|
|
||||||
```cs
|
```cs
|
||||||
public interface INewHorizons
|
public interface INewHorizons
|
||||||
{
|
{
|
||||||
void LoadConfigs(IModBehaviour mod);
|
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
||||||
|
void Create(Dictionary<string, object> config);
|
||||||
|
|
||||||
GameObject GetPlanet(string name);
|
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
||||||
|
void Create(Dictionary<string, object> config, IModBehaviour mod);
|
||||||
string GetCurrentStarSystem();
|
|
||||||
|
|
||||||
UnityEvent<string> GetChangeStarSystemEvent();
|
/// <summary>
|
||||||
|
/// Will load all configs in the regular folders (planets, systems, translations, etc) for this mod.
|
||||||
|
/// The NH addon config template is just a single call to this API method.
|
||||||
|
/// </summary>
|
||||||
|
void LoadConfigs(IModBehaviour mod);
|
||||||
|
|
||||||
UnityEvent<string> GetStarSystemLoadedEvent();
|
/// <summary>
|
||||||
|
/// Retrieve the root GameObject of a custom planet made by creating configs.
|
||||||
GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, float scale, bool alignWithNormal);
|
/// Will only work if the planet has been created (see GetStarSystemLoadedEvent)
|
||||||
|
/// </summary>
|
||||||
|
GameObject GetPlanet(string name);
|
||||||
|
|
||||||
string[] GetInstalledAddons();
|
/// <summary>
|
||||||
}
|
/// The name of the current star system loaded.
|
||||||
|
/// </summary>
|
||||||
|
string GetCurrentStarSystem();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An event invoked when the player begins loading the new star system, before the scene starts to load.
|
||||||
|
/// Gives the name of the star system being switched to.
|
||||||
|
/// </summary>
|
||||||
|
UnityEvent<string> GetChangeStarSystemEvent();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An event invoked when NH has finished generating all planets for a new star system.
|
||||||
|
/// Gives the name of the star system that was just loaded.
|
||||||
|
/// </summary>
|
||||||
|
UnityEvent<string> GetStarSystemLoadedEvent();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An event invoked when NH has finished a planet for a star system.
|
||||||
|
/// Gives the name of the planet that was just loaded.
|
||||||
|
/// </summary>
|
||||||
|
UnityEvent<string> GetBodyLoadedEvent();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses JSONPath to query a body
|
||||||
|
/// </summary>
|
||||||
|
object QueryBody(Type outType, string bodyName, string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses JSONPath to query a system
|
||||||
|
/// </summary>
|
||||||
|
object QuerySystem(Type outType, string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to overwrite the default system. This is where the player is respawned after dying.
|
||||||
|
/// </summary>
|
||||||
|
bool SetDefaultSystem(string name);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to instantly begin a warp to a new star system.
|
||||||
|
/// Will return false if that system does not exist (cannot be warped to).
|
||||||
|
/// </summary>
|
||||||
|
bool ChangeCurrentStarSystem(string name);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the uniqueIDs of each installed NH addon.
|
||||||
|
/// </summary>
|
||||||
|
string[] GetInstalledAddons();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to spawn a copy of a prop by specifying its path.
|
||||||
|
/// This is the same as using Props->details in a config, but also returns the spawned gameObject to you.
|
||||||
|
/// </summary>
|
||||||
|
GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles,
|
||||||
|
float scale, bool alignWithNormal);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to spawn an AudioSignal on a planet.
|
||||||
|
/// This is the same as using Props->signals in a config, but also returns the spawned AudioSignal to you.
|
||||||
|
/// This method will not set its position. You will have to do that with the returned object.
|
||||||
|
/// </summary>
|
||||||
|
AudioSignal SpawnSignal(IModBehaviour mod, GameObject root, string audio, string name, string frequency,
|
||||||
|
float sourceRadius = 1f, float detectionRadius = 20f, float identificationRadius = 10f, bool insideCloak = false,
|
||||||
|
bool onlyAudibleToScope = true, string reveals = "");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to spawn character dialogue on a planet. Also returns the RemoteDialogueTrigger if remoteTriggerRadius is specified.
|
||||||
|
/// This is the same as using Props->dialogue in a config, but also returns the spawned game objects to you.
|
||||||
|
/// This method will not set the position of the dialogue or remote trigger. You will have to do that with the returned objects.
|
||||||
|
/// </summary>
|
||||||
|
(CharacterDialogueTree, RemoteDialogueTrigger) SpawnDialogue(IModBehaviour mod, GameObject root, string xmlFile, float radius = 1f,
|
||||||
|
float range = 1f, string blockAfterPersistentCondition = null, float lookAtRadius = 1f, string pathToAnimController = null,
|
||||||
|
float remoteTriggerRadius = 0f);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In your main `ModBehaviour` class you can get the NewHorizons API like so:
|
In your main `ModBehaviour` class you can get the NewHorizons API like so:
|
||||||
@ -33,7 +111,7 @@ public class MyMod : ModBehaviour
|
|||||||
{
|
{
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
INewHorizons NewHorizonsAPI = ModHelper.Interaction.GetModApi<INewHorizons>("xen.NewHorizons");
|
INewHorizons NewHorizonsAPI = ModHelper.Interaction.TryGetModApi<INewHorizons>("xen.NewHorizons");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
74
docs/content/pages/tutorials/extending.md
Normal file
74
docs/content/pages/tutorials/extending.md
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
Title: Extending Configs
|
||||||
|
Description: A guide on extending config files with the New Horizons API
|
||||||
|
Sort_Priority: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
# Extending Configs
|
||||||
|
|
||||||
|
This guide will explain how to use the API to add new features to New Horizons.
|
||||||
|
|
||||||
|
## How Extending Works
|
||||||
|
|
||||||
|
Addon developers will add a key to the `extras` object in the root of the config
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Wetrock",
|
||||||
|
"extras": {
|
||||||
|
"myCoolExtensionData": {
|
||||||
|
"myCoolExtensionProperty": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Your mod will then use the API's `QueryBody` method to obtain the `myCoolExtensionData` object.
|
||||||
|
|
||||||
|
**It's up to the addon dev to list your mod as a dependency!**
|
||||||
|
|
||||||
|
## Extending Planets
|
||||||
|
|
||||||
|
You can extend all planets by hooking into the `OnBodyLoaded` event of the API:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var api = ModHelper.Interactions.TryGetModApi<INewHorizons>("xen.NewHorizons");
|
||||||
|
api.GetBodyLoadedEvent().AddListener((name) => {
|
||||||
|
ModHelper.Console.WriteLine($"Body: {name} Loaded!");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to get your extra module, first define the module as a class:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class MyCoolExtensionData {
|
||||||
|
int myCoolExtensionProperty;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, use the `QueryBody` method:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var api = ModHelper.Interactions.TryGetModApi<INewHorizons>("xen.NewHorizons");
|
||||||
|
api.GetBodyLoadedEvent().AddListener((name) => {
|
||||||
|
ModHelper.Console.WriteLine($"Body: {name} Loaded!");
|
||||||
|
var potentialData = api.QueryBody(typeof(MyCoolExtensionData), "$.extras.myCoolExtensionData", name);
|
||||||
|
// Makes sure the module is valid and not null
|
||||||
|
if (potentialData is MyCoolExtensionData data) {
|
||||||
|
ModHelper.Console.WriteLine($"myCoolExtensionProperty for {name} is {data.myCoolExtensionProperty}!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Extending Systems
|
||||||
|
|
||||||
|
Extending systems is the exact same as extending planets, except you use the `QuerySystem` method instead.
|
||||||
|
|
||||||
|
## Accessing Other Values
|
||||||
|
|
||||||
|
You can also use the `QueryBody` method to get values of the config outside of your extension object
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var primaryBody = api.QueryBody(typeof(string), "Wetrock", "$.Orbit.primaryBody");
|
||||||
|
ModHelper.Console.WriteLine($"Primary of {bodyName} is {primaryBody ?? "NULL"}!");
|
||||||
|
```
|
||||||
Loading…
x
Reference in New Issue
Block a user