diff --git a/LANCommander/LANCommander.csproj b/LANCommander/LANCommander.csproj index 5e95cfd..82d2187 100644 --- a/LANCommander/LANCommander.csproj +++ b/LANCommander/LANCommander.csproj @@ -26,6 +26,7 @@ + diff --git a/LANCommander/Pages/Servers/Components/Console.razor b/LANCommander/Pages/Servers/Components/Console.razor index c8689df..989df76 100644 --- a/LANCommander/Pages/Servers/Components/Console.razor +++ b/LANCommander/Pages/Servers/Components/Console.razor @@ -1,14 +1,21 @@ -@using Microsoft.AspNetCore.SignalR.Client +@using LANCommander.Data.Enums; +@using Microsoft.AspNetCore.SignalR.Client @using NLog; @using XtermBlazor @inject ServerService ServerService @inject ServerConsoleService ServerConsoleService @inject ServerProcessService ServerProcessService @inject NavigationManager NavigationManager +@inject IMessageService MessageService @implements IAsyncDisposable +@if (ServerConsole.Type == ServerConsoleType.RCON) +{ + +} + @code { [Parameter] public Guid ServerId { get; set; } [Parameter] public Guid ServerConsoleId { get; set; } @@ -17,6 +24,11 @@ HubConnection? HubConnection; ServerConsole ServerConsole; + Input CommandInput; + string Command; + string[] History; + int HistoryPosition; + TerminalOptions TerminalOptions = new TerminalOptions { CursorBlink = true, @@ -31,18 +43,34 @@ protected override async Task OnInitializedAsync() { ServerConsole = await ServerConsoleService.Get(ServerConsoleId); - - HubConnection = new HubConnectionBuilder() - .WithUrl(NavigationManager.ToAbsoluteUri("/hubs/gameserver")) - .Build(); - HubConnection.On("Log", (serverId, logId, message) => + History = new string[50]; + HistoryPosition = 0; + + if (ServerConsole.Type == ServerConsoleType.LogFile) { - if (serverId == ServerId && logId == ServerConsoleId) - Terminal.WriteLine(message); - }); + HubConnection = new HubConnectionBuilder() + .WithUrl(NavigationManager.ToAbsoluteUri("/hubs/gameserver")) + .Build(); - await HubConnection.StartAsync(); + HubConnection.On("Log", (serverId, logId, message) => + { + if (serverId == ServerId && logId == ServerConsoleId) + Terminal.WriteLine(message); + }); + + await HubConnection.StartAsync(); + } + else if (ServerConsole.Type == ServerConsoleType.RCON) + { + try { + ServerProcessService.RconConnect(ServerConsole); + } + catch (Exception ex) + { + await MessageService.Error($"Could not connect to RCON server: {ex.Message}"); + } + } } protected override async Task OnAfterRenderAsync(bool firstRender) @@ -63,6 +91,52 @@ } } + public async Task OnPressEnter() { + await ServerProcessService.RconSendCommandAsync(Command, ServerConsole); + + Array.Copy(History, 0, History, 1, History.Length - 1); + History[0] = Command; + HistoryPosition = -1; + Command = ""; + CommandInput.Value = ""; + await Task.Yield(); + await CommandInput.ValueChanged.InvokeAsync(); + await CommandInput.Focus(FocusBehavior.FocusAndClear); + + StateHasChanged(); + } + + public async Task OnCommandKeyDown(KeyboardEventArgs args) + { + switch (args.Key) + { + case "ArrowUp": + if (HistoryPosition < History.Length && History[HistoryPosition + 1] != null) + HistoryPosition++; + + Command = History[HistoryPosition]; + + StateHasChanged(); + break; + + case "ArrowDown": + if (HistoryPosition >= 0) + { + HistoryPosition--; + + if (HistoryPosition >= 0) + Command = History[HistoryPosition]; + else + { + Command = ""; + } + } + + StateHasChanged(); + break; + } + } + public async ValueTask DisposeAsync() { if (HubConnection is not null) diff --git a/LANCommander/Services/ServerLogService.cs b/LANCommander/Services/ServerLogService.cs index 0e92272..668c1f4 100644 --- a/LANCommander/Services/ServerLogService.cs +++ b/LANCommander/Services/ServerLogService.cs @@ -1,6 +1,9 @@ -using LANCommander.Data; +using CoreRCON; +using LANCommander.Data; +using LANCommander.Data.Enums; using LANCommander.Data.Models; using System.Diagnostics; +using System.Net; namespace LANCommander.Services { @@ -12,6 +15,9 @@ namespace LANCommander.Services { var log = await Get(logId); + if (log.Type != ServerConsoleType.LogFile) + throw new Exception("Invalid console type"); + var logPath = Path.Combine(log.Server.WorkingDirectory, log.Path); return await File.ReadAllLinesAsync(logPath); diff --git a/LANCommander/Services/ServerProcessService.cs b/LANCommander/Services/ServerProcessService.cs index a75ab72..1267f9d 100644 --- a/LANCommander/Services/ServerProcessService.cs +++ b/LANCommander/Services/ServerProcessService.cs @@ -1,4 +1,5 @@ -using LANCommander.Data.Enums; +using CoreRCON; +using LANCommander.Data.Enums; using LANCommander.Data.Models; using LANCommander.Hubs; using Microsoft.AspNetCore.SignalR; @@ -6,6 +7,7 @@ using Microsoft.EntityFrameworkCore; using NLog; using NLog.Fluent; using System.Diagnostics; +using System.Net; namespace LANCommander.Services { @@ -98,12 +100,25 @@ namespace LANCommander.Services } } + public class RconConnection + { + public RCON RCON { get; set; } + public LogReceiver LogReceiver { get; set; } + + public RconConnection(string host, int port, string password) + { + RCON = new RCON(new IPEndPoint(IPAddress.Parse(host), port), password); + } + } + public class ServerProcessService : BaseService { public Dictionary Processes = new Dictionary(); public Dictionary Threads { get; set; } = new Dictionary(); public Dictionary LogFileMonitors { get; set; } = new Dictionary(); + private Dictionary RconConnections { get; set; } = new Dictionary(); + public delegate void OnLogHandler(object sender, ServerLogEventArgs e); public event OnLogHandler OnLog; @@ -177,14 +192,36 @@ namespace LANCommander.Services private void StartMonitoringLog(ServerConsole log, Server server) { - var logPath = Path.Combine(server.WorkingDirectory, log.Path); - if (!LogFileMonitors.ContainsKey(server.Id)) { LogFileMonitors[server.Id] = new LogFileMonitor(server, log, HubContext); } } + public RCON RconConnect(ServerConsole console) + { + if (!RconConnections.ContainsKey(console.Id)) + { + var rcon = new RCON(new IPEndPoint(IPAddress.Parse(console.Host), console.Port), console.Password); + + RconConnections[console.Id] = rcon; + + return rcon; + } + else + return RconConnections[console.Id]; + } + + public async Task RconSendCommandAsync(string command, ServerConsole console) + { + if (RconConnections.ContainsKey(console.Id)) + { + return await RconConnections[console.Id].SendCommandAsync(command); + } + else + return ""; + } + public ServerProcessStatus GetStatus(Server server) { Process process = null;