爐石傳說輔助
實現原理:修改遊戲檔案
注入機器人
使用
MonoCecil,修改 Unity3D 生成的 Assembly 檔案,在內部注入我們自己編寫的Unity3D模組!
實現細節:修改遊戲檔案
其實主要是
MonoCecil 的使用
通過檔名、類名、方法名,取出方法的定義
通過檔名和方法定義實現注入static MethodDefinition fetch_method(string file, string type, string method) { // find hook method try { AssemblyDefinition ad = AssemblyDefinition.ReadAssembly(file); TypeDefinition td = null; foreach (TypeDefinition t in ad.MainModule.Types) { if (t.Name == type) { td = t; break; } } if (td == null) return null; MethodDefinition md = null; foreach (MethodDefinition t in td.Methods) { if (t.Name == method) { md = t; break; } } return md; } catch (Exception e) { Console.WriteLine(e.ToString()); return null; } }
注入完了之後,利用static AssemblyDefinition inject_method(string file, MethodDefinition method, MethodDefinition method_tobe_inject) { try { AssemblyDefinition ad = AssemblyDefinition.ReadAssembly(file); ILProcessor ilp = method.Body.GetILProcessor(); Instruction ins_first = ilp.Body.Instructions[0]; Instruction ins = ilp.Create(OpCodes.Call, ad.MainModule.Import(method_tobe_inject.Resolve())); ilp.InsertBefore(ins_first, ins); return ad; } catch (Exception e) { Console.WriteLine(e.ToString()); return null; } }
AssemblyDefinition.Write();
方法,把修改後的Assembly再寫到一個檔案裡。
實現原理一:遊戲狀態獲取
單例類
HearthStone有幾個重要的類,如SceneMgr、MulliganManager、GameState、InputManager等等。
單例,直接呼叫Get()方法就可以了!
狀態的識別
通常來說,可以使用SceneMgr取得當前的場景情況,可以使用GameState獲得當前對戰的遊戲狀態。兩者一結合,基本就是整個遊戲的狀態的了。
通過狀態就可以知道哪些類當前是有例項的,哪些是沒有的。
實現原理二:場上卡牌的資料
GameState可以獲得當前的兩個玩家Player,而Player可以活動當前的卡牌,如Player.GetHandZone().GetCards()取得手上的卡牌。
實現原理三:機器人自動執行
首先,通過分析場上的資料就可以算出該怎麼走牌,這是AI的部分,我只寫了個有啥走啥的簡單AI。
我們程式碼是使用組建的方式註冊在遊戲裡的,會被定時呼叫,呼叫的時候,進行操作(如走牌)然後及時返回即可。
實現原理四:走牌和攻擊
走牌和攻擊的實現,雖然我能夠完全模仿客戶端邏輯,但是總覺得不太靠譜,因為客戶端更新,我可能沒發現,就會出錯。因此我走牌和攻擊的實現是直接呼叫了InputManager。
InputManager包含了一些方法,用於處理滑鼠和鍵盤事件,我直接呼叫這些函式。
當然這麼做的缺陷也是很明顯的:InputManager的能力範圍有限,並且我不能組織InputManager不去處理一些事件。比如當滑鼠滑出視窗時,InputManager預設會把牌放回手裡。