最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

[C#][HarmonyPatch]Manual patch internal class/anonymous method/d

2023-03-28 16:45 作者:geleisisisi  | 我要投稿

前言:

在使用HarmonyPatch制作各種各樣mod的時(shí)候,總會(huì)遇到一些奇奇怪怪的情況導(dǎo)致無(wú)法patch。本篇文章將會(huì)介紹其中的一些情況以及應(yīng)對(duì)方法。

主要內(nèi)容:

  1. 介紹manual?patch

  2. 如何manual patch?internal?class下的method

  3. 如何manual?patch?匿名方法(委托)

另:本人并未系統(tǒng)的學(xué)習(xí)過(guò)C#,所有對(duì)于C#的了解都是基于讀別人的代碼后連猜帶蒙給蒙出來(lái)的,知識(shí)的局限性必然會(huì)導(dǎo)致我敲代碼的局限性。希望大佬們能夠多多指正我的錯(cuò)誤,以及提出更加優(yōu)化解法。

什么是manual?patch:

通常情況下,我們會(huì)使用如下的模版進(jìn)行patch,也是最常見(jiàn)的方式

這種方法,相當(dāng)于你告訴HarmonyPatch:去,把某個(gè)class下的某個(gè)method給我找到,然后我要對(duì)它進(jìn)行修改。

大多數(shù)情況下,HarmonyPatch都能幫你找到,所以這是最常見(jiàn)的方式。但是某些特殊的情況(后文我會(huì)介紹),HarmonyPatch無(wú)法做到,這個(gè)時(shí)候我們就不能依賴(lài)HarmonyPatch幫我們找到method,我們需要通過(guò)各種各樣的方式,自己去找到想要patch的method,然后把它的信息告訴HarmonyPatch,最后對(duì)該method進(jìn)行修改,那么這種方式我們就稱(chēng)它為manual?patch。因?yàn)槟阈枰謩?dòng)去找到method的信息。

那么manual?patch的模版如下

如果你看到這里還是云里霧里,沒(méi)關(guān)系,因?yàn)榻酉聛?lái)我們會(huì)通過(guò)兩個(gè)實(shí)例,結(jié)合該模版進(jìn)行操作。代碼這種東西,看多了自然就懂了。

Manual?patch?internal?class下的method:

如果想要patch的class是internal?class,那么HarmonyPatch是沒(méi)有辦法直接工作的。

實(shí)例:

以Farm?Together這款游戲進(jìn)行舉例,該游戲下有這樣一個(gè)class以及method

我的目的是對(duì)LocalFarmhandScript.StartGoingToTile進(jìn)行transpiler

  1. 將bool flag = false; 替換成?bool flag = true;

  2. 將this.teleportTime = magnitude / 3f;?替換成this.teleportTime = magnitude / 300f;

那么按照通常方法,應(yīng)該這么寫(xiě)

但是很遺憾,由于LocalFarmhandScript是internal class,HarmonyPatch沒(méi)有辦法直接尋找到該class,直接導(dǎo)致語(yǔ)句報(bào)錯(cuò)。

那么這個(gè)時(shí)候,就是使用manual?patch的時(shí)候了。我們先通過(guò)AccessTools.Method找到MethodInfo/MethodBase,通過(guò)該信息手動(dòng)定位到想要patch的method,然后進(jìn)行修改,具體例子如下

Manual?patch?anonymous method/delegate:

實(shí)例:

以Monster?Train(怪物火車(chē))這款游戲進(jìn)行舉例,該游戲下有這樣一個(gè)class以及method

我的目的是對(duì)StoryEventPoolData.TriggerNode進(jìn)行transpiler

  1. 將 saveManager.Save(true);?替換成saveManager.Save(false);

首先我嘗試的是導(dǎo)出該函數(shù)下的所有IL?instructions

導(dǎo)出數(shù)據(jù)如下

非常遺憾,無(wú)論我怎么看,我也找不到SaveManager.Save這個(gè)函數(shù)的調(diào)用,那更別談把參數(shù)從true改成false了。

但是如果我用dnspy打開(kāi)該函數(shù),把光標(biāo)移動(dòng)到saveManager.Save(true);這條語(yǔ)句上,然后右鍵點(diǎn)擊Edit?IL?Instructions,會(huì)出現(xiàn)如下截圖

很明顯,在這張截圖里,我們就能看見(jiàn)SaveManager::Save。

這時(shí)候,我們看下截圖的左上角的標(biāo)題,可以發(fā)現(xiàn)Method?Body不是TriggerNode,而是<TriggerNode>b__0。換言之,我們需要patch的其實(shí)并不是TriggerNode,而是這個(gè)<TriggerNode>b__0。

但是這個(gè)<TriggerNode>b__0究竟是什么,老實(shí)說(shuō)我真的一頭霧水。于是我去網(wǎng)上搜了下,發(fā)現(xiàn)這玩意叫匿名函數(shù)或者委托。根據(jù)我淺薄的理解,大概意思呢就是一個(gè)大函數(shù)里面包含了一個(gè)小函數(shù),由于這個(gè)小函數(shù)不常用,于是就不另外給它進(jìn)行正式的書(shū)寫(xiě)以及命名了,所以稱(chēng)它為匿名函數(shù)。

事兒就是這么個(gè)事兒,但問(wèn)題是我要如何定位到這個(gè)<TriggerNode>b__0,然后進(jìn)行修改呢?

我進(jìn)行了多種嘗試,比如

通通以失敗告終后,我突然想起上面那個(gè)farm?together的例子,先嘗試下通過(guò)AccessTools.Method能不能獲取MethodInfo,然后再談后話。

回到導(dǎo)出TriggerNode下所有IL?instructions的數(shù)據(jù),可以發(fā)現(xiàn)如下這么一條代碼

那么這段代碼里,其實(shí)就包含了所有關(guān)于我想要定位的那個(gè)<TriggerNode>b__0的信息。

首先它的全名應(yīng)該是"StoryEventPoolData/<>c__DisplayClass7_0:<TriggerNode>b__0",注意需要把雙冒號(hào)替換成單冒號(hào),因?yàn)锳ccessTools.Method就是這么規(guī)定格式的。

再來(lái)它的參數(shù)類(lèi)型為IScreen。

有了這些信息后,我們就可以嘗試使用AccessTools.Method來(lái)獲取Method信息,即

幸運(yùn)的是,我測(cè)試了它的返回值不為空,也就是說(shuō)成功找到了。那么接下來(lái)就簡(jiǎn)單了,無(wú)非就是用manual?patch來(lái)解決定位的問(wèn)題,具體代碼如下

補(bǔ)充閱讀:

https://harmony.pardeike.net/articles/patching.html

[C#][HarmonyPatch]Manual patch internal class/anonymous method/d的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
渝北区| 繁峙县| 涞水县| 临武县| 泽库县| 遂宁市| 沂源县| 永城市| 南阳市| 拉萨市| 沅陵县| 广丰县| 五寨县| 西乌| 大理市| 漾濞| 项城市| 凤阳县| 重庆市| 南澳县| 仙游县| 闵行区| 绥阳县| 连山| 宜昌市| 疏勒县| 兴化市| 汉阴县| 宁陕县| 中西区| 金寨县| 舒城县| 南涧| 万山特区| 佛坪县| 丹棱县| 东城区| 南木林县| 大石桥市| 大庆市| 全椒县|