/// <summary> /// Enqueues game related operation requests in the peers current game. /// </summary> /// <param name = "operationRequest"> /// The operation request. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> /// <remarks> /// The current for a peer is stored in the peers state property. /// Using the <see cref = "Room.EnqueueOperation" /> method ensures that all operation request dispatch logic has thread safe access to all room instance members since they are processed in a serial order. /// <para> /// Inheritors can use this method to enqueue there custom game operation to the peers current game. /// </para> /// </remarks> private void HandleChangeGroupsOperation(OperationRequest operationRequest, SendParameters sendParameters) { if (this.joinStage < JoinStages.PublishingEvents) { this.OnWrongOperationStage(operationRequest, sendParameters); return; } var changeGroupsOperation = new ChangeGroups(this.Protocol, operationRequest); if (this.ValidateOperation(changeGroupsOperation, sendParameters) == false) { return; } this.AddOperationToQueue(operationRequest.OperationCode, "game op"); // enqueue operation into game queue. // the operation request will be processed in the games ExecuteOperation method. if (this.RoomReference != null) { this.RoomReference.Room.EnqueueOperation(this, changeGroupsOperation, sendParameters); return; } if (log.IsDebugEnabled) { log.DebugFormat("Received ChangeGroups operation on peer without a game: p:{0}", this); } }
/// <summary> /// Handles WebRpc operation /// </summary> /// <param name = "request"> /// The operation request to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleRpcOperation(OperationRequest request, SendParameters sendParameters) { this.AddOperationToQueue(request.OperationCode); if (this.WebRpcHandler != null) { if (this.HttpRpcCallsLimit > 0 && this.httpForwardedRequests.Increment(1) > this.HttpRpcCallsLimit) { var resp = new OperationResponse { OperationCode = request.OperationCode, ReturnCode = (short)ErrorCode.HttpLimitReached, DebugMessage = String.Format(HiveErrorMessages.HttpForwardedOperationsLimitReached, this.HttpRpcCallsLimit) }; this.SendOperationResponse(resp, sendParameters); return; } this.WebRpcHandler.HandleCall(this, this.UserId, request, this.AuthCookie, sendParameters); return; } this.SendOperationResponse(new OperationResponse { OperationCode = request.OperationCode, ReturnCode = (short)ErrorCode.OperationInvalid, DebugMessage = HiveErrorMessages.WebRpcIsNotEnabled, }, sendParameters); }
/// <summary> /// Publishes an event to a list of actors on a specified channel. /// </summary> /// <param name = "e"> /// The event to publish. /// </param> /// <param name = "actorList"> /// A list of <see cref = "Actor" /> who should receive the event. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected void PublishEvent(HiveEventBase e, IEnumerable <Actor> actorList, SendParameters sendParameters) { var peers = actorList.Select(actor => actor.Peer); var eventData = new EventData(e.Code, e); ApplicationBase.Instance.BroadCastEvent(eventData, peers, sendParameters); }
private void OnWrongOperationStage(OperationRequest operationRequest, SendParameters sendParameters) { this.SendOperationResponse(new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = (short)ErrorCode.OperationDenied, DebugMessage = HiveErrorMessages.OperationIsNotAllowedOnThisJoinStage, }, sendParameters); }
private void SendErrorResponse(PeerBase peer, byte opCode, SendParameters sp, short retCode = (short)ErrorCode.ExternalHttpCallFailed, string msg = "", Dictionary <byte, object> parameters = null) { var response = new OperationResponse(opCode) { DebugMessage = msg, ReturnCode = retCode, Parameters = parameters }; peer.SendOperationResponse(response, sp); }
protected void HandleUnknownOperationCode(OperationRequest operationRequest, SendParameters sendParameters) { if (log.IsDebugEnabled) { log.DebugFormat("Unknown operation code: OpCode={0}", operationRequest.OperationCode); } this.SendOperationResponse( new OperationResponse(operationRequest.OperationCode) { ReturnCode = (short)ErrorCode.OperationInvalid, DebugMessage = HiveErrorMessages.UnknownOperationCode }, sendParameters); }
/// <summary> /// Checks if a operation is valid. If the operation is not valid /// an operation response containing a desciptive error message /// will be sent to the peer. /// </summary> /// <param name = "operation"> /// The operation. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> /// <returns> /// true if the operation is valid; otherwise false. /// </returns> public bool ValidateOperation(Operation operation, SendParameters sendParameters) { if (operation.IsValid) { return(true); } var errorMessage = operation.GetErrorMessage(); this.SendOperationResponse(new OperationResponse { OperationCode = operation.OperationRequest.OperationCode, ReturnCode = (short)ErrorCode.OperationInvalid, DebugMessage = errorMessage }, sendParameters); return(false); }
private void HandleRoomNotFound(SendParameters sendParameters, JoinGameRequest joinRequest) { this.OnRoomNotFound(joinRequest.GameId); var response = new OperationResponse { OperationCode = (byte)OperationCode.JoinGame, ReturnCode = (short)ErrorCode.GameIdNotExists, DebugMessage = HiveErrorMessages.GameIdDoesNotExist, }; this.SendOperationResponse(response, sendParameters); if (log.IsDebugEnabled) { log.DebugFormat("Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}", joinRequest.GameId, this.UserId, HiveErrorMessages.GameIdDoesNotExist, this); } }
protected bool CreateGame(HivePeer peer, JoinGameRequest request, SendParameters sendParameters) { peer.JoinStage = HivePeer.JoinStages.CreatingOrLoadingGame; return this.Join(peer, request, 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; }
/// <summary> /// Handles the <see cref = "JoinGameRequest" /> to enter a <see cref = "HiveGame" />. /// This method removes the peer from any previously joined room, finds the room intended for join /// and enqueues the operation for it to handle. /// </summary> /// <param name = "operationRequest"> /// The operation request to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleJoinGameOperation(OperationRequest operationRequest, SendParameters sendParameters) { if (this.JoinStage != JoinStages.Connected) { this.OnWrongOperationStage(operationRequest, sendParameters); return; } // create join operation var joinRequest = new JoinGameRequest(this.Protocol, operationRequest); if (this.ValidateOperation(joinRequest, sendParameters) == false) { return; } // remove peer from current game this.RemovePeerFromCurrentRoom(LeaveReason.SwitchRoom, "eventual switch from other room."); // try to get the game reference from the game cache RoomReference gameReference; var pluginTraits = this.GetPluginTraits(); if (joinRequest.JoinMode > 0 || pluginTraits.AllowAsyncJoin) { var pluginName = joinRequest.Plugins != null && joinRequest.Plugins.Length > 0? joinRequest.Plugins[0] : String.Empty; gameReference = this.GetOrCreateRoom(joinRequest.GameId, pluginName); } else { if (this.TryGetRoomReference(joinRequest.GameId, out gameReference) == false) { this.OnRoomNotFound(joinRequest.GameId); var response = new OperationResponse { OperationCode = (byte)OperationCode.JoinGame, ReturnCode = (short)ErrorCode.GameIdNotExists, DebugMessage = HiveErrorMessages.GameIdDoesNotExist, }; this.SendOperationResponse(response, sendParameters); if (log.IsWarnEnabled) { log.WarnFormat("Game '{0}' userId '{1}' failed to join. msg:{2} -- peer:{3}", joinRequest.GameId, this.UserId, HiveErrorMessages.GameIdDoesNotExist, this); } return; } } // save the game reference in the peers state this.RoomReference = gameReference; // finally enqueue the operation into game queue gameReference.Room.EnqueueOperation(this, operationRequest, sendParameters); }
/// <summary> /// Handles the <see cref = "LeaveRequest" /> to leave a <see cref = "HiveGame" />. /// </summary> /// <param name = "operationRequest"> /// The operation request to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleLeaveOperation(OperationRequest operationRequest, SendParameters sendParameters) { // check if the peer have a reference to game if (this.RoomReference == null) { if (log.IsDebugEnabled) { log.DebugFormat("Received leave operation on peer without a game: peerId={0}", this.ConnectionId); } return; } // enqueue the leave operation into game queue. this.RoomReference.Room.EnqueueOperation(this, operationRequest, sendParameters); this.ReleaseRoomReferenceInternal(); }
protected override void HandleCreateGameOperation(HivePeer peer, SendParameters sendParameters, CreateGameRequest createGameRequest) { if (this.isClosed) { if (!this.ReinitGame()) { this.SendErrorResponse(peer, createGameRequest.OperationCode, ErrorCode.InternalServerError, HiveErrorMessages.ReinitGameFailed, sendParameters); createGameRequest.OnJoinFailed(ErrorCode.InternalServerError, HiveErrorMessages.ReinitGameFailed); this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, createGameRequest); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' failed to create game. msg:{2} -- peer:{3}", this.Name, peer.UserId, HiveErrorMessages.ReinitGameFailed, peer); } return; } } string msg; if (!this.ValidatePlugin(createGameRequest, out msg)) { this.SendErrorResponse(peer, createGameRequest.OperationCode, ErrorCode.PluginMismatch, msg, sendParameters); createGameRequest.OnJoinFailed(ErrorCode.PluginMismatch, msg); this.JoinFailureHandler(LeaveReason.ServerDisconnect, peer, createGameRequest); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' failed to create game. msg:{2} -- peer:{3}", this.Name, peer.UserId, msg, peer); } return; } this.HandleCreateGameOperationInt(peer, sendParameters, createGameRequest); }
/// <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 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; }
/// <summary> /// Handles the <see cref = "JoinGameRequest" /> to enter a <see cref = "HiveGame" />. /// This method removes the peer from any previously joined room, finds the room intended for join /// and enqueues the operation for it to handle. /// </summary> /// <param name = "operationRequest"> /// The operation request to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleJoinOperation(OperationRequest operationRequest, SendParameters sendParameters) { if (this.JoinStage != JoinStages.Connected) { this.OnWrongOperationStage(operationRequest, sendParameters); return; } // create join operation var joinRequest = new JoinGameRequest(this.Protocol, operationRequest); if (this.ValidateOperation(joinRequest, sendParameters) == false) { return; } // remove peer from current game this.RemovePeerFromCurrentRoom(LeaveReason.SwitchRoom, "eventual switch from other room."); // get a game reference from the game cache // the game will be created by the cache if it does not exists already var pluginName = joinRequest.Plugins != null && joinRequest.Plugins.Length > 0 ? joinRequest.Plugins[0] : String.Empty; var gameReference = this.GetRoomReference(joinRequest, pluginName); // save the game reference in the peers state this.RoomReference = gameReference; // finally enqueue the operation into game queue gameReference.Room.EnqueueOperation(this, operationRequest, sendParameters); }
/// <summary> /// Called when the client sends an <see cref = "OperationRequest" />. /// </summary> /// <param name = "operationRequest"> /// The operation request. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters) { Dictionary <byte, object> dict = operationRequest.Parameters; foreach (object value in dict.Values) { log.Info("============HivePeer==========:" + value.ToString()); } if (log.IsDebugEnabled) { log.DebugFormat("OnOperationRequest. Code={0}", operationRequest.OperationCode); } var opCode = (OperationCode)operationRequest.OperationCode; switch (opCode) { case OperationCode.Authenticate: this.AddOperationToQueue(operationRequest.OperationCode); return; case OperationCode.CreateGame: this.AddOperationToQueue(operationRequest.OperationCode); this.HandleCreateGameOperation(operationRequest, sendParameters); return; case OperationCode.JoinGame: this.HandleJoinGameOperation(operationRequest, sendParameters); return; case OperationCode.Ping: this.HandlePingOperation(operationRequest, sendParameters); return; case OperationCode.DebugGame: this.HandleDebugGameOperation(operationRequest, sendParameters); return; case OperationCode.Leave: this.HandleLeaveOperation(operationRequest, sendParameters); return; case OperationCode.RaiseEvent: this.HandleRaiseEventOperation(operationRequest, sendParameters); return; case OperationCode.GetProperties: this.HandleGetPropertiesOperation(operationRequest, sendParameters); return; case OperationCode.SetProperties: this.HandleSetPropertiesOperation(operationRequest, sendParameters); return; case OperationCode.ChangeGroups: this.HandleChangeGroupsOperation(operationRequest, sendParameters); return; case OperationCode.Rpc: this.HandleRpcOperation(operationRequest, sendParameters); return; default: this.HandleUnknownOperationCode(operationRequest, sendParameters); return; } }
/// <summary> /// Handles the <see cref = "LeaveRequest" /> to leave a <see cref = "HiveGame" />. /// </summary> /// <param name = "operationRequest"> /// The operation request to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleLeaveOperation(OperationRequest operationRequest, SendParameters sendParameters) { // check if the peer have a reference to game if (this.RoomReference == null) { if (log.IsDebugEnabled) { log.DebugFormat("Received leave operation on peer without a game: peerId={0}", this.ConnectionId); } return; } var leaveOperation = new LeaveRequest(this.Protocol, operationRequest); if (this.ValidateOperation(leaveOperation, sendParameters) == false) { if (log.IsDebugEnabled) { log.Debug($"Wrong leave request. Use default one. errorMsg:{leaveOperation.GetErrorMessage()}"); } // we create default request to remove actor for sure leaveOperation = new LeaveRequest(this.Protocol, EmptyLeaveRequest); } this.AddOperationToQueue(operationRequest.OperationCode, $"IsInActive:{leaveOperation.IsCommingBack}"); var rr = this.RoomReference; this.RoomReference = null; // enqueue the leave operation into game queue. rr.Room.EnqueueOperation(this, leaveOperation, sendParameters); DisposeRoomReference(rr); }
/// <summary> /// Handles a ping operation. /// </summary> /// <param name = "operationRequest"> /// The operation request to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandlePingOperation(OperationRequest operationRequest, SendParameters sendParameters) { this.AddOperationToQueue(operationRequest.OperationCode); this.SendOperationResponse(new OperationResponse { OperationCode = operationRequest.OperationCode }, sendParameters); }
/// <summary> /// Handles the <see cref = "JoinGameRequest" /> to enter a <see cref = "HiveGame" />. /// This method removes the peer from any previously joined room, finds the room intended for join /// and enqueues the operation for it to handle. /// </summary> /// <param name = "operationRequest"> /// The operation request to handle. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void HandleJoinGameOperation(OperationRequest operationRequest, SendParameters sendParameters) { if (this.JoinStage != JoinStages.Connected || this.RoomReference != null) { this.OnWrongOperationStage(operationRequest, sendParameters); return; } // create join operation var joinRequest = new JoinGameRequest(this.Protocol, operationRequest, this.UserId); if (this.ValidateOperation(joinRequest, sendParameters) == false) { return; } // try to get the game reference from the game cache RoomReference gameReference; var pluginTraits = this.GetPluginTraits(); if (joinRequest.JoinMode > 0 || pluginTraits.AllowAsyncJoin) { gameReference = this.GetOrCreateRoom(joinRequest.GameId); } else { if (this.TryGetRoomReference(joinRequest.GameId, out gameReference) == false) { this.HandleRoomNotFound(sendParameters, joinRequest); return; } } // save the game reference in the peers state this.RoomReference = gameReference; this.roomCreationTS = gameReference.Room.RoomCreationTS; this.AddOperationToQueue(operationRequest.OperationCode, $"JoinMode:{joinRequest.JoinMode}"); // finally enqueue the operation into game queue gameReference.Room.EnqueueOperation(this, joinRequest, sendParameters); }
protected virtual void HandleCreateGameOperation(OperationRequest operationRequest, SendParameters sendParameters) { // The JoinRequest from the Lite application is also used for create game operations to support all feaures // provided by Lite games. // The only difference is the operation code to prevent games created by a join operation. // On "LoadBalancing" game servers games must by created first by the game creator to ensure that no other joining peer // reaches the game server before the game is created. var createRequest = new JoinGameRequest(this.Protocol, operationRequest); if (this.ValidateOperation(createRequest, sendParameters) == false) { return; } // remove peer from current game this.RemovePeerFromCurrentRoom(LeaveReason.SwitchRoom, "eventual switch from other room."); var pluginName = createRequest.Plugins != null && createRequest.Plugins.Length > 0 ? createRequest.Plugins[0] : String.Empty; // try to create the game RoomReference gameReference; if (this.TryCreateRoom(createRequest.GameId, out gameReference, pluginName) == false) { var response = new OperationResponse { OperationCode = (byte)OperationCode.CreateGame, ReturnCode = (short)ErrorCode.GameIdAlreadyExists, DebugMessage = HiveErrorMessages.GameAlreadyExist, }; this.SendOperationResponse(response, sendParameters); return; } // save the game reference in the peers state this.RoomReference = gameReference; // finally enqueue the operation into game queue gameReference.Room.EnqueueOperation(this, operationRequest, sendParameters); }
protected virtual void HandleCreateGameOperation(OperationRequest operationRequest, SendParameters sendParameters) { if (this.JoinStage != JoinStages.Connected || this.RoomReference != null) { this.OnWrongOperationStage(operationRequest, sendParameters); return; } // On "LoadBalancing" game servers games must by created first by the game creator to ensure that no other joining peer // reaches the game server before the game is created. // we use JoinGameRequest to make sure that GameId is set var createRequest = new JoinGameRequest(this.Protocol, operationRequest, this.UserId); if (this.ValidateOperation(createRequest, sendParameters) == false) { return; } // try to create the game RoomReference gameReference; if (this.TryCreateRoom(createRequest.GameId, out gameReference) == false) { var response = new OperationResponse { OperationCode = (byte)OperationCode.CreateGame, ReturnCode = (short)ErrorCode.GameIdAlreadyExists, DebugMessage = HiveErrorMessages.GameAlreadyExist, }; this.SendOperationResponse(response, sendParameters); return; } // save the game reference in the peers state this.RoomReference = gameReference; this.roomCreationTS = gameReference.Room.RoomCreationTS; this.AddOperationToQueue(operationRequest.OperationCode); // finally enqueue the operation into game queue gameReference.Room.EnqueueOperation(this, createRequest, sendParameters); }
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 bool ProcessLeaveGame(int actorNr, LeaveRequest request, SendParameters sendParameters, HivePeer peer) { this.LeaveOperationHandler(peer, sendParameters, request); return true; }
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 virtual bool ProcessSetProperties(HivePeer peer, bool result, string errorMsg, SetPropertiesRequest request, SendParameters sendParameters) { this.PublishResultsAndSetGameProperties(result, errorMsg, request, peer, sendParameters); 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); }
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); }
public bool HandleCall(PeerBase peer, string userId, OperationRequest request, object authResultsSecure, SendParameters sp) { var rpcRequest = new WebRpcRequest(peer.Protocol, request); if (!rpcRequest.IsValid) { var msg = string.Format("Invalid RPC request format: {0}", rpcRequest.GetErrorMessage()); Log.Error(msg); this.SendErrorResponse(peer, request.OperationCode, sp, (short)ErrorCode.OperationInvalid, msg); return(false); } try { var data = this.SerializeRequest(rpcRequest, userId, authResultsSecure); var uri = this.MakeRequestUri(rpcRequest); return(this.SendHttpRequest(peer, uri, data, rpcRequest)); } catch (Exception e) { var msg = string.Format("Exception during RPC request handling {0}", e); Log.Error(msg); this.SendErrorResponse(peer, request.OperationCode, sp, msg: msg); } return(true); }
/// <summary> /// Called when the client sends an <see cref = "OperationRequest" />. /// </summary> /// <param name = "operationRequest"> /// The operation request. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters) { if (log.IsDebugEnabled) { log.DebugFormat("OnOperationRequest. Code={0}", operationRequest.OperationCode); } switch ((OperationCode)operationRequest.OperationCode) { case OperationCode.Authenticate: //this.HandleAuthenticateOperation(request, sendParameters); return; case OperationCode.CreateGame: this.HandleCreateGameOperation(operationRequest, sendParameters); return; case OperationCode.JoinGame: this.HandleJoinGameOperation(operationRequest, sendParameters); return; case OperationCode.Ping: this.HandlePingOperation(operationRequest, sendParameters); return; case OperationCode.DebugGame: //this.HandleDebugGameOperation(request, sendParameters); return; case OperationCode.Join: this.HandleJoinOperation(operationRequest, sendParameters); return; case OperationCode.Leave: this.HandleLeaveOperation(operationRequest, sendParameters); return; case OperationCode.RaiseEvent: case OperationCode.GetProperties: case OperationCode.SetProperties: case OperationCode.ChangeGroups: this.HandleGameOperation(operationRequest, sendParameters); return; case OperationCode.Rpc: if (this.WebRpcHandler != null) { this.WebRpcHandler.HandleCall(this, this.UserId, operationRequest, this.AuthCookie, sendParameters); return; } this.SendOperationResponse(new OperationResponse { OperationCode = (byte)OperationCode.Rpc, ReturnCode = (short)ErrorCode.OperationInvalid, DebugMessage = "Rpc is not enabled", }, sendParameters); return; } var message = String.Format("Unknown operation code {0}", operationRequest.OperationCode); this.SendOperationResponse(new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = (short)ErrorCode.OperationInvalid, DebugMessage = message }, sendParameters); }
protected virtual bool ProcessRaiseEvent(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters, Actor actor) { return this.RaiseEventOperationHandler(peer, raiseEventRequest, sendParameters, actor); }
protected virtual void HandleDebugGameOperation(OperationRequest operationRequest, SendParameters sendParameters) { }
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); } }
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); }
private void OnSetPropertiesFailHandler(string errorMessage, Dictionary<byte, object> parameters, Hashtable oldPropertyValues, SetPropertiesRequest request, HivePeer peer, SendParameters sendParameters) { LogPlugin.Error(errorMessage); this.SendErrorResponse(peer, request.OperationCode, ErrorCode.PluginReportedError, errorMessage, sendParameters, parameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' SetProperties plugin error. msg:{2} -- peer:{3}", this.Name, peer.UserId, errorMessage, peer); } this.RevertProperties(oldPropertyValues, request); }
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 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); } } }
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 void LeaveOperationHandler(HivePeer peer, SendParameters sendParameters, LeaveRequest request) { this.RemovePeerFromGame(peer, request != null && request.IsCommingBack); if (peer != null && request != null) { // is always reliable, so it gets a response peer.SendOperationResponse(new OperationResponse { OperationCode = request.OperationRequest.OperationCode }, sendParameters); } }
/// <summary> /// Enqueues game related operation requests in the peers current game. /// </summary> /// <param name = "operationRequest"> /// The operation request. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> /// <remarks> /// The current for a peer is stored in the peers state property. /// Using the <see cref = "Room.EnqueueOperation" /> method ensures that all operation request dispatch logic has thread safe access to all room instance members since they are processed in a serial order. /// <para> /// Inheritors can use this method to enqueue there custom game operation to the peers current game. /// </para> /// </remarks> protected virtual void HandleGameOperation(OperationRequest operationRequest, SendParameters sendParameters) { if (this.JoinStage != JoinStages.Complete) { this.OnWrongOperationStage(operationRequest, sendParameters); return; } // enqueue operation into game queue. // the operation request will be processed in the games ExecuteOperation method. if (this.RoomReference != null) { this.RoomReference.Room.EnqueueOperation(this, operationRequest, sendParameters); return; } if (log.IsDebugEnabled) { log.DebugFormat("Received game operation on peer without a game: peerId={0}", this.ConnectionId); } }
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; }
//当客户端成功连接服务器时调用 protected override void OnOperationRequest(Photon.SocketServer.OperationRequest operationRequest, Photon.SocketServer.SendParameters sendParameters) { //通过opcode获得处理的handler,如果找不到,则使用默认的Handler BaseHandler baseHandler = DictTool.GetValue <ResponseCode, BaseHandler>(Main.Instance.HandlerDict, (ResponseCode)operationRequest.OperationCode); if (baseHandler != null) { baseHandler.OnOperationRequest(operationRequest, sendParameters, this); } else { DictTool.GetValue <ResponseCode, BaseHandler>(Main.Instance.HandlerDict, (ResponseCode)ResponseCode.Default) .OnOperationRequest(operationRequest, sendParameters, this); } }
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> /// Enqueues an <see cref = "OperationRequest" /> to the end of the execution queue. /// </summary> /// <param name = "peer"> /// The peer. /// </param> /// <param name = "operationRequest"> /// The operation request to enqueue. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> /// <remarks> /// <see cref = "ExecuteOperation" /> is called sequentially for each operation request /// stored in the execution queue. /// Using an execution queue ensures that operation request are processed in order /// and sequentially to prevent object synchronization (multi threading). /// </remarks> public void EnqueueOperation(HivePeer peer, OperationRequest operationRequest, SendParameters sendParameters) { this.ExecutionFiber.Enqueue(() => this.ExecuteOperation(peer, operationRequest, sendParameters)); }
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); }
/// <summary> /// This method is invoked sequentially for each operation request /// enqueued in the <see cref = "ExecutionFiber" /> using the /// <see cref = "EnqueueOperation" /> method. /// </summary> /// <param name = "peer"> /// The peer. /// </param> /// <param name = "operation"> /// The operation request. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected virtual void ExecuteOperation(HivePeer peer, OperationRequest operation, SendParameters sendParameters) { }
/// <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> /// Publishes an event to a single actor on a specified channel. /// </summary> /// <param name = "e"> /// The event to publish. /// </param> /// <param name = "actor"> /// The <see cref = "Actor" /> who should receive the event. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected void PublishEvent(HiveEventBase e, Actor actor, SendParameters sendParameters) { var eventData = new EventData(e.Code, e); actor.Peer.SendEvent(eventData, sendParameters); }
protected virtual void HandleCreateGameOperation(HivePeer peer, SendParameters sendParameters, CreateGameRequest createGameRequest) { this.CreateGame(peer, createGameRequest, sendParameters); }
/// <summary> /// Publishes an event to a list of actors on a specified channel. /// </summary> /// <param name = "e"> /// The event to publish. /// </param> /// <param name = "actorList"> /// A list of <see cref = "Actor" /> who should receive the event. /// </param> /// <param name = "sendParameters"> /// The send Parameters. /// </param> protected void PublishEvent(EventData e, IEnumerable <Actor> actorList, SendParameters sendParameters) { var peers = actorList.Select(actor => actor.Peer); ApplicationBase.Instance.BroadCastEvent(e, peers, sendParameters); }
/// <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 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); }
/// <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 virtual bool ProcessCreateGame(HivePeer peer, JoinGameRequest joinRequest, SendParameters sendParameters) { var result = this.CreateGame(peer, joinRequest, sendParameters); this.ActorsManager.DeactivateActors(this); return result; }
/// <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); }
protected virtual bool ProcessJoin(int actorNr, JoinGameRequest joinRequest, SendParameters sendParameters, ProcessJoinParams prms, HivePeer peer) { return this.JoinSendResponseAndEvents(peer, joinRequest, sendParameters, actorNr, prms); }
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; }
public abstract void OnOperationRequest(OperationRequest operationRequest, Photon.SocketServer.SendParameters sendParameters, ClientPeer peer);