Использование Harmony для исправления реального содержимого асинхронного метода игры UnityC#

Место общения программистов C#
Ответить
Anonymous
 Использование Harmony для исправления реального содержимого асинхронного метода игры Unity

Сообщение Anonymous »


Используя dotPeek, я смог увидеть метод, часть которого я хочу изменить, а именно цифру 4 в CreateLobbyAsync на другое целое число.

public async void StartHost() { if (!(bool) (UnityEngine.Object) UnityEngine.Object.FindObjectOfType()) { Debug.Log((object) «Сценарий менеджера меню отсутствует в сцене; невозможно запустить хост»); } еще { если (GameNetworkManager.Instance.currentLobby.HasValue) { Debug.Log((object) «Пытался запустить хост, но значение currentLobby не равно нулю! Этого не должно произойти. Выход из currentLobby и установка нуля."); this.LeaveCurrentSteamLobby(); } если (!this.disableSteam) { GameNetworkManager gameNetworkManager = GameNetworkManager.Instance; gameNetworkManager.currentLobby = ожидайте SteamMatchmaking.CreateLobbyAsync(4); gameNetworkManager = (GameNetworkManager) ноль; } UnityEngine.Object.FindObjectOfType().StartHosting(); this.SubscribeToConnectionCallbacks(); this.isHostingGame = правда; this.connectedPlayers = 1; }

Однако базовый IL показывает, что фактическая функциональность, которую я хочу изменить, содержится не в доступном методе, а в другом автоматически сгенерированном методе.

Вот метод, который я хотел изменить.

StartHost() cil управляемый { .custom экземпляр void [netstandard]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [netstandard]System.Type) "=" 01 00 23 47 61 6d 65 4e 65 74 77 6f 72 6b 4d 61 // ..#GameNetworkMa 6e 61 67 65 72 2b 3c 53 74 61 72 74 48 6f 73 74 // nager+d__79.. ) // тип(тип значения GameNetworkManager/'d__79') .maxstack 2 .locals инициализация( [0] тип значения GameNetworkManager/'d__79' V_0 ) IL_0000: ldloca.s V_0 IL_0002: вызвать тип значения [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::Create() IL_0007: тип значения stfld [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder GameNetworkManager/'d__79'::'t__builder' IL_000c: ldloca.s V_0 IL_000e: ldarg.0 // это IL_000f: класс stfld GameNetworkManager GameNetworkManager/'d__79'::'4__this' IL_0014: ldloca.s V_0 IL_0016: ldc.i4.m1 IL_0017: stfld int32 GameNetworkManager/'d__79'::'1__state' IL_001c: ldloca.s V_0 IL_001e: тип значения ldflda [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder GameNetworkManager/'d__79'::'t__builder' IL_0023: ldloca.s V_0 IL_0025: вызвать экземпляр void [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::Start(!!0/*valuetype GameNetworkManager/'d__79'*/&) IL_002a: в отставке } // конец метода GameNetworkManager::StartHost Вот реальная функциональность, на которую есть ссылка, к которой мне не удалось получить доступ

.class вложенный частный запечатанный автоматический ansi beforefieldinit 'd__79' расширяет [netstandard]System.ValueType реализует [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine { .custom экземпляр void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (01 00 00 00 ) .field public int32 '1__state' .field public valuetype [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder 't__builder' .field публичного класса GameNetworkManager '4__this' .field частного класса GameNetworkManager '7__wrap1' .field Private valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 'u__1' .method частный окончательный экземпляр виртуального новостного слотаidebysig void MoveNext() cil управляемый { .override экземпляр метода void [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext() .maxstack 3 .locals инициализация( [0] int32 V_0, [1] класс GameNetworkManager V_1, [2] тип значения [netstandard]System.Nullable`1 V_2, [3] тип значения [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 В_3, [4] класс [netstandard]System.Exception V_4 ) IL_0000: ldarg.0 // это IL_0001: ldfld int32 GameNetworkManager/'d__79'::'1__state' IL_0006: stloc.0 // V_0 IL_0007: ldarg.0 // это IL_0008: класс ldfld GameNetworkManager GameNetworkManager/'d__79'::'4__this' IL_000d: stloc.1 // V_1 .пытаться { IL_000e: ldloc.0 // V_0 IL_000f: brfalse IL_009e // [654 5 - 654 89] IL_0014: вызов !!0/*class MenuManager*/ [UnityEngine.CoreModule]UnityEngine.Object::FindObjectOfType() IL_0019: вызов bool [UnityEngine.CoreModule]UnityEngine.Object::op_Implicit(класс [UnityEngine.CoreModule]UnityEngine.Object) IL_001e: brtrue.s IL_002f // [656 7 - 656 94] IL_0020: ldstr «Сценарий менеджера меню отсутствует в сцене; невозможно запустить хост» IL_0025: вызов void [UnityEngine.CoreModule]UnityEngine.Debug::Log(объект) IL_002a: покинуть IL_010e // [660 7 - 660 61] IL_002f: вызов класса GameNetworkManager GameNetworkManager::get_Instance() IL_0034: тип значения экземпляра callvirt [netstandard]System.Nullable`1 GameNetworkManager::get_currentLobby() IL_0039: stloc.2 // V_2 IL_003a: ldloca.s V_2 IL_003c: вызвать экземпляр bool valuetype [netstandard]System.Nullable`1::get_HasValue() IL_0041: brfalse.s IL_0053 // [662 9 - 662 143] IL_0043: ldstr «Пытался запустить хост, но значение currentLobby не равно нулю! Этого не должно произойти. Выходим из currentLobby и устанавливаем значение null." IL_0048: вызов void [UnityEngine.CoreModule]UnityEngine.Debug::Log(объект) // [663 9 - 663 38] IL_004d: ldloc.1 // V_1 IL_004e: экземпляр вызова void GameNetworkManager::LeaveCurrentSteamLobby() // [665 7 - 665 30] IL_0053: ldloc.1 // V_1 IL_0054: ldfld bool GameNetworkManager::disableSteam IL_0059: brtrue.s IL_00d5 // [667 9 - 667 76] IL_005b:ldarg.0 // это IL_005c: вызов класса GameNetworkManager GameNetworkManager::get_Instance() IL_0061: класс stfld GameNetworkManager GameNetworkManager/'d__79'::'7__wrap1' // [668 9 - 668 85] IL_0066: ldc.i4.4 IL_0067: класс вызова [netstandard]System.Threading.Tasks.Task`1 [Facepunch.Steamworks.Win64]Steamworks .SteamMatchmaking::CreateLobbyAsync(int32) IL_006c: тип значения экземпляра callvirt [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1*/> class [netstandard]System.Threading.Tasks.Task`1::GetAwaiter() IL_0071: stloc.3 // V_3 IL_0072: ldloca.s V_3 IL_0074: вызвать экземпляр bool valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::get_IsCompleted() IL_0079: brtrue.s IL_00ba IL_007b:ldarg.0 // это IL_007c: ldc.i4.0 IL_007d: дубль IL_007e: stloc.0 // V_0 IL_007f: stfld int32 GameNetworkManager/'d__79'::'1__state' IL_0084: ldarg.0 // это IL_0085: ldloc.3 // V_3 IL_0086: тип значения stfld [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 GameNetworkManager/'d__79' ::'u__1' IL_008b:ldarg.0 // это IL_008c: тип значения ldflda [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder GameNetworkManager/'d__79'::'t__builder' IL_0091: ldloca.s V_3 IL_0093: ldarg.0 // это IL_0094: вызов экземпляра void [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::AwaitUnsafeOnCompleted(!!0/*valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1*/&, !!1/*valuetype GameNetworkManager/'d__79'*/&) IL_0099: покинуть IL_0121 IL_009e: ldarg.0 // это IL_009f: ldfld valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 GameNetworkManager/'d__79' ::'u__1' IL_00a4: stloc.3 // V_3 IL_00a5: ldarg.0 // это IL_00a6: тип значения ldflda [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 GameNetworkManager/'d__79'::'u__1' IL_00ab: initobj valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 IL_00b1:ldarg.0 // это IL_00b2: ldc.i4.m1 IL_00b3: дубль IL_00b4: stloc.0 // V_0 IL_00b5: stfld int32 GameNetworkManager/'d__79'::'1__state' IL_00ba: ldloca.s V_3 IL_00bc: экземпляр вызова !0/*valuetype [netstandard]System.Nullable`1*/ valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::GetResult() IL_00c1:stloc.2 // V_2 IL_00c2: ldarg.0 // это IL_00c3: класс ldfld GameNetworkManager GameNetworkManager/'d__79'::'7__wrap1' IL_00c8: ldloc.2 // V_2 IL_00c9: экземпляр callvirt void GameNetworkManager::set_currentLobby(valuetype [netstandard]System.Nullable`1) // [669 9 - 669 55] IL_00ce: ldarg.0 // это IL_00cf: ldnull IL_00d0: класс stfld GameNetworkManager GameNetworkManager/'d__79'::'7__wrap1' // [671 7 - 671 72] IL_00d5: вызов !!0/*class MenuManager*/ [UnityEngine.CoreModule]UnityEngine.Object::FindObjectOfType() IL_00da: экземпляр callvirt void MenuManager::StartHosting() // [672 7 - 672 44] IL_00df: ldloc.1 // V_1 IL_00e0: экземпляр вызова void GameNetworkManager::SubscribeToConnectionCallbacks() // [673 7 - 673 32] IL_00e5: ldloc.1 // V_1 IL_00e6: ldc.i4.1 IL_00e7: stfld bool GameNetworkManager::isHostingGame // [674 7 - 674 32] IL_00ec: ldloc.1 // V_1 IL_00ed: ldc.i4.1 IL_00ee: stfld int32 GameNetworkManager::connectedPlayers IL_00f3: оставь.s IL_010e } // конец .try поймать [netstandard]System.Exception { IL_00f5: stloc.s V_4 IL_00f7: ldarg.0 // это IL_00f8: ldc.i4.s -2 // 0xfe IL_00fa: stfld int32 GameNetworkManager/'d__79'::'1__state' IL_00ff: ldarg.0 // это IL_0100: тип значения ldflda [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder GameNetworkManager/'d__79'::'t__builder' IL_0105: ldloc.s V_4 IL_0107: экземпляр вызова void [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::SetException(class [netstandard]System.Exception) IL_010c: оставь.с IL_0121 } // конец улова IL_010e: ldarg.0 // это IL_010f: ldc.i4.s -2 // 0xfe IL_0111: stfld int32 GameNetworkManager/'d__79'::'1__state' IL_0116: ldarg.0 // это IL_0117: тип значения ldflda [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder GameNetworkManager/'d__79'::'t__builder' IL_011c: экземпляр вызова void [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::SetResult() IL_0121: в отставке } // конец метода 'd__79'::MoveNext .method частный окончательный экземпляр виртуального новостного слотаidebysig void SetStateMachine( класс [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine ) цил удалось { .custom экземпляр void [netstandard]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (01 00 00 00 ) .override экземпляр метода void [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine(класс [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) .maxstack 8 IL_0000: ldarg.0 // это IL_0001: тип значения ldflda [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder GameNetworkManager/'d__79'::'t__builder' IL_0006: ldarg.1 // stateMachine IL_0007: экземпляр вызова void [netstandard]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::SetStateMachine(класс [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) IL_000c: в отставку } // конец метода 'd__79'::SetStateMachine } // конец класса 'd__79' Мне до сих пор не удалось получить доступ к частям, которые я действительно хочу изменить, а именно к целому числу, хранящемуся в d__79, потому что я не могу получить доступ к автоматически сгенерированному методу с помощью Harmony.

На данный момент патчер работает и возвращает исходный доступный, но бесполезный метод.

Когда я добавил MethodType.Enumerator в HarmonyPatch(), он просто возвращал сообщение «Данный ключ отсутствует в словаре». ошибка. Я предполагаю, потому что я пытаюсь получить доступ к GetNext StartHost вместо d__79.

[HarmonyTranspiler] [HarmonyPatch(typeof(GameNetworkManager), nameof(GameNetworkManager.StartHost)] статический IEnumerable TranspileMoveNext(IEnumerable instr) { коды вар = новый список(instr); for (int i = 0; я
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»