Данный файл DBC, используемый игрой, содержит записи, информацию о внутриигровых используемых заклинаниях.:) (например, идентификатор, имя, повреждение и т. д. и т. д.)
Чтобы быть более сложным, строковые данные сохраняются в блоке после записей.Строковые данные в записях содержат смещение к строке (поэтому на самом деле это не строка)
У меня есть структура для файла DBC, которая выглядит следующим образом:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SpellEntry
{
private const int MAX_EFFECT_INDEX = 3;
public uint ID;
public uint Category;
public uint Dispel;
public uint Mechanic;
public uint Attributes;
public uint AttributesEx;
public uint AttributesEx2;
public uint AttributesEx3;
public uint AttributesEx4;
public uint AttributesEx5;
public uint AttributesEx6;
public uint AttributesEx7;
public uint Stances;
public uint unk_320_2;
public uint StancesNot;
public uint unk_320_3;
public uint Targets;
public uint TargetCreatureType;
public uint RequiresSpellFocus;
public uint FacingCasterFlags;
public uint CasterAuraState;
public uint TargetAuraState;
public uint CasterAuraStateNot;
public uint TargetAuraStateNot;
public uint casterAuraSpell;
public uint targetAuraSpell;
public uint excludeCasterAuraSpell;
public uint excludeTargetAuraSpell;
public uint CastingTimeIndex;
public uint RecoveryTime;
public uint CategoryRecoveryTime;
public uint InterruptFlags;
public uint AuraInterruptFlags;
public uint ChannelInterruptFlags;
public uint procFlags;
public uint procChance;
public uint procCharges;
public uint maxLevel;
public uint baseLevel;
public uint spellLevel;
public uint DurationIndex;
public uint powerType;
public uint manaCost;
public uint manaCostPerlevel;
public uint manaPerSecond;
public uint manaPerSecondPerLevel;
public uint rangeIndex;
public float speed;
public uint modalNextSpell;
public uint StackAmount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] Totem;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I4)]
public int[] Reagent;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.U4)]
public uint[] ReagentCount;
public int EquippedItemClass;
public int EquippedItemSubClassMask;
public int EquippedItemInventoryTypeMask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] Effect;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectDieSides;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectBaseDice;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectDicePerLevel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectRealPointsPerLevel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectBasePoints;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectMechanic;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectImplicitTargetA;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectImplicitTargetB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectRadiusIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectApplyAuraName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectAmplitude;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectMultipleValue;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectChainTarget;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectItemType;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
//public int[] EffectMiscValue;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
//public int[] EffectMiscValueB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectTriggerSpell;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectPointsPerComboPoint;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX)]
public Flag96[] EffectSpellClassMask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] SpellVisual;
public uint SpellIconID;
public uint activeIconID;
public uint spellPriority;
[MarshalAs(UnmanagedType.LPStr)]
public string SpellName;
[MarshalAs(UnmanagedType.LPStr)]
public string Rank;
[MarshalAs(UnmanagedType.LPStr)]
public string Description;
[MarshalAs(UnmanagedType.LPStr)]
public string ToolTip;
public uint ManaCostPercentage;
public uint StartRecoveryCategory;
public uint StartRecoveryTime;
public uint MaxTargetLevel;
public uint SpellFamilyName;
public Flag96 SpellFamilyFlags;
public uint MaxAffectedTargets;
public uint DmgClass;
public uint PreventionType;
public uint StanceBarOrder;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] DmgMultiplier;
public uint MinFactionId;
public uint MinReputation;
public uint RequiredAuraVision;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] TotemCategory;
public int AreaGroupId;
public int SchoolMask;
public uint runeCostID;
public uint spellMissileID;
public uint PowerDisplayId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.R4)]
public float[] unk_320_4;
public uint spellDescriptionVariableID;
public uint SpellDifficultyId;
}
[StructLayout(LayoutKind.Sequential)]
public struct Flag96
{
public uint DwA;
public uint DwB;
public uint DwC;
public override string ToString()
{
return string.Format("DwA: {0} - DwB: {1} - DwC: {2}", DwA, DwB, DwC);
}
}
Итак, чтоЯ пытаюсь сделать маршалинг байтов в эту структуру со следующим кодом:
byte[] buff = new byte[Marshal.SizeOf(typeof(Spell.SpellEntry))];
binReader.BaseStream.Seek(DBCFile.HEADER_SIZE + (index * 4 * 234), SeekOrigin.Begin);
var bytes = binReader.ReadBytes(buff.Length);
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var obj = (Spell.SpellEntry)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(Spell.SpellEntry));
handle.Free();
, что дает мне AccessViolationException в строке Marshal.PtrToStructure.Я подозреваю, что моя структура недействительна, как-то, вы можете исправить меня или дать подсказку?Что интересно, когда я отлаживаю в IDE, похоже, что он правильно читает структуру, но выдает это исключение ... странно.
Я также пытался читать в struct один за другим, как
spell[index].ID = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Category = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Dispel = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Mechanic = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
, который работает на 100% хорошо для меня, но выглядит неубедительно, и это действительно долго в коде.Marshaling выглядит более профессионально :) Итак, что вы думаете, Маршалинг быстрее, чем читать по одному, если да, как мне это исправить? Спасибо