From 0f45ecec5337dc6255930295e8968d50991229fe Mon Sep 17 00:00:00 2001 From: Scionwest_cp Date: Tue, 3 Aug 2010 20:20:24 -0700 Subject: [PATCH] MudEngine: - Updated all game commands to support the new Player.Send() method. Returning CommandResults is no longer supported. - Login command now executes the Look command upon completing login. - Look command now supports Rooms DetailDescription property. Use this for multi-line descriptions. - Several changes to the Restart command. Still not working fully however, it no longer calls duplicate methods. - Fixed Walk command not moving players around. - Loading engine commands no longer happens more than once. - Added additional Server Console log output - BaseCharacter.Send() now correctly displays content to the user and prints the "Command:" message to the player after every command completed. - The Server now sets Player.IsControlled to true when a player connects. - BaseCharacter.Send() checks if the game is multi-player or not. If it is, it prints to Console, if not then prints to telnet clients. Mud Offline Example: - Updated Zeroth Realm creation to use Room.DetailDescription now that the Look command supports it. - Updated the Game loop. No longer needs to print to the console due to the player.Execute() command automatically printing content to the console. Mud Server: - Removed player from server as it was not being used any longer. --- MudEngine/Commands/CommandLogin.cs | 1 + MudEngine/Commands/CommandLook.cs | 14 ++++-- MudEngine/Commands/CommandRestart.cs | 11 ++++- MudEngine/Commands/CommandWalk.cs | 8 +-- MudEngine/GameManagement/CommandEngine.cs | 49 ++++++++++--------- MudEngine/GameManagement/Game.cs | 31 ++++++++++-- .../GameObjects/Characters/BaseCharacter.cs | 30 ++++++++---- MudEngine/Networking/Server.cs | 1 + MudEngine/Scripting/ScriptEngine.cs | 12 ++++- MudOfflineExample/Environments/Zeroth.cs | 6 ++- MudOfflineExample/Program.cs | 10 ++-- MudServer/Program.cs | 4 +- 12 files changed, 116 insertions(+), 61 deletions(-) diff --git a/MudEngine/Commands/CommandLogin.cs b/MudEngine/Commands/CommandLogin.cs index 1ac88c6..cbb5977 100644 --- a/MudEngine/Commands/CommandLogin.cs +++ b/MudEngine/Commands/CommandLogin.cs @@ -53,6 +53,7 @@ namespace MudEngine.Commands } player.Send("Welcome " + player.Name + "!"); + player.CommandSystem.ExecuteCommand("Look", player); return new CommandResults(); } } diff --git a/MudEngine/Commands/CommandLook.cs b/MudEngine/Commands/CommandLook.cs index 7cc8b67..6960eee 100644 --- a/MudEngine/Commands/CommandLook.cs +++ b/MudEngine/Commands/CommandLook.cs @@ -19,16 +19,22 @@ namespace MudEngine.Commands public CommandResults Execute(string command, BaseCharacter player) { - StringBuilder desc = new StringBuilder(); - if (player.CurrentRoom == null) { return new CommandResults("Not within a created Room."); } - desc.AppendLine(player.CurrentRoom.Description); + if (player.CurrentRoom.DetailedDescription.Count == 0) + player.Send(player.CurrentRoom.Description); + else + { + foreach(string entry in player.CurrentRoom.DetailedDescription) + { + player.Send(entry); + } + } - return new CommandResults(desc.ToString()); + return new CommandResults(); } } } diff --git a/MudEngine/Commands/CommandRestart.cs b/MudEngine/Commands/CommandRestart.cs index 26d4cf1..58bb048 100644 --- a/MudEngine/Commands/CommandRestart.cs +++ b/MudEngine/Commands/CommandRestart.cs @@ -32,8 +32,17 @@ namespace MudEngine.Commands string filename = Path.Combine(path, player.ActiveGame.PlayerCollection[i].Filename); player.ActiveGame.PlayerCollection[i].Save(filename); } - player.ActiveGame.Server.EndServer(); + + //player.ActiveGame.Server.EndServer(); //-Handled in Game.Shutdown() below. + player.ActiveGame.Shutdown(); + player.ActiveGame.Start(); + /* Game.Start() calls this, do we need a reference to the playercollection? + * They should be unloaded anyway and re-loaded during game.start to force a clean restart of all objects. player.ActiveGame.Server.Initialize(555, ref player.ActiveGame.PlayerCollection); + */ + + Console.WriteLine("Server Restart Completed."); + //This is never printed as CommandResults is no longer outputted to the player console, player.Send is used return new CommandResults("Server Restarted."); } return new CommandResults("Access Denied."); diff --git a/MudEngine/Commands/CommandWalk.cs b/MudEngine/Commands/CommandWalk.cs index cd91ff4..a3cbda9 100644 --- a/MudEngine/Commands/CommandWalk.cs +++ b/MudEngine/Commands/CommandWalk.cs @@ -33,13 +33,9 @@ namespace MudEngine.Commands //Move the player into their new room player.Move(door.TravelDirection); - CommandResults cmd = player.CommandSystem.ExecuteCommand("Look", player); - string lookValue = ""; + player.CommandSystem.ExecuteCommand("Look", player); - if (cmd.Result.Length != 0) - lookValue = cmd.Result[0].ToString(); - - return new CommandResults(new object[] { lookValue, player.CurrentRoom }); + return null; } } } diff --git a/MudEngine/GameManagement/CommandEngine.cs b/MudEngine/GameManagement/CommandEngine.cs index 76f54d7..92c3864 100644 --- a/MudEngine/GameManagement/CommandEngine.cs +++ b/MudEngine/GameManagement/CommandEngine.cs @@ -19,23 +19,23 @@ namespace MudEngine.GameManagement /// /// Gets or Sets a Dictionary list of available commands to use. /// - public Dictionary CommandCollection { get; set; } + public static Dictionary CommandCollection { get; set; } - internal Dictionary _Commands { get; set; } + internal Dictionary __Commands { get; set; } public CommandEngine() { - if ((CommandCollection == null) || (CommandCollection.Count == 0)) - LoadBaseCommands(); + if ((CommandEngine.CommandCollection == null) || (CommandEngine.CommandCollection.Count == 0)) + CommandEngine.LoadBaseCommands(); - _Commands = CommandCollection; + //_Commands = CommandEngine.CommandCollection; } - public List GetCommands() + public static List GetCommands() { List temp = new List(); - foreach (string name in CommandCollection.Keys) + foreach (string name in CommandEngine.CommandCollection.Keys) { temp.Add(name); } @@ -43,20 +43,21 @@ namespace MudEngine.GameManagement return temp; } - public string GetCommand(object Parameter) + public static IGameCommand GetCommand(string command) { - List objectList = (List)Parameter; - - foreach (object obj in objectList) + if (IsValidCommand(command)) { - if (obj is string) - return (string)obj; + foreach (IGameCommand cmd in CommandCollection.Values) + { + if (cmd.Name.ToLower() == command.ToLower()) + return cmd; + } } return null; } - public bool IsValidCommand(string Name) + public static bool IsValidCommand(string Name) { if (CommandCollection.ContainsKey(Name.ToLower())) return true; @@ -75,11 +76,13 @@ namespace MudEngine.GameManagement if (Game.IsDebug) Log.Write("Executing command: " + command); - foreach (string key in CommandCollection.Keys) + foreach (string key in CommandEngine.CommandCollection.Keys) { if (commandKey.ToLower().Contains(key.ToLower())) { - return player.CommandSystem._Commands[key].Execute(command, player); + IGameCommand cmd = CommandEngine.CommandCollection[key]; + return cmd.Execute(command, player); + //return player.CommandSystem._Commands[key].Execute(command, player); //return player.Commands.ExecuteCommand[key.ToLower()]Execute(command, player); } } @@ -87,7 +90,7 @@ namespace MudEngine.GameManagement return new CommandResults(); } - public void LoadBaseCommands() + public static void LoadBaseCommands() { LoadCommandLibrary(Assembly.GetExecutingAssembly(), true); } @@ -98,12 +101,12 @@ namespace MudEngine.GameManagement /// commands dictionary for use with the project /// /// - public void LoadCommandLibrary() + public static void LoadCommandLibrary() { LoadCommandLibrary(Assembly.GetExecutingAssembly()); } - public void LoadCommandLibrary(string libraryFilename) + public static void LoadCommandLibrary(string libraryFilename) { if (System.IO.File.Exists(libraryFilename)) { @@ -112,18 +115,18 @@ namespace MudEngine.GameManagement } } - public void LoadCommandLibrary(List commandLibraries) + public static void LoadCommandLibrary(List commandLibraries) { foreach (Assembly lib in commandLibraries) LoadCommandLibrary(lib); } - public void LoadCommandLibrary(Assembly commandLibrary) + public static void LoadCommandLibrary(Assembly commandLibrary) { LoadCommandLibrary(commandLibrary, false); } - public void LoadCommandLibrary(Assembly commandLibrary, bool purgeOldCommands) + public static void LoadCommandLibrary(Assembly commandLibrary, bool purgeOldCommands) { //no assembly passed for whatever reason, don't attempt to enumerate through it. if (commandLibrary == null) @@ -165,7 +168,7 @@ namespace MudEngine.GameManagement } } - public void ClearCommands() + public static void ClearCommands() { CommandCollection = new Dictionary(); } diff --git a/MudEngine/GameManagement/Game.cs b/MudEngine/GameManagement/Game.cs index c359b3b..56f6c83 100644 --- a/MudEngine/GameManagement/Game.cs +++ b/MudEngine/GameManagement/Game.cs @@ -238,12 +238,31 @@ namespace MudEngine.GameManagement /// public bool Start() { - Log.Write("Starting Game..."); + Log.Write("Game Initializing..."); + //Setup the scripting engine and load our script library scriptEngine.Initialize(); - - Log.Write("Initializing location..."); + + /* + * If a custom player script is loaded in the script engine, then the base commands are + * loaded when the script is instanced automatically. If there is no script then these + * don't get loaded and will need to be forced. + * This prevents a duplicate "Loading Commands" message in the server console if the + * player script exists and pre-loads the commands during script instancing in ScriptEngine.Initialize() + */ + Log.Write("Initializing Command Engine..."); + if ((CommandEngine.CommandCollection == null) || (CommandEngine.CommandCollection.Count == 0)) + CommandEngine.LoadBaseCommands(); + + if (IsDebug) + { + foreach (string command in CommandEngine.CommandCollection.Keys) + Log.Write("Command Loaded: " + command); + } + //See if we have an Initial Realm set + //TODO: Check for saved Realm files and load + Log.Write("Initializing World..."); foreach (Realm r in RealmCollection) { if (r.IsInitialRealm) @@ -260,12 +279,14 @@ namespace MudEngine.GameManagement return false; } else - Log.Write("Initial Location defined -> " + InitialRealm.Name + "." + InitialRealm.InitialZone.Name + "." + InitialRealm.InitialZone.InitialRoom.Name); + Log.Write("Initial Location loaded-> " + InitialRealm.Name + "." + InitialRealm.InitialZone.Name + "." + InitialRealm.InitialZone.InitialRoom.Name); - Log.Write("Starting Server..."); //Start the Telnet server if (IsMultiplayer) + { + Log.Write("Starting Server..."); this.StartServer(); + } //Game is running now. IsRunning = true; diff --git a/MudEngine/GameObjects/Characters/BaseCharacter.cs b/MudEngine/GameObjects/Characters/BaseCharacter.cs index 6e860ee..8623915 100644 --- a/MudEngine/GameObjects/Characters/BaseCharacter.cs +++ b/MudEngine/GameObjects/Characters/BaseCharacter.cs @@ -125,12 +125,18 @@ namespace MudEngine.GameObjects.Characters //TODO: Check the Room/Zone/Realm to see if anything needs to occure during travel. } - public String ExecuteCommand(string command) + 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. - CommandResults result = CommandSystem.ExecuteCommand(command, this); + 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(); @@ -141,7 +147,7 @@ namespace MudEngine.GameObjects.Characters } return sb.ToString(); } - return ""; + */ } internal void Initialize() @@ -153,26 +159,27 @@ namespace MudEngine.GameObjects.Characters Log.Write("Loading internal game commands..."); //Loads the MudEngine Game Commands - CommandSystem.LoadBaseCommands(); + //CommandSystem.LoadBaseCommands(); //Ensure custom commands are loaded until everything is fleshed out. if (Game.IsDebug) { - foreach (string command in CommandSystem.GetCommands()) + foreach (string command in CommandEngine.GetCommands()) { Log.Write("Command loaded: " + command); } } - string result = ExecuteCommand("Login"); - + ExecuteCommand("Login"); + //Set the players initial room CurrentRoom = ActiveGame.InitialRealm.InitialZone.InitialRoom; } internal void Receive(string data) { - data = ExecuteCommand(data); - Send(data); + //data = ExecuteCommand(data); + ExecuteCommand(data); + //Send(data); //Results no longer returned as Player.Send() is used by the commands now. if (!ActiveGame.IsRunning) Disconnect(); } @@ -190,7 +197,10 @@ namespace MudEngine.GameObjects.Characters if (newLine) data += "\n\r"; - client.Send(encoding.GetBytes(data)); + if (ActiveGame.IsMultiplayer) + client.Send(encoding.GetBytes(data)); + else + Console.Write(data); } catch (Exception) { diff --git a/MudEngine/Networking/Server.cs b/MudEngine/Networking/Server.cs index 178ed21..bf35c10 100644 --- a/MudEngine/Networking/Server.cs +++ b/MudEngine/Networking/Server.cs @@ -79,6 +79,7 @@ namespace MudEngine.Networking } while (sub < 0); players[sub].client = server.Accept(); players[sub].IsActive = true; + players[sub].IsControlled = true; clientThreads[sub] = new Thread(ReceiveThread); clientThreads[sub].Start((object)sub); } diff --git a/MudEngine/Scripting/ScriptEngine.cs b/MudEngine/Scripting/ScriptEngine.cs index 60295b5..3f51c38 100644 --- a/MudEngine/Scripting/ScriptEngine.cs +++ b/MudEngine/Scripting/ScriptEngine.cs @@ -194,6 +194,7 @@ namespace MudEngine.Scripting { if (_ScriptTypes == ScriptTypes.Assembly) { + Log.Write("Loading Assembly based scripts..."); InitializeAssembly(); } else @@ -203,6 +204,8 @@ namespace MudEngine.Scripting foreach (Assembly assembly in _AssemblyCollection) { + Log.Write("Checking " + Path.GetFileName(assembly.Location) + " for scripts..."); + foreach (Type t in assembly.GetTypes()) { if (t.BaseType == null) @@ -210,6 +213,7 @@ namespace MudEngine.Scripting if (t.BaseType.Name == "BaseObject") { GameObjects.Add(new GameObject(Activator.CreateInstance(t, new object[] {_Game}), t.Name)); + Log.Write(t.Name + " script loaded."); continue; } else if (t.BaseType.Name == "BaseCharacter") @@ -217,6 +221,7 @@ namespace MudEngine.Scripting GameObject obj = new GameObject(Activator.CreateInstance(t, new object[] {_Game}), t.Name); GameObjects.Add(obj); obj.GetProperty().CurrentRoom = _Game.InitialRealm.InitialZone.InitialRoom; + Log.Write(t.Name + " script loaded."); continue; } } @@ -234,18 +239,21 @@ namespace MudEngine.Scripting if (libraries.Length == 0) { - Log.Write("Failed to load Script Assembly!"); + Log.Write("No possible script libraries found."); return; } foreach (string library in libraries) + { + Log.Write("Found possible script libary: " + Path.GetFileName(library)); _AssemblyCollection.Add(Assembly.LoadFile(library)); - + } _AssemblyCollection.Add(Assembly.GetExecutingAssembly()); } private void InitializeSourceFiles() { + Log.Write("Source file scripts is not supported! Please change the script engine settings to load pre-compiled Assemblies!"); } public GameObject GetObject(string objectName) diff --git a/MudOfflineExample/Environments/Zeroth.cs b/MudOfflineExample/Environments/Zeroth.cs index 24e5e31..034b966 100644 --- a/MudOfflineExample/Environments/Zeroth.cs +++ b/MudOfflineExample/Environments/Zeroth.cs @@ -42,7 +42,8 @@ namespace MUDGame Room bedroom = new Room(game); bedroom.Name = "Bedroom"; - bedroom.Description = "This is your bedroom, it's small but comfortable. You have a bed, a book shelf and a rug on the floor.\nYou may walk to the WEST to find you Closet."; + bedroom.DetailedDescription.Add("This is your bedroom, it's small but comfortable. You have a bed, a book shelf and a rug on the floor."); + bedroom.DetailedDescription.Add("You may walk to the WEST to find you Closet."); bedroom.Zone = zone.Name; bedroom.Realm = realm.Name; bedroom.IsInitialRoom = true; @@ -50,7 +51,8 @@ namespace MUDGame Room closet = new Room(game); closet.Name = "Closet"; - closet.Description = "Your closet contains clothing and some shoes.\nYou may walk to your EAST to find your Room."; + closet.DetailedDescription.Add("Your closet contains clothing and some shoes."); + closet.DetailedDescription.Add("You may walk to your EAST to find your Room."); closet.Zone = zone.Name; closet.Realm = realm.Name; zone.AddRoom(closet); diff --git a/MudOfflineExample/Program.cs b/MudOfflineExample/Program.cs index 803c14f..8a81069 100644 --- a/MudOfflineExample/Program.cs +++ b/MudOfflineExample/Program.cs @@ -57,17 +57,15 @@ namespace MUDGame Console.WriteLine("Available Commands are\n Look\n Exit\n Walk 'direction' where direction = north/south/east/west/up/down\n"); //Invoke the Look command so the player knows whats around him/her - Console.WriteLine(player.ExecuteCommand("Look")); + player.ExecuteCommand("Look"); //Broken? has not been tested since CommandEngine changes. while (game.IsRunning) { + /* No longer needed as player.ExecuteCommand() will place this for us. Console.Write("Command: "); - Console.WriteLine(player.ExecuteCommand(Console.ReadLine())); + */ + player.ExecuteCommand(Console.ReadLine()); } - - // - Exit command handles this now - game.Shutdown(); - Console.WriteLine("Press Enter to exit."); - Console.ReadKey(); } } } diff --git a/MudServer/Program.cs b/MudServer/Program.cs index d23db74..59b2d58 100644 --- a/MudServer/Program.cs +++ b/MudServer/Program.cs @@ -20,7 +20,7 @@ namespace MudServer realm.BuildZeroth(); - BaseCharacter serverAdmin = new BaseCharacter(game); + //BaseCharacter serverAdmin = new BaseCharacter(game); //Setup the game game.AutoSave = true; @@ -39,7 +39,7 @@ namespace MudServer game.ServerType = ProtocolType.Tcp; game.ServerPort = 555; game.MaximumPlayers = 1000; - Game.IsDebug = true; + Game.IsDebug = false; game.Start();