1
0
Fork 0

Fill things out a bit and star working on de/serialisation

This commit is contained in:
Starbeamrainbowlabs 2017-01-07 17:35:56 +00:00
parent 9ccd3239a1
commit 6e894f58fc
6 changed files with 166 additions and 22 deletions

View File

@ -7,7 +7,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>Nibriboard</RootNamespace>
<AssemblyName>Nibriboard</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
@ -40,6 +40,7 @@
<Compile Include="RippleSpace\ChunkReference.cs" />
<Compile Include="RippleSpace\DrawnLine.cs" />
<Compile Include="RippleSpace\Reference.cs" />
<Compile Include="Utilities.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="RippleSpace\" />

View File

@ -1,32 +1,34 @@
using System;
using System.IO;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.Serialization;
namespace Nibriboard.RippleSpace
{
/// <summary>
/// Represents a single chunk of an infinite <see cref="Nibriboard.RippleSpace.Plane" />.
/// </summary>
public class Chunk : IEnumerable<DrawnLine>
[Serializable]
public class Chunk : IEnumerable<DrawnLine>, IDeserializationCallback
{
/// <summary>
/// The lines that this chunk currently contains.
/// </summary>
private List<DrawnLine> lines = new List<DrawnLine>();
/// <summary>
/// The plane that this chunk is located on.
/// </summary>
public readonly Plane Plane;
/// <summary>
/// The size of this chunk.
/// </summary>
public readonly int Size;
/// <summary>
/// The location of this chunk chunk on the plane.
/// </summary>
public readonly ChunkReference Location;
/// <summary>
/// The time at which this chunk was loaded.
/// </summary>
@ -36,17 +38,80 @@ namespace Nibriboard.RippleSpace
/// </summary>
public DateTime TimeLastAccessed { get; private set; } = DateTime.Now;
public Chunk(Plane inPlane, int inSize)
/// <summary>
/// Whether this <see cref="T:Nibriboard.RippleSpace.Chunk"/> is primary chunk.
/// Primary chunks are always loaded.
/// </summary>
public bool IsPrimaryChunk
{
get {
if(Location.X < Location.Plane.PrimaryChunkAreaSize &&
Location.X > -Location.Plane.PrimaryChunkAreaSize &&
Location.Y < Location.Plane.PrimaryChunkAreaSize &&
Location.Y > -Location.Plane.PrimaryChunkAreaSize)
{
return true;
}
return false;
}
}
/// <summary>
/// Whether this chunk is inactive or not.
/// </summary>
/// <remarks>
/// Note that even if a chunk is inactive, it's not guaranteed that
/// it will be unloaded. It's possible that the server will keep it
/// loaded anyway - it could be a primary chunk, or the server may not
/// have many chunks loaded at a particular time.
/// </remarks>
public bool Inactive
{
get {
// If the time we were last accessed + the inactive timer is
// still less than the current time, then we're inactive.
if (TimeLastAccessed.AddMilliseconds(Plane.InactiveMillisecs) < DateTime.Now)
return false;
return true;
}
}
/// <summary>
/// Whether this chunk could, theorectically, be unloaded. Of course,
/// the server may decide it doesn't need to unload us even if we're
/// inactive.
/// </summary>
public bool CouldUnload
{
get {
// If we're a primary chunk or not inactive, then we shouldn't
// unload it.
if (IsPrimaryChunk || !Inactive)
return false;
return true;
}
}
public Chunk(Plane inPlane, int inSize, ChunkReference inLocation)
{
Plane = inPlane;
Size = inSize;
Location = inLocation;
}
/// <summary>
/// Updates the time the chunk was last accessed, thereby preventing it
/// from becoming inactive.
/// </summary>
public void UpdateAccessTime()
{
TimeLastAccessed = DateTime.Now;
}
#region Enumerator
public DrawnLine this[int i]
{
get {
@ -70,25 +135,28 @@ namespace Nibriboard.RippleSpace
return GetEnumerator();
}
#endregion
#region Serialisation
public static async Task<Chunk> FromFile(Plane plane, string filename)
{
StreamReader chunkSource = new StreamReader(filename);
FileStream chunkSource = new FileStream(filename, FileMode.Open);
return await FromStream(plane, chunkSource);
}
public static async Task<Chunk> FromStream(Plane plane, StreamReader chunkSource)
public static async Task<Chunk> FromStream(Plane plane, Stream chunkSource)
{
Chunk result = new Chunk(
plane,
int.Parse(chunkSource.ReadLine())
);
Chunk loadedChunk = await Utilities.DeserialiseBinaryObject<Chunk>(chunkSource);
loadedChunk.Plane = plane;
string nextLine = string.Empty;
while((nextLine = await chunkSource.ReadLineAsync()) != null)
{
throw new NotImplementedException();
}
return result;
return loadedChunk;
}
public void OnDeserialization(object sender)
{
UpdateAccessTime();
}
#endregion
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Security.Policy;
using System.IO;
namespace Nibriboard.RippleSpace
{
/// <summary>
@ -34,5 +35,23 @@ namespace Nibriboard.RippleSpace
{
return $"{Plane.Name}-{X},{Y}.chunk";
}
public static ChunkReference Parse(Plane plane, string source)
{
if (!source.StartsWith("ChunkReference:"))
throw new InvalidDataException($"Error: That isn't a valid chunk reference. Chunk references start with 'ChunkReference:'.");
// Trim the extras off the reference
source = source.Substring("ChunkReference:".Length);
source = source.Trim("() \v\t\r\n".ToCharArray());
int x = source.Substring(0, source.IndexOf(","));
int y = source.Substring(source.IndexOf(",") + 1);
return new ChunkReference(
plane,
x,
y
);
}
}
}

View File

@ -10,5 +10,24 @@ namespace Nibriboard.RippleSpace
{
}
public static LocationReference Parse(Plane plane, string source)
{
// TODO: Decide if this is the format that we want to use for location references
if (!source.StartsWith("LocationReference:"))
throw new InvalidDataException($"Error: That isn't a valid location reference. Location references start with 'ChunkReference:'.");
// Trim the extras off the reference
source = source.Substring("LocationReference:".Length);
source = source.Trim("() \v\t\r\n".ToCharArray());
int x = source.Substring(0, source.IndexOf(","));
int y = source.Substring(source.IndexOf(",") + 1);
return new LocationReference(
plane,
x,
y
);
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.IO;
namespace Nibriboard.RippleSpace
{
/// <summary>
@ -18,6 +19,23 @@ namespace Nibriboard.RippleSpace
/// </summary>
public readonly int ChunkSize;
/// <summary>
/// The path to the directory that the plane's information will be stored in.
/// </summary>
public readonly string StorageDirectory;
/// <summary>
/// The number of milliseconds that should pass since a chunk's last
/// access in order for it to be considered inactive.
/// </summary>
public int InactiveMillisecs = 60 * 1000;
/// <summary>
/// The number of chunks in a square around (0, 0) that should always be
/// loaded.
/// </summary>
public int PrimaryChunkAreaSize = 10;
/// <summary>
/// The chunkspace that holds the currently loaded and active chunks.
/// </summary>
@ -27,6 +45,8 @@ namespace Nibriboard.RippleSpace
{
Name = inName;
ChunkSize = inChunkSize;
StorageDirectory = $"./Planes/{Name}";
}
public async Task<Chunk> FetchChunk(ChunkReference chunkLocation)

17
Nibriboard/Utilities.cs Normal file
View File

@ -0,0 +1,17 @@
using System;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Nibriboard
{
public static class Utilities
{
public static async Task<T> DeserialiseBinaryObject<T>(Stream sourceStream)
{
return await Task.Run(() => {
BinaryFormatter formatter = new BinaryFormatter();
return (T)formatter.Deserialize(sourceStream);
});
}
}
}