diff --git a/.github/workflows/on-release.yml b/.github/workflows/on-release.yml index bed8492..d828f3c 100644 --- a/.github/workflows/on-release.yml +++ b/.github/workflows/on-release.yml @@ -1,7 +1,7 @@ name: Publish NuGet and upload release env: MOD_ID: 3482 - LATEST_GAME_VERSION: 0.2.0.0 + KSP2_ID: 22407 on: release: @@ -35,7 +35,7 @@ jobs: echo "artifact_name=PatchManager-$version.zip" >> $GITHUB_ENV echo "zip=$(ls -1 dist/PatchManager-*.zip | head -n 1)" >> $GITHUB_ENV echo "upload_url=$(wget -qO- https://api.github.com/repos/$GITHUB_REPOSITORY/releases | jq '.[0].upload_url' | tr -d \")" >> $GITHUB_ENV - echo "changelog=$(wget -qO- https://api.github.com/repos/$GITHUB_REPOSITORY/releases | jq '.[0].body' | tr -d \" | sed 's/@/%40/g')" >> $GITHUB_ENV + echo "changelog=$(wget -qO- https://api.github.com/repos/$GITHUB_REPOSITORY/releases | jq '.[0].body' | tr -d \" | jq -Rr @uri)" >> $GITHUB_ENV - name: Check if version exists id: check-version @@ -79,10 +79,14 @@ jobs: else echo "Login to space dock successful" fi - + + - name: Query latest game version + run: | + echo "LATEST_GAME_VERSION=$(curl 'https://spacedock.info/api/${{ env.KSP2_ID }}/versions' | jq '.[0].friendly_version' | tr -d \")" >> $GITHUB_ENV + - name: Update mod on spacedock run: | - result=$(curl -b ./cookies -F "version=${{ env.version }}" -F "changelog=${{ env.changelog }}" -F "game-version=${{ env.LATEST_GAME_VERSION}}" -F "notify-followers=yes" -F "zipball=@${{ env.zip }}" "https://spacedock.info/api/mod/${{ env.MOD_ID }}/update") + result=$(curl -b ./cookies -F "version=${{ env.version }}" -F "changelog=${{ env.changelog }}" -F "game-version=${{ env.LATEST_GAME_VERSION }}" -F "notify-followers=yes" -F "zipball=@${{ env.zip }}" "https://spacedock.info/api/mod/${{ env.MOD_ID }}/update") errored=$(echo $result | jq .error) if [ "$errored" == "true" ]; then echo "Upload to space dock errored: $(echo $result | jq .reason)" diff --git a/plugin_template/swinfo.json b/plugin_template/swinfo.json index ad9ba60..563a2e1 100644 --- a/plugin_template/swinfo.json +++ b/plugin_template/swinfo.json @@ -5,7 +5,7 @@ "name": "Patch Manager", "description": "A mod for generic patching needs similar to KSP 1's Module Manager.", "source": "https://github.com/KSP2Community/PatchManager", - "version": "0.8.0", + "version": "0.9.0", "version_check": "https://raw.githubusercontent.com/KSP2Community/PatchManager/main/plugin_template/swinfo.json", "ksp2_version": { "min": "0.2.0", diff --git a/src/PatchManager.Science/Modifiables/DiscoverablesModifiable.cs b/src/PatchManager.Science/Modifiables/DiscoverablesModifiable.cs new file mode 100644 index 0000000..dba6efd --- /dev/null +++ b/src/PatchManager.Science/Modifiables/DiscoverablesModifiable.cs @@ -0,0 +1,32 @@ +using PatchManager.SassyPatching; +using PatchManager.SassyPatching.Modifiables; +using PatchManager.Science.Selectables; + +namespace PatchManager.Science.Modifiables; +/// +/// Modifiable for . This is used to modify the discoverables object. +/// +public class DiscoverablesModifiable : JTokenModifiable +{ + private DiscoverablesSelectable _discoverablesSelectable; + + /// + /// Creates a new for the given . + /// + /// The selectable to modify. + public DiscoverablesModifiable(DiscoverablesSelectable selectable) : base(selectable.DiscoverablesObject, selectable.SetModified) + { + _discoverablesSelectable = selectable; + } + + /// + public override void Set(DataValue dataValue) + { + if (dataValue.IsDeletion) + { + _discoverablesSelectable.SetDeleted(); + return; + } + base.Set(dataValue); + } +} \ No newline at end of file diff --git a/src/PatchManager.Science/Modifiables/RegionsModifiable.cs b/src/PatchManager.Science/Modifiables/RegionsModifiable.cs new file mode 100644 index 0000000..6a45bd6 --- /dev/null +++ b/src/PatchManager.Science/Modifiables/RegionsModifiable.cs @@ -0,0 +1,33 @@ +using PatchManager.SassyPatching; +using PatchManager.SassyPatching.Modifiables; +using PatchManager.Science.Selectables; + +namespace PatchManager.Science.Modifiables; + +/// +/// Modifiable for . This is used to modify the discoverables object. +/// +public class RegionsModifiable : JTokenModifiable +{ + private RegionsSelectable _regionsSelectable; + + /// + /// Creates a new for the given . + /// + /// The selectable to modify. + public RegionsModifiable(RegionsSelectable selectable) : base(selectable.RegionsObject, selectable.SetModified) + { + _regionsSelectable = selectable; + } + + /// + public override void Set(DataValue dataValue) + { + if (dataValue.IsDeletion) + { + _regionsSelectable.SetDeleted(); + return; + } + base.Set(dataValue); + } +} \ No newline at end of file diff --git a/src/PatchManager.Science/Rulesets/DiscoverablesRuleset.cs b/src/PatchManager.Science/Rulesets/DiscoverablesRuleset.cs new file mode 100644 index 0000000..cbb5dd2 --- /dev/null +++ b/src/PatchManager.Science/Rulesets/DiscoverablesRuleset.cs @@ -0,0 +1,38 @@ +using KSP.Game.Science; +using Newtonsoft.Json.Linq; +using PatchManager.SassyPatching; +using PatchManager.SassyPatching.Attributes; +using PatchManager.SassyPatching.Interfaces; +using PatchManager.SassyPatching.NewAssets; +using PatchManager.Science.Selectables; + +namespace PatchManager.Science.Rulesets; + +/// +/// A ruleset for modifying discoverable positions in the game +/// +[PatcherRuleset("discoverables","science_region_discoverables")] +public class DiscoverablesRuleset : IPatcherRuleSet +{ + /// + public bool Matches(string label) => label == "science_region_discoverables"; + + /// + public ISelectable ConvertToSelectable(string type, string name, string jsonData) => + new DiscoverablesSelectable(JObject.Parse(jsonData)); + + /// + public INewAsset CreateNew(List dataValues) + { + var bodyName = dataValues[0].String; + var bakedDiscoverables = new CelestialBodyBakedDiscoverables + { + BodyName = bodyName, + Discoverables = [], + Version = dataValues.Count > 1 ? dataValues[1].String : "0.1" + }; + return new NewGenericAsset("science_region_discoverables", + $"{bodyName.ToLowerInvariant()}_science_regions_discoverables", + new DiscoverablesSelectable(JObject.FromObject(bakedDiscoverables))); + } +} \ No newline at end of file diff --git a/src/PatchManager.Science/Rulesets/RegionsRuleset.cs b/src/PatchManager.Science/Rulesets/RegionsRuleset.cs new file mode 100644 index 0000000..833bbed --- /dev/null +++ b/src/PatchManager.Science/Rulesets/RegionsRuleset.cs @@ -0,0 +1,38 @@ +using KSP.Game.Science; +using Newtonsoft.Json.Linq; +using PatchManager.SassyPatching; +using PatchManager.SassyPatching.Attributes; +using PatchManager.SassyPatching.Interfaces; +using PatchManager.SassyPatching.NewAssets; +using PatchManager.Science.Selectables; + +namespace PatchManager.Science.Rulesets; +/// +/// Ruleset for science regions +/// +[PatcherRuleset("regions","science_region")] +public class RegionsRuleset : IPatcherRuleSet +{ + /// + public bool Matches(string label) => label == "science_region"; + + /// + public ISelectable ConvertToSelectable(string type, string name, string jsonData) => + new RegionsSelectable(JObject.Parse(jsonData)); + + /// + public INewAsset CreateNew(List dataValues) + { + var bodyName = dataValues[0].String; + var bakedDiscoverables = new CelestialBodyScienceRegionsData + { + BodyName = bodyName, + SituationData = new CBSituationData(), + Regions = [], + Version = dataValues.Count > 1 ? dataValues[1].String : "0.1" + }; + return new NewGenericAsset("science_region", + $"{bodyName.ToLowerInvariant()}_science_regions", + new RegionsSelectable(JObject.FromObject(bakedDiscoverables))); + } +} \ No newline at end of file diff --git a/src/PatchManager.Science/Selectables/DiscoverablesSelectable.cs b/src/PatchManager.Science/Selectables/DiscoverablesSelectable.cs new file mode 100644 index 0000000..d285aca --- /dev/null +++ b/src/PatchManager.Science/Selectables/DiscoverablesSelectable.cs @@ -0,0 +1,125 @@ +using KSP.Game.Science; +using Newtonsoft.Json.Linq; +using PatchManager.SassyPatching; +using PatchManager.SassyPatching.Interfaces; +using PatchManager.SassyPatching.Selectables; +using PatchManager.Science.Modifiables; + +namespace PatchManager.Science.Selectables; + +/// +/// A selectable that represents discoverables +/// +public sealed class DiscoverablesSelectable : BaseSelectable +{ +#pragma warning disable CS0414 // Field is assigned but its value is never used + private bool _modified; +#pragma warning restore CS0414 // Field is assigned but its value is never used + private bool _deleted; + + /// + /// Marks this part selectable as having been modified any level down + /// + public void SetModified() + { + _modified = true; + } + + /// + /// Marks this part as goneso + /// + public void SetDeleted() + { + SetModified(); + _deleted = true; + } + + + /// + /// The main object that represents this discoverable object + /// + public JObject DiscoverablesObject; + private JArray _discoverablesArray; + + /// + /// Create a new discoverables selectable from a JObject + /// + /// Discoverable + public DiscoverablesSelectable(JObject discoverablesObject) + { + DiscoverablesObject = discoverablesObject; + ElementType = "discoverables"; + Name = discoverablesObject["BodyName"].Value(); + Children = []; + Classes = + ["BodyName"]; + _discoverablesArray = (JArray)discoverablesObject["Discoverables"]; + foreach (var jToken in _discoverablesArray) + { + var discoverable = (JObject)jToken; + var name = discoverable["ScienceRegionId"]!.Value(); + Classes.Add(name); + Children.Add(new JTokenSelectable(SetModified, discoverable, + disc => ((JObject)disc)["ScienceRegionId"]!.Value(), "discoverable")); + } + } + + /// + public override List Children { get; } + + /// + public override string Name { get; } + + /// + public override List Classes { get; } + + /// + public override bool MatchesClass(string @class, out DataValue classValue) + { + foreach (var jToken in _discoverablesArray) + { + var discoverable = (JObject)jToken; + var name = discoverable["ScienceRegionId"]!.Value(); + if (name != @class) continue; + classValue = DataValue.FromJToken(discoverable); + return true; + } + classValue = DataValue.Null; + return false; + } + + /// + public override bool IsSameAs(ISelectable other) => other is DiscoverablesSelectable discoverablesSelectable && + discoverablesSelectable.DiscoverablesObject == + DiscoverablesObject; + + /// + public override IModifiable OpenModification() => new DiscoverablesModifiable(this); + + /// + public override ISelectable AddElement(string elementType) + { + var position = new CelestialBodyDiscoverablePosition + { + ScienceRegionId = elementType, + Position = new Vector3d(), + Radius = 0.0 + }; + var jObject = JObject.FromObject(position); + _discoverablesArray.Add(jObject); + var selectable = new JTokenSelectable(SetModified, jObject, + disc => ((JObject)disc)["ScienceRegionId"]!.Value(), "discoverable"); + Classes.Add(elementType); + Children.Add(selectable); + return selectable; + } + + /// + public override string Serialize() => _deleted ? "" : DiscoverablesObject.ToString(); + + /// + public override DataValue GetValue() => DataValue.FromJToken(DiscoverablesObject); + + /// + public override string ElementType { get; } +} \ No newline at end of file diff --git a/src/PatchManager.Science/Selectables/ExperimentSelectable.cs b/src/PatchManager.Science/Selectables/ExperimentSelectable.cs index faecf83..7d75a35 100644 --- a/src/PatchManager.Science/Selectables/ExperimentSelectable.cs +++ b/src/PatchManager.Science/Selectables/ExperimentSelectable.cs @@ -52,8 +52,8 @@ public ExperimentSelectable(JObject scienceData) ElementType = "scienceExperiment"; ScienceObject = scienceData; DataObject = (JObject)scienceData["data"]!; - Classes = new List(); - Children = new List(); + Classes = []; + Children = []; foreach (var subToken in DataObject) { Classes.Add(subToken.Key); @@ -81,7 +81,6 @@ public override bool MatchesClass(string @class, out DataValue classValue) classValue = DataValue.FromJToken(DataObject[@class]); return true; - } /// diff --git a/src/PatchManager.Science/Selectables/RegionsSelectable.cs b/src/PatchManager.Science/Selectables/RegionsSelectable.cs new file mode 100644 index 0000000..94ca94f --- /dev/null +++ b/src/PatchManager.Science/Selectables/RegionsSelectable.cs @@ -0,0 +1,124 @@ +using KSP.Game.Science; +using Newtonsoft.Json.Linq; +using PatchManager.SassyPatching; +using PatchManager.SassyPatching.Interfaces; +using PatchManager.SassyPatching.Selectables; +using PatchManager.Science.Modifiables; + +namespace PatchManager.Science.Selectables; + +/// +/// This is the selectable for science regions +/// +public sealed class RegionsSelectable : BaseSelectable +{ + #pragma warning disable CS0414 // Field is assigned but its value is never used + private bool _modified; +#pragma warning restore CS0414 // Field is assigned but its value is never used + private bool _deleted; + + /// + /// Marks this part selectable as having been modified any level down + /// + public void SetModified() + { + _modified = true; + } + + /// + /// Marks this part as goneso + /// + public void SetDeleted() + { + SetModified(); + _deleted = true; + } + + + /// + /// The main object that represents this discoverable object + /// + public JObject RegionsObject; + private JArray _regionsArray; + + /// + /// Create a new regions selectable from a JObject + /// + /// Region + public RegionsSelectable(JObject regionsObject) + { + RegionsObject = regionsObject; + ElementType = "regions"; + Name = regionsObject["BodyName"].Value(); + Children = [new JTokenSelectable(SetModified, regionsObject["SituationData"], "SituationData","SituationData")]; + Classes = ["BodyName", "SituationData"]; + _regionsArray = (JArray)regionsObject["Regions"]; + foreach (var jToken in _regionsArray) + { + var discoverable = (JObject)jToken; + var name = discoverable["Id"]!.Value(); + Classes.Add(name); + Children.Add(new JTokenSelectable(SetModified, discoverable, + disc => ((JObject)disc)["Id"]!.Value(), "region")); + } + } + + /// + public override List Children { get; } + + /// + public override string Name { get; } + + /// + public override List Classes { get; } + + /// + public override bool MatchesClass(string @class, out DataValue classValue) + { + foreach (var jToken in _regionsArray) + { + var discoverable = (JObject)jToken; + var name = discoverable["Id"]!.Value(); + if (name != @class) continue; + classValue = DataValue.FromJToken(discoverable); + return true; + } + classValue = DataValue.Null; + return false; + } + + /// + public override bool IsSameAs(ISelectable other) => other is RegionsSelectable regionsSelectable && + regionsSelectable.RegionsObject == + RegionsObject; + + /// + public override IModifiable OpenModification() => new RegionsModifiable(this); + + /// + public override ISelectable AddElement(string elementType) + { + var position = new CelestialBodyDiscoverablePosition + { + ScienceRegionId = elementType, + Position = new Vector3d(), + Radius = 0.0 + }; + var jObject = JObject.FromObject(position); + _regionsArray.Add(jObject); + var selectable = new JTokenSelectable(SetModified, jObject, + disc => ((JObject)disc)["ScienceRegionID"]!.Value(), "discoverable"); + Classes.Add(elementType); + Children.Add(selectable); + return selectable; + } + + /// + public override string Serialize() => _deleted ? "" : RegionsObject.ToString(); + + /// + public override DataValue GetValue() => DataValue.FromJToken(RegionsObject); + + /// + public override string ElementType { get; } +} \ No newline at end of file