local s=script.Parent local u=require(script.Parent.ScriptInfoUtils)local X=require(script.Parent.LoaderUtils)local x=require(script.Parent.BounceTemplateUtils)local y={}y.ClassName="\083\116\097\116\105\099\076\101\103\097\099\121\076\111\097\100\101\114"y.__index=y function y.new()local s=setmetatable({_packageLookups={}},y)return s end function y.__call(u,s)return u:Require(s)end function y.Lock(s)error("\067\097\110\110\111\116 \115\116\097\114\116 \108\111\097\100\101\114 \119\104\105\108\101 \110\111\116 \114\117\110\110\105\110\103")end function y.Require(X,s,u)if type(u)=="\110\117\109\098\101\114"then return require(u)elseif type(u)=="\115\116\114\105\110\103"then local x=X:_findModule(s,u)if x then X:_ensureFakeLoader(x)return require(x)else error("\069\114\114\111\114\058 \076\105\098\114\097\114\121 \'"..(tostring(u).."\' \100\111\101\115 \110\111\116 \101\120\105\115\116\046"),2)end elseif typeof(u)=="\073\110\115\116\097\110\099\101"and u:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then return require(u)else error(("\069\114\114\111\114\058 \109\111\100\117\108\101 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103 \111\114 \077\111\100\117\108\101\083\099\114\105\112\116\044 \103\111\116 \'\037\115\' \102\111\114 \'\037\115\'"):format(typeof(u),tostring(u)))end end function y._findModule(x,s,X)assert(typeof(s)=="\073\110\115\116\097\110\099\101","\066\097\100 \114\111\111\116")assert(type(X)=="\115\116\114\105\110\103","\066\097\100 \110\097\109\101")local y=x:_findPackageRoot(s)while y do local s=x:_getOrCreateLookup(y)if s[X]then return s[X]end local t=y:FindFirstChild(u.DEPENDENCY_FOLDER_NAME)if t then for s,u in pairs(t:GetChildren())do if u:IsA("\070\111\108\100\101\114")and u.Name:sub(1,1)=="\064"then for s,u in pairs(u:GetChildren())do local y=x:_getPackageFolderLookup(u)if y[X]then return y[X]end end else local s=x:_getPackageFolderLookup(u)if s[X]then return s[X]end end end end y=x:_findPackageRoot(y)end return nil end function y.GetLoader(u,s)assert(typeof(s)=="\073\110\115\116\097\110\099\101","\066\097\100 \109\111\100\117\108\101\083\099\114\105\112\116")return setmetatable({},{__call=function(X,x)return u:Require(s,x)end;__index=function(X,x)return u:Require(s,x)end})end function y._getPackageFolderLookup(u,s)if s:IsA("\079\098\106\101\099\116\086\097\108\117\101")then if s.Value then return u:_getOrCreateLookup(s.Value)else warn("\091\083\116\097\116\105\099\076\101\103\097\099\121\076\111\097\100\101\114\093 - \066\097\100 \108\105\110\107 \105\110 \112\097\099\107\097\103\101\070\111\108\100\101\114")return{}end elseif s:IsA("\070\111\108\100\101\114")or s:IsA("\067\097\109\101\114\097")then return u:_getOrCreateLookup(s)elseif s:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then return u:_getOrCreateLookup(s)else warn(("\085\110\107\110\111\119\110 \105\110\115\116\097\110\099\101 \037\113 \040\037\115\041 \105\110 \100\101\112\101\110\100\101\110\099\121\070\111\108\100\101\114 - \037\113"):format(s.Name,s.ClassName,s:GetFullName()))return{}end end function y._getOrCreateLookup(u,s)assert(typeof(s)=="\073\110\115\116\097\110\099\101","\066\097\100 \112\097\099\107\097\103\101\070\111\108\100\101\114\079\114\077\111\100\117\108\101\083\099\114\105\112\116")if u._packageLookups[s]then return u._packageLookups[s]end local X={}u:_buildLookup(X,s)u._packageLookups[s]=X return X end function y._buildLookup(x,s,X)if X:IsA("\070\111\108\100\101\114")or X:IsA("\067\097\109\101\114\097")then if X.Name~=u.DEPENDENCY_FOLDER_NAME then for u,X in pairs(X:GetChildren())do x:_buildLookup(s,X)end end elseif X:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then s[X.Name]=X end end function y._findPackageRoot(u,s)assert(typeof(s)=="\073\110\115\116\097\110\099\101","\066\097\100 \105\110\115\116\097\110\099\101")local x=s.Parent while x and x~=game do if X.isPackage(x)then return x elseif u:_couldBePackageRootTopLevel(x)then return x else x=x.Parent end end return nil end function y._couldBePackageRootTopLevel(u,s)for s,u in pairs(s:GetChildren())do if u:IsA("\070\111\108\100\101\114")and u.Name:sub(1,1)=="\064"then for s,u in pairs(u:GetChildren())do if X.isPackage(u)then return true end end end end return true end function y._ensureFakeLoader(X,u)assert(typeof(u)=="\073\110\115\116\097\110\099\101","\066\097\100 \109\111\100\117\108\101")local y=u.Parent if not y then warn("\091\083\116\097\116\105\099\076\101\103\097\099\121\076\111\097\100\101\114\093 - \078\111 \112\097\114\101\110\116")return end local t=Load and true or false local W=y:FindFirstChild("\108\111\097\100\101\114")if W then if x.isBounceTemplate(W)then W.Archivable=t end return end local l=x.create(s,"\108\111\097\100\101\114")l.Archivable=t l.Parent=y end return y


local loader = script.Parent
local ScriptInfoUtils = require(script.Parent.ScriptInfoUtils)
local LoaderUtils = require(script.Parent.LoaderUtils)
local BounceTemplateUtils = require(script.Parent.BounceTemplateUtils)

local StaticLegacyLoader = {}
StaticLegacyLoader.ClassName = "StaticLegacyLoader"
StaticLegacyLoader.__index = StaticLegacyLoader

function StaticLegacyLoader.new()
	local self = setmetatable({
		_packageLookups = {};
	}, StaticLegacyLoader)

	return self
end

function StaticLegacyLoader:__call(value)
	return self:Require(value)
end

function StaticLegacyLoader:Lock()
	error("Cannot start loader while not running")
end

function StaticLegacyLoader:Require(root, value)
	if type(value) == "number" then
		return require(value)
	elseif type(value) == "string" then
		-- use very slow module recovery mechanism
		local module = self:_findModule(root, value)
		if module then
			self:_ensureFakeLoader(module)
			return require(module)
		else
			error("Error: Library '" .. tostring(value) .. "' does not exist.", 2)
		end
	elseif typeof(value) == "Instance" and value:IsA("ModuleScript") then
		return require(value)
	else
		error(("Error: module must be a string or ModuleScript, got '%s' for '%s'")
			:format(typeof(value), tostring(value)))
	end
end

function StaticLegacyLoader:_findModule(root, name)
	assert(typeof(root) == "Instance", "Bad root")
	assert(type(name) == "string", "Bad name")

	-- Implement the node_modules recursive find algorithm
	local packageRoot = self:_findPackageRoot(root)
	while packageRoot do
		-- Build lookup
		local highLevelLookup = self:_getOrCreateLookup(packageRoot)
		if highLevelLookup[name] then
			return highLevelLookup[name]
		end

		-- Ok, search our package dependencies
		local dependencies = packageRoot:FindFirstChild(ScriptInfoUtils.DEPENDENCY_FOLDER_NAME)
		if dependencies then
			for _, instance in pairs(dependencies:GetChildren()) do
				if instance:IsA("Folder") and instance.Name:sub(1, 1) == "@" then
					for _, child in pairs(instance:GetChildren()) do
						local lookup = self:_getPackageFolderLookup(child)
						if lookup[name] then
							return lookup[name]
						end
					end
				else
					local lookup = self:_getPackageFolderLookup(instance)
					if lookup[name] then
						return lookup[name]
					end
				end
			end
		end

		-- We failed to find anything... search up a level...
		packageRoot = self:_findPackageRoot(packageRoot)
	end

	return nil
end

function StaticLegacyLoader:GetLoader(moduleScript)
	assert(typeof(moduleScript) == "Instance", "Bad moduleScript")

	return setmetatable({}, {
		__call = function(_self, value)
			return self:Require(moduleScript, value)
		end;
		__index = function(_self, key)
			return self:Require(moduleScript, key)
		end;
	})
end

function StaticLegacyLoader:_getPackageFolderLookup(instance)
	if instance:IsA("ObjectValue") then
		if instance.Value then
			return self:_getOrCreateLookup(instance.Value)
		else
			warn("[StaticLegacyLoader] - Bad link in packageFolder")
			return {}
		end
	elseif instance:IsA("Folder") or instance:IsA("Camera") then
		return self:_getOrCreateLookup(instance)
	elseif instance:IsA("ModuleScript") then
		return self:_getOrCreateLookup(instance)
	else
		warn(("Unknown instance %q (%s) in dependencyFolder - %q")
			:format(instance.Name, instance.ClassName, instance:GetFullName()))
		return {}
	end
end

function StaticLegacyLoader:_getOrCreateLookup(packageFolderOrModuleScript)
	assert(typeof(packageFolderOrModuleScript) == "Instance", "Bad packageFolderOrModuleScript")

	if self._packageLookups[packageFolderOrModuleScript] then
		return self._packageLookups[packageFolderOrModuleScript]
	end

	local lookup = {}

	self:_buildLookup(lookup, packageFolderOrModuleScript)

	self._packageLookups[packageFolderOrModuleScript] = lookup
	return lookup
end

function StaticLegacyLoader:_buildLookup(lookup, instance)
	if instance:IsA("Folder") or instance:IsA("Camera") then
		if instance.Name ~= ScriptInfoUtils.DEPENDENCY_FOLDER_NAME then
			for _, item in pairs(instance:GetChildren()) do
				self:_buildLookup(lookup, item)
			end
		end
	elseif instance:IsA("ModuleScript") then
		lookup[instance.Name] = instance
	end
end

function StaticLegacyLoader:_findPackageRoot(instance)
	assert(typeof(instance) == "Instance", "Bad instance")

	local current = instance.Parent

	while current and current ~= game do
		if LoaderUtils.isPackage(current) then
			return current
		elseif self:_couldBePackageRootTopLevel(current) then
			return current
		else
			current = current.Parent
		end
	end

	return nil
end

function StaticLegacyLoader:_couldBePackageRootTopLevel(current)
	for _, instance in pairs(current:GetChildren()) do
		if instance:IsA("Folder") and instance.Name:sub(1, 1) == "@" then
			for _, item in pairs(instance:GetChildren()) do
				if LoaderUtils.isPackage(item) then
					return true
				end
			end
		end
	end

	return true
end

function StaticLegacyLoader:_ensureFakeLoader(module)
	assert(typeof(module) == "Instance", "Bad module")

	local parent = module.Parent
	if not parent then
		warn("[StaticLegacyLoader] - No parent")
		return
	end

	-- NexusUnitTest
	-- luacheck: ignore
	-- selene: allow(undefined_variable)
	local shouldBeArchivable = Load and true or false

	-- Already have link
	local found = parent:FindFirstChild("loader")
	if found then
		if BounceTemplateUtils.isBounceTemplate(found) then
			found.Archivable = shouldBeArchivable
		end

		return
	end

	local link = BounceTemplateUtils.create(loader, "loader")
	link.Archivable = shouldBeArchivable
	link.Parent = parent
end

return StaticLegacyLoader
