Exemple #1
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 virtual void Save(Stream stream)
        {
            var output = new SaveWriter(stream, this);

            #region Basic Game Information (Header, Expansions, Mods)

            #region Header
            output.Write(SaveHelpers.FileStart);
            output.Write(0x08);
            output.Write(this.Version.Bytes);
            output.Write(this.Build.Bytes);
            WriteCurrentTurnNumber(output);
            output.Write((byte)this.GameMode);

            var headerCiv =
                HeaderCiv != null ? HeaderCiv.SaveName.Bytes :
                Players[0].Civilization != null ? Players[0].Civilization.SaveName.Bytes :
                BitConverter.GetBytes(0x00);
            output.Write(headerCiv);
            var headerDifficulty =
                HeaderDifficulty.HasValue ? HeaderDifficulty.Value : Players[0].Difficulty;
            output.Write(SaveHelpers.ConvertOptionEnumToSaveStr(headerDifficulty).Bytes);
            output.Write(SaveHelpers.ConvertOptionEnumToSaveStr(this.HeaderStartingEra.Value).Bytes);
            WriteCurrentEra(output);
            output.Write(SaveHelpers.ConvertOptionEnumToSaveStr(this.GamePace.Value).Bytes);
            output.Write(SaveHelpers.ConvertOptionEnumToSaveStr(this.Map.Size.Value).Bytes);

            output.Write(this.Map.Path.Bytes);
            #endregion

            #region Expansions
            output.Write(this._Expansions.Count);
            foreach (var expansion in this.Expansions)
            {
                output.Write(expansion.SaveId);
                output.Write(0x01);
                output.Write(expansion.SaveName.Bytes);
            }
            #endregion

            #region Mods
            output.Write(Mods.Count);
            foreach (var mod in this.Mods)
            {
                output.Write(mod.SaveId.Bytes);
                output.Write(0x01);
                output.Write(mod.SaveName.Bytes);
            }
            #endregion

            #endregion

            #region Nothing Important

            #region Unknown + Map Path
            output.WriteEmptyBlocks(2);
            WritePlayerColor(output);
            output.Write(HeaderCrazyBytes);
            output.Write(0x00);
            output.Write(0x03);
            output.Write(0x03);
            output.Write(0x02);

            output.Write(this.Map.Path.Bytes);
            #endregion

            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteFullBlocks(SaveHelpers.StandardSectionBlockCount);
            #endregion

            #region Player Information

            output.WritePlayerNamesSection();
            output.WritePlayerTypeSection();
            output.WritePlayerSlotsSection();
            output.WritePlayerTeamsSection();
            output.WritePlayerDifficultiesSection(this.Expansions.Contains(Expansion.Expansion.BraveNewWorld));

            WriteCivilizationsSection(output);

            WriteLeadersSection(output);

            #region Current Player Index
            output.Write(0x06);
            WriteCurrentPlayerIndex(output);
            output.WriteEmptyBlocks(3);
            #endregion

            #endregion

            #region Nothing Important

            #region Mostly Blank
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteFullBlocks(SaveHelpers.StandardSectionBlockCount);
            output.WriteEmptyBlocks(2);
            output.Write((byte)0x00);
            output.Write(0x02);
            output.Write(0x00);
            output.Write(SaveHelpers.FullBlock);
            output.WriteEmptyBlocks(8);
            #endregion

            output.WriteEmptySection();
            output.WriteEmptySection();

            #endregion

            WritePlayerPasswordsSection(output);

            #region Starting Era + Temperature Text Key + Unimportant Things

            #region Blank
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(67);
            #endregion

            output.WriteTextKey("CLIMATE", "Temperate");

            #region Actual Starting Era
            output.Write(0x00);
            output.Write(0x05);
            output.Write(0x05);
            output.Write(0x19);
            output.WriteEmptyBlocks(5);
            output.Write(new byte[] { 0x33, 0x33, 0x73, 0x3F, 0x00, 0x00, 0x80, 0x3E });

            var startingEra      = this.StartingEra.Value;
            var startingEraList  = this.StartingEra.PossibleValues.Keys.ToList();
            int startingEraIndex = startingEraList.IndexOf(startingEra);
            output.Write(startingEraIndex);
            #endregion

            #region Blank
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(65);
            #endregion

            #region Blank
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(64);
            #endregion

            #region Blank
            output.Write(0x07);
            output.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
            #endregion

            #endregion

            #region Game Name + Time Offset + Turn Number
            output.WriteFullBlocks(1);
            output.Write(Name.Bytes);
            output.Write(TimeOffset);
            output.Write(GameStarted);
            WriteCurrentTurnNumber(output);
            output.Write((byte)0x02);
            output.WriteEmptyBlocks(2);
            #endregion

            output.WritePlayerDifficultiesSection(this.Expansions.Contains(Expansion.Expansion.BraveNewWorld));

            #region Nothing Important

            #region Mostly Blank
            output.Write(SaveHelpers.SectionDelimiter);
            output.Write(0x03);
            output.WriteFullBlocks(SaveHelpers.StandardSectionBlockCount - 1);
            output.Write((byte)0x00);
            output.Write((byte)0x00);
            #endregion

            output.WriteEmptySection();

            #endregion

            #region City-State Stuff + Random Seed

            #region Random Seed + Map Path + City-State Count
            output.WriteEmptyBlocks(2);
            output.Write((byte)0x00);

            output.Write(this.RandomSeed);
            output.Write((byte)0x00);
            output.Write((byte)0x00);

            output.Write(this.Map.Path.Bytes);

            output.WriteEmptyBlocks(2);
            output.Write(this.Map.NumberOfCityStates);
            #endregion

            #region City-States
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(SaveHelpers.MaxPlayers);
            WriteMinorCivs(output);
            output.Write(0x00);
            #endregion

            #region City-State Bits
            output.Write(SaveHelpers.SectionDelimiter);
            for (int i = 0; i < Players.Length; i++)
            {
                if (Players[i].Civilization != null && Players[i].Civilization is CivilizationMinor)
                {
                    output.Write(true);
                }
                else
                {
                    output.Write(false);
                }
            }
            output.Write((byte)0x00);
            #endregion

            #endregion

            #region Turn Timer Seconds + Unimportant Things

            #region Unknown
            output.Write(0x04);
            output.Write(0x00);
            #endregion

            output.WriteFullSection();
            output.WritePlayerNamesSection();

            #region Turn Timer Seconds
            output.Write(0x05);
            output.Write(this.TurnTimer);
            #endregion

            #region A Bunch of Bools
            //Maybe IsPlayer? The only false is the Barbarians
            output.Write(SaveHelpers.SectionDelimiter);
            for (int i = 0; i < SaveHelpers.SectionDelimiter - 1; i++)
            {
                output.Write(true);
            }
            output.Write(false);
            #endregion

            #endregion

            #region Player Colors
            WritePlayerColorsSection(output);
            #endregion

            #region Repeated Data + Unimportant Things

            output.Write(new byte[] { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 });

            #region Sea Level Text Key
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(16);
            output.Write(0x01);
            output.Write(0x01);
            output.Write(0x00);

            output.WriteTextKey("SEALEVEL", "Medium");

            output.Write(0x00);
            output.Write((byte)0x00);
            #endregion

            output.WritePlayerSlotsSection();

            output.WritePlayerTypeSection();

            #region Random Seed
            output.Write(0x00);
            output.Write(this.RandomSeed);
            output.Write(0x00);
            #endregion

            output.WritePlayerTeamsSection();

            #region Turn Timer Text Key
            output.Write((byte)0x00);
            output.Write(0x04);
            output.Write(0x00);
            output.WriteTextKey("TURNTIMER", "Fast");

            output.Write(0x19);
            output.Write(0x09);
            output.Write(0x03);
            output.Write(0x03);
            output.Write(0x04);
            output.Write((byte)0x00);
            #endregion

            #endregion

            #region Victory Conditions
            output.Write(0x05);

            output.Write(BitConverter.GetBytes(this.TimeVictory));
            output.Write(BitConverter.GetBytes(this.ScienceVictory));
            output.Write(BitConverter.GetBytes(this.DominationVictory));
            output.Write(BitConverter.GetBytes(this.CulturalVictory));
            output.Write(BitConverter.GetBytes(this.DiplomaticVictory));
            #endregion

            #region Random Map Stuff
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(16);
            if (this.HasGnkOrBnw)
            {
                output.Write(0x02);
            }
            int mapSizeId = (((int)this.Map.Size.Value) / 2) - 1;
            output.Write(mapSizeId);
            output.Write(0x00);

            var worldSize = SaveHelpers.ConvertOptionEnumToSaveStr(this.Map.Size.Value);
            output.WriteTextKey(worldSize.Prefix, worldSize.Value, true);

            output.Write(SaveHelpers.GetExpectedCrazyMapSizeBytes(this));
            #endregion

            #region Options

            #region Game Options
            //Number of options
            output.Write(GetNumberOfSettings() + CustomSettings.Count);

            output.WriteGamePreference("DYNAMIC_TURNS", DynamicTurns);
            output.WriteGamePreference("SIMULTANEOUS_TURNS", SimultaneousTurns);
            output.WriteGamePreference("PITBOSS", Pitboss);

            output.WriteGamePreference("QUICK_COMBAT", QuickCombat);
            output.WriteGamePreference("QUICK_MOVEMENT", QuickMovement);

            output.WriteGamePreference("END_TURN_TIMER_ENABLED", EnableTurnTimer);
            output.WriteGamePreference("POLICY_SAVING", AllowPolicySaving);
            output.WriteGamePreference("PROMOTION_SAVING", AllowPromotionSaving);
            output.WriteGamePreference("COMPLETE_KILLS", CompleteKills);
            output.WriteGamePreference("DISABLE_START_BIAS", DisableStartBias);
            output.WriteGamePreference("NEW_RANDOM_SEED", NewRandomSeed);
            output.WriteGamePreference("NO_GOODY_HUTS", NoAncientRuins);
            output.WriteGamePreference("NO_BARBARIANS", NoBarbarians);
            output.WriteGamePreference("NO_CITY_RAZING", NoCityRazing);
            output.WriteGamePreference("ONE_CITY_CHALLENGE", OneCityChallenge);
            output.WriteGamePreference("RAGING_BARBARIANS", RagingBarbarians);
            output.WriteGamePreference("RANDOM_PERSONALITIES", RandomPersonalities);

            output.WriteGamePreference("ALWAYS_WAR", AlwaysWar);
            output.WriteGamePreference("ALWAYS_PEACE", AlwaysPeace);
            output.WriteGamePreference("NO_CHANGING_WAR_PEACE", NoChangingWarPeace);
            output.WriteGamePreference("LOCK_MODS", LockMods);
            output.WriteGamePreference("NO_SCIENCE", NoScience);
            output.WriteGamePreference("NO_POLICIES", NoPolicies);
            output.WriteGamePreference("NO_HAPPINESS", NoHappiness);

            if (HasGnkOrBnw)
            {
                output.WriteGamePreference("NO_ESPIONAGE", NoEspionage);
                output.WriteGamePreference("NO_RELIGION", NoReligion);
            }

            if (_Expansions.Contains(Expansion.Expansion.BraveNewWorld))
            {
                output.WriteGamePreference("NO_LEAGUES", NoLeagues);
                output.WriteGamePreference("NO_CULTURE_OVERVIEW_UI", NoCultureOverviewUI);
            }

            foreach (var setting in CustomSettings)
            {
                output.WriteGamePreference(setting.Key, setting.Value);
            }
            #endregion

            #region Map Options
            var mapProperties = this.Map.MapProperties;
            output.Write(mapProperties.Count);
            int index = 1;
            foreach (var prop in mapProperties)
            {
                object value          = prop.Value;
                var    possibleValues = prop.PossibleValues.Keys.ToList();
                var    propIndex      = possibleValues.IndexOf(value) + 1;
                var    strProp        = new SaveString(index.ToString());
                output.Write(strProp.Bytes);
                output.Write(propIndex);
                index++;
            }
            #endregion

            #endregion

            #region Nothing Important
            #region Build Number
            var buildStr = new SaveString(this.Build + " FINAL RELEASE");
            output.Write(buildStr.Bytes);
            #endregion

            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(16);

            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(16);

            #region Email Addresses (Ignore)
            output.Write(SaveHelpers.SectionDelimiter);
            output.WriteEmptyBlocks(64);
            #endregion
            #endregion

            WriteRawGameData(output);
        }
 protected virtual void WriteCurrentEra(SaveWriter output)
 {
     output.Write(SaveHelpers.ConvertOptionEnumToSaveStr(this.HeaderStartingEra.Value).Bytes);
 }
 protected override void WriteCurrentEra(SaveWriter output)
 {
     output.Write(SaveHelpers.ConvertOptionEnumToSaveStr(HeaderCurrentEra.Value).Bytes);
 }