/// <summary> /// Gathers the cards in the specified rectangle. /// </summary> /// <param name="gatheringRectangle">The gathering rectangle.</param> public void GatherCards(Rectangle gatheringRectangle) { SharedObject gatheringStackSharedObject = null; for (int i = ZOrderListOfSharedObjects.Count - 1; i >= 0; i--) { SharedObject sharedObject = ZOrderListOfSharedObjects[i]; if (gatheringRectangle.Contains(sharedObject.Rectangle) && sharedObject.GrabberName == null && sharedObject.GameElements.First() is Card) { gatheringStackSharedObject = sharedObject; break; } } if (gatheringStackSharedObject != null) { gatheringStackSharedObject.SetAllCardsSameFace(false); List <SharedObject> listSharedObjectsToGather = new List <SharedObject>(); for (int i = ZOrderListOfSharedObjects.Count - 1; i >= 0; i--) { SharedObject sharedObject = ZOrderListOfSharedObjects[i]; if (gatheringRectangle.Contains(sharedObject.Rectangle) && sharedObject.GrabberName == null && sharedObject.GameElements.First() is Card && sharedObject != gatheringStackSharedObject) { sharedObject.SetAllCardsSameFace(false); listSharedObjectsToGather.Add(sharedObject); } } foreach (SharedObject sharedObject in listSharedObjectsToGather) { GatherCards(sharedObject, gatheringStackSharedObject); } // gatheringStackSharedObject.Shuffle(); // Broadcast the gathering shared object move event: StateChangeEventDataType stateChangeEventDataType = new StateChangeEventDataType(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = gatheringStackSharedObject.Id; stateChangeEventDataType.NewSharedObjectLocation = gatheringStackSharedObject.Location; stateChangeEventDataType.SharedObjectSize = gatheringStackSharedObject.Rectangle.Size; stateChangeEventDataType.NewSharedObjectPicture = gatheringStackSharedObject.Picture; ScgBroadcastorService.BroadcastStateChange(stateChangeEventDataType, null, null); } }
/// <summary> /// Gathers the cards of sharedObject in the GameElments of gatheringObject. /// </summary> /// <param name="sharedObject">The shared object.</param> /// <param name="gatheringObject">The gathering object.</param> public void GatherCards(SharedObject sharedObject, SharedObject gatheringObject) { if (sharedObject.GameElements.First() is Card && gatheringObject.GameElements.First() is Card) { if (gatheringObject.GameElements.Count == 1) { // The gathering object was a single card. Change its size for a stack of cards: gatheringObject.Rectangle = new Rectangle(gatheringObject.Rectangle.X, gatheringObject.Rectangle.Y, DimXStackOfCards, DimYStackOfCards); // and apply again magnetic grid: gatheringObject.Rectangle = new Rectangle(GetMagneticLocation(gatheringObject.Rectangle), gatheringObject.Rectangle.Size); } // Transfer the cards: try { foreach (Card card in sharedObject.GameElements) { gatheringObject.GameElements.Insert(0, card); } } catch (Exception ex) { ScgBroadcastorService.LogError(string.Format("Unexpected exception '{0}' in GameState.GatherCards in foreach loop doing gatheringObject.GameElements.Add(card);", ex.Message), 97); throw; } // Broadcast the gathering shared object move event: StateChangeEventDataType stateChangeEventDataType = new StateChangeEventDataType(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = gatheringObject.Id; stateChangeEventDataType.NewSharedObjectLocation = gatheringObject.Location; stateChangeEventDataType.SharedObjectSize = gatheringObject.Rectangle.Size; stateChangeEventDataType.NewSharedObjectPicture = gatheringObject.Picture; ScgBroadcastorService.BroadcastStateChange(stateChangeEventDataType, null, null); // Remove the source shared object and broadcast the dispose event: ZOrderListOfSharedObjects.Remove(sharedObject); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.DisposeSharedObject; stateChangeEventDataType.SharedObjectId = sharedObject.Id; ScgBroadcastorService.BroadcastStateChange(stateChangeEventDataType, null, null); } }
/// <summary> /// Gathers the cards in the specified rectangle. /// </summary> /// <param name="gatheringRectangle">The gathering rectangle.</param> public void GatherCards(Rectangle gatheringRectangle) { SharedObject gatheringStackSharedObject = null; for (int i = ZOrderListOfSharedObjects.Count - 1; i >= 0; i--) { SharedObject sharedObject = ZOrderListOfSharedObjects[i]; if (gatheringRectangle.Contains(sharedObject.Rectangle) && sharedObject.GrabberName == null && sharedObject.GameElements.First() is Card) { gatheringStackSharedObject = sharedObject; break; } } if (gatheringStackSharedObject != null) { gatheringStackSharedObject.SetAllCardsSameFace(false); List<SharedObject> listSharedObjectsToGather = new List<SharedObject>(); for (int i = ZOrderListOfSharedObjects.Count - 1; i >= 0; i--) { SharedObject sharedObject = ZOrderListOfSharedObjects[i]; if (gatheringRectangle.Contains(sharedObject.Rectangle) && sharedObject.GrabberName == null && sharedObject.GameElements.First() is Card && sharedObject != gatheringStackSharedObject) { sharedObject.SetAllCardsSameFace(false); listSharedObjectsToGather.Add(sharedObject); } } foreach (SharedObject sharedObject in listSharedObjectsToGather) { GatherCards(sharedObject, gatheringStackSharedObject); } // gatheringStackSharedObject.Shuffle(); // Broadcast the gathering shared object move event: StateChangeEventDataType stateChangeEventDataType = new StateChangeEventDataType(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = gatheringStackSharedObject.Id; stateChangeEventDataType.NewSharedObjectLocation = gatheringStackSharedObject.Location; stateChangeEventDataType.SharedObjectSize = gatheringStackSharedObject.Rectangle.Size; stateChangeEventDataType.NewSharedObjectPicture = gatheringStackSharedObject.Picture; ScgBroadcastorService.BroadcastStateChange(stateChangeEventDataType, null, null); } }
/// <summary> /// Notifies the server command. /// (Will be remotely called by the clients) /// </summary> /// <param name="clientCommandData">The client command data.</param> public void NotifyServerCmd(ClientCommandDataType clientCommandData) { // Handle the received mouseEventData and update the State of the Shared Card Game: switch (clientCommandData.ClientCommandType) { case ClientCommandType.LeavingCmd: lock (ClientsLocker) { LogInfo( string.Format("NotifyServerCmd (LeavingCmd, clientCommandData.ClientName = '{0}')", clientCommandData.ClientName), 10); Client leavingClient; var foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out leavingClient); if (foundTheClient) { // Free a possible grabbed object by the leaving client: if (leavingClient.GrabbedSharedObject != null) { leavingClient.GrabbedSharedObject.GrabberName = null; leavingClient.GrabbedSharedObject. ContextualMenuOpened = false; } Clients.Remove(leavingClient.Name); LogInfo(string.Format("_clients.Remove(leavingClient.Name = '{0}')", leavingClient.Name), 11); // Remove the private area of the inactive client var removedSharedObjectId = _gameState.RemovePrivateArea(leavingClient.Name); // Note: The removedSharedObjectId should be >= 0 if (removedSharedObjectId >= 0) { // Inform other existing clients of the disposed PrivateArea id: foreach (var client in Clients) { // Prepare StateChangeEventDataType: var stateChangeEventDataType = new StateChangeEventDataType(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.DisposeSharedObject; stateChangeEventDataType.SharedObjectId = removedSharedObjectId; stateChangeEventDataType.PrivateOwnerClientName = leavingClient.Name; // Send the StateChangeEventDataType to the client: client.Value.ScgBroadcastorCallBack.BroadcastToClient( stateChangeEventDataType); LogInfo( string.Format( "BroadcastToClient'{0}'(DisposeSharedObject, removedSharedObjectId = '{1}')", client.Value.Name, removedSharedObjectId), 12); } } } } break; case ClientCommandType.GatheringCmd: lock (GameStateLocker) { Rectangle gatheringRectangle = clientCommandData.TargetRectangle; LogInfo(string.Format("NotifyServerCmd (GatheringCmd, clientCommandData.ClientName = '{0} gatheringRectangle = [Location={1},Size={2}]')", clientCommandData.ClientName, gatheringRectangle.Location, gatheringRectangle.Size), 20); try { _gameState.GatherCards(gatheringRectangle); } catch (Exception ex) { LogError(string.Format("Unexpected exception '{0}' raised in NotifyServerCmd(GatheringCmd) handling when calling _gameState.GatherCards(gatheringRectangle)", ex.Message), 98); throw; } } break; case ClientCommandType.RequestDealingParametersCmd: lock (GameStateLocker) { SharedObject stackOfCards = _gameState.GetSharedObjectFromId(clientCommandData.SharedObjectId); LogInfo( string.Format( "NotifyServerCmd (RequestDealingParametersCmd, clientCommandData.ClientName = '{0}', clientCommandData.SharedObjectId = '{1}')", clientCommandData.ClientName, clientCommandData.SharedObjectId), 31); if (stackOfCards != null && stackOfCards.GameElements.First() is Card && stackOfCards.GrabberName == null) { Client theClient; bool foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out theClient); if (foundTheClient && theClient != null) { // Do the specific stuff here: // Prepare and send state change for the clicked stack of cards shared object: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.OpenDealingParametersDialog; stateChange.SharedObjectId = stackOfCards.Id; stateChange.GrabbingClientName = clientCommandData.ClientName; stateChange.ReleasingClientName = null; stateChange.PrivateOwnerClientName = null; stateChange.DealingClockwise = DealingClockwise; stateChange.NumberOfCardsToDeal = NumberOfCardsToDeal; LogInfo( "Broadcasting state change (OpenDealingParametersDialog) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // Prepare and send state change for the clicked stack of cards shared object: stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = clientCommandData.ClientName; stateChange.ReleasingClientName = null; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // The stackOfCards is again grabbed: stackOfCards.GrabberName = clientCommandData.ClientName; stackOfCards.ContextualMenuOpened = false; theClient.GrabbedSharedObject = stackOfCards; } } } break; case ClientCommandType.CancelDealingParametersDialogCmd: lock (GameStateLocker) { SharedObject stackOfCards = _gameState.GetSharedObjectFromId(clientCommandData.SharedObjectId); LogInfo( string.Format( "NotifyServerCmd (CancelDealingParametersDialogCmdl, clientCommandData.ClientName = '{0}', clientCommandData.SharedObjectId = '{1}')", clientCommandData.ClientName, clientCommandData.SharedObjectId), 31); if (stackOfCards != null && stackOfCards.GameElements.First() is Card) { Client theClient; bool foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out theClient); if (foundTheClient && theClient != null) { // Do the specific stuff here: // Prepare and send state change for the clicked stack of cards shared object: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.ReleasingClientName = clientCommandData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // The stackOfCards is no more grabbed: stackOfCards.GrabberName = null; stackOfCards.ContextualMenuOpened = false; theClient.GrabbedSharedObject = null; } } } break; case ClientCommandType.ExtractFirstCardCmd: lock (GameStateLocker) { SharedObject stackOfCards = _gameState.GetSharedObjectFromId(clientCommandData.SharedObjectId); LogInfo( string.Format("NotifyServerCmd (ExtractFirstCardCmd, clientCommandData.ClientName = '{0}', clientCommandData.SharedObjectId = '{1}')", clientCommandData.ClientName, clientCommandData.SharedObjectId), 31); if (stackOfCards != null && stackOfCards.GameElements.First() is Card) { // Check that no card is already present at the extraction location; Point extractLocation = new Point(stackOfCards.Location.X + stackOfCards.Rectangle.Width / 2 - ScgGameState.MagneticGridStep - ScgGameState.DimXCard, stackOfCards.Location.Y + stackOfCards.Rectangle.Height / 2 - ScgGameState.MagneticGridStep - ScgGameState.DimYCard); // Vérifier l'extract location !!! SharedObject otherObject = _gameState.GetSharedObjectAt(extractLocation); if (!(otherObject != null && otherObject.GameElements.First() is Card && otherObject.Location.Equals(extractLocation))) { LogInfo(string.Format("OK, the extraction Location is free ! clientCommandData.ClientName='{0}'", clientCommandData.ClientName), 97); Client theClient; bool foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out theClient); if (foundTheClient && theClient != null) { // Extract the top most card and create a new shared object: Card extractedCard = (Card) stackOfCards.GameElements.First(); stackOfCards.GameElements.RemoveAt(0); // Create a new shared object for the extracted card: SharedObject newSharedObject = new SharedObject(_gameState.ZOrderListOfSharedObjects, _gameState.GetFreeId(), new Rectangle( new Point( stackOfCards.Location.X - ScgGameState.MagneticGridStep, stackOfCards.Location.Y - ScgGameState.MagneticGridStep), new Size(ScgGameState.DimXCard, ScgGameState.DimYCard)), null, new List<GameElement>()); newSharedObject.GameElements.Add(extractedCard); if (stackOfCards.GameElements.Count == 1) { // Resize the clickedSharedObject which owns now a single card: stackOfCards.Rectangle = new Rectangle(stackOfCards.Location, new Size(ScgGameState.DimXCard, ScgGameState.DimYCard)); // Apply magnetic grid: stackOfCards.Rectangle = new Rectangle( ScgGameState.GetMagneticLocation( stackOfCards.Rectangle), stackOfCards.Rectangle.Size); } // The stackOfCards is no more grabbed: stackOfCards.GrabberName = null; stackOfCards.ContextualMenuOpened = false; // Prepare and send state change for the clicked shared object: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.ReleasingClientName = clientCommandData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // Add the new Shared object to the ZOrderList: _gameState.ZOrderListOfSharedObjects.Insert(0, newSharedObject); // Prepare sending the state change for the new Shared object: stateChange.StateChangeEventType = StateChangeEventType.NewSharedObject; stateChange.SharedObjectId = newSharedObject.Id; stateChange.NewSharedObjectPicture = newSharedObject.Picture; stateChange.NewSharedObjectLocation = newSharedObject.Location; stateChange.SharedObjectSize = newSharedObject.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.PrivateOwnerClientName = null; LogInfo( string.Format("Broadcasting state change (NewSharedObject) for the extracted card shared object (newSharedObject.Id ={0})",newSharedObject.Id),95); BroadcastStateChange(stateChange, null, null); // Mark the new object as not grabbed: newSharedObject.GrabberName = null; theClient.GrabbedSharedObject = null; newSharedObject.BringToFront(); } } else { LogWarning(string.Format("NOT OK, the extraction Location is not free ! clientCommandData.ClientName='{0}'", clientCommandData.ClientName), 97); } } } break; case ClientCommandType.CountCardsCmd: lock (GameStateLocker) { SharedObject stackOfCards = _gameState.GetSharedObjectFromId(clientCommandData.SharedObjectId); LogInfo( string.Format( "NotifyServerCmd (CountCardsCmd clientCommandData.ClientName = '{0}', clientCommandData.SharedObjectId = '{1}')", clientCommandData.ClientName, clientCommandData.SharedObjectId), 31); if (stackOfCards != null && stackOfCards.GameElements.First() is Card) { Client theClient; bool foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out theClient); if (foundTheClient && theClient != null) { // Do the specific stuff here: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.ShowMessage; stateChange.SharedObjectId = stackOfCards.Id; stateChange.RecipientClientName = clientCommandData.ClientName; stateChange.ToEveryone = false; stateChange.MessageToDisplay = string.Format("This deck includes {0} cards.", stackOfCards.GameElements.Count); stateChange.MessageBoxTitle = "Deck Card Count"; LogInfo( "Broadcasting state change (ShowMessage) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // Prepare and send state change for the clicked stack of cards shared object: stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.ReleasingClientName = clientCommandData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // The stackOfCards is no more grabbed: stackOfCards.GrabberName = null; stackOfCards.ContextualMenuOpened = false; theClient.GrabbedSharedObject = null; } } } break; case ClientCommandType.DealCmd: lock (GameStateLocker) { SharedObject stackOfCards = _gameState.GetSharedObjectFromId(clientCommandData.SharedObjectId); LogInfo( string.Format( "NotifyServerCmd (DealCmd, clientCommandData.ClientName = '{0}', clientCommandData.SharedObjectId = '{1}')", clientCommandData.ClientName, clientCommandData.SharedObjectId), 31); if (stackOfCards != null && stackOfCards.GameElements.First() is Card) { Client theDealerClient; bool foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out theDealerClient); if (foundTheClient && theDealerClient != null) { // Do the specific stuff here: DealingClockwise = clientCommandData.DealingClockwise; NumberOfCardsToDeal = clientCommandData.NumberOfCardsToDeal; //DO THE DEALING: TO BE COMPLETED // Code issued from ExtractFirstCard as reference // Extract the top most card and create a new shared object: Card extractedCard = (Card)stackOfCards.GameElements.First(); stackOfCards.GameElements.RemoveAt(0); // Create a new shared object for the extracted card: SharedObject newSharedObject = new SharedObject(_gameState.ZOrderListOfSharedObjects, _gameState.GetFreeId(), new Rectangle( new Point( stackOfCards.Location.X - ScgGameState.MagneticGridStep, stackOfCards.Location.Y - ScgGameState.MagneticGridStep), new Size(ScgGameState.DimXCard, ScgGameState.DimYCard)), null, new List<GameElement>()); newSharedObject.GameElements.Add(extractedCard); if (stackOfCards.GameElements.Count == 1) { // Resize the clickedSharedObject which owns now a single card: stackOfCards.Rectangle = new Rectangle(stackOfCards.Location, new Size(ScgGameState.DimXCard, ScgGameState.DimYCard)); // Apply magnetic grid: stackOfCards.Rectangle = new Rectangle( ScgGameState.GetMagneticLocation( stackOfCards.Rectangle), stackOfCards.Rectangle.Size); } // The stackOfCards is no more grabbed: stackOfCards.GrabberName = null; stackOfCards.ContextualMenuOpened = false; // Prepare and send state change for the clicked shared object: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.ReleasingClientName = clientCommandData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // Add the new Shared object to the ZOrderList: _gameState.ZOrderListOfSharedObjects.Insert(0, newSharedObject); // Prepare sending the state change for the new Shared object: stateChange.StateChangeEventType = StateChangeEventType.NewSharedObject; stateChange.SharedObjectId = newSharedObject.Id; stateChange.NewSharedObjectPicture = newSharedObject.Picture; stateChange.NewSharedObjectLocation = newSharedObject.Location; stateChange.SharedObjectSize = newSharedObject.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.PrivateOwnerClientName = null; LogInfo( string.Format("Broadcasting state change (NewSharedObject) for the extracted card shared object (newSharedObject.Id ={0})", newSharedObject.Id), 95); BroadcastStateChange(stateChange, null, null); // Prepare and send state change for the clicked stack of cards shared object: stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.ReleasingClientName = clientCommandData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // The stackOfCards is no more grabbed: stackOfCards.GrabberName = null; stackOfCards.ContextualMenuOpened = false; theDealerClient.GrabbedSharedObject = null; } } } break; case ClientCommandType.ShuffleUpCmd: lock (GameStateLocker) { SharedObject stackOfCards = _gameState.GetSharedObjectFromId(clientCommandData.SharedObjectId); LogInfo( string.Format( "NotifyServerCmd (ShuffleUpCmd, clientCommandData.ClientName = '{0}', clientCommandData.SharedObjectId = '{1}')", clientCommandData.ClientName, clientCommandData.SharedObjectId), 31); if (stackOfCards != null && stackOfCards.GameElements.First() is Card) { Client theClient; bool foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out theClient); if (foundTheClient && theClient != null) { // Do the specific stuff here: stackOfCards.Shuffle(); // Prepare and send state change for the clicked stack of cards shared object: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.ReleasingClientName = clientCommandData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // The stackOfCards is no more grabbed: stackOfCards.GrabberName = null; stackOfCards.ContextualMenuOpened = false; theClient.GrabbedSharedObject = null; } } } break; case ClientCommandType.ContextualMenuClosedCmd: lock (GameStateLocker) { SharedObject stackOfCards = _gameState.GetSharedObjectFromId(clientCommandData.SharedObjectId); LogInfo( string.Format( "NotifyServerCmd (ContextualMenuClosedCmd, clientCommandData.ClientName = '{0}', clientCommandData.SharedObjectId = '{1}')", clientCommandData.ClientName, clientCommandData.SharedObjectId), 31); if (stackOfCards != null && stackOfCards.GameElements.First() is Card) { Client theClient; bool foundTheClient = Clients.TryGetValue(clientCommandData.ClientName, out theClient); if (foundTheClient && theClient != null && theClient.GrabbedSharedObject != null && theClient.GrabbedSharedObject.Id == stackOfCards.Id) { // Do the specific stuff here: // Nothing to do. // Prepare and send state change for the clicked stack of cards shared object: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChange.SharedObjectId = stackOfCards.Id; stateChange.NewSharedObjectPicture = stackOfCards.Picture; stateChange.NewSharedObjectLocation = stackOfCards.Location; stateChange.SharedObjectSize = stackOfCards.Rectangle.Size; stateChange.GrabbingClientName = null; stateChange.ReleasingClientName = clientCommandData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( "Broadcasting state change (SharedObjectMove) for the clicked shared object (stackOfCard)", 95); BroadcastStateChange(stateChange, null, null); // The stackOfCards is no more grabbed: stackOfCards.GrabberName = null; stackOfCards.ContextualMenuOpened = false; theClient.GrabbedSharedObject = null; } } } break; } }
public void NotifyServerChatMessage(ChatMessageDataType chatMessageData) { lock (ClientsLocker) { var inactiveClients = new List<string>(); foreach (var client in Clients) { try { (client.Value).ScgBroadcastorCallBack.BroadcastChatMessageToClient(chatMessageData); } catch (Exception ex) { LogError(string.Format("Exception '{0}' raised in ScgBroadcastorService.BroadcastStateChange when calling (client.Value).ScgBroadcastorCallBack.BroadcastChatMessageToClient('{2}'). client.Value.Name = '{1}')", ex.Message, client.Value.Name, chatMessageData.ChatMessage), 99); inactiveClients.Add(client.Key); } } if (inactiveClients.Count > 0) { foreach (var inactiveClient in inactiveClients) { // Search the leavingClient (Client) corresponding to the inactiveClient (name): Client leavingClient; var foundTheClient = Clients.TryGetValue(inactiveClient, out leavingClient); if (foundTheClient) { // Free a possible grabbed object by the leaving client: if (leavingClient.GrabbedSharedObject != null) { leavingClient.GrabbedSharedObject.GrabberName = null; leavingClient.GrabbedSharedObject.ContextualMenuOpened = false; } } // Remove the inactive client from the clients list: Clients.Remove(inactiveClient); LogInfo(string.Format("_clients.Remove(inactiveClient = '{0}')", inactiveClient), 13); // Remove the private area of the inactive client var removedSharedObjectId = _gameState.RemovePrivateArea(inactiveClient); // Note: The removedSharedObjectId should be >= 0 if (removedSharedObjectId >= 0) { // Inform other existing clients of the disposed PrivateArea id: foreach (var client in Clients) { // Prepare StateChangeEventDataType: var aStateChangeEventDataType = new StateChangeEventDataType(); aStateChangeEventDataType.StateChangeEventType = StateChangeEventType.DisposeSharedObject; aStateChangeEventDataType.SharedObjectId = removedSharedObjectId; aStateChangeEventDataType.PrivateOwnerClientName = inactiveClient; // Send the StateChangeEventDataType to the client: client.Value.ScgBroadcastorCallBack.BroadcastToClient( aStateChangeEventDataType); LogInfo( string.Format( "BroadcastToClient'{0}'(DisposeSharedObject, removedSharedObjectId = '{1}')", client.Value.Name, removedSharedObjectId), 14); } } } } } }
/// <summary> /// Notifies the server of a MouseEvent on the client. /// (Will be remotely called by the clients) /// </summary> /// <param name="mouseEventData">The mouse event data.</param> public void NotifyServer(MouseEventDataType mouseEventData) { // Handle the received mouseEventData and update the State of the Shared Card Game: var stateChangeEventDataType = new StateChangeEventDataType(); Client theClient; bool foundTheClient; SharedObject clickedSharedObject; string otherFaceCardPicture = null; SharedObject enclosingPrivateArea = null; lock (GameStateLocker) { switch (mouseEventData.MouseEventType) { case MouseEventType.MouseDown: if (mouseEventData.MouseButton == MouseButtons.Left) { clickedSharedObject = _gameState.GetSharedObjectAt(mouseEventData.MouseLocation); foundTheClient = Clients.TryGetValue(mouseEventData.ClientName, out theClient); if (clickedSharedObject != null && clickedSharedObject.GrabberName == null && (clickedSharedObject.PrivateOwnerName == null || clickedSharedObject.PrivateOwnerName == mouseEventData.ClientName) && !_gameState.IsInOtherClientPrivateAreaAt(mouseEventData.MouseLocation, mouseEventData.ClientName) && (clickedSharedObject.PrivateOwnerName == null || !_gameState.PrivateAreaIsNotEmpty(clickedSharedObject))) { LogInfo("LeftClick accepted", 999); if (foundTheClient && theClient != null && theClient.GrabbedSharedObject == null) { // Set client grabbing data: theClient.GrabbedSharedObject = clickedSharedObject; theClient.GrabbedRelativePosition = new Point(mouseEventData.MouseLocation.X - clickedSharedObject.Location.X, mouseEventData.MouseLocation.Y - clickedSharedObject.Location.Y); // Set the clicked object data: clickedSharedObject.GrabberName = mouseEventData.ClientName; clickedSharedObject.GrabbedLocation = clickedSharedObject.Location; clickedSharedObject.BringToFront(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = clickedSharedObject.Id; stateChangeEventDataType.GrabbingClientName = mouseEventData.ClientName; stateChangeEventDataType.ReleasingClientName = null; stateChangeEventDataType.PrivateOwnerClientName = clickedSharedObject.PrivateOwnerName; stateChangeEventDataType.NewSharedObjectLocation = clickedSharedObject.Location; stateChangeEventDataType.SharedObjectSize = clickedSharedObject.Rectangle.Size; // Prepare the shown picture of cards according to the card location on Private Areas enclosingPrivateArea = _gameState.FindEnclosingPrivateArea(clickedSharedObject); var clickedSharedObjectTopElement = clickedSharedObject.GetTopElement(); if (clickedSharedObjectTopElement != null) { if (enclosingPrivateArea != null && clickedSharedObject.GameElements.Count == 1 && clickedSharedObjectTopElement is Card) { // The grabbedSharedObject is a Card and is completely inside a PrivateArea if ((clickedSharedObjectTopElement as Card).FaceUp) { stateChangeEventDataType.NewSharedObjectPicture = (clickedSharedObjectTopElement as Card).RectoPicture; otherFaceCardPicture = (clickedSharedObjectTopElement as Card).VersoPicture; } else { stateChangeEventDataType.NewSharedObjectPicture = (clickedSharedObjectTopElement as Card).VersoPicture; otherFaceCardPicture = (clickedSharedObjectTopElement as Card).RectoPicture; } } else { // Regular case enclosingPrivateArea = null; stateChangeEventDataType.NewSharedObjectPicture = clickedSharedObject.Picture; } } } } else if (clickedSharedObject == null && GatheringClient == null && foundTheClient && theClient != null && theClient.GrabbedSharedObject == null) { GatheringClient = mouseEventData.ClientName; GatheringFromLocation = mouseEventData.MouseLocation; GatheringToLocation = mouseEventData.MouseLocation; } } else if (mouseEventData.MouseButton == MouseButtons.Right) { clickedSharedObject = _gameState.GetSharedObjectAt(mouseEventData.MouseLocation); // Check that the clicked shared object is free: if (clickedSharedObject != null && clickedSharedObject.GrabberName == null && !_gameState.IsInOtherClientPrivateAreaAt(mouseEventData.MouseLocation, mouseEventData.ClientName)) { LogInfo(string.Format("RightClick on free sharedObject Id={0}", clickedSharedObject.Id), 19); if (clickedSharedObject.GameElements.Count == 1) { // Right click on a non stacked shared object: if (clickedSharedObject.GetTopElement() is Card) { // Right click on a non stacked card: var card = clickedSharedObject.GetTopElement() as Card; if (card != null) { foundTheClient = Clients.TryGetValue(mouseEventData.ClientName, out theClient); if (foundTheClient && theClient != null && theClient.GrabbedSharedObject == null) { card.Flip(); // Set client grabbing data: theClient.GrabbedSharedObject = clickedSharedObject; theClient.GrabbedRelativePosition = new Point( mouseEventData.MouseLocation.X - clickedSharedObject.Location.X, mouseEventData.MouseLocation.Y - clickedSharedObject.Location.Y); // Set the clicked object data: clickedSharedObject.GrabberName = mouseEventData.ClientName; clickedSharedObject.GrabbedLocation = clickedSharedObject.Location; clickedSharedObject.BringToFront(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = clickedSharedObject.Id; stateChangeEventDataType.PrivateOwnerClientName = clickedSharedObject.PrivateOwnerName; stateChangeEventDataType.GrabbingClientName = mouseEventData.ClientName; stateChangeEventDataType.ReleasingClientName = null; stateChangeEventDataType.NewSharedObjectLocation = clickedSharedObject.Location; stateChangeEventDataType.SharedObjectSize = clickedSharedObject.Rectangle.Size; // Prepare the shown picture of cards according to the card location on Private Areas var clickedSharedObjectTopElement = clickedSharedObject.GetTopElement(); if (clickedSharedObjectTopElement != null) { enclosingPrivateArea = _gameState.FindEnclosingPrivateArea(clickedSharedObject); if (enclosingPrivateArea != null && clickedSharedObject.GameElements.Count == 1 && clickedSharedObjectTopElement is Card) { // The clickedSharedObject is a Card and is completely inside a PrivateArea if ((clickedSharedObjectTopElement as Card).FaceUp) { stateChangeEventDataType.NewSharedObjectPicture = (clickedSharedObjectTopElement as Card) .RectoPicture; otherFaceCardPicture = (clickedSharedObjectTopElement as Card) .VersoPicture; } else { stateChangeEventDataType.NewSharedObjectPicture = (clickedSharedObjectTopElement as Card) .VersoPicture; otherFaceCardPicture = (clickedSharedObjectTopElement as Card) .RectoPicture; } } else { // Regular case enclosingPrivateArea = null; stateChangeEventDataType.NewSharedObjectPicture = clickedSharedObject.Picture; } } } } } } else { // Right click on a stacked shared object: if (clickedSharedObject.GameElements.First() is Card) { // Right click on a stack of cards: // Grab the card and open contextual menu: // Check that the client is not already grabbing another object: foundTheClient = Clients.TryGetValue(mouseEventData.ClientName, out theClient); if (foundTheClient && theClient != null && theClient.GrabbedSharedObject == null) { // Prepare and send state change "OpenContextualMenuOnSharedObject" for the clicked shared object: StateChangeEventDataType stateChange = new StateChangeEventDataType(); stateChange.StateChangeEventType = StateChangeEventType.OpenContextualMenuOnSharedObject; stateChange.SharedObjectId = clickedSharedObject.Id; stateChange.GrabbingClientName = mouseEventData.ClientName; stateChange.PrivateOwnerClientName = null; LogInfo( string.Format( "Broadcasting stateChange (OpenContextualMenuOnSharedObject) SharedObjectId={0}", stateChange.SharedObjectId), 39); BroadcastStateChange(stateChange, null, null); // Mark the clicked object as grabbed for ContextualMenu opened: clickedSharedObject.ContextualMenuOpened = true; // Prepare state change "SharedObjectMove" // --- From here, code to refactorise with mouse down ----------- // Set client grabbing data: theClient.GrabbedSharedObject = clickedSharedObject; theClient.GrabbedRelativePosition = new Point(mouseEventData.MouseLocation.X - clickedSharedObject.Location.X, mouseEventData.MouseLocation.Y - clickedSharedObject.Location.Y); // Set the clicked object data: clickedSharedObject.GrabberName = mouseEventData.ClientName; clickedSharedObject.GrabbedLocation = clickedSharedObject.Location; clickedSharedObject.BringToFront(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = clickedSharedObject.Id; stateChangeEventDataType.GrabbingClientName = mouseEventData.ClientName; stateChangeEventDataType.ReleasingClientName = null; stateChangeEventDataType.PrivateOwnerClientName = clickedSharedObject.PrivateOwnerName; stateChangeEventDataType.NewSharedObjectLocation = clickedSharedObject.Location; stateChangeEventDataType.SharedObjectSize = clickedSharedObject.Rectangle.Size; // Prepare the shown picture of cards according to the card location on Private Areas enclosingPrivateArea = _gameState.FindEnclosingPrivateArea(clickedSharedObject); var clickedSharedObjectTopElement = clickedSharedObject.GetTopElement(); if (clickedSharedObjectTopElement != null) { if (enclosingPrivateArea != null && clickedSharedObject.GameElements.Count == 1 && clickedSharedObjectTopElement is Card) { // The grabbedSharedObject is a Card and is completely inside a PrivateArea if ((clickedSharedObjectTopElement as Card).FaceUp) { stateChangeEventDataType.NewSharedObjectPicture = (clickedSharedObjectTopElement as Card).RectoPicture; otherFaceCardPicture = (clickedSharedObjectTopElement as Card).VersoPicture; } else { stateChangeEventDataType.NewSharedObjectPicture = (clickedSharedObjectTopElement as Card).VersoPicture; otherFaceCardPicture = (clickedSharedObjectTopElement as Card).RectoPicture; } } else { // Regular case enclosingPrivateArea = null; stateChangeEventDataType.NewSharedObjectPicture = clickedSharedObject.Picture; } } // --- Till here, code to refactorise with mouse down ----------- } } } } } break; case MouseEventType.MouseMove: if (mouseEventData.MouseButton == MouseButtons.Left) { foundTheClient = Clients.TryGetValue(mouseEventData.ClientName, out theClient); if (foundTheClient && theClient != null && theClient.GrabbedSharedObject != null && !theClient.GrabbedSharedObject.ContextualMenuOpened ) { var grabbedSharedObject = theClient.GrabbedSharedObject; // Set the clicked object data: grabbedSharedObject.MoveTo( new Point(mouseEventData.MouseLocation.X - theClient.GrabbedRelativePosition.X, mouseEventData.MouseLocation.Y - theClient.GrabbedRelativePosition.Y)); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = grabbedSharedObject.Id; stateChangeEventDataType.GrabbingClientName = mouseEventData.ClientName; stateChangeEventDataType.ReleasingClientName = null; stateChangeEventDataType.PrivateOwnerClientName = grabbedSharedObject.PrivateOwnerName; stateChangeEventDataType.NewSharedObjectLocation = grabbedSharedObject.Location; stateChangeEventDataType.SharedObjectSize = grabbedSharedObject.Rectangle.Size; // Prepare the shown picture of cards according to the card location on Private Areas var grabbedSharedObjectTopElement = grabbedSharedObject.GetTopElement(); if (grabbedSharedObjectTopElement != null) { enclosingPrivateArea = _gameState.FindEnclosingPrivateArea(grabbedSharedObject); if (enclosingPrivateArea != null && grabbedSharedObject.GameElements.Count == 1 && grabbedSharedObjectTopElement is Card) { // The grabbedSharedObject is a Card and is completely inside a PrivateArea if ((grabbedSharedObjectTopElement as Card).FaceUp) { stateChangeEventDataType.NewSharedObjectPicture = (grabbedSharedObjectTopElement as Card).RectoPicture; otherFaceCardPicture = grabbedSharedObject.GrabberName != enclosingPrivateArea.PrivateOwnerName || !enclosingPrivateArea.Rectangle.Contains( new Rectangle( grabbedSharedObject.GrabbedLocation.X, grabbedSharedObject.GrabbedLocation.Y, grabbedSharedObject.Rectangle.Width, grabbedSharedObject.Rectangle.Height)) ? null : (grabbedSharedObjectTopElement as Card).VersoPicture; } else { stateChangeEventDataType.NewSharedObjectPicture = (grabbedSharedObjectTopElement as Card).VersoPicture; otherFaceCardPicture = grabbedSharedObject.GrabberName != enclosingPrivateArea.PrivateOwnerName || !enclosingPrivateArea.Rectangle.Contains( new Rectangle( grabbedSharedObject.GrabbedLocation.X, grabbedSharedObject.GrabbedLocation.Y, grabbedSharedObject.Rectangle.Width, grabbedSharedObject.Rectangle.Height)) ? null : (grabbedSharedObjectTopElement as Card).RectoPicture; } } else { // Regular case enclosingPrivateArea = null; stateChangeEventDataType.NewSharedObjectPicture = grabbedSharedObject.Picture; } } } else if (GatheringClient == mouseEventData.ClientName) { GatheringToLocation = mouseEventData.MouseLocation; stateChangeEventDataType.StateChangeEventType = StateChangeEventType.ShowGatheringRectangle; stateChangeEventDataType.GatheringRectangle = new Rectangle(Math.Min(GatheringFromLocation.X, GatheringToLocation.X), Math.Min(GatheringFromLocation.Y, GatheringToLocation.Y), Math.Abs(GatheringToLocation.X - GatheringFromLocation.X), Math.Abs(GatheringToLocation.Y - GatheringFromLocation.Y)); } } break; case MouseEventType.MouseUp: if (mouseEventData.MouseButton == MouseButtons.Left || mouseEventData.MouseButton == MouseButtons.Right) { foundTheClient = Clients.TryGetValue(mouseEventData.ClientName, out theClient); if (foundTheClient && theClient != null && theClient.GrabbedSharedObject != null && !theClient.GrabbedSharedObject.ContextualMenuOpened) { var grabbedSharedObject = theClient.GrabbedSharedObject; // Set client grabbing data: theClient.GrabbedSharedObject = null; theClient.GrabbedRelativePosition = new Point(0, 0); // Set the clicked object data: grabbedSharedObject.GrabberName = null; // Change the object location on the next magnetic grid step: grabbedSharedObject.MoveTo(ScgGameState.GetMagneticLocation(grabbedSharedObject.Rectangle)); // Test if shared object is released outside the game field: if (!new Rectangle(0, 0, ScgGameState.GamefieldDimX, ScgGameState.GamefieldDimY) .Contains(grabbedSharedObject.Rectangle)) { // If so, put it back at its grabbed location: grabbedSharedObject.MoveTo(grabbedSharedObject.GrabbedLocation); } grabbedSharedObject.BringToFront(); // Handle stacking SharedObject stackObject; if (_gameState.TryToStackOnAnotherSharedObject(grabbedSharedObject, out stackObject)) { // Prepare stateChangeEventType of type DisposeSharedObject: stateChangeEventDataType.StateChangeEventType = StateChangeEventType.DisposeSharedObject; stateChangeEventDataType.SharedObjectId = grabbedSharedObject.Id; stateChangeEventDataType.PrivateOwnerClientName = grabbedSharedObject.PrivateOwnerName; stateChangeEventDataType.SharedObjectSize = grabbedSharedObject.Rectangle.Size; stateChangeEventDataType.GrabbingClientName = null; stateChangeEventDataType.NewSharedObjectLocation = grabbedSharedObject.Location; stateChangeEventDataType.NewSharedObjectPicture = null; stateChangeEventDataType.ReleasingClientName = grabbedSharedObject.GrabberName; //Broadcast the DisposeSharedObject stateChangeEventType: BroadcastStateChange(stateChangeEventDataType, null, null); // The grabbed object is now the stacked object: grabbedSharedObject = stackObject; } // Prepare the stateChangeEventType to be sent: stateChangeEventDataType.StateChangeEventType = StateChangeEventType.SharedObjectMove; stateChangeEventDataType.SharedObjectId = grabbedSharedObject.Id; stateChangeEventDataType.GrabbingClientName = null; stateChangeEventDataType.ReleasingClientName = mouseEventData.ClientName; stateChangeEventDataType.PrivateOwnerClientName = grabbedSharedObject.PrivateOwnerName; stateChangeEventDataType.NewSharedObjectLocation = grabbedSharedObject.Location; stateChangeEventDataType.SharedObjectSize = grabbedSharedObject.Rectangle.Size; // Prepare the shown picture of cards according to the card location on Private Areas var grabbedSharedObjectTopElement = grabbedSharedObject.GetTopElement(); if (grabbedSharedObjectTopElement != null) { enclosingPrivateArea = _gameState.FindEnclosingPrivateArea(grabbedSharedObject); if (enclosingPrivateArea != null && grabbedSharedObject.GameElements.Count == 1 && grabbedSharedObjectTopElement is Card) { // The grabbedSharedObject is a Card and is completely inside a PrivateArea if ((grabbedSharedObjectTopElement as Card).FaceUp) { stateChangeEventDataType.NewSharedObjectPicture = (grabbedSharedObjectTopElement as Card).RectoPicture; otherFaceCardPicture = (grabbedSharedObjectTopElement as Card).VersoPicture; } else { stateChangeEventDataType.NewSharedObjectPicture = (grabbedSharedObjectTopElement as Card).VersoPicture; otherFaceCardPicture = (grabbedSharedObjectTopElement as Card).RectoPicture; } } else { // Regular case enclosingPrivateArea = null; stateChangeEventDataType.NewSharedObjectPicture = grabbedSharedObject.Picture; } } } else if (GatheringClient == mouseEventData.ClientName) { GatheringClient = null; stateChangeEventDataType.StateChangeEventType = StateChangeEventType.HideGatheringRectangle; stateChangeEventDataType.GatheringRectangle = new Rectangle(Math.Min(GatheringFromLocation.X, GatheringToLocation.X), Math.Min(GatheringFromLocation.Y, GatheringToLocation.Y), Math.Abs(GatheringToLocation.X - GatheringFromLocation.X), Math.Abs(GatheringToLocation.Y - GatheringFromLocation.Y)); } } break; } // if required, Broadcast The state change to each client: BroadcastStateChange(stateChangeEventDataType, enclosingPrivateArea, otherFaceCardPicture); } }
/// <summary> /// Registers the new client. /// </summary> /// <param name="clientName">Name of the client.</param> /// <param name="clientProtocolVersion"></param> public void RegisterClient(string clientName, int clientProtocolVersion) { if (!string.IsNullOrEmpty(clientName)) { try { var callback = OperationContext.Current.GetCallbackChannel<IScgBroadcastorCallBack>(); if (clientProtocolVersion != Common.ClientServerProtocolVersion) { callback.BroadcastBadProtocolVersion(Common.ClientServerProtocolVersion); return; } lock (ClientsLocker) { if (Clients.Count <= MaxClientCount) { lock (GameStateLocker) { LogInfo(string.Format("RegisterClient(clientName = '{0}')", clientName), 1); var removedPrivateAreaId = -1; //Remove the old client using the same name: if (Clients.Keys.Contains(clientName)) { // The new client uses an already registerd name. Refuse it: return; } //{ // Clients.Remove(clientName); // LogWarning(string.Format("_clients.Remove(clientName = '{0}')", clientName), 2); // // Remove the private area of the old client // removedPrivateAreaId = _gameState.RemovePrivateArea(clientName); // // Note: The removedSharedObjectId should be >= 0 // if (removedPrivateAreaId >= 0) // { // // Inform other existing clients of the disposed PrivateArea id: // foreach (var client in Clients) // { // // Prepare StateChangeEventDataType: // var stateChangeEventDataType = // new StateChangeEventDataType(); // stateChangeEventDataType.StateChangeEventType = // StateChangeEventType.DisposeSharedObject; // stateChangeEventDataType.SharedObjectId = removedPrivateAreaId; // // Send the StateChangeEventDataType to the client: // client.Value.ScgBroadcastorCallBack.BroadcastToClient( // stateChangeEventDataType); // LogInfo( // string.Format( // "BroadcastToClient'{0}'(DisposeSharedObject, removedPrivateAreaId = '{1}')", // client.Value.Name, removedPrivateAreaId), 3); // } // } //} Clients.Add(clientName, new Client(clientName, callback)); LogInfo(string.Format("_clients.Add(clientName = '{0}')", clientName), 4); if (Clients.Count == 1) { // Initialize a new game state _gameState = new ScgGameState(this); } bool newSharedObject; var privateArea = _gameState.CreatePrivateArea(clientName, out newSharedObject); // Search a possible client without private area (The registering client was previously already registered under another name we do not know) // WARNING: This now shouldn't occur since the registered clients will now hide the registering pane: foreach (var client in Clients) { if (_gameState.FindPrivateArea(client.Value.Name) == null) { var oldClientName = client.Value.Name; // Remove this orphan client corresponding to the old name of the registering client: Clients.Remove(oldClientName); LogWarning( string.Format("_clients.Remove(oldClientName = '{0}')", oldClientName), 5); // Inform other existing clients of the disposed PrivateArea id: foreach (var cli in Clients) { if (cli.Value.Name != clientName) { // Prepare StateChangeEventDataType: var stateChangeEventDataType = new StateChangeEventDataType(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.DisposeSharedObject; stateChangeEventDataType.PrivateOwnerClientName = oldClientName; stateChangeEventDataType.SharedObjectId = removedPrivateAreaId; // Send the StateChangeEventDataType to the client: cli.Value.ScgBroadcastorCallBack.BroadcastToClient( stateChangeEventDataType); LogInfo( string.Format( "BroadcastToClient'{0}'(DisposeSharedObject, removedPrivateAreaId = '{1}')", cli.Value.Name, removedPrivateAreaId), 6); } } break; } } // Inform other existing clients of new PrivateArea: foreach (var client in Clients) { if (client.Value.Name != clientName) { // Prepare StateChangeEventDataType: var stateChangeEventDataType = new StateChangeEventDataType(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.NewSharedObject; stateChangeEventDataType.SharedObjectId = privateArea.Id; stateChangeEventDataType.PrivateOwnerClientName = privateArea.PrivateOwnerName; stateChangeEventDataType.NewSharedObjectLocation = new Point(privateArea.Rectangle.Left, privateArea.Rectangle.Top); stateChangeEventDataType.SharedObjectSize = new Size(privateArea.Rectangle.Size.Width, privateArea.Rectangle.Size.Height); stateChangeEventDataType.NewSharedObjectPicture = privateArea.Picture; // Send the StateChangeEventDataType to the client: client.Value.ScgBroadcastorCallBack.BroadcastToClient(stateChangeEventDataType); LogInfo( string.Format( "BroadcastToClient'{0}'(NewSharedObject, privateArea.Id = '{1}')", client.Value.Name, privateArea.Id), 7); } } // Inform the new client (and only him) of the current state of the game: Client newClient; var foundNewClient = Clients.TryGetValue(clientName, out newClient); if (foundNewClient && newClient != null) { // Parse all shared objects in reversed order (from the back to the topmost one shared object): for (var i = _gameState.ZOrderListOfSharedObjects.Count - 1; i >= 0; i--) { var sharedObject = _gameState.ZOrderListOfSharedObjects[i]; // Prepare StateChangeEventDataType: var stateChangeEventDataType = new StateChangeEventDataType(); stateChangeEventDataType.StateChangeEventType = StateChangeEventType.NewSharedObject; stateChangeEventDataType.SharedObjectId = sharedObject.Id; stateChangeEventDataType.PrivateOwnerClientName = sharedObject.PrivateOwnerName; stateChangeEventDataType.NewSharedObjectLocation = new Point(sharedObject.Rectangle.Left, sharedObject.Rectangle.Top); stateChangeEventDataType.SharedObjectSize = new Size(sharedObject.Rectangle.Size.Width, sharedObject.Rectangle.Size.Height); stateChangeEventDataType.NewSharedObjectPicture = sharedObject.Picture; // Send the StateChangeEventDataType to the new (and only) client: newClient.ScgBroadcastorCallBack.BroadcastToClient(stateChangeEventDataType); LogInfo( string.Format( "BroadcastToClient'{0}'(NewSharedObject, sharedObject.Id = '{1}')", newClient, sharedObject.Id), 8); } } } } else { LogWarning( string.Format( "Refused to RegisterClient(clientName = '{0}') because the _clients list is full. ({1} clients)", clientName, Clients.Count), 1); } } } catch (Exception ex) { // Unexpected exception: LogWarning(string.Format("Unexpected exception ex.Message = '{0}' in RegisterClient)", ex.Message), 9); // Throw it to restart the service (in case of service channel canceled) throw; } } }
/// <summary> /// Broadcasts the state change to all clients. /// </summary> /// <param name="stateChangeEventDataType">Type of the state change event data.</param> /// <param name="enclosingPrivateArea">The enclosing private area.</param> /// <param name="otherFaceCardPicture">The other face card picture.</param> public void BroadcastStateChange(StateChangeEventDataType stateChangeEventDataType, SharedObject enclosingPrivateArea, string otherFaceCardPicture) { // if required, Broadcast The state change to each client: if (stateChangeEventDataType.StateChangeEventType != StateChangeEventType.NoStateChange) { lock (ClientsLocker) { var inactiveClients = new List<string>(); foreach (var client in Clients) { try { // Change the NewSharedObjectPicture information for card on private area for the PrivateAreaOwner client only: if (stateChangeEventDataType.StateChangeEventType == StateChangeEventType.SharedObjectMove && enclosingPrivateArea != null && otherFaceCardPicture != null && client.Value.Name == enclosingPrivateArea.PrivateOwnerName) { var savedPicture = stateChangeEventDataType.NewSharedObjectPicture; stateChangeEventDataType.NewSharedObjectPicture = otherFaceCardPicture; (client.Value).ScgBroadcastorCallBack.BroadcastToClient(stateChangeEventDataType); stateChangeEventDataType.NewSharedObjectPicture = savedPicture; } else { (client.Value).ScgBroadcastorCallBack.BroadcastToClient(stateChangeEventDataType); } } catch (Exception ex) { LogError(string.Format("Exception '{0}' raised in ScgBroadcastorService.BroadcastStateChange when calling (client.Value).ScgBroadcastorCallBack.BroadcastToClient(). client.Value.Name = '{1}')", ex.Message , client.Value.Name), 99); inactiveClients.Add(client.Key); } } if (inactiveClients.Count > 0) { foreach (var inactiveClient in inactiveClients) { // Search the leavingClient (Client) corresponding to the inactiveClient (name): Client leavingClient; var foundTheClient = Clients.TryGetValue(inactiveClient, out leavingClient); if (foundTheClient) { // Free a possible grabbed object by the leaving client: if (leavingClient.GrabbedSharedObject != null) { leavingClient.GrabbedSharedObject.GrabberName = null; leavingClient.GrabbedSharedObject.ContextualMenuOpened = false; } } // Remove the inactive client from the clients list: Clients.Remove(inactiveClient); LogInfo(string.Format("_clients.Remove(inactiveClient = '{0}')", inactiveClient), 13); // Remove the private area of the inactive client var removedSharedObjectId = _gameState.RemovePrivateArea(inactiveClient); // Note: The removedSharedObjectId should be >= 0 if (removedSharedObjectId >= 0) { // Inform other existing clients of the disposed PrivateArea id: foreach (var client in Clients) { // Prepare StateChangeEventDataType: var aStateChangeEventDataType = new StateChangeEventDataType(); aStateChangeEventDataType.StateChangeEventType = StateChangeEventType.DisposeSharedObject; aStateChangeEventDataType.SharedObjectId = removedSharedObjectId; stateChangeEventDataType.PrivateOwnerClientName = inactiveClient; // Send the StateChangeEventDataType to the client: client.Value.ScgBroadcastorCallBack.BroadcastToClient( aStateChangeEventDataType); LogInfo( string.Format( "BroadcastToClient'{0}'(DisposeSharedObject, removedSharedObjectId = '{1}')", client.Value.Name, removedSharedObjectId), 14); } } } } } } }