function DataStore.Get(C,l,V)if V then return C.value end local x=0 if not C.haveValue then while not C.haveValue do local l,V=(C:_GetRaw()):await()if not l then if C.backupRetries then x=x+1 if x>=C.backupRetries then C.backup=true C.haveValue=true C.value=C.backupValue break end end C:Debug("\071\101\116 \114\101\116\117\114\110\101\100 \101\114\114\111\114\058",V)end end if C.value~=nil then for l,V in pairs(C.beforeInitialGet)do C.value=V(C.value,C)end end end local G if C.value==nil and l~=nil then G=l else G=C.value end G=clone(G)C.value=G return G end function DataStore.GetAsync(l,...)local V={...}return Promise.async(function(C)C(l:Get(unpack(V)))end)end function DataStore.GetTable(V,l,...)local C,x=(V:GetTableAsync(l,...)):await()if not C then error(x)end return x end function DataStore.GetTableAsync(V,l,...)assert(l~=nil,"\089\111\117 \109\117\115\116 \112\114\111\118\105\100\101 \097 \100\101\102\097\117\108\116 \118\097\108\117\101\046")return(V:GetAsync(l,...)):andThen(function(C)local x=false assert(typeof(C)=="\116\097\098\108\101","\058\071\101\116\084\097\098\108\101\047\058\071\101\116\084\097\098\108\101\065\115\121\110\099 \119\097\115 \117\115\101\100 \119\104\101\110 \116\104\101 \118\097\108\117\101 \105\110 \116\104\101 \100\097\116\097 \115\116\111\114\101 \105\115\110\'\116 \097 \116\097\098\108\101\046")for l,V in pairs(l)do if C[l]==nil then C[l]=V x=true end end if x then V:Set(C)end return C end)end function DataStore.Set(C,l,V)C.value=clone(l)C:_Update(V)end function DataStore.Update(V,l)V.value=l(V.value)V:_Update()end function DataStore.Increment(C,l,V)C:Set(C:Get(V)+l)end function DataStore.IncrementAsync(C,l,V)(C:GetAsync(V)):andThen(function(V)C:Set(V+l)end)end function DataStore.OnUpdate(V,l)table.insert(V.callbacks,l)end function DataStore.BeforeInitialGet(V,l)table.insert(V.beforeInitialGet,l)end function DataStore.BeforeSave(V,l)V.beforeSave=l end function DataStore.AfterSave(V,l)table.insert(V.afterSave,l)end


function DataStore:Get(defaultValue, dontAttemptGet)
	if dontAttemptGet then
		return self.value
	end

	local backupCount = 0

	if not self.haveValue then
		while not self.haveValue do
			local success, error = self:_GetRaw():await()

			if not success then
				if self.backupRetries then
					backupCount = backupCount + 1

					if backupCount >= self.backupRetries then
						self.backup = true
						self.haveValue = true
						self.value = self.backupValue
						break
					end
				end

				self:Debug("Get returned error:", error)
			end
		end

		if self.value ~= nil then
			for _,modifier in pairs(self.beforeInitialGet) do
				self.value = modifier(self.value, self)
			end
		end
	end

	local value

	if self.value == nil and defaultValue ~= nil then --not using "not" because false is a possible value
		value = defaultValue
	else
		value = self.value
	end

	value = clone(value)

	self.value = value

	return value
end

function DataStore:GetAsync(...)
	local args = { ... }
	return Promise.async(function(resolve)
		resolve(self:Get(unpack(args)))
	end)
end

function DataStore:GetTable(default, ...)
	local success, result = self:GetTableAsync(default, ...):await()
	if not success then
		error(result)
	end
	return result
end

function DataStore:GetTableAsync(default, ...)
	assert(default ~= nil, "You must provide a default value.")

	return self:GetAsync(default, ...):andThen(function(result)
		local changed = false
		assert(
			typeof(result) == "table",
			":GetTable/:GetTableAsync was used when the value in the data store isn't a table."
		)

		for defaultKey, defaultValue in pairs(default) do
			if result[defaultKey] == nil then
				result[defaultKey] = defaultValue
				changed = true
			end
		end

		if changed then
			self:Set(result)
		end

		return result
	end)
end

function DataStore:Set(value, _dontCallOnUpdate)
	self.value = clone(value)
	self:_Update(_dontCallOnUpdate)
end

function DataStore:Update(updateFunc)
	self.value = updateFunc(self.value)
	self:_Update()
end

function DataStore:Increment(value, defaultValue)
	self:Set(self:Get(defaultValue) + value)
end

function DataStore:IncrementAsync(add, defaultValue)
	self:GetAsync(defaultValue):andThen(function(value)
		self:Set(value + add)
	end)
end

function DataStore:OnUpdate(callback)
	table.insert(self.callbacks, callback)
end

function DataStore:BeforeInitialGet(modifier)
	table.insert(self.beforeInitialGet, modifier)
end

function DataStore:BeforeSave(modifier)
	self.beforeSave = modifier
end

function DataStore:AfterSave(callback)
	table.insert(self.afterSave, callback)
end
