* StandardCharacter now automatically invokes the Login command upon connection to the server. Login command not implemented completely yet.

* Telnet client header information is now successfully (finally) stripped out of the first stream received.
* Command System underwent some optimizations along with now always returning a Boolean value once execution of a command is completed.
* ICommand interface now forces all ICommand.Execute methods to return a Boolean value.
* DataPaths class re-wrote and is now simi in-use by StandardGame and the Login command
* Minor adjustments to how characters are initialized upon connection in various classes.
This commit is contained in:
Scionwest_cp 2012-03-03 20:57:47 -08:00
parent 0720393626
commit ec5a674062
10 changed files with 185 additions and 74 deletions

View file

@ -58,12 +58,7 @@ namespace MudEngine.Core
/// <returns></returns> /// <returns></returns>
public List<ICommand> GetCommands() public List<ICommand> GetCommands()
{ {
List<ICommand> collection = new List<ICommand>(); return CommandSystem.Commands.Values.ToList();
foreach (ICommand c in CommandSystem.Commands.Values)
collection.Add(c);
return collection;
} }
/// <summary> /// <summary>
@ -101,7 +96,7 @@ namespace MudEngine.Core
/// </summary> /// </summary>
/// <param name="command"></param> /// <param name="command"></param>
/// <param name="character"></param> /// <param name="character"></param>
public void Execute(string command, StandardCharacter character) public Boolean Execute(string command, StandardCharacter character)
{ {
//All Types that implement ICommand must have their class name begin with Command. //All Types that implement ICommand must have their class name begin with Command.
//We must insert the 'Command' string into the beginning of the users Command //We must insert the 'Command' string into the beginning of the users Command
@ -119,20 +114,20 @@ namespace MudEngine.Core
try try
{ {
//Execute the command //Execute the command
cmd.Execute(command, character); return cmd.Execute(command, character);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.WriteLine("Error: " + ex.Message); Logger.WriteLine("Error: " + ex.Message);
Console.WriteLine("Error: " + ex.Message); Console.WriteLine("Error: " + ex.Message);
} }
return;
} }
} }
//Let the player know that it was not a valid command. //Let the player know that it was not a valid command.
//TODO: Implement another way of performing this. I don't want game related classes tied to the system.
character.SendMessage("Invalid Command Used."); character.SendMessage("Invalid Command Used.");
return false;
} }
/// <summary> /// <summary>

View file

@ -13,6 +13,6 @@ namespace MudEngine.Core.Interface
string Description { get; set; } string Description { get; set; }
List<string> Help { get; set; } List<string> Help { get; set; }
void Execute(string command, StandardCharacter character); Boolean Execute(string command, StandardCharacter character);
} }
} }

View file

@ -2,32 +2,62 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Reflection;
using System.IO;
namespace MudEngine.DAL namespace MudEngine.DAL
{ {
public enum DataTypes
{
Players,
Environments,
Characters,
Equipment
}
/// <summary> /// <summary>
/// Contains the paths for the engines file storage. /// Contains the paths for the engines file storage.
/// </summary> /// </summary>
public struct DataPaths public class DataPaths
{ {
/// <summary> public DataPaths()
/// Path to the engines Script directory {
/// </summary> String path = Assembly.GetExecutingAssembly().Location;
public String Scripts { get; set; } String assemblyFile = Path.GetFileName(path);
this._InstallRoot = path.Substring(0, path.Length - assemblyFile.Length);
/// <summary> this.SetAbsolutePath(Path.Combine(this._InstallRoot, "Players"), DataTypes.Players);
/// Path to the engines Environment files. }
/// </summary>
public String Environments { get; set; }
/// <summary> public void SetAbsolutePath(String path, DataTypes objectType)
/// Gets the Path to the Characters save directory {
/// </summary> if (!path.EndsWith(@"\"))
public String Characters { get; set; } path = path.Insert(path.Length, @"\");
/// <summary> switch (objectType)
/// Gets the path to the saved players directory. {
/// </summary> case DataTypes.Players:
public String Players { get; set; } this._Players = path;
break;
}
}
public void SetRelativePath(String path, DataTypes objectType)
{
}
public String GetPath(DataTypes objectType)
{
if (objectType == DataTypes.Players)
return this._Players;
else
return String.Empty;
}
private String _InstallRoot;
private String _Players;
private String _Environments;
private String _Characters;
private String _Equipment;
} }
} }

View file

@ -46,8 +46,28 @@ namespace MudEngine.Game.Characters
/// </summary> /// </summary>
public Boolean Immovable { get; set; } public Boolean Immovable { get; set; }
/// <summary>
/// Gets or Sets if this character is enabled.
/// </summary>
public Boolean Enabled { get; set; } public Boolean Enabled { get; set; }
/// <summary>
/// Gets or Sets if this client is fully logged into the account.
/// </summary>
public Boolean LoggedIn
{
get
{
return this._LoggedIn;
}
private set
{
if (value)
this.OnLoginEvent();
this._LoggedIn = value;
}
}
//TODO: Add current location to characters //TODO: Add current location to characters
//public IEnvironment CurrentLocation //public IEnvironment CurrentLocation
@ -76,7 +96,6 @@ namespace MudEngine.Game.Characters
this._Writer = new StreamWriter(new NetworkStream(this._Connection, true)); this._Writer = new StreamWriter(new NetworkStream(this._Connection, true));
this._Writer.AutoFlush = true; //Flushes the stream automatically. this._Writer.AutoFlush = true; //Flushes the stream automatically.
this._InitialMessage = true; //Strips Telnet client garbage text from initial message sent from client.
} }
public void Initialize() public void Initialize()
@ -111,21 +130,27 @@ namespace MudEngine.Game.Characters
base.Load(filename); base.Load(filename);
} }
internal void ExecuteCommand(string command) internal Boolean ExecuteCommand(string command)
{ {
if (this.Enabled) if (this.Enabled)
{ {
Commands.Execute(command, this); Boolean result = Commands.Execute(command, this);
SendMessage(""); SendMessage("");
SendMessage("Command:", false); SendMessage("Command:", false);
return result;
} }
else
return false;
} }
public void Connect(Socket connection) public void Connect(Socket connection)
{ {
this._Connection = connection; this._Connection = connection;
//this.Initialize();
OnConnectEvent(); OnConnectEvent();
} }
@ -186,7 +211,8 @@ namespace MudEngine.Game.Characters
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
input = enc.GetString(buffer.ToArray()); input = enc.GetString(buffer.ToArray());
buffer.Clear(); buffer.Clear();
return input; //Return a trimmed string.
return CleanString(input);
} }
else else
buffer.Add(buf[0]); buffer.Add(buf[0]);
@ -206,6 +232,10 @@ namespace MudEngine.Game.Characters
} }
} }
public void FlushBuffer()
{
}
String CleanString(String line) String CleanString(String line)
{ {
/* /*
@ -224,22 +254,22 @@ namespace MudEngine.Game.Characters
else else
return String.Empty; return String.Empty;
* */ * */
Match m = Regex.Match(line, @"\w+"); // Regex.Replace(line, @"[^\u0000-\u007F]", "");
Regex invalidChars = new Regex( line = m.Value;
@"(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\uFEFF\uFFFE\uFFFF]", return line.Trim();
RegexOptions.Compiled);
if (String.IsNullOrEmpty(line))
return "";
else
return invalidChars.Replace(line, "");
} }
public delegate void OnConnectHandler(); public delegate void OnConnectHandler();
public event OnConnectHandler OnConnectEvent; public event OnConnectHandler OnConnectEvent;
public void OnConnect() public void OnConnect()
{ {
this.SendMessage(this.Game.Server.MOTD); //Greet the user with the game information
this.SendMessage(this.Game.Name);
this.SendMessage(this.Game.Description);
this.SendMessage(String.Empty);
//Log the user in.
this.LoggedIn = this.ExecuteCommand("Login");
} }
public delegate void OnDisconnectHandler(); public delegate void OnDisconnectHandler();
@ -252,13 +282,13 @@ namespace MudEngine.Game.Characters
public event OnLoginHandler OnLoginEvent; public event OnLoginHandler OnLoginEvent;
public void OnLogin() public void OnLogin()
{ {
this.SendMessage(this.Game.Server.MOTD);
} }
private Socket _Connection; private Socket _Connection;
private StreamReader _Reader; private StreamReader _Reader;
private StreamWriter _Writer; private StreamWriter _Writer;
private Boolean _InitialMessage; private Boolean _LoggedIn;
private List<byte> buffer = new List<byte>(); private List<byte> buffer = new List<byte>();
} }
} }

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.IO;
using MudEngine.Networking; using MudEngine.Networking;
using MudEngine.Core; using MudEngine.Core;
@ -108,12 +109,10 @@ namespace MudEngine.Game
//Setup default save paths. //Setup default save paths.
DataPaths paths = new DataPaths(); DataPaths paths = new DataPaths();
paths.Environments = @"\Environment";
paths.Characters = @"\Characters";
paths.Players = @"\SavedPlayer";
paths.Scripts = @"\Scripts";
this.SavePaths = paths; this.SavePaths = paths;
SetupPaths();
} }
/// <summary> /// <summary>
@ -169,5 +168,11 @@ namespace MudEngine.Game
{ {
} }
private void SetupPaths()
{
if (!Directory.Exists(this.SavePaths.GetPath(DataTypes.Players)))
Directory.CreateDirectory(this.SavePaths.GetPath(DataTypes.Players));
}
} }
} }

View file

@ -66,7 +66,7 @@ namespace MudEngine.GameScripts
if (!File.Exists(filename)) if (!File.Exists(filename))
return; return;
XElement data = XElement.Load(filename); //XElement data = XElement.Load(filename);
} }
catch catch
{ {

View file

@ -28,13 +28,24 @@ namespace MudEngine.GameScripts.Commands
Description = "Account login command."; Description = "Account login command.";
} }
public void Execute(string command, Game.Characters.StandardCharacter character) public Boolean Execute(string command, Game.Characters.StandardCharacter character)
{ {
//reference to the Characters Game.
StandardGame game = character.Game; StandardGame game = character.Game;
//Store a reference to this character for other methods within this class.
this._Character = character;
if (character.LoggedIn)
{
character.SendMessage("You are already logged in!");
return false;
}
character.SendMessage("Please enter character name: "); character.SendMessage("Please enter character name: ");
String name = String.Empty; String name = String.Empty;
//Repeat the login process until we get a valid name.
while (String.IsNullOrEmpty(name)) while (String.IsNullOrEmpty(name))
{ {
character.SendMessage("Enter your character name: ", false); character.SendMessage("Enter your character name: ", false);
@ -42,36 +53,73 @@ namespace MudEngine.GameScripts.Commands
name = String.Empty; name = String.Empty;
Boolean isFound = false; Boolean isFound = false;
while (String.IsNullOrEmpty(name)) //Get the supplied name
{
name = character.GetInput(); name = character.GetInput();
//Check if the name entered is blank. Ensure that we remove leading and ending spaces
if (String.IsNullOrEmpty(name)) if (String.IsNullOrEmpty(name))
continue; continue;
//Look if the file exists. //Look if the file exists.
if (File.Exists(game.SavePaths.Players + @"\" + name)) String filename = game.SavePaths.GetPath(DAL.DataTypes.Players) + name;
isFound = true;
else
{
character.SendMessage("Enter your password: ", false);
if (File.Exists(game.SavePaths.GetPath(DAL.DataTypes.Players) + name))
isFound = true;
//if the character name supplied exists, load it.
if (isFound)
{
//Perform a password check
character.SendMessage("Please enter a password for " + name);
String password = character.GetInput(); String password = character.GetInput();
//If the password is empty, then restart the process.
if (String.IsNullOrEmpty(password)) if (String.IsNullOrEmpty(password))
{ {
//Reset the process if no password supplied.
name = String.Empty; name = String.Empty;
continue; continue;
} }
//Load the character from file.
character.Load(game.SavePaths.GetPath(DAL.DataTypes.Players) + name);
//Check if the characters password matches that of the saved player password
if ("1234" != password)
{
//No match, bail.
character.SendMessage("Invalid password provided.");
name = String.Empty;
continue;
}
else //End our loading.
{
character.SendMessage("Welcome back " + character.Name + "!");
return true;
}
}
else else
{ {
character.SendMessage("No character with that name was found. Create a new one? (Yes/No)");
String result = character.GetInput();
if (result.ToLower() == "yes")
{
return CreateCharacter(name);
}
else
{
continue;
} }
} }
} }
return false;
} }
private Boolean CreateCharacter(String name)
{
return false;
} }
private StandardCharacter _Character;
} }
} }

View file

@ -24,7 +24,7 @@ namespace MudEngine.GameScripts.Commands
this.Description = "Chat command that allows objects to communicate."; this.Description = "Chat command that allows objects to communicate.";
} }
public void Execute(string command, StandardCharacter character) public Boolean Execute(string command, StandardCharacter character)
{ {
//Grab a reference to the character for simplifying access. //Grab a reference to the character for simplifying access.
StandardGame game = character.Game; StandardGame game = character.Game;
@ -42,6 +42,8 @@ namespace MudEngine.GameScripts.Commands
//Send a different copy of the message to the broadcastor. //Send a different copy of the message to the broadcastor.
character.SendMessage("You say: " + message); character.SendMessage("You say: " + message);
return true;
} }
} }
} }

View file

@ -25,13 +25,14 @@ namespace MudEngine.GameScripts.Commands
this.Description = "Chat command that allows objects to communicate."; this.Description = "Chat command that allows objects to communicate.";
} }
public void Execute(string command, StandardCharacter character) public Boolean Execute(string command, StandardCharacter character)
{ {
//Grab a reference to the character for simplifying access. //Grab a reference to the character for simplifying access.
StandardGame game = character.Game; StandardGame game = character.Game;
//Stop the game. //Stop the game.
new Thread(game.Stop).Start(); new Thread(game.Stop).Start();
return true;
} }
} }
} }

View file

@ -35,6 +35,7 @@ namespace MudEngine.Networking
StandardCharacter character = new StandardCharacter(game, "New Player", "New networked client.", connection); StandardCharacter character = new StandardCharacter(game, "New Player", "New networked client.", connection);
//Invoke the Characters Server connection method //Invoke the Characters Server connection method
character.Initialize();
character.Connect(connection); character.Connect(connection);
this._ConnectedCharacters.Add(character); this._ConnectedCharacters.Add(character);
this._ConnectedThreads.Add(new Thread(ReceiveDataThread)); this._ConnectedThreads.Add(new Thread(ReceiveDataThread));
@ -51,7 +52,6 @@ namespace MudEngine.Networking
private void ReceiveDataThread(Object index) private void ReceiveDataThread(Object index)
{ {
StandardCharacter character = this._ConnectedCharacters[(Int32)index]; StandardCharacter character = this._ConnectedCharacters[(Int32)index];
character.Initialize();
while (character.Game.Server.Status == ServerStatus.Running && while (character.Game.Server.Status == ServerStatus.Running &&
character.Enabled) character.Enabled)