Add console system to print debug output to the PB screen.

This commit is contained in:
Anna Rose 2025-02-08 14:48:59 -05:00
parent 4a288ed859
commit c75159f706
9 changed files with 205 additions and 16 deletions

View File

@ -55,7 +55,7 @@ namespace IngameScript
{ {
if (innerDoor.Status == DoorStatus.Closed || outerDoor.Status == DoorStatus.Open || OxygenBalanced) { return false; } if (innerDoor.Status == DoorStatus.Closed || outerDoor.Status == DoorStatus.Open || OxygenBalanced) { return false; }
_p.Echo("DEBUG: Balancing Oxygen Tank"); _console.Print($"{_name}: Balancing Oxygen Tank");
// Configure the vent to suck in Oxygen. // Configure the vent to suck in Oxygen.
airVent.Depressurize = true; airVent.Depressurize = true;
@ -64,6 +64,7 @@ namespace IngameScript
} }
private string _name; private string _name;
private PrefixedConsole _console;
private MyGridProgram _p; private MyGridProgram _p;
private float targetOxygenLevel = 0.0F; private float targetOxygenLevel = 0.0F;
@ -75,10 +76,11 @@ namespace IngameScript
private IMyAirVent airSensor; private IMyAirVent airSensor;
private const int CooldownTicks = 120; private const int CooldownTicks = 120;
public Airlock(MyGridProgram p, string name) public Airlock(MyGridProgram program, Console console, string name)
{ {
_p = p; _p = program;
_name = name; _name = name;
_console = console.CreatePrefixedConsole(_name);
// Find the appropriate blocks given the airlock name // Find the appropriate blocks given the airlock name
initDoors(); initDoors();
@ -204,17 +206,19 @@ namespace IngameScript
// Cooldown period // Cooldown period
int cooldown = 0; int cooldown = 0;
while(cooldown < CooldownTicks) { while (cooldown < CooldownTicks)
{
cooldown++; cooldown++;
yield return true; yield return true;
} }
setLights(AirlockLightState.Off); setLights(AirlockLightState.Off);
_console.Print("Cycling Complete.");
} }
private void closeDoors() private void closeDoors()
{ {
_p.Echo("DEBUG: Closing Doors"); _console.Print("Closing Doors");
// close the doors // close the doors
innerDoor.Enabled = true; innerDoor.Enabled = true;
@ -225,7 +229,7 @@ namespace IngameScript
private void pressurizeDepressurize() private void pressurizeDepressurize()
{ {
_p.Echo("DEBUG: Cycling"); _console.Print("Cycling");
// toggle the current state // toggle the current state
airVent.Depressurize = !airVent.Depressurize; airVent.Depressurize = !airVent.Depressurize;
@ -236,14 +240,14 @@ namespace IngameScript
if (airVent.Depressurize && airSensor != null) if (airVent.Depressurize && airSensor != null)
{ {
targetOxygenLevel = airSensor.GetOxygenLevel(); targetOxygenLevel = airSensor.GetOxygenLevel();
_p.Echo($"Set depressurization target to {targetOxygenLevel}"); _console.Print($"Set depressurization target to {targetOxygenLevel}");
} }
} }
// Open the appropriate door based on pressure state. // Open the appropriate door based on pressure state.
private void openDoor() private void openDoor()
{ {
_p.Echo("DEBUG: Opening Door"); _console.Print($"Opening Door");
if (airVent.Status == VentStatus.Pressurized) if (airVent.Status == VentStatus.Pressurized)
{ {
@ -298,7 +302,7 @@ namespace IngameScript
private void error(string error) private void error(string error)
{ {
_p.Echo(error); _console.Print(error);
setLights(AirlockLightState.Error); setLights(AirlockLightState.Error);
} }
} }

View File

@ -23,4 +23,6 @@
<AdditionalFiles Include="Instructions.readme" /> <AdditionalFiles Include="Instructions.readme" />
<AdditionalFiles Include="thumb.png" /> <AdditionalFiles Include="thumb.png" />
</ItemGroup> </ItemGroup>
<Import Project="..\Mixins\Console\Console.projitems" Label="shared" />
<Import Project="..\Mixins\ConfigParser\ConfigParser.projitems" Label="shared" />
</Project> </Project>

View File

@ -11,9 +11,11 @@ namespace IngameScript
private int _tickCount = 0; private int _tickCount = 0;
private MyCommandLine _cli; private MyCommandLine _cli;
private Console _console;
public Program() public Program()
{ {
_console = new Console(this);
_cli = new MyCommandLine(); _cli = new MyCommandLine();
_jobs = new List<IEnumerator<bool>>(); _jobs = new List<IEnumerator<bool>>();
_airlocks = new Dictionary<string, Airlock>(); _airlocks = new Dictionary<string, Airlock>();
@ -25,32 +27,32 @@ namespace IngameScript
if (!door.CustomName.StartsWith("Airlock")) continue; if (!door.CustomName.StartsWith("Airlock")) continue;
string airlockName = door.CustomName.Split(' ')[0]; string airlockName = door.CustomName.Split(' ')[0];
if (_airlocks.ContainsKey(airlockName)) continue; if (_airlocks.ContainsKey(airlockName)) continue;
Airlock newAirlock = new Airlock(this, airlockName); Airlock newAirlock = new Airlock(this, _console, airlockName);
if (!newAirlock.Functional) if (!newAirlock.Functional)
{ {
Echo($"{airlockName} is missing one or more required blocks."); _console.Print($"{airlockName} is missing one or more required blocks.");
continue; continue;
} }
_airlocks[airlockName] = newAirlock; _airlocks[airlockName] = newAirlock;
} }
Echo($"Found {_airlocks.Count} airlocks."); _console.Print($"Found {_airlocks.Count} airlocks.");
} }
public void Main(string argument, UpdateType updateSource) public void Main(string argument, UpdateType updateSource)
{ {
Echo($"index: {_tickCount++}"); _console.PrintLower($"Total Ticks: {_tickCount++}");
if (updateSource == UpdateType.Trigger || updateSource == UpdateType.Terminal) if (updateSource == UpdateType.Trigger || updateSource == UpdateType.Terminal)
{ {
_cli.TryParse(argument); _cli.TryParse(argument);
if (_cli.ArgumentCount == 0) { Echo("You must provide an airlock ID."); } if (_cli.ArgumentCount == 0) { _console.Print("You must provide an airlock ID."); }
else else
{ {
string airlockName = $"Airlock{_cli.Argument(0)}"; string airlockName = $"Airlock{_cli.Argument(0)}";
if (!_airlocks.ContainsKey(airlockName)) if (!_airlocks.ContainsKey(airlockName))
{ {
Echo($"Invalid airlock ID {_cli.Argument(0)}"); _console.Print($"Invalid airlock ID {_cli.Argument(0)}");
} }
else else
{ {
@ -68,7 +70,7 @@ namespace IngameScript
job.Dispose(); job.Dispose();
_jobs.Remove(job); _jobs.Remove(job);
i--; i--;
Echo("Airlock Cycling Complete."); _console.Print("Job Removed From Queue.");
} }
} }

View File

@ -0,0 +1,44 @@
using Sandbox.ModAPI.Ingame;
using System;
using System.Collections.Generic;
namespace IngameScript
{
public class ConfigParser
{
private Dictionary<string, string> _config;
private IMyTerminalBlock _input;
public ConfigParser(IMyTerminalBlock input)
{
_input = input;
_config = new Dictionary<string, string>();
Parse();
}
// Get a config value, or a default value.
// that also does type inference, but the type of `defaultValue` must contain a `Parse()` method.
public T GetValue<T>(string key, T defaultValue)
{
if (!_config.ContainsKey(key))
{
return defaultValue;
}
return (T)Convert.ChangeType(_config[key], typeof(T));
}
// Only call this method manually if you are monitoring CustomData for changes.
public void Parse()
{
_config.Clear();
string[] lines = _input.CustomData.Split('\n');
foreach (string line in lines)
{
string[] tokens = line.Split('=');
if (tokens.Length != 2) continue;
_config[tokens[0]] = tokens[1];
}
}
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>8a3cdcc5-4b55-4d87-a415-698a0e1ff06f</SharedGUID>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)/**/*.cs" Visible=" '$(ShowCommonFiles)' == 'true' " />
</ItemGroup>
</Project>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>8a3cdcc5-4b55-4d87-a415-698a0e1ff06f</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props"/>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props"/>
<PropertyGroup/>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<Import Project="ConfigParser.projitems" Label="Shared"/>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets"/>
</Project>

77
Mixins/Console/Console.cs Normal file
View File

@ -0,0 +1,77 @@
// A utility class representing output to the console.
// Provides a Print() function that will both call MyGridProgram.Echo()
// and also output to the Programmable Block's LCD.
using Sandbox.ModAPI.Ingame;
using System.Collections.Generic;
using System.Text;
namespace IngameScript
{
public class Console
{
private MyGridProgram _program;
private int _maxLines;
private List<string> _buffer;
private const int DefaultMaxLines = 10;
public Console(MyGridProgram program)
{
_program = program;
_buffer = new List<string>();
// Check the PB's custom data for a maxlines directive.
ConfigParser config = new ConfigParser(_program.Me);
_maxLines = config.GetValue("ConsoleMaxLines", DefaultMaxLines);
}
public PrefixedConsole CreatePrefixedConsole(string prefix)
{
return new PrefixedConsole(this, prefix);
}
public void Print(string text)
{
_program.Echo(text);
_program.Me.GetSurface(0).WriteText(writeToBuffer(text));
}
// Text written with this method goes to the lower screen / keyboard,
// with no buffering.
public void PrintLower(string text)
{
_program.Me.GetSurface(1).WriteText(text);
}
// Adds the text to the buffer, trims the top if necessary, and builds a printable
// string.
private string writeToBuffer(string text)
{
_buffer.Add(text);
if (_buffer.Count > _maxLines) _buffer.RemoveAt(0);
StringBuilder result = new StringBuilder("", 800);
foreach (string line in _buffer) result.AppendLine(line);
return result.ToString();
}
}
// This class is necessary because we need to keep a *single* buffer
// to write to. So we can ask the primary Console for a prefixer.
public class PrefixedConsole
{
private Console _console;
private string _prefix;
public PrefixedConsole(Console console, string prefix)
{
_console = console;
_prefix = prefix + ": ";
}
public void Print(string text)
{
_console.Print(_prefix + text);
}
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>8a3cdcc5-4b55-4d87-a415-698a0e1ff06f</SharedGUID>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)/**/*.cs" Visible=" '$(ShowCommonFiles)' == 'true' " />
</ItemGroup>
</Project>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>8a3cdcc5-4b55-4d87-a415-698a0e1ff06f</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props"/>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props"/>
<PropertyGroup/>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<Import Project="Console.projitems" Label="Shared"/>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets"/>
</Project>