using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
namespace GUD_Server
{
//trying to seperate out command parser
internal class CommandParser
{
string tempMessage;
bool workingOnHelp;
string tempHelpTopic;
string tempHelpSubject;
static string colorBoldGreen;
static string colorReset;
SortedList<string, ConnectionInfo> allSocketInfo;
public CommandParser()
{
//sets colors that are used by the parser
//TODO: to be merged once colors are made a dictionary
colorBoldGreen = "\u001B[32;1;m";
colorReset = "\u001B[0;m";
//cast connection into it's orginal state
//ConnectionInfo thisConnection = (ConnectionInfo)_connected;
//performLogin removed
//buffer for recieved text
//string tempMessage = "";
//Counters for idle users
//TODO: See about adding system tick clock
//timeout counters removed
//for Help system editing
//bool workingOnHelp = false;
//string tempHelpTopic = "";
//string tempHelpSubject = "";
}
public bool CheckForCommands(ConnectionInfo _connected, object _AllSockets, string characterPath, string helpFilePath) //bool value will stand in for wasValidCommand
{
ConnectionInfo thisConnection = (ConnectionInfo)_connected;
// add to the characters total time on game.
TimeSpan tempSpan = DateTime.Now - thisConnection.subTime;
thisConnection.characterStats("add_timespan", (object)tempSpan);
thisConnection.subTime = DateTime.Now;
Thread.Sleep(100);
//recieve input from player and send output. will return null if nothing occurred
tempMessage = (string)thisConnection.EnOrDeQueue("de", null);
if (tempMessage != null && tempMessage != "")
{
//grab player input
while (tempMessage.IndexOf(" ") >= 0)
{
//trim extra spaces
tempMessage = tempMessage.Replace(" ", " ");
}
while (tempMessage.IndexOf(" ") == 0)
{
// remove any spaces from front of input
tempMessage = tempMessage.Remove(0, 1);
}
string[] inputArray = tempMessage.Split(' '); //break up buffer to indvidual words
if (inputArray[0] != "") //discard spaces
{
//checks first Character in word for command characters
string firstLetter = inputArray[0].Substring(0, 1);
//flag for invalid commands
bool wasValidCommand = false;
//notes from DougMud author, using the If structure can cause longer commands to hide smaller ones
//smaller commands should go torwards the end
//the switch statement contains cases for all 26 letters to make it easier to add commands later.
//The excess letters can be removed if wanted, they should fall through to default.
//TODO: Move all commands to seperate methods. This was done to make command editing easier and more editable
//TODO: Add save command
switch (firstLetter)
{
case "a":
return false;
case "b":
return false;
case "c":
if (inputArray[0].Length <= "color".Length && inputArray[0].ToLower() == "color".Substring(0, inputArray[0].Length))
{
Color(thisConnection);
}
return true;
case "d":
return false;
case "e":
return false;
case "f":
return false;
case "g":
return false;
case "h":
if (inputArray[0].Length <= "help".Length && inputArray[0].ToLower() == "help".Substring(0, inputArray[0].Length))
{
Help(thisConnection, GetOrSetHelp, inputArray);
return true;
}
else if (inputArray[0].Length <= "helpcreate".Length && inputArray[0].ToLower() == "helpcreate".Substring(0, inputArray[0].Length))
{
HelpCreate(thisConnection, GetOrSetHelp, inputArray, helpFileContents);
return true;
}
return false;
case "i":
return false;
case "j":
return false;
case "k":
return false;
case "l":
if (inputArray[0].Length <= "last".Length && inputArray[0].ToLower() == "last".Substring(0, inputArray[0].Length))
{
Last(thisConnection, inputArray, characterPath);
return true;
}
return false;
case "m":
return false;
case "n":
return false;
case "o":
return false;
case "p":
return false;
case "q":
if (inputArray[0].Length <= "quit".Length && inputArray[0].ToLower() == "quit".Substring(0, inputArray[0].Length))
{
Quit(thisConnection, inputArray, characterPath);
return true;
}
return false;
case "r":
return false;
case "s":
if (inputArray[0].Length <= "shout".Length && inputArray[0].ToLower() == "shout".Substring(0, inputArray[0].Length))
{
Shout(thisConnection, inputArray, _AllSockets);
return true;
}
return false;
case "t":
if (inputArray[0].Length <= "tell".Length && inputArray[0].ToLower() == "tell".Substring(0, inputArray[0].Length))
{
Tell(thisConnection, inputArray, _AllSockets, colorBoldGreen, colorReset);
return true;
}
else if (inputArray[0].Length <= "time".Length && inputArray[0].ToLower() == "time".Substring(0, inputArray[0].Length))
{
Time(thisConnection);
return true;
}
return false;
case "u":
return false;
case "v":
return false;
case "w":
return false;
case "x":
return false;
case "y":
return false;
case "z":
return false;
case "~": //for admin commands
return false;
default:
return false;
}
}
}
}
//public objects
//User Commands
private void Color(ConnectionInfo thisConnection)
{
//Activates vt102 Color Codes for the connection
thisConnection.sendto(0, (string)thisConnection.characterStats("set_color", null));
}
private void Help(ConnectionInfo thisConnection, object GetOrSetHelp, String[] inputArray)
{
if (inputArray.Length > 1)
{
thisConnection.sendto(0, (string)GetOrSetHelp("get", inputArray[1], null));
}
else
{
thisConnection.sendto(0, "Get help with what?\r\n");
}
}
private void HelpCreate(ConnectionInfo thisConnection, object GetOrSetHelp, String[] inputArray, SortedList helpFileContents)
{
//TODO: Need to add permission levels less someone malicously edit the lot
// helpcreate start/addall/cancel/show/generate
// remove/addline/topic/save
// start -- flips boolean to allow working with a new entry.
// addwork -- add your work (hopefully completed)
// cancel -- cancel work done...
// show -- show what you've done so far...
// generate-- regenerate the 'topics' listing for help.
// save -- save helptopics to file.
// topic -- give topic to current work.
// addline -- add a line to the subject matter of the topic
// remove -- remove a topic from the help system.
if (inputArray.Length > 1)
{
if (inputArray[1] == "start")
{
// Toggle flags that denotes player is working on helpfiles.
workingOnHelp = true;
thisConnection.sendto(0, "Ok. Starting work on the help files.\r\n");
}
else if (inputArray[1] == "addwork")
{
// add help to the system, and turn workingOnHelp flag off, then reset stuffs for working with
if (workingOnHelp == true)
{
if (tempHelpTopic.Length < 3 || tempHelpSubject.Length < 4)
{
thisConnection.sendto(0, "Must have a topic, and subject of at least 4 characters to add to the help.\r\n\r\n");
}
else
{
GetOrSetHelp("set", tempHelpTopic, tempHelpSubject);
thisConnection.sendto(0, "Ok. " + tempHelpTopic + " added to the help.\r\n");
tempHelpTopic = "";
tempHelpSubject = "";
workingOnHelp = false;
}
}
else
{
thisConnection.sendto(0, "Must be working on help to add a topic.\r\n");
}
}
else if (inputArray[1] == "cancel")
{
// cancel current work.
tempHelpTopic = "";
tempHelpSubject = "";
workingOnHelp = false;
thisConnection.sendto(0, "Ok. Work cancelled.\r\n");
}
else if (inputArray[1] == "show")
{
// Show current state of help subject
if (workingOnHelp == true)
{
string temp_show = "Topic: " + tempHelpTopic + " With Subject:\r\n\r\n"
+ tempHelpSubject + "\r\n";
thisConnection.sendto(0, temp_show);
}
else
{
thisConnection.sendto(0, "Must be working on help to do that.\r\n");
}
}
else if (inputArray[1] == "generate")
{
// regenerate a topics listing for 'help topics'
GetOrSetHelp("generate_topics", null, null);
thisConnection.sendto(0, "Ok. Topics regenerated.\r\n\r\n");
}
else if (inputArray[1] == "remove")
{
// remove a topic from the help. helpcreate remove <name>
if (inputArray.Length > 2)
{
if (helpFileContents.ContainsKey(inputArray[2]))
{
helpFileContents.Remove(inputArray[2].ToLower());
thisConnection.sendto(0, "Ok. Removed " + inputArray[2].ToLower() + " from help.\r\n");
}
else
{
thisConnection.sendto(0, "Cannot remove! Help does not contain record for " + inputArray[2].ToLower());
}
}
else
{
thisConnection.sendto(0, "Usage: helpcreate remove <topicname>.\r\n");
}
}
else if (inputArray[1] == "save")
{
// HelpSave Command
// save help to disk.
GetOrSetHelp("save", null, null);
thisConnection.sendto(0, "Ok help contents saved to disk.\r\n");
return;
//HelpSave Command
}
else if (inputArray[1] == "addline")
{
if (inputArray.Length > 1)
{
if (workingOnHelp == true)
{
if (inputArray[2] == "blanks")
{
tempHelpSubject += "\n";
}
else
{
string temp_string = "";
for (int i = 2; i < inputArray.Length; i++)
{ // grab the subject line we are adding to the subject matter.
temp_string += inputArray[i] + " ";
}
// add a newline, then add the line to the tempHelpSubject.
temp_string += "\n";
tempHelpSubject += temp_string;
}
thisConnection.sendto(0, "Ok. Added a line to the current work.\r\n");
}
else
{
thisConnection.sendto(0, "You must be working on help to add a subject line.\r\n");
}
}
else
{
thisConnection.sendto(0, "You must add at least one word to a line of the topics subject matter.\r\n\r\n");
}
}
else if (inputArray[1] == "topic")
{
// sets a topic for our subject we are working on.
// helpcreate topic <topicname>
if (workingOnHelp == true && inputArray.Length > 2 && inputArray[2].Length > 2)
{
tempHelpTopic = inputArray[2];
thisConnection.sendto(0, "Help topic set to " + tempHelpTopic);
}
else
{
thisConnection.sendto(0, "Must be working on help, and have a topic of at least 3 characters.\r\n\r\n");
}
}
else
{
thisConnection.sendto(0, "Options are... start | addwork | cancel | show | generate\r\n"
+ " remove| save | addline | topic |\r\n");
}
}
else
{
thisConnection.sendto(0, "Options are... start | addwork | cancel | show | generate\r\n"
+ " remove| save | addline | topic |\r\n");
}
}
private void Last(ConnectionInfo thisConnection, String[] inputArray, string characterPath)
{
//Last command returns last time a target player logged in
//TODO: Add a try-catch to avoid errors if data comes back bad
if (inputArray.Length > 1 && inputArray[1].Length > 2)
{
string targetName = inputArray[1].ToLower(); //Target User to be checked
// Assemble path to Character file
string characterFilePath = characterPath + "\\" + targetName.Substring(0, 1) + String.Format("\\{0}.cha", targetName);
if (System.IO.File.Exists(characterFilePath))
{
//If file is present load into memory
FileStream targetFile = new FileStream(characterFilePath, FileMode.Open, FileAccess.Read);
BinaryFormatter bFormatter = new BinaryFormatter();
Character tempCharacter = (Character)bFormatter.Deserialize(targetFile);
//Close filestream and ready for garbage collection
targetFile.Close();
targetFile.Dispose();
targetFile = null;
bFormatter = null;
//generates string to send to user with target's name and last login date
string outputMessage = tempCharacter.loggedOnAt.ToString() + " is the last time " + targetName.Substring(0, 1).ToUpper() + targetName.Substring(1, targetName.Length - 1) + " was seen.\r\n";
thisConnection.sendto(0, outputMessage);
// get it ready for reclaim.
tempCharacter = null;
}
else
{
//no such player feedback
thisConnection.sendto(0, targetName.Substring(0, 1).ToUpper() + targetName.Substring(1, targetName.Length - 1) + " is not the name of a known player.\r\n");
}
}
else
{
//TODO: Change to target self
thisConnection.sendto(0, "Please specify a name.\r\n");
}
}
private void Quit(ConnectionInfo thisConnection, String[] inputArray, string characterPath)
{
//Quit command
//Changed from quit! to Quit
if (inputArray[0].Length == 4)
{
//set alive and logged in status to false and then save file
//assemble path to save at
string characterFilePath = characterPath + "\\" + ((string)thisConnection.characterStats("get_name", null)).Substring(0, 1).ToLower() + String.Format("\\{0}.cha", ((string)thisConnection.characterStats("get_name", null)));
//open file path for saving
FileStream OutputStream = new FileStream(characterFilePath, FileMode.Create, FileAccess.Write);
BinaryFormatter bFormatter = new BinaryFormatter();
// save the stream to disk.
bFormatter.Serialize(OutputStream, (Character)thisConnection.characterStats("get_file", null));
thisConnection.sendto(0, "\r\nYou have been saved.");
//Garbage Collect Filestream
OutputStream.Close();
OutputStream.Dispose();
OutputStream = null;
bFormatter = null;
thisConnection.sendto(0, "\r\nGoodbye!\r\n");
// set these to false, so associated threads with the socket will terminate
thisConnection.isAlive = false;
thisConnection.loggedIn = false;
}
else
{
thisConnection.sendto(0, "Uncertain command, did you mean to quit? type 'quit' to leave.\r\n");
}
}
private void Shout(ConnectionInfo thisConnection, String[] inputArray, object _AllSockets)
{
// sends a message over the shout channel, to all users...
if (inputArray.Length > 1)
{
_AllSockets("shout", (object)thisConnection.characterStats("get_name", null), (object)tempMessage.Remove(0, inputArray[0].Length + 1), null);
}
else
{
thisConnection.sendto(0, "You forgot what you wanted to shout? Try again.\r\n");
}
}
private void Tell(ConnectionInfo thisConnection, String[] inputArray, object _AllSockets, string colorBoldGreen, string colorReset)
{
// tell a message to a particular user, and only them.
if (inputArray.Length == 1)
{
thisConnection.sendto(0, "Tell what to whom?");
}
else if (inputArray.Length == 2)
{
thisConnection.sendto(0, "Ok but what do you want to tell them?");
}
else if (inputArray.Length > 2)
{
// get message we intend to tell. tempMessage - firstword and secondword and 2 spaces.
string tell_message = tempMessage.Remove(0, inputArray[0].Length + inputArray[1].Length + 2);
//return message from function.
string told_what = (string)_AllSockets("tell", (object)thisConnection.characterStats("get_name", null), (object)inputArray[1], (object)tell_message);
// send message back to the 'teller'
if ((bool)thisConnection.characterStats("get_color", null) == true)
{
thisConnection.sendto(0, colorBoldGreen + told_what + colorReset);
}
else
{
thisConnection.sendto(0, told_what);
}
}
}
private void Time(ConnectionInfo thisConnection)
{
// show some time information to the user. system time. total time logged...
// current session length...
string timeOutput;
DateTime currentTime = DateTime.Now;
DateTime bornOn = (DateTime)thisConnection.characterStats("get_born", null);
TimeSpan tempSpan2 = (TimeSpan)thisConnection.characterStats("get_timespan", null);
TimeSpan currentSession = (TimeSpan)(DateTime.Now - (DateTime)thisConnection.characterStats("get_login_time", null));
timeOutput = "System time: \r\n"
+ currentTime.DayOfWeek.ToString() + ", "
+ currentTime + "\r\n\r\nYou were born:\r\n"
+ bornOn.ToString() + "\r\n\r\nTime you've been playing: \r\n"
+ "Days: " + tempSpan2.Days + " Hours: " + tempSpan2.Hours
+ " Minutes: " + tempSpan2.Minutes + " Seconds: " + tempSpan2.Seconds + "\r\n\r\n"
+ "Current Session Length: \r\n"
+ "Days: " + currentSession.Days + " Hours: " + currentSession.Hours
+ " Minutes: " + currentSession.Minutes + " Seconds: " + currentSession.Seconds + "\r\n\r\n";
thisConnection.sendto(0, timeOutput);
}
}
}