예제 #1
0
        public int RemovePeerFromGame(HiveGame game, HivePeer peer, int playerTTL, bool isCommingBack)
        {
            //if (Log.IsDebugEnabled)
            //{
            //    Log.DebugFormat("RemovePeerFromGame: conId={0}", peer.ConnectionId);
            //}


            var actorIndex = this.allActors.FindIndex(a => a.Peer == peer);

            if (actorIndex == -1)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("RemovePeerFromGame - Cant remove actor. It was not found for peer: {0}", peer);
                }

                return(-1);
            }

            var actor = this.allActors[actorIndex];

            Debug.Assert(actor.IsActive);
            --this.activeActorsCount;

            if (playerTTL != 0 && isCommingBack)
            {
                // Note: deactive actor first, so it deosn't recieve its own leave event.
                // put to disconnectedActors collection
                //actor.Peer = null;
                // TBD - fix groups
                actor.Deactivate();

                game.OnActorDeactivated(actor);
                //Note: the player TTL can be set to never timeout (expected behavior specially for SavedGames)
                if (playerTTL > 0 && playerTTL != int.MaxValue)
                {
                    // setup cleanup timer
                    actor.CleanUpTimer = game.ExecutionFiber.Schedule(() => game.RemoveInactiveActor(actor), playerTTL);
                }

                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("Actor {0}: {1} {2} to game: {3} -- peer:{4}", "deactivated", actor.ActorNr, actor.UserId, game.Name, peer.ToString());
                }
            }
            else
            {
                this.allActors.RemoveAt(actorIndex);
                // cleanup does raise leave event
                game.OnActorRemoved(actor);

                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("Actor {0}: {1} {2} to game: {3} -- peer:{4}", "removed", actor.ActorNr, actor.UserId, game.Name, peer.ToString());
                }
            }

            return(actor.ActorNr);
        }
예제 #2
0
        private void SanityChecks(HivePeer peer, int actorNr, Actor actor, ref string reason, bool checkUserOnJoin)
        {
            Actor actorInCollection;

            if (!string.IsNullOrEmpty(peer.UserId) && checkUserOnJoin)
            {
                actorInCollection = this.allActors.Find(a => actorNr == a.ActorNr || a.UserId == peer.UserId);
            }
            else
            {
                actorInCollection = this.allActors.Find(a => actorNr == a.ActorNr);
            }
            if (actorInCollection != null)
            {
                reason =
                    string.Format("Trying to add ActorNr already in list: in list: ActorNr: {0}, userId:'{1}', Active:{2},"
                                  + " trying to add: ActorNr:{3}, userId:'{4}'",
                                  actorInCollection.ActorNr,
                                  actorInCollection.UserId,
                                  actorInCollection.IsActive,
                                  actor.ActorNr,
                                  actor.UserId);
                Log.Warn(reason);
                //return false;
            }
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Actor"/> class.
        /// </summary>
        /// <param name="peer">
        /// The peer for this actor.
        /// </param>
        public Actor(HivePeer peer)
        {
            this.Peer = peer;

            // we copy the UserId so it doesn't get lost on peer disconnect
            this.UserId = peer.UserId;
        }
예제 #4
0
        /// <summary>
        /// Tries to add a <see cref="HivePeer"/> to this game instance.
        /// </summary>
        /// <param name="game"></param>
        /// <param name="peer">
        /// The peer to add.
        /// </param>
        /// <param name="actorNr">
        /// The actor Nr.
        /// </param>
        /// <param name="actor">
        /// When this method returns this out param contains the <see cref="Actor"/> associated with the <paramref name="peer"/>.
        /// </param>
        /// <param name="isNewActor">indicates that new actor was created</param>
        /// <param name="reason">
        /// reason why player can not be added
        /// </param>
        /// <param name="joinRequest"></param>
        /// <returns>
        /// Returns true if no actor exists for the specified peer and a new actor for the peer has been successfully added.
        ///   The actor parameter is set to the newly created <see cref="Actor"/> instance.
        ///   Returns false if an actor for the specified peer already exists.
        ///   The actor parameter is set to the existing <see cref="Actor"/> for the specified peer.
        /// </returns>
        public bool TryAddPeerToGame(HiveGame game, HivePeer peer, int actorNr, out Actor actor, out bool isNewActor,
                                     out Photon.Common.ErrorCode errorcode, out string reason, JoinGameRequest joinRequest)
        {
            isNewActor = false;
            errorcode  = Photon.Common.ErrorCode.InternalServerError;

            if (!this.VerifyCanJoin(peer, actorNr, game.PlayerTTL, out actor, out errorcode, out reason, ref isNewActor, game.CheckUserOnJoin, joinRequest))
            {
                return(false);
            }

            if (isNewActor)
            {
                actor = new Actor(peer);
                this.actorNumberCounter++;
                actor.ActorNr = this.actorNumberCounter;

                this.SanityChecks(peer, actorNr, actor, ref reason, game.CheckUserOnJoin);

                this.allActors.Add(actor);
            }
            else
            {
                actor.Reactivate(peer);
            }
            ++this.activeActorsCount;

            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("Actor {0}: {1} {2} to game: {3} -- peer:{4}", isNewActor ? "added" : "reactivated", actor.ActorNr, actor.UserId, game.Name, peer.ToString());
            }

            reason = "";
            return(true);
        }
예제 #5
0
 protected override bool ProcessBeforeJoinGame(JoinGameRequest joinRequest, SendParameters sendParameters, HivePeer peer)
 {
     if (joinRequest.ActorProperties != null && joinRequest.ActorProperties.ContainsKey("ProcessBeforeJoinException"))
     {
         peer = null;
         joinRequest.CacheSlice = 123;
     }
     return base.ProcessBeforeJoinGame(joinRequest, sendParameters, peer);
 }
 protected override bool ProcessCreateGame(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters)
 {
     if (base.ProcessCreateGame(peer, joinRequest, sendParameters))
     {
         // update game state at master server
         this.UpdateGameStateOnMasterOnCreate(joinRequest, peer);
     }
     return(true);
 }
예제 #7
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);
        }
예제 #8
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));
        }
예제 #9
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);
 }
예제 #10
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));
        }
예제 #11
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);
        }
예제 #12
0
파일: Game.cs 프로젝트: cernysw/UnityDemo
        protected override void ExecuteOperation(HivePeer peer, OperationRequest operationRequest, SendParameters sendParameters)
        {
            try
            {
                //if (Log.IsDebugEnabled)
                //{
                //    Log.DebugFormat("Executing operation {0}", operationRequest.OperationCode);
                //}

                switch (operationRequest.OperationCode)
                {
                // Lite operation code for join is not allowed in load balanced games.
                case (byte)Photon.Hive.Operations.OperationCode.Join:
                    this.SendErrorResponse(peer, operationRequest.OperationCode,
                                           ErrorCode.OperationDenied, HiveErrorMessages.InvalidOperationCode, sendParameters);
                    if (Log.IsDebugEnabled)
                    {
                        Log.DebugFormat("Game '{0}' userId '{1}' failed to join. msg:{2}", this.Name, peer.UserId,
                                        HiveErrorMessages.InvalidOperationCode);
                    }
                    break;

                case (byte)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;

                // all other operation codes will be handled by the Lite game implementation
                default:
                    base.ExecuteOperation(peer, operationRequest, sendParameters);
                    break;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
        }
예제 #13
0
        private bool TrySameSessionRejoin(HivePeer peer, int playerTtl, Actor actor, byte joinMode, bool forceRejoin)
        {
            if (playerTtl == 0 ||
                (joinMode != JoinModes.RejoinOnly && joinMode != JoinModes.RejoinOrJoin) ||
                (!forceRejoin && !actor.Peer.IsThisSameSession(peer))    // only if this is a Rejoin, we follow through
                )
            {
                return(false);
            }

            var actorPeer = actor.Peer;

            actor.Deactivate();
            // in order to prevent RemovePeerFromCurrentGame
            actorPeer.ReleaseRoomReference();
            actorPeer.Disconnect();
            --this.activeActorsCount;
            return(true);
        }
예제 #14
0
        /// <summary>
        /// Creates a <see cref="HivePeer"/> to handle <see cref="OperationRequest"/>s.
        /// </summary>
        /// <param name="initRequest">
        /// The initialization request.
        /// </param>
        /// <returns>
        /// A new <see cref="HivePeer"/> instance.
        /// </returns>
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            var peer = new HivePeer(initRequest);

            var settings = WebRpcSettings.Default;
            if (settings != null && settings.Enabled)
            {
                peer.WebRpcHandler = new WebRpcHandler(
                    settings.BaseUrl.Value,
                    new Dictionary<string, object>
                                    {
                                        {"AppId", this.HwId},
                                        {"AppVersion", ""},
                                        {"Region", ""},
                                        {"Cloud", ""},
                                    }, null, new HttpRequestQueueOptions(httpQueueReconnectInterval: settings.ReconnectInterval * 1000));
            }

            return peer;
        }
예제 #15
0
        protected override void OnGameFull(HivePeer peer, JoinGameRequest joinGameRequest, SendParameters sendParameters)
        {
            base.OnGameFull(peer, joinGameRequest, sendParameters);

            if (this.onGameIsFullErrorsCounter.Increment(1) >= ErrorsCountToInitiateUpdate)
            {
                if (this.gameUpdaterGuard.Increment(1) == 1)
                {
                    if (Log.IsWarnEnabled)
                    {
                        Log.WarnFormat(fullGameReinitLogGuard, "Game '{0}' has sent reinit message to master after getting {1} 'Game is full' errors",
                                       this.Name, this.onGameIsFullErrorsCounter.Value);
                    }
                    this.ReinitializeGameOnMaster();
                }
            }
            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("Game '{0}' got '{1}' errors 'Game full'", this.Name, this.onGameIsFullErrorsCounter.Value);
            }
        }
        private bool TrySameSessionRejoin(HivePeer peer, int playerTtl, Actor actor, byte joinMode, bool forceRejoin)
        {
            if (playerTtl == 0 ||
                (joinMode != JoinModes.RejoinOnly && joinMode != JoinModes.RejoinOrJoin) ||
                (!forceRejoin && !actor.Peer.IsThisSameSession(peer))    // only if this is a Rejoin, we follow through
                )
            {
                return(false);
            }

            var actorPeer = actor.Peer;

            actor.Deactivate();

            var dbgString = actorPeer.GetDebugString();

            actorPeer.SetDebugString(dbgString + $", SameSessionRejoinKick at {DateTime.Now} by p:{peer}");
            // in order to prevent RemovePeerFromCurrentGame
            actorPeer.ReleaseRoomReference();
            actorPeer.Disconnect();
            return(true);
        }
예제 #17
0
 /// <summary>
 /// Tries to add a <see cref="HivePeer"/> to this game instance.
 /// </summary>
 /// <param name="peer">
 /// The peer to add.
 /// </param>
 /// <param name="actorNr">
 /// The actor Nr.
 /// </param>
 /// <param name="actor">
 /// When this method returns this out param contains the <see cref="Actor"/> associated with the <paramref name="peer"/>.
 /// </param>
 /// <param name="errorcode">returns error code if we fail to add actor</param>
 /// <param name="reason">
 /// reason why player can not be added
 /// </param>
 /// <param name="isNewActor">returns true if actor is new</param>
 /// <param name="joinRequest">join request which was sent by client</param>
 /// <returns>
 /// Returns true if no actor exists for the specified peer and a new actor for the peer has been successfully added. 
 ///   The actor parameter is set to the newly created <see cref="Actor"/> instance.
 ///   Returns false if an actor for the specified peer already exists. 
 ///   The actor parameter is set to the existing <see cref="Actor"/> for the specified peer.
 /// </returns>
 protected virtual bool TryAddPeerToGame(HivePeer peer, int actorNr, out Actor actor, 
     out bool isNewActor, out ErrorCode errorcode, out string reason, JoinGameRequest joinRequest)
 {
     return this.ActorsManager.TryAddPeerToGame(this, peer, actorNr, out actor, out isNewActor, out errorcode, out reason, joinRequest);
 }
예제 #18
0
 protected override bool ProcessBeforeJoinGame(JoinGameRequest joinRequest, SendParameters sendParameters, HivePeer peer)
 {
     if (joinRequest.ActorProperties != null && joinRequest.ActorProperties.ContainsKey("ProcessBeforeJoinException"))
     {
         peer = null;
         joinRequest.CacheSlice = 123;
     }
     return(base.ProcessBeforeJoinGame(joinRequest, sendParameters, peer));
 }
예제 #19
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);
        }
예제 #20
0
 protected virtual void HandleCreateGameOperation(HivePeer peer, SendParameters sendParameters, CreateGameRequest createGameRequest)
 {
     this.CreateGame(peer, createGameRequest, sendParameters);
 }
예제 #21
0
        /// <summary>
        ///   Gets the actor for a <see cref = "HivePeer" />.
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <returns>
        ///   The actor for the peer or null if no actor for the peer exists (this should not happen).
        /// </returns>
        protected Actor GetActorByPeer(HivePeer peer)
        {
            var actor = this.ActorsManager.ActorsGetActorByPeer(peer);
            if (actor == null)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("Actor not found for peer: {0}", peer.ConnectionId);
                }
            }

            return actor;
        }
예제 #22
0
        protected bool CreateGame(HivePeer peer, JoinGameRequest request, SendParameters sendParameters)
        {
            peer.JoinStage = HivePeer.JoinStages.CreatingOrLoadingGame;

            return this.Join(peer, request, sendParameters);
        }
예제 #23
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;
        }
예제 #24
0
 protected virtual void HandleRemovePeerMessage(HivePeer peer, int reason, string details)
 {
     this.RemovePeerFromGame(peer, isCommingBack: false);
 }
예제 #25
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);
 }
예제 #26
0
        protected override bool ProcessJoin(int actorNr, JoinGameRequest joinRequest,
                                            SendParameters sendParameters, ProcessJoinParams prms, HivePeer peer)
        {
            if (!base.ProcessJoin(actorNr, joinRequest, sendParameters, prms, peer))
            {
                return(false);
            }

            var gamePeer = (GameClientPeer)peer;
            // update game state at master server
            var userId = gamePeer.UserId ?? string.Empty;

            this.NotifyMasterUserAdded(userId, joinRequest.AddUsers != null ? this.ActorsManager.ExpectedUsers.ToArray() : null);

            return(true);
        }
예제 #27
0
        protected virtual void UpdateGameStateOnMasterOnCreate(JoinGameRequest joinRequest, HivePeer peer)
        {
            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("UpdateGameStateOnMasterOnCreate: game - '{0}'", this.Name);
            }

            var updateEvent = this.GetUpdateGameEvent();

            updateEvent.MaxPlayers        = joinRequest.wellKnownPropertiesCache.MaxPlayer;
            updateEvent.IsOpen            = joinRequest.wellKnownPropertiesCache.IsOpen;
            updateEvent.IsVisible         = joinRequest.wellKnownPropertiesCache.IsVisible;
            updateEvent.PropertyFilter    = joinRequest.wellKnownPropertiesCache.LobbyProperties;
            updateEvent.CheckUserIdOnJoin = this.RoomState.CheckUserOnJoin;
            updateEvent.NewUsers          = new[] { peer.UserId ?? string.Empty };
            updateEvent.LobbyId           = this.LobbyId;
            updateEvent.LobbyType         = (byte)this.LobbyType;
            updateEvent.Reinitialize      = true;
            updateEvent.Replication       = ReplicationId.Renitialization;

            var properties = this.GetLobbyGameProperties(joinRequest.properties);

            if (properties != null && properties.Count > 0)
            {
                updateEvent.GameProperties = properties;
            }

            if (this.ActorsManager.InactiveActorsCount > 0)
            {
                updateEvent.InactiveUsers = this.ActorsManager.InactiveActors.Select(a => (a.UserId ?? string.Empty)).ToArray();
            }

            if (this.ActorsManager.ExpectedUsers.Count > 0)
            {
                updateEvent.ExpectedUsers = this.ActorsManager.ExpectedUsers.ToArray();
            }

            this.UpdateGameStateOnMaster(updateEvent);
        }
예제 #28
0
        protected bool UpdateCacheSlice(HivePeer peer, byte op, int? sliceIndex, ref string message)
        {
            // get the actor who send the operation request
            var actor = this.GetActorByPeer(peer);
            if (actor == null)
            {
                return false;
            }

            switch (op)
            {
                case (byte)CacheOperation.SliceIncreaseIndex:
                {
                    this.EventCache.Slice++;
                    // notify "other" actors of change
                    var sliceChangedEvent = new CacheSliceChanged(this.GetActorByPeer(peer).ActorNr) { Slice = this.EventCache.Slice };
                    this.PublishEvent(sliceChangedEvent, this.Actors, new SendParameters());
                    return true;
                }
                case (byte)CacheOperation.SliceSetIndex:
                {
                    if (sliceIndex == null)
                    {
                        message = "SliceSetIndex: Missing paramter CacheSliceIndex.";
                        return false;
                    }

                    if (this.EventCache.Slice != sliceIndex.Value)
                    {
                        this.EventCache.Slice = sliceIndex.Value;

                        var sliceChangedEvent = new CacheSliceChanged(this.GetActorByPeer(peer).ActorNr) { Slice = this.EventCache.Slice };
                        this.PublishEvent(sliceChangedEvent, this.Actors, new SendParameters());
                    }
                    return true;
                }
                case (byte)CacheOperation.SlicePurgeIndex:
                {
                    if (sliceIndex == null)
                    {
                        message = "SlicePurgeIndex: Missing paramter CacheSliceIndex.";
                        return false;
                    }

                    if (this.EventCache.Slice != sliceIndex.Value)
                    {
                        this.EventCache.RemoveSlice(sliceIndex.Value);
                        return true;
                    }

                    message = string.Format("Purging of current slice={0} not allowed.", (int)sliceIndex);
                    return false;
                }
                case (byte)CacheOperation.SlicePurgeUpToIndex:
                {
                    if (sliceIndex == null)
                    {
                        message = "SlicePurgeUpToIndex: Missing paramter CacheSliceIndex.";
                        return false;
                    }

                    if (this.EventCache.Slice > sliceIndex.Value)
                    {
                        this.EventCache.RemoveUpToSlice(sliceIndex.Value);
                        return true;
                    }

                    message = string.Format("Purging uo to current slice={0} not allowed.", (int)sliceIndex);
                    return false;
                }
            }

            message = string.Format("Unknown cache operation={0}.", op);
            return false;
        }
예제 #29
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;
        }
예제 #30
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;
        }
예제 #31
0
 protected override void JoinFailureHandler(byte leaveReason, HivePeer peer, JoinGameRequest request)
 {
     base.JoinFailureHandler(leaveReason, peer, request);
     this.NotifyMasterUserFailedToAdd((GameClientPeer)peer);
 }
예제 #32
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);
        }
예제 #33
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;
        }
예제 #34
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);
            }
        }
예제 #35
0
 /// <summary>
 ///   Removes a peer from the game. 
 ///   This method is called if a client sends a <see cref = "LeaveRequest" /> or disconnects.
 /// </summary>
 /// <param name = "peer">
 ///   The <see cref = "HivePeer" /> to remove.
 /// </param>
 /// <param name="isCommingBack">whether we expect peer will come back or not</param>
 /// <returns>
 ///   The actor number of the removed actor. 
 ///   If the specified peer does not exists -1 will be returned.
 /// </returns>
 protected virtual int RemovePeerFromGame(HivePeer peer, bool isCommingBack)
 {
     return this.ActorsManager.RemovePeerFromGame(this, peer, this.PlayerTTL, isCommingBack);
 }
예제 #36
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);
                }
            }
        }
예제 #37
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);
 }
예제 #38
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);
        }
예제 #39
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;
        }
예제 #40
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);
 }
예제 #41
0
        private bool VerifyCanJoin(HivePeer peer, int actorNr, int playerTtl,
                                   out Actor actor, out Photon.Common.ErrorCode errorcode, out string reason, ref bool isNewActor, bool checkUserIdOnJoin, JoinGameRequest joinRequest)
        {
            // check if the peer already is linked to this game
            actor = this.ActorsGetActorByPeer(peer);
            if (actor != null)
            {
                reason    = "Join failed: Peer already joined the specified game.";
                errorcode = Photon.Common.ErrorCode.JoinFailedPeerAlreadyJoined;
                return(false);
            }

            reason = string.Empty;

            var joinMode = joinRequest.JoinMode;

            if (checkUserIdOnJoin)
            {
                if (string.IsNullOrEmpty(peer.UserId))
                {
                    // ERROR: should never happen with auto-generated userid's
                    //        without autogen-userid's its not supported
                    reason    = string.Format("Join failed: UserId is not set, checkUserIdOnJoin=true expects a UserId.");
                    errorcode = Photon.Common.ErrorCode.OperationInvalid;
                    return(false);
                }
                if (!this.CheckExcludeList(peer.UserId, out reason))
                {
                    errorcode = Photon.Common.ErrorCode.JoinFailedFoundExcludedUserId;
                    return(false);
                }

                // check if the userId already joined this game
                actor = GetActorByUserId(this, peer.UserId);
                if (actor != null)
                {
                    if (actor.IsActive)
                    {
                        if (!this.TrySameSessionRejoin(peer, playerTtl, actor, joinMode, joinRequest.ForceRejoin))
                        {
                            reason    = string.Format("Join failed: UserId '{0}' already joined the specified game (JoinMode={1}).", peer.UserId, joinMode);
                            errorcode = Photon.Common.ErrorCode.JoinFailedFoundActiveJoiner;
                            return(false);
                        }

                        errorcode = 0;
                        return(true);
                    }

                    // actor.IsInactive
                    // verify is not inactive actor is not expired, since actorlist could contain expired actors after reload
                    if (canPlayerTtlExpire(playerTtl) && actor.DeactivationTime.HasValue)
                    {
                        var scheduleTime = (int)((DateTime)actor.DeactivationTime - DateTime.Now).TotalMilliseconds + playerTtl;
                        if (scheduleTime <= 0)
                        {
                            reason    = string.Format("Join failed: UserId '{0}' is expired (JoinMode={1}).", peer.UserId, joinMode);
                            errorcode = Photon.Common.ErrorCode.JoinFailedWithRejoinerNotFound;
                            return(false);
                        }
                    }
#if !AutoRejoin
                    if (joinMode != JoinModes.RejoinOnly && joinMode != JoinModes.RejoinOrJoin)
                    {
                        reason    = string.Format("Found inactive UserId '{0}', but not rejoining (JoinMode={1}).", peer.UserId, joinMode);
                        errorcode = Photon.Common.ErrorCode.JoinFailedFoundInactiveJoiner;
                        return(false);
                    }
#endif
                    errorcode = 0;
                    return(true);
                }
            }
            else
            {
                // actorNr > 0 => re-joing with actornr & without userid
                if (actorNr > 0)
                {
                    actor = GetActorByNumber(this, actorNr);
                    if (actor == null)
                    {
                        // not finding the actor was allways an error - so NO JoinOrRejoin (NOR RejoinOrJoin)!
                        reason    = string.Format("Rejoin failed: actor nr={0} not found.", actorNr);
                        errorcode = Photon.Common.ErrorCode.JoinFailedWithRejoinerNotFound;
                        return(false);
                    }

                    if (actor.IsActive)
                    {
                        if (!this.TrySameSessionRejoin(peer, playerTtl, actor, joinMode, false))
                        {
                            reason    = string.Format(HiveErrorMessages.UserAlreadyJoined, actorNr, joinMode);
                            errorcode = Photon.Common.ErrorCode.JoinFailedFoundActiveJoiner;
                            return(false);
                        }

                        errorcode = 0;
                        return(true);
                    }

                    // TODO: comment above stays that we re-join without userid.
                    // why we check it here? it also may be null or empty
                    // this may happen if checkUserOnJoin is false
                    if (actor.IsInactive && actor.UserId != peer.UserId)
                    {
                        Guid tmpGuid;
                        if (!(Guid.TryParse(actor.UserId, out tmpGuid) && Guid.TryParse(peer.UserId, out tmpGuid)))
                        {
                            reason = "Rejoin failed: userId of peer doesn't match userid of actor.";

                            errorcode = errorcode = Photon.Common.ErrorCode.InternalServerError;
                            return(false);
                        }

                        Log.Debug("Rejoin: userId of peer doesn't match userid of actor. But are GUId's - assuming its AutoUserIds");
                    }

                    // actor is inActive
                    if (canPlayerTtlExpire(playerTtl) && actor.DeactivationTime.HasValue)
                    {
                        var sceduleTime = (int)((DateTime)actor.DeactivationTime - DateTime.Now).TotalMilliseconds + playerTtl;
                        if (sceduleTime <= 0)
                        {
                            reason    = string.Format("Join failed: ActorNr '{0}' is expired.", actorNr);
                            errorcode = Photon.Common.ErrorCode.JoinFailedWithRejoinerNotFound;
                            return(false);
                        }
                    }
#if !AutoRejoin
                    if (joinMode != JoinModes.RejoinOnly && joinMode != JoinModes.RejoinOrJoin)
                    {
                        // should never happen, since actorn>0 means rejoinmode is set / see joingamerequest.actornr
                        reason    = string.Format("Found inactive ActorNr '{0}', but not rejoining (JoinMode={1}).", actorNr, joinMode);
                        errorcode = Photon.Common.ErrorCode.InternalServerError;
                        return(false);
                    }
#endif
                    errorcode = 0;
                    return(true);
                }
            }

            if (joinMode == JoinModes.RejoinOnly)
            {
                reason    = string.Format("Rejoin failed: userid={0} not found, actor nr={1}.", peer.UserId, actorNr);
                errorcode = Photon.Common.ErrorCode.JoinFailedWithRejoinerNotFound;
                return(false);
            }

            // create new actor instance
            isNewActor = true;
            errorcode  = 0;
            return(true);
        }
예제 #42
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);
        }
예제 #43
0
 public override bool IsThisSameSession(HivePeer peer)
 {
     return(this.AuthToken != null && peer.AuthToken != null && this.AuthToken.AreEqual(peer.AuthToken));
 }
예제 #44
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);
 }
예제 #45
0
        /// <summary>
        ///   Sends a <see cref = "JoinEvent" /> to all <see cref = "Actor" />s.
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <param name = "joinRequest">
        ///   The join request.
        /// </param>
        protected virtual void PublishJoinEvent(HivePeer peer, JoinGameRequest joinRequest)
        {
            if (this.SuppressRoomEvents)
            {
                return;
            }

            var actor = this.GetActorByPeer(peer);
            if (actor == null)
            {
                Log.ErrorFormat("There is no Actor for peer {0}", peer.ConnectionId);
                return;
            }

            // generate a join event and publish to all actors in the room
            var joinEvent = new JoinEvent(actor.ActorNr, this.ActorsManager.ActorsGetActorNumbers().ToArray());

            if (joinRequest.BroadcastActorProperties)
            {
                joinEvent.ActorProperties = joinRequest.ActorProperties;
                if (this.PublishUserId)
                {
                    if (joinEvent.ActorProperties == null)
                    {
                        joinEvent.ActorProperties = new Hashtable();
                    }
                    joinEvent.ActorProperties.Add((byte)ActorParameter.UserId, peer.UserId);
                }
            }

            this.PublishEvent(joinEvent, this.Actors, new SendParameters());
        }
예제 #46
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;
        }
예제 #47
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);
        }