/// <summary> /// Enqueues RaiseEvent 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 HandleRaiseEventOperation(OperationRequest operationRequest, SendParameters sendParameters) { if (this.joinStage < JoinStages.PublishingEvents) { this.OnWrongOperationStage(operationRequest, sendParameters); return; } var raiseEventOperation = new RaiseEventRequest(this.Protocol, operationRequest); if (this.ValidateOperation(raiseEventOperation, 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, raiseEventOperation, sendParameters); return; } if (log.IsDebugEnabled) { log.DebugFormat("Received RaiseEvent operation on peer without a game: p:{0}", this); } }
public void RemoveEventsFromCache(RaiseEventRequest raiseEventRequest) { foreach (var slice in this.eventCache.Values) { var removedCount = slice.RemoveEvents(raiseEventRequest); this.gameAppCounters.EventCacheTotalEventsDecrementBy(removedCount); } }
public int RemoveEvents(RaiseEventRequest raiseEventRequest) { var removedCount = 0; if (raiseEventRequest.EvCode == 0 && raiseEventRequest.Actors == null && raiseEventRequest.Data == null) { removedCount = this.cachedRoomEvents.Count; this.cachedRoomEvents.Clear(); return(removedCount); } for (var i = this.cachedRoomEvents.Count - 1; i >= 0; i--) { var cachedEvent = this.cachedRoomEvents[i]; if (raiseEventRequest.EvCode != 0 && cachedEvent.Code != raiseEventRequest.EvCode) { continue; } if (raiseEventRequest.Actors != null && raiseEventRequest.Actors.Length > 0) { bool actorMatch = false; for (int a = 0; a < raiseEventRequest.Actors.Length; a++) { if (cachedEvent.ActorNr != raiseEventRequest.Actors[a]) { continue; } actorMatch = true; break; } if (actorMatch == false) { continue; } } if (raiseEventRequest.Data == null) { ++removedCount; this.cachedRoomEvents.RemoveAt(i); continue; } if (Compare(raiseEventRequest.Data as Hashtable, cachedEvent.Data as Hashtable)) { ++removedCount; this.cachedRoomEvents.RemoveAt(i); } } return(removedCount); }
/// <summary> /// Helper method of <see cref = "HandleRaiseEventOperation" />. /// Stores an event for new actors. /// </summary> /// <param name = "actor"> /// The actor. /// </param> /// <param name = "raiseEventRequest"> /// The raise event request. /// </param> /// <param name="msg"> /// Contains an error message if the method returns false. /// </param> /// <returns> /// True if <see cref = "RaiseEventRequest.Cache" /> is valid. /// </returns> protected bool UpdateEventCache(Actor actor, RaiseEventRequest raiseEventRequest, out string msg) { msg = null; CustomEvent customEvent; switch (raiseEventRequest.Cache) { case (byte)CacheOperation.DoNotCache: return(true); case (byte)CacheOperation.AddToRoomCache: customEvent = new CustomEvent(actor.ActorNr, raiseEventRequest.EvCode, raiseEventRequest.Data); this.eventCache.AddEvent(customEvent); return(true); case (byte)CacheOperation.AddToRoomCacheGlobal: customEvent = new CustomEvent(0, raiseEventRequest.EvCode, raiseEventRequest.Data); this.eventCache.AddEvent(customEvent); return(true); } // cache operations for the actor event cache currently only working with hashtable data Hashtable eventData; if (raiseEventRequest.Data == null || raiseEventRequest.Data is Hashtable) { eventData = (Hashtable)raiseEventRequest.Data; } else { msg = string.Format("Cache operation '{0}' requires a Hashtable as event data.", raiseEventRequest.Cache); return(false); } switch (raiseEventRequest.Cache) { case (byte)CacheOperation.MergeCache: this.actorEventCache.MergeEvent(actor.ActorNr, raiseEventRequest.EvCode, eventData); return(true); case (byte)CacheOperation.RemoveCache: this.actorEventCache.RemoveEvent(actor.ActorNr, raiseEventRequest.EvCode); return(true); case (byte)CacheOperation.ReplaceCache: this.actorEventCache.ReplaceEvent(actor.ActorNr, raiseEventRequest.EvCode, eventData); return(true); default: msg = string.Format("Unknown cache operation '{0}'.", raiseEventRequest.Cache); return(false); } }
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); }
private void SendEvents(object state) { var rnd = new Random(); while (!Console.KeyAvailable) { var data = new Hashtable(); var operation = new RaiseEventRequest { EvCode = 100, Data = data }; var request = new OperationRequest((byte)Lite.Operations.OperationCode.RaiseEvent, operation); //Console.Write('s'); this.gameServerClient.SendOperationRequest(request, new SendParameters()); Thread.Sleep(rnd.Next(500, 1000)); } }
public void RemoveEvents(RaiseEventRequest raiseEventRequest) { for (int i = this.cachedRoomEvents.Count - 1; i >= 0; i--) { var cachedEvent = this.cachedRoomEvents[i]; if (raiseEventRequest.EvCode != 0 && cachedEvent.Code != raiseEventRequest.EvCode) { continue; } if (raiseEventRequest.Actors != null && raiseEventRequest.Actors.Length > 0) { bool actorMatch = false; for (int a = 0; a < raiseEventRequest.Actors.Length; a++) { if (cachedEvent.ActorNr != raiseEventRequest.Actors[a]) { continue; } actorMatch = true; break; } if (actorMatch == false) { continue; } } if (raiseEventRequest.Data == null) { this.cachedRoomEvents.RemoveAt(i); continue; } if (Compare(raiseEventRequest.Data, cachedEvent.Data)) { this.cachedRoomEvents.RemoveAt(i); } } }
public void Service() { if (connectionState == TestClientConnectionState.Disconnected) { Rejoin(); return; } if (connectionState != TestClientConnectionState.InGame) { return; } if ((DateTime.UtcNow - lastEvent).Milliseconds < interval) { return; } lastEvent = DateTime.UtcNow; var data = new Hashtable { { 0, watch.ElapsedMilliseconds } }; var operation = new RaiseEventRequest { EvCode = 100, Data = data, ReceiverGroup = 1 }; var request = new OperationRequest((byte)Photon.Hive.Operations.OperationCode.RaiseEvent, operation); this.gameServerClient.SendOperationRequest(request, new SendParameters()); // if (log.IsDebugEnabled) // { // log.DebugFormat("TestClient({0}): sent event", userId); // } }
protected virtual bool ProcessRaiseEvent(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters, Actor actor) { return this.RaiseEventOperationHandler(peer, raiseEventRequest, sendParameters, actor); }
/// <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 override 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; } if (raiseEventRequest.HttpForward && this.HttpForwardedOperationsLimit > 0 && this.httpForwardedRequests.Increment(1) > this.HttpForwardedOperationsLimit) { this.SendErrorResponse(peer, raiseEventRequest.OperationCode, ErrorCode.HttpLimitReached, HiveErrorMessages.HttpForwardedOperationsLimitReached, sendParameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' RaiseEvent denied. msg:{2} -- peer:{3}", this.Name, peer.UserId, HiveErrorMessages.HttpForwardedOperationsLimitReached, peer); } return; } RequestHandler handler = () => { try { return this.ProcessRaiseEvent(peer, raiseEventRequest, sendParameters, actor); } catch (Exception e) { this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e, raiseEventRequest); Log.Error(raiseEventRequest.DumpRequest()); Log.Error(this.ActorsManager.DumpActors()); Log.ErrorFormat("Master Client id = {0}, SuprressRoomEvent:{1}", this.MasterClientId, this.SuppressRoomEvents); Log.Error(e); } return false; }; var info = new RaiseEventCallInfo(this.PendingPluginContinue, this.callEnv) { ActorNr = actor.ActorNr, Request = raiseEventRequest, UserId = peer.UserId, Nickname = actor.Nickname, Handler = handler, Peer = peer, SendParams = sendParameters, }; try { this.Plugin.OnRaiseEvent(info); } catch (Exception e) { this.Plugin.ReportError(Photon.Hive.Plugin.ErrorCodes.UnhandledException, e); } }
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; }
private void SendEvents(object state) { var rnd = new Random(); while (!Console.KeyAvailable) { var data = new Hashtable(); var operation = new RaiseEventRequest { EvCode = 100, Data = data }; var request = new OperationRequest((byte)Photon.Hive.Operations.OperationCode.RaiseEvent, operation); //Console.Write('s'); this.gameServerClient.SendOperationRequest(request, new SendParameters()); Thread.Sleep(rnd.Next(500, 1000)); } }
/// <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(LitePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters) { // get the actor who send the operation request Actor actor = this.GetActorByPeer(peer); if (actor == null) { return; } var customEvent = new CustomEvent(actor.ActorNr, raiseEventRequest.EvCode, raiseEventRequest.Data); if (raiseEventRequest.Cache == (byte)CacheOperation.RemoveFromRoomCache) { this.roomEventCache.RemoveEvents(raiseEventRequest); var response = new OperationResponse(raiseEventRequest.OperationRequest.OperationCode) { ReturnCode = 0 }; peer.SendOperationResponse(response, sendParameters); return; } // publish the custom event IEnumerable <Actor> recipients; if (raiseEventRequest.Actors != null && raiseEventRequest.Actors.Length > 0) { recipients = this.Actors.GetActorsByNumbers(raiseEventRequest.Actors); sendParameters.Flush = raiseEventRequest.Flush; this.PublishEvent(customEvent, recipients, sendParameters); return; } switch (raiseEventRequest.ReceiverGroup) { case (byte)ReceiverGroup.All: { recipients = this.Actors; if (raiseEventRequest.Cache == (byte)CacheOperation.AddToRoomCache) { customEvent.Cache = raiseEventRequest.Cache; this.roomEventCache.AddEvent(customEvent); } else if (raiseEventRequest.Cache == (byte)CacheOperation.AddToRoomCacheGlobal) { customEvent.ActorNr = 0; customEvent.Cache = raiseEventRequest.Cache; this.roomEventCache.AddEvent(customEvent); } else if (raiseEventRequest.Cache != (byte)CacheOperation.DoNotCache) { if (!this.UpdateEventCache(actor, raiseEventRequest, raiseEventRequest.EvCode)) { peer.SendOperationResponse( new OperationResponse { OperationCode = raiseEventRequest.OperationRequest.OperationCode, ReturnCode = -1, DebugMessage = "Invalid cache operation " + raiseEventRequest.Cache }, sendParameters); return; } customEvent.Cache = raiseEventRequest.Cache; } break; } case (byte)ReceiverGroup.Others: { recipients = this.Actors.GetExcludedList(actor); if (raiseEventRequest.Cache == (byte)CacheOperation.AddToRoomCache) { customEvent.Cache = raiseEventRequest.Cache; this.roomEventCache.AddEvent(customEvent); } else if (raiseEventRequest.Cache == (byte)CacheOperation.AddToRoomCacheGlobal) { customEvent.ActorNr = 0; customEvent.Cache = raiseEventRequest.Cache; this.roomEventCache.AddEvent(customEvent); } else if (raiseEventRequest.Cache != (byte)CacheOperation.DoNotCache) { if (!this.UpdateEventCache(actor, raiseEventRequest, raiseEventRequest.EvCode)) { peer.SendOperationResponse( new OperationResponse { OperationCode = raiseEventRequest.OperationRequest.OperationCode, ReturnCode = -1, DebugMessage = "Invalid cache operation " + raiseEventRequest.Cache }, sendParameters); return; } customEvent.Cache = raiseEventRequest.Cache; } break; } case (byte)ReceiverGroup.MasterClient: { recipients = new[] { this.Actors[0] }; break; } default: { peer.SendOperationResponse( new OperationResponse { OperationCode = raiseEventRequest.OperationRequest.OperationCode, ReturnCode = -1, DebugMessage = "Invalid ReceiverGroup " + raiseEventRequest.ReceiverGroup }, sendParameters); return; } } this.PublishEvent(customEvent, recipients, sendParameters); }
public void RemoveEventsFromCache(RaiseEventRequest raiseEventRequest) { this.RemoveEventsFromCache(raiseEventRequest.EvCode, raiseEventRequest.Actors, raiseEventRequest.Data); }
/// <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 bool RaiseEventOperationHandler(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters, Actor actor) { sendParameters.Flush = raiseEventRequest.Flush; if (raiseEventRequest.IsCacheSliceIndexOperation) { var msg = string.Empty; if (!this.UpdateCacheSlice(actor.Peer, raiseEventRequest.Cache, raiseEventRequest.CacheSliceIndex, ref msg)) { this.SendErrorResponse(peer, raiseEventRequest.OperationCode, ErrorCode.OperationInvalid, msg, sendParameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' userId '{1}' failed to update Cache Slice. msg:{2} -- peer:{3}", this.Name, peer.UserId, msg, peer); } if (Log.IsWarnEnabled) { Log.Warn(msg); } } return false; } if (raiseEventRequest.IsCacheOpRemoveFromCache) { this.EventCache.RemoveEventsFromCache(raiseEventRequest); var response = new OperationResponse(raiseEventRequest.OperationRequest.OperationCode); peer.SendOperationResponse(response, sendParameters); return false; } if (raiseEventRequest.IsCacheOpRemoveFromCacheForActorsLeft) { var currentActorNumbers = this.ActorsManager.ActorsGetActorNumbers(); this.EventCache.RemoveEventsForActorsNotInList(currentActorNumbers); var response = new OperationResponse(raiseEventRequest.OperationRequest.OperationCode); peer.SendOperationResponse(response, sendParameters); return false; } // publish the custom event var customEvent = new CustomEvent(actor.ActorNr, raiseEventRequest.EvCode, raiseEventRequest.Data); var updateEventCache = false; IEnumerable<Actor> recipients; if (raiseEventRequest.Actors != null && raiseEventRequest.Actors.Length > 0) { recipients = this.ActorsManager.ActorsGetActorsByNumbers(raiseEventRequest.Actors); } else if (raiseEventRequest.Group != 0) { var group = this.GroupManager.GetActorGroup(raiseEventRequest.Group); if (group != null) { recipients = group.GetExcludedList(actor); } else { // group does not exists yet because no one joined it yet. // it's not an error to sent events to empty groups so no error response will be sent return false; } } else { switch ((ReceiverGroup)raiseEventRequest.ReceiverGroup) { case ReceiverGroup.All: recipients = this.Actors; updateEventCache = true; break; case ReceiverGroup.Others: recipients = this.ActorsManager.ActorsGetExcludedList(actor); updateEventCache = true; break; case ReceiverGroup.MasterClient: recipients = new[] { this.ActorsManager.ActorsGetActorByNumber(this.MasterClientId) }; break; default: this.SendErrorResponse(peer, raiseEventRequest.OperationCode, ErrorCode.OperationInvalid, HiveErrorMessages.InvalidReceiverGroup + raiseEventRequest.ReceiverGroup, sendParameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' user '{1}' sent wrong receiver group. msg:{2} -- peer:{3}", this.Name, peer.UserId, HiveErrorMessages.InvalidReceiverGroup + raiseEventRequest.ReceiverGroup, peer); } return false; } } if (updateEventCache && raiseEventRequest.Cache != (byte)CacheOperation.DoNotCache) { string msg; if (!this.UpdateEventCache(actor, raiseEventRequest, out msg)) { this.SendErrorResponse(peer, raiseEventRequest.OperationCode, ErrorCode.OperationInvalid, msg, sendParameters); if (Log.IsWarnEnabled) { Log.WarnFormat("Game '{0}' user '{1}' failed to update EventCache. msg:{2} -- peer:{3}", this.Name, peer.UserId, msg, peer); } return false; } } this.PublishEvent(customEvent, recipients, sendParameters); return true; }
/// <summary> /// Helper method of <see cref = "HandleRaiseEventOperation" />. /// Stores an event for new actors. /// </summary> /// <param name = "actor"> /// The actor. /// </param> /// <param name = "raiseEventRequest"> /// The raise event request. /// </param> /// <param name = "eventCode"> /// The event code. /// </param> /// <returns> /// True if <see cref = "RaiseEventRequest.Cache" /> is valid. /// </returns> protected bool UpdateEventCache(Actor actor, RaiseEventRequest raiseEventRequest, byte eventCode) { switch (raiseEventRequest.Cache) { case (byte)CacheOperation.MergeCache: { EventCache eventCache; if (!this.cachedEvents.TryGetValue(actor.ActorNr, out eventCache)) { eventCache = new EventCache(); this.cachedEvents.Add(actor.ActorNr, eventCache); } Hashtable @event; if (eventCache.TryGetValue(eventCode, out @event)) { // null events are removed if (raiseEventRequest.Data == null) { eventCache.Remove(eventCode); } else { // merge or delete foreach (DictionaryEntry pair in raiseEventRequest.Data) { // null values are removed if (pair.Value == null) { @event.Remove(pair.Key); } else { @event[pair.Key] = pair.Value; } } } } else if (raiseEventRequest.Data != null) { // new @event = raiseEventRequest.Data; eventCache.Add(eventCode, @event); } return(true); } case (byte)CacheOperation.RemoveCache: { EventCache eventCache; if (!this.cachedEvents.TryGetValue(actor.ActorNr, out eventCache)) { return(true); } eventCache.Remove(eventCode); return(true); } case (byte)CacheOperation.ReplaceCache: { EventCache eventCache; if (!this.cachedEvents.TryGetValue(actor.ActorNr, out eventCache)) { eventCache = new EventCache(); this.cachedEvents.Add(actor.ActorNr, eventCache); } eventCache.Remove(eventCode); if (raiseEventRequest.Data != null) { Hashtable @event = raiseEventRequest.Data; eventCache.Add(eventCode, @event); } return(true); } default: { return(false); } } }
/// <summary> /// Helper method of <see cref = "HandleRaiseEventOperation" />. /// Stores an event for new actors. /// </summary> /// <param name = "actor"> /// The actor. /// </param> /// <param name = "raiseEventRequest"> /// The raise event request. /// </param> /// <param name="msg"> /// Contains an error message if the method returns false. /// </param> /// <returns> /// True if <see cref = "RaiseEventRequest.Cache" /> is valid. /// </returns> protected bool UpdateEventCache(Actor actor, RaiseEventRequest raiseEventRequest, out string msg) { return this.UpdateEventCache(actor, raiseEventRequest.EvCode, raiseEventRequest.Data, raiseEventRequest.Cache, out msg); }
/// <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(LitePeer 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.Join: { var joinRequest = new JoinRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(joinRequest, sendParameters) == false) { return; } if (this.LogQueue.Log.IsDebugEnabled) { this.LogQueue.Add( new LogEntry( "ExecuteOperation: " + (OperationCode)operationRequest.OperationCode, "Peer=" + peer.ConnectionId)); } joinRequest.OnStart(); this.HandleJoinOperation(peer, joinRequest, sendParameters); joinRequest.OnComplete(); break; } case OperationCode.Leave: { var leaveOperation = new LeaveRequest(peer.Protocol, operationRequest); if (peer.ValidateOperation(leaveOperation, sendParameters) == false) { return; } if (this.LogQueue.Log.IsDebugEnabled) { this.LogQueue.Add( new LogEntry( "ExecuteOperation: " + (OperationCode)operationRequest.OperationCode, "Peer=" + peer.ConnectionId)); } leaveOperation.OnStart(); this.HandleLeaveOperation(peer, leaveOperation, sendParameters); 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 { OperationCode = 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: { string message = string.Format("Unknown operation code {0}", (OperationCode)operationRequest.OperationCode); peer.SendOperationResponse( new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = -1, DebugMessage = message }, sendParameters); if (Log.IsWarnEnabled) { Log.Warn(message); } } break; } } catch (Exception ex) { Log.Error(ex); } }
/// <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); }
/// <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(LitePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters) { // get the actor who send the operation request Actor actor = this.GetActorByPeer(peer); if (actor == null) { return; } sendParameters.Flush = raiseEventRequest.Flush; if (raiseEventRequest.Cache == (byte)CacheOperation.RemoveFromRoomCache) { this.eventCache.RemoveEvents(raiseEventRequest); var response = new OperationResponse(raiseEventRequest.OperationRequest.OperationCode) { ReturnCode = 0 }; peer.SendOperationResponse(response, sendParameters); return; } if (raiseEventRequest.Cache == (byte)CacheOperation.RemoveFromCacheForActorsLeft) { var currentActorNumbers = this.Actors.GetActorNumbers(); this.eventCache.RemoveEventsForActorsNotInList(currentActorNumbers); var response = new OperationResponse(raiseEventRequest.OperationRequest.OperationCode) { ReturnCode = 0 }; peer.SendOperationResponse(response, sendParameters); return; } // publish the custom event var customEvent = new CustomEvent(actor.ActorNr, raiseEventRequest.EvCode, raiseEventRequest.Data); bool updateEventCache = false; IEnumerable <Actor> recipients; if (raiseEventRequest.Actors != null && raiseEventRequest.Actors.Length > 0) { recipients = this.Actors.GetActorsByNumbers(raiseEventRequest.Actors); } else if (raiseEventRequest.Group != 0) { ActorGroup group; if (this.actorGroups.TryGetValue(raiseEventRequest.Group, out group)) { recipients = group.GetExcludedList(actor); } else { return; } } else { switch ((ReceiverGroup)raiseEventRequest.ReceiverGroup) { case ReceiverGroup.All: recipients = this.Actors; updateEventCache = true; break; case ReceiverGroup.Others: recipients = this.Actors.GetExcludedList(actor); updateEventCache = true; break; case ReceiverGroup.MasterClient: recipients = new[] { this.Actors[0] }; break; default: peer.SendOperationResponse( new OperationResponse { OperationCode = raiseEventRequest.OperationRequest.OperationCode, ReturnCode = -1, DebugMessage = "Invalid ReceiverGroup " + raiseEventRequest.ReceiverGroup }, sendParameters); return; } } if (updateEventCache && raiseEventRequest.Cache != (byte)CacheOperation.DoNotCache) { string msg; if (!this.UpdateEventCache(actor, raiseEventRequest, out msg)) { peer.SendOperationResponse( new OperationResponse { OperationCode = raiseEventRequest.OperationRequest.OperationCode, ReturnCode = -1, DebugMessage = msg }, sendParameters); return; } } this.PublishEvent(customEvent, recipients, sendParameters); }