Skip to content

Commit 50ed7e5

Browse files
authored
Merge pull request #44 from KSP2Community/dev
Added ResourceManagerUIFix and DecoupledCraftNameFix
2 parents 33c3158 + 3619062 commit 50ed7e5

File tree

10 files changed

+255
-83
lines changed

10 files changed

+255
-83
lines changed

.github/workflows/release.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,29 @@ jobs:
1212
- name: Checkout repository
1313
uses: actions/checkout@v4
1414

15+
- name: Download NuGet
16+
id: download-nuget
17+
run: |
18+
sudo curl -o /usr/local/bin/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
19+
20+
- name: Install jq
21+
uses: dcarbone/[email protected]
22+
1523
- name: Build the solution
1624
run: |
25+
version=$(jq -r '.version' plugin_template/swinfo.json)
26+
echo "Version is $version"
1727
dotnet build "CommunityFixes.sln" -c Release
28+
echo "release_filename=CommunityFixes-$version.zip" >> $GITHUB_ENV
1829
echo "zip=$(ls -1 dist/CommunityFixes-*.zip | head -n 1)" >> $GITHUB_ENV
30+
echo "upload_url=$(wget -qO- https://api.github.com/repos/$GITHUB_REPOSITORY/releases | jq '.[0].upload_url' | tr -d \")" >> $GITHUB_ENV
1931
2032
- name: Upload zip to release
21-
uses: actions/upload-release-asset@v1.0.1
33+
uses: shogo82148/actions-upload-release-asset@v1.7.2
2234
env:
2335
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2436
with:
2537
upload_url: ${{ env.upload_url }}
2638
asset_path: ${{ env.zip }}
27-
asset_name: ${{ env.artifact_name }}
28-
asset_content_type: application/zip
39+
asset_name: ${{ env.release_filename }}
40+
asset_content_type: application/zip

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ This project aims to bring together community bug fixes for Kerbal Space Program
1515
- **Revert After Recovery Fix** by [munix](https://github.com/jan-bures) - Fixes the Revert buttons being enabled after recovering a vessel.
1616
- **Experiment Biome Pause Fix** by [dmarcuse](https://github.com/dmarcuse) - Fixes experiments that don't care about biome pausing when the biome changes.
1717
- **Stock Mission Fix** by [Cheese](https://github.com/cheese3660) - Fixes the incorrect completion conditions of the mission _Second Dibs: Gold Edition_.
18+
- **Resource Manager UI Fix** by [munix](https://github.com/jan-bures) - Fixes the Resource Manager bug where moving a tank from the right pane back to the left pane caused it to duplicate.
19+
- **Decoupled Craft Name Fix** by [munix](https://github.com/jan-bures) - Decoupled and docked/undocked vessels get names based on the original vessels instead of "Default Name" and "(Combined)".
1820

1921
## Planned fixes
2022
To see what fixes are planned to be implemented, you can visit the [Issues page](https://github.com/Bit-Studios/CommunityFixes/issues) on the project's GitHub.

plugin_template/swinfo.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"name": "Community Fixes",
66
"description": "Community project that aims to bring together bug fixes for KSP 2.",
77
"source": "https://github.com/KSP2Community/CommunityFixes",
8-
"version": "0.10.0",
8+
"version": "0.11.0",
99
"version_check": "https://raw.githubusercontent.com/KSP2Community/CommunityFixes/main/plugin_template/swinfo.json",
1010
"ksp2_version": {
1111
"min": "0.2.0",

src/CommunityFixes/CommunityFixesConfig.cs

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/CommunityFixes/CommunityFixesMod.cs

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class CommunityFixesMod : BaseSpaceWarpPlugin
1616
[PublicAPI] public const string ModVer = MyPluginInfo.PLUGIN_VERSION;
1717

1818
private static readonly Assembly Assembly = typeof(CommunityFixesMod).Assembly;
19-
internal new static CommunityFixesConfig Config;
19+
internal new static Configuration Config;
2020

2121
private readonly List<BaseFix> _fixes = new();
2222

@@ -33,11 +33,11 @@ private void Awake()
3333
return;
3434
}
3535

36-
Config = new CommunityFixesConfig(base.Config);
36+
Config = new Configuration(base.Config);
3737

3838
foreach (var type in types)
3939
{
40-
if (type.IsAbstract || !HasFixType(type))
40+
if (type.IsAbstract || !type.IsSubclassOf(typeof(BaseFix)))
4141
{
4242
continue;
4343
}
@@ -66,9 +66,7 @@ public override void OnInitialized()
6666

6767
private bool LoadFix(Type type)
6868
{
69-
var fixName = GetFixName(type);
70-
71-
if (!Config.LoadConfig(type, fixName))
69+
if (!Config.IsFixEnabled(type))
7270
{
7371
return false;
7472
}
@@ -84,40 +82,4 @@ private bool LoadFix(Type type)
8482

8583
return true;
8684
}
87-
88-
private static string GetFixName(Type type)
89-
{
90-
var attributes = Attribute.GetCustomAttributes(type);
91-
foreach (var attribute in attributes)
92-
{
93-
if (attribute is FixAttribute fix)
94-
{
95-
return fix.Name;
96-
}
97-
}
98-
99-
throw new Exception($"The attribute {typeof(FixAttribute).FullName} has to be declared on a fix class.");
100-
}
101-
102-
private static bool HasFixType(Type type)
103-
{
104-
if (type == null)
105-
{
106-
return false;
107-
}
108-
109-
// return all inherited types
110-
var currentBaseType = type.BaseType;
111-
while (currentBaseType != null)
112-
{
113-
if (currentBaseType == typeof(BaseFix))
114-
{
115-
return true;
116-
}
117-
118-
currentBaseType = currentBaseType.BaseType;
119-
}
120-
121-
return false;
122-
}
12385
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using BepInEx.Configuration;
2+
using CommunityFixes.Fix;
3+
4+
namespace CommunityFixes;
5+
6+
internal class Configuration
7+
{
8+
private const string TogglesSection = "Toggle fixes";
9+
10+
private readonly Dictionary<Type, ConfigEntry<bool>> _fixesEnabled = new();
11+
private readonly ConfigFile _file;
12+
13+
/// <summary>
14+
/// Creates a new config file object.
15+
/// </summary>
16+
/// <param name="file">The config file to use.</param>
17+
public Configuration(ConfigFile file)
18+
{
19+
_file = file;
20+
}
21+
22+
/// <summary>
23+
/// Gets the toggle value for a fix class.
24+
/// </summary>
25+
/// <param name="type">Type of the fix class.</param>
26+
/// <returns>The toggle value for the fix class.</returns>
27+
public bool IsFixEnabled(Type type)
28+
{
29+
// If the toggle value for a fix class is already defined, we return it
30+
if (_fixesEnabled.TryGetValue(type, out var isEnabled))
31+
{
32+
return isEnabled.Value;
33+
}
34+
35+
// Otherwise create a new config entry for the fix class and return its default value (true)
36+
var metadata = FixAttribute.GetForType(type);
37+
var configEntry = _file.Bind(TogglesSection, type.Name, true, metadata.Name);
38+
_fixesEnabled.Add(type, configEntry);
39+
return configEntry.Value;
40+
}
41+
42+
/// <summary>
43+
/// Binds a config entry to a hack class.
44+
/// </summary>
45+
/// <param name="hackType">The hack class type.</param>
46+
/// <param name="key">The config entry key.</param>
47+
/// <param name="defaultValue">The config entry default value.</param>
48+
/// <param name="description">The config entry description.</param>
49+
/// <typeparam name="T">The config entry type.</typeparam>
50+
/// <returns>The config entry.</returns>
51+
public ConfigEntry<T> BindFixValue<T>(Type hackType, string key, T defaultValue, string description = null)
52+
{
53+
return _file.Bind($"{hackType.Name} settings", key, defaultValue, description);
54+
}
55+
}

src/CommunityFixes/Fix/BaseFix.cs

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,54 @@
1-
using BepInEx.Logging;
1+
using BepInEx.Configuration;
22
using HarmonyLib;
33
using KSP.Game;
4+
using SpaceWarp.API.Logging;
45

56
namespace CommunityFixes.Fix;
67

8+
/// <summary>
9+
/// Base class for all fixes.
10+
/// </summary>
711
public abstract class BaseFix : KerbalMonoBehaviour
812
{
9-
public virtual void OnInitialized()
10-
{
11-
}
13+
private Configuration Config { get; }
1214

15+
/// <summary>
16+
/// The logger for the fix.
17+
/// </summary>
18+
internal ILogger Logger { get; }
19+
20+
/// <summary>
21+
/// The harmony instance for the fix.
22+
/// </summary>
1323
protected Harmony HarmonyInstance { get; }
14-
internal ManualLogSource Logger { get; }
1524

25+
/// <summary>
26+
/// Creates a new fix.
27+
/// </summary>
1628
protected BaseFix()
1729
{
18-
Logger = BepInEx.Logging.Logger.CreateLogSource($"CF/{GetType().Name}");
30+
Config = CommunityFixesMod.Config;
31+
Logger = new BepInExLogger(BepInEx.Logging.Logger.CreateLogSource($"CF/{GetType().Name}"));
1932
HarmonyInstance = new Harmony(GetType().FullName);
2033
}
34+
35+
/// <summary>
36+
/// Binds a config entry to a fix class.
37+
/// </summary>
38+
/// <param name="key">The config entry key.</param>
39+
/// <param name="defaultValue">The config entry default value.</param>
40+
/// <param name="description">The config entry description.</param>
41+
/// <typeparam name="T">The config entry type.</typeparam>
42+
/// <returns>The config entry.</returns>
43+
private protected ConfigEntry<T> BindConfigValue<T>(string key, T defaultValue, string description = null)
44+
{
45+
return Config.BindFixValue(GetType(), key, defaultValue, description);
46+
}
47+
48+
/// <summary>
49+
/// Called when the fix is initialized.
50+
/// </summary>
51+
public virtual void OnInitialized()
52+
{
53+
}
2154
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System.Text.RegularExpressions;
2+
using HarmonyLib;
3+
using KSP.Messages;
4+
using KSP.Sim.impl;
5+
6+
namespace CommunityFixes.Fix.FairingEjectSidewaysFix;
7+
8+
[Fix("Decoupled craft name fix")]
9+
public class DecoupledCraftNameFix : BaseFix
10+
{
11+
public override void OnInitialized()
12+
{
13+
Messages.Subscribe<DecoupleMessage>(msg => HandleDecoupleMessage((DecoupleMessage)msg));
14+
Messages.Subscribe<VesselUndockedMessage>(msg => HandleUndockMessage((VesselUndockedMessage)msg));
15+
16+
HarmonyInstance.PatchAll(typeof(DecoupledCraftNameFix));
17+
}
18+
19+
private void HandleDecoupleMessage(DecoupleMessage decoupleMessage)
20+
{
21+
var part1Guid = new IGGuid(Guid.Parse(decoupleMessage.PartGuid));
22+
var part2Guid = decoupleMessage.OtherPartGuid;
23+
24+
var vessel1 = Game.UniverseModel.FindPartComponent(part1Guid)?.PartOwner?.SimulationObject?.Vessel;
25+
var vessel2 = Game.UniverseModel.FindPartComponent(part2Guid)?.PartOwner?.SimulationObject?.Vessel;
26+
27+
HandleSeparationEvent(vessel1, vessel2);
28+
}
29+
30+
private void HandleUndockMessage(VesselUndockedMessage undockMessage)
31+
{
32+
VesselComponent vessel1 = undockMessage.VesselOne?.Model;
33+
VesselComponent vessel2 = undockMessage.VesselTwo?.Model;
34+
35+
HandleSeparationEvent(vessel1, vessel2);
36+
}
37+
38+
private void HandleSeparationEvent(VesselComponent vessel1, VesselComponent vessel2)
39+
{
40+
Logger.LogDebug($"Separated: {vessel1?.Name}, {vessel2?.Name}");
41+
42+
if (vessel2 is not { Name: var newName } ||
43+
!newName.StartsWith("Default Name") ||
44+
string.IsNullOrEmpty(vessel1?.Name))
45+
{
46+
return;
47+
}
48+
49+
var match = Regex.Match(vessel1!.Name, @"-(\d+)$");
50+
newName = match.Success
51+
? Regex.Replace(vessel1.Name, @"-\d+$", $"-{int.Parse(match.Groups[1].Value) + 1}")
52+
: $"{vessel1.Name}-2";
53+
54+
Logger.LogDebug($"Renaming {vessel2.Name} to {newName}");
55+
56+
vessel2.SimulationObject.Name = newName;
57+
}
58+
59+
[HarmonyPatch(typeof(SpaceSimulation), nameof(SpaceSimulation.CreateCombinedVesselSimObject))]
60+
[HarmonyPrefix]
61+
public static void CreateCombinedVesselSimObjectPrefix(
62+
// ReSharper disable once InconsistentNaming
63+
ref string __state,
64+
VesselComponent masterVessel
65+
)
66+
{
67+
__state = masterVessel.Name;
68+
}
69+
70+
[HarmonyPatch(typeof(SpaceSimulation), nameof(SpaceSimulation.CreateCombinedVesselSimObject))]
71+
[HarmonyPostfix]
72+
public static void CreateCombinedVesselSimObjectPostfix(
73+
// ReSharper disable once InconsistentNaming
74+
string __state,
75+
// ReSharper disable once InconsistentNaming
76+
ref SimulationObjectModel __result
77+
)
78+
{
79+
__result.Name = __state;
80+
}
81+
}

0 commit comments

Comments
 (0)