Co-locate the two cockpit-pod projects into a single repository:
- Console/ : TeslaConsole, the net48 WinForms operator console (decompiled
reconstruction) plus its differential + catalog test suite.
- Launcher/ : TeslaLauncher, the net6 pod-side Service + Agent rewrite.
Adds a combined TeslaSuite.sln, root README documenting the shared wire
contract (and its current duplication, the main follow-up), and a root
.gitignore. Histories were not preserved per request; this is a fresh start
from the current working state of both projects.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
417 lines
8.2 KiB
C#
417 lines
8.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Windows.Forms;
|
|
using System.Xml;
|
|
|
|
namespace TeslaConsole.RedPlanet;
|
|
|
|
internal static class RPDefaults
|
|
{
|
|
public abstract class ScenarioDefaults
|
|
{
|
|
private bool mScoreCompression;
|
|
|
|
private TimeSpan mMissionLength = new TimeSpan(0, 10, 0);
|
|
|
|
private string mMapKey;
|
|
|
|
private string mVehicleKey;
|
|
|
|
private string mTimeOfDayKey;
|
|
|
|
private string mWeatherKey;
|
|
|
|
private int mLaunchDelay = 15;
|
|
|
|
public bool ScoreCompression
|
|
{
|
|
get
|
|
{
|
|
return mScoreCompression;
|
|
}
|
|
set
|
|
{
|
|
mScoreCompression = value;
|
|
}
|
|
}
|
|
|
|
public TimeSpan MissionLength
|
|
{
|
|
get
|
|
{
|
|
return mMissionLength;
|
|
}
|
|
set
|
|
{
|
|
mMissionLength = value;
|
|
}
|
|
}
|
|
|
|
public string MapKey
|
|
{
|
|
get
|
|
{
|
|
return mMapKey;
|
|
}
|
|
set
|
|
{
|
|
mMapKey = value;
|
|
}
|
|
}
|
|
|
|
public string VehicleKey
|
|
{
|
|
get
|
|
{
|
|
return mVehicleKey;
|
|
}
|
|
set
|
|
{
|
|
mVehicleKey = value;
|
|
}
|
|
}
|
|
|
|
public string TimeOfDayKey
|
|
{
|
|
get
|
|
{
|
|
return mTimeOfDayKey;
|
|
}
|
|
set
|
|
{
|
|
mTimeOfDayKey = value;
|
|
}
|
|
}
|
|
|
|
public string WeatherKey
|
|
{
|
|
get
|
|
{
|
|
return mWeatherKey;
|
|
}
|
|
set
|
|
{
|
|
mWeatherKey = value;
|
|
}
|
|
}
|
|
|
|
public int LaunchDelay
|
|
{
|
|
get
|
|
{
|
|
return mLaunchDelay;
|
|
}
|
|
set
|
|
{
|
|
mLaunchDelay = value;
|
|
}
|
|
}
|
|
|
|
public ScenarioDefaults()
|
|
{
|
|
}
|
|
|
|
public abstract void Save(XmlNode parrentNode);
|
|
|
|
protected void SaveCommonData(XmlNode scenarioNode)
|
|
{
|
|
scenarioNode.AppendChild(scenarioNode.OwnerDocument.CreateElement("ScoreCompression")).InnerText = mScoreCompression.ToString();
|
|
scenarioNode.AppendChild(scenarioNode.OwnerDocument.CreateElement("MissionLength")).InnerText = mMissionLength.ToString();
|
|
if (!string.IsNullOrEmpty(mMapKey))
|
|
{
|
|
scenarioNode.AppendChild(scenarioNode.OwnerDocument.CreateElement("MapKey")).InnerText = mMapKey;
|
|
}
|
|
if (!string.IsNullOrEmpty(mVehicleKey))
|
|
{
|
|
scenarioNode.AppendChild(scenarioNode.OwnerDocument.CreateElement("VehicleKey")).InnerText = mVehicleKey;
|
|
}
|
|
if (!string.IsNullOrEmpty(mTimeOfDayKey))
|
|
{
|
|
scenarioNode.AppendChild(scenarioNode.OwnerDocument.CreateElement("TimeOfDayKey")).InnerText = mTimeOfDayKey;
|
|
}
|
|
if (!string.IsNullOrEmpty(mWeatherKey))
|
|
{
|
|
scenarioNode.AppendChild(scenarioNode.OwnerDocument.CreateElement("WeatherKey")).InnerText = mWeatherKey;
|
|
}
|
|
scenarioNode.AppendChild(scenarioNode.OwnerDocument.CreateElement("LaunchDelay")).InnerText = mLaunchDelay.ToString();
|
|
}
|
|
|
|
public abstract void Parse(XmlNode scenarioNode);
|
|
|
|
protected bool ParseCommonData(XmlNode node)
|
|
{
|
|
switch (node.Name)
|
|
{
|
|
case "ScoreCompression":
|
|
{
|
|
if (bool.TryParse(node.InnerText, out var result2))
|
|
{
|
|
mScoreCompression = result2;
|
|
}
|
|
return true;
|
|
}
|
|
case "MissionLength":
|
|
{
|
|
if (TimeSpan.TryParse(node.InnerText, out var result3))
|
|
{
|
|
mMissionLength = result3;
|
|
}
|
|
return true;
|
|
}
|
|
case "MapKey":
|
|
if (!string.IsNullOrEmpty(node.InnerText))
|
|
{
|
|
mMapKey = node.InnerText;
|
|
}
|
|
return true;
|
|
case "VehicleKey":
|
|
if (!string.IsNullOrEmpty(node.InnerText))
|
|
{
|
|
mVehicleKey = node.InnerText;
|
|
}
|
|
return true;
|
|
case "TimeOfDayKey":
|
|
if (!string.IsNullOrEmpty(node.InnerText))
|
|
{
|
|
mTimeOfDayKey = node.InnerText;
|
|
}
|
|
return true;
|
|
case "WeatherKey":
|
|
if (!string.IsNullOrEmpty(node.InnerText))
|
|
{
|
|
mWeatherKey = node.InnerText;
|
|
}
|
|
return true;
|
|
case "LaunchDelay":
|
|
{
|
|
if (int.TryParse(node.InnerText, out var result))
|
|
{
|
|
mLaunchDelay = result;
|
|
}
|
|
return true;
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class DeathRaceDefaults : ScenarioDefaults
|
|
{
|
|
public const string DeathRaceNode = "DeathRaceDefaults";
|
|
|
|
private string mColorKey;
|
|
|
|
private string mBadgeKey;
|
|
|
|
public string ColorKey
|
|
{
|
|
get
|
|
{
|
|
return mColorKey;
|
|
}
|
|
set
|
|
{
|
|
mColorKey = value;
|
|
}
|
|
}
|
|
|
|
public string BadgeKey
|
|
{
|
|
get
|
|
{
|
|
return mBadgeKey;
|
|
}
|
|
set
|
|
{
|
|
mBadgeKey = value;
|
|
}
|
|
}
|
|
|
|
public override void Save(XmlNode parrentNode)
|
|
{
|
|
XmlNode xmlNode = parrentNode.AppendChild(parrentNode.OwnerDocument.CreateElement("DeathRaceDefaults"));
|
|
SaveCommonData(xmlNode);
|
|
if (!string.IsNullOrEmpty(mColorKey))
|
|
{
|
|
xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement("ColorKey")).InnerText = mColorKey;
|
|
}
|
|
if (!string.IsNullOrEmpty(mBadgeKey))
|
|
{
|
|
xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement("BadgeKey")).InnerText = mBadgeKey;
|
|
}
|
|
}
|
|
|
|
public override void Parse(XmlNode scenarioNode)
|
|
{
|
|
foreach (XmlNode childNode in scenarioNode.ChildNodes)
|
|
{
|
|
if (ParseCommonData(childNode))
|
|
{
|
|
continue;
|
|
}
|
|
switch (childNode.Name)
|
|
{
|
|
case "ColorKey":
|
|
if (!string.IsNullOrEmpty(childNode.InnerText))
|
|
{
|
|
mColorKey = childNode.InnerText;
|
|
}
|
|
break;
|
|
case "BadgeKey":
|
|
if (!string.IsNullOrEmpty(childNode.InnerText))
|
|
{
|
|
mBadgeKey = childNode.InnerText;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class FootballDefaults : ScenarioDefaults
|
|
{
|
|
public const string FootballNode = "FootballDefaults";
|
|
|
|
private string mTeamKey;
|
|
|
|
private string mPositionKey;
|
|
|
|
public string TeamKey
|
|
{
|
|
get
|
|
{
|
|
return mTeamKey;
|
|
}
|
|
set
|
|
{
|
|
mTeamKey = value;
|
|
}
|
|
}
|
|
|
|
public string PositionKey
|
|
{
|
|
get
|
|
{
|
|
return mPositionKey;
|
|
}
|
|
set
|
|
{
|
|
mPositionKey = value;
|
|
}
|
|
}
|
|
|
|
public override void Save(XmlNode parrentNode)
|
|
{
|
|
XmlNode xmlNode = parrentNode.AppendChild(parrentNode.OwnerDocument.CreateElement("FootballDefaults"));
|
|
SaveCommonData(xmlNode);
|
|
if (!string.IsNullOrEmpty(mTeamKey))
|
|
{
|
|
xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement("TeamKey")).InnerText = mTeamKey;
|
|
}
|
|
if (!string.IsNullOrEmpty(mPositionKey))
|
|
{
|
|
xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement("PositionKey")).InnerText = mPositionKey;
|
|
}
|
|
}
|
|
|
|
public override void Parse(XmlNode scenarioNode)
|
|
{
|
|
foreach (XmlNode childNode in scenarioNode.ChildNodes)
|
|
{
|
|
if (ParseCommonData(childNode))
|
|
{
|
|
continue;
|
|
}
|
|
switch (childNode.Name)
|
|
{
|
|
case "TeamKey":
|
|
if (!string.IsNullOrEmpty(childNode.InnerText))
|
|
{
|
|
mTeamKey = childNode.InnerText;
|
|
}
|
|
break;
|
|
case "PositionKey":
|
|
if (!string.IsNullOrEmpty(childNode.InnerText))
|
|
{
|
|
mPositionKey = childNode.InnerText;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static readonly string sDefaultsFilePath;
|
|
|
|
private static readonly DeathRaceDefaults sDeathRace;
|
|
|
|
private static readonly FootballDefaults sFootball;
|
|
|
|
public static DeathRaceDefaults DeathRace => sDeathRace;
|
|
|
|
public static FootballDefaults Football => sFootball;
|
|
|
|
static RPDefaults()
|
|
{
|
|
sDefaultsFilePath = Path.Combine(Program.GetCommonAppDataDirectory(), "RPDefaults.rpd");
|
|
sDeathRace = new DeathRaceDefaults();
|
|
sFootball = new FootballDefaults();
|
|
if (File.Exists(sDefaultsFilePath))
|
|
{
|
|
try
|
|
{
|
|
Import(sDefaultsFilePath);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("The Red Planet defaults file appears to be corrupt. Please open the Red Planet Defaults Dialog and save to create a new defaults file.", "Error Loading Red Planet Defaults!", MessageBoxButtons.OK);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Import(string fileName)
|
|
{
|
|
XmlDocument xmlDocument = new XmlDocument();
|
|
xmlDocument.Load(fileName);
|
|
foreach (XmlNode childNode in xmlDocument.DocumentElement.ChildNodes)
|
|
{
|
|
switch (childNode.Name)
|
|
{
|
|
case "DeathRaceDefaults":
|
|
sDeathRace.Parse(childNode);
|
|
break;
|
|
case "FootballDefaults":
|
|
sFootball.Parse(childNode);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Save()
|
|
{
|
|
try
|
|
{
|
|
Export(sDefaultsFilePath);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("The Red Planet defaults file could not be saved. These defaults will only be remembered until the application is closed.", "Error Saving Red Planet Defaults!", MessageBoxButtons.OK);
|
|
}
|
|
}
|
|
|
|
public static void Export(string filePath)
|
|
{
|
|
XmlDocument xmlDocument = new XmlDocument();
|
|
xmlDocument.AppendChild(xmlDocument.CreateElement("RPDefaults"));
|
|
sDeathRace.Save(xmlDocument.DocumentElement);
|
|
sFootball.Save(xmlDocument.DocumentElement);
|
|
string directoryName = Path.GetDirectoryName(filePath);
|
|
if (!Directory.Exists(directoryName))
|
|
{
|
|
Directory.CreateDirectory(directoryName);
|
|
}
|
|
xmlDocument.Save(filePath);
|
|
}
|
|
}
|