/// <summary> /// Handles the <see cref = "SetPropertiesRequest" /> and sends event <see cref = "PropertiesChangedEvent" /> to all <see cref = "Actor" />s in the room. /// </summary> /// <param name = "peer"> /// The peer. /// </param> /// <param name = "setPropertiesRequest"> /// The <see cref = "SetPropertiesRequest" /> operation to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleSetPropertiesOperation(LitePeer peer, SetPropertiesRequest setPropertiesRequest, SendParameters sendParameters) { if (setPropertiesRequest.ActorNumber > 0) { Actor actor = this.Actors.GetActorByNumber(setPropertiesRequest.ActorNumber); if (actor == null) { peer.SendOperationResponse( new OperationResponse { OperationCode = setPropertiesRequest.OperationRequest.OperationCode, ReturnCode = -1, DebugMessage = string.Format("Actor with number {0} not found.", setPropertiesRequest.ActorNumber) }, sendParameters); return; } actor.Properties.SetProperties(setPropertiesRequest.Properties); } else { this.Properties.SetProperties(setPropertiesRequest.Properties); } peer.SendOperationResponse(new OperationResponse { OperationCode = setPropertiesRequest.OperationRequest.OperationCode }, sendParameters); // if the optional paramter Broadcast is set a EvPropertiesChanged // event will be send to room actors if (setPropertiesRequest.Broadcast) { Actor actor = this.Actors.GetActorByPeer(peer); IEnumerable<Actor> recipients = this.Actors.GetExcludedList(actor); var propertiesChangedEvent = new PropertiesChangedEvent(actor.ActorNr) { TargetActorNumber = setPropertiesRequest.ActorNumber, Properties = setPropertiesRequest.Properties }; this.PublishEvent(propertiesChangedEvent, recipients, sendParameters); } }
protected override void HandleSetPropertiesOperation(LitePeer peer, SetPropertiesRequest request, SendParameters sendParameters) { byte? newMaxPlayer = null; bool? newIsOpen = null; bool? newIsVisible = null; object[] newLobbyProperties = null; // try to parse build in propeties if game properties should be set (ActorNumber == 0) bool updateGameProperties = request.ActorNumber == 0 && request.Properties != null && request.Properties.Count > 0; // special handling for game and actor properties send by AS3/Flash (Amf3 protocol) or JSON clients if (peer.Protocol.ProtocolType == ProtocolType.Amf3V152 || peer.Protocol.ProtocolType == ProtocolType.Json) { if (updateGameProperties) { Utilities.ConvertAs3WellKnownPropertyKeys(request.Properties, null); } else { Utilities.ConvertAs3WellKnownPropertyKeys(null, request.Properties); } } if (updateGameProperties) { if (!TryParseDefaultProperties(peer, request, request.Properties, sendParameters, out newMaxPlayer, out newIsOpen, out newIsVisible, out newLobbyProperties)) { return; } } base.HandleSetPropertiesOperation(peer, request, sendParameters); // report to master only if game properties are updated if (!updateGameProperties) { return; } // set default properties if (newMaxPlayer.HasValue && newMaxPlayer.Value != this.maxPlayers) { this.maxPlayers = newMaxPlayer.Value; } if (newIsOpen.HasValue && newIsOpen.Value != this.isOpen) { this.isOpen = newIsOpen.Value; } if (newIsVisible.HasValue && newIsVisible.Value != this.isVisible) { this.isVisible = newIsVisible.Value; } if (newLobbyProperties != null) { this.lobbyProperties = new HashSet<object>(newLobbyProperties); } Hashtable gameProperties; if (newLobbyProperties != null) { // if the property filter for the app lobby properties has been changed // all game properties are resend to the master server because the application // lobby might not contain all properties specified. gameProperties = this.GetLobbyGameProperties(this.Properties.GetProperties()); } else { // property filter hasn't chjanged; only the changed properties will // be updatet in the application lobby gameProperties = this.GetLobbyGameProperties(request.Properties); } this.UpdateGameStateOnMaster(newMaxPlayer, newIsOpen, newIsVisible, newLobbyProperties, gameProperties); }
/// <summary> /// Called for each operation in the execution queue. /// Every <see cref = "Room" /> has a queue of incoming operations to execute. /// Per game <see cref = "ExecuteOperation" /> is never executed multi-threaded, thus all code executed here has thread safe access to all instance members. /// </summary> /// <param name = "peer"> /// The peer. /// </param> /// <param name = "operationRequest"> /// The operation request to execute. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected override void ExecuteOperation(LitePeer peer, OperationRequest operationRequest, SendParameters sendParameters) { try { base.ExecuteOperation(peer, operationRequest, sendParameters); if (Log.IsDebugEnabled) { Log.DebugFormat("Executing operation {0}", (OperationCode)operationRequest.OperationCode); } switch ((OperationCode)operationRequest.OperationCode) { case OperationCode.Join: { var joinRequest = new JoinRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(joinRequest, sendParameters) == false) { return; } this.logQueue.Add(new LogEntry("ExecuteOperation: " + (OperationCode)operationRequest.OperationCode, "Peer=" + peer.ConnectionId)); joinRequest.OnStart(); this.HandleJoinOperation(peer, joinRequest, sendParameters); joinRequest.OnComplete(); break; } case OperationCode.Leave: { var leaveOperation = new LeaveRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(leaveOperation, sendParameters) == false) { return; } this.logQueue.Add(new LogEntry("ExecuteOperation: " + (OperationCode)operationRequest.OperationCode, "Peer=" + peer.ConnectionId)); leaveOperation.OnStart(); this.HandleLeaveOperation(peer, leaveOperation, sendParameters); leaveOperation.OnComplete(); break; } case OperationCode.RaiseEvent: { var raiseEventOperation = new RaiseEventRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(raiseEventOperation, sendParameters) == false) { return; } raiseEventOperation.OnStart(); this.HandleRaiseEventOperation(peer, raiseEventOperation, sendParameters); raiseEventOperation.OnComplete(); break; } case OperationCode.GetProperties: { var getPropertiesOperation = new GetPropertiesRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(getPropertiesOperation, sendParameters) == false) { return; } getPropertiesOperation.OnStart(); this.HandleGetPropertiesOperation(peer, getPropertiesOperation, sendParameters); getPropertiesOperation.OnComplete(); break; } case OperationCode.SetProperties: { var setPropertiesOperation = new SetPropertiesRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(setPropertiesOperation, sendParameters) == false) { return; } setPropertiesOperation.OnStart(); this.HandleSetPropertiesOperation(peer, setPropertiesOperation, sendParameters); setPropertiesOperation.OnComplete(); break; } case OperationCode.Ping: { peer.SendOperationResponse(new OperationResponse { OperationCode = operationRequest.OperationCode }, sendParameters); break; } default: { string message = string.Format("Unknown operation code {0}", (OperationCode)operationRequest.OperationCode); peer.SendOperationResponse( new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = -1, DebugMessage = message }, sendParameters); if (Log.IsWarnEnabled) { Log.Warn(message); } } break; } } catch (Exception ex) { Log.Error(ex); } }
protected override void HandleSetPropertiesOperation(LitePeer peer, SetPropertiesRequest request, SendParameters sendParameters) { byte? newMaxPlayer = null; bool? newIsOpen = null; bool? newIsVisible = null; object[] newLobbyProperties = null; // try to parse build in propeties if game properties should be set (ActorNumber == 0) bool updateGameProperties = request.ActorNumber == 0 && request.Properties != null && request.Properties.Count > 0; if (updateGameProperties) { if (!TryParseDefaultProperties(peer, request, request.Properties, sendParameters, out newMaxPlayer, out newIsOpen, out newIsVisible, out newLobbyProperties)) { return; } } base.HandleSetPropertiesOperation(peer, request, sendParameters); // report to master only if game properties are updated if (!updateGameProperties) { return; } Hashtable gameProperties; if (newLobbyProperties != null) { this.lobbyProperties = new HashSet<object>(newLobbyProperties); // app lobby properties have changed. // all new properties which are specified are send to the master server // because the SetPropertiesRequest might not contain all of the new // properties specified. gameProperties = new Hashtable(); foreach (var entry in this.lobbyProperties) { object value; if (this.Properties.TryGetValue(entry, out value)) { gameProperties.Add(entry, value); } } } else { if (this.lobbyProperties == null) { // if no filter is set for properties which should be listet in the lobby // all changed properties are sent to the master gameProperties = request.Properties; } else { gameProperties = new Hashtable(); foreach (var key in this.lobbyProperties) { if (request.Properties.ContainsKey(key)) { gameProperties.Add(key, request.Properties[key]); } } } } if (newMaxPlayer.HasValue && newMaxPlayer.Value != this.maxPlayers) { this.maxPlayers = newMaxPlayer.Value; gameProperties[(byte)GameParameter.MaxPlayer] = this.maxPlayers; } else { gameProperties.Remove((byte)GameParameter.MaxPlayer); } if (newIsOpen.HasValue && newIsOpen.Value != this.isOpen) { this.isOpen = newIsOpen.Value; gameProperties[(byte)GameParameter.IsOpen] = this.isOpen; } else { gameProperties.Remove((byte)GameParameter.IsOpen); } if (newIsVisible.HasValue && newIsVisible.Value != this.isVisible) { this.isVisible = newIsVisible.Value; gameProperties[(byte)GameParameter.IsVisible] = this.isVisible; } else { gameProperties.Remove((byte)GameParameter.IsVisible); } if (newLobbyProperties != null) { gameProperties[(byte)GameParameter.Properties] = newLobbyProperties; } this.UpdateGameStateOnMaster(gameProperties, null, null, false); }