From 30bcbc42dce32bb81134fff66f91f36298d38073 Mon Sep 17 00:00:00 2001 From: jxjacob <4712066+jxjacob@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:18:43 -0400 Subject: [PATCH] FIX THE MEMORY LEAK AT LONG LAST we love process handles we love process handles --- GSTHD/AttachToEmulator.cs | 31 ++-- GSTHD/Autotracker.cs | 327 ++++++++++++++++++++++++++----------- GSTHD/CollectedItem.cs | 5 +- GSTHD/ControlExtensions.cs | 4 - GSTHD/Form1.cs | 189 ++++++++++++++++++--- GSTHD/Form1_MenuBar.cs | 49 +++++- GSTHD/Form2.cs | 5 +- GSTHD/GossipStone.cs | 145 +++++++++------- GSTHD/Item.cs | 6 +- GSTHD/Layout.cs | 28 +++- GSTHD/Memory.cs | 28 ++-- GSTHD/PanelWothBarren.cs | 1 + GSTHD/Program.cs | 10 +- GSTHD/Settings.cs | 2 + GSTHD/WotH.cs | 6 + 15 files changed, 597 insertions(+), 239 deletions(-) diff --git a/GSTHD/AttachToEmulator.cs b/GSTHD/AttachToEmulator.cs index fb0997f..51b5523 100644 --- a/GSTHD/AttachToEmulator.cs +++ b/GSTHD/AttachToEmulator.cs @@ -57,7 +57,7 @@ public static Tuple attachToProject64(Form1 baseForm, bool doOffs if (gameInfo.Item2 == 8) { uint addr = Memory.Int8AddrFix(gameInfo.Item1); - if (Memory.ReadInt8(target, potOff + addr) == gameInfo.Item3) + if (Memory.ReadInt8(target.Handle, potOff + addr) == gameInfo.Item3) { Debug.WriteLine(potOff.ToString("X")); romAddrStart = potOff; @@ -67,7 +67,7 @@ public static Tuple attachToProject64(Form1 baseForm, bool doOffs else if (gameInfo.Item2 == 16) { uint addr = Memory.Int16AddrFix(gameInfo.Item1); - if (Memory.ReadInt16(target, potOff + addr) == gameInfo.Item3) + if (Memory.ReadInt16(target.Handle, potOff + addr) == gameInfo.Item3) { Debug.WriteLine(potOff.ToString("X")); romAddrStart = potOff; @@ -76,7 +76,7 @@ public static Tuple attachToProject64(Form1 baseForm, bool doOffs } else if (gameInfo.Item2 == 32) { - if (Memory.ReadInt32(target, potOff + gameInfo.Item1) == gameInfo.Item3) + if (Memory.ReadInt32(target.Handle, potOff + gameInfo.Item1) == gameInfo.Item3) { Debug.WriteLine(potOff.ToString("X")); romAddrStart = potOff; @@ -93,11 +93,6 @@ public static Tuple attachToProject64(Form1 baseForm, bool doOffs return Tuple.Create(target, romAddrStart); } - //for (int i = 0; i < 4; i++) - //{ - // switch (i) - // { - for (uint potOff = 0xDFD00000; potOff < 0xE01FFFFF; potOff += 16) { @@ -123,16 +118,16 @@ public static Tuple attachToProject64(Form1 baseForm, bool doOffs if (gameInfo.Item2 == 8) { uint addr = Memory.Int8AddrFix(gameInfo.Item1); - gamecheck = Memory.ReadInt8(target, romAddrStart + addr); + gamecheck = Memory.ReadInt8(target.Handle, romAddrStart + addr); } else if (gameInfo.Item2 == 16) { uint addr = Memory.Int16AddrFix(gameInfo.Item1); - gamecheck = Memory.ReadInt16(target, romAddrStart + addr); + gamecheck = Memory.ReadInt16(target.Handle, romAddrStart + addr); } else if (gameInfo.Item2 == 32) { - gamecheck = Memory.ReadInt32(target, romAddrStart + gameInfo.Item1); + gamecheck = Memory.ReadInt32(target.Handle, romAddrStart + gameInfo.Item1); } else { @@ -227,16 +222,16 @@ public static Tuple attachToBizhawk(Form1 baseForm) if (gameInfo.Item2 == 8) { uint addr = Memory.Int8AddrFix(gameInfo.Item1); - gamecheck = Memory.ReadInt8(target, romAddrStart + addr); + gamecheck = Memory.ReadInt8(target.Handle, romAddrStart + addr); } else if (gameInfo.Item2 == 16) { uint addr = Memory.Int16AddrFix(gameInfo.Item1); - gamecheck = Memory.ReadInt16(target, romAddrStart + addr); + gamecheck = Memory.ReadInt16(target.Handle, romAddrStart + addr); } else if (gameInfo.Item2 == 32) { - gamecheck = Memory.ReadInt32(target, (uint)(addressDLL + romAddrStart + gameInfo.Item1)); + gamecheck = Memory.ReadInt32(target.Handle, (uint)(addressDLL + romAddrStart + gameInfo.Item1)); } else { @@ -309,12 +304,12 @@ public static Tuple attachToRMG(Form1 baseForm) // read the address to find the address of the starting point in the rom - ulong readAddress = Memory.ReadInt64(target, (romAddrStart)); + ulong readAddress = Memory.ReadInt64(target.Handle, (romAddrStart)); if (gameInfo.Item2 == 8) { var addr = Memory.Int8AddrFix(readAddress + 0x80000000 + gameInfo.Item1); - var wherethefuck = Memory.ReadInt8(target, addr); + var wherethefuck = Memory.ReadInt8(target.Handle, addr); if ((wherethefuck & 0xff) == gameInfo.Item3) { return Tuple.Create(target, (readAddress + 0x80000000)); @@ -324,7 +319,7 @@ public static Tuple attachToRMG(Form1 baseForm) else if (gameInfo.Item2 == 16) { var addr = Memory.Int16AddrFix(readAddress + 0x80000000 + gameInfo.Item1); - var wherethefuck = Memory.ReadInt16(target, addr); + var wherethefuck = Memory.ReadInt16(target.Handle, addr); if ((wherethefuck & 0xffff) == gameInfo.Item3) { return Tuple.Create(target, (readAddress + 0x80000000)); @@ -334,7 +329,7 @@ public static Tuple attachToRMG(Form1 baseForm) else if (gameInfo.Item2 == 32) { // use this previously read address to find the game verification data - var wherethefuck = Memory.ReadInt32(target, (readAddress + 0x80000000 + gameInfo.Item1)); + var wherethefuck = Memory.ReadInt32(target.Handle, (readAddress + 0x80000000 + gameInfo.Item1)); if ((wherethefuck & 0xffffffff) == gameInfo.Item3) { return Tuple.Create(target, (readAddress + 0x80000000)); diff --git a/GSTHD/Autotracker.cs b/GSTHD/Autotracker.cs index 401c324..c4f514d 100644 --- a/GSTHD/Autotracker.cs +++ b/GSTHD/Autotracker.cs @@ -11,6 +11,8 @@ using System.Xml.Linq; using System.Runtime.InteropServices; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Tab; +using System.Net.NetworkInformation; +using System.Timers; namespace GSTHD { @@ -25,6 +27,7 @@ public class TrackedAddress public int offset; public string type; public string group; + public Control targetControl; } public class TrackedGroup { @@ -34,10 +37,12 @@ public class TrackedGroup public int count = 0; public int countMax; public bool isDouble = false; + public Control targetControl; } public class Autotracker : UpdatableFromSettings { private Process emulator; + private IntPtr emuHandle; private uint offset; private ulong offset64; @@ -52,7 +57,7 @@ public class Autotracker : UpdatableFromSettings private int desiredGameStateBytes; private uint desiredGameStateValue; - private System.Threading.Timer timer; + private System.Timers.Timer timer; private Form1 form; private int timeout; @@ -62,6 +67,7 @@ public class Autotracker : UpdatableFromSettings public Autotracker(Process theProgram, uint foundOffset, ref Form1 theForm) { emulator = theProgram; + emuHandle = emulator.Handle; offset = foundOffset; form = theForm; form.CurrentLayout.ListUpdatables.Add(this); @@ -71,7 +77,11 @@ public Autotracker(Process theProgram, uint foundOffset, ref Form1 theForm) SetGameStateTargets(form.CurrentLayout.App_Settings.AutotrackingGame); Debug.WriteLine("Beginning timer with " + trackedAddresses.Count + " addresses and " + trackedGroups.Count + " groups"); - timer = new System.Threading.Timer(MainTracker, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + //timer = new System.Threading.Timer(MainTracker, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + timer = new System.Timers.Timer(1000); + timer.Elapsed += MainTracker; + timer.AutoReset = true; + timer.Enabled = true; } } @@ -79,6 +89,7 @@ public Autotracker(Process theProgram, uint foundOffset, ref Form1 theForm) public Autotracker(Process theProgram, ulong foundOffset, Form1 theForm) { emulator = theProgram; + emuHandle = emulator.Handle; offset64 = foundOffset; form = theForm; form.CurrentLayout.ListUpdatables.Add(this); @@ -87,13 +98,138 @@ public Autotracker(Process theProgram, ulong foundOffset, Form1 theForm) if (form.CurrentLayout.App_Settings.AutotrackingGame != null) { SetGameStateTargets(form.CurrentLayout.App_Settings.AutotrackingGame); - + CalibrateTracks(); Debug.WriteLine("Beginning timer with " + trackedAddresses.Count + " addresses and " + trackedGroups.Count + " groups"); - timer = new System.Threading.Timer(MainTracker, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + //timer = new System.Threading.Timer(MainTracker, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + timer = new System.Timers.Timer(1000); + timer.Elapsed += MainTracker; + timer.AutoReset = true; + timer.Enabled = true; } } - private void MainTracker(object state) + private void CalibrateTracks() + { + // go through each address or group and store the controls that they are going to update so i can skip that godawful foreach controls for every single damn update + // also removes addresses without a counterpart on the layout + + var tac = new List(); + + foreach (TrackedAddress ta in trackedAddresses) + { + if (ta.group != "") + { + TrackedGroup result = trackedGroups.Find(x => x.name.Equals(ta.group)); + if (result.targetControl != null) + { + //Debug.WriteLine("group " + result.name + " already has a targetcontrol, skipping"); + continue; + } + foreach (Control thing in form.Controls[0].Controls) + { + if (thing is CollectedItem ci) + { + if (ci.AutoName == result.name) + { + result.targetControl = thing; + break; + } + else if (ci.AutoSubName == result.name && form.Settings.SubtractItems) + { + result.targetControl = thing; + break; + } + + } + else if (thing is DoubleItem di) + { + if (di.AutoName == result.name) + { + result.targetControl = thing; + break; + } + } + else if (thing is Item it) + { + if (it.AutoName == result.name) + { + result.targetControl = thing; + break; + } + + } + } + if (result.targetControl == null) + { + Debug.WriteLine("group " + result.name + " doesnt have a thing on the tracker"); + tac.Add(ta); + } + } else + { + foreach (Control thing in form.Controls[0].Controls) + { + if (ta.type == "item" && thing is Item it) + { + if (it.AutoName == ta.name) + { + ta.targetControl = thing; + break; + } + + } + else if (ta.type == "item" && thing is Medallion md) + { + if (md.AutoName == ta.name) + { + ta.targetControl = thing; + break; + } + + } + else if (ta.type == "item" && thing is Song sg) + { + if (sg.AutoName == ta.name) + { + ta.targetControl = thing; + break; + } + + } + else if (ta.type == "collectable" && thing is CollectedItem ci) + { + if (ci.AutoName == ta.name) + { + ta.targetControl = thing; + break; + } + + } + else if (ta.type == "collectable" && thing is Item it2) + { + if (it2.AutoName == ta.name) + { + ta.targetControl = thing; + break; + } + + } + } + if (ta.targetControl == null) + { + Debug.WriteLine("item " + ta.name + " doesnt have a thing on the tracker"); + tac.Add(ta); + } + } + + } + + foreach( var thing in tac) + { + trackedAddresses.Remove(thing); + } + } + + private void MainTracker(object state, ElapsedEventArgs e) { FlushGroups(); foreach (var ta in trackedAddresses) @@ -117,10 +253,10 @@ private void MainTracker(object state) if (result.isDouble) { if (ta.type == "doubleitem_l") { - result.runningvalue = result.runningvalue ^ 1; + result.runningvalue ^= 1; } else { - result.runningvalue = result.runningvalue ^ 2; + result.runningvalue ^= 2; } } else { @@ -158,11 +294,11 @@ public int GoRead(uint addr, int numOfBits) switch (numOfBits) { case 8: - return Memory.ReadInt8(emulator, offset + Memory.Int8AddrFix(addr)); + return Memory.ReadInt8(emuHandle, offset + Memory.Int8AddrFix(addr)); case 16: - return Memory.ReadInt16(emulator, offset + Memory.Int16AddrFix(addr)); + return Memory.ReadInt16(emuHandle, offset + Memory.Int16AddrFix(addr)); case 32: - return Memory.ReadInt32(emulator, offset + addr); + return Memory.ReadInt32(emuHandle, offset + addr); default: Debug.WriteLine("could not define how many bits to read"); return 0; @@ -172,11 +308,11 @@ public int GoRead(uint addr, int numOfBits) switch (numOfBits) { case 8: - return Memory.ReadInt8(emulator, offset64 + Memory.Int8AddrFix(addr)); + return Memory.ReadInt8(emuHandle, offset64 + Memory.Int8AddrFix(addr)); case 16: - return Memory.ReadInt16(emulator, offset64 + Memory.Int16AddrFix(addr)); + return Memory.ReadInt16(emuHandle, offset64 + Memory.Int16AddrFix(addr)); case 32: - return Memory.ReadInt32(emulator, offset64 + addr); + return Memory.ReadInt32(emuHandle, offset64 + addr); default: Debug.WriteLine("could not define how many bits to read"); return 0; @@ -189,54 +325,69 @@ private void UTSingle(TrackedAddress ta, int theRead) { if (ta.currentValue != theRead) { - - - // i can't fucking stand this method - foreach (Control thing in form.Controls[0].Controls) + if (ta.targetControl is Item it) { - if (ta.type == "item" && thing is Item) - { - if (((Item)thing).AutoName == ta.name) - { - UpdateTrackerItem((Item)thing, ta, theRead); - break; - } - - } else if (ta.type == "item" && thing is Medallion) - { - if (((Medallion)thing).AutoName == ta.name) - { - UpdateTrackerMedallion((Medallion)thing, ta, theRead); - break; - } - - } else if (ta.type == "item" && thing is Song) - { - if (((Song)thing).AutoName == ta.name) - { - UpdateTrackerSong((Song)thing, ta, theRead); - break; - } - - } - else if (ta.type == "collectable" && thing is CollectedItem) - { - if (((CollectedItem)thing).AutoName == ta.name) - { - UpdateTrackerCollectable((CollectedItem)thing, ta, theRead); - break; - } - - } else if (ta.type == "collectable" && thing is Item) - { - if (((Item)thing).AutoName == ta.name) - { - UpdateTrackerItem((Item)thing, ta, theRead); - break; - } - - } + UpdateTrackerItem(it, ta, theRead); + } + else if (ta.targetControl is Medallion md) + { + UpdateTrackerMedallion(md, ta, theRead); + } + else if(ta.targetControl is Song sg) + { + UpdateTrackerSong(sg, ta, theRead); + } + else if(ta.targetControl is CollectedItem ci) + { + UpdateTrackerCollectable(ci, ta, theRead); } + + // i can't fucking stand this method + //foreach (Control thing in form.Controls[0].Controls) + //{ + // if (ta.type == "item" && thing is Item) + // { + // if (((Item)thing).AutoName == ta.name) + // { + // UpdateTrackerItem((Item)thing, ta, theRead); + // break; + // } + + // } else if (ta.type == "item" && thing is Medallion) + // { + // if (((Medallion)thing).AutoName == ta.name) + // { + // UpdateTrackerMedallion((Medallion)thing, ta, theRead); + // break; + // } + + // } else if (ta.type == "item" && thing is Song) + // { + // if (((Song)thing).AutoName == ta.name) + // { + // UpdateTrackerSong((Song)thing, ta, theRead); + // break; + // } + + // } + // else if (ta.type == "collectable" && thing is CollectedItem) + // { + // if (((CollectedItem)thing).AutoName == ta.name) + // { + // UpdateTrackerCollectable((CollectedItem)thing, ta, theRead); + // break; + // } + + // } else if (ta.type == "collectable" && thing is Item) + // { + // if (((Item)thing).AutoName == ta.name) + // { + // UpdateTrackerItem((Item)thing, ta, theRead); + // break; + // } + + // } + //} ta.currentValue = theRead; } } @@ -247,44 +398,32 @@ private void UTGrouped(TrackedGroup tg, bool forceUpdate = false) { //Debug.WriteLine(tg.name + ": " + tg.runningvalue); - // i can't fucking stand this method - foreach (Control thing in form.Controls[0].Controls) + if (tg.targetControl is CollectedItem ci) { - if (thing is CollectedItem ci) + // i could abosutely opimize this bit but i dont think i care lmao + if (ci.AutoName == tg.name) { - if (ci.AutoName == tg.name) - { - if (ci.AutoSubName != null && form.Settings.SubtractItems) - { - UpdateTrackerCollectable(ci, new TrackedAddress(), tg.runningvalue - GetSubtractValue(ci.AutoSubName)); - } else - { - UpdateTrackerCollectable(ci, new TrackedAddress(), tg.runningvalue); - } - break; - } else if (ci.AutoSubName == tg.name && form.Settings.SubtractItems) + if (ci.AutoSubName != null && form.Settings.SubtractItems) { - UpdateTrackerCollectable(ci, new TrackedAddress(), GetSubtractValue(ci.AutoName) - tg.runningvalue); - break; + UpdateTrackerCollectable(ci, new TrackedAddress(), tg.runningvalue - GetSubtractValue(ci.AutoSubName)); } - - } else if (thing is DoubleItem) - { - if (((DoubleItem)thing).AutoName == tg.name) + else { - UpdateTrackerDoubleItem((DoubleItem)thing, tg.runningvalue); - break; + UpdateTrackerCollectable(ci, new TrackedAddress(), tg.runningvalue); } - } else if (thing is Item) + } + else if (ci.AutoSubName == tg.name && form.Settings.SubtractItems) { - if (((Item)thing).AutoName == tg.name) - { - UpdateTrackerItem((Item)thing, tg.runningvalue); - break; - } - + UpdateTrackerCollectable(ci, new TrackedAddress(), GetSubtractValue(ci.AutoName) - tg.runningvalue); } + } else if (tg.targetControl is DoubleItem di) + { + UpdateTrackerDoubleItem(di, tg.runningvalue); + } else if (tg.targetControl is Item it) + { + UpdateTrackerItem(it, tg.runningvalue); } + tg.currentValue = tg.runningvalue; } } @@ -527,17 +666,23 @@ private int GetSubtractValue(string name) public void StopTimer() { - timer.Change(-1, -1); + timer.Stop(); } private void StartTimer() { - timer.Change(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + timer.Start(); } public void NukeTimer() { - if (timer != null) timer.Dispose(); + if (timer != null) + { + timer.Elapsed -= MainTracker; + timer.Stop(); + timer.Close(); + timer = null; + } timer = null; } diff --git a/GSTHD/CollectedItem.cs b/GSTHD/CollectedItem.cs index 2cdc9b1..411b78b 100644 --- a/GSTHD/CollectedItem.cs +++ b/GSTHD/CollectedItem.cs @@ -15,7 +15,6 @@ class CollectedItem : PictureBox, ProgressibleElement, DraggableAutocheckEl private readonly DraggableAutocheckElementBehaviour DragBehaviour; private string[] ImageNames; - private int ImageIndex = 0; private Label ItemCount; private Size CollectedItemSize; private Size CollectedItemCountPosition; @@ -145,8 +144,8 @@ public void SetState(int state) { if (this.InvokeRequired) { - SetStateCallback d = new SetStateCallback(SetState); - this.Invoke(d, new object[] {state}); + this.Invoke(new SetStateCallback(SetState), new object[] {state}); + return; } else { CollectedItems = state; diff --git a/GSTHD/ControlExtensions.cs b/GSTHD/ControlExtensions.cs index 9dc53de..6a355d5 100644 --- a/GSTHD/ControlExtensions.cs +++ b/GSTHD/ControlExtensions.cs @@ -16,10 +16,6 @@ public static void ClearAndDispose(this Control ctrl) { ClearAndDispose(ctrl.Controls[0]); } - if (ctrl is GossipStone gs) - { - gs.NukeTimer(); - } if (ctrl is PanelWothBarren pw) { foreach (WotH item in pw.ListWotH) diff --git a/GSTHD/Form1.cs b/GSTHD/Form1.cs index 6ec6b83..b503eb0 100644 --- a/GSTHD/Form1.cs +++ b/GSTHD/Form1.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Timers; using System.Windows.Forms; namespace GSTHD @@ -22,8 +23,10 @@ public partial class Form1 : Form public Layout CurrentLayout; Panel LayoutContent; public Autotracker TheAutotracker; + public System.Timers.Timer StoneCyclingTimer; + private int cyclecount = 0; - PictureBox pbox_collectedSkulls; + public List currentlyCycling = new List(); public Settings Settings; @@ -66,6 +69,8 @@ private void LoadAll(object sender, EventArgs e) LoadLayout(); SetMenuBar(); //setAutoTracker(); + if (Settings.DeleteOldAutosaves) CleanUpOldAutos(); + this.KeyPreview = true; //this.KeyDown += changeCollectedSkulls; @@ -73,10 +78,6 @@ private void LoadAll(object sender, EventArgs e) private void Reload(bool changeLayout = false) { - if (TheAutotracker != null) - { - StopAutotracker(); - } //trying to figure out why this was here. is it cuz in the older version you couldnt just open a new layout and had to edit the json to get it to swap? // otherwise, why would you need to reload all the settings //LoadSettings(); @@ -104,6 +105,7 @@ public void LoadSettings() ListPlaces.Clear(); ListPlaces.Add(""); ListPlacesWithTag.Clear(); + currentlyCycling.Clear(); JObject json_places = JObject.Parse(File.ReadAllText(@"" + Settings.ActivePlaces)); foreach (var property in json_places) { @@ -129,9 +131,52 @@ private void SetMenuBar() MenuBar.SetRenderer(); } + private void CleanUpOldAutos() + { + // list everything in dir + // if more than 25, get the oldest ones then nukeem + Debug.WriteLine("------begin"); + if (Directory.Exists("Autosaves")) + { + var files = Directory.GetFiles("Autosaves").OrderBy(f => new FileInfo(f).CreationTime); + int todelete = files.Count() - 25; + if (todelete > 0) + { + foreach (string file in files) + { + //Debug.WriteLine(file + " gets deleted"); + FileInfo fi = new FileInfo(file); + fi.Delete(); + todelete--; + if (todelete == 0) break; + } + //files.OrderBy(x => ((FileInfo)x).CreationTime; + //foreach (string file in files) + //{ + // FileInfo fi = new FileInfo(file); + // if (fi.LastAccessTime < DateTime.Now.AddMonths(-3)) + // fi.Delete(); + //} + } + } + + } + private void LoadLayout() { Controls.Clear(); + if (StoneCyclingTimer != null) + { + StoneCyclingTimer.Elapsed -= IncrementStones; + StoneCyclingTimer.Stop(); + StoneCyclingTimer.Close(); + StoneCyclingTimer = null; + } + //StoneCyclingTimer = new System.Threading.Timer(IncrementStones, null, TimeSpan.FromSeconds(Settings.GossipCycleTime), TimeSpan.FromSeconds(Settings.GossipCycleTime)); + StoneCyclingTimer = new System.Timers.Timer(Settings.GossipCycleTime*1000); + StoneCyclingTimer.Elapsed += IncrementStones; + StoneCyclingTimer.AutoReset = true; + StoneCyclingTimer.Enabled = true; if (LayoutContent != null) LayoutContent.Dispose(); LayoutContent = new Panel(); CurrentLayout = new Layout(); @@ -146,6 +191,12 @@ private void LoadLayout() public void UpdateLayoutFromSettings() { CurrentLayout.UpdateFromSettings(); + //StoneCyclingTimer.Change(TimeSpan.FromSeconds(Settings.GossipCycleTime), TimeSpan.FromSeconds(Settings.GossipCycleTime)); + StoneCyclingTimer.Close(); + StoneCyclingTimer = new System.Timers.Timer(Settings.GossipCycleTime * 1000); + StoneCyclingTimer.Elapsed += IncrementStones; + StoneCyclingTimer.AutoReset = true; + StoneCyclingTimer.Enabled = true; } private void changeCollectedSkulls(object sender, KeyEventArgs k) @@ -161,23 +212,42 @@ private void changeCollectedSkulls(object sender, KeyEventArgs k) public void Reset(object sender) { ControlExtensions.ClearAndDispose(LayoutContent); + currentlyCycling.Clear(); + StopAutotracker(); + if (StoneCyclingTimer != null) + { + StoneCyclingTimer.Elapsed -= IncrementStones; + StoneCyclingTimer.Stop(); + StoneCyclingTimer.Close(); + StoneCyclingTimer = null; + } + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); try { - if (((ToolStripItem)sender).Text == "Open Layout") + if (sender == null) { Reload(); } + else { - Reload(true); - } else - { - Reload(); + if (((ToolStripItem)sender).Text == "Open Layout") + { + Reload(true); + } + else + { + Reload(); + } } - } catch (Exception ex) + } catch (Exception) { Reload(); } - Process.GetCurrentProcess().Refresh(); GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + Process.GetCurrentProcess().Refresh(); } public void SetAutotracker(Process emulator, uint offset) @@ -192,12 +262,53 @@ public void SetAutotracker(Process emulator, ulong offset) private void StopAutotracker() { - if (TheAutotracker != null) CurrentLayout.ListUpdatables.Remove(TheAutotracker); - TheAutotracker.NukeTimer(); + if (TheAutotracker != null) + { + CurrentLayout.ListUpdatables.Remove(TheAutotracker); + TheAutotracker.NukeTimer(); + } TheAutotracker = null; } - public void SaveState() + public void AddCycling(GossipStone gs) + { + currentlyCycling.Add(gs); + } + + public void RemoveCycling(GossipStone gs) + { + currentlyCycling.Remove(gs); + } + + private void IncrementStones(object state, ElapsedEventArgs e) + { + // for stone in ubdatables + // stone.incrementcycle + try + { + foreach (var obj in currentlyCycling) + { + if (obj is GossipStone gs) + { + if (gs.HeldImages.Count > 1) gs.IncrementCycle(); + } + } + } catch (InvalidOperationException) { + } + + cyclecount++; + //Debug.WriteLine(currentlyCycling.Count); + // collect every 5 minutesish + if (cyclecount > 300 / Settings.GossipCycleTime) + { + GC.Collect(); + cyclecount = 0; + // jank autosave + if (Settings.EnableAutosave) SaveState(true); + } + } + + public void SaveState(bool force = false) { JObject thejson = new JObject(); @@ -206,7 +317,7 @@ public void SaveState() if (x.Name != "") { int state = x.GetState(); - if (state != 0) + if (state != x.DefaultIndex) { thejson.Add(x.Name, state.ToString()); } @@ -310,18 +421,29 @@ public void SaveState() } + if (force) + { + if (thejson.HasValues) + { + if (!Directory.Exists("Autosaves")) Directory.CreateDirectory("Autosaves"); + File.WriteAllText(@"Autosaves/auto" + DateTime.Now.ToString("MM-dd-yyyy") + ".json", thejson.ToString()); - //open file to write to - SaveFileDialog saveFileDialog1 = new SaveFileDialog(); - saveFileDialog1.Filter = "json files (*.json)|*.json|All files (*.*)|*.*"; - saveFileDialog1.Title = "Save state to JSON file"; - saveFileDialog1.ShowDialog(); - - if (saveFileDialog1.FileName != "") + } + } + else { - System.IO.File.WriteAllText(saveFileDialog1.FileName, thejson.ToString()); + //open file to write to + SaveFileDialog saveFileDialog1 = new SaveFileDialog(); + saveFileDialog1.Filter = "json files (*.json)|*.json|All files (*.*)|*.*"; + saveFileDialog1.Title = "Save state to JSON file"; + saveFileDialog1.ShowDialog(); + + if (saveFileDialog1.FileName != "") + { + File.WriteAllText(saveFileDialog1.FileName, thejson.ToString()); + } + saveFileDialog1.Dispose(); } - saveFileDialog1.Dispose(); } public void LoadState() @@ -334,12 +456,21 @@ public void LoadState() if (filedia.ShowDialog() == DialogResult.OK) { // reset for safekeepings - Reload(); + Reset(null); //all of the fucking things JObject loadedjson = JObject.Parse(File.ReadAllText(filedia.FileName)); + int missingItems = 0; foreach (JProperty x in (JToken)loadedjson) { - Control found = this.Controls.Find(x.Name, true)[0]; + Control found = null; + try + { + found = this.Controls.Find(x.Name, true)[0]; + } catch (IndexOutOfRangeException) + { + missingItems++; + Debug.WriteLine(x.Name + " not found in layout. Skipping"); + } if (found is Item) { int conv = (int)x.Value; @@ -413,6 +544,10 @@ public void LoadState() } } + if (missingItems > 0) + { + MessageBox.Show("Warning: " + missingItems.ToString() + " items in the state file could not be found in your layout. Skipping."); + } } filedia.Dispose(); } diff --git a/GSTHD/Form1_MenuBar.cs b/GSTHD/Form1_MenuBar.cs index 16f8cd2..35e009a 100644 --- a/GSTHD/Form1_MenuBar.cs +++ b/GSTHD/Form1_MenuBar.cs @@ -52,6 +52,9 @@ private struct MenuItems public ToolStripMenuItem CycleLength; public ToolStripMenuItem ForceGossipCycles; + //Autosaving + public ToolStripMenuItem EnableAutosaves; + public ToolStripMenuItem DeleteOldAutosaves; // Memory Engine public ToolStripMenuItem SelectEmulator; @@ -317,6 +320,24 @@ private void MakeMenu() gossipSubMenu.DropDownItems.Add(Items.ForceGossipCycles); } optionMenu.DropDownItems.Add(gossipSubMenu); + //------------- + ToolStripMenuItem AutosaveSubMenu = new ToolStripMenuItem("Autosaves"); + { + Items.EnableAutosaves = new ToolStripMenuItem("Enable Autosaving", null, new EventHandler(menuBar_ToggleEnableAutosaves)) + { + CheckOnClick = true, + }; + AutosaveSubMenu.DropDownItems.Add(Items.EnableAutosaves); + + + Items.DeleteOldAutosaves = new ToolStripMenuItem("Automatically Delete Old Autosaves", null, new EventHandler(menuBar_ToggleDeleteOldAutosaves)) + { + CheckOnClick = true, + }; + AutosaveSubMenu.DropDownItems.Add(Items.DeleteOldAutosaves); + } + optionMenu.DropDownItems.Add(AutosaveSubMenu); + //------------------- } MenuStrip.Items.Add(optionMenu); @@ -377,10 +398,13 @@ public void ReadSettings() Items.OverrideHeldImage.Checked = Settings.OverrideHeldImage; Items.ForceGossipCycles.Checked = Settings.ForceGossipCycles; + + Items.EnableAutosaves.Checked = Settings.EnableAutosave; + Items.DeleteOldAutosaves.Checked = Settings.DeleteOldAutosaves; try { GossipeCycleLengthOptions[Settings.GossipCycleTime].Checked = true; - } catch (Exception ex) + } catch (Exception) { } @@ -662,6 +686,20 @@ private void menuBar_ToggleSubtractItem(object sender, EventArgs e) Form.UpdateLayoutFromSettings(); } + private void menuBar_ToggleEnableAutosaves(object sender, EventArgs e) + { + Settings.EnableAutosave = Items.EnableAutosaves.Checked; + Settings.Write(); + Form.UpdateLayoutFromSettings(); + } + + private void menuBar_ToggleDeleteOldAutosaves(object sender, EventArgs e) + { + Settings.DeleteOldAutosaves = Items.DeleteOldAutosaves.Checked; + Settings.Write(); + Form.UpdateLayoutFromSettings(); + } + private void menuBar_SetGossipCycleLength(object sender, EventArgs e) { var choice = (ToolStripMenuItem)sender; @@ -669,7 +707,7 @@ private void menuBar_SetGossipCycleLength(object sender, EventArgs e) try { GossipeCycleLengthOptions[Settings.GossipCycleTime].Checked = false; - } catch (Exception ex) + } catch (Exception) { } @@ -759,13 +797,6 @@ public void menuBar_ConnectToEmulator(object sender, EventArgs e) - } - - public void menuBar_VerifyConnection(object sender, EventArgs e) - { - // spit out so much info to make sure shit does infact connect - // will be removed eventually - } private class Form1_MenuBar_ColorTable_LightTheme : ProfessionalColorTable diff --git a/GSTHD/Form2.cs b/GSTHD/Form2.cs index 412e878..72e2046 100644 --- a/GSTHD/Form2.cs +++ b/GSTHD/Form2.cs @@ -21,8 +21,6 @@ public partial class Form2 : Form Layout CurrentLayout; public Panel LayoutContent; - PictureBox pbox_collectedSkulls; - Settings Settings; public Form2() @@ -80,7 +78,7 @@ private void LoadAll(object sender, EventArgs e) public void Reload() { - LoadSettings(); + //LoadSettings(); LoadLayout(); } @@ -115,6 +113,7 @@ public void LoadSettings() private void LoadLayout() { Controls.Clear(); + if (LayoutContent != null) LayoutContent.Dispose(); LayoutContent = new Panel(); CurrentLayout = new Layout(); CurrentLayout.LoadBroadcastLayout(LayoutContent, Settings, ListSometimesHintsSuggestions, ListPlacesWithTag, this); diff --git a/GSTHD/GossipStone.cs b/GSTHD/GossipStone.cs index 27c7224..2f26633 100644 --- a/GSTHD/GossipStone.cs +++ b/GSTHD/GossipStone.cs @@ -1,8 +1,11 @@ using System; +using System.Activities; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.Linq; using System.Runtime.Remoting; +using System.Runtime.Remoting.Messaging; using System.Windows.Forms; namespace GSTHD @@ -37,12 +40,13 @@ public override string ToString() { public class GossipStone : PictureBox, ProgressibleElement, DraggableElement, UpdatableFromSettings { private readonly Settings Settings; + private Form1 f1; private readonly ProgressibleElementBehaviour ProgressBehaviour; private readonly DraggableElementBehaviour DragBehaviour; private string[] ImageNames; private bool HoldsImage; - private List HeldImages = new List(); + public List HeldImages = new List(); private int CycleIndex = 0; private bool canCycle = false; private int ImageIndex = 0; @@ -51,11 +55,12 @@ public class GossipStone : PictureBox, ProgressibleElement, Dr bool isBroadcastable; public bool hoveredOver; + private bool isCyling = false; + Size GossipStoneSize; - private System.Threading.Timer CyclingTimer; - delegate void UpdateImageCallbacK(); + delegate void IncrementCallbacK(); public GossipStone(ObjectPoint data, Settings settings, bool isOnBroadcast = false) : this(settings, data.Name, data.X, data.Y, data.ImageCollection, data.Size, data.isScrollable, data.SizeMode, data.isBroadcastable, data.CanCycle, isOnBroadcast) { } @@ -89,6 +94,7 @@ public GossipStone(Settings settings, string name, int x, int y, string[] imageC this.isScrollable = isScrollable; this.canCycle = CanCycle; this.isBroadcastable = isBroadcastable; + if (!isOnBroadcast) @@ -106,23 +112,35 @@ public GossipStone(Settings settings, string name, int x, int y, string[] imageC } + public void tryToKill() + { + if (isCyling && HeldImages.Count > 1) + { + f1.RemoveCycling(this); + } + } + + private Form1 FindF1(Control c) + { + if (c == null) return null; + if (c is Form1 f1) + { + return f1; + } else + { + return FindF1(c.Parent); + } + } + // both of these functions are for when the stone is in a WOTH panel, so that it can be scrolled without the whole WOTH panle scrolling as well private void Panel_MouseEnter(object sender, EventArgs e) { this.hoveredOver = true; - if (HeldImages.Count > 1 && CyclingTimer != null) - { - CyclingTimer.Change(-1, -1); - } } private void Panel_MouseLeave(object sender, EventArgs e) { this.hoveredOver = false; - if (HeldImages.Count > 1) - { - CyclingTimer.Change(TimeSpan.FromSeconds(Settings.GossipCycleTime), TimeSpan.FromSeconds(Settings.GossipCycleTime)); - } } private void Mouse_Wheel(object sender, MouseEventArgs e) @@ -161,10 +179,6 @@ private void Mouse_DragDrop(object sender, DragEventArgs e) { HeldImages.Add(dropContent.ImageName); } - if (HeldImages.Count > 1 && CyclingTimer == null) - { - CyclingTimer = new System.Threading.Timer(IncrementCycle, null, TimeSpan.FromSeconds(Settings.GossipCycleTime), TimeSpan.FromSeconds(Settings.GossipCycleTime)); - } } else { @@ -180,10 +194,6 @@ private void Mouse_DragDrop(object sender, DragEventArgs e) remotewindow.HeldImages = HeldImages; remotewindow.CycleIndex = 0; remotewindow.UpdateImage(); - if (HeldImages.Count > 1 && remotewindow.CyclingTimer == null) - { - remotewindow.CyclingTimer = new System.Threading.Timer(remotewindow.IncrementCycle, null, TimeSpan.FromSeconds(Settings.GossipCycleTime), TimeSpan.FromSeconds(Settings.GossipCycleTime)); - } } } @@ -203,22 +213,30 @@ public void Mouse_Move(object sender, MouseEventArgs e) public void UpdateImage() { + if (f1 == null) + { + this.f1 = FindF1(this.Parent); + } if (HoldsImage) { if (Image != null) Image.Dispose(); Image = null; - Image = Image.FromFile(@"Resources/" + HeldImages[CycleIndex]); + try + { + Image = Image.FromFile(@"Resources/" + HeldImages[CycleIndex]); + } catch (ArgumentOutOfRangeException) + { + CycleIndex = 0; + Image = Image.FromFile(@"Resources/" + HeldImages[CycleIndex]); + } if (isBroadcastable && Application.OpenForms["GSTHD_DK64 Broadcast View"] != null) { var remotewindow = ((GossipStone)Application.OpenForms["GSTHD_DK64 Broadcast View"].Controls.Find(this.Name, true)[0]); remotewindow.HeldImages = HeldImages; remotewindow.HoldsImage = true; + remotewindow.CycleIndex = CycleIndex; remotewindow.UpdateImage(); } - if (HeldImages.Count > 1 && CyclingTimer == null) - { - CyclingTimer = new System.Threading.Timer(IncrementCycle, null, TimeSpan.FromSeconds(Settings.GossipCycleTime), TimeSpan.FromSeconds(Settings.GossipCycleTime)); - } } else { @@ -233,6 +251,20 @@ public void UpdateImage() remotewindow.UpdateImage(); } } + if (f1 != null) + { + // if wasnt cycling but now should be, add to cycling + if (!isCyling && HeldImages.Count > 1) + { + isCyling = true; + f1.AddCycling(this); + } else if (isCyling && HeldImages.Count < 2) + { + isCyling = false; + f1.RemoveCycling(this); + } + // if was cycling but now shouldnt be, remove from cycling + } } public GossipStoneState GetState() @@ -288,20 +320,33 @@ public void DecrementState() } } - public void IncrementCycle(object state) + public void IncrementCycle() { - CycleIndex++; - if (CycleIndex == HeldImages.Count) - { - CycleIndex=0; - } - try + + if (InvokeRequired) { - Invoke(new UpdateImageCallbacK(UpdateImage)); - } catch (Exception e) + //TheQueuedThing = IncrementCycle; + try + { + Invoke(new IncrementCallbacK(IncrementCycle)); + } catch (ObjectDisposedException) { + //blank + } + + } else { + if (!hoveredOver && HeldImages.Count > 1) + { + CycleIndex++; + if (CycleIndex == HeldImages.Count) + { + CycleIndex = 0; + } + UpdateImage(); + } } + } public void ResetState() @@ -315,23 +360,11 @@ public void ResetState() { CycleIndex = 0; } - if (HeldImages.Count <= 1) - { - if (CyclingTimer != null) CyclingTimer.Dispose(); - CyclingTimer = null; - CycleIndex = 0; - } if (isBroadcastable && Application.OpenForms["GSTHD_DK64 Broadcast View"] != null) { var remotewindow = ((GossipStone)Application.OpenForms["GSTHD_DK64 Broadcast View"].Controls.Find(this.Name, true)[0]); remotewindow.CycleIndex = 0; remotewindow.HeldImages = HeldImages; - if (HeldImages.Count <= 1) - { - if (remotewindow.CyclingTimer != null) remotewindow.CyclingTimer.Dispose(); - remotewindow.CyclingTimer = null; - remotewindow.CycleIndex = 0; - } } } else { @@ -352,31 +385,17 @@ public void ResetState() public void StartDragDrop() { - if (HeldImages.Count > 1) - { - //TODO: finish this thought lmao - } else - { - HoldsImage = false; - } - UpdateImage(); var dropContent = new DragDropContent(false, HeldImages[CycleIndex]); DoDragDrop(dropContent, DragDropEffects.Copy); + HeldImages.Remove(dropContent.ImageName); + if (HeldImages.Count == 0) HoldsImage = false; + UpdateImage(); SaveChanges(); } - public void NukeTimer() - { - if (CyclingTimer != null) CyclingTimer.Dispose(); - CyclingTimer = null; - } - public void UpdateFromSettings() { - if (HeldImages.Count > 1) - { - CyclingTimer.Change(TimeSpan.FromSeconds(Settings.GossipCycleTime), TimeSpan.FromSeconds(Settings.GossipCycleTime)); - } + //pass } public void SaveChanges() diff --git a/GSTHD/Item.cs b/GSTHD/Item.cs index cfcddbc..75f46b8 100644 --- a/GSTHD/Item.cs +++ b/GSTHD/Item.cs @@ -15,7 +15,7 @@ public class Item : PictureBox, ProgressibleElement, DraggableAutocheckElem private string[] ImageNames; private int ImageIndex = 0; - private int DefaultIndex = 0; + public int DefaultIndex = 0; private string DragImage = null; bool isBroadcastable; @@ -143,8 +143,8 @@ public void SetState(int state) { if (this.InvokeRequired) { - SetStateCallback d = new SetStateCallback(SetState); - this.Invoke(d, new object[] { state }); + Invoke(new SetStateCallback(SetState), new object[] { state }); + return; } else { diff --git a/GSTHD/Layout.cs b/GSTHD/Layout.cs index 2120c4c..eef0484 100644 --- a/GSTHD/Layout.cs +++ b/GSTHD/Layout.cs @@ -51,9 +51,34 @@ public void UpdateFromSettings() public void LoadLayout(Panel panelLayout, Settings settings, SortedSet listSometimesHintsSuggestions, Dictionary listPlacesWithTag, Form1 form) { + ListUpdatables.Clear(); if (settings.ActiveLayout != string.Empty) { - JObject json_layout = JObject.Parse(File.ReadAllText(@"" + settings.ActiveLayout)); + JObject json_layout; + try + { + json_layout = JObject.Parse(File.ReadAllText(@"" + settings.ActiveLayout)); + if (!json_layout.ContainsKey("AppSize")) + { + MessageBox.Show("Layout file " + settings.ActiveLayout.ToString() + " does not appear to contain any GSTHD layout data.\nReverting to dk64.json.", "GSTHD", MessageBoxButtons.OK, MessageBoxIcon.Error); + // set settings to dk64.json + settings.ActiveLayout = "layouts\\dk64.json"; + settings.Write(); + // force reload + form.Reset(null); + return; + } + } catch (JsonReaderException) + { + MessageBox.Show("File " + settings.ActiveLayout.ToString() + " does not appear to be a proper json file.\nReverting to dk64.json.", "GSTHD", MessageBoxButtons.OK, MessageBoxIcon.Error); + // set settings to dk64.json + settings.ActiveLayout = "layouts\\dk64.json"; + settings.Write(); + // force reload + form.Reset(null); + return; + } + foreach (var category in json_layout) { if (category.Key.ToString() == "AppSize") @@ -531,6 +556,7 @@ public void LoadLayout(Panel panelLayout, Settings settings, SortedSet l public void LoadBroadcastLayout(Panel panelLayout, Settings settings, SortedSet listSometimesHintsSuggestions, Dictionary listPlacesWithTag, Form2 form) { + ListUpdatables.Clear(); if (settings.ActiveLayout != string.Empty) { JObject json_layout = JObject.Parse(File.ReadAllText(@"" + settings.ActiveLayout.Replace(".json", "") + "_broadcast.json")); diff --git a/GSTHD/Memory.cs b/GSTHD/Memory.cs index 31896d5..e2de67e 100644 --- a/GSTHD/Memory.cs +++ b/GSTHD/Memory.cs @@ -28,60 +28,60 @@ public static class Memory //32-bit functions - public static int ReadInt8(Process P, uint memAdr) + public static int ReadInt8(IntPtr P, uint memAdr) { return ReadBytes(P, memAdr, 1)[0]; } - public static int ReadInt16(Process P, uint memAdr) + public static int ReadInt16(IntPtr P, uint memAdr) { return BitConverter.ToInt16(ReadBytes(P, memAdr, 2), 0); } - public static int ReadInt32(Process P, uint memAdr) + public static int ReadInt32(IntPtr P, uint memAdr) { return BitConverter.ToInt32(ReadBytes(P, memAdr, 4), 0); } - public static UInt32 ReadUInt32(Process P, uint memAdr) + public static UInt32 ReadUInt32(IntPtr P, uint memAdr) { IntPtr ptrBytesRead = new IntPtr(0); byte[] buffer = new byte[3]; - ReadProcessMemory(P.Handle, (UIntPtr)memAdr, buffer, 4, ptrBytesRead); + ReadProcessMemory(P, (UIntPtr)memAdr, buffer, 4, ptrBytesRead); return BitConverter.ToUInt32(ReadBytes(P, memAdr, 4), 0); } - private static byte[] ReadBytes(Process P, uint memAdr, uint bytesToRead) + private static byte[] ReadBytes(IntPtr P, uint memAdr, uint bytesToRead) { IntPtr ptrBytesRead = new IntPtr(0); byte[] buffer = new byte[bytesToRead]; - ReadProcessMemory(P.Handle, new UIntPtr(memAdr), buffer, bytesToRead, ptrBytesRead); + ReadProcessMemory(P, new UIntPtr(memAdr), buffer, bytesToRead, ptrBytesRead); return buffer; } //64-bit functions - public static int ReadInt8(Process P, ulong memAdr) + public static int ReadInt8(IntPtr P, ulong memAdr) { return ReadBytes(P, memAdr, 1)[0]; } - public static int ReadInt16(Process P, ulong memAdr) + public static int ReadInt16(IntPtr P, ulong memAdr) { return BitConverter.ToInt16(ReadBytes(P, memAdr, 2), 0); } - public static int ReadInt32(Process P, ulong memAdr) + public static int ReadInt32(IntPtr P, ulong memAdr) { return BitConverter.ToInt32(ReadBytes(P, memAdr, 4), 0); } - public static ulong ReadInt64(Process P, ulong memAdr) + public static ulong ReadInt64(IntPtr P, ulong memAdr) { return BitConverter.ToUInt64(ReadBytes(P, memAdr, 8), 0); } - private static byte[] ReadBytes(Process P, ulong memAdr, uint bytesToRead) + private static byte[] ReadBytes(IntPtr P, ulong memAdr, uint bytesToRead) { - IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, P.Id); + //IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, P.ToInt32()); IntPtr ptrBytesRead = new IntPtr(0); byte[] buffer = new byte[bytesToRead]; - ReadProcessMemory(processHandle, new UIntPtr(memAdr), buffer, bytesToRead, ptrBytesRead); + ReadProcessMemory(P, new UIntPtr(memAdr), buffer, bytesToRead, ptrBytesRead); return buffer; } diff --git a/GSTHD/PanelWothBarren.cs b/GSTHD/PanelWothBarren.cs index 1b73ee0..ee2772e 100644 --- a/GSTHD/PanelWothBarren.cs +++ b/GSTHD/PanelWothBarren.cs @@ -295,6 +295,7 @@ public void RemoveWotH(WotH woth) this.Controls.Remove(woth.LabelPlace); foreach (var gossipStone in woth.listGossipStone) { + gossipStone.tryToKill(); this.Controls.Remove(gossipStone); } diff --git a/GSTHD/Program.cs b/GSTHD/Program.cs index ed552c1..038947a 100644 --- a/GSTHD/Program.cs +++ b/GSTHD/Program.cs @@ -16,13 +16,17 @@ static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); //dembunging + //Form1 F1 = new Form1(); //try //{ - Application.Run(new Form1()); - //} catch (Exception ex) + // Application.Run(F1); + //} catch (OutOfMemoryException) //{ - // MessageBox.Show(ex.Source + ":\n" + ex.Message, "GSTHD", MessageBoxButtons.OK, MessageBoxIcon.Error); + // F1.SaveState(true); + // MessageBox.Show("GSTHD has run into a fatal memory issue and will now close.\nYour tracker state has been saved to the GSTHD directory can be reloaded later.\nWe apologize for the inconvenience.", "GSTHD", MessageBoxButtons.OK, MessageBoxIcon.Error); + // Application.Exit(); //} } } diff --git a/GSTHD/Settings.cs b/GSTHD/Settings.cs index d1bfa51..6deeece 100644 --- a/GSTHD/Settings.cs +++ b/GSTHD/Settings.cs @@ -80,6 +80,8 @@ public enum SelectEmulatorOption public bool ForceGossipCycles { get; set; } = false; public bool OverrideHeldImage { get; set; } = false; public double GossipCycleTime { get; set; } = 1; + public bool EnableAutosave { get; set; } = true; + public bool DeleteOldAutosaves { get; set; } = true; public bool SubtractItems { get; set; } = true; public KnownColor LastWothColor { get; set; } = KnownColor.BlueViolet; diff --git a/GSTHD/WotH.cs b/GSTHD/WotH.cs index 88d9af7..dd9827e 100644 --- a/GSTHD/WotH.cs +++ b/GSTHD/WotH.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; @@ -111,6 +112,11 @@ public WotH(Settings settings, UpdateFromSettings(); } + ~WotH() + { + Debug.WriteLine("woth " + this.Name + " being killed"); + } + public void UpdateFromSettings() { MinIndex = Settings.EnableLastWoth ? 0 : 1;