diff options
Diffstat (limited to 'V3/Data/Internal')
-rw-r--r-- | V3/Data/Internal/GameStateManager.cs | 81 | ||||
-rw-r--r-- | V3/Data/Internal/OptionsManager.cs | 65 | ||||
-rw-r--r-- | V3/Data/Internal/PathManager.cs | 51 | ||||
-rw-r--r-- | V3/Data/Internal/SaveGame.cs | 65 | ||||
-rw-r--r-- | V3/Data/Internal/SaveGameManager.cs | 88 |
5 files changed, 350 insertions, 0 deletions
diff --git a/V3/Data/Internal/GameStateManager.cs b/V3/Data/Internal/GameStateManager.cs new file mode 100644 index 0000000..53ef3de --- /dev/null +++ b/V3/Data/Internal/GameStateManager.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using V3.Camera; +using V3.Map; +using V3.Objects; + +namespace V3.Data.Internal +{ + /// <summary> + /// Default implementation of IGameStateManager. + /// </summary> + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class GameStateManager : IGameStateManager + { + private readonly CameraManager mCameraManager; + private readonly CreatureFactory mCreatureFactory; + private readonly IMapManager mMapManager; + private readonly IObjectsManager mObjectsManager; + + public GameStateManager(CameraManager cameraManager, CreatureFactory creatureFactory, + IMapManager mapManager, IObjectsManager objectsManager) + { + mCameraManager = cameraManager; + mCreatureFactory = creatureFactory; + mMapManager = mapManager; + mObjectsManager = objectsManager; + } + + /// <summary> + /// Restores the given game state. + /// </summary> + public GameState GetGameState() + { + var gameState = new GameState(); + foreach (var obj in mObjectsManager.CreatureList) + { + gameState.mCreatures.Add(obj.SaveData()); + } + gameState.mCameraPosition = mCameraManager.GetCamera().Location; + return gameState; + } + + /// <summary> + /// Restores the given game state. + /// </summary> + /// <param name="gameState">the game state to restore</param> + public void LoadGameState(GameState gameState) + { + mObjectsManager.Clear(); + mObjectsManager.ImportMapObjects(mMapManager.GetObjects()); + var creatures = new Dictionary<int, ICreature>(); + + // load creatures + foreach (var creatureData in gameState.mCreatures) + { + ICreature creature = mCreatureFactory.CreateCreature(creatureData.Type, creatureData.Id); + if (creature == null) + continue; + creature.LoadData(creatureData); + if (creature is Necromancer) + mObjectsManager.CreatePlayerCharacter((Necromancer) creature); + else if (creature is King) // || creature is Prince + mObjectsManager.CreateBoss(creature); + else + mObjectsManager.CreateCreature(creature); + + creatures.Add(creature.Id, creature); + } + + // fix references + foreach (var creatureData in gameState.mCreatures) + { + if (!creatures.ContainsKey(creatureData.Id)) + continue; + creatures[creatureData.Id].LoadReferences(creatureData, creatures); + } + + if (mCameraManager.GetCamera() is CameraScrolling) + mCameraManager.GetCamera().Location = gameState.mCameraPosition; + } + } +} diff --git a/V3/Data/Internal/OptionsManager.cs b/V3/Data/Internal/OptionsManager.cs new file mode 100644 index 0000000..d581ba5 --- /dev/null +++ b/V3/Data/Internal/OptionsManager.cs @@ -0,0 +1,65 @@ +using System.IO; +using System.Runtime.Serialization; +using System.Xml.Serialization; +using Ninject; + +namespace V3.Data.Internal +{ + /// <summary> + /// Default implementation of IOptionsManager. + /// </summary> + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class OptionsManager : IOptionsManager, IInitializable + { + /// <summary> + /// The current options. + /// </summary> + public Options Options { get; private set; } + + private readonly IPathManager mPathManager; + private readonly XmlSerializer mSerializer = new XmlSerializer(typeof(Options)); + + /// <summary> + /// Creates a new OptionsManager. + /// </summary> + public OptionsManager(IPathManager pathManager) + { + mPathManager = pathManager; + } + + public void Initialize() + { + Options = LoadOptions(); + } + + /// <summary> + /// Saves the current options to the hard disk. + /// </summary> + public void SaveOptions() + { + var stream = new FileStream(mPathManager.OptionsFile, FileMode.Create, FileAccess.Write); + mSerializer.Serialize(stream, Options); + stream.Close(); + } + + private Options LoadOptions() + { + if (!File.Exists(mPathManager.OptionsFile)) + return new Options(); + var stream = new FileStream(mPathManager.OptionsFile, FileMode.Open, FileAccess.Read); + try + { + return (Options)mSerializer.Deserialize(stream); + } + catch (SerializationException) + { + // ignore so far + } + finally + { + stream.Close(); + } + return new Options(); + } + } +} diff --git a/V3/Data/Internal/PathManager.cs b/V3/Data/Internal/PathManager.cs new file mode 100644 index 0000000..3f4ad9d --- /dev/null +++ b/V3/Data/Internal/PathManager.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; + +namespace V3.Data.Internal { + /// <summary> + /// Default implementation of IPathManager. + /// </summary> + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class PathManager : IPathManager + { + /// <summary> + /// The base directory for persistent application data. + /// </summary> + public string AppDirectory { get; } + + /// <summary> + /// The file to store the options in. + /// </summary> + public string OptionsFile { get; } + + /// <summary> + /// The directory for save games. + /// </summary> + public string SaveGameDirectory { get; } + + /// <summary> + /// Creates a new path manager and initializes the paths, but does not + /// create the directories if they don’t already exist. + /// </summary> + public PathManager() + { + var localAppDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + AppDirectory = $"{localAppDir}/V3"; + SaveGameDirectory = $"{AppDirectory}/SaveGames"; + OptionsFile = $"{AppDirectory}/Options.xml"; + } + + /// <summary> + /// Creates the application directories that do not already exist. + /// </summary> + public void CreateMissingDirectories() + { + string[] directories = { AppDirectory, SaveGameDirectory }; + foreach (var directory in directories) + { + if (!Directory.Exists(directory)) + Directory.CreateDirectory(directory); + } + } + } +} diff --git a/V3/Data/Internal/SaveGame.cs b/V3/Data/Internal/SaveGame.cs new file mode 100644 index 0000000..9ff3586 --- /dev/null +++ b/V3/Data/Internal/SaveGame.cs @@ -0,0 +1,65 @@ +using System; + +namespace V3.Data.Internal +{ + // TODO: once the game state is getting larger, we have to separate the + // save game metadata from the game state. + + /// <summary> + /// A save game that has a timestamp and a title, and that can store + /// the game state. + /// </summary> + [Serializable] + public sealed class SaveGame : ISaveGame + { + /// <summary> + /// The creation time of this save game in local time. + /// </summary> + public DateTime Timestamp { get; set; } + + /// <summary> + /// The compability version of this save game. + /// </summary> + public int Version { get; set; } + + /// <summary> + /// The data stored in this save game. + /// </summary> + public GameState GameState { get; set; } + + /// <summary> + /// Empty constructor for serialization. + /// </summary> + private SaveGame() + { + } + + /// <summary> + /// Creates a new save game from the given data. + /// </summary> + /// <param name="timestamp">the creation time of the save game</param> + /// <param name="version">the compability version of the save game</param> + /// <param name="gameState">the game state to store in the save game</param> + internal SaveGame(DateTime timestamp, int version, GameState gameState) + { + Timestamp = timestamp; + Version = version; + GameState = gameState; + } + + /// <summary> + /// Compares this save game object to another save game object based + /// on the creation time. + /// </summary> + /// <param name="saveGame">the save game to compare this save game + /// with</param> + /// <returns>a value less than zero if this save game has been saved + /// before the given save game, zero if they have been saved at the + /// same time and a value greater than zero if the given save game has + /// been saved before the given one</returns> + public int CompareTo(ISaveGame saveGame) + { + return Timestamp.CompareTo(saveGame.Timestamp); + } + } +} diff --git a/V3/Data/Internal/SaveGameManager.cs b/V3/Data/Internal/SaveGameManager.cs new file mode 100644 index 0000000..1c52b50 --- /dev/null +++ b/V3/Data/Internal/SaveGameManager.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Xml.Serialization; + +namespace V3.Data.Internal +{ + /// <summary> + /// Default implementation if ISaveGameManager. + /// </summary> + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class SaveGameManager : ISaveGameManager + { + private readonly IPathManager mPathManager; + + private const int CurrentVersion = 1; + private readonly XmlSerializer mFormatter = new XmlSerializer(typeof(SaveGame)); + + /// <summary> + /// Creates a new SaveGameManager. The save game directory must already + /// be created. + /// </summary> + public SaveGameManager(IPathManager pathManager) + { + mPathManager = pathManager; + } + + /// <summary> + /// Creates and persists a new save game of the given data with the + /// title. + /// </summary> + /// <param name="gameState">the data to store</param> + public void CreateSaveGame(GameState gameState) + { + var saveGame = new SaveGame(DateTime.Now, CurrentVersion, gameState); + var fileName = GetUniqueFileName(); + var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write); + mFormatter.Serialize(stream, saveGame); + stream.Close(); + } + + /// <summary> + /// Loads all available save games and returns them ordered by the + /// creation date. + /// </summary> + /// <returns>a list of all available save games, orderd by creation + /// data</returns> + public List<ISaveGame> GetSaveGames() + { + var saveGames = new List<ISaveGame>(); + foreach (var file in Directory.GetFiles(mPathManager.SaveGameDirectory)) + { + var stream = new FileStream(file, FileMode.Open, FileAccess.Read); + try + { + var saveGame = (ISaveGame)mFormatter.Deserialize(stream); + if (saveGame.Version == CurrentVersion) + saveGames.Add(saveGame); + } + catch (SerializationException) + { + // ignore so far + } + stream.Close(); + } + saveGames.Sort(); + return saveGames; + } + + private string GetUniqueFileName() + { + var index = 1; + var fileName = GetFileName(index); + while (File.Exists(fileName)) + { + index++; + fileName = GetFileName(index); + } + return fileName; + } + + private string GetFileName(int index) + { + return $"{mPathManager.SaveGameDirectory}/{index:000}.xml"; + } + } +} |