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; }
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); }