
Key Required

-- ============================================================
-- LOBBY GUARD Β· DUNGEON QUEST REBORN By Baltazar_exe
-- ============================================================
local Config = {
-- ββ 1. YOUR ACCOUNTS (the important part) ββββββββββββ
--
-- USERNAMES of every account you play on (main + alts). Anyone
-- who joins and ISN'T on this list is treated as an intruder.
--
-- Must be the USERNAME (the @name on the profile), NOT the
-- display name. If your profile shows "Cool Name" but the @ is
-- "coolname_2010", put "coolname_2010".
--
-- If a name is missing, that account joining your party closes
-- your main. Case doesn't matter.
Allow = {
"PUT_YOUR_MAIN_USERNAME_HERE",
"PUT_YOUR_ALT_USERNAME_HERE",
-- add or remove lines to match how many accounts you have
},
-- ββ 2. DISCORD ALERT (optional) βββββββββββββββββββββ
--
-- Leave "" if you only want the game to close, no alert.
-- To get a URL: your server > channel settings > Integrations >
-- Webhooks > New Webhook > Copy URL.
WebhookURL = "",
-- Ping you in the message. Discord > Settings > Advanced >
-- Developer Mode on > right-click your name > Copy ID. Numbers
-- only. "" = no ping. PingRoleId pings a role instead.
PingUserId = "",
PingRoleId = "",
-- ββ 3. BEHAVIOUR βββββββββββββββββββββββββββββββββββββ
-- true = close the game on an intruder
-- false = only send the alert, keep playing (for testing)
CloseGame = true,
GuardInLobby = false, -- only turn on if you're in your own private/VIP server
GuardInDungeon = true,
-- When detection isn't sure where you are (happens during load /
-- mid-teleport). Off, because that moment usually means you're
-- entering the full lobby, and closing then would be a mistake.
GuardWhenUnknown = false,
CloseDelay = 1.0, -- seconds after the alert before closing (lets the webhook actually send)
RescanEvery = 1, -- seconds between player-list scans
}
-- ============================================================
-- Logic below. Nothing to edit.
-- ============================================================
local Players = game:GetService("Players")
local HttpService = game:GetService("HttpService")
-- Can be nil on auto-exec (script runs before the client builds the
-- player). Reassigned in waitReady() once it appears - no "local"
-- there, it's this same variable. With it nil, "not you" would be
-- true for YOU and the script would close the game every load.
local LocalPlayer = Players.LocalPlayer
if getgenv and getgenv().__LobbyGuardUnload then
pcall(getgenv().__LobbyGuardUnload)
end
local conns = {}
local fired = false -- already alerted
local running = true -- script alive (kept separate so the scan doesn't stop after the first alert)
local lastWhere = nil
local function allowed(name)
local want = string.lower(tostring(name))
for _, n in ipairs(Config.Allow) do
if string.lower(tostring(n)) == want then return true end
end
return false
end
-- ββ lobby or dungeon? ββββββββββββββββββββββββββββββββββββ
-- dungeon = the "dungeon" folder exists AND has "room 1"/"room 2"...
-- children (the folder alone also shows as a lobby preview).
-- lobby = the "games"/"vipServer"/"bossLobbies" hub folders.
-- The folder blinks out for a moment on room transitions, so a 2s
-- sticky window keeps it reading "dungeon" through the gap.
local DUNGEON_STICKY = 2
local lastDungeonAt = 0
local function getDungeonFolder()
local d = workspace:FindFirstChild("dungeon") or workspace:FindFirstChild("Dungeon")
if d then return d end
for _, ch in ipairs(workspace:GetChildren()) do
if string.lower(ch.Name) == "dungeon" then return ch end
end
return nil
end
local function folderLooksLikeDungeon(d)
if not (d and d.Parent) then return false end
if d:FindFirstChild("room 1") or d:FindFirstChild("Room 1") or d:FindFirstChild("room1") then
return true
end
for _, ch in ipairs(d:GetChildren()) do
local n = string.lower(ch.Name)
if n:match("^room%s*%d+") or n:match("^room%d+") then return true end
end
return false
end
local function lobbyHub()
return workspace:FindFirstChild("games") ~= nil
or workspace:FindFirstChild("vipServer") ~= nil
or workspace:FindFirstChild("bossLobbies") ~= nil
end
-- "dungeon" | "lobby" | "?"
local function whereAmI()
local ok, res = pcall(function()
if folderLooksLikeDungeon(getDungeonFolder()) then
lastDungeonAt = os.clock()
return "dungeon"
end
if lastDungeonAt > 0 and os.clock() - lastDungeonAt < DUNGEON_STICKY then
return "dungeon"
end
if lobbyHub() then return "lobby" end
return "?"
end)
return ok and res or "?"
end
local function guardActive()
local w = whereAmI()
if w == "dungeon" then return Config.GuardInDungeon ~= false, w end
if w == "lobby" then return Config.GuardInLobby ~= false, w end
return Config.GuardWhenUnknown ~= false, w
end
local function intruders()
local list = {}
if not LocalPlayer then return list end
for _, p in ipairs(Players:GetPlayers()) do
if p ~= LocalPlayer and not allowed(p.Name) then
list[#list + 1] = p
end
end
return list
end
-- Executor's request/http_request first: HttpService:PostAsync is
-- blocked for off-game domains in most executors. HttpService is the
-- fallback.
local function sendWebhook(payload)
local url = Config.WebhookURL
if type(url) ~= "string" or url == "" then return false, "no URL" end
local body = HttpService:JSONEncode(payload)
local reqFn = (syn and syn.request) or (http and http.request) or http_request
or request or (fluxus and fluxus.request)
if reqFn then
local ok, res = pcall(reqFn, {
Url = url,
Method = "POST",
Headers = { ["Content-Type"] = "application/json" },
Body = body,
})
if ok then return true end
return false, tostring(res)
end
local ok, err = pcall(function()
HttpService:PostAsync(url, body, Enum.HttpContentType.ApplicationJson)
end)
return ok, (not ok) and tostring(err) or nil
end
local function mentionText()
if Config.PingRoleId ~= "" then return "<@&" .. Config.PingRoleId .. ">" end
if Config.PingUserId ~= "" then return "<@" .. Config.PingUserId .. ">" end
return ""
end
-- Webhook is sent BEFORE closing, and the call is blocking on
-- purpose: closing first would kill the process with the request
-- still queued. Closing is the last line.
local function alert(who)
if fired then return end
fired = true
local names = {}
for _, p in ipairs(who) do
names[#names + 1] = ("%s (%s Β· ID %d)"):format(p.DisplayName, p.Name, p.UserId)
end
if #names == 0 then names[1] = "?" end
local jobId = tostring(game.JobId)
if jobId == "" then jobId = "(local / studio)" end
local content = mentionText()
if content ~= "" then content = content .. " player joined your server" end
local ok, err = sendWebhook({
content = content ~= "" and content or nil,
embeds = { {
title = "Player detected in the server",
description = ("**%d** player(s) besides you:\n%s"):format(#who, table.concat(names, "\n")),
color = 0xF0546C,
fields = {
{ name = "Your account", value = LocalPlayer
and ("%s (%s)"):format(LocalPlayer.DisplayName, LocalPlayer.Name)
or "(unknown)", inline = true },
{ name = "Players in server", value = tostring(#Players:GetPlayers()), inline = true },
{ name = "Where", value = whereAmI(), inline = true },
{ name = "PlaceId", value = tostring(game.PlaceId), inline = true },
{ name = "JobId", value = jobId, inline = false },
{ name = "Action", value = Config.CloseGame and "closing the game" or "alert only (CloseGame = false)", inline = false },
},
} },
})
if Config.WebhookURL == "" then
print("[LobbyGuard] intruder:", table.concat(names, ", "), "(no webhook configured)")
elseif ok then
print("[LobbyGuard] webhook sent:", table.concat(names, ", "))
else
warn("[LobbyGuard] webhook FAILED:", err, "- continuing anyway")
end
if not Config.CloseGame then
task.delay(30, function() fired = false end) -- re-arm so it alerts again for the next one
return
end
task.wait(Config.CloseDelay or 1)
-- 1) most executors implement this as "kill the client"
local shut = pcall(function() game:Shutdown() end)
if shut then return end
-- 2) always exists, but DISCONNECTS instead of closing the window
pcall(function()
if LocalPlayer then
LocalPlayer:Kick("LobbyGuard: another player joined the server.")
end
end)
end
local function check()
if fired then return end
local on, w = guardActive() -- checked every scan: you move in and out of dungeons all run
if not on then
if lastWhere ~= w then
lastWhere = w
print("[LobbyGuard] in " .. w .. " - guard off here")
end
return
end
if lastWhere ~= w then
lastWhere = w
print("[LobbyGuard] in " .. w .. " - watching")
end
local who = intruders()
if #who > 0 then
alert(who)
end
end
-- Nothing can arm before LocalPlayer exists - not even PlayerAdded:
-- with it nil, "p == LocalPlayer" never matches and YOUR own join
-- would fire the alert.
local function waitReady()
local t0 = os.clock()
while not Players.LocalPlayer and os.clock() - t0 < 60 do
task.wait(0.1)
end
LocalPlayer = Players.LocalPlayer
if not LocalPlayer then
warn("[LobbyGuard] Players.LocalPlayer never appeared - guard NOT armed")
return false
end
t0 = os.clock()
while not game:IsLoaded() and os.clock() - t0 < 60 do
task.wait(0.1)
end
return true
end
print(("[LobbyGuard] loaded Β· close=%s Β· accounts=%d Β· scan every %ss"):format(
tostring(Config.CloseGame), #Config.Allow, tostring(Config.RescanEvery)))
print(("[LobbyGuard] guard: lobby=%s Β· dungeon=%s Β· unknown=%s"):format(
tostring(Config.GuardInLobby ~= false),
tostring(Config.GuardInDungeon ~= false),
tostring(Config.GuardWhenUnknown ~= false)))
if Config.WebhookURL == "" then
warn("[LobbyGuard] WebhookURL empty - it will close the game with NO Discord alert")
end
if Config.CloseGame and #Config.Allow == 0 then
warn("[LobbyGuard] account list EMPTY and CloseGame on - any join (incl. your alt) closes this account")
end
do
local placeholders = 0
for _, n in ipairs(Config.Allow) do
if string.find(string.upper(tostring(n)), "PUT_YOUR") == 1 then placeholders = placeholders + 1 end
end
if placeholders > 0 then
warn(("[LobbyGuard] you left %d example name(s) (\"PUT_YOUR_...\") in Config.Allow - replace with your real USERNAMES"):format(placeholders))
end
end
task.spawn(function()
if not Players.LocalPlayer then
print("[LobbyGuard] waiting for the player to arm...")
end
if not waitReady() then return end
conns[#conns + 1] = Players.PlayerAdded:Connect(function(p)
if p == LocalPlayer then return end
if allowed(p.Name) then
print("[LobbyGuard] " .. p.Name .. " is on the list - ignored")
return
end
local on, w = guardActive()
if not on then
print(("[LobbyGuard] %s joined, but I'm in %s - guard off here"):format(p.Name, w))
return
end
alert({ p })
end)
print(("[LobbyGuard] armed Β· %d player(s) in server Β· you = %s"):format(
#Players:GetPlayers(), tostring(LocalPlayer.Name)))
-- Periodic scan, forever. PlayerAdded only catches joins from now
-- on; this catches whoever was already there or still replicating
-- when the script loaded. Only the unload stops it.
while running do
check()
task.wait(math.max(tonumber(Config.RescanEvery) or 3, 1))
end
end)
if getgenv then
getgenv().__LobbyGuardUnload = function()
for _, c in ipairs(conns) do
pcall(function() c:Disconnect() end)
end
conns = {}
fired = true
running = false
getgenv().__LobbyGuardUnload = nil
print("[LobbyGuard] unloaded")
end
endNo comments yet for this script.

![Sir Meme Hub | [16 GAMES] [$14.99 LIFETIME] | FARM/AIM/ESP](https://cdn.kocakz.me/images/e504c71fa02f6af2fd2c60f10f68873bd0f27b9de310639fc51d740f46e3c289.webp)

