0

Iam には、ID、SpellName、Category などのゲーム内で使用可能なスペル データを含む、ゲームのデータベース ファイルである DBC ファイルがあります。構造体は次のようなものです。

    [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();

さらに複雑にするために、SpellName などの文字列を DBC ファイルに格納する方法を見てみましょう。レコードではなく、文字列はファイルの末尾の「文字列テーブル」ブロックに含まれています。レコード内の文字列データには、文字列テーブル内の文字列に対する数値 (オフセット) が含まれています。(実際には文字列ではありません)。

文字列ブロック (ファイルの最後) から文字列 [] まで、すべての文字列を読み取ることができました。(これはレコードの読み取りを開始する前ではありません)次に、レコードの読み取りを開始しますが、最初の問題は次のとおりです。

1.) 構造体の最後の行で「クラッシュ」するため、読み取ることができません (実際には文字列ではないため) 2.) 文字列を数値に割り当てることができません。

読むと数字になるのですが、結果として、その文字列を、文字列テーブルの数字が指し示す SpellName に代入する必要があります。ああ

4

1 に答える 1

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

SpellEntry にはメンバーを追加できないため、Mumble は静的クラスでなければなりません。それは Marshal.SizeOf() を台無しにし、大きすぎます。Mumble の静的な GetString() メソッドが文字列テーブルにアクセスできるように、Mumble を初期化する必要があります。SpellName プロパティを別のクラスに移動すると問題は解決しますが、コードも見苦しくなります。

これはあなたをひどく混乱させる傾向があります。BitConverter を使用するバージョンを使用している場合は、代わりにそれを使用することをお勧めします。ファイル形式をランタイム形式から分離することは、実際にはここでの利点です。

于 2010-11-22T22:02:33.790 に答える