예제 #1
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;
        }
예제 #2
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);
        }
예제 #3
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);
                }
            }
        }
예제 #4
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;
        }
예제 #5
0
        private bool CheckGameCanBeCreated(HivePeer peer, JoinGameRequest joinGameRequest)
        {
            if (joinGameRequest.OperationCode == (byte)OperationCode.Join
                || joinGameRequest.JoinMode == JoinModes.CreateIfNotExists
                || joinGameRequest.JoinMode == JoinModes.RejoinOrJoin // for backwards compatibility - it seams some games expect this behavior - ISSUE: Codemasters uses RejoinOrJoin and now expects this to return false!
                || this.Plugin.IsPersistent)
            {
                return true;
            }

            this.SendErrorResponse(peer, joinGameRequest.OperationCode,
                ErrorCode.GameIdNotExists, HiveErrorMessages.GameIdDoesNotExist, new SendParameters());

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

            joinGameRequest.OnJoinFailed(ErrorCode.GameIdNotExists, HiveErrorMessages.GameIdDoesNotExist);

            this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, joinGameRequest);
            return false;
        }