aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRogueAI42 <[email protected]>2017-07-23 22:09:41 +1000
committerRogueAI42 <[email protected]>2017-07-23 22:09:41 +1000
commitbc9623bbdf635cc16cc95f8a86a241a6933a8fdd (patch)
treeb9e2c5f7861799b7b5f209046f97052493565734
parentc446a76e0c5b7b35638f1e223ad167b46f30941e (diff)
downloadhistacom2-bc9623bbdf635cc16cc95f8a86a241a6933a8fdd.tar.gz
histacom2-bc9623bbdf635cc16cc95f8a86a241a6933a8fdd.tar.bz2
histacom2-bc9623bbdf635cc16cc95f8a86a241a6933a8fdd.zip
i goofed
This reverts commit c446a76e0c5b7b35638f1e223ad167b46f30941e.
-rw-r--r--TimeHACK.Engine/SaveSystem.cs370
-rw-r--r--TimeHACK.Main/SaveDialogs/SaveFileTroubleShooter.cs27
2 files changed, 55 insertions, 342 deletions
diff --git a/TimeHACK.Engine/SaveSystem.cs b/TimeHACK.Engine/SaveSystem.cs
index cda4464..81aa322 100644
--- a/TimeHACK.Engine/SaveSystem.cs
+++ b/TimeHACK.Engine/SaveSystem.cs
@@ -1,10 +1,4 @@
-// Define BINARY_SAVE before release so the player has
-// to put some effort into cheating ;)
-// During development, leave it undefined to use the
-// easily modifiable JSON serialised format
-//#define BINARY_SAVE
-
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -13,7 +7,6 @@ using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Windows.Forms;
-using System.Runtime.CompilerServices;
namespace TimeHACK.Engine
{
@@ -26,11 +19,6 @@ namespace TimeHACK.Engine
public static Theme currentTheme { get; set; }
-#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);
-#endif
-
public static string GameDirectory
{
get
@@ -114,6 +102,36 @@ namespace TimeHACK.Engine
}
}
+ public static bool LoadSave()
+ {
+ try
+ {
+ // ON A FINAL RELEASE USE THE "FINAL RELEASE THINGS"
+ #region Final Release Things
+ //Read base64 string from file
+ //string b64 = File.ReadAllText(Path.Combine(ProfileDirectory, ProfileFile));
+ //Get Unicode byte array
+ //byte[] bytes = Convert.FromBase64String(b64);
+ //Decode the Unicode
+ //string json = Encoding.UTF8.GetString(bytes);
+ //Deserialize save object.
+ #endregion
+ // USE THE THINGS IN THE "DEVELOPER THINGS" FOR A DEVELOPMENT RELEASE
+ #region Developer Things
+ string json = File.ReadAllText(Path.Combine(ProfileDirectory, ProfileFile));
+ #endregion
+ CurrentSave = JsonConvert.DeserializeObject<Save>(json);
+
+ } catch
+ {
+ MessageBox.Show("WARNING! It looks like this save is corrupt!");
+ MessageBox.Show("We will now open the Save troubleshooter");
+
+ troubleshooter.ShowDialog();
+ }
+ return true;
+ }
+
public static void NewGame()
{
var save = new Save();
@@ -229,297 +247,21 @@ namespace TimeHACK.Engine
File.WriteAllText(Path.Combine(directory, "_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))
- {
- 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))
- throw new InvalidDataException("This is not a TimeHACK 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;
- }
-#else
- return JsonConvert.DeserializeObject<Save>(File.ReadAllText(fname));
-#endif
- }
-
- public static void WriteSave(string fname, Save save)
- {
-#if BINARY_SAVE
- using (var fobj = File.OpenWrite(fname))
- {
- 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);
- }
-#else
- // Serialize the save to JSON.
- File.WriteAllText(fname, JsonConvert.SerializeObject(save, Formatting.Indented));
-#endif
- }
public static void SaveGame()
{
- WriteSave(Path.Combine(ProfileDirectory, ProfileFile), CurrentSave);
- }
-
- public static bool LoadSave()
- {
- string savefile = Path.Combine(ProfileDirectory, ProfileFile);
- try
- {
- CurrentSave = ReadSave(savefile);
- }
- catch
- {
- MessageBox.Show("WARNING! It looks like this save is corrupt! We will now open the Save troubleshooter");
-
- troubleshooter.ShowDialog();
- }
- return true;
+ //Serialize the save to JSON.
+ string json = JsonConvert.SerializeObject(CurrentSave, Formatting.Indented);
+
+ // ADD THE TWO LINES OF CODE BELOW ON A FINAL RELEASE
+ //Get JSON bytes (Unicode format).
+ //var bytes = Encoding.UTF8.GetBytes(json);
+ //Encode the array into Base64.
+ //string b64 = Convert.ToBase64String(bytes);
+ //Write to disk.
+
+ // CHANGE THE "JSON" TO "B64" ON A FINAL RELEASE!
+ File.WriteAllText(Path.Combine(ProfileDirectory, ProfileFile), json);
}
public static byte[] GetAchievements()
@@ -553,40 +295,14 @@ namespace TimeHACK.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.
-
- [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 string ThemeName { get; set; }
}
diff --git a/TimeHACK.Main/SaveDialogs/SaveFileTroubleShooter.cs b/TimeHACK.Main/SaveDialogs/SaveFileTroubleShooter.cs
index 410d2d6..5ec84be 100644
--- a/TimeHACK.Main/SaveDialogs/SaveFileTroubleShooter.cs
+++ b/TimeHACK.Main/SaveDialogs/SaveFileTroubleShooter.cs
@@ -15,7 +15,7 @@ namespace TimeHACK.SaveDialogs
public partial class SaveFileTroubleShooter : Form
{
public string log;
- Save savedata;
+ Save savedata = new Save();
string json;
public SaveFileTroubleShooter()
{
@@ -43,9 +43,7 @@ namespace TimeHACK.SaveDialogs
// Check if the main.save file exists
- string savefile = Path.Combine(SaveSystem.ProfileDirectory, "main.save");
-
- if (!File.Exists(savefile))
+ if (!File.Exists(Path.Combine(SaveSystem.ProfileDirectory, "main.save")))
{
WriteToLog("ISSUE FOUND! File main.save doesn't exist");
@@ -60,9 +58,12 @@ namespace TimeHACK.SaveDialogs
} else {
WriteToLog("File main.save does exist - checking contents");
+ // Read the main.save file
+ json = File.ReadAllText(Path.Combine(SaveSystem.ProfileDirectory, "main.save"));
+
try
{
- savedata = SaveSystem.ReadSave(savefile);
+ savedata = Newtonsoft.Json.JsonConvert.DeserializeObject<Save>(json);
} catch
{
@@ -70,18 +71,16 @@ namespace TimeHACK.SaveDialogs
WriteToLog("Sorry, there is no repairing it easily, your data will be lost");
- string backupfile = Path.Combine(SaveSystem.ProfileDirectory, "main.backup");
+ if (Directory.Exists(Path.Combine(SaveSystem.ProfileDirectory, "main.backup"))) Directory.Delete(Path.Combine(SaveSystem.ProfileDirectory, "main.backup"));
- if (Directory.Exists(backupfile)) Directory.Delete(backupfile);
-
- File.Copy(savefile, backupfile);
+ File.Copy(Path.Combine(SaveSystem.ProfileDirectory, "main.save"), Path.Combine(SaveSystem.ProfileDirectory, "main.backup"));
SaveSystem.NewGame();
// Make sure the username is set
SaveSystem.CurrentSave.Username = SaveSystem.ProfileName;
- WriteToLog($"The corrupt file has been stored in {backupfile}");
+ WriteToLog($"The corrupt file has been stored in {Path.Combine(SaveSystem.ProfileDirectory, "main.backup")}");
EndScan(true);
}
@@ -109,12 +108,10 @@ namespace TimeHACK.SaveDialogs
}
}
- string folderspath = Path.Combine(SaveSystem.ProfileDirectory, "folders");
-
- if (!Directory.Exists(folderspath))
+ if (!Directory.Exists(Path.Combine(SaveSystem.ProfileDirectory, "folders")))
{
WriteToLog("ISSUE FOUND! Directory 'folders' doesn't exist! Creating one...");
- Directory.CreateDirectory(folderspath);
+ Directory.CreateDirectory(Path.Combine(SaveSystem.ProfileDirectory, "folders"));
SaveSystem.CheckFiles();
}
@@ -133,7 +130,7 @@ namespace TimeHACK.SaveDialogs
// Set the main.save file to the resolved one
- SaveSystem.WriteSave(Path.Combine(SaveSystem.ProfileDirectory, "main.save"), savedata);
+ File.WriteAllText(Path.Combine(SaveSystem.ProfileDirectory, "main.save"), Newtonsoft.Json.JsonConvert.SerializeObject(savedata, Newtonsoft.Json.Formatting.Indented));
textBox1.Text = log;
} else {