<|start_filename|>IsolatedStorageSaveManager.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace MonoGameSaveManager
{
    /// <summary>
    /// Uses the .NET IsolatedStorage to load/save game data.
    /// Saves end up on "C:\Users\...\AppData\Local\IsolatedStorage\..." on Windows. 
    /// </summary>
    public class IsolatedStorageSaveManager : SaveManager
    {
        /// <summary>
        /// /// <summary>
        /// Creates a new save game manager based on .NET IsolatedStorage.
        /// </summary>
        /// <param name="folderName">Name of the folder containing the save.</param>
        /// <param name="fileName">Name of the save file.</param>
        public IsolatedStorageSaveManager(string folderName, string fileName)
            : base(folderName, fileName)
        { }

        public override void Load()
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null))
            {
                // Ignore if directory doesn't exist.
                if (!isf.DirectoryExists(folderName))
                    return;

                string filePath = Path.Combine(folderName, fileName);

                // Ignore if save doesn't exist.
                if (!isf.FileExists(filePath))
                    return;

                // Open the save file.
                using (IsolatedStorageFileStream stream = isf.OpenFile(filePath, FileMode.Open))
                {
                    // Get the XML data from the stream and convert it to object.
                    XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
                    Data = (SaveData)serializer.Deserialize(stream);
                }
            }
        }

        public override void Save()
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null))
            {
                // Create directory if it doesn't exist.
                if (!isf.DirectoryExists(folderName))
                    isf.CreateDirectory(folderName);

                string filePath = Path.Combine(folderName, fileName);

                // Create new save file.
                using (IsolatedStorageFileStream stream = isf.CreateFile(filePath))
                {
                    // Convert the object to XML data and put it in the stream.
                    XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
                    serializer.Serialize(stream, Data);
                }
            }
        }
    }
}


<|start_filename|>StorageDeviceSaveManager.cs<|end_filename|>
﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace MonoGameSaveManager
{
    /// <summary>
    /// Uses the XNA StorageDevice to load/save game data.
    /// Saves end up on "C:\Users\...\Documents\SavedGames\..." on Windows. 
    /// </summary>
    public class StorageDeviceSaveManager : SaveManager
    {
        private PlayerIndex? player;

        /// <summary>
        /// Creates a new save game manager based on XNA StorageDevice.
        /// </summary>
        /// <param name="folderName">Name of the folder containing the save.</param>
        /// <param name="fileName">Name of the save file.</param>
        /// <param name="player">Player the save belongs to, or null for a global save.</param>
        public StorageDeviceSaveManager(string folderName, string fileName, PlayerIndex? player)
            : base(folderName, fileName)
        {
            this.player = player;
        }

        private StorageDevice getStorageDevice()
        {
            IAsyncResult result;
            // Get a global folder.
            if (player == null)
                result = StorageDevice.BeginShowSelector(null, null);
            // Get a player-specific subfolder.
            else
                result = StorageDevice.BeginShowSelector((PlayerIndex)player, null, null);

            result.AsyncWaitHandle.WaitOne();
            StorageDevice device = StorageDevice.EndShowSelector(result);
            result.AsyncWaitHandle.Close();
            return device;
        }

        public override void Load()
        {
            // Open a storage device.
            StorageDevice device = getStorageDevice();

            // Open a storage container.
            IAsyncResult result = device.BeginOpenContainer(folderName, null, null);
            result.AsyncWaitHandle.WaitOne();
            using (StorageContainer container = device.EndOpenContainer(result))
            {
                result.AsyncWaitHandle.Close();

                // Ignore if save doesn't exist.
                if (!container.FileExists(fileName))
                    return;

                // Open the save file.
                using (Stream stream = container.OpenFile(fileName, FileMode.Open))
                {
                    // Get the XML data from the stream and convert it to object.
                    XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
                    Data = (SaveData)serializer.Deserialize(stream);
                }
            }
        }

        public override void Save()
        {
            // Open a storage device.
            StorageDevice device = getStorageDevice();

            // Open a storage container.
            IAsyncResult resultStorage = device.BeginOpenContainer(folderName, null, null);
            resultStorage.AsyncWaitHandle.WaitOne();
            using (StorageContainer container = device.EndOpenContainer(resultStorage))
            {
                resultStorage.AsyncWaitHandle.Close();

                // Delete old save file.
                if (container.FileExists(fileName))
                    container.DeleteFile(fileName);

                // Create new save file.
                using (Stream stream = container.CreateFile(fileName))
                {
                    // Convert the object to XML data and put it in the stream.
                    XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
                    serializer.Serialize(stream, Data);
                }
            }
        }
    }
}


<|start_filename|>SaveManager.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MonoGameSaveManager
{
    /// <summary>
    /// Manages a save file for you.
    /// </summary>
    public abstract class SaveManager
    {
        protected string folderName, fileName;

        /// <summary>
        /// Access save game data.
        /// </summary>
        public SaveData Data { get; set; }

        /// <summary>
        /// Creates a new save game manager.
        /// </summary>
        /// <param name="folderName">Name of the folder containing the save.</param>
        /// <param name="fileName">Name of the save file.</param>
        public SaveManager(string folderName, string fileName)
        {
            this.folderName = folderName;
            this.fileName = fileName;
            this.Data = new SaveData();
        }

        /// <summary>
        /// Loads the data from disk to memory.
        /// </summary>
        public abstract void Load();

        /// <summary>
        /// Saves the data in memory to disk.
        /// </summary>
        public abstract void Save();
    }
}


<|start_filename|>SaveData.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MonoGameSaveManager
{
    /// <summary>
    /// Container for your save game data.
    /// Put the variables you need here, as long as it's serializable.
    /// </summary>
    [Serializable]
    public class SaveData
    {
        public int testInt;
        public bool testBool;
        public string testString;
    }
}


<|start_filename|>Game1.cs<|end_filename|>
﻿#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
using System.Diagnostics;
#endregion

namespace MonoGameSaveManager
{
    /// <summary>
    /// A basic game to test out the SaveManager functionality.
    /// Just follow along with the comments.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        SaveManager save;
        bool saved = false;

        public Game1()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            string saveFolder = "SaveManagerTest"; // put your save folder name here
            string saveFile = "test.sav"; // put your save file name here

            // Pick one:

            // - this will use the XNA StorageDevice method.
            save = new StorageDeviceSaveManager(saveFolder, saveFile, PlayerIndex.One);

            // - this will use the .NET IsolatedStorage method.
            //save = new IsolatedStorageSaveManager(saveFolder, saveFile);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            // test save stuff
            // since this is Update, i don't want it to keep saving every tick
            if (!saved)
            {
                saved = true;

                // let's make up some save data
                save.Data.testInt = 434;
                save.Data.testBool = false;
                save.Data.testString = "wow a test";

                // save it
                save.Save();

                // erase data so we can check if loading works
                save.Data = new SaveData();

                // load it back
                save.Load();

                // did it work? let's hope so!
                // this will show up in Visual Studio's Output window when running.
                // you can also just use a Breakpoint or whatever.
                Debug.WriteLine("final save data:");
                Debug.WriteLine("testInt = " + save.Data.testInt);
                Debug.WriteLine("testBool = " + save.Data.testBool);
                Debug.WriteLine("testString = " + save.Data.testString);
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}
