private void DoWork() { while (isHooked) { // do not do anything while we are in a loadingscreen // WoW doesn't like that and will crash if (AmeisenCore.IsInLoadingScreen()) { Thread.Sleep(50); continue; } if (!hookJobs.IsEmpty) { if (hookJobs.TryDequeue(out HookJob currentJob)) { // process a hook job InjectAndExecute(currentJob.Asm, currentJob.ReadReturnBytes, out bool wasJobSuccessful); // if its a chained hook job, execute it too if (currentJob.GetType() == typeof(ReturnHookJob) && wasJobSuccessful) { currentJob.ReturnValue = InjectAndExecute( ((ReturnHookJob)currentJob).ChainedJob.Asm, ((ReturnHookJob)currentJob).ChainedJob.ReadReturnBytes, out bool wasChainedJobSuccessful); } currentJob.IsFinished = true; } } Thread.Sleep(1); } }
private void ReadEvents() { while (IsActive) { if (AmeisenCore.IsInLoadingScreen()) { Thread.Sleep(50); continue; } // Unminified lua code can be found im my github repo "WowLuaStuff" string eventJson = AmeisenCore.GetLocalizedText("abEventJson='['for a,b in pairs(abEventTable)do abEventJson=abEventJson..'{'for c,d in pairs(b)do if type(d)==\"table\"then abEventJson=abEventJson..'\"args\": ['for e,f in pairs(d)do abEventJson=abEventJson..'\"'..f..'\"'if e<=table.getn(d)then abEventJson=abEventJson..','end end;abEventJson=abEventJson..']}'if a<table.getn(abEventTable)then abEventJson=abEventJson..','end else if type(d)==\"string\"then abEventJson=abEventJson..'\"event\": \"'..d..'\",'else abEventJson=abEventJson..'\"time\": \"'..d..'\",'end end end end;abEventJson=abEventJson..']'abEventTable={}", "abEventJson"); AmeisenLogger.Instance.Log(LogLevel.VERBOSE, $"LUA Events Json: {eventJson}", this); List <RawEvent> rawEvents = new List <RawEvent>(); try { // parse the events from JSON List <RawEvent> finalEvents = new List <RawEvent>(); rawEvents = JsonConvert.DeserializeObject <List <RawEvent> >(eventJson); foreach (RawEvent rawEvent in rawEvents) { if (!finalEvents.Contains(rawEvent)) { finalEvents.Add(rawEvent); } } // Fire the events AmeisenLogger.Instance.Log(LogLevel.VERBOSE, $"Parsed {finalEvents.Count} events", this); if (finalEvents.Count > 0) { foreach (RawEvent rawEvent in finalEvents) { if (EventDictionary.ContainsKey(rawEvent.@event)) { EventDictionary[rawEvent.@event].Invoke(rawEvent.time, rawEvent.args); AmeisenLogger.Instance.Log(LogLevel.VERBOSE, $"Fired OnEventFired: {rawEvent.@event}", this); } } } } catch (Exception e) { AmeisenLogger.Instance.Log(LogLevel.ERROR, $"Failed to parse events Json: {e}", this); } Thread.Sleep(1000); } }
/// <summary> /// Inject assembly code on our hook /// </summary> /// <param name="asm">assembly to execute</param> /// <param name="readReturnBytes">should the return bytes get read</param> /// <param name="successful">if the reading of return bytes was successful</param> /// <returns></returns> private byte[] InjectAndExecute(string[] asm, bool readReturnBytes, out bool successful) { List <byte> returnBytes = new List <byte>(); try { // wait for the code to be executed while (isInjectionUsed || AmeisenCore.IsInLoadingScreen() || BlackMagic.ReadInt(codeToExecute) > 0) { Thread.Sleep(5); } isInjectionUsed = true; // preparing to inject the given ASM BlackMagic.Asm.Clear(); // add all lines foreach (string s in asm) { BlackMagic.Asm.AddLine(s); } // now there is code to be executed BlackMagic.WriteInt(codeToExecute, 1); // inject it BlackMagic.Asm.Inject(codeCaveForInjection); // we don't need this atm //AmeisenManager.Instance().GetBlackMagic().Asm.AddLine("JMP " + (endsceneReturnAddress)); //int asmLenght = BlackMagic.Asm.Assemble().Length; // wait for the code to be executed while (BlackMagic.ReadInt(codeToExecute) > 0) { Thread.Sleep(1); } // if we want to read the return value do it otherwise we're done if (readReturnBytes) { byte buffer = new byte(); try { // get our return parameter address uint dwAddress = BlackMagic.ReadUInt(returnAdress); // read all parameter-bytes until we the buffer is 0 buffer = BlackMagic.ReadByte(dwAddress); while (buffer != 0) { returnBytes.Add(buffer); dwAddress = dwAddress + 1; buffer = BlackMagic.ReadByte(dwAddress); } } catch (Exception e) { AmeisenLogger.Instance.Log( LogLevel.ERROR, $"Crash at reading returnAddress: {e.ToString()}", this); } } } catch (Exception e) { // now there is no more code to be executed BlackMagic.WriteInt(codeToExecute, 0); successful = false; AmeisenLogger.Instance.Log( LogLevel.ERROR, $"Crash at InjectAndExecute: {e.ToString()}", this); foreach (string s in asm) { AmeisenLogger.Instance.Log( LogLevel.ERROR, $"ASM Content: {s}", this); } AmeisenLogger.Instance.Log( LogLevel.ERROR, $"ReadReturnBytes: {readReturnBytes}", this); } // now we can use the hook again isInjectionUsed = false; successful = true; return(returnBytes.ToArray()); }