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 Caching.RoomReference GetRoomReference(JoinGameRequest joinRequest, params object[] args) { return TestGameCache.Instance.GetRoomReference(joinRequest.GameId, this, args); }
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 virtual OperationResponse GetUserJoinResponse(JoinGameRequest joinRequest, int actorNr, ProcessJoinParams prms) { var actor = this.ActorsManager.ActorsGetActorByNumber(actorNr); var joinResponse = new JoinResponse {ActorNr = actor.ActorNr}; if (this.Properties.Count > 0) { joinResponse.CurrentGameProperties = this.Properties.GetProperties(); } foreach (var t in this.ActorsManager) { // if actor is joining normaly we skip its own properties // if actor is rejoining we send its own properties if ((t.ActorNr != actor.ActorNr || (!t.IsInactive && joinRequest.IsRejoining)) && (t.Properties.Count > 0 || this.PublishUserId)) { if (joinResponse.CurrentActorProperties == null) { joinResponse.CurrentActorProperties = new Hashtable(); } var actorProperties = t.Properties.GetProperties(); if (t.IsInactive) { actorProperties.Add((byte) ActorParameter.IsInactive, true); } if (this.PublishUserId) { actorProperties.Add((byte)ActorParameter.UserId, t.UserId); } joinResponse.CurrentActorProperties.Add(t.ActorNr, actorProperties); } } var actorList = new List<int>(); actorList.AddRange(this.ActorsManager.ActorsGetActorNumbers().ToArray()); actorList.AddRange(this.ActorsManager.InactiveActorsGetActorNumbers().ToArray()); if (!this.SuppressRoomEvents) { joinResponse.Actors = actorList.ToArray(); } var oresponse = new OperationResponse(joinRequest.OperationRequest.OperationCode, joinResponse); if (prms.ResponseExtraParameters != null) { foreach (var extraParameter in prms.ResponseExtraParameters) { oresponse.Parameters.Add(extraParameter.Key, extraParameter.Value); } } return oresponse; }
protected bool CreateGame(HivePeer peer, JoinGameRequest request, SendParameters sendParameters) { peer.JoinStage = HivePeer.JoinStages.CreatingOrLoadingGame; return this.Join(peer, request, sendParameters); }
public bool CheckBeforeJoinThisIsNewCreatedRoom(JoinGameRequest request) { if (this.ActorsManager.ActorNumberCounter == 0) { return true; } return false; }
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 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; }
private void HandleCreateGameOperationInt(HivePeer peer, SendParameters sendParameters, JoinGameRequest createGameRequest, bool fromJoin = false) { var createOptions = createGameRequest.GetCreateGameSettings(this); peer.SetPrivateCustomTypeCache(this.customTypeCache); RequestHandler handler = () => { var oldValue = this.allowSetGameState; try { this.allowSetGameState = false; // since we allow to make changes to the original request sent by the client in a plugin // we should check op.IsValid() - if not report error createGameRequest.SetupRequest(); return this.ProcessCreateGame(peer, createGameRequest, sendParameters); } catch (Exception e) { Log.ErrorFormat("Exception: {0}", e); this.allowSetGameState = oldValue; throw; } }; var info = new CreateGameCallInfo(this.PendingPluginContinue, this.callEnv) { Request = createGameRequest, UserId = peer.UserId, Nickname = createGameRequest.GetNickname(), CreateOptions = createOptions, IsJoin = fromJoin, Handler = handler, Peer = peer, SendParams = sendParameters, OnFail = (onFailMsg, errorData) => { this.allowSetGameState = false; this.failureOnCreate = true; this.SendErrorResponse(peer, createGameRequest.OperationCode, ErrorCode.PluginReportedError, onFailMsg, sendParameters, errorData); peer.ReleaseRoomReference(); peer.ScheduleDisconnect(); // this gives the client a chance to get the reason } }; try { this.Plugin.OnCreateGame(info); } catch (Exception e) { this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e); } }
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; }
private void CallPluginOnLeaveIfJoinFailed(byte reason, HivePeer peer, JoinGameRequest request) { if (peer.JoinStage == HivePeer.JoinStages.Connected || peer.JoinStage == Hive.HivePeer.JoinStages.CreatingOrLoadingGame) { if (Log.IsDebugEnabled) { Log.DebugFormat("Peer join stage is {0}. CallPluginOnLeaveIfJoinFailed will be skiped. p:{1}", peer.JoinStage, peer); } return; } if (Log.IsDebugEnabled) { Log.DebugFormat("Peer join stage is {0}. reason:{1}. CallPluginOnLeaveIfJoinFailed is called. p:{2}", peer.JoinStage, reason, peer); } var actor = this.GetActorByPeer(peer); RequestHandler handler = () => { try { this.RemovePeerFromGame(peer, false); } catch (Exception e) { Log.ErrorFormat("Exception: {0}", e); throw; } return true; }; var info = new LeaveGameCallInfo(this.PendingPluginContinue, this.callEnv) { ActorNr = actor != null ? actor.ActorNr : -1, UserId = actor != null ? actor.UserId : peer.UserId, Nickname = actor != null ? actor.Nickname : request.GetNickname(), IsInactive = false, Reason = reason, Request = null, Handler = handler, Peer = null, SendParams = new SendParameters(), }; try { this.Plugin.OnLeave(info); } catch (Exception e) { this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e); } }
protected virtual bool ProcessJoin(int actorNr, JoinGameRequest joinRequest, SendParameters sendParameters, ProcessJoinParams prms, HivePeer peer) { return this.JoinSendResponseAndEvents(peer, joinRequest, sendParameters, actorNr, prms); }
protected virtual bool ProcessCreateGame(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters) { var result = this.CreateGame(peer, joinRequest, sendParameters); this.ActorsManager.DeactivateActors(this); return result; }
protected virtual bool ProcessBeforeJoinGame(JoinGameRequest joinRequest, SendParameters sendParameters, HivePeer peer) { Actor actor; if (!this.JoinApplyGameStateChanges(peer, joinRequest, sendParameters, out actor)) { this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, joinRequest); return false; } peer.JoinStage = HivePeer.JoinStages.BeforeJoinComplete; var info = new JoinGameCallInfo(this.PendingPluginContinue, this.callEnv) { UserId = peer.UserId, Peer = peer, Nickname = actor.Nickname, ActorNr = actor.ActorNr, Request = joinRequest, JoinParams = new ProcessJoinParams(), OnFail = (reason, parameters) => this.OnJoinFailHandler(LeaveReason.PluginFailedJoin, reason, parameters, peer, sendParameters, joinRequest), }; RequestHandler handler = () => { try { if (!this.ProcessJoin(actor.ActorNr, joinRequest, sendParameters, info.JoinParams, peer)) { // here we suppose that error response is already sent this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, joinRequest); return false; } } catch (Exception e) { Log.ErrorFormat("Exception:{0}", e); throw; } return true; }; info.Handler = handler; try { this.Plugin.OnJoin(info); } catch (Exception e) { this.Plugin.ReportError(ErrorCodes.UnhandledException, e); } return true; }
protected override void JoinFailureHandler(byte leaveReason, HivePeer peer, JoinGameRequest request) { base.JoinFailureHandler(leaveReason, peer, request); if (Log.IsDebugEnabled) { Log.DebugFormat("JoinFailureHandler is called for peer with reason:{0}.room:{1},p:{2}", request.FailureReason, this.Name, peer); } this.CallPluginOnLeaveIfJoinFailed(leaveReason, peer, request); peer.ScheduleDisconnect(); }
/// <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()); }
/// <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); }
private void OnJoinFailHandler(byte leaveReason, string reasonDetails, Dictionary<byte, object> parameters, HivePeer peer, SendParameters sendParameters, JoinGameRequest request) { this.SendErrorResponse(peer, request.OperationCode, ErrorCode.PluginReportedError, reasonDetails, sendParameters, parameters); if (Log.IsWarnEnabled) { Log.WarnFormat("OnJoinFailHandler: Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}", this.Name, peer.UserId, reasonDetails, peer); } this.JoinFailureHandler(leaveReason, peer, request); }
private void ApplyGameProperties(JoinGameRequest createRequest) { // set default properties if (createRequest.newMaxPlayer.HasValue && createRequest.newMaxPlayer.Value != this.MaxPlayers) { this.MaxPlayers = createRequest.newMaxPlayer.Value; } if (createRequest.newIsOpen.HasValue && createRequest.newIsOpen.Value != this.IsOpen) { this.IsOpen = createRequest.newIsOpen.Value; } if (createRequest.newIsVisible.HasValue && createRequest.newIsVisible.Value != this.IsVisible) { this.IsVisible = createRequest.newIsVisible.Value; } if (createRequest.newLobbyProperties != null) { this.LobbyProperties = new HashSet<object>(createRequest.newLobbyProperties); } this.LobbyId = createRequest.LobbyName; this.LobbyType = (AppLobbyType)createRequest.LobbyType; }
private bool ValidatePlugin(JoinGameRequest operation, out string msg) { if (operation.Plugins != null) { if (operation.Plugins.Length > 0) { if (operation.Plugins.Length > 1) { msg = "Currently only one plugin per game supported."; return false; } if (this.Plugin.Name != operation.Plugins[0]) { var errorPlugin = this.Plugin as ErrorPlugin; if (errorPlugin != null) { msg = string.Format("Plugin Mismatch requested='{0}' got ErrorPlugin with message:'{1}'", operation.Plugins[0], errorPlugin.Message); } else { msg = string.Format("Plugin Mismatch requested='{0}' got='{1}'", operation.Plugins[0], this.Plugin.Name); } return false; } } else { if (this.Plugin.Name != "Default") { msg = string.Format("Room is setup with unexpected plugin '{0}' - instead of default (none).", this.Plugin.Name); return false; } } } msg = string.Empty; return true; }
private void CopyGamePropertiesForMasterUpdate(JoinGameRequest request) { request.properties = this.Properties.GetProperties(); if (this.MaxPlayers != 0) { request.newMaxPlayer = this.MaxPlayers; } request.newIsOpen = this.IsOpen; request.newIsVisible = this.IsVisible; if (this.LobbyProperties != null) { request.newLobbyProperties = new object[this.LobbyProperties.Count]; this.LobbyProperties.CopyTo(request.newLobbyProperties); } }
protected override OperationResponse GetUserJoinResponse(JoinGameRequest joinRequest, int actorNr, ProcessJoinParams prms) { var res = base.GetUserJoinResponse(joinRequest, actorNr, prms); if (this.Plugin.Name != "Default") { res.Parameters.Add((byte)ParameterKey.PluginName, this.Plugin.Name); res.Parameters.Add((byte)ParameterKey.PluginVersion, this.Plugin.Version); } return res; }
protected virtual bool AddExpectedUsers(JoinGameRequest joinRequest) { return this.ActorsManager.TryAddExpectedUsers(this, joinRequest); }
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); } } }
/// <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); } }
protected virtual void JoinFailureHandler(byte leaveReason, HivePeer peer, JoinGameRequest request) { if (Log.IsDebugEnabled) { Log.DebugFormat("JoinFailureHandler is called for peer with reason:{0}.room:{1},p:{2}", request.FailureReason, this.Name, peer); } peer.OnJoinFailed(request.FailureReason, request.FailureMessage); }
/// <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); }
protected bool JoinSendResponseAndEvents(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters, int actorNr, ProcessJoinParams prms) { peer.JoinStage = HivePeer.JoinStages.GettingUserResponse; var oresponse = this.GetUserJoinResponse(joinRequest, actorNr, prms); peer.SendOperationResponse(oresponse, sendParameters); peer.JoinStage = HivePeer.JoinStages.PublishingEvents; this.PublishJoinEvent(peer, joinRequest); peer.JoinStage = HivePeer.JoinStages.EventsPublished; this.PublishEventCache(peer, joinRequest); peer.JoinStage = HivePeer.JoinStages.Complete; return true; }
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; }
/// <summary> /// Sends all cached events to a peer. /// </summary> /// <param name = "litePeer"> /// The lite peer that receives the events. /// </param> /// <param name="joinRequest"></param> protected void PublishEventCache(HivePeer litePeer, JoinGameRequest joinRequest) { var @event = new CustomEvent(0, 0, null); foreach (KeyValuePair<int, EventCache> entry in this.ActorEventCache) { var actor = entry.Key; var cache = entry.Value; @event.ActorNr = actor; foreach (KeyValuePair<byte, Hashtable> eventEntry in cache) { @event.Code = @eventEntry.Key; @event.Data = @eventEntry.Value; var eventData = new EventData(@event.Code, @event); litePeer.SendEvent(eventData, new SendParameters()); } } int cacheSliceRequested = 0; if (joinRequest.CacheSlice.HasValue) { cacheSliceRequested = joinRequest.CacheSlice.Value; } foreach (var slice in this.EventCache.Slices) { if (slice >= cacheSliceRequested) { if (slice != 0) { var sliceChangedEvent = new CacheSliceChanged(0) { Slice = slice }; this.PublishEvent(sliceChangedEvent, this.GetActorByPeer(litePeer), new SendParameters()); } foreach (var customEvent in this.EventCache[slice]) { var eventData = new EventData(customEvent.Code, customEvent); litePeer.SendEvent(eventData, new SendParameters()); } } } }