public override void Read(IBitReader reader) { base.Read(reader); this._Timestamp = ImportTimestamp(reader.ReadUInt64()); this._SaveFileName = reader.ReadString(); var gameVersion = reader.ReadUInt16(); var saveVersion = reader.ReadUInt16(); var unknown1 = reader.ReadUInt16(); // 10 var unknown2 = reader.ReadUInt16(); // 0 this._UserBuildInfo = reader.ReadUInt32(); if (gameVersion != 3) { throw new SaveFormatException("unsupported save data game version"); } if (saveVersion < 20 || saveVersion > 22) { throw new SaveFormatException("unsupported save data save version"); } if (unknown1 != 10 || unknown2 != 0) { throw new SaveFormatException("unsupported save data header data"); } this._LevelName = reader.ReadString(); this._Unknown1 = reader.ReadUInt32(); reader.ReadStringList(this._PreloadedBundleNames); reader.ReadStringDictionary(this._LayerInclusion); var bundleHeapCount = reader.ReadUInt16(12); this._BundleHeaps.Clear(); for (int i = 0; i < bundleHeapCount; i++) { reader.PushFrameLength(24); var bundleHeap = new Data.BundleHeapInfo(); bundleHeap.Unknown1 = reader.ReadString(); bundleHeap.Unknown2 = reader.ReadUInt32(); bundleHeap.Unknown3 = reader.ReadUInt32(); bundleHeap.Type = (Data.BundleHeapType)reader.ReadUInt8(); bundleHeap.Unknown4 = reader.ReadUInt32(); bundleHeap.Unknown5 = reader.ReadBoolean(); bundleHeap.Unknown6 = reader.ReadUInt8(); bundleHeap.Unknown7 = reader.ReadUInt8(); bundleHeap.Unknown8 = reader.ReadUInt32(); if (saveVersion < 17) { reader.SkipBoolean(); } this._BundleHeaps.Add(bundleHeap); reader.PopFrameLength(); } var unknown3Count = reader.ReadUInt16(12); this._Unknown2.Clear(); for (int i = 0; i < unknown3Count; i++) { reader.PushFrameLength(24); var instance = new Data.SaveDataUnknown0(); instance.Unknown1 = reader.ReadUInt16(); instance.Unknown2 = reader.ReadUInt16(); instance.Unknown3 = reader.ReadUInt8(); this._Unknown2.Add(instance); reader.PopFrameLength(); } // not actually a Guid, but we will borrow it for sake of simplicity this._LevelHash = reader.ReadGuid(); var unknown5 = reader.ReadUInt32(20); if (unknown5 != 0) { throw new NotImplementedException(); } reader.SkipBits((int)unknown5); // TODO(gibbed): position move this._Unknown3 = reader.ReadUInt16(); this._Unknown4 = this._Unknown3 >= 5 ? reader.ReadUInt16() : (ushort)0; this._Unknown5 = reader.ReadBoolean(); reader.PushFramePosition(26); var componentDataPosition = reader.ReadUInt32(26); var entityBulkDataLength = reader.ReadUInt32(); var entityBulkDataPosition = reader.Position; reader.SkipBits((int)entityBulkDataLength); var unknown9 = reader.Position; reader.PushFrameLength(saveVersion >= 18 ? 24 : 6); reader.PushFrameLength(24); this._Unknown6 = reader.ReadString(); this._Unknown7 = reader.ReadString(); this._SaveName = reader.ReadString(); reader.PopFrameLength(); this._Unknown8 = reader.ReadUInt32(); this._Unknown9 = reader.ReadGuid(); this._Unknown10 = reader.ReadUInt32(); reader.PopFrameLength(); var unknown16 = reader.ReadUInt32(26); if (unknown9 != unknown16) { throw new FormatException(); } var agentBulkDataLength = reader.ReadUInt32(); var agentBulkDataPosition = reader.Position; reader.SkipBits((int)agentBulkDataLength); var agentDataCount = reader.ReadUInt8(4); var agentDataOffsetLookup = new Dictionary <byte, uint[]>(); for (int i = 0; i < agentDataCount; i++) { var index = reader.ReadUInt8(); var agentDataOffsets = new uint[5]; for (int j = 0; j < 5; j++) { var agentDataOffset = agentDataOffsets[j] = reader.ReadUInt32(26); if (agentDataOffset != 0) { if (agentDataOffset < agentBulkDataPosition || agentDataOffset > agentBulkDataPosition + agentBulkDataLength) { throw new FormatException(); } } } agentDataOffsetLookup.Add(index, agentDataOffsets); } reader.PushFrameLength(24); var entityDataCount = reader.ReadUInt16(); var entityDataOffsets = new Dictionary <uint, Tuple <uint?, uint?> >(); for (int i = 0; i < entityDataCount; i++) { var entityId = reader.ReadUInt32(); uint?entityData0Offset = null; uint?entityData1Offset = null; var entityHasData0 = reader.ReadBoolean(); if (entityHasData0 == true) { var entityDataOffset = reader.ReadUInt32(26); if (entityDataOffset < entityBulkDataPosition || entityDataOffset > entityBulkDataPosition + entityBulkDataLength) { throw new FormatException(); } entityData0Offset = entityDataOffset; } var entityHasData1 = reader.ReadBoolean(); if (entityHasData1 == true) { var entityDataOffset = reader.ReadUInt32(26); if (entityDataOffset < entityBulkDataPosition || entityDataOffset > entityBulkDataPosition + entityBulkDataLength) { throw new FormatException(); } entityData1Offset = entityDataOffset; } entityDataOffsets.Add(entityId, new Tuple <uint?, uint?>(entityData0Offset, entityData1Offset)); } var unknown17Count = reader.ReadUInt16(); this._Unknown11.Clear(); for (int i = 0; i < unknown17Count; i++) { this._Unknown11.Add(reader.ReadUInt32()); } var unknown18Count = reader.ReadUInt16(); for (int i = 0; i < unknown18Count; i++) { reader.PushFrameLength(24); var unknown19 = reader.ReadUInt32(); var unknown20Count = reader.ReadUInt16(); var unknown20 = new uint[unknown20Count]; for (int j = 0; j < unknown20Count; j++) { unknown20[j] = reader.ReadUInt32(); } reader.PopFrameLength(); throw new NotImplementedException(); } var unknown12Count = reader.ReadUInt16(); this._Unknown12.Clear(); for (int i = 0; i < unknown12Count; i++) { this._Unknown12.Add(reader.ReadUInt32()); } reader.PopFrameLength(); reader.PopFramePosition(); reader.PushFrameLength(24); var agentCount = reader.ReadUInt8(4); this._Agents.Clear(); for (int i = 0; i < agentCount; i++) { var nameHash = reader.ReadUInt32(); var index = reader.ReadUInt8(); var agent = AgentFactory.Create(nameHash); agent.Read0(reader, index); this._Agents.Add(index, agent); } reader.PopFrameLength(); if (reader.FrameCount != 0) { throw new SaveFormatException(); } if (reader.Position != componentDataPosition) { throw new SaveFormatException(); } reader.PushFrameLength(32); this._ComponentContainerAgents.Clear(); this._Unknown13 = reader.ReadUInt16(); if (this._Unknown13 == 1) { var componentCount = reader.ReadUInt16(); for (int i = 0; i < componentCount; i++) { reader.PushFrameLength(24); var componentNameHash = reader.ReadUInt32(); var componentVersion = reader.ReadUInt16(); var component = ComponentContainerAgentFactory.Create(componentNameHash); component.Read(reader, componentVersion); reader.PopFrameLength(); this._ComponentContainerAgents.Add(component); } } reader.PopFrameLength(); ReadAgentData(reader, this._Agents, agentDataOffsetLookup, 0, (r, t) => t.Read1(r, this._Unknown4)); ReadAgentData(reader, this._Agents, agentDataOffsetLookup, 1, (r, t) => t.Read2(r)); ReadAgentData(reader, this._Agents, agentDataOffsetLookup, 2, (r, t) => t.Read3(r, this._Unknown4)); ReadAgentData(reader, this._Agents, agentDataOffsetLookup, 3, (r, t) => t.Read4(r)); ReadAgentData(reader, this._Agents, agentDataOffsetLookup, 4, (r, t) => t.Read5(r)); /* * var entities = new List<Entities.Entity>(); * foreach (var kv in entityDataOffsets) * { * var entityDataFirstOffset = kv.Value.Item1; * var entityDataSecondOffset = kv.Value.Item2; * * var entity = Entities.EntityFactory.Create(kv.Key); * * if (entityDataFirstOffset.HasValue == true) * { * reader.Position = (int)entityDataFirstOffset.Value; * reader.PushFrameLength(24); * entity.Read0(reader); * reader.PopFrameLength(); * } * * if (entityDataSecondOffset.HasValue == true) * { * reader.Position = (int)entityDataSecondOffset.Value; * reader.PushFrameLength(24); * entity.Read1(reader); * reader.PopFrameLength(); * } * * entities.Add(entity); * } */ this._Entities.Clear(); foreach (var kv in entityDataOffsets) { var entityData0Offset = kv.Value.Item1; var entityData1Offset = kv.Value.Item2; var rawEntity = new Entities.RawEntity(); rawEntity.Id = kv.Key; if (entityData0Offset.HasValue == true) { reader.Position = (int)entityData0Offset.Value; rawEntity.Data0Length = (int)reader.ReadUInt32(24); rawEntity.Data0Bytes = reader.ReadBits(rawEntity.Data0Length); } if (entityData1Offset.HasValue == true) { reader.Position = (int)entityData1Offset.Value; rawEntity.Data1Length = (int)reader.ReadUInt32(24); rawEntity.Data1Bytes = reader.ReadBits(rawEntity.Data1Length); } this._Entities.Add(rawEntity); } if (reader.FrameCount != 0) { throw new SaveFormatException(); } if (reader.HasUnreadBits() == true) { throw new SaveFormatException(); } }
public override void Read(IBitReader reader) { base.Read(reader); var baseVersion = reader.ReadUInt32(); if (baseVersion < 1 || baseVersion > 11) { throw new SaveFormatException("unsupported base version"); } var version = baseVersion >= 11 ? reader.ReadUInt16() : baseVersion >= 8 ? (ushort)9 : (ushort)4; if (version > 10) { throw new SaveFormatException("unsupported version"); } var unknownLength = reader.PushFrameLength(24); if (unknownLength == 0) { this._Unknown = null; } else { this._Unknown = new Components.UnknownComponent(); this._Unknown.Read(reader, baseVersion); } reader.PopFrameLength(); var inventoryLength = reader.PushFrameLength(24); if (inventoryLength == 0) { this._Inventory = null; } else { this._Inventory = new Components.InventoryComponent(); this._Inventory.Read(reader, version); } reader.PopFrameLength(); var equipmentLength = reader.PushFrameLength(24); if (equipmentLength == 0) { this._Equipment = null; } else { this._Equipment = new Components.EquipmentComponent(); this._Equipment.Read(reader, version); } reader.PopFrameLength(); if (baseVersion >= 2) { var progressionLength = reader.PushFrameLength(24); if (progressionLength == 0) { this._Progression = null; } else { this._Progression = new Components.ProgressionComponent(); this._Progression.Read(reader, version, this._ExcludeProfiles, this._ExcludePresets); } reader.PopFrameLength(); } if (baseVersion >= 6) { var craftingProgressionLength = reader.PushFrameLength(24); if (craftingProgressionLength == 0) { this._CraftingProgression = null; } else { this._CraftingProgression = new Components.CraftingProgressionComponent(); this._CraftingProgression.Read(reader, version); } reader.PopFrameLength(); } if (baseVersion >= 4) { var solderHealthLength = reader.PushFrameLength(24); if (solderHealthLength == 0) { this._SoldierHealth = null; } else { this._SoldierHealth = new Components.SoldierHealthComponent(); this._SoldierHealth.Read(reader, version); } reader.PopFrameLength(); } if (baseVersion <= 4) { reader.SkipBits(2); // two booleans } }
public void Read(IBitReader reader, ushort baseVersion, bool excludeProfiles, bool excludePresets) { this._Level = reader.ReadInt32(); this._Unknown1 = reader.ReadFloat32(); this._Unknown2 = reader.ReadUInt32(); // skill points? if (baseVersion < 5) { return; } var version = reader.ReadUInt32(); if (version > 6) { throw new SaveFormatException("unsupported version"); } if (version >= 2 && version <= 3) { reader.SkipBits(32); } if (version >= 3) { this._Unknown3 = reader.ReadUInt32(); // skill points? } var skillGroupCount = reader.ReadUInt16(); this._SkillGroups.Clear(); for (int i = 0; i < skillGroupCount; i++) { var skillGroup = new Data.SkillGroup(); skillGroup.Read(reader); this._SkillGroups.Add(skillGroup); } if (excludeProfiles == false) { this._CurrentProfileId = reader.ReadInt32(); var profileCount = reader.ReadUInt16(); this._Profiles.Clear(); for (int i = 0; i < profileCount; i++) { var profile = new Data.Profile(); profile.Read(reader, version); this._Profiles.Add(profile); } } if (excludePresets == false) { this._CurrentPresetIndex = reader.ReadInt32(); var presetCount = reader.ReadUInt16(); this._Presets.Clear(); for (int i = 0; i < presetCount; i++) { var preset = new Data.Preset(); preset.Read(reader); this._Presets.Add(preset); } } }