Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ on:
jobs:
build:

runs-on: windows-latest
strategy:
fail-fast: false
matrix:
os: [ windows-latest, macos-latest, ubuntu-latest ]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
Expand Down
7 changes: 7 additions & 0 deletions ConsoleEngine.sln
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerraForM.Tests", "Examples
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples.Tests", "Examples.Tests", "{106CCD57-88BD-4B0A-A67F-A5DA7D8FCA3C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleEngine.CrossPlatform", "Libs\ConsoleEngine.CrossPlatform\ConsoleEngine.CrossPlatform.csproj", "{F5F065A9-F0B1-45B6-B4BC-5912BAB09803}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|Any CPU = Release|Any CPU
Expand Down Expand Up @@ -82,6 +84,10 @@ Global
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Release|Any CPU.Build.0 = Release|Any CPU
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|Any CPU.Build.0 = Release|Any CPU
{F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{99309207-1847-4EB9-A009-C7B92BC2CE64} = {CA22425D-FB6C-45C6-A14C-561DF6D969B6}
Expand All @@ -96,5 +102,6 @@ Global
{A4209E56-1ECD-4616-BB13-DF77864F462C} = {12D2B48F-E7F6-4BEC-8315-9EC8F41A059A}
{0CDE38D4-12F4-426B-9252-E57820FF8D9B} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA} = {106CCD57-88BD-4B0A-A67F-A5DA7D8FCA3C}
{F5F065A9-F0B1-45B6-B4BC-5912BAB09803} = {CA22425D-FB6C-45C6-A14C-561DF6D969B6}
EndGlobalSection
EndGlobal
1 change: 1 addition & 0 deletions ConsoleEngine/ConsoleEngine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ConsoleEngine.Abstractions\ConsoleEngine.Abstractions.csproj" />
<ProjectReference Include="..\Libs\ConsoleEngine.CrossPlatform\ConsoleEngine.CrossPlatform.csproj" />
<ProjectReference Include="..\Libs\ConsoleEngine.Logger\ConsoleEngine.Logger.csproj" />
<ProjectReference Include="..\Libs\Microsoft.Xna.Framework\Microsoft.Xna.Framework.csproj" />
<ProjectReference Include="..\Libs\ConsoleEngine.Windows\ConsoleEngine.Windows.csproj" />
Expand Down
8 changes: 6 additions & 2 deletions ConsoleEngine/GameBase.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System.Threading;
using System;
using System.Threading;
using ConsoleEngine.Abstractions.Rendering;
using ConsoleEngine.Infrastructure;
using ConsoleEngine.Infrastructure.Inputs;
using ConsoleEngine.Infrastructure.Logging;
using ConsoleEngine.Infrastructure.Rendering;
using ConsoleEngine.Infrastructure.Scenery;
using ConsoleEngine.Native;
using ConsoleEngine.CrossPlatform;

namespace ConsoleEngine;

Expand All @@ -32,7 +34,9 @@ protected GameBase(int width, int height, int fontWidth, int fontHeight)

protected GameBase(int width, int height, FontInfo fontInfo)
{
_console = new RenderConsole(new ConsoleHandler(width, height, fontInfo));
_console = new RenderConsole(OperatingSystem.IsWindows()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the platform choice is made in two places.

OperatingSystem.IsWindows() picks the Win32 or cross-platform implementation both here and in Input.cs, where it creates the static Handler. A small factory (for example Platform.CreateConsoleHandler(...) and Platform.CreateInputHandler()) would keep the decision in one place. That would make it easier to add a backend, or to force the ANSI renderer on Windows Terminal, without the two places getting out of sync.

? new ConsoleHandler(width, height, fontInfo)
: new CrossPlatformConsoleHandler(width, height, fontInfo));
Name = "Game";
Scenes = new SceneManager(this);
}
Expand Down
7 changes: 5 additions & 2 deletions ConsoleEngine/Infrastructure/Inputs/Input.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using ConsoleEngine.Abstractions.Inputs;
using ConsoleEngine.Native;
using ConsoleEngine.CrossPlatform;

namespace ConsoleEngine.Infrastructure.Inputs;

Expand All @@ -13,8 +14,10 @@ public class Input
//**********************************************************

public static readonly Input Instance = new();
private static readonly IInputHandler Handler = new InputHandler();

private static readonly IInputHandler Handler = OperatingSystem.IsWindows()
? new InputHandler()
: new CrossPlatformInputHandler();

//**********************************************************
//** ctor:
//**********************************************************
Expand Down
38 changes: 33 additions & 5 deletions ConsoleEngine/Infrastructure/Logging/Log.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Concurrent;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
Expand Down Expand Up @@ -77,16 +79,42 @@ internal static void Start(GameBase game)
Socket.Listen(10);
LoggerThread.Start();

StartLoggerProcess();
}

private static void StartLoggerProcess()
{
var logger = Path.Combine(AppContext.BaseDirectory, OperatingSystem.IsWindows() ? "ConsoleEngine.Logger.exe" : "ConsoleEngine.Logger");

_loggerProcess = new Process();
_loggerProcess.StartInfo.FileName = "ConsoleEngine.Logger.exe";
_loggerProcess.StartInfo.UseShellExecute = true;
_loggerProcess.Start();
if (OperatingSystem.IsMacOS())
{
// The game owns the current terminal, open the logger in a new Terminal window.
_loggerProcess.StartInfo.FileName = "open";
_loggerProcess.StartInfo.ArgumentList.Add("-a");
_loggerProcess.StartInfo.ArgumentList.Add("Terminal");
_loggerProcess.StartInfo.ArgumentList.Add(logger);
}
else
{
_loggerProcess.StartInfo.FileName = logger;
_loggerProcess.StartInfo.UseShellExecute = true;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: on Linux the logger runs inside the game's own terminal.

When UseShellExecute = true and FileName is an executable file, .NET on Unix runs it directly instead of opening a new window. So on Linux Process.Start succeeds and the catch below is never reached. ConsoleEngine.Logger then:

  • writes Logger up and running... and every log line into the game's alternate screen, corrupting the rendered frame,
  • writes title escape sequences (Console.Title) to the same terminal,
  • ends with Console.ReadKey(), competing with the game for keyboard input.

On Linux it would be safer to start it in a terminal emulator (x-terminal-emulator -e …, or $TERMINAL), or not to start it at all and print a hint to run the logger manually.

}

try
{
_loggerProcess.Start();
}
catch (Exception)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: if the logger fails to start, the failure is ignored and messages pile up.

When Process.Start throws (on headless Linux, for example), the exception is swallowed but Log keeps running as if the logger were attached:

  • the dispatch thread blocks in Socket.Accept() forever,
  • EnqueueMessage keeps adding to the unbounded Messages queue (10 FPS reports per second when ShowFps is on, plus every Log.WriteLine), and nothing ever reads them.

Before this change the failure at least surfaced. Consider setting a flag in the catch that stops queuing messages, or bounding the queue.

{
// No way to open a new console window here (e.g. linux without a desktop). Run ConsoleEngine.Logger manually to see the log.
}
}

internal static void Stop()
{
_running = false;
_loggerConnection.Dispose();
_loggerConnection?.Dispose();
Socket.Dispose();
Messages.Clear();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12</LangVersion>
<RootNamespace>ConsoleEngine.CrossPlatform</RootNamespace>
<Configurations>Release;Debug</Configurations>
<Platforms>AnyCPU</Platforms>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\ConsoleEngine.Abstractions\ConsoleEngine.Abstractions.csproj" />
</ItemGroup>
</Project>

Loading
Loading