• HearthBuddy炉石兄弟 Method 'CollectionDeckBoxVisual.IsValid' not found.


    [CollectionManagerScene_COLLECTION] An exception occurred when calling CacheCustomDecks: System.MissingMethodException: Method 'CollectionDeckBoxVisual.string_4 = IsValid, enum20_0 = null' not found.
    at Triton.Game.Mono.MonoClass.method_7(String string_4, Enum20[] enum20_0, Object[] object_0)
    at Triton.Game.Mono.MonoClass.method_10[T](String string_4, Enum20[] enum20_0, Object[] object_0)
    at Triton.Game.Mono.MonoClass.method_11[T](String string_4, Object[] object_0)
    at Triton.Game.Mapping.CollectionDeckBoxVisual.IsValid()
    at Triton.Bot.Utility.smethod_4()
    at Triton.Bot.Logic.Bots.DefaultBot.DefaultBot.Struct57.MoveNext().

    internal static void smethod_4()
            {
                try
                {
                    CollectionDeckTray collectionDeckTray = CollectionDeckTray.Get();
                    if (collectionDeckTray != null)
                    {
                        foreach (TraySection traySection in collectionDeckTray.m_decksContent.m_traySections)
                        {
                            CollectionDeckBoxVisual deckBox = traySection.m_deckBox;
                            long deckID = deckBox.GetDeckID();
                            string text = deckBox.m_deckName.Text;
                            bool isWild = deckBox.m_isWild;
                            if (deckID != -1L && deckBox.IsValid())
                            {
                                CustomDeckCache customDeckCache = null;
                                bool flag = true;
                                foreach (CustomDeckCache customDeckCache2 in MainSettings.Instance.CustomDecks)
                                {
                                    if (customDeckCache2.DeckId == deckID)
                                    {
                                        customDeckCache = customDeckCache2;
                                        customDeckCache.Name = text;
                                        customDeckCache.IsWild = isWild;
                                        customDeckCache.Save();
                                        flag = false;
                                        break;
                                    }
                                }
                                if (customDeckCache == null)
                                {
                                    customDeckCache = new CustomDeckCache(deckID)
                                    {
                                        DeckId = deckID,
                                        HeroCardId = deckBox.m_heroCardID,
                                        Name = deckBox.GetDeckNameText().Text,
                                        IsWild = isWild
                                    };
                                }
                                CollectionDeck deck = CollectionManager.Get().GetDeck(deckID);
                                if (!deck.m_netContentsLoaded)
                                {
                                    if (customDeckCache.CardIds.Count == 30 && flag)
                                    {
                                        MainSettings.Instance.CustomDecks.Add(customDeckCache);
                                    }
                                }
                                else
                                {
                                    customDeckCache.CardIds.Clear();
                                    foreach (CollectionDeckSlot collectionDeckSlot in deck.m_slots)
                                    {
                                        for (int i = 0; i < collectionDeckSlot.Count; i++)
                                        {
                                            customDeckCache.CardIds.Add(collectionDeckSlot.CardID);
                                        }
                                    }
                                    customDeckCache.Save();
                                    if (flag)
                                    {
                                        MainSettings.Instance.CustomDecks.Add(customDeckCache);
                                        MainSettings.Instance.Save();
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    MainSettings.Instance.CustomDecks.Clear();
                    MainSettings.Instance.Save();
                    throw;
                }
            }
    public bool IsValid()
            {
                return base.method_11<bool>("IsValid", Array.Empty<object>());
            }

    public class CollectionDeckBoxVisual自己在调用

    public long GetDeckID()
            {
                return base.method_11<long>("GetDeckID", Array.Empty<object>());
            }
    internal T method_11<T>(string string_4, params object[] object_0) where T : struct
            {
                return this.method_10<T>(string_4, null, object_0);
            }
    internal T method_10<T>(string string_4, Class276.Enum20[] enum20_0, params object[] object_0) where T : struct
            {
                IntPtr intPtr = this.method_7(string_4, enum20_0, object_0);
                if (intPtr == IntPtr.Zero)
                {
                    return default(T);
                }
                if (typeof(T) == typeof(bool))
                {
                    IntPtr addr = MonoClass.Class276_0.method_26(intPtr);
                    return (T)((object)(MonoClass.ExternalProcessMemory_0.Read<byte>(addr) > 0));
                }
                return MonoClass.ExternalProcessMemory_0.Read<T>(MonoClass.Class276_0.method_26(intPtr));
            }
    internal IntPtr method_7(string string_4, Class276.Enum20[] enum20_0, params object[] object_0)
    {
        IntPtr classInstance = this.GetClassInstance();
        if (classInstance == IntPtr.Zero)
        {
            throw new Exception("Cannot call a method on an object instance that has no address!");
        }
        IntPtr intPtr = this.method_0(string_4, enum20_0);
        if (intPtr == IntPtr.Zero)
        {
            string text = string.Empty;
            if (enum20_0 != null)
            {
                for (int i = 0; i < enum20_0.Length; i++)
                {
                    text += enum20_0[i];
                }
            }
            else
            {
                text = "null";
            }
            throw new MissingMethodException(this.ClassName, "string_4 = " + string_4 + ", enum20_0 = " + text);
        }
        return MonoClass.Class276_0.method_43(intPtr, classInstance, object_0);
    }
    internal IntPtr method_0(string string_4, Class276.Enum20[] enum20_0)
            {
                if (this.IntPtr_0 == IntPtr.Zero)
                {
                    throw new InvalidOperationException("Cannot get a method pointer on an object that has no MonoClass pointer.");
                }
                return MonoClass.smethod_4(this.IntPtr_0, string_4, enum20_0);
            }

    这个里面的this,应该某一个class的IntPtr_0

    internal IntPtr IntPtr_0
            {
                get
                {
                    IntPtr? intPtr = this.nullable_0;
                    if (intPtr == null)
                    {
                        IntPtr? intPtr2 = this.nullable_0 = new IntPtr?(this.vmethod_0(this.AssemblyPath, this.ClassNamespace, this.ClassName));
                        return intPtr2.Value;
                    }
                    return intPtr.GetValueOrDefault();
                }
            }
    private static IntPtr smethod_4(IntPtr intptr_1, string string_4, Class276.Enum20[] enum20_0)
            {
                MonoClass.Class274 @class = new MonoClass.Class274();
                @class.string_0 = string_4;
                @class.enum20_0 = enum20_0;
                Dictionary<string, List<MonoClass.Class273>> dictionary;
                if (!MonoClass.dictionary_3.TryGetValue(intptr_1, out dictionary))
                {
                    MonoClass.dictionary_3.Add(intptr_1, new Dictionary<string, List<MonoClass.Class273>>());
                    dictionary = MonoClass.dictionary_3[intptr_1];
                }
                List<MonoClass.Class273> list;
                if (!dictionary.TryGetValue(@class.string_0, out list))
                {
                    dictionary.Add(@class.string_0, new List<MonoClass.Class273>());
                    list = dictionary[@class.string_0];
                }
                MonoClass.Class273 class2 = list.FirstOrDefault(new Func<MonoClass.Class273, bool>(@class.method_0));
                if (class2 == null)
                {
                    IntPtr intPtr = MonoClass.Class276_0.method_33(intptr_1, @class.string_0, @class.enum20_0);
                    if (intPtr != IntPtr.Zero)
                    {
                        class2 = new MonoClass.Class273(@class.string_0, intPtr, @class.enum20_0);
                        list.Add(class2);
                    }
                }
                if (class2 == null)
                {
                    return IntPtr.Zero;
                }
                return class2.IntPtr_0;
            }

    这里的intptr_1是上面的类的

    下面有一个很奇怪的写法,赋值之后,还可以直接做比较

     int a = 0;
                if ((a = 10) > 9)
                {
                    Console.WriteLine(a);
                }
    internal IntPtr method_33(IntPtr intptr_37, string string_0, params Class276.Enum20[] enum20_0)
            {
                while (intptr_37 != IntPtr.Zero)
                {
                    using (AllocatedMemory allocatedMemory = this.externalProcessMemory_0.CreateAllocatedMemory(256))
                    {
                        allocatedMemory.AllocateOfChunk<IntPtr>("Itr");
                        IntPtr intPtr;
                        while ((intPtr = this.method_35(intptr_37, allocatedMemory["Itr"])) != IntPtr.Zero)
                        {
                            IntPtr address = this.method_37(intPtr);
                            if (this.externalProcessMemory_0.ReadStringA(address) == string_0)
                            {
                                if (enum20_0 != null)
                                {
                                    Class276.Enum20[] array = this.method_31(intPtr);
                                    if (array.Length != enum20_0.Length || !array.SequenceEqual(enum20_0))
                                    {
                                        continue;
                                    }
                                }
                                return intPtr;
                            }
                        }
                        intptr_37 = this.method_25(intptr_37);
                    }
                }
                return IntPtr.Zero;
            }

    有2个while循环

    第一个循环,是传入的intptr_37不为IntPtr.Zero【这里的intptr_37就是类开始的地址】

         基于externalProcessMemory_0分配256的内存

         256的内存里面,分配一个内存chunk

         intPtr = method_35(intptr_37,新分配的内存chunk)

                      第二个循环内部

            [intPtr = method_35(intptr_37,新分配的内存chunk)]  这个在下一次循环的时候会再做一次

            address = method_37(intPtr);

                                用externalProcessMemory_0.ReadStringA(address)读取方法名

                               判断方法名是否匹配,如果匹配,就返回intPtr;否则回到第二个循环

         第二个循环结束,还没有找到符合要求的,

                    会执行intptr_37 = this.method_25(intptr_37);

    第一个循环

    1.  重新分配内存chunk

    2.  第二个循环

    3.  method25修改intptr_37的值

    其中1和3的的修改,是为了在第二个循环中使用

    internal IntPtr method_25(IntPtr intptr_37)
            {
                return this.method_17<IntPtr>(this.intptr_28, new object[]
                {
                    intptr_37
                });
            }

    + intptr_0 0x10000000 System.IntPtr

    + intptr_28 0x100165A7 System.IntPtr   和intptr_0相比,相差0x165A7,也就是‭91559‬

    这里的第二个参数,只传了intptr_37

    private T method_17<T>(IntPtr intptr_37, params object[] object_0) where T : struct
            {
                return this.externalProcessMemory_0.CallInjected<T>(intptr_37, CallingConvention.Cdecl, object_0);
            }

    private readonly ExternalProcessMemory externalProcessMemory_0;

    public class ExternalProcessMemory : MemoryBase  这个类在C#写的GreyMagic里面 

    第二个循环

    1. intPtr = method_35(intptr_37,新分配的内存chunk)

    (intPtr = this.method_35(intptr_37, allocatedMemory["Itr"])  

    这里虽然2个参数没变,但是执行后的返回结果一直在变

    2. address = method_37(intPtr);

    3. 读取方法名,看是否匹配

    this.externalProcessMemory_0.ReadStringA(address)

    注意,在第二个循环里面intptr_37的不会变化的,然后是address在变 。不太清楚allocatedMemory["Itr"]是否会变化

    internal IntPtr method_35(IntPtr intptr_37, IntPtr intptr_38)
            {
                return this.method_17<IntPtr>(this.intptr_19, new object[]
                {
                    intptr_37,
                    intptr_38
                });
            }

    第一个参数是this.intptr_19 = this.intptr_0 + 120353;    intptr_0 是mono.dll的地址

    第二个参数指针数组传递了2个地址,intptr_37和intptr_38。 intptr_37是类开始的地址,intptr_38是新分配的内存chunk

    这里计算的返回结果,会作为method_37的第一个参数。第二个参数指针数组传递的值一直没变,但是返回结果一直在变。

    internal IntPtr method_37(IntPtr intPtr )
            {
                return this.method_17<IntPtr>(this.intptr_21, new object[]
                {
                    intPtr 
                });
            }

     这里第一个参数是this.intptr_21 = this.intptr_0 + 231261;

    第二个参数,指针数组只传递了一个地址intPtr 。 这个地址是intPtr = method_35(intptr_37,新分配的内存chunk)

    这个方法调用后,是为了拿到方法名的地址,根据地址读出方法名

    private T method_17<T>(IntPtr intptr_37, params object[] object_0) where T : struct
            {
                return this.externalProcessMemory_0.CallInjected<T>(intptr_37, CallingConvention.Cdecl, object_0);
            }

    第二个循环,对于类的执行结果如下

    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFC00A0 System.IntPtr
    + address 0x0BCC9A22 System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) ".ctor" string

    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFC00C0 System.IntPtr
    + address 0x0BD05E38 System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) "get_SCALED_UP_LOCAL_SCALE" string

    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFCE148 System.IntPtr
    + address 0x0BD05E52 System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) "set_SCALED_UP_LOCAL_SCALE" string

    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFBFDF8 System.IntPtr
    + address 0x0BCF8FDF System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) "Awake" string


    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFCE168 System.IntPtr
    + address 0x0BC6668E System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) "Update" string

    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFCE188 System.IntPtr
    + address 0x0BCF9174 System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) "Show" string

    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFCE1A8 System.IntPtr
    + address 0x0BCBE79B System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) "Hide" string

    + intptr_37 0x0AD14698 System.IntPtr
    + allocatedMemory["Itr"] 0x03430000 System.IntPtr
    + intPtr 0x0AFCE1C8 System.IntPtr
    + address 0x0BCFAB02 System.IntPtr
    this.externalProcessMemory_0.ReadStringA(address) "IsShown" string

    smethod_4方法的某一次返回值为  + IntPtr_0 0x0AFCE2C8 System.IntPtr,对应的方法名的GetDeckID

    - class2 {Triton.Game.Mono.MonoClass.Class273} Triton.Game.Mono.MonoClass.Class273
    Enum20_0 null ns27.Class276.Enum20[]
    + IntPtr_0 0x0AFCE2C8 System.IntPtr
    Name "GetDeckID" string
    enum20_0 null ns27.Class276.Enum20[]
    + intptr_0 0x00000000 System.IntPtr
    string_0 null string

    method_0方法中监视this的值,

    - this {Triton.Game.Mapping.CollectionDeckBoxVisual} Triton.Game.Mono.MonoClass {Triton.Game.Mapping.CollectionDeckBoxVisual}
    + Address 0x1C995690 System.IntPtr
    AssemblyPath @"C:Program Files (x86)HearthstoneHearthstone_DataManagedAssembly-CSharp.dll" string
    ClassName "CollectionDeckBoxVisual" string

    处理方案

    拿到C:Program Files (x86)HearthstoneHearthstone_DataManagedAssembly-CSharp.dll

    使用ILSpy反编译,然后搜索CollectionDeckBoxVisual,发现这个类是存在的

    搜索CollectionDeckBoxVisual.IsValid,这个方法已经不在了,新的方法名字是

     public bool IsValidForCurrentMode()
    {
        CollectionDeck collectionDeck = GetCollectionDeck();
        if (collectionDeck == null)
        {
            return false;
        }
        bool @bool = Options.Get().GetBool(Option.IN_WILD_MODE);
        return collectionDeck.IsValidForRuleset && collectionDeck.IsValidForFormat(@bool);
    }

    所以,处理思路是,把HearthBuddy里面的IsValid改为IsValidForCurrentMode【注意这里最后是mode不是model】

  • 相关阅读:
    C#在与java对接时候的UrlEncode的坑
    sql server 删除大量数据的一次坑爹之旅
    js实现黑客帝国文字下落效果
    第一个SignalR案例
    简单的放天灯动画
    计量单位符号的书写规范【转】
    阿里云OSS搭建移动应用直传服务的.Net C#示例
    UWP Windows10开发更新磁贴和动态更新磁贴
    UWP Windows10开发获取设备位置(经纬度)
    Asp.Net识别手机访问
  • 原文地址:https://www.cnblogs.com/chucklu/p/11183453.html
Copyright © 2020-2023  润新知