Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
4 changes: 4 additions & 0 deletions Obsdian.GuiConsole/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Threading.Tasks;
30 changes: 30 additions & 0 deletions Obsdian.GuiConsole/Logger/TerminalGuiLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.Extensions.Logging;
using Obsidian.GuiConsole.Window;
using Terminal.Gui.Views;

namespace Obsidian.GuiConsole.Logger;

public class TerminalGuiLogger : ILogger
{
private readonly ObsdianConsole _console;
private readonly LogLevel _minLevel;

public TerminalGuiLogger(ObsdianConsole console, LogLevel minLevel)
{
_console = console;
_minLevel = minLevel;
}

public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;

public bool IsEnabled(LogLevel logLevel) => logLevel >= _minLevel;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel)) return;

var message = formatter(state, exception);

_console.AppendLog(logLevel,message);
}
}
24 changes: 24 additions & 0 deletions Obsdian.GuiConsole/Logger/TerminalGuiLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.Extensions.Logging;
using Obsidian.GuiConsole.Window;
using Terminal.Gui.Views;

namespace Obsidian.GuiConsole.Logger;

public class TerminalGuiLoggerProvider: ILoggerProvider
{
private readonly ObsdianConsole _console;
private readonly LogLevel _minLevel;

public TerminalGuiLoggerProvider(ObsdianConsole console, LogLevel minLevel)
{
_console = console;
_minLevel = minLevel;
}

public ILogger CreateLogger(string categoryName)
{
return new TerminalGuiLogger(_console, _minLevel);
}

public void Dispose() { }
}
24 changes: 24 additions & 0 deletions Obsdian.GuiConsole/Obsidian.GuiConsole.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnablePreviewFeatures>True</EnablePreviewFeatures>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Terminal.Gui" Version="2.0.0-develop.4957" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Obsidian\Obsidian.csproj" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="config\server.json" />
<EmbeddedResource Include="config\whitelist.json" />
</ItemGroup>

</Project>
52 changes: 52 additions & 0 deletions Obsdian.GuiConsole/Program.Functions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System.Reflection;

namespace Obsidian.GuiConsole;

public partial class Program
{
private static async ValueTask GenerateConfigFiles()
{
const string path = "config";

Directory.CreateDirectory(path);

var serverJsonFile = Path.Combine(path, "server.json");
var whitelistJsonFile = Path.Combine(path, "whitelist.json");

if (!File.Exists(serverJsonFile))
{
await using var file = File.Create(serverJsonFile);

await using var embeddedFile = Assembly.GetExecutingAssembly().GetManifestResourceStream("Obsidian.GuiConsole.config.server.json");

await embeddedFile!.CopyToAsync(file);
}

if (!File.Exists(whitelistJsonFile))
{
await using var file = File.Create(whitelistJsonFile);

await using var embeddedFile = Assembly.GetExecutingAssembly().GetManifestResourceStream("Obsidian.GuiConsole.config.whitelist.json");

await embeddedFile!.CopyToAsync(file);
}
}

public static void DrawLogo()
{
const string asciilogo =
"\n" +
" ▄▄▄▄ ▄▄ ▄▄▄▄ ▀ ▄▄▄ ▐ ▄ \n" +
" ▐█ ▀█ ▐█ ▀ ██ ██ ██ ██ ▐█ ▀█ █▌▐█\n" +
" ▄█▀▄ ▐█▀▀█▄▄▀▀▀█▄▐█ ▐█ ▐█▌▐█ ▄█▀▀█ ▐█▐▐▌\n" +
"▐█▌ ▐▌██▄ ▐█▐█▄ ▐█▐█▌██ ██ ▐█▌▐█ ▐▌██▐█▌\n" +
" ▀█▄▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀▀▀ ▀▀▀ ▀ ▀ ▀▀ █ \n\n";

Console.Title = $"Obsidian for {ServerConstants.DefaultProtocol} ({ServerConstants.VERSION})";
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
Console.CursorVisible = false;
Console.WriteLine(asciilogo);
Console.ResetColor();
}
}
70 changes: 70 additions & 0 deletions Obsdian.GuiConsole/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Obsidian.GuiConsole.Logger;
using Obsidian.GuiConsole.Services;
using Obsidian.GuiConsole.Services.Command;
using Obsidian.GuiConsole.Window;
using Obsidian.Hosting;
using Terminal.Gui.App;
using Terminal.Gui.Configuration;

namespace Obsidian.GuiConsole;

public partial class Program
{
public static async Task Main(string[] args)
{
//Cool logo,but not render well on my machine -- stevesensei
DrawLogo();

//Init Gui App
ConfigurationManager.Enable(ConfigLocations.All);

//Create console window


//Normal Obsidian setup
await GenerateConfigFiles();
var builder = Host.CreateApplicationBuilder();
builder.ConfigureObsidian();
if (!Directory.Exists("logs"))
{
Directory.CreateDirectory("logs");
}

//Add Obsidian with GUI logger
var console = new ObsdianConsole();

builder.AddObsidianWithGui(x =>
{
x.AddProvider(new TerminalGuiLoggerProvider(console, LogLevel.Information));
return x;
});

//Give the server some time to shut down after CTRL-C or SIGTERM.
builder.Services.Configure<HostOptions>(opts =>
{
opts.ShutdownTimeout = TimeSpan.FromSeconds(10);
});
builder.Services.AddSingleton<CommandMiddleware>();
var hostApp = builder.Build();

IApplication? app = null;
try
{
//Run the application
await hostApp.StartAsync();
var commandMiddleware = hostApp.Services.GetRequiredService<CommandMiddleware>();
console.AddCommandMiddleware(commandMiddleware);
app = Application.Create().Init();
app.Run(console);
}
finally
{
//Cleanup when application stops
await hostApp.StopAsync();
app?.Dispose();
}
}
}
14 changes: 14 additions & 0 deletions Obsdian.GuiConsole/Services/Command/CommandMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.Extensions.Logging;
using Obsidian.API;
using Obsidian.API.Commands;

namespace Obsidian.GuiConsole.Services.Command;

public class CommandMiddleware(IServer server,ILogger<CommandMiddleware> logger)
{
public async Task ExecuteCommandFromConsoleAsync(string commandText)
{
var commandContext = new CommandContext("/"+commandText, new ConsoleCommandSender(logger), null,server);
Comment thread
stevesensei marked this conversation as resolved.
Outdated
await server.CommandHandler.ProcessCommand(commandContext);
Comment thread
stevesensei marked this conversation as resolved.
Outdated
}
}
35 changes: 35 additions & 0 deletions Obsdian.GuiConsole/Services/Command/ConsoleCommandSender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.Extensions.Logging;
using Obsidian.API;
using System.Text.RegularExpressions;

namespace Obsidian.GuiConsole.Services.Command;

public class ConsoleCommandSender(ILogger<CommandMiddleware> logger): ICommandSender
{
public CommandIssuers Issuer { get; } = CommandIssuers.Console;
public IPlayer? Player { get; } = null;

public Task SendMessageAsync(ChatMessage message)
{
List<string?> messageParts = new();
messageParts.Add(message.Text);
foreach (var extra in message.GetExtras())
messageParts.Add(extra.Text);
//log
foreach (var messagePart in messageParts)
{
if (string.IsNullOrEmpty(messagePart) || messagePart == "\n")
{
continue;
}
//remove color codes §
var clearMessage = Regex
.Replace(messagePart, "§[0-9a-fk-or]", string.Empty, RegexOptions.IgnoreCase);
//log to console
logger.LogInformation("[Console] {MessagePart}", clearMessage);
}
return Task.CompletedTask;
}

public Task SendMessageAsync(ChatMessage message, Guid sender) => throw new NotImplementedException();
}
Loading