space_engineers/Mixins/Console/Console.cs

163 lines
5.9 KiB
C#

// 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;
using System.Collections.Generic;
using System.Text;
using VRage.Game.GUI.TextPanel;
using VRage.Game.ModAPI.Ingame.Utilities;
namespace IngameScript
{
// To use this library, your Program class must implement this interface.
//
// A Program that supports consoles by initializing a MyIni instance
// and providing a public console for member objects to refer back to.
//
// (It is probably an anti-pattern that this lives outside of the Program class,
// but we can't find a cleaner way to implement this.)
public interface IConsoleProgram
{
// Properties that should be defined by the implementer.
MyIni Ini { get; }
Program.IConsole Console { get; }
}
partial class Program
{
public interface IConsole
{
void Print(string text);
void PrintLower(string text);
void UpdateTickCount();
}
// You should only instantiate one MainConsole, typically in your Program code.
// Either use a reference to that instance directly where needed or use it to create PrefixedConsoles.
public class MainConsole : IConsole
{
private List<string> _buffer = new List<string>();
private StringBuilder _builder = new StringBuilder();
private int _tickCount = 0;
private Program _program;
private string _programName;
private int _maxLines = 10;
private const int DefaultMaxLines = 10;
public MainConsole(Program program, string programName)
{
_program = program;
_programName = programName;
// Check the PB's custom data for a maxlines directive.
// TODO: can we check for which block we are and adjust accordingly? Using screen size perhaps...
_program.Ini.TryParse(program.Me.CustomData);
_maxLines = _program.Ini.Get("console", "maxLines").ToInt32(DefaultMaxLines);
// Setup the block's screens
_program.Me.GetSurface(0).ContentType = ContentType.TEXT_AND_IMAGE;
_program.Me.GetSurface(0).WriteText("Initializing...");
_program.Me.GetSurface(1).ContentType = ContentType.TEXT_AND_IMAGE;
_program.Me.GetSurface(1).FontSize = 3.5f;
_program.Me.GetSurface(1).TextPadding = 22.5f;
_program.Me.GetSurface(1).Alignment = TextAlignment.CENTER;
_program.Me.GetSurface(1).WriteText("Initializing...");
switch ((int)_program.Me.GetSurface(1).SurfaceSize.X)
{
case 512:
_maxLines = 10;
break;
case 256:
_maxLines = 17;
break;
default:
Print("Warning: unknown Programmable Block size.");
break;
}
}
public void Print(string text)
{
_program.Echo(text);
_program.Me.GetSurface(0).WriteText(writeToBuffer(text));
}
// Write the "standard" text to the lower console
public void UpdateTickCount()
{
PrintLower($"{_programName}\nTotal Ticks: {++_tickCount}");
}
// Most programs probably want to use UpdateTickCount to get program name and
// tick information.
// If you want something else on the lower screen, write it here. This is unbuffered,
// so text will be replaced instead of appended.
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)
{
_builder.Clear();
_buffer.Add(text);
if (_buffer.Count > _maxLines) _buffer.RemoveAt(0);
foreach (string line in _buffer) _builder.AppendLine(line);
return _builder.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 : IConsole
{
private IConsole _console;
private string _prefix;
public PrefixedConsole(IConsole console, string prefix)
{
_console = console;
_prefix = prefix + ": ";
}
public void Print(string text)
{
_console.Print(_prefix + text);
}
// sub-consoles can't print to the ephemeral display
public void PrintLower(string text) { }
public void UpdateTickCount() { }
}
// A replacement for the main console if you don't want the display screens involved.
// Good if you're using the Programmable Block's screens for your own purposes, but still
// need PrefixedConsole support.
//
// Content will just be printed via Echo, and PrintLower and UpdateTickCount will simply print
// an error.
public class EchoConsole : IConsole
{
private Program _program;
public EchoConsole(Program program)
{
_program = program;
}
public void Print(string text)
{
_program.Echo(text);
}
public void PrintLower(string text) { }
public void UpdateTickCount() { }
}
}
}