Initial Check-in for Alpha 2.0 source code.

Includes working Telnet server, working command engine and Character code.
This commit is contained in:
Scionwest_cp 2012-02-28 20:11:10 -08:00
parent 224f754514
commit 3d8051c995
28 changed files with 1495 additions and 0 deletions

54
MudEngine/MudEngine.sln Normal file
View file

@ -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

View file

@ -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"
}

View file

@ -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
{
/// <summary>
/// Gets or Sets a collection of help topics related to this command.
/// </summary>
[Browsable(false)]
public List<string> Help { get; set; }
public BaseCommand()
{
Help = new List<string>();
this.Name = this.GetType().Name.Substring("Command".Length);
}
/// <summary>
/// Executes the command for the character supplied.
/// </summary>
/// <param name="command"></param>
/// <param name="character"></param>
public abstract void Execute(string command, StandardCharacter character);
public string Name {get;set;}
public string Description
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
}

View file

@ -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<string, ICommand> Commands
{
get
{
if (_Commands == null)
_Commands = new Dictionary<string, ICommand>();
return _Commands;
}
private set
{
_Commands = value;
}
}
private static Dictionary<String, ICommand> _Commands;
public Dictionary<String, ICommand> CommandCollection { get; private set; }
public CommandSystem(Dictionary<String, ICommand> commands)
{
this.CommandCollection = new Dictionary<string, ICommand>();
this.CommandCollection = commands;
//Handled by the StandardGame class now.
//LoadCommands();
}
public List<ICommand> GetCommands()
{
List<ICommand> collection = new List<ICommand>();
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();
}
}
}

View file

@ -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<string> Help { get; set; }
void Execute(string command, StandardCharacter character);
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.Core.Interfaces
{
/// <summary>
/// Provides an API for scripts that need to be Initialized and Destroyed during gameplay.
/// </summary>
public interface IGameComponent
{
/// <summary>
/// Method for initializing any code that must be executed prior to anything else.
/// </summary>
void Initialize();
/// <summary>
/// Method for destroying any resources that the class might be using.
/// </summary>
void Destroy();
}
}

View file

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.Core.Interfaces
{
/// <summary>
/// Public API for scripts that take advantage of the engines Networking
/// </summary>
public interface INetworked
{
/// <summary>
/// Method used for sending messages from the server to the object.
/// </summary>
/// <param name="message"></param>
void SendMessage(String message);
/// <summary>
/// Method for disconnecting the object from the server.
/// </summary>
void Disconnect();
/// <summary>
/// Method for connecting a object to the server.
/// </summary>
void Connect();
}
}

View file

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.Core.Interfaces
{
/// <summary>
/// Public API for classes that need to be saved during runtime.
/// </summary>
public interface ISavable
{
/// <summary>
/// Objects filename.
/// </summary>
String Filename { get; set; }
/// <summary>
/// Save method for dumping the object to physical file.
/// </summary>
/// <param name="path"></param>
void Save(String path);
/// <summary>
/// Load method for retrieving saved data from file.
/// </summary>
/// <param name="filename">Filename is required complete with Path since this object does not exist yet (can not get filename from non-existing object)</param>
void Load(String filename);
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.Core.Interfaces
{
/// <summary>
/// Public API for classes that need to be updated constantly.
/// </summary>
public interface IUpdatable
{
void Update();
}
}

View file

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text;
namespace MudEngine.Core
{
/// <summary>
/// Public Engine Logging Class.
/// </summary>
public static class Logger
{
/// <summary>
/// The Log Filename for the engine log.
/// </summary>
public static string LogFilename { get; set; }
/// <summary>
/// Gets or Sets if the Logger is enabled or disabled.
/// </summary>
public static Boolean Enabled { get; set; }
/// <summary>
/// Gets or Sets if the logger will output it's information to the Console.
/// </summary>
public static Boolean ConsoleOutPut { get; set; }
/// <summary>
/// Clears the queued log messages from cache
/// </summary>
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();
}
/// <summary>
/// Writes a single line to the engine log file.
/// </summary>
/// <param name="message"></param>
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<string>();
//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 + ").");
}
}
/// <summary>
/// Returns an array of messages that have been queued in the log cache.
/// </summary>
/// <returns></returns>
public static String[] GetMessages()
{
if (_Messages == null)
return new string[0];
else
return _Messages.ToArray();
}
private static List<String> _Messages;
}
}

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.DAL
{
/// <summary>
/// Contains the paths for the engines file storage.
/// </summary>
public struct DataPaths
{
/// <summary>
/// Path to the engines Script directory
/// </summary>
public String Scripts { get; set; }
/// <summary>
/// Path to the engines Environment files.
/// </summary>
public String Environments { get; set; }
/// <summary>
/// Path to the engines saved objects (Equipment etc).
/// </summary>
public String Objects { get; set; }
}
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.DAL
{
public class XmlParser
{
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.Game.Characters
{
/// <summary>
/// Various server roles that a character can have.
/// </summary>
public enum CharacterRoles
{
Admin,
Immortal,
GM,
QuestGiver,
Player,
NPC
}
}

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.Game.Characters
{
/// <summary>
/// Stats that are used by the Character
/// </summary>
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; }
}
}

View file

@ -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
{
/// <summary>
/// Standard Character class used by all character based objects
/// </summary>
public class StandardCharacter : BaseScript, INetworked, ISavable, IUpdatable, IGameComponent
{
/// <summary>
/// Gets a reference to the currently active game.
/// </summary>
public StandardGame Game { get; private set; }
/// <summary>
/// Gets what this Characters role on the server is.
/// </summary>
public CharacterRoles Role { get; protected set; }
/// <summary>
/// Gets what this characters stats are.
/// </summary>
public CharacterStats Stats { get; protected set; }
//TODO: Should be Private/Protected?
public String Password { get; set; }
/// <summary>
/// Flags this object as non-movable in the world.
/// </summary>
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();
}
}
}

View file

@ -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
{
/// <summary>
/// Returns a direction that is reversed from what was supplied.
/// </summary>
/// <param name="Direction"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// Returns a enum value that matches that of the string supplied.
/// </summary>
/// <param name="Direction"></param>
/// <returns></returns>
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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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<string> 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);
}
}
}

View file

@ -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<StandardCharacter> Connections { get; set; }
/// <summary>
/// Creates a new character for the player and sets it up on the server.
/// </summary>
/// <param name="game"></param>
/// <param name="connection"></param>
public static void AddConnection(StandardGame game, Socket connection)
{
//Exception checking.
if (Connections == null)
Connections = new List<StandardCharacter>();
//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();
}
/// <summary>
/// Removes the specified player character from the server.
/// </summary>
/// <param name="character"></param>
public static void RemoveConnection(StandardCharacter character)
{
Connections.Remove(character);
}
/// <summary>
/// Disconnects all of the currently connected clients.
/// </summary>
public static void DisconnectAll()
{
if (Connections == null)
return;
foreach (StandardCharacter character in Connections)
{
character.Disconnect();
}
Connections.Clear();
}
}
}

View file

@ -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; }
/// <summary>
/// Sets up a server on the specified port.
/// </summary>
/// <param name="port"></param>
/// <param name="maxConnections"></param>
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));
}
/// <summary>
/// Starts the game server. It will listen on a different thread of incoming connections
/// </summary>
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;
}
}

View file

@ -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")]

View file

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{27C84625-1D4A-4DBF-9770-46D535506485}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MudEngine</RootNamespace>
<AssemblyName>MudEnginePC</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;WINDOWS_PC</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Core\BaseCommand.cs" />
<Compile Include="Core\CommandSystem.cs" />
<Compile Include="Core\Interfaces\ICommand.cs" />
<Compile Include="Core\Interfaces\IGameComponent.cs" />
<Compile Include="Core\Interfaces\INetworked.cs" />
<Compile Include="Core\Interfaces\ISavable.cs" />
<Compile Include="Core\Interfaces\IUpdatable.cs" />
<Compile Include="Core\Logger.cs" />
<Compile Include="DAL\DataPaths.cs" />
<Compile Include="DAL\XmlParser.cs" />
<Compile Include="GameScripts\Commands\CommandSay.cs" />
<Compile Include="Game\Characters\CharacterRoles.cs" />
<Compile Include="Game\Characters\CharacterStats.cs" />
<Compile Include="Game\Characters\StandardCharacter.cs" />
<Compile Include="GameScripts\BaseScript.cs" />
<Compile Include="Game\StandardGame.cs" />
<Compile Include="Game\Environment\TravelDirections.cs" />
<Compile Include="Networking\ConnectionManager.cs" />
<Compile Include="Networking\Server.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Game\Objects\" />
<Folder Include="Scripting\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -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"
}

View file

@ -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();
}
}
}

View file

@ -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")]

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{9F118DC3-CB8E-45FB-ABA5-10D50A6CD3F1}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WinPC_Server</RootNamespace>
<AssemblyName>WinPC_Server</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WinPC_Engine\WinPC_Engine.csproj">
<Project>{27C84625-1D4A-4DBF-9770-46D535506485}</Project>
<Name>WinPC_Engine</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -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"
}