mirror of
https://github.com/sbrl/Nibriboard.git
synced 2018-01-10 21:33:49 +00:00
Fill things out a bit and star working on de/serialisation
This commit is contained in:
parent
9ccd3239a1
commit
6e894f58fc
6 changed files with 166 additions and 22 deletions
|
@ -7,7 +7,7 @@
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>Nibriboard</RootNamespace>
|
<RootNamespace>Nibriboard</RootNamespace>
|
||||||
<AssemblyName>Nibriboard</AssemblyName>
|
<AssemblyName>Nibriboard</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
<Compile Include="RippleSpace\ChunkReference.cs" />
|
<Compile Include="RippleSpace\ChunkReference.cs" />
|
||||||
<Compile Include="RippleSpace\DrawnLine.cs" />
|
<Compile Include="RippleSpace\DrawnLine.cs" />
|
||||||
<Compile Include="RippleSpace\Reference.cs" />
|
<Compile Include="RippleSpace\Reference.cs" />
|
||||||
|
<Compile Include="Utilities.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="RippleSpace\" />
|
<Folder Include="RippleSpace\" />
|
||||||
|
|
|
@ -1,32 +1,34 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace Nibriboard.RippleSpace
|
namespace Nibriboard.RippleSpace
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a single chunk of an infinite <see cref="Nibriboard.RippleSpace.Plane" />.
|
/// Represents a single chunk of an infinite <see cref="Nibriboard.RippleSpace.Plane" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Chunk : IEnumerable<DrawnLine>
|
[Serializable]
|
||||||
|
public class Chunk : IEnumerable<DrawnLine>, IDeserializationCallback
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The lines that this chunk currently contains.
|
/// The lines that this chunk currently contains.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<DrawnLine> lines = new List<DrawnLine>();
|
private List<DrawnLine> lines = new List<DrawnLine>();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The plane that this chunk is located on.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Plane Plane;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The size of this chunk.
|
/// The size of this chunk.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly int Size;
|
public readonly int Size;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The location of this chunk chunk on the plane.
|
||||||
|
/// </summary>
|
||||||
|
public readonly ChunkReference Location;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time at which this chunk was loaded.
|
/// The time at which this chunk was loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -36,17 +38,80 @@ namespace Nibriboard.RippleSpace
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime TimeLastAccessed { get; private set; } = DateTime.Now;
|
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;
|
Plane = inPlane;
|
||||||
Size = inSize;
|
Size = inSize;
|
||||||
|
Location = inLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the time the chunk was last accessed, thereby preventing it
|
||||||
|
/// from becoming inactive.
|
||||||
|
/// </summary>
|
||||||
public void UpdateAccessTime()
|
public void UpdateAccessTime()
|
||||||
{
|
{
|
||||||
TimeLastAccessed = DateTime.Now;
|
TimeLastAccessed = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Enumerator
|
||||||
|
|
||||||
public DrawnLine this[int i]
|
public DrawnLine this[int i]
|
||||||
{
|
{
|
||||||
get {
|
get {
|
||||||
|
@ -70,25 +135,28 @@ namespace Nibriboard.RippleSpace
|
||||||
return GetEnumerator();
|
return GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Serialisation
|
||||||
|
|
||||||
public static async Task<Chunk> FromFile(Plane plane, string filename)
|
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);
|
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(
|
Chunk loadedChunk = await Utilities.DeserialiseBinaryObject<Chunk>(chunkSource);
|
||||||
plane,
|
loadedChunk.Plane = plane;
|
||||||
int.Parse(chunkSource.ReadLine())
|
|
||||||
);
|
|
||||||
|
|
||||||
string nextLine = string.Empty;
|
return loadedChunk;
|
||||||
while((nextLine = await chunkSource.ReadLineAsync()) != null)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnDeserialization(object sender)
|
||||||
|
{
|
||||||
|
UpdateAccessTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Security.Policy;
|
using System.Security.Policy;
|
||||||
|
using System.IO;
|
||||||
namespace Nibriboard.RippleSpace
|
namespace Nibriboard.RippleSpace
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -34,5 +35,23 @@ namespace Nibriboard.RippleSpace
|
||||||
{
|
{
|
||||||
return $"{Plane.Name}-{X},{Y}.chunk";
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.IO;
|
||||||
namespace Nibriboard.RippleSpace
|
namespace Nibriboard.RippleSpace
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -18,6 +19,23 @@ namespace Nibriboard.RippleSpace
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly int ChunkSize;
|
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>
|
/// <summary>
|
||||||
/// The chunkspace that holds the currently loaded and active chunks.
|
/// The chunkspace that holds the currently loaded and active chunks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -27,6 +45,8 @@ namespace Nibriboard.RippleSpace
|
||||||
{
|
{
|
||||||
Name = inName;
|
Name = inName;
|
||||||
ChunkSize = inChunkSize;
|
ChunkSize = inChunkSize;
|
||||||
|
|
||||||
|
StorageDirectory = $"./Planes/{Name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Chunk> FetchChunk(ChunkReference chunkLocation)
|
public async Task<Chunk> FetchChunk(ChunkReference chunkLocation)
|
||||||
|
|
17
Nibriboard/Utilities.cs
Normal file
17
Nibriboard/Utilities.cs
Normal 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue