public void Loop() { try { // Hook the game process so we can read the memory bool isNowOpen = (goatMemory.HookProcess() && !goatMemory.proc.HasExited); if (isNowOpen != isOpen) { if (!isNowOpen) { LogWriter.WriteLine("escapegoat2.exe is unavailable."); } else { LogWriter.WriteLine("escapegoat2.exe is available."); } isOpen = isNowOpen; } // If we're open, do all the magic if (isOpen) { Pulse(); } } catch (Exception e) { if (this.exceptionsCaught < 10 && this.totalExceptionsCaught < 30) { this.exceptionsCaught++; this.totalExceptionsCaught++; LogWriter.WriteLine("Exception #{0} (P:{2}): {1}", this.exceptionsCaught, e.ToString(), this.pulseCount); } else if (this.totalExceptionsCaught < 30) { LogWriter.WriteLine("Too many exceptions, rebooting autosplitter. (P:{0})", this.pulseCount); this.goatMemory.Dispose(); this.goatMemory = new GoatMemory(); this.exceptionsCaught = 0; } else if (this.totalExceptionsCaught == 30) { LogWriter.WriteLine("Too many total exceptions, no longer logging them. (P:{0})", this.pulseCount); this.totalExceptionsCaught++; } } // We cache memory pointers during each pulse inside goatMemory for // performance reasons, we need to manually clear the cache here so // that goatMemory knows we are done making calls to it and that we // do not need these values anymore. // // We need this to occur even if (actually, especially if) and // exception occurs to clear any potentially dead memory pointers // that occured due to reading memory just as it's being // moved/freed. goatMemory.ClearCaches(); }
public GoatState() { map = new WorldMap(); goatMemory = new GoatMemory(); goatTriggers = new GoatTriggers(); }