예제 #1
0
        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);
        }
예제 #2
0
 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);
 }
예제 #3
0
        /// <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);
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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;
        }
예제 #6
0
        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;
        }
예제 #7
0
        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;
        }
예제 #8
0
 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);
     }
 }
예제 #9
0
 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);
 }
예제 #10
0
        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;
        }
예제 #11
0
        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);
        }
예제 #12
0
 protected virtual bool ProcessSetProperties(HivePeer peer, bool result, string errorMsg, SetPropertiesRequest request, SendParameters sendParameters)
 {
     this.PublishResultsAndSetGameProperties(result, errorMsg, request, peer, sendParameters);
     return true;
 }
예제 #13
0
        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;
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        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);
        }
예제 #16
0
        protected Hashtable GetOldPropertyValues(SetPropertiesRequest request)
        {
            if (request.TargetActor != null)
            {
                return request.TargetActor.Properties.GetProperties(request.Properties.Keys);
            }

            return this.Properties.GetProperties(request.Properties.Keys);
        }
예제 #17
0
 /// <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);
 }
예제 #18
0
        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);
        }