local e={}local M=require(((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\076\117\097\116\114\105")):WaitForChild("\115\101\114\118\105\099\101\115"))local v=require(M.replicatedStorage.luatri_config)local B=require(M.replicatedStorage.states)local w=require(M.replicatedStorage.warns)local b=workspace:WaitForChild("\073\110\116\101\114\105\111\114\115",math.huge)local Y={}local f={}local C={}local y=true function e.setModelVisibility(e,M)M=not M for e,v in pairs(e:GetDescendants())do if v:IsA("\066\097\115\101\080\097\114\116")then if f[v]==nil then f[v]=v.Transparency end v.Transparency=M and f[v]or 1 v.CanCollide=M end end end function e.setFolderVisibility(M,v)for M,B in pairs(M:GetChildren())do if B.Name~="\099\117\108\108\066\114\117\115\104"then if B:IsA("\077\111\100\101\108")then e.setModelVisibility(B,v)elseif B:IsA("\066\097\115\101\080\097\114\116")then if f[B]==nil then f[B]=B.Transparency end B.Transparency=v and f[B]or 1 B.CanCollide=v end end end end function e.setup()for e,M in pairs(b:GetChildren())do local v=M:FindFirstChild("\099\117\108\108\066\114\117\115\104")if v and v:IsA("\066\097\115\101\080\097\114\116")then local e=v.Size/2 local B=v.Position-e local w=v.Position+e table.insert(Y,{minPos=B;maxPos=w,folder=M;part=v})else if M then warn(w[1]..(" \102\111\114 "..tostring(M)))else warn(w[2])end end end end function e.isCameraInRegion(e,M)local v=B.camPos return v.X>=e.X and(v.X<=M.X and(v.Y>=e.Y and(v.Y<=M.Y and(v.Z>=e.Z and v.Z<=M.Z))))end function e.showAllItems()for M,v in pairs(Y)do e.setFolderVisibility(v.folder,true)end C={}end function e.cullFolder(M)e.setFolderVisibility(M,false)C[M]=true end function e.restoreFolderVisibility(M)e.setFolderVisibility(M,true)C[M]=nil end function e.updateCulling()local M={}local v={}for B,w in pairs(Y)do local b=w.minPos local Y=w.maxPos local f=w.folder if e.isCameraInRegion(b,Y)then if not C[f]then M[f]=true end else if C[f]then v[f]=true end end end for M in pairs(M)do e.cullFolder(M)end for M in pairs(v)do e.restoreFolderVisibility(M)end end function e.onHeartbeat()if v.InteriorCulling~=y then y=v.InteriorCulling if not y then e.showAllItems()end end if y then e.updateCulling()end end return e
local interior = {}

local svc = require(game:GetService("ReplicatedStorage"):WaitForChild("Luatri"):WaitForChild("services"))
local cfg = require(svc.replicatedStorage.luatri_config)
local state = require(svc.replicatedStorage.states)
local wrn = require(svc.replicatedStorage.warns)

local interiorFolder = workspace:WaitForChild("Interiors",math.huge)

local cullRegions = {}
local initialTransparencyMap = {}
local activeCullFolders = {}
local cullingEnabled = true

function interior.setModelVisibility(model, visible)
	visible = not visible
	for _, descendant in pairs(model:GetDescendants()) do
		if descendant:IsA("BasePart") then
			if initialTransparencyMap[descendant] == nil then
				initialTransparencyMap[descendant] = descendant.Transparency
			end
			descendant.Transparency = visible and initialTransparencyMap[descendant] or 1
			descendant.CanCollide = visible
		end
	end
end

function interior.setFolderVisibility(folder, visible)
	for _, item in pairs(folder:GetChildren()) do
		if item.Name ~= "cullBrush" then
			if item:IsA("Model") then
				interior.setModelVisibility(item, visible)
			elseif item:IsA("BasePart") then
				if initialTransparencyMap[item] == nil then
					initialTransparencyMap[item] = item.Transparency
				end
				item.Transparency = visible and initialTransparencyMap[item] or 1
				item.CanCollide = visible
			end
		end
	end
end

function interior.setup()
	for _, folder in pairs(interiorFolder:GetChildren()) do
		local cullBrush = folder:FindFirstChild("cullBrush")
		if cullBrush and cullBrush:IsA("BasePart") then
			local size = cullBrush.Size / 2
			local minPos = cullBrush.Position - size
			local maxPos = cullBrush.Position + size
			table.insert(cullRegions, {
				minPos = minPos,
				maxPos = maxPos,
				folder = folder,
				part = cullBrush,
			})
		else
			if folder then
				warn(wrn[1] .. " for " .. tostring(folder))
			else
				warn(wrn[2])
			end
		end
	end
end

function interior.isCameraInRegion(minPos, maxPos) -- todo: get rid of this crap
	local camPos = state.camPos
	return camPos.X >= minPos.X
		and camPos.X <= maxPos.X
		and camPos.Y >= minPos.Y
		and camPos.Y <= maxPos.Y
		and camPos.Z >= minPos.Z
		and camPos.Z <= maxPos.Z
end

function interior.showAllItems()
	for _, data in pairs(cullRegions) do
		interior.setFolderVisibility(data.folder, true)
	end
	activeCullFolders = {}
end

function interior.cullFolder(folder)
	interior.setFolderVisibility(folder, false)
	activeCullFolders[folder] = true
end

function interior.restoreFolderVisibility(folder)
	interior.setFolderVisibility(folder, true)
	activeCullFolders[folder] = nil
end

function interior.updateCulling()
	local foldersToCull = {}
	local foldersToUncull = {}
	for _, data in pairs(cullRegions) do
		local minPos = data.minPos
		local maxPos = data.maxPos
		local folder = data.folder
		if interior.isCameraInRegion(minPos, maxPos) then
			if not activeCullFolders[folder] then
				foldersToCull[folder] = true
			end
		else
			if activeCullFolders[folder] then
				foldersToUncull[folder] = true
			end
		end
	end
	for folder in pairs(foldersToCull) do
		interior.cullFolder(folder)
	end
	for folder in pairs(foldersToUncull) do
		interior.restoreFolderVisibility(folder)
	end
end
function interior.onHeartbeat()
	if cfg.InteriorCulling ~= cullingEnabled then
		cullingEnabled = cfg.InteriorCulling
		if not cullingEnabled then
			interior.showAllItems()
		end
	end
	if cullingEnabled then
		interior.updateCulling()
	end
end

return interior
