MainWindow
private void button_0_Click(object sender, RoutedEventArgs e) { Configuration.Instance.SaveAll(); this.button_0.IsEnabled = false; this.comboBox_1.IsEnabled = false; this.comboBox_0.IsEnabled = false; this.checkBox_0.IsEnabled = false; this.listBox_0.IsEnabled = false; try { this.bool_0 = false; if (BotManager.IsRunning) { BotManager.Stop(); } else { BotManager.Start(); } } finally { this.bool_0 = true; } this.stopwatch_0.Restart(); }
BotManager
public static bool Start() { object obj = BotManager.object_0; bool result; lock (obj) { if (BotManager.IsRunning) { BotManager.ilog_0.ErrorFormat("[Start] The BotThread is already running. Please use BotManager.Stop first.", Array.Empty<object>()); result = false; } else if (!TritonHs.Initialized) { BotManager.ilog_0.ErrorFormat("[Start] TritonHs is not initialized yet.", Array.Empty<object>()); result = false; } else if (BotManager.CurrentBot == null) { BotManager.ilog_0.ErrorFormat("[Start] There is no bot to run. Please assign a bot first.", Array.Empty<object>()); result = false; } else { BotManager.ilog_0.InfoFormat("[Start] Now creating the BotThread.", Array.Empty<object>()); BotManager.bool_3 = false; BotManager.BotThread = new Thread(new ThreadStart(BotManager.smethod_4)); BotManager.BotThread.Start(); result = true; } } return result; }
private static void smethod_4() { object obj = BotManager.object_0; lock (obj) { Thread.Sleep(1); } TritonHs.Memory.DisableCache(); TritonHs.Memory.ClearCache(); TritonHs.Memory.Executor.FrameDropWaitTime = 15000u; TritonHs.Memory.Executor.ExecuteWaitTime = 15000; try { TritonHs.smethod_2(true); } catch { } try { BotManager.smethod_0(BotManager.CurrentBot); goto IL_FA; } catch { BotManager.autoResetEvent_0.Set(); goto IL_FA; } IL_87: try { if (BotManager.MsBeforeNextTick != 0) { Thread.Sleep(BotManager.MsBeforeNextTick); BotManager.MsBeforeNextTick = 0; } BotManager.smethod_1(BotManager.CurrentBot); BotManager.bool_3 = false; if (BotManager.MsBetweenTicks != 0) { Thread.Sleep(BotManager.MsBetweenTicks); } } catch (InjectionDesyncException) { BotManager.ilog_0.DebugFormat("[BotThreadFunction] An InjectionDesyncException was detected.", Array.Empty<object>()); BotManager.bool_3 = true; TritonHs.InvokeEvent(BotManager.eventHandler_1, new object[] { null, new ClientFrozenEventArgs() }); } catch { } IL_FA: if (!BotManager.autoResetEvent_0.WaitOne(0)) { goto IL_87; } try { BotManager.smethod_2(BotManager.CurrentBot); } catch { } BotManager.BotThread = null; if (BotManager.bool_3) { TritonHs.InvokeEvent(BotManager.eventHandler_1, new object[] { null, new ClientFrozenEventArgs() }); return; } try { TritonHs.smethod_2(true); } catch { } }
重点在ibot_1.Start();,这里启动后,进入DefaultBot的流程
internal static void smethod_0(IBot ibot_1) { try { object obj = BotManager.object_0; lock (obj) { if (BotManager.bool_0) { return; } BotManager.bool_0 = true; } BotManager.smethod_3(ibot_1, BotManager.botEvent_0); try { using (TritonHs.AcquireFrame()) { using (TritonHs.Memory.TemporaryCacheState(false)) { TritonHs.Memory.ClearCache(); ibot_1.Start(); } } } catch (Exception exception) { BotManager.ilog_0.Error("[Start] Exception during execution:", exception); throw; } BotManager.smethod_3(ibot_1, BotManager.botEvent_1); } finally { object obj = BotManager.object_0; lock (obj) { BotManager.bool_0 = false; } } }
MainWindow
private void method_11(IBot ibot_0) { base.Dispatcher.BeginInvoke(new Action(this.method_35), Array.Empty<object>()); if (this.bool_0) { base.Dispatcher.BeginInvoke(new Action(this.method_36), Array.Empty<object>()); } }
DefaultBot
namespace Triton.Bot.Logic.Bots.DefaultBot
{
// Token: 0x02000256 RID: 598
public class DefaultBot : IRunnable, IAuthored, IBase, IBot, IConfigurable
public void Start() { this.coroutine_0 = new Coroutine(new Func<Task>(this.method_53)); this.bool_2 = false; GameEventManager.Instance.Start(); PluginManager.Start(); RoutineManager.Start(); ProcessHookManager.Enable(); GameEventManager.NewGame += this.method_18; GameEventManager.GameOver += this.method_19; GameEventManager.MulliganConfirm += this.method_16; InactivePlayerKicker inactivePlayerKicker = InactivePlayerKicker.Get(); if (inactivePlayerKicker != null) { inactivePlayerKicker.SetShouldCheckForInactivity(false); } }
DefaultBot.Tick方法中,以下三行代码
GameEventManager.Instance.Tick();
PluginManager.Tick();
RoutineManager.Tick();
public void Tick() { if (this.coroutine_0.IsFinished) { DefaultBot.ilog_0.DebugFormat("The bot coroutine has finished in a state of {0}", this.coroutine_0.Status); BotManager.Stop(); return; } if (!TritonHs.IsClientInUsableState(true)) { BotManager.MsBeforeNextTick += 750; this.method_17(); return; } if (!this.bool_2 && ChatMgr.Get().FriendListFrame != null) { DefaultBot.ilog_0.ErrorFormat("[Tick] FriendListFrame != null.", Array.Empty<object>()); Client.LeftClickAtDialog(BnetBar.Get().m_friendButton.m_OnlineCountText.Transform.Position); BotManager.MsBeforeNextTick += 1000; this.method_17(); return; } bool flag; if (TritonHs.HandleDialog(new ShouldAcceptFriendlyChallengeDelegate(this.ShouldAcceptFriendlyChallenge), out flag)) { if (flag) { BotManager.Stop(); } BotManager.MsBeforeNextTick += 3000; this.method_17(); return; } GameEventManager.Instance.Tick(); PluginManager.Tick(); RoutineManager.Tick(); try { this.coroutine_0.Resume(); } catch { this.method_17(); throw; } }
RoutineManager.Tick
RoutineManager.CurrentRoutine就是silver fish
public static void Tick() { RoutineManager.Tick(RoutineManager.CurrentRoutine); }
调试的时候,routine.Tick();会自动反编译,加载出一个DefaultRoutine.dll【这里的调试必须是F11】
public static void Tick(IRoutine routine) { RoutineManager.smethod_0(routine, RoutineManager.routineEvent_2); try { routine.Tick(); } catch (Exception exception) { RoutineManager.ilog_0.Error("Exception during routine Tick.", exception); } RoutineManager.smethod_0(routine, RoutineManager.routineEvent_3); }
namespace Buddy.Coroutines
{
// Token: 0x0200009E RID: 158
public sealed class Coroutine : IDisposable
public void Resume() { if (this.IsDisposed) { throw new ObjectDisposedException(base.GetType().FullName); } if (this.IsFinished) { throw new InvalidOperationException("This coroutine has finished execution and cannot be resumed."); } if (Coroutine.coroutine_0 == this) { throw new InvalidOperationException("A coroutine cannot resume itself"); } this.method_0(false); }
private void method_0(bool bool_2) { SynchronizationContext synchronizationContext = SynchronizationContext.Current; Coroutine coroutine = Coroutine.coroutine_0; try { Coroutine.coroutine_0 = this; SynchronizationContext.SetSynchronizationContext(null); Action action = this.action_0; this.action_0 = null; action(); if (!bool_2) { this.Ticks++; } this.method_2(bool_2); } finally { Coroutine.coroutine_0 = coroutine; SynchronizationContext.SetSynchronizationContext(synchronizationContext); } }
[CompilerGenerated]
private sealed class Class67
public void method_0() { Task<object> task; try { task = this.func_0(); } catch (Exception innerException) { throw this.coroutine_0.method_1(new CoroutineUnhandledException("Exception was thrown by root coroutine task producer", innerException)); } if (task == null) { throw this.coroutine_0.method_1(new CoroutineBehaviorException("The root coroutine task producer returned null")); } this.coroutine_0.task_0 = task; }
上面的default routine加载后,直接搜索getHoldList
定位到出错的地方
ERROR Logger (null) - [Tick] Exception during execution:
Buddy.Coroutines.CoroutineUnhandledException: Exception was thrown by coroutine ---> System.NullReferenceException: Object reference not set to an instance of an object.
at HREngine.Bots.Mulligan.getHoldList(MulliganData mulliganData, Behavior behave) in
RoutinesDefaultRoutineSilverfishaiMulligan.cs:line 307
at HREngine.Bots.DefaultRoutine.d__41.MoveNext() in
public async Task<bool> Logic(string type, object context) { bool flag = type == "mulligan"; bool result; if (flag) { await this.MulliganLogic(context as MulliganData); result = true; } else if (type == "emote") { await this.EmoteLogic(context as EmoteData); result = true; } else if (type == "our_turn") { await this.OurTurnLogic(); result = true; } else if (type == "opponent_turn") { await this.OpponentTurnLogic(); result = true; } else if (type == "our_turn_combat") { await this.OurTurnCombatLogic(); result = true; } else if (type == "opponent_turn_combat") { await this.OpponentTurnCombatLogic(); result = true; } else if (type == "arena_draft") { await this.ArenaDraftLogic(context as ArenaDraftData); result = true; } else if (type == "handle_quests") { await this.HandleQuestsLogic(context as QuestData); result = true; } else { result = false; } return result; }
在DefaultRoutine加载后,可以直接添加监视
CardDB.Instance.cardIdstringToEnum("ULD_194") ,ULD_194 ,HREngine.Bots.CardDB.cardIDEnum
- CardDB.Instance.getCardDataFromID(HREngine.Bots.CardDB.cardIDEnum.ULD_194) ,{HREngine.Bots.CardDB.Card} ,HREngine.Bots.CardDB.Card
cost是0x3E8=1000,name是unknown