/// <summary> /// Handles a broadcast callback call received from the ScgBroadcastService. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> public void HandleBroadcast(object sender, EventArgs e) { if (InvokeRequired) { BeginInvoke(new HandleBroadcastCallback(HandleBroadcast), sender, e); } else { if (sender is StateChangeEventDataType) { var stateChangeEventData = (StateChangeEventDataType) sender; // Handle the received stateChangeEventData and report the state change to the GUI elements: try { // getting the event type: var stateChangeEventType = stateChangeEventData.StateChangeEventType; //var id = stateChangeEventData.SharedObjectId; ResourceManager rm; switch (stateChangeEventType) { case StateChangeEventType.NewSharedObject: try { LogInfo( string.Format( "Handling stateChangeEventData (stateChangeEventType = StateChangeEventType.NewSharedObject, stateChangeEventData.NewSharedObjectPicture = '{0}', stateChangeEventData.SharedObjectId = {1}", stateChangeEventData.NewSharedObjectPicture, stateChangeEventData.SharedObjectId), 1); // Test if first NewSharedObject state change received from registration if (timerRegisteringTimeOut.Enabled) { // So the registration has been accepted. - Collapse the register panel: splitContainerGameField.Panel1Collapsed = true; // Update the main form title with player name as suffix: Text = Resources.Form1_HandleBroadcast_Shared_Card_Game___ + ClientRegisteredName; // Disable the registering timeout: timerRegisteringTimeOut.Enabled = false; // Set the chat form visible: _chatForm.Visible = true; } // Create the asked new shared object: MouseEventTransparentPictureBox newMouseEventTransparentPictureBox = new MouseEventTransparentPictureBox(); RedirectMouseEventsToGameFieldForControl(newMouseEventTransparentPictureBox); newMouseEventTransparentPictureBox.BackColor = Color.Transparent; rm = Resources.ResourceManager; newMouseEventTransparentPictureBox.Image = (Bitmap) rm.GetObject(stateChangeEventData.NewSharedObjectPicture); newMouseEventTransparentPictureBox.Location = stateChangeEventData.NewSharedObjectLocation; newMouseEventTransparentPictureBox.Size = stateChangeEventData.SharedObjectSize; newMouseEventTransparentPictureBox.Name = stateChangeEventData.SharedObjectId.ToString(); newMouseEventTransparentPictureBox.SizeMode = PictureBoxSizeMode.StretchImage; newMouseEventTransparentPictureBox.TabIndex = 1; newMouseEventTransparentPictureBox.TabStop = false; newMouseEventTransparentPictureBox.Parent = splitContainerGameField.Panel2; // Handle new private areas: if (stateChangeEventData.PrivateOwnerClientName != null) { // Create the label of the new private area: MouseEventTransparentLabel labelPrivateArea = new MouseEventTransparentLabel(); RedirectMouseEventsToGameFieldForControl(labelPrivateArea); labelPrivateArea.BackColor = Color.Ivory; labelPrivateArea.Text = stateChangeEventData.PrivateOwnerClientName; labelPrivateArea.TextAlign = ContentAlignment.MiddleCenter; labelPrivateArea.Top = 0; labelPrivateArea.Width = newMouseEventTransparentPictureBox.Width; labelPrivateArea.Height = 12; newMouseEventTransparentPictureBox.Controls.Add(labelPrivateArea); // The new private area must be the topmost private area newMouseEventTransparentPictureBox.BringToFront(); // But other regular shared object must stay on top of it if they are intersecting with it: BringToFrontRegularSharedObjectControlsOnPrivateArea(newMouseEventTransparentPictureBox); // Prepare the player vector control: (not visible at the moment but ready) Point playerLocation = stateChangeEventData.NewSharedObjectLocation; playerLocation.X += stateChangeEventData.SharedObjectSize.Width/2; playerLocation.Y += stateChangeEventData.SharedObjectSize.Height/2; MouseEventTransparentVectorControl playerVector = new MouseEventTransparentVectorControl(playerLocation, playerLocation); RedirectMouseEventsToGameFieldForControl(playerVector); playerVector.UpdateLocation(); playerVector.Parent = splitContainerGameField.Panel2; // Add the new player vector to the _playerVectors list: _playerVectors.Add(stateChangeEventData.PrivateOwnerClientName, playerVector); SendPlayerVectorsToBack(); // Test if the new private area is our: if (stateChangeEventData.PrivateOwnerClientName == ClientRegisteredName) { // Display the welcome message: MessageBoxEx.Show(this, string.Format( Resources.Form1_HandleBroadcast_Welcome_in_the_game___0___ + Environment.NewLine + Environment.NewLine + Resources .Form1_HandleBroadcast_Please__choose_your_playing_position_by_dragging_your_private_area_from_the_top_left_corner_to_your_wished_position_around_the_game_field_, ClientRegisteredName), Resources.Form1_HandleBroadcast_Welcome); } } // Update the playerVector if the new shared object is grabbed by a player (the new // shared object has been extracted from a stack, he is grabbed until button mouse release) if (stateChangeEventData.GrabbingClientName != null) { // No playor vector displayed on our own display: if (stateChangeEventData.GrabbingClientName != ClientRegisteredName) { // Test if the event is about a private area: if (stateChangeEventData.PrivateOwnerClientName == null) { // not a private area, prepare to show the player vector: MouseEventTransparentVectorControl playerVector; // Try to get the playerVector control of the grabbing player: if (_playerVectors.TryGetValue(stateChangeEventData.GrabbingClientName, out playerVector)) { // Show the playerVector from the grabbing player's private area // to the grabbed shared object location and set it visible: Point to = stateChangeEventData.NewSharedObjectLocation; to.X += stateChangeEventData.SharedObjectSize.Width/2; to.Y += stateChangeEventData.SharedObjectSize.Height/2; playerVector.To = to; playerVector.UpdateLocation(); playerVector.Visible = true; SendPlayerVectorsToBack(); playerVector.Invalidate(); } } else { // The event is about the private area, just update the // location of the playerVector but do not show it: MouseEventTransparentVectorControl playerVector; if ( _playerVectors.TryGetValue( stateChangeEventData.PrivateOwnerClientName, out playerVector)) { Point pt = stateChangeEventData.NewSharedObjectLocation; pt.X += stateChangeEventData.SharedObjectSize.Width/2; pt.Y += stateChangeEventData.SharedObjectSize.Height/2; playerVector.From = pt; playerVector.To = pt; playerVector.UpdateLocation(); playerVector.Visible = false; playerVector.Invalidate(); } } } } else { // The event concerned shared object is not grabbed: // Test if it's a private area or not: if (stateChangeEventData.PrivateOwnerClientName == null) { // the event concerned shared object is not a private area and is not (or no more) // grabbed: hide the eventualy visible playerVector: MouseEventTransparentVectorControl playerVector; if (stateChangeEventData.ReleasingClientName != null && _playerVectors.TryGetValue(stateChangeEventData.ReleasingClientName, out playerVector)) { playerVector.To = playerVector.From; playerVector.UpdateLocation(); playerVector.Visible = false; playerVector.Invalidate(); } } } newMouseEventTransparentPictureBox.BringToFront(); } catch (Exception ex) { // Log any unexpected exception here: LogError(string.Format( "Unexpected exception '{0}' raised in NewSharedObject handling.", ex.Message), 21); // and rethrow it. throw; } break; case StateChangeEventType.SharedObjectMove: try { foreach (Control control in splitContainerGameField.Panel2.Controls) { if (control is MouseEventTransparentPictureBox && control.Name == stateChangeEventData.SharedObjectId.ToString()) { control.Location = stateChangeEventData.NewSharedObjectLocation; control.Size = stateChangeEventData.SharedObjectSize; rm = Resources.ResourceManager; (control as MouseEventTransparentPictureBox).Image = (Bitmap) rm.GetObject(stateChangeEventData.NewSharedObjectPicture); control.BringToFront(); // Update the playerVector: if (stateChangeEventData.GrabbingClientName != null) { if (stateChangeEventData.GrabbingClientName != ClientRegisteredName) { if (stateChangeEventData.PrivateOwnerClientName == null) { MouseEventTransparentVectorControl playerVector; if ( _playerVectors.TryGetValue( stateChangeEventData.GrabbingClientName, out playerVector)) { Point to = stateChangeEventData.NewSharedObjectLocation; to.X += stateChangeEventData.SharedObjectSize.Width/2; to.Y += stateChangeEventData.SharedObjectSize.Height/2; playerVector.To = to; playerVector.UpdateLocation(); playerVector.Visible = true; SendPlayerVectorsToBack(); playerVector.Invalidate(); } } else { MouseEventTransparentVectorControl playerVector; if ( _playerVectors.TryGetValue( stateChangeEventData.PrivateOwnerClientName, out playerVector)) { Point pt = stateChangeEventData.NewSharedObjectLocation; pt.X += stateChangeEventData.SharedObjectSize.Width/2; pt.Y += stateChangeEventData.SharedObjectSize.Height/2; playerVector.From = pt; playerVector.To = pt; playerVector.UpdateLocation(); playerVector.Visible = false; playerVector.Invalidate(); } } } } else { if (stateChangeEventData.PrivateOwnerClientName == null) { MouseEventTransparentVectorControl playerVector; if (stateChangeEventData.ReleasingClientName != null && _playerVectors.TryGetValue( stateChangeEventData.ReleasingClientName, out playerVector)) { playerVector.To = playerVector.From; playerVector.UpdateLocation(); playerVector.Visible = false; playerVector.Invalidate(); } } } break; } } } catch (Exception ex) { LogError(string.Format( "Unexpected exception '{0}' raised in SharedObjectMove handling.", ex.Message), 22); throw; } break; case StateChangeEventType.DisposeSharedObject: LogInfo( string.Format( "Handling stateChangeEventData (stateChangeEventType = StateChangeEventType.DisposeSharedObject, stateChangeEventData.SharedObjectId = {0}", stateChangeEventData.SharedObjectId), 2); try { foreach (Control control in splitContainerGameField.Panel2.Controls) { if (control is MouseEventTransparentPictureBox && control.Name == stateChangeEventData.SharedObjectId.ToString()) { if (stateChangeEventData.PrivateOwnerClientName != null) { // It's a private area, the player stateChangeEventData.PrivateOwnerClientName has left. // Remove its playerVector from the _playerVectors list and dispose it: MouseEventTransparentVectorControl playerVector; if (_playerVectors.TryGetValue(stateChangeEventData.PrivateOwnerClientName, out playerVector)) { playerVector.Dispose(); } _playerVectors.Remove(stateChangeEventData.PrivateOwnerClientName); } var i = splitContainerGameField.Panel2.Controls.IndexOf(control); splitContainerGameField.Panel2.Controls.RemoveAt(i); control.Dispose(); break; } } } catch (Exception ex) { LogError( string.Format( "Unexpected exception '{0}' raised in DisposeSharedObject handling.", ex.Message), 23); throw; } break; case StateChangeEventType.ShowGatheringRectangle: try { if (_gatheringRectangleControl == null) { _gatheringRectangleControl = new MouseEventTransparentGatheringRectangleControl( stateChangeEventData.GatheringRectangle); RedirectMouseEventsToGameFieldForControl(_gatheringRectangleControl); _gatheringRectangleControl.Parent = splitContainerGameField.Panel2; } else { _gatheringRectangleControl.Rectangle = stateChangeEventData.GatheringRectangle; } } catch (Exception ex) { LogError(string.Format( "Unexpected exception '{0}' raised in ShowGatheringRectangle handling.", ex.Message), 21); throw; } break; case StateChangeEventType.HideGatheringRectangle: try { if (_gatheringRectangleControl != null) { splitContainerGameField.Panel2.Controls.Remove(_gatheringRectangleControl); _gatheringRectangleControl = null; // Send the gathering command to the server _client.NotifyServerCmd( new ClientCommandDataType { ClientName = ClientRegisteredName, ClientCommandType = ClientCommandType.GatheringCmd, TargetRectangle = stateChangeEventData.GatheringRectangle }); } } catch (Exception ex) { LogError(string.Format( "Unexpected exception '{0}' raised in HideGatheringRectangle handling.", ex.Message), 21); throw; } break; case StateChangeEventType.OpenContextualMenuOnSharedObject: LogInfo(string.Format( "Handling stateChangeEventData (stateChangeEventType = StateChangeEventType.OpenContextualMenuOnSharedObject, stateChangeEventData.SharedObjectId = {0}", stateChangeEventData.SharedObjectId), 4); if (stateChangeEventData.GrabbingClientName == ClientRegisteredName) { // The local client has right clicked on the Shared object and has grabbed it // He can now open the contextual menu: try { // Search for the MouseEventTransparentControl corresponding to the shared object: foreach (Control control in splitContainerGameField.Panel2.Controls) { if (control is MouseEventTransparentPictureBox && control.Name == stateChangeEventData.SharedObjectId.ToString()) { LogInfo("Opening contextual menu.",5); // Open the contextual Menu by setting it to the found control control.ContextMenuStrip = contextMenuStripStackOfCards; _controlOwningContextMenuStrip = control; break; } } } catch (Exception ex) { LogError(string.Format( "Unexpected exception '{0}' raised in OpenContextualMenuOnSharedObject handling.", ex.Message), 28); throw; } } break; case StateChangeEventType.OpenDealingParametersDialog: LogInfo(string.Format( "Handling stateChangeEventData (stateChangeEventType = StateChangeEventType.OpenDealingParametersDialog, stateChangeEventData.SharedObjectId = {0}", stateChangeEventData.SharedObjectId), 27); if (stateChangeEventData.GrabbingClientName == ClientRegisteredName) { // The local client has Requested to open the DealingParametersDialog // He can now do this: try { // Search for the MouseEventTransparentControl corresponding to the shared object: foreach (Control control in splitContainerGameField.Panel2.Controls) { if (control is MouseEventTransparentPictureBox && control.Name == stateChangeEventData.SharedObjectId.ToString()) { LogInfo("Opening DealingParametersDialog.", 5); //Opening DealingParametersDialog _dealingParametersDialog.DealingDirectionIsClockwise = stateChangeEventData.DealingClockwise; _dealingParametersDialog.NumberOfCardsToDeal = stateChangeEventData.NumberOfCardsToDeal; _dealingParametersDialog.ShowDialog(); if (_dealingParametersDialog.DialogResult == DialogResult.OK) { // A CORRIGER: Notify the server of the Dealing try { LogInfo(string.Format("_client.NotifyServerCmd ClientName={0}, ClientCommandType=ClientCommandType.RequestDealingParameters, SharedObjectId={1}", ClientRegisteredName, stateChangeEventData.SharedObjectId), 34); _client.NotifyServerCmd( new ClientCommandDataType { ClientName = ClientRegisteredName, ClientCommandType = ClientCommandType.DealCmd, DealingClockwise = _dealingParametersDialog.DealingDirectionIsClockwise, NumberOfCardsToDeal = _dealingParametersDialog.NumberOfCardsToDeal, SharedObjectId = stateChangeEventData.SharedObjectId }); } catch (Exception ex) { LogError(string.Format("ERROR: Unexpected exception '{0} raised on _client.NotifyServerCmd", ex.Message), 34); // ignore } } else { // A CORRIGER (Notify the server of the cancelling) try { LogInfo(string.Format("_client.NotifyServerCmd ClientName={0}, ClientCommandType=ClientCommandType.CancelDealingParametersDialogCmd, SharedObjectId={1}", ClientRegisteredName, stateChangeEventData.SharedObjectId), 34); _client.NotifyServerCmd( new ClientCommandDataType { ClientName = ClientRegisteredName, ClientCommandType = ClientCommandType.CancelDealingParametersDialogCmd, SharedObjectId = stateChangeEventData.SharedObjectId }); } catch (Exception ex) { LogError(string.Format("ERROR: Unexpected exception '{0} raised on _client.NotifyServerCmd", ex.Message), 34); // ignore } } break; } } } catch (Exception ex) { LogError(string.Format( "Unexpected exception '{0}' raised in OpenDealingParametersDialog handling.", ex.Message), 28); throw; } } break; case StateChangeEventType.ShowMessage: if (stateChangeEventData.ToEveryone || stateChangeEventData.RecipientClientName == ClientRegisteredName) { LogInfo( string.Format( "Handling stateChangeEventData (stateChangeEventType = StateChangeEventType.ShowMessage, stateChangeEventData.NewSharedObjectPicture = '{0}', stateChangeEventData.SharedObjectId = {1}, MessageToDisplay='{2}'", stateChangeEventData.NewSharedObjectPicture, stateChangeEventData.SharedObjectId, stateChangeEventData.MessageToDisplay), 1); MessageBoxEx.Show(this, stateChangeEventData.MessageToDisplay, stateChangeEventData.MessageBoxTitle); } break; } //_pictureBoxRaptor.SendToBack(); } catch (Exception ex) { LogError(string.Format("Unexpected exception '{0}' raised in HandleBroadcast.", ex.Message), 25); throw; } } else if (sender is ChatMessageDataType) { ChatMessageDataType chatMessageData = (ChatMessageDataType)sender; // Handle the received chatMessageData and update the Chat Window: try { if (_chatForm != null) { _chatForm.LogReceivedMessage(chatMessageData); } } catch (Exception ex) { LogError( string.Format( "Unexpected exception '{0}' raised in HandleBroadcast when handling a ChatMessageDataType.", ex.Message), 45); throw; } } else if (sender is int) { // Bad Client Protolcol Version // Handle the received required serverProtocolVersion and Display an error message: int serverProtocolVersion = (int) sender; LogError( string.Format( "Bad client protocol version {0}. The server requires version '{1}'.", Common.ClientServerProtocolVersion, serverProtocolVersion), 46); timerRegisteringTimeOut.Enabled = false; MessageBoxEx.Show(this, string.Format("ERROR: BAD COMMUNICATION PROTOCOL VERSION:" + Environment.NewLine + Environment.NewLine + "The WCF service running on the server requires the communication protocol version {0}. You are using an obsolete SharedCardGame.exe client implementing communication protocol version {1}." + Environment.NewLine + "To succesfully connect to this server, please download the latest SharedCardGame.exe client version at:" + Environment.NewLine + Environment.NewLine + "http://www.raptordev.ch/SharedCardGame_Client.zip",serverProtocolVersion, Common.ClientServerProtocolVersion)); if (_client != null) { _client.Abort(); _client = null; } Close(); } } }
/// <summary> /// Registers the client. /// </summary> private void RegisterClient() { // Dispose all currently MouseEventTransparentPictureBox controls representing // sharable objects issued from previous session: var controlsToDispose = new List<Control>(); foreach (Control control in splitContainerGameField.Panel2.Controls) { if (control is IMouseEventTransparentControl && control.Name != "_pictureBoxRaptor") { controlsToDispose.Add(control); } } foreach (var control in controlsToDispose) { control.Dispose(); } // Abort previous session: if ((_client != null)) { LogInfo("Aborting previous session: _client.Abort()", 0); try { _client.Abort(); _client = null; } catch (Exception ex) { LogError(string.Format("Unexpected exception '{0}' was raised when aborting previous session.", ex.Message), 0); return; } } // Prepare the new _ScgBroadcastorServiceClient: var cb = new ScgBroadcastorCallback(); cb.SetHandler(HandleBroadcast); var context = new InstanceContext(cb); _client = new ScgBroadcastorServiceClient(context); // Try to register to the server: LogInfo(string.Format("_client.RegisterClient(clientName='{0}')", textBoxPlayerName.Text), 0); try { _client.RegisterClient(textBoxPlayerName.Text, Common.ClientServerProtocolVersion); } catch (Exception ex) { LogError(string.Format("Unexpected exception '{0}' was raised when registering client '{1}'.", ex.Message, textBoxPlayerName.Text), 0); MessageBoxEx.Show(this, string.Format("Unexpected exception '{0}' was raised when registering client '{1}'." + Environment.NewLine + "An external corporate firewall might block outgoing TCP requests.", ex.Message, textBoxPlayerName.Text)); return; } ClientRegisteredName = textBoxPlayerName.Text; // Enable registering timeout timerRegisteringTimeOut.Enabled = false; timerRegisteringTimeOut.Enabled = true; labelWarningNotRegistered.Visible = false; }