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); }
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; } }
/// <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; }
/// <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); }
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); }
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); }
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)); }
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); }
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)); }
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); }
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); } }
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); }
/// <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; }
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); }
/// <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); }
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)); }
/// <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); }
protected virtual void HandleCreateGameOperation(HivePeer peer, SendParameters sendParameters, CreateGameRequest createGameRequest) { this.CreateGame(peer, createGameRequest, sendParameters); }
/// <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; }
protected bool CreateGame(HivePeer peer, JoinGameRequest request, SendParameters sendParameters) { peer.JoinStage = HivePeer.JoinStages.CreatingOrLoadingGame; return this.Join(peer, request, sendParameters); }
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; }
protected virtual void HandleRemovePeerMessage(HivePeer peer, int reason, string details) { this.RemovePeerFromGame(peer, isCommingBack: false); }
/// <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); }
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); }
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); }
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; }
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; }
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; }
protected override void JoinFailureHandler(byte leaveReason, HivePeer peer, JoinGameRequest request) { base.JoinFailureHandler(leaveReason, peer, request); this.NotifyMasterUserFailedToAdd((GameClientPeer)peer); }
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); }
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; }
/// <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); } }
/// <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); }
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); } } }
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); }
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); }
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; }
/// <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); }
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); }
/// <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); }
public override bool IsThisSameSession(HivePeer peer) { return(this.AuthToken != null && peer.AuthToken != null && this.AuthToken.AreEqual(peer.AuthToken)); }
/// <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); }
/// <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()); }
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); }