Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How to destroy a server when all the players have left it?

Hi.

I have made a VIP server system for my game, everything works perfectly. The only problem is, is that once a player creates a server, it is there forever and I don't know how to destroy it, because I am teleporting the player to a different place.

The code:

-- Services
local DSS = game:GetService("DataStoreService")
local RS = game:GetService("ReplicatedStorage")
local TS = game:GetService("TeleportService")
local Players = game:GetService("Players")

--DataStores
local ServerAccessCodesDS = DSS:GetDataStore("ServerAccessCodesDS.")
local ServerNamesDS = DSS:GetDataStore("ServerNamesDS.")
local LocalOwnedServersDS = DSS:GetDataStore("LocalOwnedServersDS.")
local CustomServerJoinCodesDS = DSS:GetDataStore("CustomServerJoinCodesDS.")
local GlobalPrivateServerDS = DSS:GetOrderedDataStore("GlobalPrivateServerDS.")
local PrivateServerOwnerIdDS = DSS:GetDataStore("PrivateServerOwnerIdDS.")
local ServerInfoDS = DSS:GetDataStore("ServerInfoDS.")

local value = Instance.new("IntValue")
value.Parent = script.Parent
value.Name = "MaxServers"

--Paths
local menu = script.Parent.Parent
local createServerButton = menu.Frame.CreateServer.CreateButton

local yourServersButton = menu.Frame.YourServers_Button
local joinServerButton = menu.Frame.JoinByCode.JoinButton

local teleportGui = RS:WaitForChild("TeleportingGui")

-- Vars
local plr = menu.Parent.Parent


local psid = game.PrivateServerId
local servers = {}
local JoinServerCodeEntered;

pcall(function()
	for i,v in pairs(LocalOwnedServersDS:GetAsync(plr.UserId) or nil) do
		table.insert(servers, v)
		warn(plr.Name.." PS codes are: "..v)
	end
end)

function GenerateServerInviteCode()
	while true do
		local code = math.random(111111,999999)
		if not ServerNamesDS:GetAsync(code) then
			return code
		end
	end
end

function SortGlobalPrivateSeversAsync()
	local pages = GlobalPrivateServerDS:GetSortedAsync(false, 100)
	
	for i,v in pairs(menu.Frame.ServerList:GetChildren()) do
		if v:IsA("Frame") then
			v:Destroy()
		end
	end
	
	local data = pages:GetCurrentPage()
	
	for i,v in pairs(data) do
		warn(v.value, v.key)
		task.wait(.2)
		local ServerInfoDictionary = ServerInfoDS:GetAsync(v.key)
		local ServerFrameClone = script.ServersTemplate:Clone()
		ServerFrameClone.Parent = script.Parent.Parent.Frame.ServerList
		ServerFrameClone.PlayerCount.Text = v.value.."/20"
		ServerFrameClone.ServerName.Text = ServerInfoDictionary.ServerName
		ServerFrameClone.JoinServerButton.MouseButton1Click:Connect(function()
			local code = ServerAccessCodesDS:GetAsync(v.key)
			
			TS:SetTeleportGui(teleportGui)
			
			TS:TeleportToPrivateServer(9619375620, code, {plr})
		end)
	end
	
end

if string.len(psid) >= 30 then
RS:WaitForChild("PrivateServerOwnerValue").Value = PrivateServerOwnerIdDS:GetAsync(psid)
else
	
end

script.Parent.RemoteEvent.OnServerEvent:Connect(function(plr, txt)
	JoinServerCodeEntered = txt
end)

joinServerButton.MouseButton1Click:Connect(function()
	if JoinServerCodeEntered ~= nil then
		local id = ServerNamesDS:GetAsync(JoinServerCodeEntered)
		local code = ServerAccessCodesDS:GetAsync(id)
		
		TS:SetTeleportGui(teleportGui)
		TS:TeleportToPrivateServer(9619375620, code, {plr})
	end
end)

function UpdateYourServersList()
	for i,v in pairs(menu.Frame.YourServers:GetChildren()) do
		if v:IsA("Frame") then
			v:Destroy()
		end
	end
	
	for i,v in pairs(servers) do
		local id = ServerNamesDS:GetAsync(v)
		local ServerInfoDictionary = ServerInfoDS:GetAsync(id)
		local YourServerFrameClone = script.YourServersTemplate:Clone()
		YourServerFrameClone.Name = v..i
		YourServerFrameClone.Parent = menu.Frame.YourServers
		YourServerFrameClone.JoinCode.Text = v
		YourServerFrameClone.ServerName.Text = ServerInfoDictionary.ServerName
		YourServerFrameClone.JoinServerButton.MouseButton1Click:Connect(function()
			local code = ServerAccessCodesDS:GetAsync(id)
			local teleportGui = RS:WaitForChild("TeleportingGui"):Clone()
			teleportGui.Parent = plr.PlayerGui
			TS:SetTeleportGui(teleportGui)
	        TS:TeleportToPrivateServer(9619375620, code, {plr})
		end)
	end
	warn("Successfully loaded ", plr.Name, "'s servers!")
end

createServerButton.MouseButton1Click:Connect(function()
    if value.Value == 1 then return warn("Max!") end
	value.Value = 1
	print(value.Value)
	local code, id = TS:ReserveServer(9619375620)
	local NewJoinCode = GenerateServerInviteCode()
	GlobalPrivateServerDS:SetAsync(id, 0)
	CustomServerJoinCodesDS:SetAsync(id, NewJoinCode)
	ServerNamesDS:SetAsync(NewJoinCode, id)
	ServerAccessCodesDS:SetAsync(id, code)
	PrivateServerOwnerIdDS:SetAsync(id, plr.UserId)
	
	local ServerInfoDictionary = {
		ServerName = script.Parent.GetServerName:InvokeClient(plr),
	}
	
	ServerInfoDS:SetAsync(id, ServerInfoDictionary)
	table.insert(servers, NewJoinCode)
	local success, errorMessage = pcall(function()
		LocalOwnedServersDS:SetAsync(plr.UserId, servers)
	end)
	
	UpdateYourServersList()
	SortGlobalPrivateSeversAsync()
end)

Players.PlayerAdded:Connect(function()
	if string.len(psid) >= 30 then
		GlobalPrivateServerDS:SetAsync(psid, #Players:GetPlayers())
	end
end)

Players.PlayerRemoving:Connect(function()
	if string.len(psid) >= 30 then
		GlobalPrivateServerDS:SetAsync(psid, #Players:GetPlayers())
	end
end)

game:BindToClose(function()
	if string.len(psid) >= 30 then
		GlobalPrivateServerDS:SetAsync(psid, 0)
	end
end)

UpdateYourServersList()

plr.CharacterAdded:Connect(function()
	UpdateYourServersList()
end)

while true do
	SortGlobalPrivateSeversAsync()
	task.wait(60)
end

Any help would be appreciated, thanks!

2 answers

i think bindToClose and MessagingService would help you here basically when bindToClose fires send data to the main menu server that this server has closed im not sure how you do this as im not familiar with MessagingService but heres the Api link https://developer.roblox.com/en-us/api-reference/class/MessagingService

game:BindToClose(function()
	print("Game is shutting down.")
end)

2 comments

0

Ok I have written a new script, but I have one problem. I don't know how to teleport the player when they click the 'join button'

0

Teleport Service?

Here is the new script which uses MessagingService and BindToClose:

local servers = {}
local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("#ServersData[pcall1]Save")
local runService = game:GetService("RunService")

local playerUserId = "#ServersData[pcall1]Data"

local data = playerData:GetAsync(playerUserId)  --Checks if player has stored data

if data then
	servers = data
end


game:BindToClose(function()
	wait(10)
end)

local arrayofunions = {}


local TS = game:GetService("TeleportService")
local Players = game:GetService("Players")
local messagingService = game:GetService("MessagingService")
local httpService = game:GetService("HttpService")
local rs = game:GetService("ReplicatedStorage")
local asktoinvite = rs.AskToInvite
local tp = rs.TeleportToServer
local newserver = rs.CreateServer
--local code = TS:ReserveServer(9619375620) -- Returns a code
--local players = Players:GetPlayers() -- Get a list of all players

--wait(5)
--TS:TeleportToPrivateServer(9619375620,code,players) -- Actually teleport the players
local CurServerId = game.PrivateServerId
local CurServerNumber = 0
local isReserved = game.PrivateServerId ~= "" and game.PrivateServerOwnerId == 0

local function ServerUpdate(ServerId,UserId,Psid)
	local createnewarr = true
	local data = playerData:GetAsync(playerUserId)  --Checks if player has stored data

	if data then
		servers = data
	end
	--if servers then
	--	for i,v in ipairs(servers) do
	--		
	--	end
	--end
	for i,v in ipairs(servers) do
		if v.server == ServerId and v.plr ==  UserId then
			createnewarr = false
		end
	end
	local arr = {server = ServerId,plr = UserId,id = nil}
	if Psid then
		for i,v in ipairs(servers) do
			if v.server == ServerId and v.id == nil then
				v.id = Psid
				createnewarr = false
			end
		end
	end
	if Psid == nil then
		for i,v in ipairs(servers) do
			if v.server == ServerId and v.id then
				createnewarr = false
			end
		end
	end
	if createnewarr == true then
		table.insert(servers,arr)
	end
	local success, err = pcall(function()
		local playerUserId = "#ServersData[pcall1]Data"
		playerData:SetAsync(playerUserId,servers) --Saves player data
	end)
	if not success then
		warn('Could not save data!')
		print(err)
	end		
	
	


end




Players.PlayerRemoving:Connect(function(player)
	CurServerNumber -= 1
	for i,v in ipairs(servers) do
		if game.PrivateServerId == v.id and isReserved then
			local messageData = {}

			messageData["sender"] = v.id
			messageData["message"] = CurServerNumber

			local encoded = httpService:JSONEncode(messageData)
			messagingService:PublishAsync("#ServersData[pcall1]Data", encoded)
		end
	end
end)

Players.PlayerAdded:Connect(function(player)
	for i,v in ipairs(servers) do
		if v.plr == player.UserId and isReserved and v.id == nil then
			ServerUpdate(v.server,v.plr,game.PrivateServerId)
		end
	end
	CurServerNumber += 1
	for i,v in ipairs(servers) do
		if game.PrivateServerId == v.id and isReserved then
			local messageData = {}

			messageData["sender"] = v.id
			messageData["message"] = CurServerNumber

			local encoded = httpService:JSONEncode(messageData)
			messagingService:PublishAsync("#ServersData[pcall1]Data", encoded)
		end
	end
end)

local function addtolist(PrivateServerId,amount,player)
	coroutine.wrap(function()
		local List = player.PlayerGui:WaitForChild("System",10).Frame.List
		local StandartFrame = game:GetService("ReplicatedStorage").Frame:Clone()
		StandartFrame.Parent = List
		local Owner = StandartFrame:FindFirstChild("Owner")
		local UserId = StandartFrame:FindFirstChild("UserId")
		local Players = StandartFrame:FindFirstChild("Players")
		local data
		for i,v in ipairs(servers) do
			if v.id == PrivateServerId then
				data = v
			end
		end
		if data then
			UserId.Text = "UserId: "..tostring(data.plr)
			Players.Text = "Players: "..tostring(amount).." / 50"
			Owner.Text = "Owner: "..game:GetService("Players"):GetNameFromUserIdAsync(data.plr)
		end
	end)()
end
function callbackFunction(serviceData)
	local decodedData = httpService:JSONDecode(serviceData.Data)
	arrayofunions[decodedData.sender] = decodedData.message
	if decodedData.message == 0 then
		arrayofunions[decodedData.sender] = nil	
	end
	--for i,v in ipairs(game:GetService("Players"):GetChildren()) do
	--addtolist(decodedData.sender,decodedData.message,v)
	--end
end
messagingService:SubscribeAsync("#ServersData[pcall1]Data", callbackFunction)

newserver.OnServerEvent:Connect(function(plr)
	local bool = false
	for i,v in ipairs(servers) do
		if game.PrivateServerId == v.id and v.plr == plr.UserId then
			
			bool = true
			break
		end
		if v.plr == plr.UserId and v.id ~= game.PrivateServerId then
			TS:TeleportToPrivateServer(9619375620,v.server,{plr})
			bool = true
		end
	end
	if bool == false then
		
		local code = TS:ReserveServer(9619375620) -- Returns a code
		ServerUpdate(code,plr.UserId)
		TS:TeleportToPrivateServer(9619375620,code,{plr})
		
		
	
		
	end


	
end)
coroutine.wrap(function()
	while wait(10) do
		for i,v in ipairs(servers) do
			if game.PrivateServerId == v.id and isReserved then
				local messageData = {}

				messageData["sender"] = v.id
				messageData["message"] = CurServerNumber

				local encoded = httpService:JSONEncode(messageData)
				messagingService:PublishAsync("#ServersData[pcall1]Data", encoded)
			end
		end
	end
end)()




coroutine.wrap(function()
	while wait(1) do
		for i,plr in ipairs(game:GetService("Players"):GetChildren()) do
			coroutine.wrap(function()
				for i,c in ipairs(plr.PlayerGui:WaitForChild("System",10).Frame.List:GetChildren()) do
					if c:IsA("Frame") then
						c:Destroy()
					end
				end
			end)()
		end
		for i,v in ipairs(servers) do
			if v.id ~= nil and arrayofunions[v.id] then

				for i,j in ipairs(game:GetService("Players"):GetChildren()) do
					coroutine.wrap(function()
						addtolist(v.id,arrayofunions[v.id],j)
					end)()
				end
			end
		end
	end
end)()

This discussion is preserved as it was. New answers, comments, and votes are closed.