#12 add configurable column for fuel status tracking in engine roster

This commit is contained in:
2024-06-20 17:41:50 -05:00
parent 8ae319fbee
commit d0e2c3f99e
8 changed files with 257 additions and 70 deletions

View File

@@ -12,7 +12,7 @@
<PropertyGroup Condition="'$(AssemblyVersion)' == '' OR '$(MajorVersion)' != '' OR '$(MinorVersion)' != ''">
<MajorVersion Condition="'$(MajorVersion)' == ''">0</MajorVersion>
<MinorVersion Condition="'$(MinorVersion)' == ''">1</MinorVersion>
<PatchVersion Condition="'$(PatchVersion)' == ''">4</PatchVersion>
<PatchVersion Condition="'$(PatchVersion)' == ''">5</PatchVersion>
<AssemblyVersion>$(MajorVersion).$(MinorVersion).$(PatchVersion)</AssemblyVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<ProductVersion>$(AssemblyVersion)</ProductVersion>

View File

@@ -0,0 +1,9 @@
namespace TweaksAndThings.Enums;
public enum EngineRosterFuelDisplayColumn
{
None,
Engine,
Crew,
Status
}

View File

@@ -0,0 +1,122 @@
using HarmonyLib;
using Model;
using Model.Definition;
using Model.Definition.Data;
using Model.OpsNew;
using Model.Physics;
using Railloader;
using RMROC451.TweaksAndThings.Settings;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using TweaksAndThings.Enums;
using UI;
using UI.Builder;
using UI.EngineRoster;
using UI.Tooltips;
using UnityEngine;
using static Model.Car;
namespace TweaksAndThings.Patches;
[HarmonyPatch(typeof(EngineRosterRow))]
[HarmonyPatch(nameof(EngineRosterRow.Refresh))]
[HarmonyPatchCategory("RMROC451TweaksAndThings")]
public class EngineRosterRow_Refresh_Patch
{
public static void Postfix(EngineRosterRow __instance)
{
TweaksAndThings? tweaksAndThings = SingletonPluginBase<TweaksAndThings>.Shared;
RosterFuelColumnSettings? rosterFuelColumnSettings = tweaksAndThings?.settings?.EngineRosterFuelColumnSettings;
if (tweaksAndThings == null ||
rosterFuelColumnSettings == null ||
!tweaksAndThings.IsEnabled ||
rosterFuelColumnSettings.EngineRosterFuelStatusColumn == EngineRosterFuelDisplayColumn.None || (!GameInput.IsAltDown && !rosterFuelColumnSettings.EngineRosterShowsFuelStatusAlways))
{
return;
}
try
{
string fuelInfoText = string.Empty;
string fuelInfoTooltip = string.Empty;
Car engineOrTender = __instance._engine;
List<LoadSlot> loadSlots = __instance._engine.Definition.LoadSlots;
if (!loadSlots.Any())
{
engineOrTender = DetermineFuelCar(__instance._engine);
loadSlots = engineOrTender != null ? engineOrTender.Definition.LoadSlots : Enumerable.Empty<LoadSlot>().ToList();
}
var offender = loadSlots.OrderBy(ls => (engineOrTender.GetLoadInfo(ls.RequiredLoadIdentifier, out int slotIndex)?.Quantity ?? 0) / loadSlots[slotIndex].MaximumCapacity).FirstOrDefault().RequiredLoadIdentifier;
for (int i = 0; i < loadSlots.Count; i++)
{
CarLoadInfo? loadInfo = engineOrTender.GetLoadInfo(i);
if (loadInfo.HasValue)
{
CarLoadInfo valueOrDefault = loadInfo.GetValueOrDefault();
var fuelLevel = FuelLevel(valueOrDefault.Quantity, loadSlots[i].MaximumCapacity);
fuelInfoText += loadSlots[i].RequiredLoadIdentifier == offender ? fuelLevel + " " : string.Empty;
//fuelInfoText += TextSprites.PiePercent(valueOrDefault.Quantity, loadSlots[i].MaximumCapacity) + " ";
fuelInfoTooltip += $"{TextSprites.PiePercent(valueOrDefault.Quantity, loadSlots[i].MaximumCapacity)} {valueOrDefault.LoadString(CarPrototypeLibrary.instance.LoadForId(valueOrDefault.LoadId))}\n";
}
}
switch (rosterFuelColumnSettings.EngineRosterFuelStatusColumn)
{
case EngineRosterFuelDisplayColumn.Engine:
SetLabelAndTooltip(ref __instance.nameLabel, ref __instance.nameTooltip, fuelInfoText, fuelInfoTooltip);
break;
case EngineRosterFuelDisplayColumn.Crew:
SetLabelAndTooltip(ref __instance.crewLabel, ref __instance.crewTooltip, fuelInfoText, fuelInfoTooltip);
break;
case EngineRosterFuelDisplayColumn.Status:
SetLabelAndTooltip(ref __instance.infoLabel, ref __instance.infoTooltip, fuelInfoText, fuelInfoTooltip);
break;
default:
break;
}
} catch (Exception ex)
{
rosterFuelColumnSettings.EngineRosterFuelStatusColumn = EngineRosterFuelDisplayColumn.None;
Log.Error(ex, "Error Detecting fuel status for engine roster");
}
}
private static void SetLabelAndTooltip(ref TMP_Text label, ref UITooltipProvider tooltip, string fuelInfoText, string fuelInfoTooltip)
{
label.text = $" {fuelInfoText} {label.text}";
tooltip.TooltipInfo = new TooltipInfo(tooltip.tooltipTitle, fuelInfoTooltip);
}
public static string FuelLevel(float quantity, float capacity)
{
float num = capacity <= 0f ? 0 : Mathf.Clamp(quantity / capacity * 100, 0, 100);
return $"{Mathf.FloorToInt(num):D2}%";
}
public static Car DetermineFuelCar(BaseLocomotive engine)
{
Car car;
if (engine is SteamLocomotive steamLocomotive && new Func<Car>(steamLocomotive.FuelCar) != null)
{
car = steamLocomotive.FuelCar();
}
else
{
if (!(engine is DieselLocomotive))
{
throw new InvalidOperationException($"Unable to detect locomotive fuel source for {engine}");
}
car = engine;
}
return car;
}
}

View File

@@ -4,6 +4,7 @@ using HarmonyLib;
using Helpers;
using Newtonsoft.Json;
using Railloader;
using RMROC451.TweaksAndThings.Settings;
using Serilog;
using System;
using System.Collections.Generic;
@@ -35,9 +36,7 @@ public class ExpandedConsole_Add_Patch
TweaksAndThings tweaksAndThings = SingletonPluginBase<TweaksAndThings>.Shared;
StateManager shared = StateManager.Shared;
GameStorage gameStorage = shared.Storage;
WebhookSettings settings = tweaksAndThings.settings.WebhookSettingsList.FirstOrDefault(ws => ws.RailroadMark == gameStorage.RailroadMark);
Log.Information(entry.Text);
WebhookSettings settings = tweaksAndThings?.settings?.WebhookSettingsList?.FirstOrDefault(ws => ws.RailroadMark == gameStorage.RailroadMark);
if (
settings != null &&
@@ -50,7 +49,6 @@ public class ExpandedConsole_Add_Patch
var carId = t.IsMatch(entry.Text) ? Regex.Match(entry.Text, "car:(.*?)\"").Groups[1].Captures[0].ToString() : string.Empty;
Model.Car? car = TrainController.Shared.CarForString(carId);
Log.Information($"|{carId}| {car?.IsLocomotive}");
bool engineInMessage = car?.IsLocomotive ?? false;
var image = engineInMessage ?
new
@@ -91,7 +89,6 @@ public class ExpandedConsole_Add_Patch
}
};
string EndPoint = settings.WebhookUrl;
Log.Information(JsonConvert.SerializeObject(SuccessWebHook));
var content = new StringContent(JsonConvert.SerializeObject(SuccessWebHook), Encoding.UTF8, "application/json");

View File

@@ -11,6 +11,7 @@
<GameAssembly Include="0Harmony" />
<GameAssembly Include="KeyValue.Runtime" />
<GameAssembly Include="Definition" />
<GameAssembly Include="Ops" />
<GameAssembly Include="UnityEngine.CoreModule" />
<GameAssembly Include="UnityEngine.UI" />

View File

@@ -1,58 +0,0 @@
using Newtonsoft.Json;
using System.IO;
using System.Runtime;
using System;
using Serilog;
using System.Collections.Generic;
using System.Linq;
namespace TweaksAndThings;
public class Settings
{
public Settings()
{
WebhookSettingsList = new[] { new WebhookSettings() }.ToList();
}
public Settings(
List<WebhookSettings> webhookSettingsList,
bool handBrakeAndAirTagModifiers
)
{
this.WebhookSettingsList = webhookSettingsList;
this.HandBrakeAndAirTagModifiers = handBrakeAndAirTagModifiers;
}
public List<WebhookSettings> WebhookSettingsList;
public bool HandBrakeAndAirTagModifiers;
internal void AddAnotherRow()
{
if (!string.IsNullOrEmpty(WebhookSettingsList.Last().WebhookUrl))
{
WebhookSettingsList.Add(new());
Log.Information($"Adding another {nameof(WebhookSettings)} list entry, last one was filled in");
}
}
}
public class WebhookSettings
{
public WebhookSettings() { }
public WebhookSettings(
bool webhookEnabled,
string railroadMark,
string webhookUrl
)
{
this.WebhookEnabled = webhookEnabled;
this.RailroadMark = railroadMark;
this.WebhookUrl = webhookUrl;
}
public bool WebhookEnabled = false;
public string RailroadMark = string.Empty;
public string WebhookUrl = string.Empty;
}

View File

@@ -0,0 +1,76 @@
using Serilog;
using System.Collections.Generic;
using System.Linq;
using TweaksAndThings.Enums;
namespace RMROC451.TweaksAndThings.Settings;
public class Settings
{
public Settings()
{
WebhookSettingsList = new[] { new WebhookSettings() }.ToList();
EngineRosterFuelColumnSettings = new();
}
public Settings(
List<WebhookSettings> webhookSettingsList,
bool handBrakeAndAirTagModifiers,
RosterFuelColumnSettings engineRosterFuelColumnSettings
)
{
WebhookSettingsList = webhookSettingsList;
HandBrakeAndAirTagModifiers = handBrakeAndAirTagModifiers;
EngineRosterFuelColumnSettings = engineRosterFuelColumnSettings;
}
public List<WebhookSettings>? WebhookSettingsList;
public bool HandBrakeAndAirTagModifiers;
public RosterFuelColumnSettings? EngineRosterFuelColumnSettings;
internal void AddAnotherRow()
{
WebhookSettingsList = !WebhookSettingsList?.Any() ?? false ? new[] { new WebhookSettings() }.ToList() : new List<WebhookSettings>();
if (!string.IsNullOrEmpty(WebhookSettingsList.OrderByDescending(wsl => wsl.WebhookUrl).Last().WebhookUrl))
{
WebhookSettingsList.Add(new());
Log.Information($"Adding another {nameof(WebhookSettings)} list entry, last one was filled in");
}
}
}
public class WebhookSettings
{
public WebhookSettings() { }
public WebhookSettings(
bool webhookEnabled,
string railroadMark,
string webhookUrl
)
{
WebhookEnabled = webhookEnabled;
RailroadMark = railroadMark;
WebhookUrl = webhookUrl;
}
public bool WebhookEnabled = false;
public string RailroadMark = string.Empty;
public string WebhookUrl = string.Empty;
}
public class RosterFuelColumnSettings
{
public RosterFuelColumnSettings() { }
public RosterFuelColumnSettings(
bool engineRosterShowsFuelStatusAlways,
EngineRosterFuelDisplayColumn engineRosterFuelStatusColumn
)
{
this.EngineRosterShowsFuelStatusAlways = engineRosterShowsFuelStatusAlways;
this.EngineRosterFuelStatusColumn = engineRosterFuelStatusColumn;
}
public bool EngineRosterShowsFuelStatusAlways;
public EngineRosterFuelDisplayColumn EngineRosterFuelStatusColumn;
}

View File

@@ -2,10 +2,14 @@
using Game.State;
using HarmonyLib;
using Railloader;
using RMROC451.TweaksAndThings.Settings;
using Serilog;
using System;
using System.Linq;
using System.Net.Http;
using TweaksAndThings.Enums;
using UI.Builder;
using static Model.Car;
namespace TweaksAndThings
{
@@ -43,12 +47,6 @@ namespace TweaksAndThings
//moddingContext.RegisterConsoleCommand(new EchoCommand());
settings = moddingContext.LoadSettingsData<Settings>(self.Id);
if (!settings?.WebhookSettingsList?.Any() ?? true)
{
if (settings == null) settings = new();
settings.WebhookSettingsList = new[] { new WebhookSettings() }.ToList();
this.moddingContext.SaveSettingsData(this.modDefinition.Id, settings ?? new());
}
}
public override void OnEnable()
@@ -73,11 +71,53 @@ namespace TweaksAndThings
public void ModTabDidOpen(UIPanelBuilder builder)
{
logger.Information("Daytime!");
if (!settings?.WebhookSettingsList?.Any() ?? true)
{
if (settings == null) settings = new();
settings.WebhookSettingsList = new[] { new WebhookSettings() }.ToList();
settings.EngineRosterFuelColumnSettings = new();
}
//WebhookUISection(ref builder);
//builder.AddExpandingVerticalSpacer();
WebhooksListUISection(ref builder);
builder.AddExpandingVerticalSpacer();
HandbrakesAndAnglecocksUISection(ref builder);
builder.AddExpandingVerticalSpacer();
EnginRosterShowsFuelStatusUISection(ref builder);
}
private void EnginRosterShowsFuelStatusUISection(ref UIPanelBuilder builder)
{
var columns = Enum.GetValues(typeof(EngineRosterFuelDisplayColumn)).Cast<EngineRosterFuelDisplayColumn>().Select(i => i.ToString()).ToList();
builder.AddSection("Fuel Display in Engine Roster", delegate (UIPanelBuilder builder)
{
builder.AddField(
"Enable",
builder.AddDropdown(columns, (int)(settings?.EngineRosterFuelColumnSettings?.EngineRosterFuelStatusColumn ?? EngineRosterFuelDisplayColumn.None),
delegate (int column)
{
if (settings == null) settings = new() { WebhookSettingsList = new[] { new WebhookSettings() }.ToList(), EngineRosterFuelColumnSettings = new() };
settings.EngineRosterFuelColumnSettings.EngineRosterFuelStatusColumn = (EngineRosterFuelDisplayColumn)column;
builder.Rebuild();
}
)
).Tooltip("Enable Fuel Display in Engine Roster", $"Will add remaing fuel indication to Engine Roster (with details in roster row tooltip), Examples : {string.Join(" ", Enumerable.Range(0,4).Select(i => TextSprites.PiePercent(i, 4)))}");
builder.AddField(
"Always Visible?",
builder.AddToggle(
() => settings?.EngineRosterFuelColumnSettings?.EngineRosterShowsFuelStatusAlways ?? false,
delegate (bool enabled)
{
if (settings == null) settings = new() { WebhookSettingsList = new[] { new WebhookSettings() }.ToList(), EngineRosterFuelColumnSettings = new() };
settings.EngineRosterFuelColumnSettings.EngineRosterShowsFuelStatusAlways = enabled;
builder.Rebuild();
}
)
).Tooltip("Fuel Display in Engine Roster Always Visible", $"Always displayed, if you want it hidden and only shown when you care to see, uncheck this, and then you can press ALT for it to populate on the next UI refresh cycle.");
});
}
private void HandbrakesAndAnglecocksUISection(ref UIPanelBuilder builder)