-- Monochrome Hub loader: works out which game this is and runs that game's -- script, served from monochrome.xocat.online. One line for every game: -- loadstring(game:HttpGet("https://monochrome.xocat.online/Monochrome.luau"))() local RAW = "https://monochrome.xocat.online/" local KEY_HOST = "https://thanks.xocat.online" local WORKINK = "https://work.ink/2XZF/mono-v2" local KEY_FILE = "Monochrome/key.txt" -- universe id (game.GameId) -> script. Universe, not place, so every place -- of a game (lobbies, map servers) resolves the same. local GAMES = { [66654135] = { name = "Murder Mystery 2", file = "Games/MM2/Script.luau" }, [4826476142] = { name = "dingus", file = "Games/dingus/Script.luau" }, [10090256806] = { name = "TTK", file = "Games/TTK/Script.luau" }, [5371687033] = { name = "QUICKDRAW: LEGACY", file = "Games/Quickdraw/Script.luau" }, [2404080894] = { name = "Funky Friday", file = "Games/FunkyFriday/Script.luau" }, [111958650] = { name = "Arsenal", file = "Games/Arsenal/Script.luau" }, [4126908979] = { name = "Parkour Reborn", file = "Games/ParkourReborn/Script.luau" }, [2132866904] = { name = "FRONTLINES", file = "Games/Frontlines/Script.luau" }, [8307114974] = { name = "Operation One", file = "Games/OperationOne/Script.luau" }, -- Gated + closed source: the script is not on the public site. It lives in -- the key worker's KV and is only handed out for a valid 24h key, fetched -- from KEY_HOST/s?game=..&key=.. . `gate` is the KV script name. [7633926880] = { name = "BloxStrike", gate = "BloxStrike" }, } local HttpService = game:GetService("HttpService") local Players = game:GetService("Players") local LocalPlayer = Players.LocalPlayer local function notify(text, dur) pcall(function() game:GetService("StarterGui"):SetCore("SendNotification", { Title = "Monochrome", Text = text, Duration = dur or 6 }) end) end local entry = GAMES[game.GameId] if not entry then local names = {} for _, g in pairs(GAMES) do names[#names + 1] = g.name end table.sort(names) warn("Monochrome: no script for this game yet (universe " .. tostring(game.GameId) .. "). Supported: " .. table.concat(names, ", ")) notify("No script for this game yet.") return end -- Anonymous (no user): which published version of this place the server runs. The -- Discord status board only calls it a game update when this number goes up, so an -- edit to the game's page is never mistaken for one. Fire and forget. task.spawn(pcall, game.HttpGet, game, RAW .. "api/pv?u=" .. game.GameId .. "&p=" .. game.PlaceId .. "&v=" .. game.PlaceVersion) -- ---------------------------------------------------------------- ungated if entry.file then local ok, src = pcall(game.HttpGet, game, RAW .. entry.file) if not ok or type(src) ~= "string" or #src < 1000 then warn("Monochrome: could not download " .. entry.file .. ": " .. tostring(src)) return end local fn, err = loadstring(src, "=Monochrome/" .. entry.file) if not fn then warn("Monochrome: " .. entry.file .. " failed to compile: " .. tostring(err)) return end return fn() end -- ---------------------------------------------------------------- key gate local rf, wf, mkf, isf, isdir, clip = readfile, writefile, makefolder, isfile, isfolder, setclipboard local G = (typeof(getgenv) == "function") and getgenv() or nil if G and (typeof(G.setclipboard) == "function") then clip = G.setclipboard end local function savedKey() if not (isf and rf) then return nil end local ok, k = pcall(function() return isf(KEY_FILE) and rf(KEY_FILE) or nil end) return ok and type(k) == "string" and (k:gsub("%s", "")):upper() or nil end local function storeKey(k) pcall(function() if mkf and isdir and not isdir("Monochrome") then mkf("Monochrome") end if wf then wf(KEY_FILE, k) end end) end -- fetch the gated script for a key; returns src (200) | "expired" | "down" local function fetchGated(key) local url = KEY_HOST .. "/s?game=" .. HttpService:UrlEncode(entry.gate) .. "&key=" .. HttpService:UrlEncode(key) local ok, body = pcall(game.HttpGet, game, url) if not ok then -- HttpGet throws on non-2xx: a rejected key reads as an error string local s = tostring(body):lower() if s:find("expired") or s:find("invalid") or s:find("401") or s:find("bad key") then return "expired" end return "down" end if type(body) == "string" and #body > 1000 then return body end return "expired" end local function run(src) local fn, err = loadstring(src, "=Monochrome/" .. entry.name) if not fn then warn("Monochrome: " .. entry.name .. " failed to compile: " .. tostring(err)) return end return fn() end -- try the saved key first, silently do local k = savedKey() if k then local r = fetchGated(k) if r ~= "expired" and r ~= "down" then return run(r) end if r == "down" then notify("Key server unreachable. Try again in a moment.", 6); return end end end -- no valid key: the gate. Get key copies the work.ink link; paste the 24h key. local mount = (gethui and gethui()) or game:GetService("CoreGui") local TweenService = game:GetService("TweenService") local gui = Instance.new("ScreenGui") gui.Name = HttpService:GenerateGUID(false) gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.DisplayOrder = 2000000 gui.Parent = mount local shade = Instance.new("Frame") shade.Size = UDim2.fromScale(1, 1); shade.BackgroundColor3 = Color3.new(0, 0, 0); shade.BackgroundTransparency = 1; shade.BorderSizePixel = 0; shade.Parent = gui local card = Instance.new("CanvasGroup") card.AnchorPoint = Vector2.new(0.5, 0.5); card.Position = UDim2.fromScale(0.5, 0.5); card.Size = UDim2.fromOffset(400, 250) card.BackgroundColor3 = Color3.fromRGB(20, 20, 24); card.BorderSizePixel = 0; card.GroupTransparency = 1; card.Parent = gui Instance.new("UICorner", card).CornerRadius = UDim.new(0, 12) local st = Instance.new("UIStroke", card); st.Color = Color3.new(1, 1, 1); st.Transparency = 0.85 local sc = Instance.new("UIScale", card); sc.Scale = 0.94 local function label(y, size, colour, font, str, h, wrap) local l = Instance.new("TextLabel") l.BackgroundTransparency = 1; l.Position = UDim2.fromOffset(20, y); l.Size = UDim2.new(1, -40, 0, h or size + 6) l.Font = font; l.TextSize = size; l.TextColor3 = colour l.TextXAlignment = Enum.TextXAlignment.Left; l.TextYAlignment = Enum.TextYAlignment.Top; l.TextWrapped = wrap ~= false; l.Text = str; l.Parent = card return l end label(18, 16, Color3.fromRGB(245, 245, 250), Enum.Font.GothamBold, "Monochrome ยท " .. entry.name .. " needs a key") label(44, 13, Color3.fromRGB(170, 170, 182), Enum.Font.Gotham, "Get a key (24 hours, free) from the link, then paste it below. One key per day.", 40) local box = Instance.new("TextBox") box.Position = UDim2.fromOffset(20, 94); box.Size = UDim2.fromOffset(360, 38); box.BackgroundColor3 = Color3.fromRGB(30, 30, 36); box.BorderSizePixel = 0 box.Font = Enum.Font.GothamMedium; box.TextSize = 14; box.TextColor3 = Color3.fromRGB(245, 245, 250); box.PlaceholderText = "MONO-XXXX-XXXX-XXXX" box.PlaceholderColor3 = Color3.fromRGB(110, 110, 120); box.Text = ""; box.ClearTextOnFocus = false; box.Parent = card Instance.new("UICorner", box).CornerRadius = UDim.new(0, 9) local status = label(140, 12, Color3.fromRGB(255, 120, 120), Enum.Font.Gotham, "", 16) local function button(x, w, y, txt, accent) local b = Instance.new("TextButton") b.Position = UDim2.fromOffset(x, y); b.Size = UDim2.fromOffset(w, 38); b.AutoButtonColor = true; b.BorderSizePixel = 0 b.BackgroundColor3 = accent and Color3.fromRGB(245, 245, 250) or Color3.fromRGB(38, 38, 44) b.Font = Enum.Font.GothamBold; b.TextSize = 13; b.TextColor3 = accent and Color3.fromRGB(10, 10, 12) or Color3.fromRGB(245, 245, 250); b.Text = txt; b.Parent = card Instance.new("UICorner", b).CornerRadius = UDim.new(0, 9) return b end local getBtn = button(20, 175, 168, "Get a key", false) local redeemBtn = button(205, 175, 168, "Redeem", true) button(20, 360, 214, "Close", false).MouseButton1Click:Connect(function() pcall(function() gui:Destroy() end) end) getBtn.MouseButton1Click:Connect(function() if clip then pcall(clip, WORKINK) end status.TextColor3 = Color3.fromRGB(150, 200, 150) status.Text = "Link copied. Open it in your browser, come back with the key." end) redeemBtn.MouseButton1Click:Connect(function() local k = (box.Text:gsub("%s", "")):upper() if #k < 10 then status.TextColor3 = Color3.fromRGB(255, 120, 120); status.Text = "Paste your key first." return end status.TextColor3 = Color3.fromRGB(170, 170, 182); status.Text = "Checking..." task.spawn(function() local r = fetchGated(k) if r == "down" then status.TextColor3 = Color3.fromRGB(255, 120, 120); status.Text = "Key server unreachable." return end if r == "expired" then status.TextColor3 = Color3.fromRGB(255, 120, 120); status.Text = "That key is not valid or has expired." return end storeKey(k) -- optional: also tag the supporter star pcall(game.HttpGet, game, KEY_HOST .. "/redeem?key=" .. HttpService:UrlEncode(k) .. "&user=" .. HttpService:UrlEncode(LocalPlayer.Name)) pcall(function() gui:Destroy() end) run(r) end) end) local ti = TweenInfo.new(0.22, Enum.EasingStyle.Quad, Enum.EasingDirection.Out) TweenService:Create(shade, ti, { BackgroundTransparency = 0.45 }):Play() TweenService:Create(card, ti, { GroupTransparency = 0 }):Play() TweenService:Create(sc, TweenInfo.new(0.28, Enum.EasingStyle.Back, Enum.EasingDirection.Out), { Scale = 1 }):Play()