#ifndef SCHEMA_H
#define SCHEMA_H

class c_schema_system
{
private:
    uintptr_t m_address;

public:
    explicit c_schema_system(uintptr_t address = 0)
            : m_address(address) {}
                
    // Find a schema by name.
    c_schema_system* find(const hash32_t hash)
    {
        // Gets the type scope.
        uintptr_t type_scope = get_type_scope();
        if (type_scope == 0)
        {
            return 0;
        }

        // Reads the entries from the type scope.
        uintptr_t entries = m_process.read<uintptr_t>(type_scope + 0x4C0 + 0x10);
        if (entries == 0) 
        {
            return 0;
        }

        // Reads the entries count.
        uint16_t entries_count = m_process.read<uint16_t>(type_scope + 0x4C0 + 0x26);
        if (entries_count == 0) 
        {
            return 0;
        }

        // Iterates through all entries.
        for (int32_t i = 0; i < entries_count; i++)
        {
            // Reads the declared class.
            uintptr_t declared_class = m_process.read<uintptr_t>(entries + (static_cast<uintptr_t>(i) * 0x18) + 0x10);
            if (declared_class == 0) 
            {
                continue;
            }

            // Reads the class address.
            uintptr_t class_address = m_process.read<uintptr_t>(declared_class + 0x20);
            if (class_address == 0) 
            {
                continue;
            }

            // Reads the class name address.
            uintptr_t class_name_address = m_process.read<uintptr_t>(class_address + 0x08);
            if (class_name_address == 0)
            {
                continue;
            }

            char class_name[120]{};
            
            // Reads the class name.
            if (m_process.read_string(class_name_address, class_name, sizeof(class_name)) == 0)
            {
                continue;
            }
 
            // Compare name hash.
            const hash32_t hashed_str = FNV1a::get(class_name);
            if (hashed_str != hash)
            {
                continue;
            }

            return reinterpret_cast<c_schema_system*>(class_address);
        }

        return 0;
    }

    // Gets the offset of a field by name.
    uint16_t offset(const hash32_t hash)
    {
        // Reads the field count.
        uint16_t fields_count = m_process.read<uint16_t>(reinterpret_cast<uintptr_t>(this) + 0x1C);
        if (fields_count == 0)
        {
            return 0;
        }

        // Reads the fields address.
        uintptr_t fields = m_process.read<uintptr_t>(reinterpret_cast<uintptr_t>(this) + 0x28);
        if (fields == 0)
        {
            return 0;
        }

        // Iterates through all fields.
        for (int32_t i = 0; i < fields_count; i++, fields += 0x20)
        {
            // Reads the field offset address.
            uint16_t offset = m_process.read<uint16_t>(fields + 0x10);
            if (offset == 0) 
            {
                continue;
            }

            // Reads the field name address.
            uintptr_t field_address_name = m_process.read<uintptr_t>(fields);
            if (field_address_name == 0)
            {
                continue;
            }

            char field_name[120]{};
            
            // Reads the field name.
            if (m_process.read_string(field_address_name, field_name, sizeof(field_name)) == 0)
            {
                continue;
            }
            
            // Compare name hash.
            const hash32_t hashed_str = FNV1a::get(field_name);
            if (hashed_str != hash)
            {
                continue;
            }

            LOG("%s 0x%x\n", field_name, (long)offset);
            return offset;
        }
        return 0;
    }

private:
    class c_schema_field
    {
    public:
    };

    class c_schema_class_binding
    {
        uintptr_t get_fields() 
        {
            return m_process.read<uintptr_t>(reinterpret_cast<uintptr_t>(this) + 0x28);
        }
        
        uint16_t get_fields_size() 
        {
            return m_process.read<uint16_t>(reinterpret_cast<uintptr_t>(this) + 0x1C);
        }
    };

    // Gets the type scope for client.dll module
    uintptr_t get_type_scope() const
    {
        //
        // mov rax, [rbx+0xXXX]
        //
        uintptr_t scope_table = m_process.read<uintptr_t>(reinterpret_cast<uintptr_t>(this) + 0x198);
        if (scope_table == 0)
        {
            return 0;
        }

        //
        // mov rax, [rax+rcx*8]
        // ret
        //
        return m_process.read<uintptr_t>(scope_table + (0x10 * 0x08));
    }
};

#endif // SCHEMA_H

melhore o código