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(2000, 5000)); } }
/// <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> /// <returns> /// True if <see cref = "RaiseEventRequest.Cache" /> is valid. /// </returns> protected bool UpdateEventCache(Actor actor, RaiseEventRequest raiseEventRequest) { CustomEvent customEvent; switch (raiseEventRequest.Cache) { case (byte)CacheOperation.AddToRoomCache: customEvent = new CustomEvent(actor.ActorNr, raiseEventRequest.EvCode, raiseEventRequest.Data) { Cache = raiseEventRequest.Cache }; this.eventCache.AddEvent(customEvent); return true; case (byte)CacheOperation.AddToRoomCacheGlobal: customEvent = new CustomEvent(0, raiseEventRequest.EvCode, raiseEventRequest.Data) { Cache = raiseEventRequest.Cache }; this.eventCache.AddEvent(customEvent); return true; case (byte)CacheOperation.MergeCache: { EventCache eventCache; if (!this.eventCacheOld.TryGetValue(actor.ActorNr, out eventCache)) { eventCache = new EventCache(); this.eventCacheOld.Add(actor.ActorNr, eventCache); } Hashtable @event; if (eventCache.TryGetValue(raiseEventRequest.EvCode, out @event)) { // null events are removed if (raiseEventRequest.Data == null) { eventCache.Remove(raiseEventRequest.EvCode); } 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(raiseEventRequest.EvCode, @event); } return true; } case (byte)CacheOperation.RemoveCache: { EventCache eventCache; if (!this.eventCacheOld.TryGetValue(actor.ActorNr, out eventCache)) { return true; } eventCache.Remove(raiseEventRequest.EvCode); return true; } case (byte)CacheOperation.ReplaceCache: { EventCache eventCache; if (!this.eventCacheOld.TryGetValue(actor.ActorNr, out eventCache)) { eventCache = new EventCache(); this.eventCacheOld.Add(actor.ActorNr, eventCache); } eventCache.Remove(raiseEventRequest.EvCode); if (raiseEventRequest.Data != null) { Hashtable @event = raiseEventRequest.Data; eventCache.Add(raiseEventRequest.EvCode, @event); } return true; } default: { return false; } } }
/// <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) { Cache = raiseEventRequest.Cache }; bool updateEventCache = false; IEnumerable<Actor> recipients; if (raiseEventRequest.Actors != null && raiseEventRequest.Actors.Length > 0) { recipients = this.Actors.GetActorsByNumbers(raiseEventRequest.Actors); } 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) { if (!this.UpdateEventCache(actor, raiseEventRequest)) { peer.SendOperationResponse( new OperationResponse { OperationCode = raiseEventRequest.OperationRequest.OperationCode, ReturnCode = -1, DebugMessage = "Invalid cache operation " + raiseEventRequest.Cache }, sendParameters); return; } } this.PublishEvent(customEvent, recipients, 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(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; } 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; } 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; } 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(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); }
/// <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; } }