Locking servers

Ok, so I’m aware there is already a system to lock servers, you just kick any new players that join, right?
If lots of servers are locked, then the chance of a player constantly joining and getting kicked becomes larger. This will become irritating and enthuse the player to stop trying.
Is there any possible way to stop players from joining a server, even if it’s not full?

My only idea is to fill remaining slots with a bunch of dummies that register as players;
But that really doesn’t seem possible, and it’s not very practical.

Any ideas?

2 Likes

I would recommend using private servers

2 Likes

The point of locking the server is so it can’t be accessed. The server remains open untill all players in that server leave, and it closes.
Unless a public server can be changed into a private server whilst it is open (and this stops other players from joining) but I’m not sure if that’s possible.
If I’m wrong, can you explain it a little clearer?

Could you explain more about why you’d recommend using private servers? Wouldn’t this require your start place to distribute players? You’d have to handle players joining their friends too right?

I think he’s talking about a softshutdown

Maybe just have it rather then kick them teleport them to another server with some information.

2 Likes

But then it might be constantly teleporting, which is even worse if you are not using a computer, as you can’t simply close the window.

If I had to propose a solution, you could leverage the recently added MessagingService (see Cross-Server Messaging) and TeleportService to distribute players.

The ideology is like this: You lock a server. A player attempts to join this server. Rather than kicking them, make a call to the MessagingService that basically says “Hey, are any of you other servers unlocked?” and then servers that are unlocked can respond with their instance ID. You can select the ID however you want if there’s multiple returned, that’s on you, and you can make use of TeleportToPlaceInstance to send players to it.

13 Likes

Maybe choose the server with the least amount of players. Or one that is about to begin the game.

This is a really nice idea.
So if the player joins a server, and it’s locked, a gui pops up that allows the player to join any of the unlocked servers.
The only problem is, my skill in programming is very limited, I’m always trying new stuff but I’m taking steady steps, and communicating with other servers seems like a big task.
Could you provide any more info on how I could do this?

That wiki page I put up (Cross-Server Messaging) should have everything you need. I’ve not delved into this service before but it’s likely easy knowing how Roblox designs their API.

Yea my original suggestion was to have a button that teleports players in a place that anyone can access, but make the button only visible to those who have access to the private server.

@EtiTheSpirit’s suggestion is probably better

Here’s some untested code I wipped up off an uncopylocked place.

local MessagingService = game:GetService("MessagingService")
local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")

local MESSAGING_TOPIC = "FindEmptyServer"

-- stuff to detect requests
function onMessageGot(msg)
	if msg == 'hey any open servers?' then
		local amountOfPlayers = #Players:GetPlayers()
		if amountOfPlayers < Players.MaxPlayers then
			return game.JobId
		end
	end
end
MessagingService:SubscribeAsync(MESSAGING_TOPIC,onMessageGot)


-- requesting an open server
local foundJobId = MessagingService:PublishAsync(MESSAGING_TOPIC,'hey any open servers?')

if foundJobId then
	TeleportService:TeleportToPlaceInstance(game.PlaceId, foundJobId, Player)
else
	print'sorry, no open servers'
end

I hope it makes it more digestible.

2 Likes

Just a quick correction: …probably not, but… according to the dev hub, PublishAsync :link: does not provide return values like a function call would; you would have to subscribe to a different topic that would send the data specifying the JobId, or you could specify a different action within that topic that gets the data.

I made my own variation of your code that gathers all the data published from a player-specific message topic into an array, sorts it by player count, and chooses the one with the least players.

-- stuff to detect requests

local function onMessageGot(msg)

	--[[ get the topic from the data sent
	msg = {
		Sent = -- the time when the message was sent
		Data = -- message sent over by the developer
	}
	--]]
	local msgTopic = msg.Data

	local amountOfPlayers = #Players:GetPlayers()
	if amountOfPlayers < Players.MaxPlayers then

		-- the table to send
		local sendTable = {
			Count = amountOfPlayers,
			JobId = game.JobId
		}
		-- send the table back to specified topic
		MessagingService:PublishAsync(msgTopic, sendTable)
	end
end

MessagingService:SubscribeAsync(MESSAGING_TOPIC, onMessageGot)
-- requesting an open server

-- open a new player-specific topic
local newMessagingTopic = string.format("ReturnEmptyServersFor-%d", Player.UserId)

-- make a table to store any responses
local openServers = {}

local function onReturnMessageGot(msg)
	-- insert the data into the table
	openServers[#openServers + 1] = msg.Data
end

local retSubscription = MessagingService:SubscribeAsync(newMessagingTopic, onReturnMessageGot)
MessagingService:PublishAsync(MESSAGING_TOPIC, newMessagingTopic)

-- wait for all the servers to respond
-- might be shorter, I don't know
wait(5)

-- disconnect from the topic since it's not being used anymore
retSubscription:Disconnect()

if #openServers > 0 then -- at least 1 server is open

	-- sort servers by player count
	table.sort(openServers, function(a, b)
		return a.Count < b.Count
	end

	-- choose the one with the lowest count
	local foundJobId = openServers[1].JobId

	TeleportService:TeleportToPlaceInstance(game.PlaceId, foundJobId, Player)

else
	print("sorry, no open servers")
end

One could also receive just the first server to respond and get the player to teleport them there as soon as possible, you would just disconnect the subscription from inside the callback:

--[[ requesting an open server ]]
local retSubscription
local function onReturnMessageGot(msg)
	local foundJobId = msg.Data.JobId
	retSubscription:Disconnect()

	TeleportService:TeleportToPlaceInstance(game.PlaceId, foundJobId, Player)

end

getConnection = MessagingService:SubscribeAsync(newMessagingTopic, onReturnMessageGot)
MessagingService:PublishAsync(MESSAGING_TOPIC, newMessagingTopic)

You might also want to wrap your PublishAsyncs in a pcall since this is a networking function that can error, but you can also use Promises :link: for this!

4 Likes

Has anyone implemented this in their games? Im wondering how well this is working.