function DataStore.SaveAsync(o)return(Promise.async(function(M,U)if not o.valueUpdated then M(false)return end if RunService:IsStudio()and not SaveInStudio then warn(("\068\097\116\097 \115\116\111\114\101 \037\115 \097\116\116\101\109\112\116\101\100 \116\111 \115\097\118\101 \105\110 \115\116\117\100\105\111 \119\104\105\108\101 \083\097\118\101\073\110\083\116\117\100\105\111 \105\115 \102\097\108\115\101\046"):format(o.Name))if not SaveInStudioObject then warn("\089\111\117 \099\097\110 \115\101\116 \116\104\101 \118\097\108\117\101 \111\102 \116\104\105\115 \098\121 \099\114\101\097\116\105\110\103 \097 \066\111\111\108\086\097\108\117\101 \110\097\109\101\100 \083\097\118\101\073\110\083\116\117\100\105\111 \105\110 \083\101\114\118\101\114\083\116\111\114\097\103\101\046")end M(false)return end if o.backup then warn("\084\104\105\115 \100\097\116\097 \115\116\111\114\101 \105\115 \097 \098\097\099\107\117\112 \115\116\111\114\101\044 \097\110\100 \116\104\117\115 \119\105\108\108 \110\111\116 \098\101 \115\097\118\101\100\046")M(false)return end if o.value~=nil then local k=clone(o.value)if o.beforeSave then local M,v=pcall(o.beforeSave,k,o)if M then k=v else U(v,Constants.SaveFailure.BeforeSaveError)return end end local v=Verifier.testValidity(k)if v then U(v,Constants.SaveFailure.InvalidData)return end return(o.savingMethod:Set(k)):andThen(function()M(true,k)end)end end)):andThen(function(M,U)if M then for M,k in pairs(o.afterSave)do local v,q=pcall(k,U,o)if not v then end end o.valueUpdated=false end end)end function DataStore.BindToClose(M,o)table.insert(M.bindToClose,o)end function DataStore.GetKeyValue(M,o)return(M.value or{})[o]end function DataStore.SetKeyValue(U,o,M)if not U.value then U.value=U:Get({})end U.value[o]=M end local o={}do function o.BeforeInitialGet(M,o)M.combinedBeforeInitialGet=o end function o.BeforeSave(M,o)M.combinedBeforeSave=o end function o.Get(U,o,M)local k=U.combinedStore:Get({})local v=k[U.combinedName]if not M then if v==nil then v=o else if U.combinedBeforeInitialGet and not U.combinedInitialGot then v=U.combinedBeforeInitialGet(v)end end end U.combinedInitialGot=true k[U.combinedName]=clone(v)U.combinedStore:Set(k,true)return clone(v)end function o.Set(U,o,M)local k=U.combinedStore:GetTable({})k[U.combinedName]=o U.combinedStore:Set(k,M)U:_Update(M)end function o.Update(M,o)M:Set(o(M:Get()))M:_Update()end function o.Save(o)o.combinedStore:Save()end function o.OnUpdate(M,o)if not M.onUpdateCallbacks then M.onUpdateCallbacks={o}else M.onUpdateCallbacks[#M.onUpdateCallbacks+1]=o end end function o._Update(M,o)if not o then for o,U in pairs(M.onUpdateCallbacks or{})do U(M:Get(),M)end end M.combinedStore:_Update(true)end function o.SetBackup(M,o)M.combinedStore:SetBackup(o)end end local M={}M.__index=DataStore
--[[**
	<description>
	Asynchronously saves the data to the data store.
	</description>
**--]]
function DataStore:SaveAsync()
	return Promise.async(function(resolve, reject)
		if not self.valueUpdated then
			--   warn(("Data store %s was not saved as it was not updated."):format(self.Name))
			resolve(false)
			return
		end

		if RunService:IsStudio() and not SaveInStudio then
			warn(("Data store %s attempted to save in studio while SaveInStudio is false."):format(self.Name))
			if not SaveInStudioObject then
				warn("You can set the value of this by creating a BoolValue named SaveInStudio in ServerStorage.")
			end
			resolve(false)
			return
		end

		if self.backup then
			warn("This data store is a backup store, and thus will not be saved.")
			resolve(false)
			return
		end

		if self.value ~= nil then
			local save = clone(self.value)

			if self.beforeSave then
				local success, result = pcall(self.beforeSave, save, self)

				if success then
					save = result
				else
					reject(result, Constants.SaveFailure.BeforeSaveError)
					return
				end
			end

			local problem = Verifier.testValidity(save)
			if problem then
				reject(problem, Constants.SaveFailure.InvalidData)
				return
			end

			return self.savingMethod:Set(save):andThen(function()
				resolve(true, save)
			end)
		end
	end):andThen(function(saved, save)
		if saved then
			for _, afterSave in pairs(self.afterSave) do
				local success, err = pcall(afterSave, save, self)

				if not success then
					--	warn("Error on AfterSave: "..err)
				end
			end

			self.valueUpdated = false
		end
	end)
end

function DataStore:BindToClose(callback)
	table.insert(self.bindToClose, callback)
end

function DataStore:GetKeyValue(key)
	return (self.value or {})[key]
end

function DataStore:SetKeyValue(key, newValue)
	if not self.value then
		self.value = self:Get({})
	end

	self.value[key] = newValue
end

local CombinedDataStore = {}

do
	function CombinedDataStore:BeforeInitialGet(modifier)
		self.combinedBeforeInitialGet = modifier
	end

	function CombinedDataStore:BeforeSave(modifier)
		self.combinedBeforeSave = modifier
	end

	function CombinedDataStore:Get(defaultValue, dontAttemptGet)
		local tableResult = self.combinedStore:Get({})
		local tableValue = tableResult[self.combinedName]

		if not dontAttemptGet then
			if tableValue == nil then
				tableValue = defaultValue
			else
				if self.combinedBeforeInitialGet and not self.combinedInitialGot then
					tableValue = self.combinedBeforeInitialGet(tableValue)
				end
			end
		end

		self.combinedInitialGot = true
		tableResult[self.combinedName] = clone(tableValue)
		self.combinedStore:Set(tableResult, true)
		return clone(tableValue)
	end

	function CombinedDataStore:Set(value, dontCallOnUpdate)
		local tableResult = self.combinedStore:GetTable({})
		tableResult[self.combinedName] = value
		self.combinedStore:Set(tableResult, dontCallOnUpdate)
		self:_Update(dontCallOnUpdate)
	end

	function CombinedDataStore:Update(updateFunc)
		self:Set(updateFunc(self:Get()))
		self:_Update()
	end

	function CombinedDataStore:Save()
		self.combinedStore:Save()
	end

	function CombinedDataStore:OnUpdate(callback)
		if not self.onUpdateCallbacks then
			self.onUpdateCallbacks = { callback }
		else
			self.onUpdateCallbacks[#self.onUpdateCallbacks + 1] = callback
		end
	end

	function CombinedDataStore:_Update(dontCallOnUpdate)
		if not dontCallOnUpdate then
			for _, callback in pairs(self.onUpdateCallbacks or {}) do
				callback(self:Get(), self)
			end
		end

		self.combinedStore:_Update(true)
	end

	function CombinedDataStore:SetBackup(retries)
		self.combinedStore:SetBackup(retries)
	end
end

local DataStoreMetatable = {}

DataStoreMetatable.__index = DataStore
