/// <summary>
        ///   Enqueues game related operation requests in the peers current game.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        /// <remarks>
        ///   The current for a peer is stored in the peers state property.
        ///   Using the <see cref = "Room.EnqueueOperation" /> method ensures that all operation request dispatch logic has thread safe access to all room instance members since they are processed in a serial order.
        ///   <para>
        ///     Inheritors can use this method to enqueue there custom game operation to the peers current game.
        ///   </para>
        /// </remarks>
        private void HandleChangeGroupsOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (this.joinStage < JoinStages.PublishingEvents)
            {
                this.OnWrongOperationStage(operationRequest, sendParameters);
                return;
            }

            var changeGroupsOperation = new ChangeGroups(this.Protocol, operationRequest);

            if (this.ValidateOperation(changeGroupsOperation, sendParameters) == false)
            {
                return;
            }

            this.AddOperationToQueue(operationRequest.OperationCode, "game op");

            // enqueue operation into game queue.
            // the operation request will be processed in the games ExecuteOperation method.
            if (this.RoomReference != null)
            {
                this.RoomReference.Room.EnqueueOperation(this, changeGroupsOperation, sendParameters);
                return;
            }

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("Received ChangeGroups operation on peer without a game: p:{0}", this);
            }
        }
        /// <summary>
        /// Handles WebRpc operation
        /// </summary>
        /// <param name = "request">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleRpcOperation(OperationRequest request, SendParameters sendParameters)
        {
            this.AddOperationToQueue(request.OperationCode);

            if (this.WebRpcHandler != null)
            {
                if (this.HttpRpcCallsLimit > 0 && this.httpForwardedRequests.Increment(1) > this.HttpRpcCallsLimit)
                {
                    var resp = new OperationResponse
                    {
                        OperationCode = request.OperationCode,
                        ReturnCode    = (short)ErrorCode.HttpLimitReached,
                        DebugMessage  = String.Format(HiveErrorMessages.HttpForwardedOperationsLimitReached, this.HttpRpcCallsLimit)
                    };

                    this.SendOperationResponse(resp, sendParameters);
                    return;
                }

                this.WebRpcHandler.HandleCall(this, this.UserId, request, this.AuthCookie, sendParameters);
                return;
            }

            this.SendOperationResponse(new OperationResponse
            {
                OperationCode = request.OperationCode,
                ReturnCode    = (short)ErrorCode.OperationInvalid,
                DebugMessage  = HiveErrorMessages.WebRpcIsNotEnabled,
            }, sendParameters);
        }
Beispiel #3
0
        /// <summary>
        ///   Publishes an event to a list of actors on a specified channel.
        /// </summary>
        /// <param name = "e">
        ///   The event to publish.
        /// </param>
        /// <param name = "actorList">
        ///   A list of <see cref = "Actor" /> who should receive the event.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected void PublishEvent(HiveEventBase e, IEnumerable <Actor> actorList, SendParameters sendParameters)
        {
            var peers     = actorList.Select(actor => actor.Peer);
            var eventData = new EventData(e.Code, e);

            ApplicationBase.Instance.BroadCastEvent(eventData, peers, sendParameters);
        }
 private void OnWrongOperationStage(OperationRequest operationRequest, SendParameters sendParameters)
 {
     this.SendOperationResponse(new OperationResponse
     {
         OperationCode = operationRequest.OperationCode,
         ReturnCode    = (short)ErrorCode.OperationDenied,
         DebugMessage  = HiveErrorMessages.OperationIsNotAllowedOnThisJoinStage,
     }, sendParameters);
 }
Beispiel #5
0
        private void SendErrorResponse(PeerBase peer, byte opCode, SendParameters sp, short retCode = (short)ErrorCode.ExternalHttpCallFailed, string msg = "", Dictionary <byte, object> parameters = null)
        {
            var response = new OperationResponse(opCode)
            {
                DebugMessage = msg,
                ReturnCode   = retCode,
                Parameters   = parameters
            };

            peer.SendOperationResponse(response, sp);
        }
        protected void HandleUnknownOperationCode(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (log.IsDebugEnabled)
            {
                log.DebugFormat("Unknown operation code: OpCode={0}", operationRequest.OperationCode);
            }

            this.SendOperationResponse(
                new OperationResponse(operationRequest.OperationCode)
            {
                ReturnCode   = (short)ErrorCode.OperationInvalid,
                DebugMessage = HiveErrorMessages.UnknownOperationCode
            }, sendParameters);
        }
        /// <summary>
        ///   Checks if a operation is valid. If the operation is not valid
        ///   an operation response containing a desciptive error message
        ///   will be sent to the peer.
        /// </summary>
        /// <param name = "operation">
        ///   The operation.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        /// <returns>
        ///   true if the operation is valid; otherwise false.
        /// </returns>
        public bool ValidateOperation(Operation operation, SendParameters sendParameters)
        {
            if (operation.IsValid)
            {
                return(true);
            }

            var errorMessage = operation.GetErrorMessage();

            this.SendOperationResponse(new OperationResponse
            {
                OperationCode = operation.OperationRequest.OperationCode,
                ReturnCode    = (short)ErrorCode.OperationInvalid,
                DebugMessage  = errorMessage
            },
                                       sendParameters);
            return(false);
        }
        private void HandleRoomNotFound(SendParameters sendParameters, JoinGameRequest joinRequest)
        {
            this.OnRoomNotFound(joinRequest.GameId);

            var response = new OperationResponse
            {
                OperationCode = (byte)OperationCode.JoinGame,
                ReturnCode    = (short)ErrorCode.GameIdNotExists,
                DebugMessage  = HiveErrorMessages.GameIdDoesNotExist,
            };

            this.SendOperationResponse(response, sendParameters);

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}", joinRequest.GameId, this.UserId,
                                HiveErrorMessages.GameIdDoesNotExist, this);
            }
        }
Beispiel #9
0
        protected bool CreateGame(HivePeer peer, JoinGameRequest request, SendParameters sendParameters)
        {
            peer.JoinStage = HivePeer.JoinStages.CreatingOrLoadingGame;

            return this.Join(peer, request, sendParameters);
        }
Beispiel #10
0
        protected bool JoinSendResponseAndEvents(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters, int actorNr, ProcessJoinParams prms)
        {
            peer.JoinStage = HivePeer.JoinStages.GettingUserResponse;
            var oresponse = this.GetUserJoinResponse(joinRequest, actorNr, prms);
            peer.SendOperationResponse(oresponse, sendParameters);

            peer.JoinStage = HivePeer.JoinStages.PublishingEvents;
            this.PublishJoinEvent(peer, joinRequest);
            peer.JoinStage = HivePeer.JoinStages.EventsPublished;
            this.PublishEventCache(peer, joinRequest);

            peer.JoinStage = HivePeer.JoinStages.Complete;
            return true;
        }
Beispiel #11
0
        /// <summary>
        ///   Handles the <see cref = "JoinGameRequest" /> to enter a <see cref = "HiveGame" />.
        ///   This method removes the peer from any previously joined room, finds the room intended for join
        ///   and enqueues the operation for it to handle.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleJoinGameOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (this.JoinStage != JoinStages.Connected)
            {
                this.OnWrongOperationStage(operationRequest, sendParameters);
                return;
            }

            // create join operation
            var joinRequest = new JoinGameRequest(this.Protocol, operationRequest);

            if (this.ValidateOperation(joinRequest, sendParameters) == false)
            {
                return;
            }

            // remove peer from current game
            this.RemovePeerFromCurrentRoom(LeaveReason.SwitchRoom, "eventual switch from other room.");

            // try to get the game reference from the game cache
            RoomReference gameReference;
            var           pluginTraits = this.GetPluginTraits();

            if (joinRequest.JoinMode > 0 || pluginTraits.AllowAsyncJoin)
            {
                var pluginName = joinRequest.Plugins != null && joinRequest.Plugins.Length > 0? joinRequest.Plugins[0] : String.Empty;
                gameReference = this.GetOrCreateRoom(joinRequest.GameId, pluginName);
            }
            else
            {
                if (this.TryGetRoomReference(joinRequest.GameId, out gameReference) == false)
                {
                    this.OnRoomNotFound(joinRequest.GameId);

                    var response = new OperationResponse
                    {
                        OperationCode = (byte)OperationCode.JoinGame,
                        ReturnCode    = (short)ErrorCode.GameIdNotExists,
                        DebugMessage  = HiveErrorMessages.GameIdDoesNotExist,
                    };

                    this.SendOperationResponse(response, sendParameters);

                    if (log.IsWarnEnabled)
                    {
                        log.WarnFormat("Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}", joinRequest.GameId, this.UserId, HiveErrorMessages.GameIdDoesNotExist, this);
                    }

                    return;
                }
            }

            // save the game reference in the peers state
            this.RoomReference = gameReference;

            // finally enqueue the operation into game queue
            gameReference.Room.EnqueueOperation(this, operationRequest, sendParameters);
        }
Beispiel #12
0
        /// <summary>
        ///   Handles the <see cref = "LeaveRequest" /> to leave a <see cref = "HiveGame" />.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleLeaveOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            // check if the peer have a reference to game
            if (this.RoomReference == null)
            {
                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("Received leave operation on peer without a game: peerId={0}", this.ConnectionId);
                }

                return;
            }

            // enqueue the leave operation into game queue.
            this.RoomReference.Room.EnqueueOperation(this, operationRequest, sendParameters);

            this.ReleaseRoomReferenceInternal();
        }
Beispiel #13
0
        protected override void HandleCreateGameOperation(HivePeer peer, SendParameters sendParameters, CreateGameRequest createGameRequest)
        {
            if (this.isClosed)
            {
                if (!this.ReinitGame())
                {
                    this.SendErrorResponse(peer, createGameRequest.OperationCode,
                        ErrorCode.InternalServerError, HiveErrorMessages.ReinitGameFailed, sendParameters);

                    createGameRequest.OnJoinFailed(ErrorCode.InternalServerError, HiveErrorMessages.ReinitGameFailed);

                    this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, createGameRequest);

                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat("Game '{0}' userId '{1}' failed to create game. msg:{2} -- peer:{3}", this.Name, peer.UserId,
                            HiveErrorMessages.ReinitGameFailed, peer);
                    }

                    return;
                }
            }

            string msg;
            if (!this.ValidatePlugin(createGameRequest, out msg))
            {
                this.SendErrorResponse(peer, createGameRequest.OperationCode, ErrorCode.PluginMismatch, msg, sendParameters);
                createGameRequest.OnJoinFailed(ErrorCode.PluginMismatch, msg);
                this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, createGameRequest);

                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("Game '{0}' userId '{1}' failed to create game. msg:{2} -- peer:{3}", this.Name, peer.UserId, msg, peer);
                }
                return;
            }

            this.HandleCreateGameOperationInt(peer, sendParameters, createGameRequest);
        }
Beispiel #14
0
 /// <summary>
 /// Handles the <see cref="JoinGameRequest"/>: Joins a peer to a room and calls <see cref="PublishJoinEvent"/>.
 ///   Before a JoinOperation reaches this point (inside a room), the <see cref="HivePeer"/> made 
 ///   sure that it is removed from the previous Room (if there was any).
 /// </summary>
 /// <param name="peer">
 /// The peer.
 /// </param>
 /// <param name="sendParameters">
 /// The send Parameters.
 /// </param>
 /// <param name="joinGameRequest">
 /// The join Game Request.
 /// </param>
 protected virtual void HandleJoinGameOperation(HivePeer peer, SendParameters sendParameters, JoinGameRequest joinGameRequest)
 {
     this.Join(peer, joinGameRequest, sendParameters);
 }
Beispiel #15
0
        protected bool Join(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters)
        {
            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("Processing Join from IP: {0} to port: {1}", peer.RemoteIP, peer.LocalPort);
            }

            Actor a;
            if (this.JoinApplyGameStateChanges(peer, joinRequest, sendParameters, out a))
            {
                return this.JoinSendResponseAndEvents(peer, joinRequest, sendParameters, a.ActorNr, new ProcessJoinParams());
            }

            this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, joinRequest);

            return false;
        }
Beispiel #16
0
        /// <summary>
        ///   Handles the <see cref = "JoinGameRequest" /> to enter a <see cref = "HiveGame" />.
        ///   This method removes the peer from any previously joined room, finds the room intended for join
        ///   and enqueues the operation for it to handle.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleJoinOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (this.JoinStage != JoinStages.Connected)
            {
                this.OnWrongOperationStage(operationRequest, sendParameters);
                return;
            }

            // create join operation
            var joinRequest = new JoinGameRequest(this.Protocol, operationRequest);

            if (this.ValidateOperation(joinRequest, sendParameters) == false)
            {
                return;
            }

            // remove peer from current game
            this.RemovePeerFromCurrentRoom(LeaveReason.SwitchRoom, "eventual switch from other room.");

            // get a game reference from the game cache
            // the game will be created by the cache if it does not exists already
            var pluginName    = joinRequest.Plugins != null && joinRequest.Plugins.Length > 0 ? joinRequest.Plugins[0] : String.Empty;
            var gameReference = this.GetRoomReference(joinRequest, pluginName);

            // save the game reference in the peers state
            this.RoomReference = gameReference;

            // finally enqueue the operation into game queue
            gameReference.Room.EnqueueOperation(this, operationRequest, sendParameters);
        }
        /// <summary>
        ///   Called when the client sends an <see cref = "OperationRequest" />.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            Dictionary <byte, object> dict = operationRequest.Parameters;

            foreach (object value in dict.Values)
            {
                log.Info("============HivePeer==========:" + value.ToString());
            }
            if (log.IsDebugEnabled)
            {
                log.DebugFormat("OnOperationRequest. Code={0}", operationRequest.OperationCode);
            }

            var opCode = (OperationCode)operationRequest.OperationCode;

            switch (opCode)
            {
            case OperationCode.Authenticate:
                this.AddOperationToQueue(operationRequest.OperationCode);
                return;

            case OperationCode.CreateGame:
                this.AddOperationToQueue(operationRequest.OperationCode);
                this.HandleCreateGameOperation(operationRequest, sendParameters);
                return;

            case OperationCode.JoinGame:
                this.HandleJoinGameOperation(operationRequest, sendParameters);
                return;

            case OperationCode.Ping:
                this.HandlePingOperation(operationRequest, sendParameters);
                return;

            case OperationCode.DebugGame:
                this.HandleDebugGameOperation(operationRequest, sendParameters);
                return;

            case OperationCode.Leave:
                this.HandleLeaveOperation(operationRequest, sendParameters);
                return;

            case OperationCode.RaiseEvent:
                this.HandleRaiseEventOperation(operationRequest, sendParameters);
                return;

            case OperationCode.GetProperties:
                this.HandleGetPropertiesOperation(operationRequest, sendParameters);
                return;

            case OperationCode.SetProperties:
                this.HandleSetPropertiesOperation(operationRequest, sendParameters);
                return;

            case OperationCode.ChangeGroups:
                this.HandleChangeGroupsOperation(operationRequest, sendParameters);
                return;

            case OperationCode.Rpc:
                this.HandleRpcOperation(operationRequest, sendParameters);
                return;

            default:
                this.HandleUnknownOperationCode(operationRequest, sendParameters);
                return;
            }
        }
        /// <summary>
        ///   Handles the <see cref = "LeaveRequest" /> to leave a <see cref = "HiveGame" />.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleLeaveOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            // check if the peer have a reference to game
            if (this.RoomReference == null)
            {
                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("Received leave operation on peer without a game: peerId={0}", this.ConnectionId);
                }

                return;
            }

            var leaveOperation = new LeaveRequest(this.Protocol, operationRequest);

            if (this.ValidateOperation(leaveOperation, sendParameters) == false)
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug($"Wrong leave request. Use default one. errorMsg:{leaveOperation.GetErrorMessage()}");
                }
                // we create default request to remove actor for sure
                leaveOperation = new LeaveRequest(this.Protocol, EmptyLeaveRequest);
            }

            this.AddOperationToQueue(operationRequest.OperationCode, $"IsInActive:{leaveOperation.IsCommingBack}");

            var rr = this.RoomReference;

            this.RoomReference = null;
            // enqueue the leave operation into game queue.
            rr.Room.EnqueueOperation(this, leaveOperation, sendParameters);

            DisposeRoomReference(rr);
        }
        /// <summary>
        ///   Handles a ping operation.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandlePingOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            this.AddOperationToQueue(operationRequest.OperationCode);

            this.SendOperationResponse(new OperationResponse {
                OperationCode = operationRequest.OperationCode
            }, sendParameters);
        }
        /// <summary>
        ///   Handles the <see cref = "JoinGameRequest" /> to enter a <see cref = "HiveGame" />.
        ///   This method removes the peer from any previously joined room, finds the room intended for join
        ///   and enqueues the operation for it to handle.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleJoinGameOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (this.JoinStage != JoinStages.Connected || this.RoomReference != null)
            {
                this.OnWrongOperationStage(operationRequest, sendParameters);
                return;
            }

            // create join operation
            var joinRequest = new JoinGameRequest(this.Protocol, operationRequest, this.UserId);

            if (this.ValidateOperation(joinRequest, sendParameters) == false)
            {
                return;
            }

            // try to get the game reference from the game cache
            RoomReference gameReference;
            var           pluginTraits = this.GetPluginTraits();

            if (joinRequest.JoinMode > 0 || pluginTraits.AllowAsyncJoin)
            {
                gameReference = this.GetOrCreateRoom(joinRequest.GameId);
            }
            else
            {
                if (this.TryGetRoomReference(joinRequest.GameId, out gameReference) == false)
                {
                    this.HandleRoomNotFound(sendParameters, joinRequest);
                    return;
                }
            }

            // save the game reference in the peers state
            this.RoomReference  = gameReference;
            this.roomCreationTS = gameReference.Room.RoomCreationTS;

            this.AddOperationToQueue(operationRequest.OperationCode, $"JoinMode:{joinRequest.JoinMode}");

            // finally enqueue the operation into game queue
            gameReference.Room.EnqueueOperation(this, joinRequest, sendParameters);
        }
Beispiel #21
0
        protected virtual void HandleCreateGameOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            // The JoinRequest from the Lite application is also used for create game operations to support all feaures
            // provided by Lite games.
            // The only difference is the operation code to prevent games created by a join operation.
            // On "LoadBalancing" game servers games must by created first by the game creator to ensure that no other joining peer
            // reaches the game server before the game is created.
            var createRequest = new JoinGameRequest(this.Protocol, operationRequest);

            if (this.ValidateOperation(createRequest, sendParameters) == false)
            {
                return;
            }

            // remove peer from current game
            this.RemovePeerFromCurrentRoom(LeaveReason.SwitchRoom, "eventual switch from other room.");

            var pluginName = createRequest.Plugins != null && createRequest.Plugins.Length > 0 ? createRequest.Plugins[0] : String.Empty;

            // try to create the game
            RoomReference gameReference;

            if (this.TryCreateRoom(createRequest.GameId, out gameReference, pluginName) == false)
            {
                var response = new OperationResponse
                {
                    OperationCode = (byte)OperationCode.CreateGame,
                    ReturnCode    = (short)ErrorCode.GameIdAlreadyExists,
                    DebugMessage  = HiveErrorMessages.GameAlreadyExist,
                };

                this.SendOperationResponse(response, sendParameters);
                return;
            }

            // save the game reference in the peers state
            this.RoomReference = gameReference;

            // finally enqueue the operation into game queue
            gameReference.Room.EnqueueOperation(this, operationRequest, sendParameters);
        }
        protected virtual void HandleCreateGameOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (this.JoinStage != JoinStages.Connected || this.RoomReference != null)
            {
                this.OnWrongOperationStage(operationRequest, sendParameters);
                return;
            }

            // On "LoadBalancing" game servers games must by created first by the game creator to ensure that no other joining peer
            // reaches the game server before the game is created.
            // we use JoinGameRequest to make sure that GameId is set
            var createRequest = new JoinGameRequest(this.Protocol, operationRequest, this.UserId);

            if (this.ValidateOperation(createRequest, sendParameters) == false)
            {
                return;
            }

            // try to create the game
            RoomReference gameReference;

            if (this.TryCreateRoom(createRequest.GameId, out gameReference) == false)
            {
                var response = new OperationResponse
                {
                    OperationCode = (byte)OperationCode.CreateGame,
                    ReturnCode    = (short)ErrorCode.GameIdAlreadyExists,
                    DebugMessage  = HiveErrorMessages.GameAlreadyExist,
                };

                this.SendOperationResponse(response, sendParameters);
                return;
            }

            // save the game reference in the peers state
            this.RoomReference = gameReference;

            this.roomCreationTS = gameReference.Room.RoomCreationTS;

            this.AddOperationToQueue(operationRequest.OperationCode);
            // finally enqueue the operation into game queue
            gameReference.Room.EnqueueOperation(this, createRequest, sendParameters);
        }
Beispiel #23
0
        protected virtual void HandleChangeGroupsOperation(HivePeer peer, ChangeGroups changeGroupsRequest, SendParameters sendParameters)
        {
            // get the actor who send the operation request
            var actor = this.GetActorByPeer(peer);
            if (actor == null)
            {
                return;
            }

            actor.RemoveGroups(changeGroupsRequest.Remove);

            if (changeGroupsRequest.Add != null)
            {
                if (changeGroupsRequest.Add.Length > 0)
                {
                    foreach (byte groupId in changeGroupsRequest.Add)
                    {
                        this.GroupManager.AddActorToGroup(groupId, actor);
                    }
                }
                else
                {
                    this.GroupManager.AddToAllGroups(actor);
                }
            }
        }
Beispiel #24
0
 protected virtual bool ProcessLeaveGame(int actorNr, LeaveRequest request, SendParameters sendParameters, HivePeer peer)
 {
     this.LeaveOperationHandler(peer, sendParameters, request);
     return true;
 }
Beispiel #25
0
        protected virtual void HandleDebugGameOperation(HivePeer peer, DebugGameRequest request, SendParameters sendParameters)
        {
            // Room: Properties; # of cached events
            // Actors:  Count, Last Activity, Actor #, Peer State, Connection ID
            // Room Reference

            // get info from request (was gathered in Peer class before operation was forwarded to the game):
            var peerInfo = request.Info;
            var debugInfo = peerInfo + this;

            if (Log.IsInfoEnabled)
            {
                Log.Info("DebugGame: " + debugInfo);
            }

            this.LogQueue.WriteLog();

            var debugGameResponse = new DebugGameResponse { Info = debugInfo };

            peer.SendOperationResponse(new OperationResponse(request.OperationRequest.OperationCode, debugGameResponse), sendParameters);
        }
Beispiel #26
0
 protected virtual bool ProcessSetProperties(HivePeer peer, bool result, string errorMsg, SetPropertiesRequest request, SendParameters sendParameters)
 {
     this.PublishResultsAndSetGameProperties(result, errorMsg, request, peer, sendParameters);
     return true;
 }
Beispiel #27
0
        /// <summary>
        ///   Handles the <see cref = "RaiseEventRequest" />: Sends a <see cref = "CustomEvent" /> to actors in the room.
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <param name = "raiseEventRequest">
        ///   The operation
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleRaiseEventOperation(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters)
        {
            // get the actor who send the operation request
            var actor = this.GetActorByPeer(peer);
            if (actor == null)
            {
                return;
            }

            this.RaiseEventOperationHandler(peer, raiseEventRequest, sendParameters, actor);
        }
Beispiel #28
0
        private void OnJoinFailHandler(byte leaveReason, string reasonDetails, Dictionary<byte, object> parameters,
            HivePeer peer, SendParameters sendParameters, JoinGameRequest request)
        {
            this.SendErrorResponse(peer, request.OperationCode,
                ErrorCode.PluginReportedError, reasonDetails, sendParameters, parameters);

            if (Log.IsWarnEnabled)
            {
                Log.WarnFormat("OnJoinFailHandler: Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}", this.Name, peer.UserId, reasonDetails, peer);
            }

            this.JoinFailureHandler(leaveReason, peer, request);
        }
Beispiel #29
0
        public bool HandleCall(PeerBase peer, string userId, OperationRequest request, object authResultsSecure, SendParameters sp)
        {
            var rpcRequest = new WebRpcRequest(peer.Protocol, request);

            if (!rpcRequest.IsValid)
            {
                var msg = string.Format("Invalid RPC request format: {0}", rpcRequest.GetErrorMessage());
                Log.Error(msg);
                this.SendErrorResponse(peer, request.OperationCode, sp, (short)ErrorCode.OperationInvalid, msg);
                return(false);
            }

            try
            {
                var data = this.SerializeRequest(rpcRequest, userId, authResultsSecure);

                var uri = this.MakeRequestUri(rpcRequest);

                return(this.SendHttpRequest(peer, uri, data, rpcRequest));
            }
            catch (Exception e)
            {
                var msg = string.Format("Exception during RPC request handling {0}", e);
                Log.Error(msg);
                this.SendErrorResponse(peer, request.OperationCode, sp, msg: msg);
            }

            return(true);
        }
Beispiel #30
0
        /// <summary>
        ///   Called when the client sends an <see cref = "OperationRequest" />.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (log.IsDebugEnabled)
            {
                log.DebugFormat("OnOperationRequest. Code={0}", operationRequest.OperationCode);
            }

            switch ((OperationCode)operationRequest.OperationCode)
            {
            case OperationCode.Authenticate:
                //this.HandleAuthenticateOperation(request, sendParameters);
                return;

            case OperationCode.CreateGame:
                this.HandleCreateGameOperation(operationRequest, sendParameters);
                return;

            case OperationCode.JoinGame:
                this.HandleJoinGameOperation(operationRequest, sendParameters);
                return;

            case OperationCode.Ping:
                this.HandlePingOperation(operationRequest, sendParameters);
                return;

            case OperationCode.DebugGame:
                //this.HandleDebugGameOperation(request, sendParameters);
                return;

            case OperationCode.Join:
                this.HandleJoinOperation(operationRequest, sendParameters);
                return;

            case OperationCode.Leave:
                this.HandleLeaveOperation(operationRequest, sendParameters);
                return;

            case OperationCode.RaiseEvent:
            case OperationCode.GetProperties:
            case OperationCode.SetProperties:
            case OperationCode.ChangeGroups:
                this.HandleGameOperation(operationRequest, sendParameters);
                return;

            case OperationCode.Rpc:
                if (this.WebRpcHandler != null)
                {
                    this.WebRpcHandler.HandleCall(this, this.UserId, operationRequest, this.AuthCookie, sendParameters);
                    return;
                }

                this.SendOperationResponse(new OperationResponse
                {
                    OperationCode = (byte)OperationCode.Rpc,
                    ReturnCode    = (short)ErrorCode.OperationInvalid,
                    DebugMessage  = "Rpc is not enabled",
                },
                                           sendParameters);

                return;
            }

            var message = String.Format("Unknown operation code {0}", operationRequest.OperationCode);

            this.SendOperationResponse(new OperationResponse
            {
                OperationCode = operationRequest.OperationCode,
                ReturnCode    = (short)ErrorCode.OperationInvalid,
                DebugMessage  = message
            }, sendParameters);
        }
Beispiel #31
0
 protected virtual bool ProcessRaiseEvent(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters, Actor actor)
 {
     return this.RaiseEventOperationHandler(peer, raiseEventRequest, sendParameters, actor);
 }
 protected virtual void HandleDebugGameOperation(OperationRequest operationRequest, SendParameters sendParameters)
 {
 }
Beispiel #33
0
        private void HandleCreateGameOperationInt(HivePeer peer, SendParameters sendParameters,
            JoinGameRequest createGameRequest, bool fromJoin = false)
        {
            var createOptions = createGameRequest.GetCreateGameSettings(this);

            peer.SetPrivateCustomTypeCache(this.customTypeCache);

            RequestHandler handler = () =>
            {
                var oldValue = this.allowSetGameState;

                try
                {
                    this.allowSetGameState = false;

                    // since we allow to make changes to the original request sent by the client in a plugin
                    // we should check op.IsValid() - if not report error
                    createGameRequest.SetupRequest();

                    return this.ProcessCreateGame(peer, createGameRequest, sendParameters);
                }
                catch (Exception e)
                {
                    Log.ErrorFormat("Exception: {0}", e);
                    this.allowSetGameState = oldValue;
                    throw;
                }
            };

            var info = new CreateGameCallInfo(this.PendingPluginContinue, this.callEnv)
            {
                Request = createGameRequest,
                UserId = peer.UserId,
                Nickname = createGameRequest.GetNickname(),
                CreateOptions = createOptions,
                IsJoin = fromJoin,
                Handler = handler,
                Peer = peer,
                SendParams = sendParameters,
                OnFail = (onFailMsg, errorData) =>
                {
                    this.allowSetGameState = false;
                    this.failureOnCreate = true;

                    this.SendErrorResponse(peer, createGameRequest.OperationCode,
                        ErrorCode.PluginReportedError, onFailMsg, sendParameters, errorData);

                    peer.ReleaseRoomReference();
                    peer.ScheduleDisconnect(); // this gives the client a chance to get the reason
                }
            };

            try
            {
                this.Plugin.OnCreateGame(info);
            }
            catch (Exception e)
            {
                this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e);
            }
        }
Beispiel #34
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);
        }
Beispiel #35
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);
        }
Beispiel #36
0
 protected virtual void SendErrorResponse(HivePeer peer, byte opCode, ErrorCode errorCode, string msg, SendParameters sendParameters,
     Dictionary<byte, object> errorData = null)
 {
     peer.SendOperationResponse(
         new OperationResponse { OperationCode = opCode, ReturnCode = (short)errorCode, DebugMessage = msg, Parameters = errorData, },
         sendParameters);
 }
Beispiel #37
0
        protected override void HandleJoinGameOperation(HivePeer peer, SendParameters sendParameters, JoinGameRequest joinGameRequest)
        {
            if (this.isClosed)
            {
                if (!this.CheckGameCanBeCreated(peer, joinGameRequest))
                {
                    return;
                }

                if (!this.ReinitGame())
                {
                    this.SendErrorResponse(peer, joinGameRequest.OperationCode,
                        ErrorCode.InternalServerError, HiveErrorMessages.ReinitGameFailed, sendParameters);

                    joinGameRequest.OnJoinFailed(ErrorCode.InternalServerError, HiveErrorMessages.ReinitGameFailed);

                    this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, joinGameRequest);
                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat("Game '{0}' userId '{1}' failed to join. msg:{2}", this.Name, peer.UserId,
                            HiveErrorMessages.ReinitGameFailed);
                    }
                    return;
                }
            }

            //TBD do we still need this?
            string msg;
            if (!this.ValidatePlugin(joinGameRequest, out msg))
            {
                this.SendErrorResponse(peer, joinGameRequest.OperationCode, ErrorCode.PluginMismatch, msg, sendParameters);

                joinGameRequest.OnJoinFailed(ErrorCode.InternalServerError, HiveErrorMessages.ReinitGameFailed);
                this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, joinGameRequest);

                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("HandleJoinGameOperation: Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}", this.Name, peer.UserId, msg, peer);
                }
                return;
            }

            if (this.ActorsManager.ActorNumberCounter == 0) // we were just beeing created
            {
                if (!this.CheckGameCanBeCreated(peer, joinGameRequest))
                {
                    return;
                }

                this.HandleCreateGameOperationInt(peer, sendParameters, joinGameRequest, true);
            }
            else
            {
                peer.SetPrivateCustomTypeCache(this.customTypeCache);

                RequestHandler handler = () =>
                {
                    try
                    {
                        return this.ProcessBeforeJoinGame(joinGameRequest, sendParameters, peer);
                    }
                    catch (Exception e)
                    {
                        Log.ErrorFormat("Exception: {0}", e);
                        throw;
                    }
                };
                var info = new BeforeJoinGameCallInfo(this.PendingPluginContinue, this.callEnv)
                {
                    Request = joinGameRequest,
                    UserId = peer.UserId,
                    Nickname = joinGameRequest.GetNickname(),
                    Handler = handler,
                    Peer = peer,
                    SendParams = sendParameters,
                    OnFail = (onFailMsg, errorData) =>
                    {
                        this.allowSetGameState = false;
                        joinGameRequest.OnJoinFailed(ErrorCode.PluginReportedError, onFailMsg);
                        this.OnJoinFailHandler(LeaveReason.ServerDisconnect, onFailMsg, errorData, peer, sendParameters, joinGameRequest);
                    }
                };

                try
                {

                    this.Plugin.BeforeJoin(info);
                }
                catch (Exception e)
                {
                    this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e);
                }
            }
        }
Beispiel #38
0
        protected bool ValidateGame(HivePeer peer, JoinGameRequest joinGameRequest, SendParameters sendParameters)
        {
            // check if the game is open
            if (this.IsOpen == false)
            {
                this.SendErrorResponse(peer, joinGameRequest.OperationCode, ErrorCode.GameClosed,
                    HiveErrorMessages.GameClosed, sendParameters);

                joinGameRequest.OnJoinFailed(ErrorCode.GameClosed, HiveErrorMessages.GameClosed);

                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("ValidateGame: Game '{0}' userId '{1}' failed to join. msg:{2} -- peer: {3}",
                        this.Name, peer.UserId, HiveErrorMessages.GameClosed, peer);
                }
                return false;
            }

            var am = this.ActorsManager;
            var isGameFull = am.ActorsCount + am.InactiveActorsCount + am.YetExpectedUsersCount >= this.MaxPlayers;

            // check if the maximum number of players has already been reached
            if (this.MaxPlayers > 0 && isGameFull && !this.ActorsManager.IsExpectedUser(peer.UserId))
            {
                this.SendErrorResponse(peer, joinGameRequest.OperationCode, ErrorCode.GameFull,
                    HiveErrorMessages.GameFull, sendParameters);

                joinGameRequest.OnJoinFailed(ErrorCode.GameFull, HiveErrorMessages.GameFull);

                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("ValidateGame: Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}",
                        this.Name, peer.UserId, HiveErrorMessages.GameFull, peer);
                }

                return false;
            }

            return true;
        }
Beispiel #39
0
        protected void LeaveOperationHandler(HivePeer peer, SendParameters sendParameters, LeaveRequest request)
        {
            this.RemovePeerFromGame(peer, request != null && request.IsCommingBack);

            if (peer != null && request != null)
            {
                // is always reliable, so it gets a response
                peer.SendOperationResponse(new OperationResponse { OperationCode = request.OperationRequest.OperationCode }, sendParameters);
            }
        }
Beispiel #40
0
        /// <summary>
        ///   Enqueues game related operation requests in the peers current game.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        /// <remarks>
        ///   The current for a peer is stored in the peers state property.
        ///   Using the <see cref = "Room.EnqueueOperation" /> method ensures that all operation request dispatch logic has thread safe access to all room instance members since they are processed in a serial order.
        ///   <para>
        ///     Inheritors can use this method to enqueue there custom game operation to the peers current game.
        ///   </para>
        /// </remarks>
        protected virtual void HandleGameOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (this.JoinStage != JoinStages.Complete)
            {
                this.OnWrongOperationStage(operationRequest, sendParameters);
                return;
            }

            // enqueue operation into game queue.
            // the operation request will be processed in the games ExecuteOperation method.
            if (this.RoomReference != null)
            {
                this.RoomReference.Room.EnqueueOperation(this, operationRequest, sendParameters);
                return;
            }

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("Received game operation on peer without a game: peerId={0}", this.ConnectionId);
            }
        }
Beispiel #41
0
        protected bool RaiseEventOperationHandler(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters, Actor actor)
        {
            sendParameters.Flush = raiseEventRequest.Flush;

            if (raiseEventRequest.IsCacheSliceIndexOperation)
            {
                var msg = string.Empty;

                if (!this.UpdateCacheSlice(actor.Peer, raiseEventRequest.Cache, raiseEventRequest.CacheSliceIndex, ref msg))
                {

                    this.SendErrorResponse(peer, raiseEventRequest.OperationCode, ErrorCode.OperationInvalid, msg, sendParameters);

                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat("Game '{0}' userId '{1}' failed to update Cache Slice. msg:{2} -- peer:{3}", this.Name, peer.UserId, msg, peer);
                    }

                    if (Log.IsWarnEnabled)
                    {
                        Log.Warn(msg);
                    }
                }
                return false;
            }

            if (raiseEventRequest.IsCacheOpRemoveFromCache)
            {
                this.EventCache.RemoveEventsFromCache(raiseEventRequest);
                var response = new OperationResponse(raiseEventRequest.OperationRequest.OperationCode);
                peer.SendOperationResponse(response, sendParameters);
                return false;
            }

            if (raiseEventRequest.IsCacheOpRemoveFromCacheForActorsLeft)
            {
                var currentActorNumbers = this.ActorsManager.ActorsGetActorNumbers();
                this.EventCache.RemoveEventsForActorsNotInList(currentActorNumbers);
                var response = new OperationResponse(raiseEventRequest.OperationRequest.OperationCode);
                peer.SendOperationResponse(response, sendParameters);
                return false;
            }

            // publish the custom event
            var customEvent = new CustomEvent(actor.ActorNr, raiseEventRequest.EvCode, raiseEventRequest.Data);

            var updateEventCache = false;
            IEnumerable<Actor> recipients;

            if (raiseEventRequest.Actors != null && raiseEventRequest.Actors.Length > 0)
            {
                recipients = this.ActorsManager.ActorsGetActorsByNumbers(raiseEventRequest.Actors);
            }
            else if (raiseEventRequest.Group != 0)
            {
                var group = this.GroupManager.GetActorGroup(raiseEventRequest.Group);
                if (group != null)
                {
                    recipients = group.GetExcludedList(actor);
                }
                else
                {
                    // group does not exists yet because no one joined it yet.
                    // it's not an error to sent events to empty groups so no error response will be sent
                    return false;
                }
            }
            else
            {
                switch ((ReceiverGroup)raiseEventRequest.ReceiverGroup)
                {
                    case ReceiverGroup.All:
                        recipients = this.Actors;
                        updateEventCache = true;
                        break;

                    case ReceiverGroup.Others:
                        recipients = this.ActorsManager.ActorsGetExcludedList(actor);
                        updateEventCache = true;
                        break;

                    case ReceiverGroup.MasterClient:
                        recipients = new[] { this.ActorsManager.ActorsGetActorByNumber(this.MasterClientId) };
                        break;

                    default:
                        this.SendErrorResponse(peer, raiseEventRequest.OperationCode, ErrorCode.OperationInvalid,
                            HiveErrorMessages.InvalidReceiverGroup + raiseEventRequest.ReceiverGroup, sendParameters);

                        if (Log.IsWarnEnabled)
                        {
                            Log.WarnFormat("Game '{0}' user '{1}' sent wrong receiver group. msg:{2} -- peer:{3}",
                                this.Name, peer.UserId, HiveErrorMessages.InvalidReceiverGroup + raiseEventRequest.ReceiverGroup, peer);
                        }
                        return false;
                }
            }

            if (updateEventCache && raiseEventRequest.Cache != (byte)CacheOperation.DoNotCache)
            {
                string msg;
                if (!this.UpdateEventCache(actor, raiseEventRequest, out msg))
                {
                    this.SendErrorResponse(peer, raiseEventRequest.OperationCode, ErrorCode.OperationInvalid, msg, sendParameters);
                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat("Game '{0}' user '{1}' failed to update EventCache. msg:{2} -- peer:{3}",
                            this.Name, peer.UserId, msg, peer);
                    }
                    return false;
                }
            }

            this.PublishEvent(customEvent, recipients, sendParameters);
            return true;
        }
        //当客户端成功连接服务器时调用

        protected override void OnOperationRequest(Photon.SocketServer.OperationRequest operationRequest, Photon.SocketServer.SendParameters sendParameters)
        {
            //通过opcode获得处理的handler,如果找不到,则使用默认的Handler
            BaseHandler baseHandler = DictTool.GetValue <ResponseCode, BaseHandler>(Main.Instance.HandlerDict, (ResponseCode)operationRequest.OperationCode);

            if (baseHandler != null)
            {
                baseHandler.OnOperationRequest(operationRequest, sendParameters, this);
            }
            else
            {
                DictTool.GetValue <ResponseCode, BaseHandler>(Main.Instance.HandlerDict, (ResponseCode)ResponseCode.Default)
                .OnOperationRequest(operationRequest, sendParameters, this);
            }
        }
Beispiel #43
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;
        }
Beispiel #44
0
 /// <summary>
 ///   Enqueues an <see cref = "OperationRequest" /> to the end of the execution queue.
 /// </summary>
 /// <param name = "peer">
 ///   The peer.
 /// </param>
 /// <param name = "operationRequest">
 ///   The operation request to enqueue.
 /// </param>
 /// <param name = "sendParameters">
 ///   The send Parameters.
 /// </param>
 /// <remarks>
 ///   <see cref = "ExecuteOperation" /> is called sequentially for each operation request
 ///   stored in the execution queue.
 ///   Using an execution queue ensures that operation request are processed in order
 ///   and sequentially to prevent object synchronization (multi threading).
 /// </remarks>
 public void EnqueueOperation(HivePeer peer, OperationRequest operationRequest, SendParameters sendParameters)
 {
     this.ExecutionFiber.Enqueue(() => this.ExecuteOperation(peer, operationRequest, sendParameters));
 }
Beispiel #45
0
        private bool ConvertParamsAndValidateGame(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters)
        {
            // ValidateGame checks isOpen and maxplayers
            // and does not apply to rejoins
            if (this.CheckBeforeJoinThisIsNewCreatedRoom(joinRequest))
            {
                return true;
            }

            if (joinRequest.IsRejoining)
            {
                string errorMsg;
                ErrorCode errorcode;

                if (this.CheckUserOnJoin)
                {
                    if (this.ActorsManager.GetActorByUserId(peer.UserId) != null)
                    {
                        return true;
                    }

                    errorcode = ErrorCode.JoinFailedWithRejoinerNotFound;
                    errorMsg = HiveErrorMessages.UserNotFound;
                }
                else
                {
                    if (this.ActorsManager.GetActorByNumber(joinRequest.ActorNr) != null)
                    {
                        return true;
                    }

                    errorcode = ErrorCode.JoinFailedWithRejoinerNotFound;
                    errorMsg = string.Format(HiveErrorMessages.ActorNotFound, joinRequest.ActorNr);
                }

                if (joinRequest.JoinMode == JoinModes.RejoinOnly)
                {
                    this.SendErrorResponse(peer, joinRequest.OperationCode, errorcode, errorMsg, sendParameters);

                    joinRequest.OnJoinFailed(errorcode, errorMsg);

                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat("ConvertParamsAndValidateGame: Game '{0}' userId '{1}' failed to join. msg:'{2}' (JoinMode={3}) -- peer:{4}",
                            this.Name, peer.UserId, errorMsg, joinRequest.JoinMode, peer);
                    }

                    return false;
                }

                //TBD - I suggest beeing even stricter if the room is configured with expected users - we don't support JoinMode2!
                if (joinRequest.JoinMode == JoinModes.RejoinOrJoin && this.ActorsManager.IsExpectedUser(peer.UserId))
                {
                    errorMsg = HiveErrorMessages.CanNotUseRejoinOrJoinIfPlayerExpected;
                    this.SendErrorResponse(peer, joinRequest.OperationCode, ErrorCode.OperationDenied, errorMsg, sendParameters);

                    joinRequest.OnJoinFailed(ErrorCode.OperationDenied, errorMsg);

                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat("Game '{0}' userId '{1}' failed to join. msg:{2} (JoinMode={3}) -- peer:{4}",
                            this.Name, peer.UserId, errorMsg, joinRequest.JoinMode, peer);
                    }

                    return false;
                }
            }

            return this.ValidateGame(peer, joinRequest, sendParameters);
        }
Beispiel #46
0
 /// <summary>
 ///   This method is invoked sequentially for each operation request
 ///   enqueued in the <see cref = "ExecutionFiber" /> using the
 ///   <see cref = "EnqueueOperation" /> method.
 /// </summary>
 /// <param name = "peer">
 ///   The peer.
 /// </param>
 /// <param name = "operation">
 ///   The operation request.
 /// </param>
 /// <param name = "sendParameters">
 ///   The send Parameters.
 /// </param>
 protected virtual void ExecuteOperation(HivePeer peer, OperationRequest operation, SendParameters sendParameters)
 {
 }
Beispiel #47
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);
            }
        }
Beispiel #48
0
        /// <summary>
        ///   Publishes an event to a single actor on a specified channel.
        /// </summary>
        /// <param name = "e">
        ///   The event to publish.
        /// </param>
        /// <param name = "actor">
        ///   The <see cref = "Actor" /> who should receive the event.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected void PublishEvent(HiveEventBase e, Actor actor, SendParameters sendParameters)
        {
            var eventData = new EventData(e.Code, e);

            actor.Peer.SendEvent(eventData, sendParameters);
        }
Beispiel #49
0
 protected virtual void HandleCreateGameOperation(HivePeer peer, SendParameters sendParameters, CreateGameRequest createGameRequest)
 {
     this.CreateGame(peer, createGameRequest, sendParameters);
 }
Beispiel #50
0
        /// <summary>
        ///   Publishes an event to a list of actors on a specified channel.
        /// </summary>
        /// <param name = "e">
        ///   The event to publish.
        /// </param>
        /// <param name = "actorList">
        ///   A list of <see cref = "Actor" /> who should receive the event.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected void PublishEvent(EventData e, IEnumerable <Actor> actorList, SendParameters sendParameters)
        {
            var peers = actorList.Select(actor => actor.Peer);

            ApplicationBase.Instance.BroadCastEvent(e, peers, sendParameters);
        }
Beispiel #51
0
        /// <summary>
        ///   Handles the <see cref = "GetPropertiesRequest" /> operation: Sends the properties with the <see cref = "OperationResponse" />.
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <param name = "getPropertiesRequest">
        ///   The operation to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleGetPropertiesOperation(HivePeer peer, GetPropertiesRequest getPropertiesRequest, SendParameters sendParameters)
        {
            var response = new GetPropertiesResponse();

            // check if game properties should be returned
            if ((getPropertiesRequest.PropertyType & (byte)PropertyType.Game) == (byte)PropertyType.Game)
            {
                response.GameProperties = this.Properties.GetProperties(getPropertiesRequest.GamePropertyKeys);
            }

            // check if actor properties should be returned
            if ((getPropertiesRequest.PropertyType & (byte)PropertyType.Actor) == (byte)PropertyType.Actor)
            {
                response.ActorProperties = new Hashtable();

                if (getPropertiesRequest.ActorNumbers == null)
                {
                    foreach (var actor in this.Actors)
                    {
                        this.AddActorPropertiesToResponse(getPropertiesRequest, actor, response);
                    }
                }
                else
                {
                    foreach (var actorNumber in getPropertiesRequest.ActorNumbers)
                    {
                        var actor = this.ActorsManager.ActorsGetActorByNumber(actorNumber);
                        this.AddActorPropertiesToResponse(getPropertiesRequest, actor, response);
                    }
                }
            }

            peer.SendOperationResponse(new OperationResponse(getPropertiesRequest.OperationRequest.OperationCode, response), sendParameters);
        }
Beispiel #52
0
        protected override bool ProcessRaiseEvent(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters, Actor actor)
        {
            var result = base.ProcessRaiseEvent(peer, raiseEventRequest, sendParameters, actor);

            if (raiseEventRequest.Cache >= 10)
            {
                this.onCachOpEvent.Set();
            }
            else
            {
                this.onRaiseEvent.Set();
            }
            return(result);
        }
Beispiel #53
0
 /// <summary>
 /// Handles the <see cref="LeaveRequest"/> and calls <see cref="RemovePeerFromGame"/>.
 /// </summary>
 /// <param name="peer">
 /// The peer.
 /// </param>
 /// <param name="sendParameters">
 /// The send Parameters.
 /// </param>
 /// <param name="leaveOperation">
 /// The operation.
 /// </param>
 protected virtual void HandleLeaveOperation(HivePeer peer, SendParameters sendParameters, LeaveRequest leaveOperation)
 {
     this.LeaveOperationHandler(peer, sendParameters, leaveOperation);
 }
Beispiel #54
0
        protected virtual bool ProcessCreateGame(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters)
        {
            var result = this.CreateGame(peer, joinRequest, sendParameters);

            this.ActorsManager.DeactivateActors(this);

            return result;
        }
Beispiel #55
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);
 }
Beispiel #56
0
 protected virtual bool ProcessJoin(int actorNr, JoinGameRequest joinRequest, SendParameters sendParameters, ProcessJoinParams prms, HivePeer peer)
 {
     return this.JoinSendResponseAndEvents(peer, joinRequest, sendParameters, actorNr, prms);
 }
Beispiel #57
0
        protected bool JoinApplyGameStateChanges(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters, out Actor actor)
        {
            var isCreatingGame = false;
            var isNewGame = false;
            if (peer.JoinStage == HivePeer.JoinStages.CreatingOrLoadingGame)
            {
                isCreatingGame = true;
                if (this.CheckBeforeJoinThisIsNewCreatedRoom(joinRequest))
                {
                    isNewGame = true;
                    this.ApplyGameProperties(joinRequest);
                }
                else
                {
                    this.CopyGamePropertiesForMasterUpdate(joinRequest);
                }
            }

            actor = null;
            peer.JoinStage = HivePeer.JoinStages.ConvertingParams;
            if (this.IsDisposed)
            {
                // join arrived after being disposed - repeat join operation
                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("Join operation on disposed game. GameName={0}", this.Name);
                }

                return false;
            }

            if (!this.ConvertParamsAndValidateGame(peer, joinRequest, sendParameters))
            {
                return false;
            }

            peer.JoinStage = HivePeer.JoinStages.CheckingCacheSlice;
            if (joinRequest.CacheSlice.HasValue && !this.EventCache.HasSlice(joinRequest.CacheSlice.Value))
            {
                var msg = string.Format(HiveErrorMessages.CacheSliceNoAviable, joinRequest.CacheSlice);
                this.SendErrorResponse(peer, joinRequest.OperationCode, ErrorCode.OperationInvalid, msg, sendParameters);
                joinRequest.OnJoinFailed(ErrorCode.OperationInvalid, msg);

                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("JoinApplyGameStateChanges: Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}",
                        this.Name, peer.UserId, msg, peer);
                }
                return false;
            }

            peer.JoinStage = HivePeer.JoinStages.AddingActor;
            ErrorCode errorcode;
            string reason;
            // create an new actor
            bool isNewActor;
            if (this.TryAddPeerToGame(peer, joinRequest.ActorNr, out actor, out isNewActor, out errorcode, out reason, joinRequest) == false)
            {
                this.SendErrorResponse(peer, joinRequest.OperationCode, errorcode, reason, sendParameters);
                joinRequest.OnJoinFailed(errorcode, reason);

                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("JoinApplyGameStateChanges: Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}",
                        this.Name, peer.UserId, reason, peer);
                }
                return false;
            }

            // check if a room removal is in progress and cancel it if so
            if (this.RemoveTimer != null)
            {
                this.RemoveTimer.Dispose();
                this.RemoveTimer = null;
            }

            if (this.MasterClientId == 0)
            {
                this.UpdateMasterClientId();
            }

            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("JoinApplyGameStateChanges: Actor {0} is added. MasterClientId is {1}", actor.ActorNr, this.MasterClientId);
            }

            peer.JoinStage = HivePeer.JoinStages.CheckAfterJoinParams;

            // set game properties for join from the first actor (game creator)
            if (isNewGame)
            {
                this.DeleteCacheOnLeave = joinRequest.DeleteCacheOnLeave;
                this.SuppressRoomEvents = joinRequest.SuppressRoomEvents;
                if (this.MaxEmptyRoomTTL < joinRequest.EmptyRoomLiveTime)
                {
                    var msg = string.Format(HiveErrorMessages.MaxTTLExceeded, joinRequest.EmptyRoomLiveTime, MaxEmptyRoomTTL);
                    this.SendErrorResponse(peer, joinRequest.OperationCode, ErrorCode.OperationInvalid, msg, sendParameters);
                    joinRequest.OnJoinFailed(ErrorCode.OperationInvalid, msg);

                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat("Game '{0}' userId '{1}' failed to create. msg:{2} -- peer:{3}", this.Name, peer.UserId, msg, peer);
                    }
                    return false;
                }
                this.EmptyRoomLiveTime = joinRequest.EmptyRoomLiveTime;
                this.PlayerTTL = joinRequest.PlayerTTL;
                this.CheckUserOnJoin = joinRequest.CheckUserOnJoin;
                this.PublishUserId = joinRequest.PublishUserId;

                if (joinRequest.GameProperties != null)
                {
                    this.Properties.SetProperties(joinRequest.GameProperties);
                }

                if (joinRequest.AddUsers != null)
                {
                    this.Properties.Set((byte)GameParameter.ExpectedUsers, joinRequest.AddUsers);
                }
            }

            if (Log.IsDebugEnabled)
            {
                if (isCreatingGame)
                {
                    Log.DebugFormat(
                        "{0} Game - name={2}, lobyName={3}, lobbyType={4}, maxPlayers={5}, IsOpen={6}, IsVisible={7}, EmptyRoomLiveTime={8}, PlayerTTL={9}, CheckUserOnJoin={10}, PublishUserId={11}, ExpectedUsers={12}",
                        isNewGame ? "Created" : "Loaded", // 0
                        "", // 1
                        this.Name, // 2
                        this.LobbyId,
                        this.LobbyType,
                        this.MaxPlayers,
                        this.IsOpen,
                        this.IsVisible,
                        this.EmptyRoomLiveTime,
                        this.PlayerTTL,
                        this.CheckUserOnJoin,
                        this.PublishUserId,
                        joinRequest.AddUsers != null ? joinRequest.AddUsers.Aggregate((current, next) => current + ", " + next) : ""
                        );
                }
            }

            if (!this.AddExpectedUsers(joinRequest))
            {
                this.SendErrorResponse(peer, joinRequest.OperationRequest.OperationCode, ErrorCode.InternalServerError,
                        HiveErrorMessages.CantAddSlots, sendParameters);
                joinRequest.OnJoinFailed(ErrorCode.InternalServerError, HiveErrorMessages.CantAddSlots);
                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("Game '{0}' userId '{1}' failed to join. msg:{2}", this.Name, peer.UserId, HiveErrorMessages.CantAddSlots);
                }
                return false;
            }

            peer.JoinStage = HivePeer.JoinStages.ApplyActorProperties;
            // set custom actor properties if defined
            if (joinRequest.ActorProperties != null)
            {
                // this is set by the server only
                joinRequest.ActorProperties.Remove((byte)ActorParameter.IsInactive);
                joinRequest.ActorProperties.Remove((byte)ActorParameter.UserId);

                actor.Properties.SetProperties(joinRequest.ActorProperties);
            }

            if (!isNewGame && this.ModifyExpectedUsersProperty(joinRequest.AddUsers))
            {
                const byte propertyId = (byte)GameParameter.ExpectedUsers;
                var propertiesChangedEvent = new PropertiesChangedEvent(0)
                {
                    Properties = new Hashtable
                    {
                        {propertyId, this.Properties.GetProperty(propertyId).Value}
                    }
                };
                this.PublishEvent(propertiesChangedEvent, this.Actors, sendParameters); // shouldn't we publish this in the next JoinStage2?
            }
            return true;
        }
 public abstract void OnOperationRequest(OperationRequest operationRequest, Photon.SocketServer.SendParameters sendParameters, ClientPeer peer);