function ZoneController.updateDetection(q)local R={enterDetection="\095\099\117\114\114\101\110\116\069\110\116\101\114\068\101\116\101\099\116\105\111\110";exitDetection="\095\099\117\114\114\101\110\116\069\120\105\116\068\101\116\101\099\116\105\111\110"}for R,Y in pairs(R)do local h=q[R]if h==enum.Detection.Automatic then if charactersTotalVolume>WHOLE_BODY_DETECTION_LIMIT then h=enum.Detection.Centre else h=enum.Detection.WholeBody end end q[Y]=h end end function ZoneController._formHeartbeat(q)local R=heartbeatConnections[q]if R then return end local Y=0 R=heartbeat:Connect(function()local R=os.clock()if R>=Y then local h local X for R,Y in pairs(activeZones)do if R.activeTriggers[q]then local q=R.accuracy if h==nil or q<h then h=q end ZoneController.updateDetection(R)local Y=R._currentEnterDetection if X==nil or Y<X then X=Y end end end local P=h local B=heartbeatActions[q](X)for R,Y in pairs(activeZones)do if R.activeTriggers[q]then local Y=R.accuracy local h=B[R]or{}local X=false for q,R in pairs(h)do X=true break end if X and Y>P then P=Y end R:_updateOccupants(q,h)end end local U=enum.Accuracy.getProperty(P)Y=R+U end end)heartbeatConnections[q]=R end function ZoneController._deregisterConnection(q,R)activeConnections-=1 if activeTriggers[R]==1 then activeTriggers[R]=nil local q=heartbeatConnections[R]if q then heartbeatConnections[R]=nil q:Disconnect()end else activeTriggers[R]-=1 end q.activeTriggers[R]=nil if dictLength(q.activeTriggers)==0 then activeZones[q]=nil ZoneController._updateZoneDetails()end if q.touchedConnectionActions[R]then q:_disconnectTouchedConnection(R)end end function ZoneController._updateZoneDetails()activeParts={}activePartToZone={}allParts={}allPartToZone={}activeZonesTotalVolume=0 for q,R in pairs(registeredZones)do local Y=activeZones[q]if Y then activeZonesTotalVolume+=q.volume end for R,h in pairs(q.groupParts)do if Y then table.insert(activeParts,h)activePartToZone[h]=q end table.insert(allParts,h)allPartToZone[h]=q end end end function ZoneController._getZonesAndPlayers(q,R,Y,h)local X=R if not X then for q,R in pairs(q)do X+=q.volume end end local P={}if charactersTotalVolume<X then for q,R in pairs(players:GetPlayers())do local X=ZoneController.getTouchingZones(R,Y,h)for q,h in pairs(X)do if not Y or h.activeTriggers.player then fillOccupants(P,h,R)end end end else for q,R in pairs(q)do if not Y or q.activeTriggers.player then local R=workspace:FindPartsInRegion3WithWhiteList(q.region,bodyParts,#bodyParts)local Y={}for q,R in pairs(R)do local h=R.Parent.Name if not Y[h]then Y[h]=players:GetPlayerFromCharacter(R.Parent)end end for R,Y in pairs(Y)do if Y and q:findPlayer(Y)then fillOccupants(P,q,Y)end end end end end return P end

function ZoneController.updateDetection(zone)
	local detectionTypes = {
		["enterDetection"] = "_currentEnterDetection",
		["exitDetection"] = "_currentExitDetection",
	}
	for detectionType, currentDetectionName in pairs(detectionTypes) do
		local detection = zone[detectionType]
		if detection == enum.Detection.Automatic then
			if charactersTotalVolume > WHOLE_BODY_DETECTION_LIMIT then
				detection = enum.Detection.Centre
			else
				detection = enum.Detection.WholeBody
			end
		end
		zone[currentDetectionName] = detection
	end
end

function ZoneController._formHeartbeat(registeredTriggerType)
	local heartbeatConnection = heartbeatConnections[registeredTriggerType]
	if heartbeatConnection then return end
	-- This will only ever connect once per triggerType per server
	-- This means instead of initiating a loop per-zone we can handle everything within
	-- a singular connection. This is particularly beneficial for player-orinetated
	-- raycasting, where a raycast only needs to be cast once per interval, as apposed
	-- to every zone per interval
	-- I utilise heartbeat with os.clock() to provide precision (where needed) and flexibility
	local nextCheck = 0
	heartbeatConnection = heartbeat:Connect(function()
		local clockTime = os.clock()
		if clockTime >= nextCheck then
			local lowestAccuracy
			local lowestDetection
			for zone, _ in pairs(activeZones) do
				if zone.activeTriggers[registeredTriggerType] then
					local zAccuracy = zone.accuracy
					if lowestAccuracy == nil or zAccuracy < lowestAccuracy then
						lowestAccuracy = zAccuracy
					end
					ZoneController.updateDetection(zone)
					local zDetection = zone._currentEnterDetection
					if lowestDetection == nil or zDetection < lowestDetection then
						lowestDetection = zDetection
					end
				end
			end
			local highestAccuracy = lowestAccuracy
			local zonesAndOccupants = heartbeatActions[registeredTriggerType](lowestDetection)
			for zone, _ in pairs(activeZones) do
				if zone.activeTriggers[registeredTriggerType] then
					local zAccuracy = zone.accuracy
					local occupantsDict = zonesAndOccupants[zone] or {}
					local occupantsPresent = false
					for k,v in pairs(occupantsDict) do
						occupantsPresent = true
						break
					end
					if occupantsPresent and zAccuracy > highestAccuracy then
						highestAccuracy = zAccuracy
					end
					zone:_updateOccupants(registeredTriggerType, occupantsDict)
				end
			end
			----
			local cooldown = enum.Accuracy.getProperty(highestAccuracy)
			nextCheck = clockTime + cooldown
			----
		end
	end)
	heartbeatConnections[registeredTriggerType] = heartbeatConnection
end

function ZoneController._deregisterConnection(registeredZone, registeredTriggerType)
	activeConnections -= 1
	if activeTriggers[registeredTriggerType] == 1 then
		activeTriggers[registeredTriggerType] = nil
		local heartbeatConnection = heartbeatConnections[registeredTriggerType]
		if heartbeatConnection then
			heartbeatConnections[registeredTriggerType] = nil
			heartbeatConnection:Disconnect()
		end
	else
		activeTriggers[registeredTriggerType] -= 1
	end
	registeredZone.activeTriggers[registeredTriggerType] = nil
	if dictLength(registeredZone.activeTriggers) == 0 then
		activeZones[registeredZone] = nil
		ZoneController._updateZoneDetails()
	end
	if registeredZone.touchedConnectionActions[registeredTriggerType] then
		registeredZone:_disconnectTouchedConnection(registeredTriggerType)
	end
end

function ZoneController._updateZoneDetails()
	activeParts = {}
	activePartToZone = {}
	allParts = {}
	allPartToZone = {}
	activeZonesTotalVolume = 0
	for zone, _ in pairs(registeredZones) do
		local isActive = activeZones[zone]
		if isActive then
			activeZonesTotalVolume += zone.volume
		end
		for _, zonePart in pairs(zone.groupParts) do
			if isActive then
				table.insert(activeParts, zonePart)
				activePartToZone[zonePart] = zone
			end
			table.insert(allParts, zonePart)
			allPartToZone[zonePart] = zone
		end
	end
end

function ZoneController._getZonesAndPlayers(zonesDictToCheck, zoneCustomVolume, onlyActiveZones, recommendedDetection)
	local totalZoneVolume = zoneCustomVolume
	if not totalZoneVolume then
		for zone, _ in pairs(zonesDictToCheck) do
			totalZoneVolume += zone.volume
		end
	end
	local zonesAndOccupants = {}
	if charactersTotalVolume < totalZoneVolume then
		-- If the volume of all *characters* within the server is *less than* the total
		-- volume of all active zones (i.e. zones which listen for .playerEntered)
		-- then it's more efficient cast regions and rays within each character and
		-- then determine the zones they belong to
		for _, plr in pairs(players:GetPlayers()) do
			local touchingZones = ZoneController.getTouchingZones(plr, onlyActiveZones, recommendedDetection)
			for _, zone in pairs(touchingZones) do
				if not onlyActiveZones or zone.activeTriggers["player"] then
					fillOccupants(zonesAndOccupants, zone, plr)
				end
			end
		end
	else
		-- If the volume of all *active zones* within the server is *less than* the total
		-- volume of all characters, then it's more efficient to perform the region and raycast
		-- checks directly within each zone to determine players inside
		for zone, _ in pairs(zonesDictToCheck) do
			if not onlyActiveZones or zone.activeTriggers["player"] then
				local result = workspace:FindPartsInRegion3WithWhiteList(zone.region, bodyParts, #bodyParts)
				local playersDict = {}
				for _, bodyPart in pairs(result) do
					local parentName = bodyPart.Parent.Name
					if not playersDict[parentName] then
						playersDict[parentName] = players:GetPlayerFromCharacter(bodyPart.Parent)
					end
				end
				for _, plr in pairs(playersDict) do
					if plr and zone:findPlayer(plr) then
						fillOccupants(zonesAndOccupants, zone, plr)
					end
				end
			end
		end
	end
	return zonesAndOccupants
end


