1
0
Fork 0
mirror of https://github.com/sbrl/Nibriboard.git synced 2018-01-10 21:33:49 +00:00

[server] Add plane status and tweak soft loaded chunk limit

This commit is contained in:
Starbeamrainbowlabs 2017-12-16 12:01:07 +00:00
parent 3486a28759
commit 4397d90fe9
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
4 changed files with 104 additions and 14 deletions

View file

@ -65,6 +65,7 @@ namespace Nibriboard
await destination.WriteLineAsync(" save Save the ripplespace to disk");
await destination.WriteLineAsync(" plane list List all the currently loaded planes");
await destination.WriteLineAsync(" plane create {new-plane-name} [{chunkSize}] Create a new named plane, optionally with the specified chunk size.");
await destination.WriteLineAsync(" plane status {plane-name} Show the statistics of the current plane.");
break;
case "save":
await destination.WriteAsync("Saving ripple space - ");
@ -83,7 +84,7 @@ namespace Nibriboard
case "list":
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($" {plane.Name} @ {plane.ChunkSize} ({plane.LoadedChunks} / ~{plane.SoftLoadedChunkLimit} chunks loaded, {plane.UnloadableChunks} inactive, {plane.TotalChunks} total at last save)");
await destination.WriteLineAsync();
await destination.WriteLineAsync($"Total {server.PlaneManager.Planes.Count}");
break;
@ -104,6 +105,29 @@ namespace Nibriboard
await destination.WriteLineAsync($"Created plane with name {newPlaneName} and chunk size {chunkSize}.");
break;
case "status":
if(commandParts.Length < 3) {
await destination.WriteLineAsync("Error: No plane name specified!");
return;
}
string targetPlaneName = commandParts[2].Trim();
Plane targetPlane = server.PlaneManager.GetByName(targetPlaneName);
if(targetPlane == null) {
await destination.WriteLineAsync($"Error: A plane with the name {targetPlaneName} doesn't exist.");
return;
}
await destination.WriteLineAsync($"Name: {targetPlane.Name}");
await destination.WriteLineAsync($"Chunk size: {targetPlane.ChunkSize}");
await destination.WriteLineAsync($"Loaded chunks: {targetPlane.LoadedChunks}");
await destination.WriteLineAsync($"Unloaded chunks: {targetPlane.TotalChunks - targetPlane.LoadedChunks}");
await destination.WriteLineAsync($"Total chunks: {targetPlane.TotalChunks}");
await destination.WriteLineAsync($"Primary chunk area size: {targetPlane.PrimaryChunkAreaSize}");
await destination.WriteLineAsync($"Min unloadeable chunks: {targetPlane.MinUnloadeableChunks}");
await destination.WriteLineAsync($"Soft loaded chunk limit: {targetPlane.SoftLoadedChunkLimit}");
break;
default:
await destination.WriteLineAsync($"Error: Unknown sub-action {subAction}.");
@ -111,6 +135,33 @@ namespace Nibriboard
}
break;
/*case "chunk":
if(commandParts.Length < 2) {
await destination.WriteLineAsync("Error: No sub-action specified.");
break;
}
string chunkSubAction = commandParts[1].Trim();
switch(chunkSubAction)
{
case "list":
if(commandParts.Length < 3) {
await destination.WriteLineAsync("Error: No plane specified to list the chunks of!");
return;
}
Plane plane = server.PlaneManager.GetByName(commandParts[2].Trim());
foreach(Chunk chunk in plane.
break;
default:
await destination.WriteLineAsync($"Error: Unknown sub-action {chunkSubAction}.");
break;
}
break;*/
default:
await destination.WriteLineAsync($"Error: Unrecognised command {commandName}");
break;

View file

@ -20,7 +20,7 @@ namespace Nibriboard.RippleSpace
}
/// <summary>
/// Creates a new blank <see cref="Nibriboard.RippleSpace.ChunkReference" />.
/// Creates a new blank <see cref="ChunkReference" />.
/// Don't use this yourself! This is only for Newtonsoft.Json to use when deserialising references.
/// </summary>
public ChunkReference() : base()

View file

@ -43,7 +43,7 @@ namespace Nibriboard.RippleSpace
/// loaded.
/// Works like a radius.
/// </summary>
public int PrimaryChunkAreaSize = 10;
public int PrimaryChunkAreaSize = 5;
/// <summary>
/// The minimum number of potentially unloadable chunks that we should have
@ -95,6 +95,19 @@ namespace Nibriboard.RippleSpace
return result;
}
}
/// <summary>
/// Calculates the total number of chunks created that are on this plane - including those
/// that are currently unloaded.
/// </summary>
/// <description>
/// This is, understandably, a rather expensive operation - so use with caution!
/// Also, this count is only accurate to the last save.
/// </description>
public int TotalChunks {
get {
return Directory.GetFileSystemEntries(StorageDirectory, "*.chunk").Length;
}
}
/// <summary>
/// Initialises a new plane.
@ -110,7 +123,7 @@ namespace Nibriboard.RippleSpace
// Set the soft loaded chunk limit to double the number of chunks in the
// primary chunks area
// Note that the primary chunk area is a radius around (0, 0) - not the diameter
SoftLoadedChunkLimit = PrimaryChunkAreaSize * PrimaryChunkAreaSize * 4;
SoftLoadedChunkLimit = PrimaryChunkAreaSize * PrimaryChunkAreaSize * 16;
}
private async Task LoadPrimaryChunks()
@ -131,7 +144,7 @@ namespace Nibriboard.RippleSpace
}
}
await FetchChunks(primaryChunkRefs);
await FetchChunks(primaryChunkRefs, false);
}
/// <summary>
@ -139,16 +152,24 @@ namespace Nibriboard.RippleSpace
/// </summary>
/// <param name="chunkRefs">The chunk references to fetch the attached chunks for.</param>
/// <returns>The chunks attached to the specified chunk references.</returns>
public async Task<List<Chunk>> FetchChunks(List<ChunkReference> chunkRefs)
public async Task<List<Chunk>> FetchChunks(IEnumerable<ChunkReference> chunkRefs, bool autoCreate)
{
// todo Paralellise loading with https://www.nuget.org/packages/AsyncEnumerator
// Todo Paralellise loading with https://www.nuget.org/packages/AsyncEnumerator
List<Chunk> chunks = new List<Chunk>();
foreach(ChunkReference chunkRef in chunkRefs)
chunks.Add(await FetchChunk(chunkRef));
foreach(ChunkReference chunkRef in chunkRefs) {
Chunk nextChunk = await FetchChunk(chunkRef, true);
if(nextChunk != null) // Might be null if we're not allowed to create new chunks
chunks.Add(nextChunk);
}
return chunks;
}
public async Task<List<Chunk>> FetchChunks(IEnumerable<ChunkReference> chunkRefs)
{
return await FetchChunks(chunkRefs, true);
}
public async Task<Chunk> FetchChunk(ChunkReference chunkLocation)
public async Task<Chunk> FetchChunk(ChunkReference chunkLocation, bool autoCreate)
{
// If the chunk is in the loaded chunk-space, then return it immediately
if(loadedChunkspace.ContainsKey(chunkLocation))
@ -162,13 +183,22 @@ namespace Nibriboard.RippleSpace
Chunk loadedChunk;
if(File.Exists(chunkFilePath)) // If the chunk exists on disk, load it
loadedChunk = await Chunk.FromFile(this, chunkFilePath);
else // Ooooh! It's a _new_, never-before-seen one! Create a brand new chunk :D
else
{
// Ooooh! It's a _new_, never-before-seen one! Create a brand new chunk :D
// ....but only if we've been told it's ok to create new chunks.
if(!autoCreate) return null;
loadedChunk = new Chunk(this, ChunkSize, chunkLocation);
}
loadedChunk.OnChunkUpdate += HandleChunkUpdate;
loadedChunkspace.Add(chunkLocation, loadedChunk);
return loadedChunk;
}
public async Task<Chunk> FetchChunk(ChunkReference chunkLocation)
{
return await FetchChunk(chunkLocation, true);
}
/// <summary>
/// Works out whether a chunk currently exists.

View file

@ -116,6 +116,15 @@ namespace Nibriboard.RippleSpace
return newPlane;
}
public Plane GetByName(string targetPlaneName)
{
foreach(Plane plane in Planes) {
if(plane.Name == targetPlaneName)
return plane;
}
return null;
}
public async Task StartMaintenanceMonkey()
{
Log.WriteLine("[RippleSpace/Maintenance] Automated maintenance monkey created.");