/// <summary>Creates a Room (representation) with given name and properties and the "listing options" as provided by parameters.</summary>
 /// <param name="roomName">Name of the room (can be null until it's actually created on server).</param>
 /// <param name="options">Room options.</param>
 protected internal Room(string roomName, RoomOptions options)
     : base(roomName, options.CustomRoomProperties)
 {
     // base sets name and (custom)properties. here we set "well known" properties
     this.isVisible = options.IsVisible;
     this.isOpen = options.IsOpen;
     this.maxPlayers = options.MaxPlayers;
     this.PropsListedInLobby = options.CustomRoomPropertiesForLobby;
     this.PlayerTTL = options.PlayerTtl;
     this.RoomTTL = options.EmptyRoomTtl;
 }
 /// <summary>Internal "factory" method to create a room-instance.</summary>
 protected internal virtual Room CreateRoom(string roomName, RoomOptions opt)
 {
     if (opt == null)
     {
         opt = new RoomOptions();
     }
     Room r = new Room(roomName, opt);
     return r;
 }
        /// <summary>
        /// Joins a room by roomName. If this client returns to the room, set the previously used Player.ID as actorNumber.
        /// </summary>
        /// <remarks>
        /// This method is useful when you are using a lobby to list rooms and know their names.
        /// A room's name has to be unique (per region and game version), so it does not matter which lobby it's in.
        ///
        /// If this client returns to the room, set the previously used Player.ID as actorNumber.
        /// When you are using Custom Authentication with unique user IDs, the server will use the userID
        /// to find the previously assigned actorNumber in the room.
        ///
        /// For turnbased games, this is especially useful as rooms can be continued after hours or days.
        /// To return to a room, set the actorNumber to anything but 0. It's best practice to use -1 with
        /// Custom Authentication and unique user accounts.
        ///
        /// If the room is full, closed or not existing, this will fail. Override this class and implement
        /// OnOperationResponse(OperationResponse operationResponse) to get the errors.
        ///
        /// OpJoinRoom can only be called while the client is connected to a Master Server.
        /// You should check LoadBalancingClient.Server and LoadBalancingClient.IsConnectedAndReady before calling this method.
        /// Alternatively, check the returned bool value.
        ///
        /// While the server is joining the game, the State will be ClientState.Joining.
        /// It's set immediately when this method sends the Operation.
        ///
        /// If successful, the LoadBalancingClient will get a Game Server Address and use it automatically
        /// to switch servers and join the room. When you're in the room, this client's State will become
        /// ClientState.Joined (both, for joining or creating it).
        /// Set a OnStateChangeAction method to check for states.
        ///
        /// When joining a room, this client's Player Custom Properties will be sent to the room.
        /// Use LocalPlayer.SetCustomProperties to set them, even while not yet in the room.
        /// Note that the player properties will be cached locally and sent to any next room you would join, too.
        ///
        /// It's usually better to use OpJoinOrCreateRoom for invitations.
        /// Then it does not matter if the room is already setup.
        /// </remarks>
        /// <param name="roomName">The name of the room to join. Must be existing already, open and non-full or can't be joined.</param>
        /// <param name="actorNumber">When returning to a room, use a non-0 value. For Turnbased games, set the previously assigned Player.ID or -1 when using Custom Authentication.</param>
        /// <returns>If the operation could be sent currently (requires connection to Master Server).</returns>
        public bool OpJoinRoom(string roomName, int actorNumber)
        {
            this.State = ClientState.Joining;
            this.lastJoinType = JoinType.JoinRoom;
            this.lastJoinActorNumber = actorNumber;
            this.createRoomOptions = new RoomOptions();
            this.CurrentRoom = CreateRoom(roomName, this.createRoomOptions);

            Hashtable playerPropsToSend = null;
            if (this.Server == ServerConnection.GameServer)
            {
                playerPropsToSend = this.LocalPlayer.AllProperties;
            }

            bool onGameServer = this.Server == ServerConnection.GameServer;
            return this.loadBalancingPeer.OpJoinRoom(roomName, playerPropsToSend, actorNumber, this.createRoomOptions, null, false, onGameServer);
        }
        /// <summary>
        /// Joins a specific room by name. If the room does not exist (yet), it will be created implicitly.
        /// </summary>
        /// <remarks>
        /// Unlike OpJoinRoom, this operation does not fail if the room does not exist.
        /// This can be useful when you send invitations to a room before actually creating it:
        /// Any invited player (whoever is first) can call this and on demand, the room gets created implicitly.
        ///
        /// If you set room properties in RoomOptions, they get ignored when the room is existing already.
        /// This avoids changing the room properties by late joining players. Only when the room gets created,
        /// the RoomOptions are set in this case.
        ///
        /// If this client returns to the room, set the previously used Player.ID as actorNumber.
        /// When you are using Custom Authentication with unique user IDs, the server will use the userID
        /// to find the previously assigned actorNumber in the room.
        ///
        /// For turnbased games, this is especially useful as rooms can be continued after hours or days.
        /// To return to a room, set the actorNumber to anything but 0. It's best practice to use -1 with
        /// Custom Authentication and unique user accounts.
        ///
        /// If the room is full or closed, this will fail. Override this class and implement
        /// OnOperationResponse(OperationResponse operationResponse) to get the errors.
        ///
        /// This method can only be called while the client is connected to a Master Server.
        /// You should check LoadBalancingClient.Server and LoadBalancingClient.IsConnectedAndReady before calling this method.
        /// Alternatively, check the returned bool value.
        ///
        /// While the server is joining the game, the State will be ClientState.Joining.
        /// It's set immediately when this method sends the Operation.
        ///
        /// If successful, the LoadBalancingClient will get a Game Server Address and use it automatically
        /// to switch servers and join the room. When you're in the room, this client's State will become
        /// ClientState.Joined (both, for joining or creating it).
        /// Set a OnStateChangeAction method to check for states.
        ///
        /// When entering the room, this client's Player Custom Properties will be sent to the room.
        /// Use LocalPlayer.SetCustomProperties to set them, even while not yet in the room.
        /// Note that the player properties will be cached locally and sent to any next room you would join, too.
        /// </remarks>
        /// <param name="roomName">The name of the room to join (might be created implicitly).</param>
        /// <param name="actorNumber">When returning to a room, use a non-0 value. For Turnbased games, set the previously assigned Player.ID or -1 when using Custom Authentication.</param>
        /// <param name="roomOptions">Contains the parameters and properties of the new room. See RoomOptions class for a description of each.</param>
        /// <param name="lobby">Typed lobby to be used if the roomname is not in use (and room gets created). If != null, it will also set CurrentLobby.</param>
        /// <returns>If the operation could be sent currently (requires connection to Master Server).</returns>
        public bool OpJoinOrCreateRoom(string roomName, int actorNumber, RoomOptions roomOptions, TypedLobby lobby)
        {
            if (roomOptions == null)
            {
                roomOptions = new RoomOptions();
            }
            this.State = ClientState.Joining;
            this.lastJoinType = JoinType.JoinOrCreateRoom;
            this.lastJoinActorNumber = actorNumber;
            this.createRoomOptions = roomOptions;
            this.CurrentRoom = CreateRoom(roomName, roomOptions);

            Hashtable playerPropsToSend = null;
            if (this.Server == ServerConnection.GameServer)
            {
                playerPropsToSend = this.LocalPlayer.AllProperties;
            }

            if (lobby != null) this.CurrentLobby = lobby;
            bool onGameServer = this.Server == ServerConnection.GameServer;
            return this.loadBalancingPeer.OpJoinRoom(roomName, playerPropsToSend, actorNumber, roomOptions, lobby, true, onGameServer);
        }
 public bool OpJoinOrCreateRoom(string roomName, int actorNumber, RoomOptions roomOptions)
 {
     return OpJoinOrCreateRoom(roomName, actorNumber, roomOptions, null);
 }
        /// <summary>
        /// Creates a new room on the server (or fails if the name is already in use).
        /// </summary>
        /// <remarks>
        /// If you don't want to create a unique room-name, pass null or "" as name and the server will assign a
        /// roomName (a GUID as string). Room names are unique.
        ///
        /// A room will be attached to the specified lobby. Use null as lobby to attach the
        /// room to the lobby you are now in. If you are in no lobby, the default lobby is used.
        ///
        /// Multiple lobbies can help separate players by map or skill or game type. Each room can only be found
        /// in one lobby (no matter if defined by name and type or as default).
        ///
        /// This method can only be called while the client is connected to a Master Server.
        /// You should check LoadBalancingClient.Server and LoadBalancingClient.IsConnectedAndReady before calling this method.
        /// Alternatively, check the returned bool value.
        ///
        /// Even when sent, the Operation will fail (on the server) if the roomName is in use.
        /// Override this class and implement  OnOperationResponse(OperationResponse operationResponse) to get the errors.
        ///
        ///
        /// While the server is creating the game, the State will be ClientState.Joining.
        /// The state Joining is used because the client is on the way to enter a room (no matter if joining or creating).
        /// It's set immediately when this method sends the Operation.
        ///
        /// If successful, the LoadBalancingClient will get a Game Server Address and use it automatically
        /// to switch servers and enter the room. When you're in the room, this client's State will become
        /// ClientState.Joined (both, for joining or creating it).
        /// Set a OnStateChangeAction method to check for states.
        ///
        /// When entering the room, this client's Player Custom Properties will be sent to the room.
        /// Use LocalPlayer.SetCustomProperties to set them, even while not yet in the room.
        /// Note that the player properties will be cached locally and sent to any next room you would join, too.
        /// </remarks>
        /// <param name="roomName">The name to create a room with. Must be unique and not in use or can't be created. If null, the server will assign a GUID as name.</param>
        /// <param name="roomOptions">Contains the parameters and properties of the new room. See RoomOptions class for a description of each.</param>
        /// <param name="lobby">The lobby (name and type) in which to create the room. Null uses the current lobby or the default lobby (if not in a lobby).</param>
        /// <returns>If the operation could be sent currently (requires connection to Master Server).</returns>
        public bool OpCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby lobby)
        {
            this.State = ClientState.Joining;
            this.lastJoinType = JoinType.CreateRoom;
            this.lastJoinActorNumber = 0;
            this.createRoomOptions = roomOptions;
            this.CurrentRoom = this.CreateRoom(roomName, roomOptions);

            Hashtable playerPropsToSend = null;
            if (this.Server == ServerConnection.GameServer)
            {
                playerPropsToSend = this.LocalPlayer.AllProperties;
            }

            this.CurrentLobby = lobby;
            bool onGameServer = this.Server == ServerConnection.GameServer;
            return this.loadBalancingPeer.OpCreateRoom(roomName, roomOptions, lobby, playerPropsToSend, onGameServer);
        }
        public bool OpCreateRoom(string roomName, bool isVisible, bool isOpen, byte maxPlayers, Hashtable customGameProperties, string[] propsListedInLobby, string lobbyName, LobbyType lobbyType, int playerTtl, int roomTtl)
        {
            this.State = ClientState.Joining;
            this.lastJoinType = JoinType.CreateRoom;
            this.lastJoinActorNumber = 0;
            this.createRoomOptions = new RoomOptions()
            {
                IsVisible = isVisible,
                IsOpen = isOpen,
                MaxPlayers = maxPlayers,
                PlayerTtl = playerTtl,
                EmptyRoomTtl = roomTtl,
                CleanupCacheOnLeave = true,
                CustomRoomProperties = customGameProperties,
                CustomRoomPropertiesForLobby = propsListedInLobby
            };
            this.CurrentRoom = this.CreateRoom(roomName, this.createRoomOptions);

            Hashtable playerPropsToSend = null;
            if (this.Server == ServerConnection.GameServer)
            {
                playerPropsToSend = this.LocalPlayer.AllProperties;
            }

            this.CurrentLobby = new TypedLobby(lobbyName, lobbyType);

            bool onGameServer = this.Server == ServerConnection.GameServer;
            return this.loadBalancingPeer.OpCreateRoom(roomName, this.createRoomOptions, new TypedLobby(lobbyName, lobbyType), playerPropsToSend, onGameServer);
        }
        /// <summary>
        /// Joins a room by name or creates new room if room with given name not exists.
        /// The OperationResponse depends on the server the peer is connected to:
        /// Master will return a Game Server to connect to.
        /// Game Server will return the joined Room's data.
        /// This is an async request which triggers a OnOperationResponse() call.
        /// </summary>
        /// <remarks>
        /// If the room is not existing (anymore), the OperationResponse will have a returnCode of ErrorCode.GameDoesNotExist.
        /// Other possible ErrorCodes are: GameClosed, GameFull.
        /// </remarks>
        /// <param name="roomName">The name of an existing room.</param>
        /// <param name="playerProperties">This player's custom properties.</param>
        /// <param name="actorId">To allow players to return to a game, they have to specify their actorId.</param>
        /// <param name="createRoomOptions">Options used for new room creation (only sent if createIfNotExists is true).</param>
        /// <param name="lobby">Typed lobby to be used if the roomname is not in use (and room gets created). It's never used when createIfNotExists is false.</param>
        /// <param name="createIfNotExists">Tells the server to create the room if it doesn't exist (if true).</param>
        /// <param name="onGameServer">Master- and Game-Server require different parameters. This allows us to optimize the requests based on the server type (unknown in peer).</param>
        /// <returns>If the operation could be sent (requires connection).</returns>
        public virtual bool OpJoinRoom(string roomName, Hashtable playerProperties, int actorId, RoomOptions createRoomOptions, TypedLobby lobby, bool createIfNotExists, bool onGameServer)
        {
            if (this.DebugOut >= DebugLevel.INFO)
            {
                this.Listener.DebugReturn(DebugLevel.INFO, "OpJoinOrCreateRoom()");
            }

            if (string.IsNullOrEmpty(roomName))
            {
                this.Listener.DebugReturn(DebugLevel.ERROR, "OpJoinOrCreateRoom() failed. Please specify a roomname.");
                return false;
            }

            Dictionary<byte, object> op = new Dictionary<byte, object>();
            op[ParameterCode.RoomName] = roomName;

            if (createIfNotExists)
            {
                op[ParameterCode.JoinMode] = (byte)JoinMode.CreateIfNotExists;
                if (lobby != null)
                {
                    op[ParameterCode.LobbyName] = lobby.Name;
                    op[ParameterCode.LobbyType] = (byte)lobby.Type;
                }
            }

            if (actorId != 0)
            {
                op[ParameterCode.JoinMode] = (byte)JoinMode.Rejoin;
                op[ParameterCode.ActorNr] = actorId;
            }

            if (onGameServer)
            {
                if (playerProperties != null)
                {
                    op[ParameterCode.PlayerProperties] = playerProperties;
                    op[ParameterCode.Broadcast] = true;
                }

                if (createIfNotExists)
                {
                    this.RoomOptionsToOpParameters(op, createRoomOptions);
                }
            }

            return this.OpCustom(OperationCode.JoinGame, op, true);
        }
        /// <summary>
        /// Creates a room (on either Master or Game Server).
        /// The OperationResponse depends on the server the peer is connected to:
        /// Master will return a Game Server to connect to.
        /// Game Server will return the joined Room's data.
        /// This is an async request which triggers a OnOperationResponse() call.
        /// </summary>
        /// <remarks>
        /// If the room is already existing, the OperationResponse will have a returnCode of ErrorCode.GameAlreadyExists.
        /// </remarks>
        /// <param name="roomName">The name of this room. Must be unique. Pass null to make the server assign a name.</param>
        /// <param name="roomOptions">Room creation options. Pass null for defaults.</param>
        /// <param name="lobby">Lobby this room gets added to. If null, current lobby (or default lobby) is used.</param>
        /// <param name="playerProperties">This player's custom properties. Use string keys!</param>
        /// <param name="onGameServer">This operation sends more parameters to the GameServer than to the MasterServer to optimize traffic.</param>
        /// <returns>If the operation could be sent (requires connection).</returns>
        public virtual bool OpCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby lobby, Hashtable playerProperties, bool onGameServer)
        {
            if (this.DebugOut >= DebugLevel.INFO)
            {
                this.Listener.DebugReturn(DebugLevel.INFO, "OpCreateRoom()");
            }

            Dictionary<byte, object> op = new Dictionary<byte, object>();
            if (!string.IsNullOrEmpty(roomName))
            {
                op[ParameterCode.RoomName] = roomName;
            }
            if (lobby != null && !string.IsNullOrEmpty(lobby.Name))
            {
                op[ParameterCode.LobbyName] = lobby.Name;
                op[ParameterCode.LobbyType] = lobby.Type;
            }

            // room- and player-props are only needed by the GameServer
            if (onGameServer)
            {
                if (playerProperties != null)
                {
                    op[ParameterCode.PlayerProperties] = playerProperties;
                    op[ParameterCode.Broadcast] = true;
                }

                this.RoomOptionsToOpParameters(op, roomOptions);
            }

            return this.OpCustom(OperationCode.CreateGame, op, true);
        }
        private void RoomOptionsToOpParameters(Dictionary<byte, object> op, RoomOptions roomOptions)
        {
            if (roomOptions == null)
            {
                roomOptions = new RoomOptions();
            }

            Hashtable gameProperties = new Hashtable();
            gameProperties[GamePropertyKey.IsOpen] = roomOptions.IsOpen;
            gameProperties[GamePropertyKey.IsVisible] = roomOptions.IsVisible;
            gameProperties[GamePropertyKey.PropsListedInLobby] = (roomOptions.CustomRoomPropertiesForLobby == null) ? new string[0] : roomOptions.CustomRoomPropertiesForLobby;
            gameProperties.MergeStringKeys(roomOptions.CustomRoomProperties);
            if (roomOptions.MaxPlayers > 0)
            {
                gameProperties[GamePropertyKey.MaxPlayers] = roomOptions.MaxPlayers;
            }
            op[ParameterCode.GameProperties] = gameProperties;

            op[ParameterCode.CleanupCacheOnLeave] = roomOptions.CleanupCacheOnLeave;

            if (roomOptions.CheckUserOnJoin)
            {
                op[ParameterCode.CheckUserOnJoin] = true;   //TURNBASED
            }

            if (roomOptions.PlayerTtl > 0 || roomOptions.PlayerTtl == -1)
            {
                op[ParameterCode.PlayerTTL] = roomOptions.PlayerTtl;   //TURNBASED
            }
            if (roomOptions.EmptyRoomTtl > 0)
            {
                op[ParameterCode.EmptyRoomTTL] = roomOptions.EmptyRoomTtl;   //TURNBASED
            }
            if (roomOptions.SuppressRoomEvents)
            {
                op[ParameterCode.SuppressRoomEvents] = true;
            }
            if (roomOptions.Plugins != null)
            {
                op[ParameterCode.Plugins] = roomOptions.Plugins;
            }
        }
Example #11
0
        /// <summary>
        /// Demo method that makes up a roomname and sets up the room in general.
        /// </summary>
        public void CreateTurnbasedRoom(string roomPwd)
        {
            string newRoomName = this.PlayerName + "-" + Random.Range(0, 1000).ToString("D4");    // for int, Random.Range is max-exclusive!
            Debug.Log("CreateTurnbasedRoom() will create: " + newRoomName);

            var customRoomProperties = new Hashtable() { { "pwd", roomPwd } };

            RoomOptions roomOptions = new RoomOptions() {
                MaxPlayers = kPlayersNum,
                CustomRoomProperties = customRoomProperties,
                CustomRoomPropertiesForLobby = kRoomPropsInLobby,
                EmptyRoomTtl = kEmptyRoomTtl,
                PlayerTtl = kPlayerTtl
            };
            this.OpCreateRoom(newRoomName, roomOptions, TypedLobby.Default);
        }
Example #12
0
 /// <summary>
 /// Override of the factory method used by the LoadBalancing framework (which we extend here) to create a Room instance.
 /// </summary>
 /// <remarks>
 /// While CreateParticleDemoRoom will make the server create the room, this method creates a local object to represent that room.
 ///
 /// This method is used by a LoadBalancingClient automatically whenever this client joins or creates a room.
 /// We override it to produce a ParticleRoom which has more features like Map and GridSize.
 /// </remarks>
 protected internal override Room CreateRoom(string roomName, RoomOptions opt)
 {
     return new ParticleRoom(roomName, opt);
 }
        /// <summary>
        /// Joins a specific room by name. If the room does not exist (yet), it will be created implicitly.
        /// </summary>
        /// <remarks>
        /// Unlike OpJoinRoom, this operation does not fail if the room does not exist.
        /// This can be useful when you send invitations to a room before actually creating it:
        /// Any invited player (whoever is first) can call this and on demand, the room gets created implicitly.
        ///
        /// If you set room properties in RoomOptions, they get ignored when the room is existing already.
        /// This avoids changing the room properties by late joining players. Only when the room gets created,
        /// the RoomOptions are set in this case.
        ///
        /// If this client returns to the room, set the previously used Player.ID as actorNumber.
        /// When you are using Custom Authentication with unique user IDs, the server will use the userID
        /// to find the previously assigned actorNumber in the room.
        ///
        /// For turnbased games, this is especially useful as rooms can be continued after hours or days.
        /// To return to a room, set the actorNumber to anything but 0. It's best practice to use -1 with
        /// Custom Authentication and unique user accounts.
        ///
        /// If the room is full or closed, this will fail. Override this class and implement
        /// OnOperationResponse(OperationResponse operationResponse) to get the errors.
        ///
        /// This method can only be called while the client is connected to a Master Server.
        /// You should check LoadBalancingClient.Server and LoadBalancingClient.IsConnectedAndReady before calling this method.
        /// Alternatively, check the returned bool value.
        ///
        /// While the server is joining the game, the State will be ClientState.Joining.
        /// It's set immediately when this method sends the Operation.
        ///
        /// If successful, the LoadBalancingClient will get a Game Server Address and use it automatically
        /// to switch servers and join the room. When you're in the room, this client's State will become
        /// ClientState.Joined (both, for joining or creating it).
        /// Set a OnStateChangeAction method to check for states.
        ///
        /// When entering the room, this client's Player Custom Properties will be sent to the room.
        /// Use LocalPlayer.SetCustomProperties to set them, even while not yet in the room.
        /// Note that the player properties will be cached locally and sent to any next room you would join, too.
        /// </remarks>
        /// <param name="roomName">The name of the room to join (might be created implicitly).</param>
        /// <param name="actorNumber">When returning to a room, use a non-0 value. For Turnbased games, set the previously assigned Player.ID or -1 when using Custom Authentication.</param>
        /// <param name="roomOptions">Contains the parameters and properties of the new room. See RoomOptions class for a description of each.</param>
        /// <param name="lobby">Typed lobby to be used if the roomname is not in use (and room gets created). If != null, it will also set CurrentLobby.</param>
        /// <returns>If the operation could be sent currently (requires connection to Master Server).</returns>
        public bool OpJoinOrCreateRoom(string roomName, int actorNumber, RoomOptions roomOptions, TypedLobby lobby)
        {
            this.State = ClientState.Joining;
            this.lastJoinType = JoinType.JoinOrCreateRoom;
            this.CurrentLobby = lobby;
            bool onGameServer = this.Server == ServerConnection.GameServer;

            LoadBalancingPeer.EnterRoomParams opParams = new LoadBalancingPeer.EnterRoomParams();
            this.enterRoomParamsCache = opParams;
            opParams.RoomName = roomName;
            opParams.ActorNumber = actorNumber;
            opParams.RoomOptions = roomOptions;
            opParams.Lobby = lobby;
            opParams.CreateIfNotExists = true;
            opParams.OnGameServer = onGameServer;

            return this.loadBalancingPeer.OpJoinRoom(opParams);
            //return this.loadBalancingPeer.OpJoinRoom(roomName, playerPropsToSend, actorNumber, roomOptions, lobby, true, onGameServer);
        }
Example #14
0
 /// <summary>
 /// Uses the base constructor to initialize this ParticleRoom.
 /// </summary>
 protected internal ParticleRoom(string roomName, RoomOptions opt)
     : base(roomName, opt)
 {
 }