local D=game:GetService("\068\097\116\097\083\116\111\114\101\083\101\114\118\105\099\101")local p={}p.__index=p function p.createDefault(D)local p p=function(D,n)for D,I in pairs(D)do n[D]=typeof(I)=="\116\097\098\108\101"and p(I)or I end end return D.template and p(D.template)end function p.validate(n,D,p)return D end function p.cache(n,D,p)n.entries[D]={value=p;updated=false}end function p.save(p,D)local n=p.entries[D]if not n or not n.updated then return end p.dataStore:UpdateAsync(function(D)return p:validate(n.value,D)end)end function p.retrieve(p,D)local n=p.entries[D]if n then return n.value end local I=p.dataStore:GetAsync(D)or p:createDefault()return p:cacheEntry(D,I)end function p.update(n,D,p)local I=n:retrieve(D)I.value=n:validate(p,I.level)end function p.remove(p,D)p.entries[D]=nil p.dataStore:RemoveAsync(D)end function p.new(n)local I={}setmetatable(I,p)I.name=n I.dataStore=D:GetDataStore(n)I.entries={}I.template=nil return I end return p
-- OptimisticSide
-- 5/8/2021
-- Data store wrapper

local DataStoreService = game:GetService("DataStoreService")

local DataStore = {}
DataStore.__index = DataStore

-- Create a default entry based on
-- template.
function DataStore:createDefault()
	local deepCopy
	deepCopy = function(from, to)
		for index, value in pairs(from) do
			to[index] = typeof(value) == "table" and deepCopy(value) or value
		end
	end

	-- Create a deep copy of
	-- the given template.
	return self.template and deepCopy(self.template)
end

-- Default entry validation procedure.
function DataStore:validate(new, old)
	-- This is just a placeholder function.
	-- You should redefine this function
	-- with whatever you need to do here.
	return new
end

-- Cache an entry in the data store.
function DataStore:cache(key, value)
	self.entries[key] = {
		value = value,
		updated = false
	}
end

-- Forces the update of a cached entry.
function DataStore:save(key)
	-- Ensure entry is existent
	-- and has been updated.
	local entry = self.entries[key]
	if not entry or not entry.updated then
		return
	end

	-- Update the entry.
	self.dataStore:UpdateAsync(function(old)
		return self:validate(entry.value, old)
	end)
end

-- Retrieve an entry in the data store.
function DataStore:retrieve(key)
	-- If entry already cached, return that.
	local cached = self.entries[key]
	if cached then
		return cached.value
	end

	-- Load data from data store.
	local data = self.dataStore:GetAsync(key) or self:createDefault()
	return self:cacheEntry(key, data)
end

-- Update an entry.
-- If not cached, load it from data store.
function DataStore:update(key, value)
	-- Retrieve entry and update it.
	local entry = self:retrieve(key)
	entry.value = self:validate(value, entry.level)
end

-- Remove an entry.
function DataStore:remove(key)
	-- Removals are pushed to data store
	-- immediately.
	self.entries[key] = nil
	self.dataStore:RemoveAsync(key)
end

-- Create datastore object.
function DataStore.new(name)
	local self = {}
	setmetatable(self, DataStore)

	self.name = name
	self.dataStore = DataStoreService:GetDataStore(name)
	self.entries = {}
	self.template = nil

	return self
end

return DataStore
