--[[ FUFU CORE - remote loader Owner / Developer: Fufu Usage (any executor exposing loadstring + HttpGet): loadstring(game:HttpGet("https://fufu-core.pages.dev"))() This file is what that endpoint serves. It stays tiny and stable: the hub itself lives in manifest.lua + src/, so releases never require a new loadstring. Optional configuration, set BEFORE running the loader: getgenv().FUFU_CORE_OPTIONS = { BaseUrl = nil, -- load from another host serving the same tree, must end with "/" PinVersion = nil, -- e.g. "1.0.0": refuse to start if the remote version differs NoCache = false, -- never fall back to the on-disk module cache Debug = false, -- verbose logging } The loader only bootstraps: it resolves the repository, downloads the manifest and the module manager, then hands over to src/Core/Bootstrap.lua. ]] local LOADER_VERSION = 4 -- Hosting endpoints, tried in order; the first one that serves manifest.lua wins and -- is used for the whole session. Every endpoint serves the same file tree -- (manifest.lua, src/..., scripts/...). To add a custom domain, put it first -- (tools/build-site.mjs can also inject it at build time, see docs/DEPLOYMENT.md): -- { Name = "script.fufucore.de", Url = "https://script.fufucore.de/" }, local ENDPOINTS = { { Name = "fufu-core.pages.dev", Url = "https://fufu-core.pages.dev/" }, { Name = "cloudflare", Url = "https://fufu-core.pages.dev/" }, } local TAG = "[FUFU CORE]" local genv = (typeof(getgenv) == "function" and getgenv()) or _G local options = type(genv.FUFU_CORE_OPTIONS) == "table" and genv.FUFU_CORE_OPTIONS or {} local startedAt = os.clock() local stage = "Starting" local function log(...) print(TAG, ...) end local function setStage(name) stage = name if options.Debug then log(string.format("stage: %s (+%.2fs)", name, os.clock() - startedAt)) end end -- Surfaces a failure both in the console and on screen. Never swallowed silently. local function fail(message) genv.FUFU_CORE_LOADING = nil local text = string.format("Load failed during '%s': %s", stage, tostring(message)) genv.FUFU_CORE_STATUS = { Ok = false, Stage = stage, Error = tostring(message), LoaderVersion = LOADER_VERSION } warn(TAG, text) pcall(function() game:GetService("StarterGui"):SetCore("SendNotification", { Title = "FUFU CORE - load failed", Text = text:sub(1, 180), Duration = 15, }) end) return nil, text end --------------------------------------------------------------------------------------- -- HTTP --------------------------------------------------------------------------------------- local function httpGet(url) if type(options.Fetch) == "function" then return options.Fetch(url) end local okGet, body = pcall(function() return game:HttpGet(url, true) end) if okGet and type(body) == "string" then return body end local req = (typeof(request) == "function" and request) or (typeof(http_request) == "function" and http_request) if req then local okReq, res = pcall(req, { Url = url, Method = "GET" }) if okReq and type(res) == "table" then if res.StatusCode == 200 and type(res.Body) == "string" then return res.Body end error("HTTP " .. tostring(res.StatusCode), 0) end end error(tostring(body), 0) end -- Classifies a response body. Returns nil when it is usable, otherwise a reason. -- Some executors return "" (or the host's error page) for a failed request instead -- of raising an error, so "the call succeeded" is never taken as "we got the file". local function invalidReason(body) if type(body) ~= "string" then return "no response body (" .. typeof(body) .. ")" end if #body == 0 or not body:find("%S") then return "empty response (0 bytes): the host answered without content - usually a missing, private or suspended repository that the executor reports as success" end local head = body:sub(1, 200):lower() if head:match("^%s*404: not found") or head:match("^%s*not found") then return "404 (file not found on the host)" end if head:match("^%s* %s", candidate.Name, tostring(err))) end if not baseUrl then return fail("could not download manifest.lua (" .. table.concat(errors, "; ") .. ")") end setStage("Reading manifest") local manifestChunk, compileError = loadstring(manifestSource, "=FUFU/manifest") if not manifestChunk then return fail("manifest.lua does not compile: " .. tostring(compileError)) end local okManifest, manifest = pcall(manifestChunk) if not okManifest or type(manifest) ~= "table" or type(manifest.Modules) ~= "table" then return fail("manifest.lua is invalid: " .. tostring(manifest)) end if type(manifest.MinLoader) == "number" and manifest.MinLoader > LOADER_VERSION then return fail(string.format("this loader (v%d) is too old for hub %s; re-copy the loadstring.", LOADER_VERSION, tostring(manifest.Version))) end if options.PinVersion and options.PinVersion ~= manifest.Version then return fail(string.format("version pinned to %s but the repository serves %s.", tostring(options.PinVersion), tostring(manifest.Version))) end -- Shared context handed to every module as `...`. local Hub = { Name = manifest.Name or "FUFU CORE", Version = manifest.Version or "0.0.0", Build = manifest.Build, Manifest = manifest, BaseUrl = baseUrl, Ref = ref, -- name of the endpoint that served this session CacheKey = tostring(manifest.Build or manifest.Version or "0"):gsub("[^%w%.%-_]", "-"), Env = genv, Options = options, StartedAt = startedAt, LoaderVersion = LOADER_VERSION, fetch = fetch, setStage = setStage, } setStage("Loading module manager") local managerSource, managerError = fetch(baseUrl .. "src/Core/ModuleManager.lua?v=" .. Hub.CacheKey) if not managerSource then return fail("module manager unavailable: " .. tostring(managerError)) end local managerChunk, managerCompileError = loadstring(managerSource, "=FUFU/Core/ModuleManager") if not managerChunk then return fail("module manager does not compile: " .. tostring(managerCompileError)) end local okManager, Modules = pcall(managerChunk, Hub) if not okManager or type(Modules) ~= "table" then return fail("module manager failed to start: " .. tostring(Modules)) end Hub.Modules = Modules Hub.import = Modules.import setStage("Downloading modules") local okPreload, missing = Modules.preload(manifest.Modules) if not okPreload then local names = {} for _, item in ipairs(missing) do table.insert(names, string.format("%s (%s)", item.Path, item.Error)) end return fail("missing modules: " .. table.concat(names, ", ")) end setStage("Bootstrap") local okImport, Bootstrap = pcall(Modules.import, "Core/Bootstrap") if not okImport then return fail(Bootstrap) end local okStart, startError = xpcall(Bootstrap.start, function(err) return tostring(err) .. "\n" .. debug.traceback() end) if not okStart then if type(Hub.Unload) == "function" then pcall(Hub.Unload, "bootstrap failure") end return fail(startError) end -- "No error" is not the same as "initialised": confirm the hub is really there. setStage("Verifying interface") local window = Hub.Window local gui = window and window.Gui if genv.FUFU_CORE == nil or Hub.Unloaded then return fail("bootstrap finished but the hub is not registered") end if typeof(gui) ~= "Instance" or gui.Parent == nil or typeof(window.Root) ~= "Instance" then pcall(Hub.Unload, "interface missing") return fail("bootstrap finished but the interface was not created") end local pageCount = 0 for _ in pairs(window.Pages) do pageCount += 1 end if pageCount == 0 then pcall(Hub.Unload, "no pages") return fail("bootstrap finished but no page was built") end genv.FUFU_CORE_LOADING = nil genv.FUFU_CORE_STATUS = { Ok = true, Stage = "Ready", Version = Hub.Version, Build = Hub.Build, Source = ref, Modules = #manifest.Modules, Pages = pageCount, Seconds = os.clock() - startedAt, LoaderVersion = LOADER_VERSION, } log(string.format("v%s ready in %.2fs - %d modules, %d pages, interface visible (source: %s)", Hub.Version, os.clock() - startedAt, #manifest.Modules, pageCount, tostring(ref))) return genv.FUFU_CORE end local ok, result, message = xpcall(main, function(err) return tostring(err) .. "\n" .. debug.traceback() end) if not ok then return fail(result) end return result, message