Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

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

Asked by 1 year ago

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

Log in to vote
0
Answered by
Puppynniko 1059 Moderation Voter
1 year ago

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)
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' ROBLOXIS14NOW 5 — 1y
0
Teleport Service? Puppynniko 1059 — 1y
Ad
Log in to vote
0
Answered by 1 year ago
Edited 1 year ago

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)()

Answer this question