-- MuzzyHub Loader (this is the ONLY file customers get) -- Asks for the key once, saves it, then asks the shop bot for the script that matches the game you are in. -- No game logic and no secrets in here - the real scripts are only ever sent by the bot after the key checks out. -- -- Everything lives inside CORE (a string) so a copy of it can be queued to re-run itself after a rejoin -- (the Throw Food auto-reconnect and the Punch to Escape lobby reload use getgenv().MuzzyBootstrap for that). -- Edit the two settings at the top of CORE if the bot URL ever changes. local CORE = [==[ local CORE_SRC = ... -- this chunk's own source (passed in below) local API = "https://muzzyhub.com" local KEY_FILE = "MuzzyHub_key.txt" -- where the key is saved (executor workspace) local Players = game:GetService("Players") local HttpService = game:GetService("HttpService") local genv = (getgenv and getgenv()) or _G ---------------------------------------------------------------- theme (the one picked in a script's Config tab) -- The scripts save the chosen theme per account; the key box and messages use the same colours. local THEMES = { Classic = { bg = {15, 15, 20}, panel = {29, 29, 38}, text = {236, 236, 242}, dim = {145, 145, 162}, accent = {139, 92, 246}, onAccent = {255, 255, 255} }, Midnight = { bg = {9, 11, 22}, panel = {21, 25, 46}, text = {232, 236, 250}, dim = {134, 144, 180}, accent = {88, 130, 255}, onAccent = {255, 255, 255} }, Crimson = { bg = {17, 9, 11}, panel = {38, 19, 24}, text = {246, 232, 234}, dim = {170, 134, 140}, accent = {235, 64, 82}, onAccent = {255, 255, 255} }, Emerald = { bg = {8, 17, 14}, panel = {18, 37, 30}, text = {230, 246, 238}, dim = {126, 166, 148}, accent = {46, 204, 138}, onAccent = {8, 24, 18} }, Sunset = { bg = {20, 11, 17}, panel = {43, 22, 35}, text = {250, 236, 238}, dim = {178, 138, 150}, accent = {255, 120, 90}, onAccent = {255, 255, 255} }, Ocean = { bg = {7, 17, 23}, panel = {16, 39, 53}, text = {228, 244, 250}, dim = {120, 160, 178}, accent = {40, 200, 232}, onAccent = {6, 22, 30} }, Rose = { bg = {22, 12, 18}, panel = {46, 25, 38}, text = {252, 236, 244}, dim = {180, 134, 158}, accent = {255, 105, 180}, onAccent = {255, 255, 255} }, Mono = { bg = {11, 11, 11}, panel = {29, 29, 29}, text = {240, 240, 240}, dim = {150, 150, 150}, accent = {236, 236, 236}, onAccent = {14, 14, 14} }, Light = { bg = {236, 236, 244}, panel = {255, 255, 255}, text = {26, 26, 36}, dim = {104, 104, 126}, accent = {124, 77, 255}, onAccent = {255, 255, 255} }, } local function loadTheme() local name pcall(function() local id = tostring(Players.LocalPlayer.UserId) for _, f in ipairs({ "MuzzyHub/Appearance_" .. id .. ".json", "MuzzyHub_Appearance_" .. id .. ".json" }) do if isfile and isfile(f) then name = HttpService:JSONDecode(readfile(f)).theme break end end end) local t = THEMES[name] or THEMES.Classic local function c(v) return Color3.fromRGB(v[1], v[2], v[3]) end return { bg = c(t.bg), panel = c(t.panel), text = c(t.text), dim = c(t.dim), accent = c(t.accent), onAccent = c(t.onAccent) } end -- only one load at a time (double-clicking execute shouldn't spam the API) if genv.__MuzzyLoading then return end genv.__MuzzyLoading = true ---------------------------------------------------------------- small helpers local function trim(s) return tostring(s or ""):match("^%s*(.-)%s*$") or "" end local function parentGui(gui) pcall(function() gui.Parent = (gethui and gethui()) or game:GetService("CoreGui") end) if not gui.Parent then gui.Parent = Players.LocalPlayer:WaitForChild("PlayerGui") end end -- a message in the console AND a small banner at the top of the screen (the key is never printed) local function say(msg, bad) if bad then warn("[MuzzyHub] " .. msg) else print("[MuzzyHub] " .. msg) end task.spawn(function() pcall(function() local old = (gethui and gethui() or game:GetService("CoreGui")):FindFirstChild("MuzzyHubToast") if old then old:Destroy() end local TH = loadTheme() local g = Instance.new("ScreenGui") g.Name, g.ResetOnSpawn, g.DisplayOrder = "MuzzyHubToast", false, 2000 parentGui(g) local l = Instance.new("TextLabel") l.Size = UDim2.fromOffset(440, 48) l.Position = UDim2.new(0.5, -220, 0, 24) l.BackgroundColor3 = TH.bg l.TextColor3 = TH.text l.Font, l.TextSize, l.TextWrapped = Enum.Font.GothamMedium, 14, true l.Text = "MuzzyHub: " .. msg l.Parent = g Instance.new("UICorner", l).CornerRadius = UDim.new(0, 10) local s = Instance.new("UIStroke", l) s.Color, s.Thickness = bad and Color3.fromRGB(210, 70, 70) or TH.accent, 1.5 task.wait(8) g:Destroy() end) end) end -- a stable id for this device (the bot locks a key to the first device that uses it) local function getHwid() -- ClientId first: it's what the shop's other loader used, so keys already locked to a device keep working local ok, id = pcall(function() return game:GetService("RbxAnalyticsService"):GetClientId() end) if ok and id and tostring(id) ~= "" then return tostring(id) end ok, id = pcall(function() if gethwid then return gethwid() end end) if ok and id and tostring(id) ~= "" then return tostring(id) end return nil end ---------------------------------------------------------------- saved key local function readSavedKey() local ok, k = pcall(function() if isfile and readfile and isfile(KEY_FILE) then return readfile(KEY_FILE) end end) k = ok and trim(k) or "" return k ~= "" and k or nil end local function saveKey(k) if writefile then pcall(writefile, KEY_FILE, k) end end local function forgetKey() pcall(function() if delfile and isfile and isfile(KEY_FILE) then delfile(KEY_FILE) elseif writefile then writefile(KEY_FILE, "") end end) end -- the key box (shown only when no key is saved / given) local function askForKey() local TH = loadTheme() local ev = Instance.new("BindableEvent") local g = Instance.new("ScreenGui") g.Name, g.ResetOnSpawn, g.DisplayOrder = "MuzzyHubKey", false, 2000 parentGui(g) local f = Instance.new("Frame") f.Size, f.Position = UDim2.fromOffset(380, 160), UDim2.new(0.5, -190, 0.5, -80) f.BackgroundColor3, f.BorderSizePixel = TH.bg, 0 f.Parent = g Instance.new("UICorner", f).CornerRadius = UDim.new(0, 12) local st = Instance.new("UIStroke", f) st.Color, st.Thickness, st.Transparency = TH.accent, 1.5, 0.4 local title = Instance.new("TextLabel") title.Size, title.Position, title.BackgroundTransparency = UDim2.new(1, 0, 0, 40), UDim2.fromOffset(0, 6), 1 title.Text, title.TextColor3 = "MuzzyHub - enter your key", TH.text title.Font, title.TextSize = Enum.Font.GothamBold, 16 title.Parent = f local box = Instance.new("TextBox") box.Size, box.Position = UDim2.new(1, -40, 0, 36), UDim2.fromOffset(20, 52) box.BackgroundColor3, box.TextColor3 = TH.panel, TH.text box.PlaceholderText, box.PlaceholderColor3 = "MUZZY-XXXXXX-XXXXXX-XXXXXX", TH.dim box.Font, box.TextSize, box.Text, box.ClearTextOnFocus = Enum.Font.Gotham, 13, "", false box.Parent = f Instance.new("UICorner", box).CornerRadius = UDim.new(0, 8) local go = Instance.new("TextButton") go.Size, go.Position = UDim2.new(1, -40, 0, 36), UDim2.fromOffset(20, 104) go.BackgroundColor3, go.TextColor3 = TH.accent, TH.onAccent go.Text, go.Font, go.TextSize = "Continue", Enum.Font.GothamBold, 14 go.Parent = f Instance.new("UICorner", go).CornerRadius = UDim.new(0, 8) local x = Instance.new("TextButton") x.Size, x.Position = UDim2.fromOffset(26, 22), UDim2.new(1, -34, 0, 8) x.BackgroundColor3, x.TextColor3 = Color3.fromRGB(190, 55, 55), Color3.new(1, 1, 1) x.Text, x.Font, x.TextSize = "X", Enum.Font.GothamBold, 13 x.Parent = f Instance.new("UICorner", x).CornerRadius = UDim.new(0, 6) local function submit() local k = trim(box.Text) if k ~= "" then ev:Fire(k) end end go.MouseButton1Click:Connect(submit) box.FocusLost:Connect(function(enter) if enter then submit() end end) x.MouseButton1Click:Connect(function() ev:Fire(false) end) local k = ev.Event:Wait() g:Destroy() return k or nil end ---------------------------------------------------------------- talking to the bot -- POST /api/v1/load (key + hwid + place in a JSON body, so the key never ends up in a URL). -- Returns the HTTP status code and the response body. local function callLoad(key, hwid, place) local req = request or http_request or (syn and syn.request) or (http and http.request) if req then local ok, res = pcall(req, { Url = API .. "/api/v1/load", Method = "POST", Headers = { ["Content-Type"] = "application/json" }, Body = HttpService:JSONEncode({ key = key, hwid = hwid, place = place }), }) if ok and type(res) == "table" then return res.StatusCode, res.Body end return nil, tostring(res) end -- no request() in this executor: plain GET (we only learn "worked" or "failed") local q = "?key=" .. HttpService:UrlEncode(key) .. "&hwid=" .. HttpService:UrlEncode(hwid) .. "&place=" .. HttpService:UrlEncode(place) local ok, res = pcall(game.HttpGet, game, API .. "/api/v1/load" .. q) if ok then return 200, res end local code = tostring(res):match("(%d%d%d)") return code and tonumber(code) or nil, tostring(res) end -- what to tell the user for each failure reason from the bot local REASONS = { invalid_key = "That key isn't valid. Check you copied it exactly.", revoked = "That key has been revoked. Contact support in the Discord.", expired = "That key has expired. Renew it in the Discord.", hwid_mismatch = "This key is locked to another device. Use /mykey in the Discord to reset your device.", missing_hwid = "Couldn't read a device id from your executor.", rate_limited = "Slow down - too many requests. Try again in a minute.", server_error = "The key server had an error. Try again in a minute.", no_script_for_game = "This game isn't supported yet - suggest it in the Discord.", } ---------------------------------------------------------------- main local function main() local hwid = getHwid() if not hwid then say(REASONS.missing_hwid, true) return end -- where the key comes from: script_key (set before the loadstring line) > saved file > the key box local key = trim((getgenv and (getgenv().script_key or getgenv().SCRIPT_KEY)) or script_key or SCRIPT_KEY or "") local fromBox = false if key == "" then key = readSavedKey() or "" end if key == "" then key = askForKey() fromBox = true if not key then say("No key entered.", true) return end end local place = tostring(game.PlaceId) local status, body = callLoad(key, hwid, place) -- ONE call per execution (no retry loops: bad keys get blocked) if status == 200 and type(body) == "string" and body ~= "" then saveKey(key) -- remember a key that works -- let the game scripts re-run this loader after a rejoin (never printed anywhere) if getgenv then getgenv().MuzzyBootstrap = "script_key=" .. string.format("%q", key) .. "; loadstring(" .. string.format("%q", CORE_SRC) .. ")(" .. string.format("%q", CORE_SRC) .. ")" end local fn, err = loadstring(body) if not fn then say("The script failed to load: " .. tostring(err), true) return end say("Loaded.") local ok, e = pcall(fn) if not ok then say("The script errored: " .. tostring(e), true) end return end -- failures local reason if status == 429 then reason = "rate_limited" elseif status == 404 then reason = "no_script_for_game" else local ok, j = pcall(function() return HttpService:JSONDecode(body) end) reason = ok and type(j) == "table" and j.reason or nil end if reason == "invalid_key" or reason == "revoked" or reason == "expired" then forgetKey() end -- ask again next time say(REASONS[reason] or ("Couldn't load (code " .. tostring(status) .. "). Try again in a minute."), true) end local ok, err = pcall(main) genv.__MuzzyLoading = nil if not ok then warn("[MuzzyHub] loader error: " .. tostring(err)) end ]==] loadstring(CORE)(CORE)