C # - Коллекции и кастинг - PullRequest
1 голос
/ 27 января 2009

У меня есть базовый класс, BaseObject и ряд классов, производных от BaseObject (DerivedObject1, DerivedObject2 и т. Д.)

У меня есть коллекция BaseObjects, в которой я храню производные объекты. Код, который я использую для этого:

// declaring and initializing the idictionary
public IDictionary<ulong, BaseObject> ObjectList = new Dictionary<ulong, BaseObject>();
// how i add derived objects to the collection
ObjectList.Add(TempObject.Guid, new DerivedObject1(this, TempObject.BaseAddress));
ObjectList.Add(TempObject2.Guid, new DerivedObject2(this, TempObject2.BaseAddress));

В классе, где хранится коллекция, я объявляю ссылку на важный объект в коллекции следующим образом:

// in the class
public DerivedObject3 LocalPlayer;
// in a method inside a class
LocalPlayer = (DerivedObject3)ObjectList[TempObject.Guid];

После того, как я вызываю метод, который назначает LocalPlayer ссылку на объект, содержащийся в Idictionary, я пытаюсь получить информацию (специфичную для DerivedObject3) о LocalPlayer в моем основном методе:

static void Main()
{
    ObjectManager OM = new ObjectManager();
    OM.LoadAddresses();
    OM.PopulateList();
    Console.WriteLine(OM.LocalPlayer.Type);
    Console.ReadLine();
}

Однако это просто возвращает «0». Я думаю, что я должен был случайно «сбросить» объект. Я не слишком опытен с .NET или ООП в целом (это хобби).

Я могу опубликовать больше кода (реальный код, а не BaseObject и т. Д.), Если это необходимо. Thankyou.

Редактировать После комментария, который мне нужно было опубликовать больше кода (я не уверен, какие биты связаны с проблемой), я опубликую больше кода (и больше не буду использовать «BaseObject» и т. Д.) Классы WowObject:

class WowObject
{
    protected const uint GuidOffset = 0x30,
        NextObjectOffset = 0x3C,
        TypeOffset = 0x14,
        XPositionOffset = 0x7D0,
        YPositionOffset = 0x7D4,
        ZPositionOffset = 0x7D8,
        RotationOffset = 0x7DC,
        DescriptorFieldsOffset = 0x8;

    protected uint baseAddress;
    protected ObjectManager OM;

    public WowObject(ObjectManager OM, uint baseAddress)
    {
        this.baseAddress = baseAddress;
        this.OM = OM;
    }

    public uint BaseAddress
    {
        get { return baseAddress; }
        set { baseAddress = value; }
    }

    public uint DescriptorFields
    {
        get { return OM.ReadUInt32((IntPtr)(BaseAddress + DescriptorFieldsOffset)); }
    }

    public int Type
    {
        get { return OM.ReadInt32((IntPtr)(BaseAddress + TypeOffset)); }
    }

    public virtual ulong Guid
    {
        get { return OM.ReadULong((IntPtr)(BaseAddress + GuidOffset)); }
        set { return;  }
    }

    public virtual float XPos
    {
        get { return OM.ReadFloat((IntPtr)(BaseAddress + XPositionOffset)); }
    }

    public virtual float YPos
    {
        get { return OM.ReadFloat((IntPtr)(BaseAddress + YPositionOffset)); }
    }

    public virtual float ZPos
    {
        get { return OM.ReadFloat((IntPtr)(BaseAddress + ZPositionOffset)); }
    }

    public float Rotation
    {
        get { return OM.ReadFloat((IntPtr)(BaseAddress + RotationOffset)); }
    }
}

class CreatureObject : WowObject
{
    protected const uint LevelOffset = 0x35 * 4,
        CurrentHealthOffset = 0x17 * 4,
        MaxHealthOffset = 0x1F * 4,
        CurrentManaOffset = 0x18 * 4,
        MaxManaOffset = 0x20 * 4,
        TargetGuidOffset = 0x12*4;
    private CreatureObject targetObject;

    public CreatureObject(ObjectManager OM, uint BaseAddress)
        : base(OM, BaseAddress)
    { }

    public CreatureObject TargetObject
    {
        get { return targetObject; }
        set { targetObject = value; }
    }

    public ulong TargetGuid
    {
        get { return OM.ReadULong((IntPtr)(BaseAddress + TargetGuid)); }
    }

    public int Level
    {
        get { return OM.ReadInt32((IntPtr)(DescriptorFields + LevelOffset)); }
    }

    public int CurrentHealth
    {
        get { return OM.ReadInt32((IntPtr)(DescriptorFields + CurrentHealthOffset)); }
    }

    public int MaxHealth
    {
        get { return OM.ReadInt32((IntPtr)(DescriptorFields + MaxHealthOffset)); }
    }

    public int CurrentMana
    {
        get { return OM.ReadInt32((IntPtr)(DescriptorFields + CurrentMana)); }
    }

    public int MaxMana
    {
        get { return OM.ReadInt32((IntPtr)(DescriptorFields + MaxManaOffset)); }
    }

    public int HealthPercent
    {
        get
        {
            double percentage = CurrentHealth / MaxHealth;
            percentage = percentage * 100;
            return (int)Math.Round(percentage);
        }
    }
}

class NpcObject : CreatureObject
{
    protected const uint SummonedByOffset = 0xE * 4,
        AttackingGuidOffset = 0x0A38;

    public NpcObject(ObjectManager OM, uint BaseAddress)
        : base(OM, BaseAddress)
    { }

    public ulong AttackingGuid
    {
        get { return OM.ReadULong((IntPtr)(BaseAddress + AttackingGuidOffset)); }
    }

    public ulong SummonedBy
    {
        get { return OM.ReadULong((IntPtr)(DescriptorFields + SummonedByOffset)); }
    }
}

class PlayerObject : CreatureObject
{
    protected const uint CurrentRageOffset = 0x19 * 4,
        CurrentEnergyOffset = 0x1B * 4,
        MaxEnergyOffset = 0x23 * 4;

    public PlayerObject(ObjectManager OM, uint BaseAddress)
        : base(OM, BaseAddress)
    { }

    public int CurrentRage
    {
        get
        {
            int RageTemp = OM.ReadInt32((IntPtr)(DescriptorFields + CurrentRageOffset));
            return (int)(Math.Floor((double)(RageTemp / 10)));
        }
    }

    public int MaxRage
    {
        get { return 100; }
    }

    public int CurrentEnergy
    {
        get { return OM.ReadInt32((IntPtr)(DescriptorFields + CurrentEnergyOffset)); }
    }

    public int MaxEnergy
    {
        get { return OM.ReadInt32((IntPtr)(DescriptorFields + MaxEnergyOffset)); }
    }
}

class LocalCharacter : PlayerObject
{
    private ulong guid = 0;

    public LocalCharacter(ObjectManager OM, uint BaseAddress)
        : base(OM, BaseAddress)
    { }

    public override ulong Guid
    {
        get { return guid; }
        set { guid = value; }
    }
}

class GameObject : WowObject
{
    protected const uint gameObject_XPos = 0x10 * 4,
        gameObject_YPos = 0x11 * 4,
        gameObject_ZPos = 0x12 * 4;

    public GameObject(ObjectManager OM, uint BaseAddress)
        : base(OM, BaseAddress)
    { }

    public override float XPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + gameObject_XPos)); }
    }

    public override float YPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + gameObject_YPos)); }
    }

    public override float ZPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + gameObject_ZPos)); }
    }
}

class DynamicObject : WowObject
{
    protected const uint dynamicObject_XPos = 0xB * 4,
        dynamicObject_YPos = 0xC * 4,
        dynamicObject_ZPos = 0xD * 4;

    public DynamicObject(ObjectManager OM, uint BaseAddress)
        : base(OM, BaseAddress)
    { }

    public override float XPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + dynamicObject_XPos)); }
    }

    public override float YPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + dynamicObject_YPos)); }
    }

    public override float ZPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + dynamicObject_ZPos)); }
    }
}

class CorpseObject : WowObject
{
    protected const uint corpseObject_XPos = 0xB * 4,
            corpseObject_YPos = 0xC * 4,
            corpseObject_ZPos = 0xD * 4;

    public CorpseObject(ObjectManager OM, uint BaseAddress)
        : base(OM, BaseAddress)
    { }

    public override float XPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + corpseObject_XPos)); }
    }

    public override float YPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + corpseObject_YPos)); }
    }

    public override float ZPos
    {
        get { return OM.ReadFloat((IntPtr)(DescriptorFields + corpseObject_ZPos)); }
    }
}

Диспетчер объектов - расширяет класс чтения памяти (отсюда и ReadUInt32 и т. Д.)

class ObjectManager : Memory
{
    public IDictionary<ulong, WowObject> ObjectList = new Dictionary<ulong, WowObject>();

    public LocalCharacter LocalPlayer;

    private const uint staticClientConnection = 0x011CA310,     // static client connection, same address every boot
        objectManagerOffset = 0x28A4,                           // offset from the ClientConnection to the object manager
        localGuidOffset = 0xC0,                                 // offset from the object manager to the local guid
        firstObjectOffset = 0xAC,                               // offset from the object manager to the first object
        nextObjectOffset = 0x3C;                                // offset from
    private uint objectManagerBase;                             // the address off the object manager

    public void LoadAddresses()
    {
        objectManagerBase = ReadUInt32((IntPtr)(ReadUInt32((IntPtr)(staticClientConnection)) + objectManagerOffset));
        LocalPlayer = new LocalCharacter(this, ReadUInt32((IntPtr)(objectManagerBase + localGuidOffset)));
    }

    public void PopulateList()
    {
        WowObject TempObject = new WowObject(this, ReadUInt32((IntPtr)(objectManagerBase + firstObjectOffset)));

        while (TempObject.BaseAddress != 0 && TempObject.BaseAddress % 2 == 0)
        {
            if (TempObject.Type == 3)
                ObjectList.Add(TempObject.Guid, new NpcObject(this, TempObject.BaseAddress));
            if (TempObject.Type == 4)
            {
                if (TempObject.Guid != LocalPlayer.Guid)
                    ObjectList.Add(TempObject.Guid, new PlayerObject(this, TempObject.BaseAddress));
                else
                {
                    ObjectList.Add(TempObject.Guid, new PlayerObject(this, TempObject.BaseAddress));
                    LocalPlayer = (LocalCharacter)ObjectList[TempObject.Guid];
                }
            }

            TempObject.BaseAddress = ReadUInt32((IntPtr)(TempObject.BaseAddress + nextObjectOffset));
        }
    }
}

Основной метод:

static void Main()
{
    ObjectManager OM = new ObjectManager();
    OM.SetProcess("Wow", "Read");
    OM.LoadAddresses();
    OM.PopulateList();
    Console.WriteLine(OM.LocalPlayer.Type);
    Console.ReadLine();
}

Ответы [ 2 ]

0 голосов
/ 27 января 2009

Если вы храните несколько объектов одного базового типа в коллекции, как правило, вам никогда не потребуется указывать точный тип объекта. Взгляните на это сообщение в блоге о принципах OOD . В частности, вы нарушаете принцип подстановки Лискова, который кратко описан в этой статье, и более подробное объяснение связано с ним.

Я бы порекомендовал прочитать эту статью несколько раз, потратив некоторое время на изучение ООД как по ссылкам, включенным в этот блог, так и по Википедии, поскольку это очень техническая тема. Это не то, что обычно можно узнать в одном чтении. Это также то, что требует сознательных усилий для правильного использования даже после того, как вы понимаете концепции, но в основном это необходимо при написании программного обеспечения в текущий день.

0 голосов
/ 27 января 2009

Сделать метод из базового класса виртуальным, а метод из переопределенного производного класса. И практическое правило, избегайте понижения до определенного типа, вы должны использовать свойства / методы из базового класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...