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];
     }
 }
示例#2
0
        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;
     }
 }