parent
94bd99a478
commit
f9339ead77
5 changed files with 126 additions and 55 deletions
@ -0,0 +1,82 @@ |
||||
using System; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Collections.Generic; |
||||
using Godot; |
||||
using File = System.IO.File; |
||||
|
||||
public class WorldSave |
||||
{ |
||||
public const string FILE_EXT = ".yf5"; |
||||
public const int MAGIC_NUMBER = 0x59463573; // "YF5s" |
||||
public const int LATEST_VERSION = 0; |
||||
|
||||
public static readonly string WORLDS_DIR = OS.GetUserDataDir() + "/worlds/"; |
||||
|
||||
|
||||
public DateTime LastSaved { get; private set; } |
||||
public int Version { get; private set; } = LATEST_VERSION; |
||||
public TimeSpan Playtime { get; set; } = TimeSpan.Zero; |
||||
|
||||
public List<(BlockPos, Color, bool)> Blocks { get; private set; } |
||||
|
||||
|
||||
public static WorldSave ReadFromFile(string path) |
||||
{ |
||||
var save = new WorldSave { LastSaved = File.GetLastAccessTime(path) }; |
||||
using (var stream = File.OpenRead(path)) { |
||||
using (var reader = new BinaryReader(stream)) { |
||||
var magic = reader.ReadInt32(); |
||||
if (magic != MAGIC_NUMBER) throw new IOException( |
||||
$"Magic number does not match ({magic:X8} != {MAGIC_NUMBER:X8})"); |
||||
|
||||
// TODO: See how to support multiple versions. |
||||
save.Version = reader.ReadUInt16(); |
||||
if (save.Version != LATEST_VERSION) throw new IOException( |
||||
$"Version does not match ({save.Version} != {LATEST_VERSION})"); |
||||
|
||||
save.Playtime = TimeSpan.FromSeconds(reader.ReadUInt32()); |
||||
|
||||
var numBlocks = reader.ReadInt32(); |
||||
save.Blocks = new List<(BlockPos, Color, bool)>(); |
||||
for (var i = 0; i < numBlocks; i++) |
||||
save.Blocks.Add((new BlockPos(reader.ReadInt32(), reader.ReadInt32()), |
||||
new Color(reader.ReadInt32()), |
||||
reader.ReadBoolean())); |
||||
} |
||||
} |
||||
return save; |
||||
} |
||||
|
||||
public void WriteToFile(string path) |
||||
{ |
||||
using (var stream = File.OpenWrite(path + ".tmp")) { |
||||
using (var writer = new BinaryWriter(stream)) { |
||||
writer.Write(MAGIC_NUMBER); |
||||
writer.Write((ushort)LATEST_VERSION); |
||||
writer.Write((uint)Playtime.TotalSeconds); |
||||
|
||||
writer.Write(Blocks.Count); |
||||
foreach (var (position, color, unbreakable) in Blocks) { |
||||
writer.Write(position.X); |
||||
writer.Write(position.Y); |
||||
writer.Write(color.ToRgba32()); |
||||
writer.Write(unbreakable); |
||||
} |
||||
} |
||||
} |
||||
new Godot.Directory().Rename(path + ".tmp", path); |
||||
LastSaved = File.GetLastWriteTime(path); |
||||
} |
||||
|
||||
|
||||
public void WriteDataFromWorld(World world) |
||||
=> Blocks = world.Blocks.Select(block => (block.Position, block.Color, block.Unbreakable)).ToList(); |
||||
|
||||
public void ReadDataIntoWorld(World world) |
||||
{ |
||||
world.Rpc(nameof(World.ClearBlocks)); |
||||
foreach (var (position, color, unbreakable) in Blocks) |
||||
world.Rpc(nameof(World.SpawnBlock), position.X, position.Y, color, unbreakable); |
||||
} |
||||
} |
Loading…
Reference in new issue