Skip to content

Commit f207550

Browse files
committed
Community resources patches
1 parent b497c28 commit f207550

File tree

6 files changed

+191
-1
lines changed

6 files changed

+191
-1
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using System;
2+
using KSP.Game;
3+
using KSP.Messages;
4+
using KSP.Sim.impl;
5+
using KSP.Sim.ResourceSystem;
6+
using PatchManager.Shared;
7+
using UnityEngine;
8+
9+
namespace PatchManager.Resources
10+
{
11+
/// <summary>
12+
/// Handles dynamic resizing of non-stageable resources flight HUD window based on number of resources
13+
/// </summary>
14+
public class NonStageableResourcesUIController : KerbalMonoBehaviour
15+
{
16+
private const string NON_STAGEABLE_RESOURCES_UI_PANEL_PATH = "GameManager/Default Game Instance(Clone)/UI Manager(Clone)/Scaled Main Canvas/FlightHudRoot(Clone)/NonStageableResources(Clone)/KSP2UIWindow/Root/UIPanel";
17+
private VesselComponent? _activeVessel;
18+
private GameObject? _nsResourcesUI;
19+
private bool _needNsUiUpdate = false;
20+
21+
private void Start()
22+
{
23+
Game.Messages.PersistentSubscribe<VesselChangedMessage>(OnVesselChanged);
24+
}
25+
26+
private void OnDestroy()
27+
{
28+
if (IsGameShuttingDown)
29+
return;
30+
Game.Messages.Unsubscribe<VesselChangedMessage>(OnVesselChanged);
31+
}
32+
33+
private void Update()
34+
{
35+
// Get active vessel
36+
_activeVessel = Game?.ViewController?.GetActiveSimVessel();
37+
38+
if (_activeVessel is null)
39+
return;
40+
41+
if (!_needNsUiUpdate) return;
42+
43+
_needNsUiUpdate = false;
44+
45+
// Update Non Stageable Resources UI size
46+
UpdateNonStageableResourcesUI();
47+
}
48+
49+
private void OnVesselChanged(MessageCenterMessage msg)
50+
{
51+
if (msg is not VesselChangedMessage vesselChangedMessage || vesselChangedMessage == null)
52+
return;
53+
54+
_needNsUiUpdate = true;
55+
}
56+
57+
/// <summary>
58+
/// Updates the height & position of the non-stageable resources UI
59+
/// </summary>
60+
/// <param name="nsResourcesCount"></param>
61+
private void UpdateNonStageableResourcesUI()
62+
{
63+
// Get number of non-stageable resources in the active vessel
64+
int nsResourcesCount = GetNonStageableResourcesCount(_activeVessel);
65+
66+
Logging.LogInfo(
67+
$"Updating the Non-Stageable Resource UI. Found {nsResourcesCount} Resources to display.");
68+
69+
// Find the non-stageable resources window game object
70+
_nsResourcesUI =
71+
GameObject.Find(
72+
NON_STAGEABLE_RESOURCES_UI_PANEL_PATH);
73+
74+
if (_nsResourcesUI == null) return;
75+
76+
// Number of resources above the default maximum of 2 (EC & Monoprop)
77+
var extraResources = Math.Max(0, nsResourcesCount - 2);
78+
79+
// Get the UI object's RectTransform
80+
var rect = _nsResourcesUI.GetComponent<RectTransform>();
81+
82+
// Increase the UI object's vertical size
83+
rect.sizeDelta = new Vector2(0, 30 * extraResources);
84+
85+
// Shift the UI object down
86+
rect.localPosition = extraResources * 15 * Vector3.down;
87+
}
88+
89+
/// <summary>
90+
/// Returns the number of non-stageable resources present on the vessel
91+
/// </summary>
92+
private int GetNonStageableResourcesCount(VesselComponent vessel)
93+
{
94+
var count = 0;
95+
96+
var controlOwner = vessel.GetControlOwner();
97+
98+
if (controlOwner == null || controlOwner.PartOwner == null) return count;
99+
100+
var containerGroup = controlOwner.PartOwner.ContainerGroup;
101+
102+
foreach (var containedResourceData in containerGroup.GetAllResourcesContainedData())
103+
{
104+
var definitionData =
105+
Game.ResourceDefinitionDatabase.GetDefinitionData(containedResourceData.ResourceID);
106+
if (definitionData.resourceProperties.NonStageable)
107+
++count;
108+
}
109+
110+
return count;
111+
}
112+
}
113+
}

Runtime/PatchManager.Resources/NonStageableResourcesUIController.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/PatchManager.Resources/ResourcesModule.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
using JetBrains.Annotations;
1+
using System.Collections.Generic;
2+
using JetBrains.Annotations;
3+
using KSP.Game;
4+
using Newtonsoft.Json.Linq;
5+
using PatchManager.Shared;
26
using PatchManager.Shared.Modules;
7+
using Unity.VisualScripting;
8+
using UnityEngine.AddressableAssets;
9+
using UnityEngine;
310

411
namespace PatchManager.Resources
512
{
@@ -9,5 +16,35 @@ namespace PatchManager.Resources
916
[UsedImplicitly]
1017
public class ResourcesModule : BaseModule
1118
{
19+
/// <summary>
20+
/// Implement the resource units from https://github.com/KSP2Community/CommunityResources
21+
/// </summary>
22+
internal static readonly Dictionary<string, string> ResourceUnits = new();
23+
24+
25+
public override void Load()
26+
{
27+
GameManager.Instance.Assets.LoadByLabel("resource_units", RegisterUnits,
28+
delegate(IList<TextAsset> assetLocations)
29+
{
30+
if (assetLocations != null)
31+
{
32+
Addressables.Release(assetLocations);
33+
}
34+
});
35+
36+
PatchManager.Instance.AddComponent<NonStageableResourcesUIController>();
37+
}
38+
39+
40+
private static void RegisterUnits(TextAsset textAsset)
41+
{
42+
var dict = JObject.Parse(textAsset.text);
43+
foreach (var value in dict)
44+
{
45+
if (value.Value is not { Type: JTokenType.String }) continue;
46+
ResourceUnits[value.Key] = value.Value.Value<string>()!;
47+
}
48+
}
1249
}
1350
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Collections.Generic;
2+
using Newtonsoft.Json.Linq;
3+
using PatchManager.SassyPatching;
4+
using PatchManager.SassyPatching.Attributes;
5+
using PatchManager.SassyPatching.Interfaces;
6+
using PatchManager.SassyPatching.NewAssets;
7+
using PatchManager.SassyPatching.Selectables;
8+
9+
namespace PatchManager.Resources.Rulesets
10+
{
11+
/// <summary>
12+
/// Implements the resource units ruleset from https://github.com/KSP2Community/CommunityResources
13+
/// </summary>
14+
[PatcherRuleset("resource_units","resource_units")]
15+
public class ResourceUnitRuleset : IPatcherRuleSet
16+
{
17+
public bool Matches(string label) => label == "resource_units";
18+
19+
public ISelectable ConvertToSelectable(string type, string name, string jsonData) => new JTokenSelectable(() =>
20+
{
21+
}, JObject.Parse(jsonData), name, type);
22+
23+
private static int _globallyIncrementingId = 0;
24+
25+
public INewAsset CreateNew(List<DataValue> dataValues)
26+
{
27+
var id = _globallyIncrementingId++;
28+
return new NewGenericAsset("resource_units", $"resource_unit_definition_{id}", new JTokenSelectable(
29+
() => { }, new JObject(), $"resource_unit_definition_{id}", "resource_units"));
30+
}
31+
}
32+
}

Runtime/PatchManager.Resources/Rulesets/ResourceUnitRuleset.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/PatchManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ namespace PatchManager
1919
{
2020
public class PatchManager : KerbalMod
2121
{
22+
internal static PatchManager Instance;
2223
public void Awake()
2324
{
2425
// Let's register all our modules!
26+
Instance = this;
2527
ModuleManager.Register(typeof(CoreModule));
2628
ModuleManager.Register(typeof(GenericModule));
2729
ModuleManager.Register(typeof(MissionsModule));

0 commit comments

Comments
 (0)