public void ReadMapPreference(GameSave gameSave) { var mapProps = gameSave.Map.MapProperties; int mapPropIndex = int.Parse(this.ReadSaveString()) - 1; if (mapPropIndex < mapProps.Count) { var mapProp = (GameProperty)mapProps[mapPropIndex]; int valIndex = this.ReadInt32() - 1; var possibleValues = mapProp.PossibleValues.Keys.ToArray(); if(valIndex >= 0 && valIndex < possibleValues.Length) mapProp.Value = possibleValues[valIndex]; } }
public static GameSave Load(Stream save, int expectedLength = -1) { var gameSave = new GameSave(); using (var reader = new SaveReader(save)) { #region Basic Game Information (Header, Expansions, Mods) #region Header var fileStart = new String(reader.ReadChars(4)); if (fileStart != "CIV5") throw new InvalidSaveException("File did not start with CIV5"); reader.VerifySectionDelimiter(0x08); gameSave.Version = reader.ReadSaveString(); gameSave.Build = reader.ReadSaveString(); gameSave.TurnNumber = reader.ReadInt32(); gameSave.GameMode = (GameMode)reader.ReadByte(); gameSave.HeaderCiv = reader.ReadCiv(); gameSave.HeaderDifficulty = reader.ReadDifficulty(); //Save these for now. We can set them later when we know what the correct GameProperty is based on expansions. var headerStartingEra = reader.ReadEra(); var currentEra = reader.ReadEra(); gameSave.GamePace.Value = reader.ReadPace(); var worldSize = reader.ReadMapSize(); gameSave.Map = reader.ReadMap(worldSize); #endregion #region Expansions int numberOfExpansions = reader.ReadInt32(); for (int i = 0; i < numberOfExpansions; i++) { byte[] expansionId = reader.ReadBytes(16); reader.ReadInt32(); var expansionName = reader.ReadSaveString(); var expansion = Expansion.Expansion.AllWithInternal.SingleOrDefault(e => Enumerable.SequenceEqual(e.SaveId, expansionId) && e.SaveName == expansionName); if (expansion == null) { expansion = new Expansion.Expansion(expansionName, expansionName, String.Empty, GameSteamIds.CivV, expansionId); } gameSave.AddExpansion(expansion); } gameSave.HeaderStartingEra.Value = headerStartingEra; gameSave.HeaderCurrentEra.Value = currentEra; #endregion #region Mods int numberOfMods = reader.ReadInt32(); for (int i = 0; i < numberOfMods; i++) { string modId = reader.ReadSaveString(); reader.ReadInt32(); string modName = reader.ReadSaveString(); gameSave.Mods.Add(new Mod(modName, modId)); } #endregion #endregion #region Nothing Important #region Unknown reader.SkipSaveStrings(2); reader.ReadPlayerColor(); reader.ReadBytes(HeaderCrazyBytes.Length); reader.SkipInt32s(4); reader.ReadSaveString(); #endregion reader.SkipIntSection(); #endregion #region Player Information #region Names reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) gameSave.Players[i].Name = reader.ReadSaveString(); #endregion #region Types reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) gameSave.Players[i].Type = (PlayerType)reader.ReadInt32(); #endregion #region Slots reader.VerifySectionDelimiter(); int slot; int playerSlotCount = -1; do { playerSlotCount++; slot = reader.ReadInt32(); } while (slot == 0x02); reader.SkipInt32s(SaveHelpers.StandardSectionBlockCount - playerSlotCount - 1); #endregion #region Teams reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) gameSave.Players[i].Team = reader.ReadInt32(); #endregion #region Difficulties reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) gameSave.Players[i].Difficulty = (PlayerDifficulty)reader.ReadInt32(); #endregion #region Civilizations reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) gameSave.Players[i].Civilization = reader.ReadCiv(i >= SaveHelpers.MaxPlayers && i != SaveHelpers.StandardSectionBlockCount - 1); #endregion #region Leaders reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) { var leader = reader.ReadLeader(); if (gameSave.Players[i].Civilization != null) gameSave.Players[i].Civilization.Leader = leader; } #endregion #region Current Player Index reader.ReadInt32(); gameSave.CurrentPlayerIndex = reader.ReadInt32(); reader.SkipSaveStrings(3); #endregion #endregion #region Nothing Important reader.SkipByteSection(309); reader.SkipIntSection(); reader.SkipStringSection(); #endregion #region Player Passwords reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) gameSave.Players[i].Password = reader.ReadSaveString(); #endregion #region Starting Era + Temperature Text Key + Unimportant Things #region Blank reader.VerifySectionDelimiter(); reader.SkipInt32s(67); #endregion reader.SkipTextKey(); #region Actual Starting Era reader.SkipInt32s(11); var startingEraIndex = reader.ReadInt32(); var startingEraList = gameSave.StartingEra.PossibleValues.Keys.ToList(); var startingEra = startingEraList[startingEraIndex]; gameSave.StartingEra.Value = startingEra; #endregion #region Blank reader.VerifySectionDelimiter(); reader.SkipInt32s(65); #endregion #region Blank reader.VerifySectionDelimiter(); reader.SkipSaveStrings(SaveHelpers.StandardSectionBlockCount); #endregion #region Blank reader.VerifySectionDelimiter(0x07); reader.ReadBytes(7); #endregion #endregion #region Game Name + Time Offset + Turn Number reader.VerifySectionDelimiter(SaveHelpers.FullBlock); gameSave.Name = reader.ReadSaveString(); gameSave.TimeOffset = reader.ReadInt32(); gameSave.GameStarted = reader.ReadBoolean(); gameSave.TurnNumber = reader.ReadInt32(); reader.ReadBytes(9); #endregion #region Player Difficulties reader.VerifySectionDelimiter(); reader.SkipInt32s(SaveHelpers.StandardSectionBlockCount); #endregion #region Nothing Important reader.SkipByteSection(258); reader.SkipIntSection(); #endregion #region City-State Stuff + Random Seed #region Random Seed + Map Path + City-State Count reader.SkipSaveStrings(2); reader.ReadByte(); gameSave.RandomSeed = reader.ReadInt32(); reader.ReadBytes(2); reader.ReadSaveString(); reader.SkipInt32s(2); gameSave.Map.NumberOfCityStates.Value = reader.ReadInt32(); #endregion #region City-States reader.VerifySectionDelimiter(); reader.SkipSaveStrings(22); for (int i = SaveHelpers.MaxPlayers; i < SaveHelpers.StandardSectionBlockCount - 1; i++) { var civ = reader.ReadCiv(true); if (gameSave.Players[i].Civilization != null && civ != null) gameSave.Players[i].Civilization.Name = civ.Name; } reader.ReadCiv(false); #endregion #region City-State Bits reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) { bool isCityState = reader.ReadBoolean(); //This is a safeguard //It will be called if a player we thought was a civ is actually a city-state //So far, I have never found a save file where this happens if (isCityState && !(gameSave.Players[i].Civilization is CivilizationMinor)) { var civ = gameSave.Players[i].Civilization; gameSave.Players[i].Civilization = new CivilizationMinor(civ.Name, civ.Color); } } reader.ReadByte(); #endregion #endregion #region Turn Timer Seconds + Unimportant Things #region Unknown reader.VerifySectionDelimiter(0x04); reader.ReadBytes(4); #endregion reader.SkipIntSection(); #region Player Names reader.SkipStringSection(); #endregion #region Turn Timer Seconds reader.VerifySectionDelimiter(0x05); gameSave.TurnTimer = reader.ReadInt32(); #endregion reader.SkipByteSection(); #endregion #region Player Colors reader.VerifySectionDelimiter(); for (int i = 0; i < SaveHelpers.StandardSectionBlockCount; i++) { var color = reader.ReadPlayerColor(); if (gameSave.Players[i].Civilization != null) gameSave.Players[i].Civilization.Color = color; } #endregion #region Repeated Data + Unimportant Things reader.ReadBytes(10); #region Sea Level Text Key reader.VerifySectionDelimiter(); reader.SkipInt32s(19); reader.SkipTextKey(); reader.ReadBytes(5); #endregion #region Player Slots reader.SkipIntSection(); #endregion #region Player Types reader.SkipIntSection(); #endregion #region Random Seed reader.SkipInt32s(3); #endregion #region Player Teams reader.SkipIntSection(); #endregion #region Turn Timer Text Key reader.ReadBytes(9); reader.SkipTextKey(); reader.SkipInt32s(5); reader.ReadByte(); #endregion #endregion #region Victory Conditions reader.VerifySectionDelimiter(0x05); gameSave.TimeVictory = reader.ReadBoolean(); gameSave.ScienceVictory = reader.ReadBoolean(); gameSave.DominationVictory = reader.ReadBoolean(); gameSave.CulturalVictory = reader.ReadBoolean(); gameSave.DiplomaticVictory = reader.ReadBoolean(); #endregion #region Random Map Stuff reader.VerifySectionDelimiter(); reader.SkipInt32s(18); if (gameSave.HasGnkOrBnw) reader.ReadInt32(); reader.SkipTextKey(); var expectedCrazyMapBytes = SaveHelpers.GetExpectedCrazyMapSizeBytes(gameSave); reader.ReadBytes(expectedCrazyMapBytes.Length); #endregion #region Options #region Game Options int numberOfPrefs = reader.ReadInt32(); for (int i = 0; i < numberOfPrefs; i++) reader.ReadPreference(gameSave); #endregion #region Map Options int numberOfMapProps = reader.ReadInt32(); for (int i = 0; i < numberOfMapProps; i++) reader.ReadMapPreference(gameSave); #endregion #endregion #region Nothing Important #region Build Number reader.ReadSaveString(); #endregion reader.SkipByteSection(); reader.SkipByteSection(); #region Email Addresses (Ignore) reader.SkipStringSection(); #endregion #endregion #region Read Raw Data if (expectedLength < 0) expectedLength = (int)save.Length; gameSave.RawGameDataIndex = reader.Position; reader.ReadBytes((int)(expectedLength - save.Position)); gameSave._OriginalBytes = reader.AllBytesRead; #endregion } return gameSave; }
public void ReadPreference(GameSave gameSave) { var prefName = this.ReadSaveString(1); switch (prefName.Value) { case "DYNAMIC_TURNS": gameSave.DynamicTurns = this.ReadIntAsBool(); break; case "SIMULTANEOUS_TURNS": gameSave.SimultaneousTurns = this.ReadIntAsBool(); break; case "PITBOSS": gameSave.Pitboss = this.ReadIntAsBool(); break; case "END_TURN_TIMER_ENABLED": gameSave.EnableTurnTimer = this.ReadIntAsBool(); break; case "POLICY_SAVING": gameSave.AllowPolicySaving = this.ReadIntAsBool(); break; case "PROMOTION_SAVING": gameSave.AllowPromotionSaving = this.ReadIntAsBool(); break; case "COMPLETE_KILLS": gameSave.CompleteKills = this.ReadIntAsBool(); break; case "DISABLE_START_BIAS": gameSave.DisableStartBias = this.ReadIntAsBool(); break; case "NEW_RANDOM_SEED": gameSave.NewRandomSeed = this.ReadIntAsBool(); break; case "NO_GOODY_HUTS": gameSave.NoAncientRuins = this.ReadIntAsBool(); break; case "NO_BARBARIANS": gameSave.NoBarbarians = this.ReadIntAsBool(); break; case "NO_CITY_RAZING": gameSave.NoCityRazing = this.ReadIntAsBool(); break; case "NO_ESPIONAGE": gameSave.NoEspionage = this.ReadIntAsBool(); break; case "ONE_CITY_CHALLENGE": gameSave.OneCityChallenge = this.ReadIntAsBool(); break; case "RAGING_BARBARIANS": gameSave.RagingBarbarians = this.ReadIntAsBool(); break; case "RANDOM_PERSONALITIES": gameSave.RandomPersonalities = this.ReadIntAsBool(); break; case "ALWAYS_WAR": gameSave.AlwaysWar = this.ReadIntAsBool(); break; case "ALWAYS_PEACE": gameSave.AlwaysPeace = this.ReadIntAsBool(); break; case "NO_CHANGING_WAR_PEACE": gameSave.NoChangingWarPeace = this.ReadIntAsBool(); break; case "LOCK_MODS": gameSave.LockMods = this.ReadIntAsBool(); break; case "NO_SCIENCE": gameSave.NoScience = this.ReadIntAsBool(); break; case "NO_RELIGION": gameSave.NoReligion = this.ReadIntAsBool(); break; case "NO_POLICIES": gameSave.NoPolicies = this.ReadIntAsBool(); break; case "NO_HAPPINESS": gameSave.NoHappiness = this.ReadIntAsBool(); break; case "NO_LEAGUES": gameSave.NoLeagues = this.ReadIntAsBool(); break; case "NO_CULTURE_OVERVIEW_UI": gameSave.NoCultureOverviewUI = this.ReadIntAsBool(); break; case "QUICK_COMBAT": gameSave.QuickCombat = this.ReadIntAsBool(); break; case "QUICK_MOVEMENT": gameSave.QuickMovement = this.ReadIntAsBool(); break; default: gameSave.CustomSettings[prefName.Value] = this.ReadIntAsBool(); break; } }