Пример #1
0
        /// <summary>
        ///   Sends a <see cref = "JoinEvent" /> to all <see cref = "Actor" />s.
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <param name = "joinRequest">
        ///   The join request.
        /// </param>
        protected virtual void PublishJoinEvent(LitePeer peer, JoinRequest joinRequest)
        {
            Actor actor = this.GetActorByPeer(peer);
            if (actor == null)
            {
                return;
            }

            // generate a join event and publish to all actors in the room
            var joinEvent = new JoinEvent(actor.ActorNr, this.Actors.GetActorNumbers().ToArray());

            if (joinRequest.BroadcastActorProperties)
            {
                joinEvent.ActorProperties = joinRequest.ActorProperties;
            }

            this.PublishEvent(joinEvent, this.Actors, new SendParameters());
        }
Пример #2
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;
                            }

                            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);
            }
        }
Пример #3
0
        /// <summary>
        ///   Handles the <see cref = "JoinRequest" />: Joins a peer to a room and calls <see cref = "PublishJoinEvent" />.
        ///   Before a JoinOperation reaches this point (inside a room), the <see cref = "LitePeer" /> made 
        ///   sure that it is removed from the previous Room (if there was any).
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <param name = "joinRequest">
        ///   The join operation.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        /// <returns>
        ///   The newly created (joined) actor or null if the peer already joined.
        /// </returns>
        protected virtual Actor HandleJoinOperation(LitePeer peer, JoinRequest joinRequest, SendParameters sendParameters)
        {
            if (this.IsDisposed)
            {
                // join arrived after being disposed - repeat join operation
                if (Log.IsWarnEnabled)
                {
                    Log.WarnFormat("Join operation on disposed game. GameName={0}", this.Name);
                }

                return null;
            }

            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("Join operation from IP: {0} to port: {1}", peer.RemoteIP, peer.LocalPort);
            }

            // create an new actor
            Actor actor;
            if (this.TryAddPeerToGame(peer, out actor) == false)
            {
                peer.SendOperationResponse(
                    new OperationResponse
                        {
                            OperationCode = joinRequest.OperationRequest.OperationCode,
                            ReturnCode = -1,
                            DebugMessage = "Peer already joined the specified game."
                        },
                    sendParameters);
                return null;
            }

            // set game properties for join from the first actor
            if (this.Actors.Count == 1)
            {
                this.DeleteCacheOnLeave = joinRequest.DeleteCacheOnLeave;

                if (joinRequest.GameProperties != null)
                {
                    this.Properties.SetProperties(joinRequest.GameProperties);
                }
            }

            // set custom actor properties if defined
            if (joinRequest.ActorProperties != null)
            {
                actor.Properties.SetProperties(joinRequest.ActorProperties);
            }

            // set operation return values and publish the response
            var joinResponse = new JoinResponse { ActorNr = actor.ActorNr };

            if (this.Properties.Count > 0)
            {
                joinResponse.CurrentGameProperties = this.Properties.GetProperties();
            }

            foreach (Actor t in this.Actors)
            {
                if (t.ActorNr != actor.ActorNr && t.Properties.Count > 0)
                {
                    if (joinResponse.CurrentActorProperties == null)
                    {
                        joinResponse.CurrentActorProperties = new Hashtable();
                    }

                    Hashtable actorProperties = t.Properties.GetProperties();
                    joinResponse.CurrentActorProperties.Add(t.ActorNr, actorProperties);
                }
            }

            peer.SendOperationResponse(new OperationResponse(joinRequest.OperationRequest.OperationCode, joinResponse), sendParameters);

            // publish join event
            this.PublishJoinEvent(peer, joinRequest);

            this.PublishEventCache(peer);

            return actor;
        }
Пример #4
0
 /// <summary>
 ///   Called by <see cref = "HandleJoinOperation" /> to get a room reference for a join operations.
 ///   This method can be overloaded by inheritors to provide custom room references.
 /// </summary>
 /// <param name = "joinRequest">The join request.</param>
 /// <returns>An <see cref = "Caching.RoomReference" /> instance.</returns>
 protected virtual RoomReference GetRoomReference(JoinRequest joinRequest)
 {
     return LiteGameCache.Instance.GetRoomReference(joinRequest.GameId, this);
 }
Пример #5
0
        /// <summary>
        ///   Handles the <see cref = "JoinRequest" /> to enter a <see cref = "LiteGame" />.
        ///   This method removes the peer from any previously joined room, finds the room intended for join
        ///   and enqueues the operation for it to handle.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request to handle.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected virtual void HandleJoinOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            // create join operation
            var joinRequest = new JoinRequest(this.Protocol, operationRequest);
            if (this.ValidateOperation(joinRequest, sendParameters) == false)
            {
                return;
            }

            // remove peer from current game
            this.RemovePeerFromCurrentRoom();

            // get a game reference from the game cache
            // the game will be created by the cache if it does not exists already
            RoomReference gameReference = this.GetRoomReference(joinRequest);

            // save the game reference in the peers state
            this.RoomReference = gameReference;

            // finally enqueue the operation into game queue
            gameReference.Room.EnqueueOperation(this, operationRequest, sendParameters);
        }
Пример #6
0
        /// <summary>
        ///   Updates the lobby when an <see cref = "Actor" /> joins.
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <param name = "joinRequest">
        ///   The join operation.
        /// </param>
        /// <param name = "sendParamters">
        ///   The send Paramters.
        /// </param>
        /// <returns>
        ///   The newly created (joined) <see cref = "Actor" />.
        /// </returns>
        protected override Actor HandleJoinOperation(LitePeer peer, JoinRequest joinRequest, SendParameters sendParamters)
        {
            Actor actor = base.HandleJoinOperation(peer, joinRequest, sendParamters);
            if (actor != null)
            {
                this.UpdateLobby();
            }

            return actor;
        }
Пример #7
0
 protected override RoomReference GetRoomReference(JoinRequest joinRequest)
 {
     return MyGameCache.Instance.GetRoomReference(joinRequest.GameId, this);
 }
Пример #8
0
 protected override RoomReference GetRoomReference(JoinRequest joinRequest)
 {
     throw new NotSupportedException("Use TryGetRoomReference or TryCreateRoomReference instead.");
 }
Пример #9
0
        protected override void ExecuteOperation(LitePeer peer, OperationRequest operationRequest, SendParameters sendParameters)
        {
            try
            {
                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("Executing operation {0}", operationRequest.OperationCode);
                }

                switch (operationRequest.OperationCode)
                {
                    case (byte)OperationCode.CreateGame:
                        var createGameRequest = new JoinGameRequest(peer.Protocol, operationRequest);
                        if (peer.ValidateOperation(createGameRequest, sendParameters) == false)
                        {
                            return;
                        }

                        if (this.LogQueue.Log.IsDebugEnabled)
                        {

                            this.LogQueue.Add(
                                new LogEntry(
                                    "ExecuteOperation: " + (OperationCode)operationRequest.OperationCode,
                                    "Peer=" + peer.ConnectionId));
                        }
                        this.HandleCreateGameOperation(peer, createGameRequest, sendParameters);
                        break;

                    case (byte)OperationCode.JoinGame:
                        var joinGameRequest = new JoinRequest(peer.Protocol, operationRequest);
                        if (peer.ValidateOperation(joinGameRequest, sendParameters) == false)
                        {
                            return;
                        }

                        if (this.LogQueue.Log.IsDebugEnabled)
                        {

                            this.LogQueue.Add(
                                new LogEntry(
                                    "ExecuteOperation: " + (OperationCode)operationRequest.OperationCode,
                                    "Peer=" + peer.ConnectionId));
                        }
                        this.HandleJoinGameOperation(peer, joinGameRequest, sendParameters);
                        break;

                    // Lite operation code for join is not allowed in load balanced games.
                    case (byte)Lite.Operations.OperationCode.Join:
                        var response = new OperationResponse
                            {
                                OperationCode = operationRequest.OperationCode,
                                ReturnCode = (short)ErrorCode.OperationDenied,
                                DebugMessage = "Invalid operation code"
                            };
                        peer.SendOperationResponse(response, sendParameters);
                        break;

                    case (byte)OperationCode.DebugGame:
                        var debugGameRequest = new DebugGameRequest(peer.Protocol, operationRequest);
                        if (peer.ValidateOperation(debugGameRequest, sendParameters) == false)
                        {
                            return;
                        }

                        if (this.LogQueue.Log.IsDebugEnabled)
                        {

                            this.LogQueue.Add(
                                new LogEntry(
                                    "ExecuteOperation: " + (OperationCode)operationRequest.OperationCode,
                                    "Peer=" + peer.ConnectionId));
                        }

                        this.HandleDebugGameOperation(peer, debugGameRequest, sendParameters);
                        break;

                    // all other operation codes will be handled by the Lite game implementation
                    default:
                        base.ExecuteOperation(peer, operationRequest, sendParameters);
                        break;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
        }
Пример #10
0
        protected virtual Actor HandleJoinGameOperation(LitePeer peer, JoinRequest joinRequest, SendParameters sendParameters)
        {
            if (!this.ValidateGame(peer, joinRequest.OperationRequest, sendParameters)) 
            {
                return null; 
            }

            // special treatment for game and actor properties sent by AS3/Flash
            var protocol = peer.Protocol.ProtocolType;
            if (protocol == ProtocolType.Amf3V152 || protocol == ProtocolType.Json)
            {
                Utilities.ConvertAs3WellKnownPropertyKeys(joinRequest.GameProperties, joinRequest.ActorProperties);  
            }

            var gamePeer = (GameClientPeer)peer;
            Actor actor = this.HandleJoinOperation(peer, joinRequest, sendParameters);

            if (actor == null)
            {
                return null;
            }

            // update game state at master server            
            var peerId = gamePeer.PeerId ?? string.Empty;
            this.UpdateGameStateOnMaster(null, null, null, null, joinRequest.GameProperties, peerId);

            return actor;            
        }
Пример #11
0
        protected virtual Actor HandleJoinGameOperation(LitePeer peer, JoinRequest joinRequest, SendParameters sendParameters)
        {
            if (!this.ValidateGame(peer, joinRequest.OperationRequest, sendParameters))
            {
                return null;
            }

            var gamePeer = (GameClientPeer)peer;

            var baseRequest = new JoinRequest(peer.Protocol, joinRequest.OperationRequest);
            Actor actor = this.HandleJoinOperation(peer, baseRequest, sendParameters);

            if (actor == null)
            {
                return null;
            }

            // update game state at master server
            var peerId = gamePeer.PeerId ?? string.Empty;
            this.UpdateGameStateOnMaster(joinRequest.GameProperties, peerId, null, false);

            return actor;
        }
Пример #12
0
        protected virtual Actor HandleCreateGameOperation(LitePeer peer, JoinRequest createRequest, SendParameters sendParameters)
        {
            if (!this.ValidateGame(peer, createRequest.OperationRequest, sendParameters))
            {
                return null;
            }

            var gamePeer = (GameClientPeer)peer;

            byte? newMaxPlayer = null;
            bool? newIsOpen = null;
            bool? newIsVisible = null;
            object[] newLobbyProperties = null;

            // try to parse build in properties for the first actor (creator of the game)
            if (this.Actors.Count == 0)
            {
                if (createRequest.GameProperties != null && createRequest.GameProperties.Count > 0)
                {
                    if (!TryParseDefaultProperties(peer, createRequest, createRequest.GameProperties, sendParameters, out newMaxPlayer, out newIsOpen, out newIsVisible, out newLobbyProperties))
                    {
                        return null;
                    }
                }
            }

            var baseRequest = new JoinRequest(peer.Protocol, createRequest.OperationRequest);
            Actor actor = this.HandleJoinOperation(peer, baseRequest, sendParameters);

            if (actor == null)
            {
                return null;
            }

            // set default properties
            if (newMaxPlayer.HasValue && newMaxPlayer.Value != this.maxPlayers)
            {
                this.maxPlayers = newMaxPlayer.Value;
            }

            if (newIsOpen.HasValue && newIsOpen.Value != this.isOpen)
            {
                this.isOpen = newIsOpen.Value;
            }

            if (newIsVisible.HasValue && newIsVisible.Value != this.isVisible)
            {
                this.isVisible = newIsVisible.Value;
            }

            if (newLobbyProperties != null)
            {
                this.lobbyProperties = new HashSet<object>(newLobbyProperties);
            }

            Hashtable gameProperties;
            if (this.lobbyProperties == null)
            {
                // if no filter is set for properties which should be listet in the lobby
                // all properties are send
                gameProperties = this.Properties.GetProperties();
            }
            else
            {
                // filter for game properties is set, only properties in the specified list
                // will be reported to the lobby
                gameProperties = new Hashtable();

                // build in properties are always sent to the master server after creating a new game
                gameProperties.Add((byte)GameParameter.MaxPlayer, this.maxPlayers);
                gameProperties.Add((byte)GameParameter.IsVisible, this.isVisible);
                gameProperties.Add((byte)GameParameter.IsOpen, this.isOpen);
                gameProperties.Add((byte)GameParameter.Properties, newLobbyProperties);

                foreach (var key in this.lobbyProperties)
                {
                    var prop = this.Properties.GetProperty(key);
                    if (prop != null)
                    {
                        gameProperties[key] = prop.Value;
                    }
                }
            }

            // update game state at master server
            var peerId = gamePeer.PeerId ?? string.Empty;
            this.UpdateGameStateOnMaster(gameProperties, peerId, null, false);

            return actor;
        }