1
0
Fork 0

Refactor command console into own class

This commit is contained in:
Starbeamrainbowlabs 2017-12-15 23:36:25 +00:00
parent 068dfa58ba
commit 8b602f1aed
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
4 changed files with 129 additions and 58 deletions

View File

@ -0,0 +1,99 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Nibriboard.RippleSpace;
namespace Nibriboard
{
public class CommandConsole
{
private NibriboardServer server;
private TcpListener commandServer;
private int commandPort;
public CommandConsole(NibriboardServer inServer, int inCommandPort)
{
server = inServer;
commandPort = inCommandPort;
}
public async Task Start()
{
commandServer = new TcpListener(IPAddress.IPv6Loopback, server.CommandPort);
commandServer.Start();
Log.WriteLine("[CommandConsole] Listening on {0}.", new IPEndPoint(IPAddress.IPv6Loopback, server.CommandPort));
while(true)
{
TcpClient nextClient = await commandServer.AcceptTcpClientAsync();
StreamReader source = new StreamReader(nextClient.GetStream());
StreamWriter destination = new StreamWriter(nextClient.GetStream()) { AutoFlush = true };
string rawCommand = await source.ReadLineAsync();
string[] commandParts = rawCommand.Split(" \t".ToCharArray());
Log.WriteLine("[CommandConsole] Client executing {0}", rawCommand);
try
{
await executeCommand(destination, commandParts);
}
catch(Exception error)
{
try
{
await destination.WriteLineAsync(error.ToString());
}
catch { nextClient.Close(); } // Make absolutely sure that the command server won't die
}
nextClient.Close();
}
}
private async Task executeCommand(StreamWriter destination, string[] commandParts)
{
string commandName = commandParts[0].Trim();
switch(commandName)
{
case "help":
await destination.WriteLineAsync("Nibriboard Server Command Console");
await destination.WriteLineAsync("=================================");
await destination.WriteLineAsync("Available commands:");
await destination.WriteLineAsync(" help Show this message");
await destination.WriteLineAsync(" save Save the ripplespace to disk");
await destination.WriteLineAsync(" planes List all the currently loaded planes");
break;
case "save":
await destination.WriteAsync("Saving ripple space - ");
await server.PlaneManager.Save();
await destination.WriteLineAsync("done.");
await destination.WriteLineAsync($"Save is now {BytesToString(server.PlaneManager.LastSaveFileSize)} in size.");
break;
case "planes":
await destination.WriteLineAsync("Planes:");
foreach(Plane plane in server.PlaneManager.Planes)
await destination.WriteLineAsync($" {plane.Name} @ {plane.ChunkSize} ({plane.LoadedChunks} / ~{plane.SoftLoadedChunkLimit} chunks loaded, {plane.UnloadableChunks} inactive)");
await destination.WriteLineAsync();
await destination.WriteLineAsync($"Total {server.PlaneManager.Planes.Count}");
break;
default:
await destination.WriteLineAsync($"Error: Unrecognised command {commandName}");
break;
}
}
public static string BytesToString(long byteCount)
{
string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; // Longs run out around EB
if(byteCount == 0)
return "0" + suf[0];
long bytes = Math.Abs(byteCount);
int place = (int)Math.Floor(Math.Log(bytes, 1024));
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
return (Math.Sign(byteCount) * num).ToString() + suf[place];
}
}
}

View File

@ -143,6 +143,7 @@
<Compile Include="NibriboardApp.cs" />
<Compile Include="Utilities\LineSimplifier.cs" />
<Compile Include="Client\Messages\LineRemoveMessage.cs" />
<Compile Include="CommandConsole.cs" />
</ItemGroup>
<!--
<ItemGroup>

View File

@ -18,11 +18,11 @@ namespace Nibriboard
/// </summary>
public class NibriboardServer
{
private TcpListener commandServer;
private CommandConsole commandServer;
private NibriboardApp appServer;
private ClientSettings clientSettings;
private RippleSpaceManager planeManager;
public RippleSpaceManager PlaneManager;
public readonly int CommandPort = 31587;
public readonly int Port = 31586;
@ -32,11 +32,14 @@ namespace Nibriboard
Port = inPort;
// Load the specified packed ripple space file if it exists - otherwise save it to disk
if(File.Exists(pathToRippleSpace)) {
planeManager = RippleSpaceManager.FromFile(pathToRippleSpace).Result;
} else {
if(File.Exists(pathToRippleSpace))
{
PlaneManager = RippleSpaceManager.FromFile(pathToRippleSpace).Result;
}
else
{
Log.WriteLine("[NibriboardServer] Couldn't find packed ripple space at {0} - creating new ripple space instead.", pathToRippleSpace);
planeManager = new RippleSpaceManager() { SourceFilename = pathToRippleSpace };
PlaneManager = new RippleSpaceManager() { SourceFilename = pathToRippleSpace };
}
clientSettings = new ClientSettings() {
@ -50,8 +53,11 @@ namespace Nibriboard
appServer = new NibriboardApp(new NibriboardAppStartInfo() {
FilePrefix = "Nibriboard.obj.client_dist",
ClientSettings = clientSettings,
SpaceManager = planeManager
SpaceManager = PlaneManager
}, IPAddress.Any, Port);
// Command Console Server setup
commandServer = new CommandConsole(this, CommandPort);
}
public async Task Start()
@ -59,7 +65,7 @@ namespace Nibriboard
await appServer.Start();
Log.WriteLine("[NibriboardServer] Started on port {0}", Port);
await planeManager.StartMaintenanceMonkey();
await PlaneManager.StartMaintenanceMonkey();
}
/// <summary>
@ -71,56 +77,7 @@ namespace Nibriboard
/// </summary>
public async Task StartCommandListener()
{
commandServer = new TcpListener(IPAddress.IPv6Loopback, CommandPort);
commandServer.Start();
Log.WriteLine("[CommandConsole] Listening on {0}.", new IPEndPoint(IPAddress.IPv6Loopback, CommandPort));
while(true)
{
TcpClient nextClient = await commandServer.AcceptTcpClientAsync();
StreamReader source = new StreamReader(nextClient.GetStream());
StreamWriter destination = new StreamWriter(nextClient.GetStream()) { AutoFlush = true };
string rawCommand = await source.ReadLineAsync();
string[] commandParts = rawCommand.Split(" \t".ToCharArray());
Log.WriteLine("[CommandConsole] Client executing {0}", rawCommand);
try
{
switch(commandParts[0].Trim())
{
case "help":
await destination.WriteLineAsync("Nibriboard Server Command Console");
await destination.WriteLineAsync("=================================");
await destination.WriteLineAsync("Available commands:");
await destination.WriteLineAsync(" help Show this message");
await destination.WriteLineAsync(" save Save the ripplespace to disk");
await destination.WriteLineAsync(" planes List all the currently loaded planes");
break;
case "save":
await destination.WriteAsync("Saving ripple space - ");
await planeManager.Save();
await destination.WriteLineAsync("done.");
break;
case "planes":
await destination.WriteLineAsync("Planes:");
foreach(Plane plane in planeManager.Planes)
await destination.WriteLineAsync($"\t{plane.Name}");
await destination.WriteLineAsync();
await destination.WriteLineAsync($"Total {planeManager.Planes.Count}");
break;
default:
await destination.WriteLineAsync($"Error: Unrecognised command {commandParts[0].Trim()}");
break;
}
}
catch(Exception error)
{
await destination.WriteLineAsync(error.ToString());
}
nextClient.Close();
}
await commandServer.Start();
}
}
}

View File

@ -41,6 +41,20 @@ namespace Nibriboard.RippleSpace
public int DefaultChunkSize { get; set; } = 512;
/// <summary>
/// The size of the last save, in bytes.
/// Returns 0 if this RippleSpace hasn't been saved yet.
/// </summary>
/// <value>The last size of the save file.</value>
public long LastSaveFileSize {
get {
if(!File.Exists(SourceFilename))
return 0;
return (new FileInfo(SourceFilename)).Length;
}
}
public RippleSpaceManager()
{
// Create a temporary directory in which to store our unpacked planes