Esempio n. 1
0
		/// <summary>
		/// Sends a chat message
		/// </summary>
		/// <param name="tag">The tag of the player sending a message. Can be null</param>
		/// <param name="message">The message</param>
		/// <param name="type">The message type</param>
		private void sendChatMessage(String tag, String message, MessageType type)
		{
			if (tag != null)
				message = clientList[tag].name + ": " + message;
			propogate(CSCommon.buildCMDString(CSCommon.cmd_chat, (byte)type, message), (tag != null) ? clientList[tag].client : null);
			output(LoggingLevels.chat, message);
		}
Esempio n. 2
0
		private void sendCriticalMessage() {
			if (String.IsNullOrEmpty(serverMessage))
				return;
			lock (serverMessage) {
				foreach (Player p in clientList.Values)
					CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_chat, (byte)MessageType.critical, serverMessage));
				serverMessage = "";
			}
		}
Esempio n. 3
0
		/// <summary>
		/// This method will periodically tick and check if a client has sent data.
		/// It will run on its own thread and is the main operation of the server.
		/// </summary>
		private void startMonitoringForData()
		{
			const int waitTime = 10;
			while (true) {
				try {
					if (returns.Count > 0)
						enterPendingPlayers();
					//pause();
					lock (lockObject) {
						modifiedClientList = false;
						foreach (String s in clientList.Keys) {
							if (!CSCommon.isLiveConnection(clientList[s].client)) {
								String name = clientList[s].name;
								removeFromGame(s, false, DisconnectMethod.midGame);
								sendMessage(name + " has been unexpectedly disconnected.", null);
							} else
								performCMDRCV(s, clientList[s].client);
							//In case player wanted to be disconnected
							if (modifiedClientList)
								break;
						}  //for
					} //lock
					if (!modifiedClientList)
						Thread.Sleep(waitTime);
					if (isGameEnd()) {
						output(LoggingLevels.debug, "Doing game ended routine");
						if (!forceGameEnd) //don't give points if team death player disconnected
							allocatePoints();
						else {
							if (reason == null)
								sendMessage("The game has ended.", null);
							else
								sendMessage("The game has ended because " + reason, null);
							propogate(CSCommon.buildCMDString(CSCommon.cmd_gameEnded), null);
							while (clientList.Count != 0) {
								foreach (String s in clientList.Keys) {
									removeFromGame(s, true, DisconnectMethod.midGame); //remove clients one by one
									break; //release enumerator
								} //foreach
							} //while
						} //if forced to end the game by server-side event.

						if (gameFinished != null)
							gameFinished(this);
						return;
					} //if game ended
					sendCriticalMessage();
				}
				catch (Exception e) {
					output(LoggingLevels.error, e.Message + e.StackTrace);
					setForceGameEnd("there was a problem with the game.");
				}
			} //while
		}
Esempio n. 4
0
		/// <summary>
		/// Creates a bot.
		/// </summary>
		/// <param name="creator">The tag of the player that will hold the bot's data initially.</param>
		/// <param name="objectType">The type of the bot.</param>
		private void createBot(String creator, ObjectType objectType) {
			String id = getBotID();
			String botName = "Bot " + id;
			String botId = "B-" + id;
			CSCommon.sendData(clientList[creator].client, CSCommon.buildCMDString(CSCommon.cmd_createBot, botId, botName, (byte)objectType));
			//Other players will just see another spawn.
			propogate(CSCommon.buildCMDString(CSCommon.cmd_distributeServerTag, botId, botName, (byte)objectType, (short)0), clientList[creator].client);
			if (objectType == ObjectType.aircraft)
				sendMessage(botName + " has been created.", null);
			bots.Add(new BotInfo(creator, botId, botName, objectType));
			bots.Sort();
		}
Esempio n. 5
0
		/// <summary>
		/// Pushes the bot to a new player, in the event the previous host was disconnected. The bots list will always be modified after this method runs. Call this method after removing the player.
		/// </summary>
		/// <param name="index">The position in bots to remove.</param>
		private void pushBot(int index) {
			String botID = bots[index].id;
			String botName = bots[index].name;
			ObjectType objectType = bots[index].objectType;
			if (clientList.Count == 0) {
				bots[index].creator = null;
				return;
			}

			String[] ids = clientList.Keys.ToArray();
			Random r = new Random();
			String pid = null; //ID of new host player for bot
			CSCommon.sendData(clientList[pid = ids[r.Next(0, ids.Length)]].client,
				CSCommon.buildCMDString(CSCommon.cmd_createBot, botID, botName, (byte)objectType));
			bots[index].creator = pid;
		}
Esempio n. 6
0
		/// <summary>
		/// Removes a player from this game. if disconnectFromServer == true, we'll assume player
		/// either did hard shutdown, or was dropped forcibly by the game because their connection timed out.
		/// In this case, we send cmd_forceDisconnect command to each client so they can get rid of that player's object.  Otherwise, we'll just put them back in the hangar.
		/// </summary>
		/// <param name="tag">The tag of the player to remove.</param>
		/// <param name="keepOnServer">If true, this player will not be dropped from the server.</param>
		/// <param name="d">The method by which this player is being disconnected. If the player was disconnected because they lost,
		/// this flag should be set to gameEnd. Otherwise, if the player hit escape or was dropped, this flag should be set to midGame.</param>
		private void removeFromGame(String tag, bool keepOnServer, DisconnectMethod d) {
			if (clientList[tag].host) //If this is the game host,
				forceGameEnd = true; //If they drop or disconnect, end the game.
			Server.returnFromGame(tag, clientList[tag], keepOnServer);
			clientList.Remove(tag);
			//In case this is a case where the client was disconnected without an in-game event,
			//IE: a connection drop, tell all clients that this object has disconnected so they can
			//clean it up.
			propogate(CSCommon.buildCMDString(CSCommon.cmd_forceDisconnect, tag), null);
			if (clientList.Count == 0)
				canEvaluateGameEnd = true;
			modifiedClientList = true;
			if (type == GameType.freeForAll)
				clearBotsFromPlayer(tag);
			//now game is unbalanced, so call it quit since players may cheat this way,
			//by starting a team death, disconnecting, and the other team gets all the points.
			//Or if there's a death match and only one player remains after this disconnect, just end the game since one player in a deth match is pointless!
			if (type == GameType.teamDeath && d == DisconnectMethod.midGame || type == GameType.oneOnOne && clientList.Count == 1)
				forceGameEnd = true;
		}
Esempio n. 7
0
		/// <summary>
		/// Sends a private message.
		/// </summary>
		/// <param name="target">The recipient of the message</param>
		/// <param name="message">The message to send</param>
		private void sendPrivateChatMessage(String target, String message) {
			Player p = getPlayerByID(target);
			if (p != null)
				CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_chat, (byte)MessageType.privateMessage, message));
		}
Esempio n. 8
0
		/// <summary>
		///    Sends a server message to all clients. To include everyone, send NULL to the exclude parameter.
		/// </summary>
		/// <param name="message">The message to send.</param>
		/// <param name="exclude">The client to exclude.</param>
		private void sendMessage(String message, TcpClient exclude) {
			propogate(CSCommon.buildCMDString(CSCommon.cmd_serverMessage, message),
			 exclude);
			output(message);
		}
Esempio n. 9
0
		/// <summary>
		/// gets data from the TCPClient passed and does a command based on the given data. This command could result in information being passed to other TCPClient objects, for instance if we've recieved information about an aircraft's state that needs to be propogated.
		/// </summary>
		/// <param name="tag">The GUID of the player to perform commands on</param>
		/// <param name="client">The player's TcpClient object</param>
		private void performCMDRCV(String tag, TcpClient client) {
			if (!CSCommon.isLiveConnection(client))
				return;
			MemoryStream stream = CSCommon.getData(client);
			if (stream == null)
				return;

			BinaryReader rcvData = new BinaryReader(stream);
			//rcvData is the list of serverCommands.
			sbyte c = 0;
			long start = 0L;
			byte command = 0;
			try {
				while (rcvData.BaseStream.Length > rcvData.BaseStream.Position) {
					start = rcvData.BaseStream.Position;
					c = rcvData.ReadSByte();
					if (c > 4)
						return;
					if (c == 1) {
						command = rcvData.ReadByte();

						switch (command) {
							case CSCommon.cmd_test:
								int testAmount = recordWin("6SRKJ695G", "ABCDEFGHI");
								CSCommon.sendData(client, CSCommon.buildCMDString(CSCommon.cmd_newval, testAmount));
								break;

							case CSCommon.cmd_createBot:
								//The player who creates the bot will spawn a thread to control them.
								createBot(tag, ObjectType.aircraft);
								break;

							case CSCommon.cmd_removeBot:
								String rBotId = removeBot(0);
								if (rBotId == null)
									break;
								sendMessage(rBotId + " has been dropped from the server", null);
								propogate(CSCommon.buildCMDString(CSCommon.cmd_forceDisconnect, rBotId), null);
								break;

							case CSCommon.cmd_whois:
								using (BinaryWriter whoWriter = new BinaryWriter(new MemoryStream())) {
									whoWriter.Write((short)clientList.Count);
									foreach (Player p in clientList.Values) {
										whoWriter.Write(p.tag);
										whoWriter.Write(p.name + ((p.admin) ? " (GM)" : ""));
									}
									CSCommon.sendResponse(client, whoWriter);
								} //using
								break;

							case CSCommon.cmd_requestStartGame:
								if (type == GameType.oneOnOne && clientList.Count == 2)
									gameStarted = true;
								if (type == GameType.teamDeath) {
									if (getNumberOfTeams() >= 2)
										gameStarted = true;
								} //if team death
								CSCommon.sendResponse(client, gameStarted);
								if (gameStarted) {
									propogate(CSCommon.buildCMDString(CSCommon.cmd_startGame), client);
								}
								break;

							case CSCommon.cmd_updatePoints:
								Player winner = getPlayerByID(rcvData.ReadString());
								if (winner == null) //winner logged off; kill doesn't count!
									break;
								//The client sending this command is the loser.
								int amount = recordWin(winner.tag, tag);
								CSCommon.sendData(winner.client, CSCommon.buildCMDString(CSCommon.cmd_newval, amount));
								break;

							case CSCommon.cmd_startGame:
								//Send cmd_startGame to all clients so they can
								//signal start locally.
								propogate(CSCommon.buildCMDString(CSCommon.cmd_startGame), client);
								break;

							case CSCommon.cmd_chat:
								bool isPrivate = rcvData.ReadBoolean();
								String chatMsg = null;
								if (isPrivate) {
									String recipient = rcvData.ReadString();
									chatMsg = clientList[tag].name + " (private): " + rcvData.ReadString();
									sendPrivateChatMessage(recipient, chatMsg);
								} else {
									chatMsg = rcvData.ReadString();
									sendChatMessage(tag, chatMsg, MessageType.normal);
								}
								break;

							case CSCommon.cmd_serverMessage:
								sendMessage(rcvData.ReadString(), client);
								break;

							case CSCommon.cmd_disconnectMe:
								String name = clientList[tag].name;
								removeFromGame(tag, true, DisconnectMethod.midGame);
								sendMessage(name + " has left the game.", null);
								return; //no need to process things further.

							case CSCommon.cmd_deleteFromGame: //silent exit
								removeFromGame(tag, true, DisconnectMethod.gameEnded); //delete will only be sent on successful game end
								return; //no need to process data further.
						} //switch
					} //if explicit command
					else {
						byte[] buffer = new byte[rcvData.ReadInt32()];
						string id = rcvData.ReadString();
						bool updateBot = false;
						int botIndex = 0;
						if (c == 3) {
							if ((botIndex = getBot(id)) > -1) {
								rcvData.ReadInt16(); //passed numArgs
								while (rcvData.ReadSByte() != 1) ;
								if (rcvData.ReadInt32() > 0)
									updateBot = true;
								else
									removeBot(botIndex);
							} //if bot exists
						} //if this is a bot update
						rcvData.BaseStream.Position = start;
						rcvData.BaseStream.Read(buffer, 0, buffer.Length);
						if (updateBot)
							bots[botIndex].data = buffer;
						propogate(buffer, client);
					} //if something else besides cmd_command.
				} //foreach serverCommand
			} catch (Exception e) {
				output("Error while reading data from " + tag + ". Char = " + c + Environment.NewLine + "Last command: " + command + Environment.NewLine + "Stack trace: " + e.Message + e.StackTrace);
			} //catch
		}
Esempio n. 10
0
		/// <summary>
		/// This method will add a new player to this game.
		/// </summary>
		/// <param name="tag">The server tag of the player being added</param>
		/// <param name="p">The Player object representing the connection.</param>
		private bool add(String tag, Player p) {
			try {
				//pauseProcessing();
				output("Adding player " + tag + "...");
				lock (lockObject) {
					if (clientList.Count == 0 && type != GameType.freeForAll) //This is first player being added, so this is the host.
						p.host = true;
					//Create local player.
					if (p.entryMode != 1) {
						int maxWeight = 0;
						CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_position, next++, (short)0));
						CSCommon.sendData(p.client,
						  CSCommon.buildCMDString(CSCommon.cmd_requestCreate, p.name, maxWeight));

						//Give this player's info to all players.
						output("Propogating connection...", true);
						if (type != GameType.teamDeath) {
							propogate(CSCommon.buildCMDString(CSCommon.cmd_distributeServerTag, tag, p.name, (byte)ObjectType.aircraft, (short)0),
							 p.client);
						} else { //if team death
							propogate(CSCommon.buildCMDString(CSCommon.cmd_distributeServerTag, tag, p.name, (byte)ObjectType.aircraft, (int)p.team, (short)0),
					  p.client);
						}
					} //if entryMode != 1

					//Give this player info about all other players.
					output("Sending info about other clients to this client...", true);
					foreach (Player player in clientList.Values) {
						if (player.entryMode == 1)  //spectator
							continue;
						if (type != GameType.teamDeath) {
							CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_distributeServerTag, player.tag, player.name, (byte)ObjectType.aircraft, (short)0));
						} else { //if team death
							CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_distributeServerTag, player.tag, player.name, (byte)ObjectType.aircraft,
								(int)player.team, (short)0));
						}
					} //foreach connected player

					foreach (BotInfo info in bots) {
						if (info.creator == null) {
							info.creator = tag;
							CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_createBot, info.id, info.name, (byte)info.objectType));
							CSCommon.sendData(p.client, new MemoryStream(info.data));
							output("Created bot " + info.id, true);
						} else
							CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_distributeServerTag, info.id, info.name, (byte)info.objectType,
								(short)0));
					}
					if (type == GameType.freeForAll) {
						output("FFA, Starting local player...", true);
						CSCommon.sendData(p.client, CSCommon.buildCMDString(CSCommon.cmd_startGame));
					} //if FFA
					clientList[tag] = p;
					if (type == GameType.teamDeath)
						incrementTeam(tag, p.team);

					String entMessage = ".";
					if (type == GameType.teamDeath)
						entMessage = " for the " + p.team + " team";
					sendMessage(clientList[tag].name +
						String.Format(" has joined this game{0}",
						(p.entryMode == 1) ? " as a spectator" : entMessage),
					   p.client);
				} //lock
				if (type != GameType.freeForAll && !canEvaluateGameEnd
					&& (type == GameType.teamDeath && getNumberOfTeams() >= 2 || type != GameType.teamDeath))
					canEvaluateGameEnd = true;
				//resumeProcessing();
				return true;
			} catch (Exception e) {
				output(e.Message + Environment.NewLine + e.StackTrace);
			}
			return false;
		}