(Add category and sorting) |
(Add page contents) |
||
Line 1: | Line 1: | ||
[[Category:Custom Modules]] | [[Category:Custom Modules]] | ||
{{DEFAULTSORT:3_Miscellaneous_and_tips_for_custom_modules}} | {{DEFAULTSORT:3_Miscellaneous_and_tips_for_custom_modules}} | ||
== Localization == | |||
For module properties that support a LocalizationField parameter it's best to use a localization file. | |||
[LocalizedField("Path/To/Your/Localization/String")] | |||
public ModuleProperty<bool> SomeToggleProperty = new(false); | |||
Localizations will be automatically loaded by SpaceWarp if placed in <code>../BepInEx/plugins/YourModFolder/localizations/</code> inside a <code>.csv</code> file. | |||
Structure your <code>.csv</code> file like so: | |||
Key,Type,Desc,English,German,French,Italian,Spanish,Japanese,Korean,Polish,Russian,Chinese (Simplified),Portuguese (Brazil),Chinese (Traditional) | |||
Path/To/Your/Localization/String,Text,,English translation goes here,German translation goes here | |||
If you don't provide a translation string for a language, it will default to English for that particular string. | |||
If you need to place a comma (",") in your translation string, wrap it inside double quotations marks, like so: | |||
Path/To/Your/Localization/String,Text,,"I can write commas here, no problem, as much commas I'd like." | |||
== PAM module headers and sorting == | |||
If you want your module to have a header before its properties or if it needs to be sorted relative to other modules in the same part, define this in your Patch Manager <code>.patch</code> file: | |||
:parts { | |||
+Module_OrbitalSurvey { | |||
+Data_OrbitalSurvey { | |||
.. | |||
} | |||
} | |||
PAMModuleVisualsOverride +: [ | |||
{ | |||
PartComponentModuleName: PartComponentModule_MyCustomModule, | |||
ModuleDisplayName: "Path/To/Your/Localization/String/Where/Your/Module/Name/Is/Defined", | |||
ShowHeader: true, | |||
ShowFooter: true // setting ShowFooter doesn't appear to have any effect? Update this guide if you have new info | |||
} | |||
]; | |||
PAMModuleSortOverride +: [ | |||
{ | |||
PartComponentModuleName: PartComponentModule_MyCustomModule, | |||
sortIndex: 40 // try setting a different value if you don't get what you need | |||
} | |||
]; | |||
} | |||
== Register your module for background resource processing == | |||
Resource consumption while the vessel is unloaded is disabled by default, as an effort to enhance performance of the stock game. If your module needs to consume resources while it's not loaded (for example Life support consumption), Space Warp supports registration of your module to consume resources. | |||
Do this somewhere where you initialize stuff for your mod (example here: in your plugin class): | |||
public class YourModPlugin : BaseSpaceWarpPlugin | |||
{ | |||
public override void OnInitialized() | |||
{ | |||
SpaceWarp.API.Parts.PartComponentModuleOverride | |||
.RegisterModuleForBackgroundResourceProcessing<PartComponentModule_YourCustomModule>(); | |||
} | |||
} | |||
== Tip: add reference to your Part Component module in your Data module class == | |||
If you need a reference to your Part Component class from inside your Data class, you can do it like so: | |||
public class Data_MyCustomModule : ModuleData | |||
{ | |||
// be sure to put the JsonIgnore attribute, as otherwise there will be a circular reference and bad things will happen | |||
[JsonIgnore] | |||
public PartComponentModule_MyCustomModule PartComponentModule; | |||
} | |||
public class PartComponentModule_MyCustomModule : PartComponentModule | |||
{ | |||
private Data_MyCustomModule _dataMyCustomModule; | |||
public override void OnStart(double universalTime) | |||
{ | |||
if (!DataModules.TryGetByType<Data_MyCustomModule>(out _dataMyCustomModule)) | |||
{ | |||
return; | |||
} | |||
_dataMyCustomModule.PartComponentModule = this; | |||
} | |||
} | |||
== Tip: fetch VesselComponent, PartOwner, Body or other values of your vessel or part == | |||
public class PartComponentModule_MyCustomModule : PartComponentModule | |||
{ | |||
public override void OnStart(double universalTime) | |||
{ | |||
var partOwner = base.Part.PartOwner; | |||
var vessel = partOwner.SimulationObject.Vessel; | |||
var body = vessel.mainBody.Name; | |||
var altitude = vessel.AltitudeFromRadius; | |||
} | |||
} | |||
== Tip: fetch other modules attached to the part == | |||
Sometimes you might need data from other modules. | |||
public class PartComponentModule_MyCustomModule : PartComponentModule | |||
{ | |||
private Data_Deployable _dataDeployable; | |||
private PartComponentModule_ScienceExperiment _moduleScienceExperiment; | |||
public override void OnStart(double universalTime) | |||
{ | |||
// get the ScienceExperiment module | |||
Part.TryGetModule(typeof(PartComponentModule_ScienceExperiment), out var m); | |||
_moduleScienceExperiment = m as PartComponentModule_ScienceExperiment; | |||
// try to get Data_Deployable if the part has a Deployable module | |||
Part.TryGetModule(typeof(PartComponentModule_Deployable), out var m2); | |||
if (m2 != null) | |||
{ | |||
var moduleDeployable = m2 as PartComponentModule_Deployable; | |||
foreach (var dataDeployable in moduleDeployable.DataModules?.ValuesList) | |||
{ | |||
if (dataDeployable is Data_Deployable) | |||
{ | |||
_dataDeployable = dataDeployable as Data_Deployable; | |||
// register for the deployment event | |||
_dataDeployable.toggleExtend.OnChangedValue += (_) => YourMethodThatWillReactToDeploying(); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
} |
Latest revision as of 18:48, 11 January 2024
Localization
For module properties that support a LocalizationField parameter it's best to use a localization file.
[LocalizedField("Path/To/Your/Localization/String")] public ModuleProperty<bool> SomeToggleProperty = new(false);
Localizations will be automatically loaded by SpaceWarp if placed in ../BepInEx/plugins/YourModFolder/localizations/
inside a .csv
file.
Structure your .csv
file like so:
Key,Type,Desc,English,German,French,Italian,Spanish,Japanese,Korean,Polish,Russian,Chinese (Simplified),Portuguese (Brazil),Chinese (Traditional) Path/To/Your/Localization/String,Text,,English translation goes here,German translation goes here
If you don't provide a translation string for a language, it will default to English for that particular string.
If you need to place a comma (",") in your translation string, wrap it inside double quotations marks, like so:
Path/To/Your/Localization/String,Text,,"I can write commas here, no problem, as much commas I'd like."
PAM module headers and sorting
If you want your module to have a header before its properties or if it needs to be sorted relative to other modules in the same part, define this in your Patch Manager .patch
file:
:parts { +Module_OrbitalSurvey { +Data_OrbitalSurvey { .. } } PAMModuleVisualsOverride +: [ { PartComponentModuleName: PartComponentModule_MyCustomModule, ModuleDisplayName: "Path/To/Your/Localization/String/Where/Your/Module/Name/Is/Defined", ShowHeader: true, ShowFooter: true // setting ShowFooter doesn't appear to have any effect? Update this guide if you have new info } ]; PAMModuleSortOverride +: [ { PartComponentModuleName: PartComponentModule_MyCustomModule, sortIndex: 40 // try setting a different value if you don't get what you need } ]; }
Register your module for background resource processing
Resource consumption while the vessel is unloaded is disabled by default, as an effort to enhance performance of the stock game. If your module needs to consume resources while it's not loaded (for example Life support consumption), Space Warp supports registration of your module to consume resources.
Do this somewhere where you initialize stuff for your mod (example here: in your plugin class):
public class YourModPlugin : BaseSpaceWarpPlugin { public override void OnInitialized() { SpaceWarp.API.Parts.PartComponentModuleOverride .RegisterModuleForBackgroundResourceProcessing<PartComponentModule_YourCustomModule>(); } }
Tip: add reference to your Part Component module in your Data module class
If you need a reference to your Part Component class from inside your Data class, you can do it like so:
public class Data_MyCustomModule : ModuleData { // be sure to put the JsonIgnore attribute, as otherwise there will be a circular reference and bad things will happen [JsonIgnore] public PartComponentModule_MyCustomModule PartComponentModule; } public class PartComponentModule_MyCustomModule : PartComponentModule { private Data_MyCustomModule _dataMyCustomModule; public override void OnStart(double universalTime) { if (!DataModules.TryGetByType<Data_MyCustomModule>(out _dataMyCustomModule)) { return; } _dataMyCustomModule.PartComponentModule = this; } }
Tip: fetch VesselComponent, PartOwner, Body or other values of your vessel or part
public class PartComponentModule_MyCustomModule : PartComponentModule { public override void OnStart(double universalTime) { var partOwner = base.Part.PartOwner; var vessel = partOwner.SimulationObject.Vessel; var body = vessel.mainBody.Name; var altitude = vessel.AltitudeFromRadius; } }
Tip: fetch other modules attached to the part
Sometimes you might need data from other modules.
public class PartComponentModule_MyCustomModule : PartComponentModule { private Data_Deployable _dataDeployable; private PartComponentModule_ScienceExperiment _moduleScienceExperiment; public override void OnStart(double universalTime) { // get the ScienceExperiment module Part.TryGetModule(typeof(PartComponentModule_ScienceExperiment), out var m); _moduleScienceExperiment = m as PartComponentModule_ScienceExperiment; // try to get Data_Deployable if the part has a Deployable module Part.TryGetModule(typeof(PartComponentModule_Deployable), out var m2); if (m2 != null) { var moduleDeployable = m2 as PartComponentModule_Deployable; foreach (var dataDeployable in moduleDeployable.DataModules?.ValuesList) { if (dataDeployable is Data_Deployable) { _dataDeployable = dataDeployable as Data_Deployable; // register for the deployment event _dataDeployable.toggleExtend.OnChangedValue += (_) => YourMethodThatWillReactToDeploying(); break; } } } } }