local C={AutoSaveProfiles=30,RobloxWriteCooldown=7;ForceLoadMaxSteps=8;AssumeDeadSessionLock=1800;IssueCountForCriticalState=5;IssueLast=120,CriticalStateLast=120,MetaTagsUpdatedValues={ProfileCreateTime=true,SessionLoadCount=true,ActiveSession=true;ForceLoadSession=true,LastUpdate=true}}local l do local C={}local x={}function x.Disconnect(C)local l=C._listener if l~=nil then local x=C._script_signal local p=x._fire_pointer_stack local j=x._listeners_next local v=x._listeners_back for C=1,x._stack_count,1 do if p[C]==l then p[C]=j[l]end end if x._tail_listener==l then local C=v[l]if C~=nil then j[C]=nil v[l]=nil else x._head_listener=nil end x._tail_listener=C elseif x._head_listener==l then local C=j[l]v[C]=nil j[l]=nil x._head_listener=C else local C=j[l]local x=v[l]if C~=nil or x~=nil then j[x]=C v[C]=x j[l]=nil v[l]=nil end end C._listener=nil x._listener_count-=1 end if C._disconnect_listener~=nil then C._disconnect_listener(C._disconnect_param)C._disconnect_listener=nil end end local p={}function p.Connect(j,C,l,p)if type(C)~="\102\117\110\099\116\105\111\110"then error("\091\077\097\100\119\111\114\107\083\099\114\105\112\116\083\105\103\110\097\108\093\058 \079\110\108\121 \102\117\110\099\116\105\111\110\115 \099\097\110 \098\101 \112\097\115\115\101\100 \116\111 \083\099\114\105\112\116\083\105\103\110\097\108\058\067\111\110\110\101\099\116\040\041")end local v=j._tail_listener if v==nil then j._head_listener=C j._tail_listener=C j._listener_count+=1 elseif v~=C and j._listeners_next[C]==nil then j._listeners_next[v]=C j._listeners_back[C]=v j._tail_listener=C j._listener_count+=1 end return{_listener=C,_script_signal=j,_disconnect_listener=l,_disconnect_param=p;Disconnect=x.Disconnect}end function p.GetListenerCount(C)return C._listener_count end function p.Fire(C,...)local l=C._fire_pointer_stack local x=C._stack_count+1 C._stack_count=x local p=C._listeners_next l[x]=C._head_listener while true do local C=l[x]l[x]=p[C]if C~=nil then(coroutine.wrap(C))(...)else break end end C._stack_count-=1 end function p.FireUntil(l,C,...)local x=l._fire_pointer_stack local p=l._stack_count+1 l._stack_count=p local j=l._listeners_next x[p]=l._head_listener while true do local l=x[p]x[p]=j[l]if l~=nil then(coroutine.wrap(l))(...)if C()~=true then x[p]=nil break end else break end end l._stack_count-=1 end function C.NewScriptSignal()return{_fire_pointer_stack={},_stack_count=0,_listener_count=0,_listeners_next={};_listeners_back={},_head_listener=nil;_tail_listener=nil,Connect=p.Connect,GetListenerCount=p.GetListenerCount;Fire=p.Fire;FireUntil=p.FireUntil}end local j=game:GetService("\082\117\110\083\101\114\118\105\099\101")local v=j.Heartbeat l={NewScriptSignal=C.NewScriptSignal;HeartbeatWait=function(C)if C==nil or C==0 then return v:Wait()else local l=0 while l<=C do local C=v:Wait()l=l+C end return l end end;ConnectToOnClose=function(C,l)if(game:GetService("\082\117\110\083\101\114\118\105\099\101")):IsStudio()==false or l==true then game:BindToClose(C)end end}end


local SETTINGS = {

	AutoSaveProfiles = 30, -- Seconds (This value may vary - ProfileService will split the auto save load evenly in the given time)
	RobloxWriteCooldown = 7, -- Seconds between successive DataStore calls for the same key
	ForceLoadMaxSteps = 8, -- Steps taken before ForceLoad request steals the active session for a profile
	AssumeDeadSessionLock = 30 * 60, -- (seconds) If a profile hasn't been updated for 30 minutes, assume the session lock is dead
		-- As of writing, os.time() is not completely reliable, so we can only assume session locks are dead after a significant amount of time.
	
	IssueCountForCriticalState = 5, -- Issues to collect to announce critical state
	IssueLast = 120, -- Seconds
	CriticalStateLast = 120, -- Seconds
	
	MetaTagsUpdatedValues = { -- Technical stuff - do not alter
		ProfileCreateTime = true,
		SessionLoadCount = true,
		ActiveSession = true,
		ForceLoadSession = true,
		LastUpdate = true,
	}
	
}

local Madwork -- Standalone Madwork reference for portable version of ProfileService
do

	local MadworkScriptSignal = {}
	
	local ScriptConnection = {}
	
	function ScriptConnection:Disconnect()
		local listener = self._listener
		if listener ~= nil then
			local script_signal = self._script_signal
			local fire_pointer_stack = script_signal._fire_pointer_stack
			local listeners_next = script_signal._listeners_next
			local listeners_back = script_signal._listeners_back
			-- Check fire pointers:
			for i = 1, script_signal._stack_count do
				if fire_pointer_stack[i] == listener then
					fire_pointer_stack[i] = listeners_next[listener]
				end
			end
			-- Remove listener:
			if script_signal._tail_listener == listener then
				local new_tail = listeners_back[listener]
				if new_tail ~= nil then
					listeners_next[new_tail] = nil
					listeners_back[listener] = nil
				else
					script_signal._head_listener = nil -- tail was also head
				end
				script_signal._tail_listener = new_tail
			elseif script_signal._head_listener == listener then
				-- If this listener is not the tail, assume another listener is the tail:
				local new_head = listeners_next[listener]
				listeners_back[new_head] = nil
				listeners_next[listener] = nil
				script_signal._head_listener = new_head
			else
				local next_listener = listeners_next[listener]
				local back_listener = listeners_back[listener]
				if next_listener ~= nil or back_listener ~= nil then -- Catch cases when duplicate listeners are disconnected
					listeners_next[back_listener] = next_listener
					listeners_back[next_listener] = back_listener
					listeners_next[listener] = nil
					listeners_back[listener] = nil
				end
			end
			self._listener = nil
			script_signal._listener_count -= 1
		end
		if self._disconnect_listener ~= nil then
			self._disconnect_listener(self._disconnect_param)
			self._disconnect_listener = nil
		end
	end
	
	local ScriptSignal = {}
	
	function ScriptSignal:Connect(listener, disconnect_listener, disconnect_param) --> [ScriptConnection]
		if type(listener) ~= "function" then
			error("[MadworkScriptSignal]: Only functions can be passed to ScriptSignal:Connect()")
		end
		local tail_listener = self._tail_listener
		if tail_listener == nil then
			self._head_listener = listener
			self._tail_listener = listener
			self._listener_count += 1
		elseif tail_listener ~= listener and self._listeners_next[listener] == nil then -- Prevent connecting the same listener more than once
			self._listeners_next[tail_listener] = listener
			self._listeners_back[listener] = tail_listener
			self._tail_listener = listener
			self._listener_count += 1
		end
		return {
			_listener = listener,
			_script_signal = self,
			_disconnect_listener = disconnect_listener,
			_disconnect_param = disconnect_param,
			Disconnect = ScriptConnection.Disconnect
		}
	end
	
	function ScriptSignal:GetListenerCount()
		return self._listener_count
	end
	
	function ScriptSignal:Fire(...)
		local fire_pointer_stack = self._fire_pointer_stack
		local stack_id = self._stack_count + 1
		self._stack_count = stack_id
		
		local listeners_next = self._listeners_next
		fire_pointer_stack[stack_id] = self._head_listener
		while true do
			local pointer = fire_pointer_stack[stack_id]
			fire_pointer_stack[stack_id] = listeners_next[pointer]
			if pointer ~= nil then
				coroutine.wrap(pointer)(...)
			else
				break
			end
		end
		self._stack_count -= 1
	end

	function ScriptSignal:FireUntil(continue_callback, ...)
		local fire_pointer_stack = self._fire_pointer_stack
		local stack_id = self._stack_count + 1
		self._stack_count = stack_id
	
		local listeners_next = self._listeners_next
		fire_pointer_stack[stack_id] = self._head_listener
		while true do
			local pointer = fire_pointer_stack[stack_id]
			fire_pointer_stack[stack_id] = listeners_next[pointer]
			if pointer ~= nil then
				coroutine.wrap(pointer)(...)
				if continue_callback() ~= true then
					fire_pointer_stack[stack_id] = nil
					break
				end
			else
				break
			end
		end
		self._stack_count -= 1
	end
	
	function MadworkScriptSignal.NewScriptSignal() --> [ScriptSignal]
		return {
			_fire_pointer_stack = {},
			_stack_count = 0,
			_listener_count = 0,
			_listeners_next = {},
			_listeners_back = {},
			_head_listener = nil,
			_tail_listener = nil,
			Connect = ScriptSignal.Connect,
			GetListenerCount = ScriptSignal.GetListenerCount,
			Fire = ScriptSignal.Fire,
			FireUntil = ScriptSignal.FireUntil,
		}
	end
	
	local RunService = game:GetService("RunService")
	local Heartbeat = RunService.Heartbeat
	
	Madwork = {
		NewScriptSignal = MadworkScriptSignal.NewScriptSignal,
		HeartbeatWait = function(wait_time) --> time_elapsed
			if wait_time == nil or wait_time == 0 then
				return Heartbeat:Wait()
			else
				local time_elapsed = 0
				while time_elapsed <= wait_time do
					local time_waited = Heartbeat:Wait()
					time_elapsed = time_elapsed + time_waited
				end
				return time_elapsed
			end
		end,
		ConnectToOnClose = function(task, run_in_studio_mode)
			if game:GetService("RunService"):IsStudio() == false or run_in_studio_mode == true then
				game:BindToClose(task)
			end
		end,
	}
end
