diff options
| author | RogueAI42 <[email protected]> | 2017-11-06 01:49:59 +1100 |
|---|---|---|
| committer | RogueAI42 <[email protected]> | 2017-11-06 01:49:59 +1100 |
| commit | 6e0a3f7f98033bd6a0cc11545433e80a19329af8 (patch) | |
| tree | e7f88b447dfa709c153e89cda4e79641f31ba603 | |
| parent | f0e2d14a959db1e5d35c4dc5f77ed3523c93200a (diff) | |
| download | histacom2-6e0a3f7f98033bd6a0cc11545433e80a19329af8.tar.gz histacom2-6e0a3f7f98033bd6a0cc11545433e80a19329af8.tar.bz2 histacom2-6e0a3f7f98033bd6a0cc11545433e80a19329af8.zip | |
clean up my old junk from save system
| -rw-r--r-- | Histacom2.Engine/Histacom2.Engine.csproj | 3 | ||||
| -rw-r--r-- | Histacom2.Engine/SaveSystem.cs | 307 | ||||
| -rw-r--r-- | Histacom2.Engine/packages.config | 1 | ||||
| -rw-r--r-- | Histacom2/SaveDialogs/SaveFileTroubleShooter.cs | 12 |
4 files changed, 28 insertions, 295 deletions
diff --git a/Histacom2.Engine/Histacom2.Engine.csproj b/Histacom2.Engine/Histacom2.Engine.csproj index 1d36223..69443b1 100644 --- a/Histacom2.Engine/Histacom2.Engine.csproj +++ b/Histacom2.Engine/Histacom2.Engine.csproj @@ -44,6 +44,9 @@ <Reference Include="System.Data" /> <Reference Include="System.Net.Http" /> <Reference Include="System.Xml" /> + <Reference Include="Whoa, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\Whoa.1.5.0\lib\net45\Whoa.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <Compile Include="BSODCreator.cs" /> diff --git a/Histacom2.Engine/SaveSystem.cs b/Histacom2.Engine/SaveSystem.cs index a3fd2ef..b4cd56f 100644 --- a/Histacom2.Engine/SaveSystem.cs +++ b/Histacom2.Engine/SaveSystem.cs @@ -2,7 +2,7 @@ // to put some effort into cheating ;) // During development, leave it undefined to use the // easily modifiable JSON serialised format -//#define BINARY_SAVE +#define BINARY_SAVE using System; using System.Collections.Generic; @@ -18,6 +18,10 @@ using System.Drawing; using System.Text.RegularExpressions; using System.Runtime.InteropServices; +#if BINARY_SAVE +using Whoa; +#endif + namespace Histacom2.Engine { public static class SaveSystem @@ -36,8 +40,7 @@ namespace Histacom2.Engine #endif #if BINARY_SAVE - private static readonly byte[] magic = Encoding.UTF8.GetBytes("THSv"); - private static readonly IOrderedEnumerable<System.Reflection.PropertyInfo> properties = typeof(Save).GetProperties().OrderBy(p => (p.GetCustomAttributes(typeof(OrderAttribute), false).SingleOrDefault() as OrderAttribute).Order); + private static readonly int magic = 0x76534854; // 'THSv' #endif public static string GameDirectory @@ -65,7 +68,11 @@ namespace Histacom2.Engine } public static string ProfileName = ""; - public static string ProfileFile = "main.save"; +#if BINARY_SAVE + public static string ProfileFile = "main.whoa"; +#else + public static string ProfileFile = "main.json"; +#endif public static string ProfileDirectory { @@ -404,162 +411,15 @@ namespace Histacom2.Engine File.WriteAllText(Path.Combine(Path.Combine(parent, dirname), "_data.info"), toWrite); } -#if BINARY_SAVE - // Be careful with this... it trusts that the calling code has already checked - // that T can be written by BinaryWriter. - // No generics, because that'd be near-impossible to read back. - private static void WriteList<T>(BinaryWriter write, List<T> list) - { - if (list == null) - write.Write(0); - else - { - write.Write(list.Count); - foreach (T obj in list) - ((dynamic)write).Write(obj); - } - } - - private static List<T> ReadList<T>(BinaryReader read, string reader) - { - int count = read.ReadInt32(); - var ret = new List<T>(count); - var function = typeof(BinaryReader).GetMethod(reader); - for (int i = 0; i < count; i++) - ret.Add((T) function.Invoke(read, new object[] { })); - return ret; - } - - private static void WriteBitfield(Stream fobj, IEnumerable<bool> bools) - { - sbyte bit = 7; - int cur = 0; - var bitfields = new byte[bools.Count() / 8 + 1]; - foreach (bool mybool in bools) - { - if (mybool) - bitfields[cur] |= (byte) (1 << bit); - bit--; - if (bit < 0) - { - bit = 7; - cur++; - } - } - fobj.Write(bitfields, 0, bitfields.Length); - } - - private static List<bool> ReadBitfield(Stream fobj, int count) - { - sbyte bit = 7; - int cur = 0; - var bitfields = new byte[count / 8 + 1]; - var bools = new List<bool>(count); - byte val = (byte) fobj.ReadByte(); - fobj.Read(bitfields, 0, bitfields.Length); - for (int i = 0; i < count; i++) - { - bools.Add(((val >> bit) & 1) == 1); - bit--; - if (bit < 0) - { - bit = 7; - cur++; - } - } - return bools; - } -#endif - public static Save ReadSave(string fname) { #if BINARY_SAVE using (var fobj = File.OpenRead(fname)) + using (var read = new BinaryReader(fobj)) { - var save = new Save(); - var header = new byte[magic.Length]; - var read = new BinaryReader(fobj); - fobj.Read(header, 0, magic.Length); - if (!magic.SequenceEqual(header)) + if (read.ReadInt32() != magic) throw new InvalidDataException("This is not a Histacom2 binary save"); - int numprops = read.ReadInt32(); - var bools = new List<System.Reflection.PropertyInfo>(); - // Holy code duplication, Batman. - // If you know a better way to get C# to do this, I'm all ears. - foreach (var property in properties.Take(numprops)) - { - if (property.PropertyType == typeof(string)) - property.SetValue(save, read.ReadString()); - else if (property.PropertyType == typeof(int)) - property.SetValue(save, read.ReadInt32()); - else if (property.PropertyType == typeof(uint)) - property.SetValue(save, read.ReadUInt32()); - else if (property.PropertyType == typeof(long)) - property.SetValue(save, read.ReadInt64()); - else if (property.PropertyType == typeof(ulong)) - property.SetValue(save, read.ReadUInt64()); - else if (property.PropertyType == typeof(short)) - property.SetValue(save, read.ReadInt16()); - else if (property.PropertyType == typeof(ushort)) - property.SetValue(save, read.ReadUInt16()); - else if (property.PropertyType == typeof(byte)) - property.SetValue(save, read.ReadByte()); - else if (property.PropertyType == typeof(sbyte)) - property.SetValue(save, read.ReadSByte()); - else if (property.PropertyType == typeof(char)) - property.SetValue(save, read.ReadChar()); - else if (property.PropertyType == typeof(float)) - property.SetValue(save, read.ReadSingle()); - else if (property.PropertyType == typeof(double)) - property.SetValue(save, read.ReadDouble()); - else if (property.PropertyType == typeof(decimal)) - property.SetValue(save, read.ReadDecimal()); - - else if (property.PropertyType == typeof(List<string>)) - property.SetValue(save, ReadList<string>(read, "ReadString")); - else if (property.PropertyType == typeof(List<int>)) - property.SetValue(save, ReadList<string>(read, "ReadInt32")); - else if (property.PropertyType == typeof(List<uint>)) - property.SetValue(save, ReadList<string>(read, "ReadUInt32")); - else if (property.PropertyType == typeof(List<long>)) - property.SetValue(save, ReadList<string>(read, "ReadInt64")); - else if (property.PropertyType == typeof(List<ulong>)) - property.SetValue(save, ReadList<string>(read, "ReadUInt64")); - else if (property.PropertyType == typeof(List<short>)) - property.SetValue(save, ReadList<string>(read, "ReadInt16")); - else if (property.PropertyType == typeof(List<ushort>)) - property.SetValue(save, ReadList<string>(read, "ReadUInt16")); - else if (property.PropertyType == typeof(List<byte>)) - property.SetValue(save, ReadList<string>(read, "ReadByte")); - else if (property.PropertyType == typeof(List<sbyte>)) - property.SetValue(save, ReadList<string>(read, "ReadSByte")); - else if (property.PropertyType == typeof(List<char>)) - property.SetValue(save, ReadList<string>(read, "ReadChar")); - else if (property.PropertyType == typeof(List<float>)) - property.SetValue(save, ReadList<string>(read, "ReadSingle")); - else if (property.PropertyType == typeof(List<double>)) - property.SetValue(save, ReadList<string>(read, "ReadDouble")); - else if (property.PropertyType == typeof(List<decimal>)) - property.SetValue(save, ReadList<string>(read, "ReadDecimal")); - - // Remember to read this boolean from the bitfield at the end. - else if (property.PropertyType == typeof(bool)) - bools.Add(property); - - else if (property.PropertyType == typeof(List<bool>)) - property.SetValue(save, ReadBitfield(fobj, read.ReadInt32())); - - // RIP - else - throw new InvalidDataException("There is no deserialisation method specified for " + property.PropertyType.ToString()); - } - - // Let's read the ultra tiny bitfield. - var loaded = ReadBitfield(fobj, bools.Count); - foreach (var item in bools.Zip(loaded, (p, b) => new { Property = p, Value = b })) - item.Property.SetValue(save, item.Value); - - return save; + return Whoa.Whoa.DeserialiseObject<Save>(fobj, SerialisationOptions.NonSerialized); } #else return JsonConvert.DeserializeObject<Save>(File.ReadAllText(fname)); @@ -570,105 +430,10 @@ namespace Histacom2.Engine { #if BINARY_SAVE using (var fobj = File.OpenWrite(fname)) + using (var write = new BinaryWriter(fobj)) { - var write = new BinaryWriter(fobj); - var bools = new List<bool>(); - fobj.Write(magic, 0, magic.Length); - write.Write(properties.Count()); // The number of properties basically acts as the version number. - - foreach (var property in properties) - { - if (property == null) - continue; - - // Types that can be written by BinaryWriter, except booleans. - if (property.PropertyType == typeof(string)) - { - var val = property.GetValue(save) as string; - if (val == null) - write.Write(""); - else - write.Write(val); - } - else if (property.PropertyType == typeof(int)) - write.Write((int) property.GetValue(save)); - else if (property.PropertyType == typeof(uint)) - write.Write((uint) property.GetValue(save)); - else if (property.PropertyType == typeof(long)) - write.Write((long) property.GetValue(save)); - else if (property.PropertyType == typeof(ulong)) - write.Write((ulong) property.GetValue(save)); - else if (property.PropertyType == typeof(short)) - write.Write((short) property.GetValue(save)); - else if (property.PropertyType == typeof(ushort)) - write.Write((ushort) property.GetValue(save)); - else if (property.PropertyType == typeof(byte)) - write.Write((byte) property.GetValue(save)); - else if (property.PropertyType == typeof(sbyte)) - write.Write((sbyte) property.GetValue(save)); - else if (property.PropertyType == typeof(char)) - write.Write((char) property.GetValue(save)); - else if (property.PropertyType == typeof(float)) - write.Write((float) property.GetValue(save)); - else if (property.PropertyType == typeof(double)) - write.Write((double) property.GetValue(save)); - else if (property.PropertyType == typeof(decimal)) - write.Write((double) property.GetValue(save)); - - // ... and their lists. - else if (property.PropertyType == typeof(List<string>)) - WriteList(write, property.GetValue(save) as List<string>); - else if (property.PropertyType == typeof(List<int>)) - WriteList(write, property.GetValue(save) as List<int>); - else if (property.PropertyType == typeof(List<uint>)) - WriteList(write, property.GetValue(save) as List<uint>); - else if (property.PropertyType == typeof(List<long>)) - WriteList(write, property.GetValue(save) as List<long>); - else if (property.PropertyType == typeof(List<ulong>)) - WriteList(write, property.GetValue(save) as List<ulong>); - else if (property.PropertyType == typeof(List<short>)) - WriteList(write, property.GetValue(save) as List<short>); - else if (property.PropertyType == typeof(List<ushort>)) - WriteList(write, property.GetValue(save) as List<ushort>); - else if (property.PropertyType == typeof(List<byte>)) - WriteList(write, property.GetValue(save) as List<byte>); - else if (property.PropertyType == typeof(List<sbyte>)) - WriteList(write, property.GetValue(save) as List<sbyte>); - else if (property.PropertyType == typeof(List<char>)) - WriteList(write, property.GetValue(save) as List<char>); - else if (property.PropertyType == typeof(List<float>)) - WriteList(write, property.GetValue(save) as List<float>); - else if (property.PropertyType == typeof(List<double>)) - WriteList(write, property.GetValue(save) as List<double>); - else if (property.PropertyType == typeof(List<decimal>)) - WriteList(write, property.GetValue(save) as List<decimal>); - - // Booleans - they go in the bitfield at the end. - else if (property.PropertyType == typeof(bool)) - bools.Add((bool) property.GetValue(save)); - - // List of booleans - it gets its own bitfield. - else if (property.PropertyType == typeof(List<bool>)) - { - var val = property.GetValue(save) as List<bool>; - if (val == null) - write.Write(0); - else - { - write.Write(val.Count()); - WriteBitfield(fobj, val); - } - } - - // Now what? - else - throw new InvalidDataException("There is no serialisation method specified for " + property.PropertyType.ToString()); - } - - // In order to save space, we store bools in a bitfield at the end. - // One byte can store 8 bools, saving a whopping 7 bytes which can then be used for - // extremely short text documents or something. - WriteBitfield(fobj, bools); + write.Write(magic); + Whoa.Whoa.SerialiseObject(fobj, save, SerialisationOptions.NonSerialized); } #else // Serialize the save to JSON. @@ -772,61 +537,25 @@ namespace Histacom2.Engine } } - - // This lets us preserve the order of properties. - // Thanks to "ghord" from StackOverflow. - public sealed class OrderAttribute : Attribute - { - private readonly int order_; - public OrderAttribute([CallerLineNumber]int order = 0) - { - order_ = order; - } - public int Order { get { return order_; } } - } - public class Save { // To maintain binary save compatibility, - // add all new properties to the end and don't remove any. - // Also, every property needs an "Order" attribute. + // add all new properties/fields to the end and don't remove any. - [Order] public string Username { get; set; } - - [Order] public string CurrentOS { get; set; } // public Dictionary<string, bool> InstalledPrograms { get; set; } InstallProgram is no longer needed... we have that data in the FileSystem - [Order] public List<string> ExperiencedStories { get; set; } - - [Order] public bool FTime95 { get; set; } - - [Order] public int mineSweepE { get; set; } = 999; - - [Order] public int mineSweepI { get; set; } = 999; - - [Order] public int mineSweepH { get; set; } = 999; - - [Order] public string ThemeName { get; set; } - - [Order] public int BytesLeft { get; set; } - - [Order] public Theme customTheme { get; set; } - - [Order] public bool FTime98 { get; set; } - - [Order] public bool[] installed95 { get; set; } = new bool[7]; // 0: WC98, 1: FTP, 2: SR, 3: EB, 4: SKNDWS, 5: TD0.1, 6: GTN } diff --git a/Histacom2.Engine/packages.config b/Histacom2.Engine/packages.config index 810e559..de52fcd 100644 --- a/Histacom2.Engine/packages.config +++ b/Histacom2.Engine/packages.config @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net452" /> + <package id="Whoa" version="1.5.0" targetFramework="net452" /> </packages>
\ No newline at end of file diff --git a/Histacom2/SaveDialogs/SaveFileTroubleShooter.cs b/Histacom2/SaveDialogs/SaveFileTroubleShooter.cs index 3283ca1..7fe258f 100644 --- a/Histacom2/SaveDialogs/SaveFileTroubleShooter.cs +++ b/Histacom2/SaveDialogs/SaveFileTroubleShooter.cs @@ -42,12 +42,12 @@ namespace Histacom2.SaveDialogs // Check if the main.save file exists - string savefile = Path.Combine(SaveSystem.ProfileDirectory, "main.save"); - string oldsavefile = Path.Combine(SaveSystem.ProfileDirectory, "oldmain.save"); + string savefile = Path.Combine(SaveSystem.ProfileDirectory, SaveSystem.ProfileFile); + string oldsavefile = Path.Combine(SaveSystem.ProfileDirectory, "old" + SaveSystem.ProfileFile); if (!File.Exists(savefile)) { - WriteToLog("ISSUE FOUND! File main.save doesn't exist"); + WriteToLog($"ISSUE FOUND! File {SaveSystem.ProfileFile} doesn't exist"); WriteToLog("Creating one..."); @@ -58,7 +58,7 @@ namespace Histacom2.SaveDialogs EndScan(true); return; } else { - WriteToLog("File main.save does exist - checking contents"); + WriteToLog($"File {SaveSystem.ProfileFile} does exist - checking contents"); bool readable = false; try @@ -136,11 +136,11 @@ namespace Histacom2.SaveDialogs } catch { // It's unusable... - WriteToLog("ISSUE FOUND! File main.save is unreadable"); + WriteToLog($"ISSUE FOUND! File {SaveSystem.ProfileFile} is unreadable"); WriteToLog("Sorry, there is no repairing it easily, your data will be lost"); - string backupfile = Path.Combine(SaveSystem.ProfileDirectory, "main.backup"); + string backupfile = savefile + ".bak"; if (Directory.Exists(backupfile)) Directory.Delete(backupfile); |
