using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
namespace GUD_Server
{
internal class Server
{
//Mud Server Code. Built out from DougMUD.
//TODO: Move Command Parser to seperate class
#region Declare Variables
int maxConnections = 40; //number of mximum clients that can be connected
int textPort = 4000; //telnetport for text
int connectionCount;
bool acceptingConnections = true;
string characterPath = ".\\characters"; //Directory for Character files
string helpFilePath = ".\\help.txt"; //Points to help file
SortedList<string, ConnectionInfo> allSocketInfo; //store information on connected clients
SortedList<string, string> helpFileContents; //stores contents of help file
#endregion Declare Variables
#region Declare Objects
TcpListener socketMonitor;
Socket socket;
NetworkStream socketStream;
StreamReader socketReciever;
StreamWriter socketSender;
#endregion Declare Objects
#region Color Codes
//fromDougMUD - author stated these needed testing
//TODO: Make the colors a dictionary
static string colorRed = "\u001B[31;m";
static string colorGreen = "\u001B[32;m";
static string colorYellow = "\u001B[33;m";
static string colorBlue = "\u001B[34;m";
static string colorMagenta = "\u001B[35;m";
static string colorCyan = "\u001B[36;m";
static string colorWhite = "\u001B[37;m";
static string colorBoldRed = "\u001B[31;1;m";
static string colorBoldGreen = "\u001B[32;1;m";
static string colorBoldYellow = "\u001B[33;1;m";
static string colorBoldBlue = "\u001B[34;1;m";
static string colorBoldMagenta = "\u001B[35;1;m";
static string colorBoldCyan = "\u001B[36;1;m";
static string colorBoldWhite = "\u001B[37;1;m";
string colorReset = "\u001B[0;m";
string colorBright = "\u001B[1;m";
string colorDim = "\u001B[2;m";
#endregion Color Codes
//removed idle messages - very annoying feature
public Server()
{
allSocketInfo = new SortedList<string, ConnectionInfo>();
helpFileContents = new SortedList<string, string>();
//Load help file into memory - see private methods
loadHelpFile(helpFilePath);
//start thread for accepting new connections
Thread acceptConnectionThread = new Thread(new ThreadStart(accept_connections));
acceptConnectionThread.Start();
} // end constructor...
#region Public Methods
public void accept_connections()
{
//TODO: Verify that server pop limit can be reached and not exceeded
while (acceptingConnections == true)
{
try
{
//Activate the Socket Monitor
socketMonitor = new TcpListener(IPAddress.Any, textPort);
socketMonitor.Start();
//Give the socket a connection and then reset the monitor
socket = socketMonitor.AcceptSocket();
socketMonitor.Stop();
socketMonitor = null;
//Setup conenctions streams for socket
//TODO: This is where the graphic pipeline will need to connect to the client
socketStream = new NetworkStream(socket);
socketReciever = new StreamReader(socketStream);
socketSender = new StreamWriter(socketStream);
//Setup connection provided that max connections has not been reached
if (connectionCount < maxConnections)
{
connectionCount++;
//grab a holding string for connection name. this holder is later replaced with the Character name
string tempConnectionName = System.Guid.NewGuid().ToString();
//Assemble the connection into a complete object
ConnectionInfo newConnection = new ConnectionInfo(socket, socketStream, socketReciever, socketSender, tempConnectionName);
AllSockets("add", (object)tempConnectionName, (object)newConnection, null);
//Start a thread and pass it the connection
Thread putInGameThread = new Thread(new ParameterizedThreadStart(PutConnectionInGame));
putInGameThread.Start((object)newConnection);
}
else
{
//if maximum connections exceeded, the client is given an error and shuts the connection
socketSender.WriteLine("Server is full. Please try again later");
socketSender.Flush();
Thread.Sleep(20);
//Close socket and disconnect client
//TODO: See about Consolidating this into a DisconnectSocket() method.
socketStream.Close();
socketReciever.Close();
socketSender.Close();
socket.Close();
// get the socket information ready for garbage reclamation.
socketStream = null;
socketReciever = null;
socketSender = null;
socket = null;
}
}
catch (Exception ex)
{
Console.WriteLine("Problem during Accepting Connection: " + ex.ToString());
}
}
}
public object GetOrSetHelp(string flag, string sKey, string sMatter)
{
lock (helpFileContents)
{
if (flag == "get")
{
#region get...
// get the help and return it, for sending to the user.
string tempMessage = "";
if (helpFileContents.TryGetValue(sKey, out tempMessage))
{
return (object)"You found help on the " + sKey + " topic.\r\n\r\n" + tempMessage;
}
else
{
return (object)"No help topic with the name of " + sKey + " exists, try again.\r\n";
}
#endregion get...
}
else if (flag == "set")
{
// add each key/value pair. topic/subject_matter
helpFileContents.Add(sKey, sMatter);
}
else if (flag == "save")
{
#region save help code...
// save the help to the file.
// will be used when dynamic adding of the help file system is put in.
if (System.IO.File.Exists(helpFilePath))
{
System.IO.File.Copy(helpFilePath, ".\\help.bak", true);
}
StreamWriter helpWriter = new StreamWriter(helpFilePath, false);
int tempCounter = 0;
foreach (KeyValuePair<string, string> item in helpFileContents)
{
if (item.Key != "topics")
{
if (tempCounter < 1)
{
// this is here jsut so a blank line isn't put at the end or beginning of the file.
// which would be bad. this makes it so the last #STOP in the file doesn't have
// a blank line before it.
}
else
{
helpWriter.WriteLine();
}
// write the key as the first line of an entry.
helpWriter.WriteLine(item.Key);
// split the value into a string for each line, for file writing.
string[] split_string = item.Value.Split('\n');
for (int i = 0; i < split_string.Length - 1; i++)
{ // write each line of the subject matter to the file...
helpWriter.WriteLine(split_string[i]);
}
// write the #STOP which signifies end of entry in text file.
helpWriter.Write("#STOP");
tempCounter++;
}
} // end foreach
helpWriter.Dispose();
helpWriter = null;
#endregion save help code...
}
else if (flag == "generate_topics")
{
#region generate_topics code...
// then will re-add the topic and subjectmatter of topic.
if (helpFileContents.ContainsKey("topics") == true)
{ // remove the topics topic if it exists.
helpFileContents.Remove("topics");
}
int tempCount = 1;
string tempsubjectMatter = "";
// generate a topics subject...
foreach (KeyValuePair<string, string> item in helpFileContents)
{
if (tempCount > 0 && tempCount % 4 == 0)
{
tempsubjectMatter += item.Key + "\r\n";
}
else
{
// for creating four columns of the topics. will add the spaces if not the last
// item on a particular line.
tempsubjectMatter += item.Key + " ".Substring(0, 18 - item.Key.Length);
}
tempCount++;
} // end foreach.
tempsubjectMatter += "\r\n";
// add the generated topics topic to the help.
helpFileContents.Add("topics", tempsubjectMatter);
#endregion generate_topics code...
}
} // end lock
return null;
} // end GetOrSetHelp
public void loadHelpFile(string filePath)
{
// read the help file, then load topics and their associated subject matter into memory.
//TODO: set code to create a help file is one if not present
StreamReader helpReader = new StreamReader(filePath);
string lineRead = "";
string subjectKey = "";
string subjectInfo = "";
while (helpReader.Peek() != -1)
{
subjectKey = helpReader.ReadLine(); // grab first line of file will be a subject key.
lineRead = helpReader.ReadLine(); // priming read.
while (helpReader.Peek() != -1 && lineRead != "#STOP")
{
if (lineRead != "#STOP")
{
subjectInfo += lineRead + "\n";
}
else { }
// grab all of the subject matter. #STOP signifies end of subject.
lineRead = helpReader.ReadLine();
}
// add the subject_matter, and subject_key to the help sortedList
GetOrSetHelp("set", subjectKey, subjectInfo);
// reset...
subjectKey = "";
subjectInfo = "";
lineRead = "";
}
helpReader.Dispose();
helpReader = null;
GetOrSetHelp("generate_topics", null, null);
}
#region Character handling threads...
public void PutConnectionInGame(object _connected)
{
//cast connection into it's orginal state
ConnectionInfo thisConnection = (ConnectionInfo)_connected;
CommandParser commandParser = new CommandParser();
PerformLogin(thisConnection);
//buffer for recieved text
string tempMessage = "";
//Counters for idle users
//TODO: See about adding system tick clock
int timeoutCounter = 0;
int timeoutCounter2 = 0;
//for Help system editing
bool workingOnHelp = false;
string tempHelpTopic = "";
string tempHelpSubject = "";
//For tracking the total logged time statistic
thisConnection.subTime = DateTime.Now;
while (thisConnection.isAlive == true)
{
//Command Parser
bool wasValidCommand = (commandParser.CheckForCommands(thisConnection, AllSockets, characterPath, helpFilePath));
if (wasValidCommand)
{
//if true
//reset timeout counters
timeoutCounter = 0;
timeoutCounter2 = 0;
}
else
{
timeoutCounter++;
}
//if timeout
#region Idle Timeout
if (timeoutCounter % 300 == 0 && timeoutCounter > 299)
{ // timeoutCounter increments every tick, tick sleeps 1/10th second at the top.
// will reach here every, (300 / (1000 / threadsleep)) seconds.
// so as it is, that's roughly every 30 seconds. as is, boot in 3.5 minutes.
//TODO: change idle to 1 minute/5 minutes total
//removed the 30 second idle messager that was bugging logged in players
timeoutCounter2++;
//Random r = new Random();
//thisConnection.sendto(0, thirty_sec_idle_messages[r.Next(0, thirty_sec_idle_messages.Length)]);
if (timeoutCounter2 == 1)
{ // give them a message every 30 seconds for 3.5 mins then boot them
thisConnection.sendto(0, "You have been idle for about 30 seconds.");
}
else if (timeoutCounter2 == 2)
{
thisConnection.sendto(0, "You have been afk for about 60 seconds now.");
}
else if (timeoutCounter2 == 3)
{
thisConnection.sendto(0, "You've been scratching your butt for a minute and a half.");
}
else if (timeoutCounter2 == 4)
{
thisConnection.sendto(0, "For two minutes you've been doing nothing, do something!");
}
else if (timeoutCounter2 == 5)
{
thisConnection.sendto(0, "It's been about 2 and a half minutes since your last entry, you have 60 seconds till boot!");
}
else if (timeoutCounter2 == 6)
{
thisConnection.sendto(0, "WARNING: You will be booted in 30 seconds if you are still afk.");
}
else if (timeoutCounter2 == 7)
{
thisConnection.sendto(0, "You are being booted, due to inactivity. Goodbye.");
Thread.Sleep(20);
thisConnection.isAlive = false;
}
}
#endregion Idle Timeout
}
// set to false so it no longer can receive messages.
thisConnection.loggedIn = false;
// clean up the connection...
AllSockets("remove", thisConnection.ConnectionName, null, null);
thisConnection.endSelf();
thisConnection = null;
// decrement ttl connections count.
connectionCount--;
}
public void PerformLogin(object _connected)
{
ConnectionInfo thisConnection = (ConnectionInfo)_connected;
// do login stuffs...
string newPlayerName = "";
string temp_password = "";
bool isIdle = false;
int timeoutCounter = 0;
int genericCounter = 0;
thisConnection.sendto(1, "\r\nName: ");
bool nameChosen = false;
bool newPlayer = false;
#region Name Creation
// here we choose a valid name. Can get disconnected from timeout, or too many bad attempts or
// just pressing enter too many times...
//TODO: fix the use of the targetName variable to one better named
while (nameChosen == false && isIdle == false)
{
newPlayerName = (string)thisConnection.EnOrDeQueue("de", null);
if (newPlayerName == null)
{
// Tracks Idle time
timeoutCounter++;
}
else if (newPlayerName == "")
{
// when they just enter in blank to the game counter2 will increment.
genericCounter += 2;
timeoutCounter = 0;
thisConnection.sendto(1, "\r\nThat cannot be your name, choose another.\r\nName: ");
}
else if (validName(newPlayerName) == true)
{
// if they chose a good name, lets get outta this loop.
genericCounter = 0;
nameChosen = true;
}
else
{
// invalid name.
genericCounter += 2;
timeoutCounter = 0;
thisConnection.sendto(1, "\r\nThat cannot be your name, choose another.\r\nName: ");
}
if (timeoutCounter > 199 && timeoutCounter % 200 == 0)
{
genericCounter++;
}
Thread.Sleep(100);
if (genericCounter >= 6)
{
// genericCounter is used to decide when they idle out or get booted from bad attempts.
isIdle = true;
thisConnection.sendto(0, "\r\nYou are getting booted.");
Thread.Sleep(50);
thisConnection.isAlive = false;
nameChosen = false;
}
if (nameChosen == true)
{
newPlayerName = newPlayerName.ToLower();
string tempLetter = newPlayerName.Substring(0, 1);
newPlayerName = newPlayerName.Remove(0, 1);
newPlayerName = tempLetter.ToUpper() + newPlayerName;
}
}
genericCounter = 0;
timeoutCounter = 0;
#endregion Name Creation
if (nameChosen == true)
{
//name was chosen, if they are already logged in, disallow.
bool tempBool = (bool)AllSockets("contains", (object)newPlayerName.ToLower(), null, null);
if (thisConnection.isAlive == true)
{
// if a person tried to login a name twice at the same time instead of one after another
// both connections could pass the above "contains" check and theoretically login two of
// the same Character and dupe items, either handing them over or dropping them.
AllSockets("remove", (string)thisConnection.ConnectionName, null, null);
string xTemp = newPlayerName.ToLower();
try
{
// will throw exception if someone tries to logon two of the same name all at
// one time instead of on after another. Let's handle, and respond.
// could be used to crash the mud if it wasn't handled, or to duplicate items
// if it isn't handled correctly.
AllSockets("add", xTemp, thisConnection, null);
}
catch (Exception ex)
{
tempBool = true;
}
}
if (tempBool == true)
{
isIdle = true;
thisConnection.sendto(0, String.Format("\r\nAccess denied, {0} is already logged in", newPlayerName));
thisConnection.sendto(0, "\r\nLogging you out..");
Thread.Sleep(50);
thisConnection.isAlive = false;
}
else
{
}
#endregion Character handling threads...
}
if (isIdle == false)
{
#region Character File Loading
// Load the Character file
string characterFilePath =
characterPath + "\\" + newPlayerName.Substring(0, 1) + String.Format("\\{0}.cha", newPlayerName.ToLower());
if (System.IO.File.Exists(characterFilePath))
{
// if the file exists, deserialize it and put it into the sockets Character.
System.IO.FileStream targetFile =
new System.IO.FileStream(characterFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
BinaryFormatter bFormatter = new BinaryFormatter();
Character tempCharacter = (Character)bFormatter.Deserialize(targetFile);
thisConnection.characterStats("set_file", tempCharacter);
newPlayer = false;
// close out file for use elsewhere.
targetFile.Close();
targetFile.Dispose();
targetFile = null;
bFormatter = null;
#endregion Character File Loading
}
else
{
thisConnection.characterStats("set_name", (object)newPlayerName);
newPlayer = true;
}
if (newPlayer == false)
{ // if old player match passwords.
#region Existing player password screen
// they are an existing player, now lets get that password.
bool pw_match = false;
thisConnection.sendto(1, "Password: ");
while (isIdle == false && pw_match == false)
{
// will loop until user idles out, exceeds maximum attempts, or succeeds
temp_password = (string)thisConnection.EnOrDeQueue("de", null);
if (temp_password == null)
{ // increment when they are idling.
timeoutCounter++;
}
else if (temp_password == "")
{ // bad password.
genericCounter += 2;
timeoutCounter = 0;
thisConnection.sendto(1, "\r\n\r\nInvalid password, choose another.\r\nPassword: ");
}
else if (temp_password == (string)thisConnection.characterStats("get_password", null))
{
// good password
genericCounter = 0;
thisConnection.sendto(0, "\r\nWelcome back " + (string)thisConnection.characterStats("get_name", null) + ".\r\n");
pw_match = true;
thisConnection.loggedIn = true;
thisConnection.characterStats("set_login_time", (object)DateTime.Now);
}
else
{
// pad password, not blank, but doesn't match.
genericCounter += 2;
timeoutCounter = 0;
thisConnection.sendto(1, "\r\n\r\nThat is not your password, try again.\r\nPassword: ");
}
if (timeoutCounter > 199 && timeoutCounter % 200 == 0)
{
genericCounter++;
}
Thread.Sleep(100);
if (genericCounter >= 6)
{
// generic counter is used to decide when they idle, or have too many bad attempts.
isIdle = true;
thisConnection.sendto(0, "\r\nYou are getting booted. Too many login attempts.");
Thread.Sleep(50);
thisConnection.isAlive = false;
}
}
genericCounter = 0;
timeoutCounter = 0;
#endregion Existing player password screen
}
else if (newPlayer == true)
{
// if new player ask for a password.
#region New Player Password Screen
// they are a new player establish a password...
bool pw_match = false;
int pass_num = 0;
string pass_one = "";
string pass_two = "";
thisConnection.sendto(1, "\r\nChoose Password: ");
while (isIdle == false && pw_match == false)
{
temp_password = (string)thisConnection.EnOrDeQueue("de", null);
if (temp_password == null)
{ // counter increments when they aren't typing anything.
timeoutCounter++;
}
else if (temp_password == "")
{ // when they enter blank for the password.
genericCounter += 1;
if (pass_num == 0)
{
thisConnection.sendto(1, "\r\n\r\nInvalid. Choose Password: ");
}
else if (pass_num == 1)
{
thisConnection.sendto(1, "\r\n\r\nInvalid. Match Password: ");
}
timeoutCounter = 0;
}
else
{
if (pass_num == 0)
{ // first password entered.
pass_one = temp_password;
pass_num++;
thisConnection.sendto(1, "\r\nMatch Password: ");
}
else if (pass_num == 1)
{ // second password entered.
pass_two = temp_password;
pass_num++;
}
if (pass_one == pass_two && pass_num == 2)
{ // if the first and second passwords matched, its all good, lets get outta the loop.
thisConnection.sendto(0, "\r\n\r\nAccepted. Passwords match.\r\n");
thisConnection.characterStats("set_password", (object)pass_one);
pw_match = true;
thisConnection.loggedIn = true;
thisConnection.characterStats("set_login_time", (object)DateTime.Now);
}
else if (pass_one != pass_two && pass_num == 2)
{ // nonmatching passwords, try again.
genericCounter++;
pass_num = 0;
thisConnection.sendto(0, "\r\nPasswords do not match, enter again.");
thisConnection.sendto(1, "\r\nChoose Password: ");
}
timeoutCounter = 0;
}
if (timeoutCounter > 199 && timeoutCounter % 200 == 0)
{
genericCounter++;
}
Thread.Sleep(100);
if (genericCounter >= 6)
{ // too many attempts or idle too long. ennnn bye bye.
isIdle = true;
thisConnection.sendto(0, "\r\n\r\nYou are getting booted. Too many bad passwords.");
Thread.Sleep(50);
thisConnection.isAlive = false;
}
}
if (isIdle == false)
{
// set players creation date.
thisConnection.characterStats("set_born", (object)DateTime.Now);
}
#endregion New Player Password Screen
}
}
}
#endregion Public Methods
#region Private Methods
public bool validName(string targetName)
{
// determine if they chose a valid name or not...
// could add a list to check against names we don't want people to have
// like curse words, or... Somebody or Something, or whatever.
if (targetName.Length < 4 || targetName.Length > 10 || targetName.Contains(" "))
{
return false;
}
Stack nameStack = new Stack();
foreach (Char tempChar in targetName)
{
nameStack.Push(tempChar);
}
try
{
// stack.pop will generate exception when empty so can exit the loop.
while (true == true)
{
Char tempChar2 = (Char)nameStack.Pop();
if (!Char.IsLetter(tempChar2))
{
return false;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
// if we get here it is a valid name.
return true;
}
public object AllSockets(string tempFlag, object objectOne, object object_Two, object object_Three)
{
// this is a wrapper for allSocketInfo, so as to be able to lock the list
// on any add or remove from any thread.
lock (allSocketInfo)
{
if (tempFlag == "add")
{
// to add
// generates exception if someone tries to login one Character multiple times by entering the name
// could only happen if someone logged in two session the same name at the same exact time,
// is handled in the PerformLogin routine, under the, deny multiple access same Character region.
allSocketInfo.Add((string)objectOne, (ConnectionInfo)object_Two);
return null;
}
else if (tempFlag == "remove")
{ // to remove a connection from the all sockets listing.
try
{
allSocketInfo.Remove((string)objectOne);
}
catch (Exception ex)
{ }
return null;
}
else if (tempFlag == "contains")
{
// determine if someone is logged in by checking if they are in the in the listing
bool tempBool = false;
foreach (KeyValuePair<string, ConnectionInfo> item in allSocketInfo)
{
if (item.Value.player.name == (string)objectOne)
{
tempBool = true;
}
} // end foreach
return (object)tempBool;
}
else if (tempFlag == "list")
{ // return updated main listing, minus dead connections.
#region Listing code.
// add each dc'd to a list for iteration through for removal from main list.
List<string> tempListing = new List<string>();
foreach (KeyValuePair<string, ConnectionInfo> item in allSocketInfo)
{
if (item.Value.isAlive == false)
{
// Im hoping this will set the ConnectionInfo of the dead connection
// to nothing and all of that be reclaimed.
tempListing.Add(item.Key);
}
} // end foreach
if (allSocketInfo.Count == 0)
{
return null;
}
foreach (string item in tempListing)
{ // remove all the dead connections from the main listing.
try
{
allSocketInfo.Remove(item);
}
catch (Exception ex)
{ }
}
List<string> tempListing2 = new List<string>();
foreach (KeyValuePair<string, ConnectionInfo> item in allSocketInfo)
{
tempListing2.Add(item.Key);
}
if (tempListing2.Count == 0)
{
return null;
}
else
{
return (object)tempListing2;
}
#endregion Listing code.
}
else if (tempFlag == "save_all")
{
#region save all connected players...
int savedCount = 0;
foreach (KeyValuePair<string, ConnectionInfo> item in allSocketInfo)
{
if (item.Value.isAlive == true && item.Value.loggedIn == true)
{ // if its true then lets save their file.
savedCount++;
string characterFilePath = characterPath + "\\" + item.Key.Substring(0, 1) + String.Format("\\{0}.cha", item.Key);
// open file to save current iterations Character.
FileStream OutputStream = new FileStream(characterFilePath, FileMode.Create, FileAccess.Write);
BinaryFormatter bFormatter = new BinaryFormatter();
// save the serialized class to a file.
bFormatter.Serialize(OutputStream, (Character)item.Value.characterStats("get_file", null));
item.Value.sendto(0, "\r\nYou have been saved.");
// tidy up, close file for use elsewhere, and get objects ready for reclaim.
OutputStream.Close();
OutputStream.Dispose();
OutputStream = null;
bFormatter = null;
}
}
return (object)savedCount;
#endregion save all connected players...
}
else if (tempFlag == "send_all")
{
// send a message to each socket in the list.
#region send all code...
foreach (KeyValuePair<string, ConnectionInfo> item in allSocketInfo)
{
// send a message to all connected regardless of where they are.
try
{
if (item.Value.loggedIn == true)
{
if ((string)objectOne != item.Key)
{
item.Value.sendto(0, (string)object_Two);
}
}
}
catch (Exception ex)
{
// would throw an exception if the connection/player disconnected we tried to send something too.
Console.WriteLine(ex.ToString());
}
}
return null;
#endregion send all code...
}
else if (tempFlag == "gossip")
{
// gossip channel
#region gossip code...
string gossipColor = colorBoldBlue; // what color we want gossip to be.
// prebuild gossiped message, with color, and without.
string gossMessageOthers = String.Format("\r\n{0} gossips, '{1}'\r\n", (string)objectOne, (string)object_Two);
string gossMessageSelf = String.Format("\r\nYou gossip, '{0}'\r\n", (string)object_Two);
string gossMessageOthers_col = gossipColor + gossMessageOthers + colorReset;
string gossMessageSelfCol = gossipColor + gossMessageSelf + colorReset;
foreach (KeyValuePair<string, ConnectionInfo> item in allSocketInfo)
{
try
{
if (item.Value.loggedIn == true)
{
// check if they are accepting gossip. and if they are logged in. if so, continue with determination.
if ((bool)item.Value.characterStats("get_gossip", null) == true)
{
// check if they are accepting color.
if ((bool)item.Value.characterStats("get_color", null) == true)
{
// self or other. show them color.
if ((string)objectOne != (string)item.Value.characterStats("get_name", null))
{
item.Value.sendto(0, gossMessageOthers_col);
}
else
{
item.Value.sendto(0, gossMessageSelfCol);
}
}
else
{
// not accepting color... show just text...
if ((string)objectOne != (string)item.Value.characterStats("get_name", null))
{
item.Value.sendto(0, gossMessageOthers);
}
else
{
item.Value.sendto(0, gossMessageSelf);
}
}
}
}
}
catch (Exception ex)
{
// would throw an exception if the connection/player disconnected we tried to send something too.
Console.WriteLine(ex.ToString());
}
}
return null;
#endregion gossip code...
}
else if (tempFlag == "shout")
{
// shout channel.
#region shout code...
string shoutColor = colorYellow;
// prebuild shout message, to self, and others, with and without color.
string shoutMessageSelf = String.Format("\r\nYou shout, '{0}'\r\n", (string)object_Two);
string shoutMessageOthers = String.Format("\r\n{0} shouts, '{1}'\r\n", (string)objectOne, (string)object_Two);
string shoutMessageSelfCol = shoutColor + shoutMessageSelf + colorReset;
string shoutMessageOthersCol = shoutColor + shoutMessageOthers + colorReset;
foreach (KeyValuePair<string, ConnectionInfo> item in allSocketInfo)
{
try
{
if (item.Value.loggedIn == true)
{
if ((bool)item.Value.characterStats("get_color", null) == true)
{ // show them color.
if ((string)objectOne != (string)item.Value.characterStats("get_name", null))
{
item.Value.sendto(0, shoutMessageOthersCol);
}
else
{
item.Value.sendto(0, shoutMessageSelfCol);
}
}
else
{
//show just text...
if ((string)objectOne != (string)item.Value.characterStats("get_name", null) && item.Value.loggedIn == true)
{
item.Value.sendto(0, shoutMessageOthers);
}
else
{
item.Value.sendto(0, shoutMessageSelf);
}
}
}
}
catch (Exception ex)
{ // would throw an exception if the connection/player disconnected we tried to send something too.
Console.WriteLine(ex.ToString());
}
} // end foreach
return null;
#endregion shout code...
}
else if (tempFlag == "tell")
{
#region tell code...
string tellfrom = (string)objectOne; // senders name.
string tellto = (string)object_Two; // recipients name.
if (tellfrom.ToLower() == tellto.ToLower())
{
return (object)"\r\nYou try to tell yourself something.\r\n";
}
else
{
tellto = tellto.Substring(0, 1).ToUpper() + tellto.Substring(1, tellto.Length - 1).ToLower();
tellfrom = tellfrom.Substring(0, 1).ToUpper() + tellfrom.Substring(1, tellfrom.Length - 1).ToLower();
ConnectionInfo tempValue;
if (allSocketInfo.TryGetValue(tellto.ToLower(), out tempValue) && tempValue.loggedIn == true)
{
string tellMessage = "\r\n" + tellfrom + " tells you, '" + (string)object_Three + "'";
if ((bool)tempValue.characterStats("get_color", null) == true)
{
tempValue.sendto(0, colorBoldGreen + tellMessage + colorReset);
}
else
{
tempValue.sendto(0, tellMessage);
}
return (object)"\r\nYou tell, '" + (string)object_Three + "' to " + tellto + ".";
}
else
{
return (object)"\r\nSorry noone here by the name of " + tellto + "\r\n";
}
}
#endregion tell code...
}
else
{
return null;
}
}
} // end AllSockets
#region help subroutines...
#endregion help subroutines...
#endregion Private Methods
#region properties...
#endregion properties...
}
}