/// <summary> /// Splits character data into several sections for easier parsing /// </summary> private void ReadHeaders(byte[] rawCharacterData) { if (rawCharacterData[0] != 0x55 || rawCharacterData[1] != 0xAA || rawCharacterData[2] != 0x55 || rawCharacterData[3] != 0xAA) { throw new Exception("Not a Diablo II Save file"); } if (rawCharacterData.Length == 130) { throw new EndOfStreamException("Brand new D2GS characters are not supported"); } OriginalBytes = rawCharacterData; OriginalCharacterBytes = null; OriginalSkillBytes = null; OriginalInventoryBytes = null; byte[] statBytes = GetStatBytes(rawCharacterData); byte[] characterBytes = GetCharacterBytes(rawCharacterData); byte[] skillBytes = GetSkillBytes(rawCharacterData); byte[] inventoryBytes = GetInventoryBytes(rawCharacterData); inventory = new Inventory(inventoryBytes); character = new Character(characterBytes); stat = new Stat(statBytes); skill = new Skill(skillBytes); // Stats will always be different, we're not reading the fractional portion of hp/mana/stamina FailedCharacterDecoding = !characterBytes.SequenceEqual(character.GetCharacterBytes()); FailedSkillDecoding = !skillBytes.SequenceEqual(skill.GetSkillBytes()); FailedInventoryDecoding = !inventoryBytes.SequenceEqual(inventory.GetInventoryBytes(character.HasMercenary)); if (FailedCharacterDecoding) { OriginalCharacterBytes = characterBytes; } if (FailedInventoryDecoding) { OriginalInventoryBytes = inventoryBytes; } if (FailedSkillDecoding) { OriginalSkillBytes = skillBytes; } // watch property Level stat.PropertyChanged += (sender, args) => { if (((PropertyChangedEventArgs)args).PropertyName == "Level") { CorrectLevel(stat.Level); } }; }
/// <summary> /// Splits character data into several sections for easier parsing /// </summary> private void ReadHeaders(byte[] rawCharacterData) { if (rawCharacterData[0] != 0x55 || rawCharacterData[1] != 0xAA || rawCharacterData[2] != 0x55 || rawCharacterData[3] != 0xAA) { throw new Exception("Not a Diablo II Save file"); } OriginalCharacterBytes = null; OriginalSkillBytes = null; OriginalInventoryBytes = null; byte[] statBytes = GetStatBytes(rawCharacterData); byte[] characterBytes = GetCharacterBytes(rawCharacterData); byte[] skillBytes = GetSkillBytes(rawCharacterData); byte[] inventoryBytes = GetInventoryBytes(rawCharacterData); inventory = new Inventory(inventoryBytes); character = new Character(characterBytes); stat = new Stat(statBytes); skill = new Skill(skillBytes); // Stats will always be different, we're not reading the fractional portion of hp/mana/stamina FailedCharacterDecoding = !characterBytes.SequenceEqual(character.GetCharacterBytes()); FailedSkillDecoding = !skillBytes.SequenceEqual(skill.GetSkillBytes()); FailedInventoryDecoding = !inventoryBytes.SequenceEqual(inventory.GetInventoryBytes(character.HasMercenary)); if (FailedCharacterDecoding) { OriginalCharacterBytes = characterBytes; } if (FailedInventoryDecoding) { OriginalInventoryBytes = inventoryBytes; } if (FailedSkillDecoding) { OriginalSkillBytes = skillBytes; } }
public byte[] GetBytes(bool skipFailedData = false) { byte[] characterBytes = (skipFailedData && FailedCharacterDecoding) ? OriginalCharacterBytes : Character.GetCharacterBytes(); byte[] statsBytes = Stat.GetStatBytes(); byte[] skillBytes = (skipFailedData && FailedSkillDecoding) ? OriginalSkillBytes : Skill.GetSkillBytes(); byte[] inventoryBytes = (skipFailedData && FailedInventoryDecoding) ? OriginalInventoryBytes : Inventory.GetInventoryBytes(Character.HasMercenary); byte[] rawCharacterData = new byte[characterBytes.Length + statsBytes.Length + skillBytes.Length + inventoryBytes.Length]; Array.Copy(characterBytes, rawCharacterData, characterBytes.Length); Array.Copy(statsBytes, 0, rawCharacterData, characterBytes.Length, statsBytes.Length); Array.Copy(skillBytes, 0, rawCharacterData, characterBytes.Length + statsBytes.Length, skillBytes.Length); Array.Copy(inventoryBytes, 0, rawCharacterData, characterBytes.Length + statsBytes.Length + skillBytes.Length, inventoryBytes.Length); FixHeaders(ref rawCharacterData); return(rawCharacterData); }
/// <summary> /// Saves player data to specified path /// </summary> /// <param name="filePath">Path to save character data as</param> public void Write(Stream saveFile, bool skipFailedData) { byte[] characterBytes = (skipFailedData && FailedCharacterDecoding) ? OriginalCharacterBytes : Character.GetCharacterBytes(); byte[] statsBytes = Stat.GetStatBytes(); byte[] skillBytes = (skipFailedData && FailedSkillDecoding) ? OriginalSkillBytes : Skill.GetSkillBytes(); byte[] inventoryBytes = (skipFailedData && FailedInventoryDecoding) ? OriginalInventoryBytes : Inventory.GetInventoryBytes(Character.HasMercenary); byte[] rawCharacterData = new byte[characterBytes.Length + statsBytes.Length + skillBytes.Length + inventoryBytes.Length]; Array.Copy(characterBytes, rawCharacterData, characterBytes.Length); Array.Copy(statsBytes, 0, rawCharacterData, characterBytes.Length, statsBytes.Length); Array.Copy(skillBytes, 0, rawCharacterData, characterBytes.Length + statsBytes.Length, skillBytes.Length); Array.Copy(inventoryBytes, 0, rawCharacterData, characterBytes.Length + statsBytes.Length + skillBytes.Length, inventoryBytes.Length); FixHeaders(ref rawCharacterData); using (BinaryWriter bw = new BinaryWriter(saveFile)) { bw.Write(rawCharacterData); } //File.WriteAllBytes(filePath, rawCharacterData); }