diff --git a/MudEngine/MudEngine.sln b/MudEngine/MudEngine.sln new file mode 100644 index 0000000..70d831e --- /dev/null +++ b/MudEngine/MudEngine.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinPC_Server", "WinPC_Server\WinPC_Server.csproj", "{9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinPC_Engine", "WinPC_Engine\WinPC_Engine.csproj", "{27C84625-1D4A-4DBF-9770-46D535506485}" +EndProject +Global + GlobalSection(TeamFoundationVersionControl) = preSolution + SccNumberOfProjects = 3 + SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} + SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs03 + SccLocalPath0 = . + SccProjectUniqueName1 = WinPC_Engine\\WinPC_Engine.csproj + SccProjectName1 = WinPC_Engine + SccLocalPath1 = WinPC_Engine + SccProjectUniqueName2 = WinPC_Server\\WinPC_Server.csproj + SccProjectName2 = WinPC_Server + SccLocalPath2 = WinPC_Server + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Debug|Any CPU.ActiveCfg = Debug|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Debug|x86.ActiveCfg = Debug|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Debug|x86.Build.0 = Debug|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Release|Any CPU.ActiveCfg = Release|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Release|Mixed Platforms.Build.0 = Release|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Release|x86.ActiveCfg = Release|x86 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}.Release|x86.Build.0 = Release|x86 + {27C84625-1D4A-4DBF-9770-46D535506485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Debug|Any CPU.Build.0 = Debug|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Debug|x86.ActiveCfg = Debug|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Release|Any CPU.ActiveCfg = Release|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Release|Any CPU.Build.0 = Release|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {27C84625-1D4A-4DBF-9770-46D535506485}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/MudEngine/MudEngine.vssscc b/MudEngine/MudEngine.vssscc new file mode 100644 index 0000000..794f014 --- /dev/null +++ b/MudEngine/MudEngine.vssscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" +} diff --git a/MudEngine/WinPC_Engine/Core/BaseCommand.cs b/MudEngine/WinPC_Engine/Core/BaseCommand.cs new file mode 100644 index 0000000..c60dee5 --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/BaseCommand.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; + +using MudEngine.Game.Characters; +using MudEngine.Core.Interface; + +namespace MudEngine.Core +{ + public abstract class BaseCommand : ICommand + { + /// + /// Gets or Sets a collection of help topics related to this command. + /// + [Browsable(false)] + public List Help { get; set; } + + public BaseCommand() + { + Help = new List(); + this.Name = this.GetType().Name.Substring("Command".Length); + } + + /// + /// Executes the command for the character supplied. + /// + /// + /// + public abstract void Execute(string command, StandardCharacter character); + + public string Name {get;set;} + + public string Description + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + } +} diff --git a/MudEngine/WinPC_Engine/Core/CommandSystem.cs b/MudEngine/WinPC_Engine/Core/CommandSystem.cs new file mode 100644 index 0000000..befd323 --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/CommandSystem.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; + +using MudEngine.Core.Interface; +using MudEngine.Game.Characters; + +namespace MudEngine.Core +{ + public class CommandSystem + { + public static Dictionary Commands + { + get + { + if (_Commands == null) + _Commands = new Dictionary(); + return _Commands; + } + private set + { + _Commands = value; + } + } + private static Dictionary _Commands; + + public Dictionary CommandCollection { get; private set; } + + public CommandSystem(Dictionary commands) + { + this.CommandCollection = new Dictionary(); + this.CommandCollection = commands; + + //Handled by the StandardGame class now. + //LoadCommands(); + } + + public List GetCommands() + { + List collection = new List(); + + foreach (ICommand c in CommandSystem.Commands.Values) + collection.Add(c); + + return collection; + } + + public ICommand GetCommand(string command) + { + foreach (ICommand c in CommandSystem.Commands.Values) + { + if (c.Name.ToLower() == command.ToLower()) + return c; + } + + return null; + } + + public bool IsValidCommand(string command) + { + if (CommandSystem.Commands.ContainsKey(command)) + return true; + else + return false; + } + + public void Execute(string command, StandardCharacter character) + { + string key = command.Insert(0, "Command"); + + foreach (string k in CommandSystem.Commands.Keys) + { + if (key.ToLower().Contains(k.ToLower())) + { + ICommand cmd = CommandSystem.Commands[k]; + try + { + cmd.Execute(command, character); + } + catch (Exception ex) + { + Logger.WriteLine("Error: " + ex.Message); + Console.WriteLine("Error: " + ex.Message); + } + + return; + } + } + + //TODO: Inform player that this was not a valid command. + } + + public static void LoadCommands() + { + LoadCommandLibrary(Assembly.GetExecutingAssembly(), true); + } + + public static void LoadCommandLibrary(Assembly commandLibrary) + { + LoadCommandLibrary(commandLibrary, true); + } + + public static void LoadCommandLibrary(Assembly commandLibrary, bool purgeLoadedCommands) + { + if (purgeLoadedCommands) + PurgeCommands(); + + if (commandLibrary == null) + return; + + foreach (Type type in commandLibrary.GetTypes()) + { + //All commands implement the ICommand interface. + //If that interface is not present on this Type, skip and go to the next one. + if (type.GetInterface("ICommand") == null) + continue; + else if (type.IsAbstract) + continue; + + ICommand cmd = (ICommand)Activator.CreateInstance(type); + + if (cmd != null) + { + //Fail safe measures. Ensure that we always have a name assigned to the commands. + if ((cmd.Name == "") || (cmd.Name == null)) + cmd.Name = cmd.GetType().Name.ToLower(); + else + cmd.Name = cmd.Name.ToLower(); //Commands are always stored in lower case. + + if (Commands.ContainsKey(cmd.Name)) + continue; //No overriding supported. Skip this command. + + //Everything checks out ok. Add the command to our collection. + Commands.Add(cmd.Name, cmd); + } + } + } + + public static void PurgeCommands() + { + Commands.Clear(); + } + } +} diff --git a/MudEngine/WinPC_Engine/Core/Interfaces/ICommand.cs b/MudEngine/WinPC_Engine/Core/Interfaces/ICommand.cs new file mode 100644 index 0000000..866fe55 --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/Interfaces/ICommand.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using MudEngine.Game.Characters; + +namespace MudEngine.Core.Interface +{ + public interface ICommand + { + string Name { get; set; } + string Description { get; set; } + List Help { get; set; } + + void Execute(string command, StandardCharacter character); + } +} diff --git a/MudEngine/WinPC_Engine/Core/Interfaces/IGameComponent.cs b/MudEngine/WinPC_Engine/Core/Interfaces/IGameComponent.cs new file mode 100644 index 0000000..8c61b7b --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/Interfaces/IGameComponent.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.Core.Interfaces +{ + /// + /// Provides an API for scripts that need to be Initialized and Destroyed during gameplay. + /// + public interface IGameComponent + { + /// + /// Method for initializing any code that must be executed prior to anything else. + /// + void Initialize(); + + /// + /// Method for destroying any resources that the class might be using. + /// + void Destroy(); + } +} diff --git a/MudEngine/WinPC_Engine/Core/Interfaces/INetworked.cs b/MudEngine/WinPC_Engine/Core/Interfaces/INetworked.cs new file mode 100644 index 0000000..a883960 --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/Interfaces/INetworked.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.Core.Interfaces +{ + /// + /// Public API for scripts that take advantage of the engines Networking + /// + public interface INetworked + { + /// + /// Method used for sending messages from the server to the object. + /// + /// + void SendMessage(String message); + + /// + /// Method for disconnecting the object from the server. + /// + void Disconnect(); + + /// + /// Method for connecting a object to the server. + /// + void Connect(); + } +} diff --git a/MudEngine/WinPC_Engine/Core/Interfaces/ISavable.cs b/MudEngine/WinPC_Engine/Core/Interfaces/ISavable.cs new file mode 100644 index 0000000..fce1efd --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/Interfaces/ISavable.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.Core.Interfaces +{ + /// + /// Public API for classes that need to be saved during runtime. + /// + public interface ISavable + { + /// + /// Objects filename. + /// + String Filename { get; set; } + + /// + /// Save method for dumping the object to physical file. + /// + /// + void Save(String path); + + /// + /// Load method for retrieving saved data from file. + /// + /// Filename is required complete with Path since this object does not exist yet (can not get filename from non-existing object) + void Load(String filename); + } +} diff --git a/MudEngine/WinPC_Engine/Core/Interfaces/IUpdatable.cs b/MudEngine/WinPC_Engine/Core/Interfaces/IUpdatable.cs new file mode 100644 index 0000000..7b52ce7 --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/Interfaces/IUpdatable.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.Core.Interfaces +{ + /// + /// Public API for classes that need to be updated constantly. + /// + public interface IUpdatable + { + void Update(); + } +} diff --git a/MudEngine/WinPC_Engine/Core/Logger.cs b/MudEngine/WinPC_Engine/Core/Logger.cs new file mode 100644 index 0000000..5df69f1 --- /dev/null +++ b/MudEngine/WinPC_Engine/Core/Logger.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Text; + +namespace MudEngine.Core +{ + /// + /// Public Engine Logging Class. + /// + public static class Logger + { + /// + /// The Log Filename for the engine log. + /// + public static string LogFilename { get; set; } + + /// + /// Gets or Sets if the Logger is enabled or disabled. + /// + public static Boolean Enabled { get; set; } + + /// + /// Gets or Sets if the logger will output it's information to the Console. + /// + public static Boolean ConsoleOutPut { get; set; } + + /// + /// Clears the queued log messages from cache + /// + public static void ClearLog() + { + //If the log file exists, delete it. + if (String.IsNullOrEmpty(LogFilename)) + LogFilename = "Engine.Log"; + + if (System.IO.File.Exists(LogFilename)) + System.IO.File.Delete(LogFilename); + + //Clear the cache. + _Messages.Clear(); + } + + /// + /// Writes a single line to the engine log file. + /// + /// + public static void WriteLine(String message) + { + //Only write to log if enabled. + if (!Enabled) + return; + + //Make sure we have a valid filename + if (String.IsNullOrEmpty(LogFilename)) + LogFilename = "Engine.Log"; + + //Ensure that the log messages cache is not null + if (_Messages == null) + _Messages = new List(); + + //Get the current time and format it + String Time = DateTime.Now.ToString("h:mm:ss:ff tt"); + + //Output to console if enabled. + if (ConsoleOutPut) + Console.WriteLine(Time + ": " + message); + + //Try to write the message to the log file. + try + { + using (System.IO.StreamWriter file = new System.IO.StreamWriter(LogFilename, true)) + { + //Write the message to file + file.WriteLine(Time + ": " + message); + //Add it to the messages cache. + _Messages.Add(Time + ": " + message); + } + } + catch + { + throw new Exception("Unable to write message (" + message + ") to log file (" + LogFilename + ")."); + } + } + + /// + /// Returns an array of messages that have been queued in the log cache. + /// + /// + public static String[] GetMessages() + { + if (_Messages == null) + return new string[0]; + else + return _Messages.ToArray(); + } + + private static List _Messages; + } +} diff --git a/MudEngine/WinPC_Engine/DAL/DataPaths.cs b/MudEngine/WinPC_Engine/DAL/DataPaths.cs new file mode 100644 index 0000000..18d4ea2 --- /dev/null +++ b/MudEngine/WinPC_Engine/DAL/DataPaths.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.DAL +{ + /// + /// Contains the paths for the engines file storage. + /// + public struct DataPaths + { + /// + /// Path to the engines Script directory + /// + public String Scripts { get; set; } + + /// + /// Path to the engines Environment files. + /// + public String Environments { get; set; } + + /// + /// Path to the engines saved objects (Equipment etc). + /// + public String Objects { get; set; } + } +} diff --git a/MudEngine/WinPC_Engine/DAL/XmlParser.cs b/MudEngine/WinPC_Engine/DAL/XmlParser.cs new file mode 100644 index 0000000..4e18fb0 --- /dev/null +++ b/MudEngine/WinPC_Engine/DAL/XmlParser.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.DAL +{ + public class XmlParser + { + + } +} diff --git a/MudEngine/WinPC_Engine/Game/Characters/CharacterRoles.cs b/MudEngine/WinPC_Engine/Game/Characters/CharacterRoles.cs new file mode 100644 index 0000000..08c9fdd --- /dev/null +++ b/MudEngine/WinPC_Engine/Game/Characters/CharacterRoles.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.Game.Characters +{ + /// + /// Various server roles that a character can have. + /// + public enum CharacterRoles + { + Admin, + Immortal, + GM, + QuestGiver, + Player, + NPC + } +} diff --git a/MudEngine/WinPC_Engine/Game/Characters/CharacterStats.cs b/MudEngine/WinPC_Engine/Game/Characters/CharacterStats.cs new file mode 100644 index 0000000..d93c66f --- /dev/null +++ b/MudEngine/WinPC_Engine/Game/Characters/CharacterStats.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MudEngine.Game.Characters +{ + /// + /// Stats that are used by the Character + /// + public struct CharacterStats + { + public int Strength { get; set; } + public int Dexterity { get; set; } + public int Constitution { get; set; } + public int Intelligence { get; set; } + public int Wisdom { get; set; } + public int Charisma { get; set; } + public int Experience { get; set; } + } +} diff --git a/MudEngine/WinPC_Engine/Game/Characters/StandardCharacter.cs b/MudEngine/WinPC_Engine/Game/Characters/StandardCharacter.cs new file mode 100644 index 0000000..1ddf003 --- /dev/null +++ b/MudEngine/WinPC_Engine/Game/Characters/StandardCharacter.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +using MudEngine.GameScripts; +using MudEngine.Core.Interfaces; +using MudEngine.Networking; +using MudEngine.Core; + +namespace MudEngine.Game.Characters +{ + /// + /// Standard Character class used by all character based objects + /// + public class StandardCharacter : BaseScript, INetworked, ISavable, IUpdatable, IGameComponent + { + /// + /// Gets a reference to the currently active game. + /// + public StandardGame Game { get; private set; } + + /// + /// Gets what this Characters role on the server is. + /// + public CharacterRoles Role { get; protected set; } + + /// + /// Gets what this characters stats are. + /// + public CharacterStats Stats { get; protected set; } + + //TODO: Should be Private/Protected? + public String Password { get; set; } + + /// + /// Flags this object as non-movable in the world. + /// + public Boolean Immovable { get; set; } + + //TODO: Add current location to characters + //public IEnvironment CurrentLocation + + protected CommandSystem Commands { get; private set; } + + public StandardCharacter(String name, String description, StandardGame game) : base(name, description) + { + this.Game = game; + + //Instance this Characters personal Command System with a copy of the command + //collection already loaded and prepared by the Active Game. + this.Commands = new CommandSystem(CommandSystem.Commands); + + this.OnConnectEvent += new OnConnectHandler(OnConnect); + } + + public StandardCharacter(String name, String description, StandardGame game, Socket connection) : this(name, description, game) + { + this._Connection = connection; + + this._Reader = new StreamReader(new NetworkStream(this._Connection, false)); + this._Writer = new StreamWriter(new NetworkStream(this._Connection, true)); + + this._Writer.AutoFlush = true; //Flushes the stream automatically. + this._InitialMessage = true; //Strips Telnet client garbage text from initial message sent from client. + } + + internal void ExecuteCommand(string command) + { + //Process commands here. + if (this._InitialMessage) + { + command = this.CleanString(command); + this._InitialMessage = false; + } + + this.Commands.Execute(command, this); + } + + public void SendMessage(string message) + { + lock (this) + { + _Writer.WriteLine(message); + } + } + + public void Disconnect() + { + Console.WriteLine("Disconnecting..."); + + //Close our currently open socket. + this._Connection.Close(); + + //Remove this character from the Connection Manager + ConnectionManager.RemoveConnection(this); + Console.WriteLine("Disconnect Complete."); + + //Stop the Update() thread. + this._LoopThread.Abort(); + } + + public void Connect() + { + _LoopThread = new Thread(Update); + _LoopThread.Start(); + + this.SendMessage(""); + OnConnectEvent(); + } + + public void Update() + { + try + { + while (this.Game.Enabled) + { + _Writer.Flush(); + String line = _Reader.ReadLine(); + ExecuteCommand(line); + } + } + catch + { + } + finally + { + this.Disconnect(); + } + } + + String CleanString(string line) + { + if ((!String.IsNullOrEmpty(line)) && (line.Length > 0)) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(line.Length); + foreach (char c in line) + { + if (char.IsSymbol(c)) continue; + + sb.Append(char.IsControl(c) ? ' ' : c); + } + String newLine = sb.ToString().Trim().Substring(2).Trim(); + return newLine; + } + else + return String.Empty; + } + + public delegate void OnConnectHandler(); + public event OnConnectHandler OnConnectEvent; + public void OnConnect() + { + _Writer.WriteLine(this.Game.Server.MOTD); + } + + private Socket _Connection; + private Thread _LoopThread; + private StreamReader _Reader; + private StreamWriter _Writer; + private Boolean _InitialMessage; + + public string Filename + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void Save(string path) + { + throw new NotImplementedException(); + } + + public void Load(string filename) + { + throw new NotImplementedException(); + } + + public void Initialize() + { + throw new NotImplementedException(); + } + + public void Destroy() + { + throw new NotImplementedException(); + } + } +} diff --git a/MudEngine/WinPC_Engine/Game/Environment/TravelDirections.cs b/MudEngine/WinPC_Engine/Game/Environment/TravelDirections.cs new file mode 100644 index 0000000..4cfb3c7 --- /dev/null +++ b/MudEngine/WinPC_Engine/Game/Environment/TravelDirections.cs @@ -0,0 +1,83 @@ +using System; + +namespace MudEngine.Game.Environment +{ + //Available directions that the character can travel in the world. + [System.Flags] + public enum AvailableTravelDirections : uint + { + None = 0, + North = 1, + South = 2, + East = 4, + West = 8, + Up = 16, + Down = 32, + Northeast = North | East, + Northwest = North | West, + Southeast = South | East, + Southwest = South | West + } + + public static class TravelDirections + { + /// + /// Returns a direction that is reversed from what was supplied. + /// + /// + /// + public static AvailableTravelDirections GetReverseDirection(AvailableTravelDirections Direction) + { + switch (Direction) + { + case AvailableTravelDirections.North: + return AvailableTravelDirections.South; + case AvailableTravelDirections.South: + return AvailableTravelDirections.North; + case AvailableTravelDirections.East: + return AvailableTravelDirections.West; + case AvailableTravelDirections.West: + return AvailableTravelDirections.East; + case AvailableTravelDirections.Up: + return AvailableTravelDirections.Down; + case AvailableTravelDirections.Down: + return AvailableTravelDirections.Up; + case AvailableTravelDirections.Northeast: + return AvailableTravelDirections.Southwest; + case AvailableTravelDirections.Southwest: + return AvailableTravelDirections.Northeast; + case AvailableTravelDirections.Northwest: + return AvailableTravelDirections.Southeast; + case AvailableTravelDirections.Southeast: + return AvailableTravelDirections.Northwest; + default: + return AvailableTravelDirections.None; + } + } + + /// + /// Returns a enum value that matches that of the string supplied. + /// + /// + /// + public static AvailableTravelDirections GetTravelDirectionValue(String Direction) + { + //Blow all of the available values up into an array. + Array values = Enum.GetValues(typeof(AvailableTravelDirections)); + + //Loop through each available value, converting it into a string. + foreach (Int32 value in values) + { + //Get the string representation of the current value + String displayName = Enum.GetName(typeof(AvailableTravelDirections), value); + + //Check if this value matches that of the supplied one. + //If so, return it as a enum + if (displayName.ToLower() == Direction.ToLower()) + return (AvailableTravelDirections)Enum.Parse(typeof(AvailableTravelDirections), displayName); + } + + return AvailableTravelDirections.None; + } + } +} \ No newline at end of file diff --git a/MudEngine/WinPC_Engine/Game/StandardGame.cs b/MudEngine/WinPC_Engine/Game/StandardGame.cs new file mode 100644 index 0000000..d2d681a --- /dev/null +++ b/MudEngine/WinPC_Engine/Game/StandardGame.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; + +using MudEngine.Networking; +using MudEngine.Core; + +namespace MudEngine.Game +{ + public class StandardGame + { + public String Name { get; set; } + + public String Website { get; set; } + + public String Description { get; set; } + + public String Version { get; set; } + + public Boolean HiddenRoomNames { get; set; } + + public Boolean Multiplayer { get; set; } + + public Int32 MaximumPlayers { get; set; } + + public Int32 MaxQueueSize { get; set; } + + public Int32 MinimumPasswordSize { get; set; } + + public Boolean AutoSave { get; set; } + + public Boolean Enabled { get; private set; } + + public Boolean Debugging { get; set; } + + public Server Server { get; protected set; } + + public StandardGame(String name) : this(name, 4000) + { + } + + public StandardGame(String name, Int32 port) + { + Logger.WriteLine("Initializing Standard Mud Game"); + this.Name = name; + this.Website = "http://scionwest.net"; + this.Description = "A sample Mud game created using the Mud Designer kit."; + this.Version = "1.0"; + this.Multiplayer = true; + this.MaximumPlayers = 50; + this.MinimumPasswordSize = 8; + this.MaxQueueSize = 20; + this.AutoSave = true; + + //Setup our server. + this.Server = new Server(port); + + this.Server.Port = port; + } + + public Boolean Start() + { + Logger.WriteLine("Starting up Standard Game"); + + //Instance Script Engine + + //Compile any scripts + + //Load our Commands + CommandSystem.LoadCommands(); + + //Load World + + //Start our server. + this.Server.Start(this); + + //If the server started without error, flag the Game as enabled. + if (this.Server.Enabled) + this.Enabled = true; + + return this.Enabled; + } + + public void Stop() + { + //Save the world. + + this.Server.Stop(); + + this.Enabled = false; + } + } +} diff --git a/MudEngine/WinPC_Engine/GameScripts/BaseScript.cs b/MudEngine/WinPC_Engine/GameScripts/BaseScript.cs new file mode 100644 index 0000000..3f59904 --- /dev/null +++ b/MudEngine/WinPC_Engine/GameScripts/BaseScript.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; + +namespace MudEngine.GameScripts +{ + public class BaseScript + { + public String Name { get; set; } + + public String ID { get; set; } + + public String Description { get; set; } + + public BaseScript(String name, String description) + { + this.ID = Guid.NewGuid().ToString(); + } + + public override string ToString() + { + if (String.IsNullOrEmpty(this.Name)) + return this.GetType().Name + " without Name"; + else + return this.Name; + } + } +} diff --git a/MudEngine/WinPC_Engine/GameScripts/Commands/CommandSay.cs b/MudEngine/WinPC_Engine/GameScripts/Commands/CommandSay.cs new file mode 100644 index 0000000..cd38bf2 --- /dev/null +++ b/MudEngine/WinPC_Engine/GameScripts/Commands/CommandSay.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using MudEngine.Core.Interface; +using MudEngine.Game; +using MudEngine.Game.Characters; +using MudEngine.Networking; + +namespace MudEngine.GameScripts.Commands +{ + public class CommandSay : ICommand + { + public string Name { get; set; } + + public string Description { get; set; } + + public List Help { get; set; } + + public CommandSay() + { + this.Name = "Say"; + this.Description = "Chat command that allows objects to communicate."; + } + + public void Execute(string command, StandardCharacter character) + { + //Grab a reference to the character for simplifying access. + StandardGame game = character.Game; + //Remove the command "Say " from the string so we only have it's message + String message = command.Substring(3).Trim(); + + //Loop through each character on the server and broadcast the message. + //TODO: This should only broadcast to characters that are in the same Environment. + foreach (StandardCharacter c in ConnectionManager.Connections) + { + //Only broadcast this message to those that are not the broadcastor. + if (c != character) + c.SendMessage(character.ToString() + " says: " + message); + } + + //Send a different copy of the message to the broadcastor. + character.SendMessage("You say: " + message); + } + } +} diff --git a/MudEngine/WinPC_Engine/Networking/ConnectionManager.cs b/MudEngine/WinPC_Engine/Networking/ConnectionManager.cs new file mode 100644 index 0000000..a923c23 --- /dev/null +++ b/MudEngine/WinPC_Engine/Networking/ConnectionManager.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +using MudEngine.Game; +using MudEngine.Game.Characters; + +namespace MudEngine.Networking +{ + public static class ConnectionManager + { + //Collection of currently connected players. + public static List Connections { get; set; } + + /// + /// Creates a new character for the player and sets it up on the server. + /// + /// + /// + public static void AddConnection(StandardGame game, Socket connection) + { + //Exception checking. + if (Connections == null) + Connections = new List(); + + //Instance a new character and provide it with the Socket. + StandardCharacter character = new StandardCharacter("New Player", "New networked client.", game, connection); + + //Add it to the Connections collection + Connections.Add(character); + + //Invoke the Characters Server connection method + character.Connect(); + } + + /// + /// Removes the specified player character from the server. + /// + /// + public static void RemoveConnection(StandardCharacter character) + { + Connections.Remove(character); + } + + /// + /// Disconnects all of the currently connected clients. + /// + public static void DisconnectAll() + { + if (Connections == null) + return; + + foreach (StandardCharacter character in Connections) + { + character.Disconnect(); + } + Connections.Clear(); + } + } +} diff --git a/MudEngine/WinPC_Engine/Networking/Server.cs b/MudEngine/WinPC_Engine/Networking/Server.cs new file mode 100644 index 0000000..69ff723 --- /dev/null +++ b/MudEngine/WinPC_Engine/Networking/Server.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +using MudEngine.Core; +using MudEngine.Core.Interfaces; +using MudEngine.Game; +using MudEngine.Game.Characters; + +namespace MudEngine.Networking +{ + [Category("Networking")] + public class Server + { + [Category("Networking")] + [Description("The name of this server")] + public String Name { get; set; } + + [Category("Networking")] + public Int32 Port { get; set; } + + [Category("Networking")] + [Description("The Message Of The Day that is presented to users when they connect.")] + public String MOTD { get; set; } + + [Category("Networking")] + [Description("Maximum number of people that can connect and play on this server at any time.")] + public Int32 MaxConnections { get; set; } + + [Category("Networking")] + [Description("Maximum number of poeple that can be queued for connection.")] + public Int32 QueuedConnectionLimit { get; set; } + + [Browsable(false)] + public Boolean Enabled { get; private set; } + + /// + /// Sets up a server on the specified port. + /// + /// + /// + public Server(Int32 port) + { + Logger.WriteLine("Initializing Mud Server Settings"); + this.Port = port; + this.MaxConnections = 50; + this.QueuedConnectionLimit = 20; + this.Name = "New Server"; + this.MOTD = "Welcome to a sample Mud Engine game server!"; + + this._Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + this._Server.Bind(new IPEndPoint(IPAddress.Any, this.Port)); + } + + /// + /// Starts the game server. It will listen on a different thread of incoming connections + /// + public void Start(StandardGame game) + { + //Start the server. + Logger.WriteLine("Starting Mud Server."); + + //Start listening for connections + this._Server.Listen(this.QueuedConnectionLimit); + + //Launch the new connections listener on a new thread. + this._ConnectionPool = new Thread(AcceptConnection); + this._ConnectionPool.Start(); + + //Flag the server as enabled. + this.Enabled = true; + + //Save a reference to the currently active game + this._Game = game; + + Logger.WriteLine("Server started."); + } + + public void Stop() + { + //Flag the server as disabled. + this.Enabled = false; + + //Stop the thread from listening for accepting new conections + this._ConnectionPool.Abort(); + + //Disconnect all of the currently connected clients. + ConnectionManager.DisconnectAll(); + + //Stop the server. + this._Server.Close(); + } + + private void AcceptConnection() + { + //While the server is enabled, constantly check for new connections. + while (this.Enabled) + { + //Grab the new connection. + Socket incomingConnection = this._Server.Accept(); + + //Send it to the Connection Manager so a Character can be instanced. + ConnectionManager.AddConnection(this._Game, incomingConnection); + } + } + + private Socket _Server; + private Thread _ConnectionPool; + private StandardGame _Game; + } +} diff --git a/MudEngine/WinPC_Engine/Properties/AssemblyInfo.cs b/MudEngine/WinPC_Engine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b992c9d --- /dev/null +++ b/MudEngine/WinPC_Engine/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WinPC_Engine")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WinPC_Engine")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8a61b00d-f6fb-4bdf-9253-531039ada2cb")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MudEngine/WinPC_Engine/WinPC_Engine.csproj b/MudEngine/WinPC_Engine/WinPC_Engine.csproj new file mode 100644 index 0000000..5b9e4a7 --- /dev/null +++ b/MudEngine/WinPC_Engine/WinPC_Engine.csproj @@ -0,0 +1,80 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {27C84625-1D4A-4DBF-9770-46D535506485} + Library + Properties + MudEngine + MudEnginePC + v4.0 + 512 + SAK + SAK + SAK + SAK + + + true + full + false + bin\Debug\ + TRACE;DEBUG;WINDOWS_PC + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MudEngine/WinPC_Engine/WinPC_Engine.csproj.vspscc b/MudEngine/WinPC_Engine/WinPC_Engine.csproj.vspscc new file mode 100644 index 0000000..feffdec --- /dev/null +++ b/MudEngine/WinPC_Engine/WinPC_Engine.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/MudEngine/WinPC_Server/Program.cs b/MudEngine/WinPC_Server/Program.cs new file mode 100644 index 0000000..866e429 --- /dev/null +++ b/MudEngine/WinPC_Server/Program.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +using MudEngine.Game; +using MudEngine.Core; + +namespace SimpleMUD +{ + public class ServerInput + { + public String Message; + + public ServerInput() + { + Message = String.Empty; + } + + public void GetInput() + { + while (true) + { + Console.WriteLine("Enter a test message: "); + Message = Console.ReadLine(); + } + } + } + + class Program + { + static void Main(string[] args) + { + Logger.LogFilename = "StandardGame.Log"; + Logger.Enabled = true; + Logger.ConsoleOutPut = true; + + StandardGame game = new StandardGame("Sample Game"); + game.Start(); + + Boolean msgReturn = false; + ServerInput input = new ServerInput(); + + Thread inputThread = new Thread(input.GetInput); + inputThread.Start(); + + while (game.Enabled) + { + if (input.Message.Equals("exit")) + { + game.Stop(); + } + else if (input.Message.Equals("test") && (msgReturn == false)) + { + Console.WriteLine("Message Works"); + input.Message = String.Empty; + } + } + + inputThread.Abort(); + } + } +} \ No newline at end of file diff --git a/MudEngine/WinPC_Server/Properties/AssemblyInfo.cs b/MudEngine/WinPC_Server/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..54fd0f8 --- /dev/null +++ b/MudEngine/WinPC_Server/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WinPC_Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WinPC_Server")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a627d239-f19d-4b18-8779-b7312aeb68b3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MudEngine/WinPC_Server/WinPC_Server.csproj b/MudEngine/WinPC_Server/WinPC_Server.csproj new file mode 100644 index 0000000..5c46f98 --- /dev/null +++ b/MudEngine/WinPC_Server/WinPC_Server.csproj @@ -0,0 +1,69 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1} + Exe + Properties + WinPC_Server + WinPC_Server + v4.0 + Client + 512 + SAK + SAK + SAK + SAK + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + {27C84625-1D4A-4DBF-9770-46D535506485} + WinPC_Engine + + + + + \ No newline at end of file diff --git a/MudEngine/WinPC_Server/WinPC_Server.csproj.vspscc b/MudEngine/WinPC_Server/WinPC_Server.csproj.vspscc new file mode 100644 index 0000000..feffdec --- /dev/null +++ b/MudEngine/WinPC_Server/WinPC_Server.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +}