/// <summary> /// Entry point for all commands execution. /// </summary> /// <param name="current"> Current session.</param> /// <param name="sessions">Collection of all sessions.</param> /// <param name="value">Message sent by chat cient.</param> internal static void HandleGameMessage(GameService current, GameSessions sessions, string value) { string command = string.Empty; string commandArgs = string.Empty; var message = value; var index = message.IndexOf(":", StringComparison.OrdinalIgnoreCase); if (index > 0) { command = message.Substring(0, index); commandArgs = message.Substring(index + 1, message.Length - index - 1); } else { command = message; } Logger.LogMessage(command); Logger.LogMessage(commandArgs); IGameCommand handler = null; if (commands.TryGetValue(command, out handler)) { handler.Execute(current, sessions, commandArgs); } }
/// <summary> /// Sends the message to the destination service. /// </summary> /// <param name="destinationService">Destination Service.</param> /// <param name="value">Message to be sent.</param> /// <param name="defunctList">List of defucnt services.</param> public static void Send(GameService destinationService, string value, List<GameService> defunctList) { try { destinationService.SendMessage(value); } catch { if (null == defunctList) { defunctList = new List<GameService>(); } defunctList.Add(destinationService); } }
/// <summary> /// Broadcasts message to all sessions after sending messages to the both associated sessions (Buddy pair). /// Then it also broacasts messages to all other session based on the the response type so that they can update /// their's buddyList. /// </summary> /// <param name="responseType">Broadcast message type.</param> /// <param name="currentService">Current service instance.</param> /// <param name="destinationService">Destination service instance.</param> /// <param name="responseToCurrentService">Message to be sent to the currentService.</param> /// <param name="responseToDestinationservice">Message to be sent to the destinationService.</param> public void BroadcastMessage(BroadcastMessageType responseType, GameService currentService, GameService destinationService, string responseToCurrentService, string responseToDestinationservice) { if (null != currentService) { this.SendMessage(currentService, responseToCurrentService); } if (null != destinationService) { this.SendMessage(destinationService, responseToDestinationservice); } List<GameService> defunctServiceList = null; // Now also send this to other players who are not playing. this.thisLock.EnterReadLock(); try { foreach (var service in this.innerCache) { // Find out logged in users excluding destination service. if (!string.IsNullOrEmpty(service.Context.LogOnName) && service != currentService && service != destinationService) { switch (responseType) { case BroadcastMessageType.LogOnResponse: if (null == service.Context.BuddyInstance) { Send(service, "JoinBuddyList:" + currentService.Context.LogOnName, defunctServiceList); } break; case BroadcastMessageType.SelectBuddyResponse: if (null == service.Context.BuddyInstance) { Send(service, "RemoveFromBuddyList:" + currentService.Context.LogOnName + ";" + destinationService.Context.LogOnName, defunctServiceList); } break; case BroadcastMessageType.GameCompleteResponse: if (null == service.Context.BuddyInstance) { Send(service, "JoinBuddyList:" + currentService.Context.LogOnName + ";" + destinationService.Context.LogOnName, defunctServiceList); } break; case BroadcastMessageType.LogOffResponse: // Now this string has \" char at front and back both. string[] defunctServiceResponse = responseToCurrentService.ToString().Split(new char[] { ':' }); // Remove quotes from the end of this string. string defunctServiceName = defunctServiceResponse[1].Substring(0, defunctServiceResponse[1].Length - 1); Send(service, "RemoveFromBuddyList:" + defunctServiceName, defunctServiceList); // Also tell services to join defunct's buddy in their buddyList as it is no more playing with anyone. if ((null != currentService) && !string.IsNullOrEmpty(currentService.Context.LogOnName)) { Send(service, "JoinBuddyList:" + currentService.Context.LogOnName, defunctServiceList); } break; } } } } finally { this.thisLock.ExitReadLock(); } // Now look at the defunctService list and take te appropriate action. if (null != defunctServiceList) { // Each pair is made of service name and it's buddy service instance. Dictionary<string, GameService> defunctBuddyPairs = null; this.thisLock.EnterWriteLock(); try { foreach (var entry in defunctServiceList) { GameService buddyInstance = entry.Context.BuddyInstance; string defunctName = entry.Context.LogOnName; this.innerCache.Remove(entry); if (null != buddyInstance && !string.IsNullOrEmpty(defunctName)) { if (null == defunctBuddyPairs) { defunctBuddyPairs = new Dictionary<string, GameService>(); } defunctBuddyPairs.Add(defunctName, buddyInstance); } } } finally { this.thisLock.ExitWriteLock(); } if (null != defunctBuddyPairs) { foreach (KeyValuePair<string, GameService> buddyPair in defunctBuddyPairs) { this.RemoveBuddyPair(buddyPair.Key, buddyPair.Value); } } } }
/// <summary> /// Attempting to add another session to the collection. /// </summary> /// <param name="entry">Session to add.</param> /// <returns>true if session was added; false otherwise.</returns> public bool TryAdd(GameService entry) { this.thisLock.EnterUpgradeableReadLock(); try { if (this.innerCache.Contains(entry)) { return false; } this.thisLock.EnterWriteLock(); try { this.innerCache.Add(entry); return true; } finally { this.thisLock.ExitWriteLock(); } } finally { this.thisLock.ExitUpgradeableReadLock(); } }
/// <summary> /// Sends message to destination service. /// </summary> /// <param name="destinationService">Destination service.</param> /// <param name="value">Message to be sent.</param> public void SendMessage(GameService destinationService, string value) { GameService defunct = null; try { destinationService.SendMessage(value); } catch { if (defunct == null) { defunct = destinationService; } } if (defunct != null) { GameService buddyInstance = defunct.Context.BuddyInstance; string defunctName = defunct.Context.LogOnName; this.thisLock.EnterWriteLock(); try { this.innerCache.Remove(defunct); } finally { this.thisLock.ExitWriteLock(); } this.RemoveBuddyPair(defunctName, buddyInstance); } }
/// <summary> /// Updates the buddyInstance of died service and broadcasts to all other sessions that /// this service died so that they can take appropriate action. /// </summary> /// <param name="defunctName">Service name.</param> /// <param name="buddyInstance">Buddy Service instance.</param> public void RemoveBuddyPair(string defunctName, GameService buddyInstance) { // If there is any buddyinstance in the destination service's context // then modify buddyinstance's context properly. if (null != buddyInstance) { buddyInstance.Context.BuddyInstance = null; } // Only broadcast for logged on users. if (!string.IsNullOrEmpty(defunctName)) { this.BroadcastMessage(BroadcastMessageType.LogOffResponse, buddyInstance, null, "BuddyDied:" + defunctName, null); } }
/// <summary> /// Attempting to remove a session from the collection. /// </summary> /// <param name="entry">Session to remove.</param> public void Remove(GameService entry) { ThreadPool.QueueUserWorkItem(new WaitCallback(this.RemoveInternal), entry); }
/// <summary> /// Get seesion list except the current session. /// </summary> /// <param name="current">Current session.</param> /// <returns>List of other player names.</returns> public string GetOtherLoggedInSessionsList(GameService current) { string players = null; this.thisLock.EnterReadLock(); try { foreach (var service in this.innerCache) { // Find out logged in users excluding myself. if (!string.IsNullOrEmpty(service.Context.LogOnName) && service != current) { if (null == service.Context.BuddyInstance) { players += string.Format(CultureInfo.InvariantCulture, "{0};", service.Context.LogOnName); } } } } finally { this.thisLock.ExitReadLock(); } return players; }
/// <summary> /// Broadcasts message to all sessions after sending messages to the both associated sessions (Buddy pair). /// Then it also broacasts messages to all other session based on the the response type so that they can update /// their's buddyList. /// </summary> /// <param name="responseType">Broadcast message type.</param> /// <param name="currentService">Current service instance.</param> /// <param name="destinationService">Destination service instance.</param> /// <param name="responseToCurrentService">Message to be sent to the currentService.</param> /// <param name="responseToDestinationservice">Message to be sent to the destinationService.</param> public void BroadcastMessage(BroadcastMessageType responseType, GameService currentService, GameService destinationService, string responseToCurrentService, string responseToDestinationservice) { if (null != currentService) { this.SendMessage(currentService, responseToCurrentService); } if (null != destinationService) { this.SendMessage(destinationService, responseToDestinationservice); } List <GameService> defunctServiceList = null; // Now also send this to other players who are not playing. this.thisLock.EnterReadLock(); try { foreach (var service in this.innerCache) { // Find out logged in users excluding destination service. if (!string.IsNullOrEmpty(service.Context.LogOnName) && service != currentService && service != destinationService) { switch (responseType) { case BroadcastMessageType.LogOnResponse: if (null == service.Context.BuddyInstance) { Send(service, "JoinBuddyList:" + currentService.Context.LogOnName, defunctServiceList); } break; case BroadcastMessageType.SelectBuddyResponse: if (null == service.Context.BuddyInstance) { Send(service, "RemoveFromBuddyList:" + currentService.Context.LogOnName + ";" + destinationService.Context.LogOnName, defunctServiceList); } break; case BroadcastMessageType.GameCompleteResponse: if (null == service.Context.BuddyInstance) { Send(service, "JoinBuddyList:" + currentService.Context.LogOnName + ";" + destinationService.Context.LogOnName, defunctServiceList); } break; case BroadcastMessageType.LogOffResponse: // Now this string has \" char at front and back both. string[] defunctServiceResponse = responseToCurrentService.ToString().Split(new char[] { ':' }); // Remove quotes from the end of this string. string defunctServiceName = defunctServiceResponse[1].Substring(0, defunctServiceResponse[1].Length - 1); Send(service, "RemoveFromBuddyList:" + defunctServiceName, defunctServiceList); // Also tell services to join defunct's buddy in their buddyList as it is no more playing with anyone. if ((null != currentService) && !string.IsNullOrEmpty(currentService.Context.LogOnName)) { Send(service, "JoinBuddyList:" + currentService.Context.LogOnName, defunctServiceList); } break; } } } } finally { this.thisLock.ExitReadLock(); } // Now look at the defunctService list and take te appropriate action. if (null != defunctServiceList) { // Each pair is made of service name and it's buddy service instance. Dictionary <string, GameService> defunctBuddyPairs = null; this.thisLock.EnterWriteLock(); try { foreach (var entry in defunctServiceList) { GameService buddyInstance = entry.Context.BuddyInstance; string defunctName = entry.Context.LogOnName; this.innerCache.Remove(entry); if (null != buddyInstance && !string.IsNullOrEmpty(defunctName)) { if (null == defunctBuddyPairs) { defunctBuddyPairs = new Dictionary <string, GameService>(); } defunctBuddyPairs.Add(defunctName, buddyInstance); } } } finally { this.thisLock.ExitWriteLock(); } if (null != defunctBuddyPairs) { foreach (KeyValuePair <string, GameService> buddyPair in defunctBuddyPairs) { this.RemoveBuddyPair(buddyPair.Key, buddyPair.Value); } } } }
/// <summary> /// Attempting to remove a session from the collection. /// </summary> /// <param name="entry">Session to remove.</param> public void Remove(GameService entry) { ThreadPool.QueueUserWorkItem(new WaitCallback(this.RemoveInternal), entry); }