diff --git a/MudEngine/FileSystem/FileManager.cs b/MudEngine/FileSystem/FileManager.cs index 95fce8d..6e3a1eb 100644 --- a/MudEngine/FileSystem/FileManager.cs +++ b/MudEngine/FileSystem/FileManager.cs @@ -60,13 +60,30 @@ namespace MudEngine.FileSystem if (line.StartsWith(";")) continue; - if (line.StartsWith(name)) + if (line.ToLower().StartsWith(name.ToLower())) return line.Substring(name.Length + 1); //Accounts for name=value; } return "No data Found."; } + public static List GetCollectionData(String filename, String item) + { + List items = new List(); + + foreach (String line in File.ReadAllLines(filename)) + { + //Ignore comments + if (line.StartsWith(";")) + continue; + + if (line.ToLower().StartsWith(item.ToLower())) + items.Add(line.Substring(item.Length + 1)); //Accounts for name=value; + } + + return items; + } + /// /// Returns the complete path to the specified data's save folder. /// diff --git a/MudEngine/GameManagement/CommandEngine.cs b/MudEngine/GameManagement/CommandEngine.cs index f723fc3..052df3a 100644 --- a/MudEngine/GameManagement/CommandEngine.cs +++ b/MudEngine/GameManagement/CommandEngine.cs @@ -73,8 +73,6 @@ namespace MudEngine.GameManagement public CommandResults ExecuteCommand(String command, BaseCharacter player) { String commandKey = command.Insert(0, "Command"); - if (Game.IsDebug) - Log.Write("Executing command: " + command); foreach (String key in CommandEngine.CommandCollection.Keys) { diff --git a/MudEngine/GameManagement/Game.cs b/MudEngine/GameManagement/Game.cs index 56a0e7a..a210d3b 100644 --- a/MudEngine/GameManagement/Game.cs +++ b/MudEngine/GameManagement/Game.cs @@ -192,10 +192,7 @@ namespace MudEngine.GameManagement WorldTime = new GameTime(this); //Prepare the Save Paths for all of our Game objects. - SaveDataPaths paths = new SaveDataPaths(); - paths.Environment = FileManager.GetDataPath(SaveDataTypes.Realms); - paths.Players = FileManager.GetDataPath(SaveDataTypes.Player); - DataPaths = paths; + DataPaths = new SaveDataPaths("World", "Player"); //Setup default settings for the Game GameTitle = "New Game"; @@ -229,11 +226,14 @@ namespace MudEngine.GameManagement WorldTime.HoursPerDay = 23; WorldTime.MinutesPerHour = 59; WorldTime.SecondsPerMinute = 59; + + AutoSave = true; + AutoSaveInterval = 30; } ~Game() { - Server = null; + Save(); } #endregion @@ -288,6 +288,9 @@ namespace MudEngine.GameManagement //Game is running now. IsRunning = true; + //Load the game and world if it was previously saved. + Load(); + Log.Write("Game startup complete."); return true; } @@ -354,8 +357,6 @@ namespace MudEngine.GameManagement { if (PlayerCollection[i].Name == "New BaseCharacter") continue; - - Log.Write("Saving " + PlayerCollection[i].Name); PlayerCollection[i].ExecuteCommand("Save"); } @@ -368,10 +369,82 @@ namespace MudEngine.GameManagement //Save the Game World. World.Save(); + + //Save the Game + String filename = GameTitle + ".ini"; + + if (File.Exists(filename)) + File.Delete(filename); + + FileManager.WriteLine(filename, this.AutoSave.ToString(), "AutoSave"); + FileManager.WriteLine(filename, this.AutoSaveInterval.ToString(), "AutoSaveInterval"); + FileManager.WriteLine(filename, this.BaseCurrencyAmount.ToString(), "BaseCurrencyAmount"); + FileManager.WriteLine(filename, this.BaseCurrencyName, "BaseCurrencyName"); + FileManager.WriteLine(filename, this.CompanyName, "CompanyName"); + FileManager.WriteLine(filename, this.DataPaths.Environment, "DataPathEnvironment"); + FileManager.WriteLine(filename, this.DataPaths.Players, "DataPathPlayers"); + FileManager.WriteLine(filename, this.GameTitle, "GameTitle"); + FileManager.WriteLine(filename, this.HideRoomNames.ToString(), "HideRoomNames"); + FileManager.WriteLine(filename, this.InitialRealm.Filename, "InitialRealm"); + FileManager.WriteLine(filename, this.IsMultiplayer.ToString(), "IsMultiplayer"); + FileManager.WriteLine(filename, this.MaximumPlayers.ToString(), "MaximumPlayers"); + FileManager.WriteLine(filename, this.PreCacheObjects.ToString(), "PreCacheObjects"); + FileManager.WriteLine(filename, this.ServerPort.ToString(), "ServerPort"); + FileManager.WriteLine(filename, this.ServerType.ToString(), "ServerType"); + FileManager.WriteLine(filename, this.Version, "Version"); + FileManager.WriteLine(filename, this.Website, "Website"); + + //TODO: Save WorldTime + //TODO: Save Story + //TODO: Save Server Information + //TODO: Save Currency Lists + //TODO: Save Script Engine information } public virtual void Load() { + String filename = GameTitle + ".ini"; + + if (!File.Exists(filename)) + return; + + Log.Write("Restoring Game Settings..."); + this.AutoSave = Convert.ToBoolean(FileManager.GetData(filename, "AutoSave")); + this.AutoSaveInterval = Convert.ToInt32(FileManager.GetData(filename, "AutoSaveInterval")); + this.BaseCurrencyAmount = Convert.ToInt32(FileManager.GetData(filename, "BaseCurrencyAmount")); + this.BaseCurrencyName = FileManager.GetData(filename, "BaseCurrencyName"); + this.CompanyName = FileManager.GetData(filename, "CompanyName"); + this.DataPaths = new SaveDataPaths(FileManager.GetData(filename, "DataPathEnvironment"), FileManager.GetData(filename, "DataPathPlayers")); + this.GameTitle = FileManager.GetData(filename, "GameTitle"); + this.HideRoomNames = Convert.ToBoolean(FileManager.GetData(filename, "HideRoomNames")); + this.InitialRealm = new Realm(this); + this.IsMultiplayer = Convert.ToBoolean(FileManager.GetData(filename, "IsMultiplayer")); + this.MaximumPlayers = Convert.ToInt32(FileManager.GetData(filename, "MaximumPlayers")); + this.PreCacheObjects = Convert.ToBoolean(FileManager.GetData(filename, "PreCacheObjects")); + this.ServerPort = Convert.ToInt32(FileManager.GetData(filename, "ServerPort")); + this.Version = FileManager.GetData(filename, "Version"); + this.Website = FileManager.GetData(filename, "Webite"); + + //Need to re-assign the enumerator value that was previously assigned to the ServerType property + Array values = Enum.GetValues(typeof(ProtocolType)); + foreach (Int32 value in values) + { + //Since enum values are not strings, we can't simply just assign the String to the enum + String displayName = Enum.GetName(typeof(ProtocolType), value); + + //If the value = the String saved, then perform the needed conversion to get our data back + if (displayName.ToLower() == FileManager.GetData(filename, "ServerType").ToLower()) + { + ServerType = (ProtocolType)Enum.Parse(typeof(ProtocolType), displayName); + break; + } + } + + //Restore the world. + Log.Write("Restoring World Environments..."); + World.Load(); + + Log.Write("Game Restore complete."); } /// diff --git a/MudEngine/GameManagement/GameWorld.cs b/MudEngine/GameManagement/GameWorld.cs index 862d48a..69bb3e6 100644 --- a/MudEngine/GameManagement/GameWorld.cs +++ b/MudEngine/GameManagement/GameWorld.cs @@ -47,7 +47,7 @@ namespace MudEngine.GameManagement /// /// Gets the collection of Realms currently available in the game world /// - public List Realms { get; private set; } + public List RealmCollection { get; private set; } private Game _Game; @@ -58,7 +58,7 @@ namespace MudEngine.GameManagement Objects = new List(); Items = new List(); Characters = new List(); - Realms = new List(); + RealmCollection = new List(); } public void Start() @@ -66,7 +66,7 @@ namespace MudEngine.GameManagement //See if we have an Initial Realm set //TODO: Check for saved Realm files and load Log.Write("Initializing World..."); - foreach (Realm r in Realms) + foreach (Realm r in RealmCollection) { if (r.IsInitialRealm) { @@ -90,9 +90,34 @@ namespace MudEngine.GameManagement public void Save() { //Save all of the Environments - for (Int32 x = 0; x <= Realms.Count - 1; x++) + for (Int32 x = 0; x <= RealmCollection.Count - 1; x++) { - Realms[x].Save(_Game.DataPaths.Environment); + RealmCollection[x].Save(_Game.DataPaths.Environment); + } + } + + public void Load() + { + String filename = _Game.GameTitle + ".ini"; + + //Restore initial realm + String realmFile = FileManager.GetData(filename, "InitialRealm"); + String realmFolder = Path.GetFileNameWithoutExtension(realmFile); + String realmPath = Path.Combine(_Game.DataPaths.Environment, realmFolder, realmFile); + + foreach (String realm in FileManager.GetCollectionData(filename, "RealmCollection")) + { + Realm r = new Realm(_Game); + r.Load(Path.Combine(realmPath, realm)); + } + + foreach (Realm r in RealmCollection) + { + if (r.IsInitialRealm) + { + _Game.InitialRealm = r; + break; + } } } @@ -106,7 +131,7 @@ namespace MudEngine.GameManagement //set Realms to avoid conflict. if (realm.IsInitialRealm) { - foreach (Realm r in Realms) + foreach (Realm r in RealmCollection) { if (r.IsInitialRealm) { @@ -121,7 +146,7 @@ namespace MudEngine.GameManagement _Game.InitialRealm = realm; //TODO: Check for duplicate Realms. - Realms.Add(realm); + RealmCollection.Add(realm); } /// @@ -167,7 +192,7 @@ namespace MudEngine.GameManagement /// private Realm GetRealm(String filename) { - foreach (Realm r in Realms) + foreach (Realm r in RealmCollection) { if (r.Filename == filename) return r; diff --git a/MudEngine/GameManagement/Log.cs b/MudEngine/GameManagement/Log.cs index 058293e..9817c74 100644 --- a/MudEngine/GameManagement/Log.cs +++ b/MudEngine/GameManagement/Log.cs @@ -12,8 +12,14 @@ namespace MudEngine.GameManagement { static List cachedMessages = new List(); public static Boolean IsVerbose; - - public static void Write(String message) + + /// + /// Writes a message to the log file and if pushMessage is true it will ignore placing the message + /// into the cachedmessages for later pooling, but push it directly to the console. + /// + /// + /// + public static void Write(String message, Boolean pushMessage) { String filename = Path.Combine(FileManager.GetDataPath(SaveDataTypes.Root), "Log.txt"); StreamWriter sw; @@ -23,11 +29,20 @@ namespace MudEngine.GameManagement else sw = File.CreateText(filename); - sw.WriteLine(message); + sw.WriteLine(DateTime.Now.ToString() + ": " + message); sw.Close(); //Add to the cache so consoles can get these messages if they want to. - cachedMessages.Add(message); + //If Pushmessage=true then we skip caching and dump it straight to the console + if ((pushMessage) && (!IsVerbose)) + Console.WriteLine(message); + else + cachedMessages.Add(message); + } + + public static void Write(String message) + { + Write(message, true); } public static String GetMessages() diff --git a/MudEngine/GameObjects/BaseObject.cs b/MudEngine/GameObjects/BaseObject.cs index 1801eba..1c1dbaf 100644 --- a/MudEngine/GameObjects/BaseObject.cs +++ b/MudEngine/GameObjects/BaseObject.cs @@ -170,11 +170,23 @@ namespace MudEngine.GameObjects public virtual void Load(String filename) { + if (String.IsNullOrEmpty(filename)) + return; + + if (!File.Exists(filename)) + { + Log.Write("Error: Attempted to load file " + filename); + return; + } this.Name = FileManager.GetData(filename, "Name"); this.Description = FileManager.GetData(filename, "Description"); this.Feel = FileManager.GetData(filename, "Feel"); this.Listen = FileManager.GetData(filename, "Listen"); this.Smell = FileManager.GetData(filename, "Smell"); + + //Set the Filename property based off the physical filename, as setting this.Name sets a default filename + //which might not match that of the actual physical filename on the harddrive. + this.Filename = Path.GetFileName(filename); } #endregion } diff --git a/MudEngine/GameObjects/Characters/BaseCharacter.cs b/MudEngine/GameObjects/Characters/BaseCharacter.cs index abf1374..1dbbc8d 100644 --- a/MudEngine/GameObjects/Characters/BaseCharacter.cs +++ b/MudEngine/GameObjects/Characters/BaseCharacter.cs @@ -136,6 +136,12 @@ namespace MudEngine.GameObjects.Characters CurrentRoom.Description = "You are in the Aybss. It is void of all life."; return; } + + //TODO: Load player Inventory. + /* Due to private accessor Inv needs to be restored via + * foreach (Item in Inventory) + * this.AddItem(Item); + */ } public override void Save(String path) @@ -211,27 +217,12 @@ namespace MudEngine.GameObjects.Characters public void ExecuteCommand(String command) { - //TODO: Character class can handle a lot of the command management here, checking various things prior to sending - //the command off to the command engine for execution. CommandSystem.ExecuteCommand(command, this); Send(""); //Blank line to help readability. //Now that the command has been executed, restore the Command: message Send("Command: ", false); - - /* No longer needed due to player.send() sending content to the player. - if (result.Result != null) - { - StringBuilder sb = new StringBuilder(); - foreach (object item in result.Result) - { - if (item is String) - sb.AppendLine(item.ToString()); - } - return sb.ToString(); - } - */ } internal void Initialize() @@ -239,13 +230,6 @@ namespace MudEngine.GameObjects.Characters if (ActiveGame.IsMultiplayer) client.Receive(new byte[255]); - if (Game.IsDebug) - Log.Write("New Player Connected."); - - Log.Write("Loading internal game commands..."); - //Loads the MudEngine Game Commands - //CommandSystem.LoadBaseCommands(); - //Ensure custom commands are loaded until everything is fleshed out. if (Game.IsDebug) { @@ -266,6 +250,7 @@ namespace MudEngine.GameObjects.Characters CurrentRoom = ActiveGame.InitialRealm.InitialZone.InitialRoom; ExecuteCommand("Login"); + Log.Write(Name + " has logged in."); ExecuteCommand("Look"); //MUST happen after Room setup is completed, otherwise the player default Abyss Room is printed. } internal void Receive(String data) @@ -343,7 +328,7 @@ namespace MudEngine.GameObjects.Characters IsActive = false; client.Close(); - Log.Write("Player " + this.Name + " disconnected."); + Log.Write(Name + " disconnected."); } } internal String ReadInput() diff --git a/MudEngine/GameObjects/Environment/Realm.cs b/MudEngine/GameObjects/Environment/Realm.cs index f86775a..791fdc7 100644 --- a/MudEngine/GameObjects/Environment/Realm.cs +++ b/MudEngine/GameObjects/Environment/Realm.cs @@ -33,6 +33,35 @@ namespace MudEngine.GameObjects.Environment public Realm(GameManagement.Game game) : base(game) { ZoneCollection = new List(); + InitialZone = new Zone(game); + } + + public override void Load(string filename) + { + base.Load(filename); + + IsInitialRealm = Convert.ToBoolean(FileManager.GetData(filename, "IsInitialRealm")); + + String zoneFile = FileManager.GetData(filename, "InitialZone"); + String realmPath = filename.Substring(0, filename.Length - Path.GetFileName(filename).Length); + String zonePath = Path.Combine(realmPath, "Zones", Path.GetFileNameWithoutExtension(zoneFile)); + + //Load all zones + foreach (String zone in FileManager.GetCollectionData(filename, "ZoneCollection")) + { + Zone z = new Zone(ActiveGame); + z.Load(Path.Combine(zonePath, zone)); + } + + //Set the initial zone. + foreach (Zone z in ZoneCollection) + { + if (z.IsInitialZone) + { + InitialZone = z; + break; + } + } } public override void Save(String path) @@ -45,10 +74,12 @@ namespace MudEngine.GameObjects.Environment FileManager.WriteLine(filename, this.IsInitialRealm.ToString(), "IsInitialRealm"); FileManager.WriteLine(filename, this.InitialZone.Filename, "InitialZone"); + String zonePath = Path.Combine(path, "Zones"); foreach (Zone z in ZoneCollection) { FileManager.WriteLine(filename, z.Filename, "ZoneCollection"); - z.Save(path); + + z.Save(zonePath); } } diff --git a/MudEngine/GameObjects/Environment/Room.cs b/MudEngine/GameObjects/Environment/Room.cs index 0cc9079..cee292a 100644 --- a/MudEngine/GameObjects/Environment/Room.cs +++ b/MudEngine/GameObjects/Environment/Room.cs @@ -91,11 +91,14 @@ namespace MudEngine.GameObjects.Environment public override void Save(String path) { - path = Path.Combine(path, "Rooms"); - base.Save(path); String filename = Path.Combine(path, Filename); + + FileManager.WriteLine(filename, IsInitialRoom.ToString(), "IsInitialRoom"); + FileManager.WriteLine(filename, this.IsSafe.ToString(), "IsSafe"); + FileManager.WriteLine(filename, this.Realm, "Realm"); + FileManager.WriteLine(filename, this.Zone, "Zone"); } /// diff --git a/MudEngine/GameObjects/Environment/Zone.cs b/MudEngine/GameObjects/Environment/Zone.cs index ef07abd..04bbaf0 100644 --- a/MudEngine/GameObjects/Environment/Zone.cs +++ b/MudEngine/GameObjects/Environment/Zone.cs @@ -79,6 +79,7 @@ namespace MudEngine.GameObjects.Environment public Zone(GameManagement.Game game) : base(game) { RoomCollection = new List(); + InitialRoom = new Room(game); IsSafe = false; Realm = "No Realm Associated."; } @@ -98,10 +99,45 @@ namespace MudEngine.GameObjects.Environment FileManager.WriteLine(filename, this.StatDrainAmount.ToString(), "StatDrainAmount"); FileManager.WriteLine(filename, this.InitialRoom.Filename, "InitialRoom"); + String roomPath = Path.Combine(path, "Rooms"); foreach (Room r in RoomCollection) { - FileManager.WriteLine(filename, r.Filename, "Room"); - r.Save(path); + FileManager.WriteLine(filename, r.Filename, "RoomCollection"); + r.Save(roomPath); + } + } + + public override void Load(string filename) + { + base.Load(filename); + + this.IsInitialZone = Convert.ToBoolean(FileManager.GetData(filename, "IsInitialZone")); + this.IsSafe = Convert.ToBoolean(FileManager.GetData(filename, "IsSafe")); + this.Realm = FileManager.GetData(filename, "Realm"); + this.StatDrain = Convert.ToBoolean(FileManager.GetData(filename, "StatDrain")); + this.StatDrainAmount = Convert.ToInt32(FileManager.GetData(filename, "StatDrainAmount")); + + //Load the InitialRoom + String roomFile = FileManager.GetData(filename, "InitialRoom"); + String realmPath = Path.Combine(ActiveGame.DataPaths.Environment, Path.GetFileNameWithoutExtension(this.Realm)); + String zonePath = Path.Combine(realmPath, "Zones", Path.GetFileNameWithoutExtension(this.Filename)); + String roomPath = Path.Combine(zonePath, "Rooms"); + + //Now get the rooms in the zone + foreach (String room in FileManager.GetCollectionData(filename, "RoomCollection")) + { + Room r = new Room(ActiveGame); + r.Load(Path.Combine(roomPath, room)); + } + + //Set the initial Room. + foreach (Room r in RoomCollection) + { + if (r.IsInitialRoom) + { + InitialRoom = r; + break; + } } } diff --git a/MudGame/Program.cs b/MudGame/Program.cs index 1314d83..0b1a731 100644 --- a/MudGame/Program.cs +++ b/MudGame/Program.cs @@ -19,11 +19,6 @@ namespace MudGame static void Main(String[] args) { - - Log.Write("Launching..."); - ScriptEngine scriptEngine; - - //Re-create the settings file if it is missing if (!File.Exists(SettingsFile)) { @@ -41,27 +36,29 @@ namespace MudGame else Log.IsVerbose = false; - Log.Write("Loading settings..."); + + Log.Write("Launching...", true); + ScriptEngine scriptEngine; + + Log.Write("Loading settings...", true); scriptEngine = new ScriptEngine(new Game(), ScriptEngine.ScriptTypes.Both); //scriptEngine.CompileScripts(); - Log.Write("Initializing Script Engine for Script Compilation..."); + Log.Write("Initializing Script Engine for Script Compilation...", true); scriptEngine.Initialize(); GameObject obj = scriptEngine.GetObjectOf("Game"); - Console.WriteLine(Log.GetMessages()); - Log.FlushMessages(); + //Console.WriteLine(Log.GetMessages()); + //Log.FlushMessages(); if (obj == null) { - Log.Write("Setting up the Default Engine Game Manager..."); game = new Game(); obj = new GameObject(game, "Game"); scriptEngine = new ScriptEngine((Game)obj.Instance, ScriptEngine.ScriptTypes.Both); } else { - Log.Write("Setting up " + obj.GetProperty("GameTitle") + " Manager..."); game = (Game)obj.Instance; scriptEngine = new ScriptEngine(game, ScriptEngine.ScriptTypes.Both); } @@ -72,9 +69,11 @@ namespace MudGame //MUST be called before game.Start() //scriptEngine.Initialize(); //game.scriptEngine = scriptEngine; //Pass this script engine off to the game to use now. - Log.Write("Starting " + obj.GetProperty().GameTitle + "..."); - Console.WriteLine(Log.GetMessages()); - Log.FlushMessages(); + Log.Write(""); + Log.Write("Starting " + obj.GetProperty().GameTitle + "...", true); + Log.Write(""); + //Console.WriteLine(Log.GetMessages()); + //Log.FlushMessages(); //Server is only enabled if the option is in the settings file //Allows developers to remove the option from the settings file and letting @@ -93,7 +92,7 @@ namespace MudGame //Make sure the Game is in fact running. if (!game.IsRunning) { - Console.WriteLine("Error starting game!\nReview Log file for details."); + Log.Write("Error starting game!\nReview Log file for details.", true); return; } @@ -104,7 +103,7 @@ namespace MudGame { if ((game.PlayerCollection[0] == null) || (game.PlayerCollection[0].Name == "New BaseCharacter")) { - Console.WriteLine("Error! No player available for creation!"); + Log.Write("Error! No player available for creation!", true); return; } } @@ -116,25 +115,20 @@ namespace MudGame List buf = new List(); - while (game.IsRunning) + try { - game.Update(); - System.Threading.Thread.Sleep(1); - - StringBuilder sb = new StringBuilder(); - - ConsoleKeyInfo info = Console.ReadKey(); - - if (info.KeyChar == '\r') + while (game.IsRunning) { - foreach (char c in buf) - sb.Append(c); - - game.PlayerCollection[0].ExecuteCommand(sb.ToString()); + game.Update(); + System.Threading.Thread.Sleep(1); } - else - buf.Add(info.KeyChar); } + catch (Exception ex) + { + Log.Write("Critical Error! " + ex.Message); + } + //Save the game on shut-down. + game.Save(); } } } \ No newline at end of file diff --git a/MudGame/bin/Debug/..svnbridge/.svnbridge b/MudGame/bin/Debug/..svnbridge/.svnbridge index 20754ee..81fb272 100644 --- a/MudGame/bin/Debug/..svnbridge/.svnbridge +++ b/MudGame/bin/Debug/..svnbridge/.svnbridge @@ -17,4 +17,16 @@ MudGame.vshost.exe.manifest Player temp Realms +svn:ignoreLog.txt +MudEngine.dll +MudEngine.pdb +MudGame.exe +MudGame.pdb +MudGame.vshost.exe +MudGame.vshost.exe.manifest +Player +temp +Realms +Mud Designer Example Game.ini +World \ No newline at end of file