protected override bool ProcessSetProperties(HivePeer peer, bool result, string errorMsg, SetPropertiesRequest request, SendParameters sendParameters) { var value = (string)request.Properties["ActorProperty"]; if (value == "OnSetPropertiesExceptionInContinue") { request = null; } return base.ProcessSetProperties(peer, result, errorMsg, request, sendParameters); }
protected override bool ProcessBeforeSetProperties(HivePeer peer, SetPropertiesRequest request, Hashtable oldValues, SendParameters sendParameters) { var value = (string)request.Properties["ActorProperty"]; if (value == "BeforeSetPropertiesExceptionInContinue") { peer = null; request.TargetActor = null; request.ActorNumber = 1; } return base.ProcessBeforeSetProperties(peer, request, oldValues, sendParameters); }
/// <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(HivePeer 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.CreateGame2: { var createGameRequest = new CreateGameRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(createGameRequest, sendParameters) == false) { return; } this.LogOperation(peer, operationRequest); createGameRequest.OnStart(); this.HandleCreateGameOperation(peer, sendParameters, createGameRequest); createGameRequest.OnComplete(); } break; case OperationCode.Join: case OperationCode.JoinGame2: { var joinGameRequest = new JoinGameRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(joinGameRequest, sendParameters) == false) { return; } // Join should be default CreateIfNotexists=true //if (!joinGameRequest.CreateIfNotExists && operationRequest.OperationCode == (byte)OperationCode.Join) //{ // joinGameRequest.CreateIfNotExists = true; //} this.LogOperation(peer, operationRequest); joinGameRequest.OnStart(); this.HandleJoinGameOperation(peer, sendParameters, joinGameRequest); joinGameRequest.OnComplete(); } break; case OperationCode.DebugGame: var debugGameRequest = new DebugGameRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(debugGameRequest, sendParameters) == false) { return; } this.LogOperation(peer, operationRequest); debugGameRequest.OnStart(); this.HandleDebugGameOperation(peer, debugGameRequest, sendParameters); debugGameRequest.OnComplete(); break; case OperationCode.Leave: { var leaveOperation = new LeaveRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(leaveOperation, sendParameters) == false) { return; } this.LogOperation(peer, operationRequest); leaveOperation.OnStart(); this.HandleLeaveOperation(peer, sendParameters, leaveOperation); 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 (operationRequest.OperationCode) , sendParameters); break; } case OperationCode.ChangeGroups: { var changeGroupsOperation = new ChangeGroups(peer.Protocol, operationRequest); if (peer.ValidateOperation(changeGroupsOperation, sendParameters) == false) { return; } changeGroupsOperation.OnStart(); this.HandleChangeGroupsOperation(peer, changeGroupsOperation, sendParameters); changeGroupsOperation.OnComplete(); break; } default: { var message = string.Format("Unknown operation code {0}", (OperationCode)operationRequest.OperationCode); this.SendErrorResponse(peer, operationRequest.OperationCode, ErrorCode.OperationInvalid, message, sendParameters); if (Log.IsWarnEnabled) { Log.Warn(message); } } break; } } catch (Exception ex) { Log.Error(ex); } }
private void UpdateGameProperties(SetPropertiesRequest request) { // set default properties if (request.newMaxPlayer.HasValue && request.newMaxPlayer.Value != this.MaxPlayers) { this.MaxPlayers = request.newMaxPlayer.Value; } if (request.newIsOpen.HasValue && request.newIsOpen.Value != this.IsOpen) { this.IsOpen = request.newIsOpen.Value; } if (request.newIsVisible.HasValue && request.newIsVisible.Value != this.IsVisible) { this.IsVisible = request.newIsVisible.Value; } if (request.newLobbyProperties != null) { this.LobbyProperties = new HashSet<object>(request.newLobbyProperties); } if (request.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. request.newGameProperties = this.GetLobbyGameProperties(this.Properties.GetProperties()); } else { // property filter hasn't changed; only the changed properties will // be updatet in the application lobby request.newGameProperties = this.GetLobbyGameProperties(request.Properties); } this.OnGamePropertiesChanged(request); }
protected bool ValidateAndFillSetPropertiesRequest(HivePeer peer, SetPropertiesRequest request, out string errorMsg) { if (peer != null) { request.SenderActor = this.GetActorByPeer(peer); if (request.SenderActor == null) { errorMsg = HiveErrorMessages.PeetNotJoinedToRoom; return false; } } if (request.ActorNumber > 0) { request.TargetActor = this.ActorsManager.ActorsGetActorByNumber(request.ActorNumber); if (request.TargetActor == null) { errorMsg = string.Format(HiveErrorMessages.ActorNotFound, request.ActorNumber); return false; } } // we need to broadcast either in case if request.Broadcast is true and propertiesUpdateResult is true or // if request.Broadcast is false and propertiesUpdateResult is true and CAS was used // if broadcast is set a EvPropertiesChanged // event will be send to room actors if (request.Broadcast || request.UsingCAS) { // UsingCAS we publish to 'All' else to 'Others' request.PublishTo = request.UsingCAS ? this.ActorsManager.Actors : this.ActorsManager.ActorsGetExcludedList(request.SenderActor); } errorMsg = null; return true; }
protected bool SetPropertiesRequestHandler(HivePeer peer, SetPropertiesRequest request, SendParameters sendParameters) { string errorMsg; if (!this.ValidateAndFillSetPropertiesRequest(peer, request, out errorMsg)) { if (peer != null) { this.SendErrorResponse(peer, request.OperationCode, ErrorCode.OperationInvalid, errorMsg, sendParameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' failed to set propeties. msg:{2} -- peer:{3}", this.Name, peer.UserId, errorMsg); } } else { throw new Exception(errorMsg); } return false; } var oldProperties = this.GetOldPropertyValues(request); var propertiesUpdateResult = this.SetNewPropertyValues(request, out errorMsg); if (!propertiesUpdateResult) { this.RevertProperties(oldProperties, request); } this.PublishResultsAndSetGameProperties(propertiesUpdateResult, errorMsg, request, peer, sendParameters); return true; }
protected virtual bool SetNewPropertyValues(SetPropertiesRequest request, out string errorMessage) { var propertiesUpdateResult = true; errorMessage = null; if (request.ActorNumber > 0) { if (request.Properties != null) { // this is set by the server only request.Properties.Remove((byte)ActorParameter.IsInactive); request.Properties.Remove((byte)ActorParameter.UserId); } propertiesUpdateResult = request.TargetActor.Properties.SetPropertiesCAS(request.Properties, request.ExpectedValues, out errorMessage); } else { if (request.MasterClientId.HasValue) { propertiesUpdateResult = this.CheckMasterClientIdValue(request.MasterClientId.Value, out errorMessage); } if (request.ExpectedUsers != null && request.ExpectedValues == null) { errorMessage = "ExpectedUsers may be updated only in CAS mode"; return false; } propertiesUpdateResult = propertiesUpdateResult && this.Properties.SetPropertiesCAS(request.Properties, request.ExpectedValues, out errorMessage); if (propertiesUpdateResult && request.MasterClientId.HasValue) { this.MasterClientId = request.MasterClientId.Value; } if (propertiesUpdateResult && request.ExpectedUsers != null) { var prevExpectedUsers = (string[])request.ExpectedValues[(byte) GameParameter.ExpectedUsers]; return this.UpdateExpectedUsersList(request.ExpectedUsers, prevExpectedUsers, out errorMessage); } } return propertiesUpdateResult; }
protected void RevertProperties(IDictionary oldPropertyValues, SetPropertiesRequest request) { // return back property values if (request.TargetActor != null) { request.TargetActor.Properties.SetProperties(oldPropertyValues); } else { this.Properties.SetProperties(oldPropertyValues); } }
protected virtual void OnGamePropertiesChanged(SetPropertiesRequest request) { Log.DebugFormat("MaxPlayer={0}, IsOpen={0}, IsVisible={0}, LobbyProperties={0}, GameProperties={0}", request.newMaxPlayer, request.newIsOpen, request.newIsVisible, request.newLobbyProperties, request.newGameProperties); }
bool IPluginHost.SetProperties(int actorNr, Hashtable properties, Hashtable expected, bool broadcast) { var request = new SetPropertiesRequest(actorNr, properties, expected, broadcast); string errorMsg; if (!this.ValidateAndFillSetPropertiesRequest(null, request, out errorMsg)) { throw new Exception(errorMsg); } var propertiesUpdateResult = this.SetNewPropertyValues(request, out errorMsg); this.PublishResultsAndSetGameProperties(propertiesUpdateResult, errorMsg, request, null, new SendParameters()); return true; }
private void OnSetPropertiesFailHandler(string errorMessage, Dictionary<byte, object> parameters, Hashtable oldPropertyValues, SetPropertiesRequest request, HivePeer peer, SendParameters sendParameters) { LogPlugin.Error(errorMessage); this.SendErrorResponse(peer, request.OperationCode, ErrorCode.PluginReportedError, errorMessage, sendParameters, parameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' SetProperties plugin error. msg:{2} -- peer:{3}", this.Name, peer.UserId, errorMessage, peer); } this.RevertProperties(oldPropertyValues, request); }
protected virtual bool ProcessSetProperties(HivePeer peer, bool result, string errorMsg, SetPropertiesRequest request, SendParameters sendParameters) { this.PublishResultsAndSetGameProperties(result, errorMsg, request, peer, sendParameters); return true; }
protected virtual bool ProcessBeforeSetProperties(HivePeer peer, SetPropertiesRequest request, Hashtable oldValues, SendParameters sendParameters) { string errorMsg; if (!this.SetNewPropertyValues(request, out errorMsg)) { this.RevertProperties(oldValues, request); this.SendErrorResponse(peer, (byte)OperationCode.SetProperties, ErrorCode.OperationInvalid, errorMsg, sendParameters); this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.SetPropertiesCASFail, null, errorMsg); return false; } RequestHandler handler = () => { try { return this.ProcessSetProperties(peer, true, string.Empty, request, sendParameters); } catch (Exception e) { this.RevertProperties(oldValues, request); this.SendErrorResponse(peer, (byte)OperationCode.SetProperties, ErrorCode.InternalServerError, e.ToString(), sendParameters); this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.SetPropertiesException, e, request); Log.Error(e); return false; } }; // we checked that actor is not null in HandleSetPropertiesOperation, but // it is still possible that actor will be null, because we do not know // how plugin will handle OnBeforeSetProperties. if it will do http request, than client peer may disconnect // so, we still need to check that client is not null var actor = request.SenderActor; var info = new SetPropertiesCallInfo(this.PendingPluginContinue, this.callEnv) { Request = request, Handler = handler, Peer = peer, UserId = peer.UserId, Nickname = actor != null ? actor.Nickname : string.Empty, SendParams = sendParameters, ActorNr = actor != null ? actor.ActorNr : -1, OnFail = (errorMessage, objects) => this.OnSetPropertiesFailHandler(errorMessage, objects, oldValues, request, peer, sendParameters), }; try { this.Plugin.OnSetProperties(info); } catch (Exception e) { this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e); } return true; }
protected override void HandleSetPropertiesOperation(HivePeer peer, SetPropertiesRequest request, SendParameters sendParameters) { var actor = this.ActorsManager.ActorsGetActorByPeer(peer); if (actor == null) { this.SendErrorResponse(peer, request.OperationCode, ErrorCode.OperationInvalid, HiveErrorMessages.PeetNotJoinedToRoom, sendParameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' SetProperties failed. msg:{2} -- peer:{3}", this.Name, peer.UserId, HiveErrorMessages.PeetNotJoinedToRoom, peer); } return; } if (request.HttpForward && this.HttpForwardedOperationsLimit > 0 && this.httpForwardedRequests.Increment(1) > this.HttpForwardedOperationsLimit) { this.SendErrorResponse(peer, request.OperationCode, ErrorCode.HttpLimitReached, HiveErrorMessages.HttpForwardedOperationsLimitReached, sendParameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' SetProperties failed. msg:{2} -- peer:{3}", this.Name, peer.UserId, HiveErrorMessages.HttpForwardedOperationsLimitReached, peer); } return; } RequestHandler handler = () => { Hashtable oldValues = null; try { string errorMsg; if (!this.ValidateAndFillSetPropertiesRequest(peer, request, out errorMsg)) { this.SendErrorResponse(peer, (byte)OperationCode.SetProperties, ErrorCode.OperationInvalid, errorMsg, sendParameters); this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.SetPropertiesPreconditionsFail, null, errorMsg); return false; } oldValues = this.GetOldPropertyValues(request); return this.ProcessBeforeSetProperties(peer, request, oldValues, sendParameters); } catch (Exception e) { if (oldValues != null) { this.RevertProperties(oldValues, request); } this.SendErrorResponse(peer, (byte)OperationCode.SetProperties, ErrorCode.InternalServerError, e.ToString(), sendParameters); this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e, request); Log.Error(e); return false; } }; var info = new BeforeSetPropertiesCallInfo(this.PendingPluginContinue, this.callEnv) { Request = request, UserId = peer.UserId, Nickname = actor.Nickname, Handler = handler, Peer = peer, SendParams = sendParameters, ActorNr = actor.ActorNr, }; try { this.Plugin.BeforeSetProperties(info); } catch (Exception e) { this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e); } }
protected override void OnGamePropertiesChanged(SetPropertiesRequest request) { Log.DebugFormat("MaxPlayer={0}, IsOpen={1}, IsVisible={2}, #LobbyProperties={3}, #GameProperties={4}", request.newMaxPlayer, request.newIsOpen, request.newIsVisible, request.newLobbyProperties == null ? 0 : request.newLobbyProperties.Count(), request.newGameProperties == null ? 0 : request.newGameProperties.Count); var expectedList = this.ActorsManager.ExpectedUsers.ToArray(); this.UpdateGameStateOnMaster(request.newMaxPlayer, request.newIsOpen, request.newIsVisible, request.newLobbyProperties, request.newGameProperties, expectedList: expectedList); }
protected Hashtable GetOldPropertyValues(SetPropertiesRequest request) { if (request.TargetActor != null) { return request.TargetActor.Properties.GetProperties(request.Properties.Keys); } return this.Properties.GetProperties(request.Properties.Keys); }
/// <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 = "request"> /// The <see cref = "SetPropertiesRequest" /> operation to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleSetPropertiesOperation(HivePeer peer, SetPropertiesRequest request, SendParameters sendParameters) { this.SetPropertiesRequestHandler(peer, request, sendParameters); }
protected void PublishResultsAndSetGameProperties(bool propertiesUpdateResult, string errorMessage, SetPropertiesRequest request, HivePeer peer, SendParameters sendParameters) { //for internal use we allow the peer to be null - meaning this is a property set by the server if (peer != null) { this.SendErrorResponse(peer, request.OperationCode, propertiesUpdateResult ? ErrorCode.Ok : ErrorCode.OperationInvalid, errorMessage, sendParameters); if (!propertiesUpdateResult) { if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' failed to SetProperties. msg:{2} -- peer:{3}", this.Name, peer.UserId, errorMessage, peer); } } } if (request.PublishTo != null && propertiesUpdateResult) { var propertiesChangedEvent = new PropertiesChangedEvent(request.SenderActor != null ? request.SenderActor.ActorNr : 0) { TargetActorNumber = request.ActorNumber, Properties = request.Properties }; this.PublishEvent(propertiesChangedEvent, request.PublishTo, sendParameters); } // report to master only if game properties are updated if (!request.UpdatingGameProperties || !propertiesUpdateResult) { return; } this.UpdateGameProperties(request); }