// 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 _buffer = new List(); 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() { } } } }