0

我有一个 DBC 文件,它是一个游戏的数据库文件,包含游戏中可用的法术数据,如 ID、SpellName、Category 等......结构是这样的:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct SpellEntry
    {
        public uint ID;
        public uint Category;
        public float speed;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I4)]
        public int[] Reagent;
        public int EquippedItemClass;
        [MarshalAs(UnmanagedType.LPStr)] // Crash here
        public string SpellName;
    }

我正在使用二进制阅读器读取文件,并将其编组到结构。片段:

                    binReader.BaseStream.Seek(DBCFile.HEADER_SIZE + (index * 4 * 234), SeekOrigin.Begin);
                    buff = binReader.ReadBytes(buff.Length);
                    GCHandle handdle = GCHandle.Alloc(buff, GCHandleType.Pinned);
                    Spell.SpellEntry testspell = (Spell.SpellEntry)Marshal.PtrToStructure(handdle.AddrOfPinnedObject(), typeof(Spell.SpellEntry));
                    handdle.Free();

现在更复杂一些,让我们看看 DBC 文件如何存储字符串,例如 SpellName。它不在记录中,字符串包含在文件末尾的“字符串表”块中。记录中的字符串数据包含字符串表中字符串的数字(偏移量)。(所以它不是一个真正的字符串)。

我设法从字符串块(在文件末尾)读取所有字符串到字符串 []。(这不是在开始阅读记录之前)然后我会开始阅读记录,但第一个问题是:

1.)我无法阅读它,因为它在我的结构的最后一行“崩溃”(因为它真的不是字符串) 2.)我无法为数字分配字符串。

当我阅读它时,它将是一个数字,但最后,我必须将该字符串分配给字符串表中的数字所指向的 SpellName。天哪

4

1 回答 1

1
public struct SpellEntry
{
    //...
    private int SpellNameOffset;
    public string SpellName {
        get { return Mumble.GetString(SpellNameOffset); }
    }
}

这很难正确,Mumble 必须是一个静态类,因为您不能向 SpellEntry 添加任何成员。这搞砸了 Marshal.SizeOf(),使它变得太大。您需要初始化 Mumble,以便其静态 GetString() 方法可以访问字符串表。将 SpellName 属性移到另一个类中可以解决问题,但也会使代码变得丑陋。

这很容易使您感到困惑。如果您有一个使用 BitConverter 的版本,那么使用它肯定会更好。实际上,将文件格式与运行时格式分开是一种资产。

于 2010-11-22T22:02:33.790 回答