function API.GetDataStore(Y,i,M)assert(type(i)=="\115\116\114\105\110\103","\068\097\116\097\083\116\111\114\101 \110\097\109\101 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103\059 \103\111\116"..type(i))assert(type(M)=="\115\116\114\105\110\103"or M==nil,"\068\097\116\097\083\116\111\114\101 \115\099\111\112\101 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103\059 \103\111\116"..type(M))M=M or"\103\108\111\098\097\108"if allStores[M]and allStores[M][i]then return allStores[M][i]end local U={}local X={}local C={}function X.SetAsync(Y,i,M)assert(M~=nil,"\086\097\108\117\101 \099\097\110\110\111\116 \098\101 \110\105\108")U[i]=M if C[i]then for i,Y in pairs(C[i])do spawn(function()Y(M)end)end end end function X.UpdateAsync(Y,i,M)local X=M(U[i])assert(X~=nil,"\086\097\108\117\101 \099\097\110\110\111\116 \098\101 \110\105\108")U[i]=X if C[i]then for i,M in pairs(C[i])do spawn(function()M(X)end)end end end function X.GetAsync(M,i)return U[i]end function X.RemoveAsync(M,i)U[i]=nil if C[i]then for i,M in pairs(C[i])do spawn(function()M(nil)end)end end end function X.IncrementAsync(Y,i,M)if M==nil then M=1 end assert(type(M)=="\110\117\109\098\101\114","\067\097\110 \111\110\108\121 \105\110\099\114\101\109\101\110\116 \110\117\109\098\101\114\115")Y:UpdateAsync(i,function(i)if i==nil then return i end assert(type(i)=="\110\117\109\098\101\114","\067\097\110 \111\110\108\121 \105\110\099\114\101\109\101\110\116 \110\117\109\098\101\114\115")return i+M end)end function X.OnUpdate(Y,i,M)assert(type(M)=="\102\117\110\099\116\105\111\110","\085\112\100\097\116\101 \102\117\110\099\116\105\111\110 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \102\117\110\099\116\105\111\110")if not C[i]then C[i]={M}else table.insert(C[i],M)end end if not allStores[M]then allStores[M]={}end allStores[M][i]=X return X end function API.GetGlobalDataStore(i)return i:GetDataStore("\103\108\111\098\097\108","\103\108\111\098\097\108")end function API.GetOrderedDataStore(Y,i,M)local U=Y:GetDataStore(i,M)local X={}local C={}function C.GetAsync(M,i)return U:GetAsync(i)end function C.SetAsync(Y,i,M)assert(type(M)=="\110\117\109\098\101\114","\086\097\108\117\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")U:SetAsync(i,M)X[i]=M end function C.UpdateAsync(Y,i,M)U:UpdateAsync(i,function(Y)local U=M(Y)assert(type(U)=="\110\117\109\098\101\114","\086\097\108\117\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")X[i]=U return U end)end function C.IncrementAsync(Y,i,M)U:IncrementAsync(i,M)X[i]=(X[i]or 0)+M end function C.RemoveAsync(M,i)U:RemoveAsync(i)X[i]=nil end function C.GetSortedAsync(C,i,M,Y,U)assert(type(M)=="\110\117\109\098\101\114"and math.floor(M)>0,"\080\097\103\101\083\105\122\101 \109\117\115\116 \098\101 \097\110 \105\110\116\101\103\101\114 \097\110\100 \103\114\101\097\116\101\114 \116\104\097\110 \048")assert(Y==nil or type(Y)=="\110\117\109\098\101\114","\077\105\110\086\097\108\117\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")assert(U==nil or type(U)=="\110\117\109\098\101\114","\077\097\120\086\097\108\117\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")if Y and U then assert(Y<=U,"\077\105\110\086\097\108\117\101 \109\117\115\116 \098\101 \108\101\115\115 \111\114 \101\113\117\097\108 \116\111 \077\097\120\086\097\108\117\101")end local I={}for i,M in pairs(X)do local X=(not Y or M>=Y)and(not U or M<=U)if X then table.insert(I,{key=i,value=M})end end table.sort(I,i and function(i,M)return i.value<M.value end or function(i,M)return M.value<i.value end)M=math.floor(M)local a={IsFinished=false}for i,Y in pairs(I)do local U=math.ceil(i/M)local X=a[U]if not X then X={}a[U]=X end local C=(i-1)%M+1 X[C]=Y end do local i=1 function a.GetCurrentPage(M)return M[i]end function a.AdvanceToNextPageAsync(M)local Y=#a if i<Y then i=i+1 end M.IsFinished=i>=Y end end return a end return C end function API.GetRequestBudgetForRequestType(M,i)return realDataStoreService:GetRequestBudgetForRequestType(i)end
-----------------------------------------------------------------------------------------------------------
-- API:

function API:GetDataStore(name, scope)
	assert(type(name) == "string", "DataStore name must be a string; got" .. type(name))
	assert(type(scope) == "string" or scope == nil, "DataStore scope must be a string; got" .. type(scope))
	scope = (scope or "global")
	if allStores[scope] and allStores[scope][name] then
		return allStores[scope][name]
	end
	local data = {}
	local d = {}
	local updateListeners = {}
	function d:SetAsync(k, v)
		assert(v ~= nil, "Value cannot be nil")
		data[k] = v
		if updateListeners[k] then
			for _, f in pairs(updateListeners[k]) do
				spawn(function()
					f(v)
				end)
			end
		end
	end
	function d:UpdateAsync(k, func)
		local v = func(data[k])
		assert(v ~= nil, "Value cannot be nil")
		data[k] = v
		if updateListeners[k] then
			for _, f in pairs(updateListeners[k]) do
				spawn(function()
					f(v)
				end)
			end
		end
	end
	function d:GetAsync(k)
		return data[k]
	end
	function d:RemoveAsync(k)
		data[k] = nil
		if updateListeners[k] then
			for _, f in pairs(updateListeners[k]) do
				spawn(function()
					f(nil)
				end)
			end
		end
	end
	function d:IncrementAsync(k, delta)
		if delta == nil then
			delta = 1
		end
		assert(type(delta) == "number", "Can only increment numbers")
		self:UpdateAsync(k, function(num)
			if num == nil then
				return num
			end
			assert(type(num) == "number", "Can only increment numbers")
			return (num + delta)
		end)
	end
	function d:OnUpdate(k, onUpdateFunc)
		assert(type(onUpdateFunc) == "function", "Update function argument must be a function")
		if not updateListeners[k] then
			updateListeners[k] = { onUpdateFunc }
		else
			table.insert(updateListeners[k], onUpdateFunc)
		end
	end
	if not allStores[scope] then
		allStores[scope] = {}
	end
	allStores[scope][name] = d
	return d
end

function API:GetGlobalDataStore()
	return self:GetDataStore("global", "global")
end

function API:GetOrderedDataStore(name, scope)
	local dataStore = self:GetDataStore(name, scope)
	local allData = {}
	local d = {}
	function d:GetAsync(k)
		return dataStore:GetAsync(k)
	end
	function d:SetAsync(k, v)
		assert(type(v) == "number", "Value must be a number")
		dataStore:SetAsync(k, v)
		allData[k] = v
	end
	function d:UpdateAsync(k, func)
		dataStore:UpdateAsync(k, function(oldValue)
			local v = func(oldValue)
			assert(type(v) == "number", "Value must be a number")
			allData[k] = v
			return v
		end)
	end
	function d:IncrementAsync(k, delta)
		dataStore:IncrementAsync(k, delta)
		allData[k] = ((allData[k] or 0) + delta)
	end
	function d:RemoveAsync(k)
		dataStore:RemoveAsync(k)
		allData[k] = nil
	end
	function d:GetSortedAsync(isAscending, pageSize, minValue, maxValue)
		assert(
			type(pageSize) == "number" and math.floor(pageSize) > 0,
			"PageSize must be an integer and greater than 0"
		)
		assert(minValue == nil or type(minValue) == "number", "MinValue must be a number")
		assert(maxValue == nil or type(maxValue) == "number", "MaxValue must be a number")
		if minValue and maxValue then
			assert(minValue <= maxValue, "MinValue must be less or equal to MaxValue")
		end
		local data = {}
		for k, v in pairs(allData) do
			local pass = ((not minValue or v >= minValue) and (not maxValue or v <= maxValue))
			if pass then
				table.insert(data, { key = k, value = v })
			end
		end
		table.sort(data, (isAscending and function(a, b)
			return (a.value < b.value)
		end or function(a, b)
			return (b.value < a.value)
		end))
		pageSize = math.floor(pageSize)
		local pages = { IsFinished = false }
		for i, v in pairs(data) do
			local pageNum = math.ceil(i / pageSize)
			local page = pages[pageNum]
			if not page then
				page = {}
				pages[pageNum] = page
			end
			local index = (((i - 1) % pageSize) + 1)
			page[index] = v
		end
		do
			local currentPage = 1
			function pages:GetCurrentPage()
				return self[currentPage]
			end
			function pages:AdvanceToNextPageAsync()
				local numPages = #pages
				if currentPage < numPages then
					currentPage = (currentPage + 1)
				end
				self.IsFinished = (currentPage >= numPages)
			end
		end
		return pages
	end
	return d
end

function API:GetRequestBudgetForRequestType(requestType)
	return realDataStoreService:GetRequestBudgetForRequestType(requestType)
end
