/// <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);
            }
        }
Пример #2
0
 public void RemoveEventsFromCache(RaiseEventRequest raiseEventRequest)
 {
     foreach (var slice in this.eventCache.Values)
     {
         var removedCount = slice.RemoveEvents(raiseEventRequest);
         this.gameAppCounters.EventCacheTotalEventsDecrementBy(removedCount);
     }
 }
Пример #3
0
        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);
        }
Пример #4
0
        /// <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);
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        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));
            }
        }
Пример #7
0
        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);
                }
            }
        }
Пример #8
0
        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);
//            }
        }
Пример #9
0
 protected virtual bool ProcessRaiseEvent(HivePeer peer, RaiseEventRequest raiseEventRequest, SendParameters sendParameters, Actor actor)
 {
     return this.RaiseEventOperationHandler(peer, raiseEventRequest, sendParameters, actor);
 }
Пример #10
0
        /// <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);
            }
        }
Пример #11
0
 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;
 }
Пример #12
0
        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));
            }
        }
Пример #13
0
        /// <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);
 }
Пример #15
0
        /// <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);
            }
        }
Пример #16
0
        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;
        }
Пример #17
0
        /// <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);
            }
            }
        }
Пример #18
0
 /// <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);
 }
Пример #19
0
        /// <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);
            }
        }
Пример #20
0
        /// <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);
        }
Пример #21
0
        /// <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);
        }