local A={}A.RetryCount=5 A.Cache={}A.Events={}A.Current={}A.Internal={Fire="\070\105\114\101";Hook="\072\111\111\107"}local M=setmetatable({},{__index=function(A,M)A[M]=game:GetService(M)return A[M]end})local J=script.Parent local F=require(J:WaitForChild("\077\115\103\083\101\114\118\105\099\101"))local k=require(J:WaitForChild("\077\097\110\097\103\101\114"))local P=M.RunService:IsStudio()local O=M.RunService:IsServer()local d=M.RunService:IsClient()local function U(A)local M=type(A)local J if M=="\116\097\098\108\101"then J={}for A,M in next,A,nil do J[U(A)]=U(M)end setmetatable(J,U(getmetatable(A)))else J=A end return J end function A.SetDefault(M,J)if M~=nil and J~=nil then A.Cache[M]=J end end function A.Clear(O,J,F,P)assert(typeof(J)=="\115\116\114\105\110\103","\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \075\101\121 \'\115\116\114\105\110\103\' \101\120\112\101\099\116\101\100\044 \103\111\116 \'"..(typeof(J).."\'"))assert(F~=nil,"\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \073\110\100\101\120 \101\120\112\101\099\116\101\100\044 \103\111\116 \'"..(typeof(F).."\'"))table.insert(A.Current,F)local d=M.DataStoreService:GetDataStore(J,F)local U=0 local h,q=nil,nil repeat h,q=pcall(function()d:RemoveAsync(J..("\058"..F))end)if not h then k.wait(6)U=U+1 end until h or U==A.RetryCount table.remove(A.Current,table.find(A.Current,F))return h end function A.Save(O,J,F,P)assert(typeof(J)=="\115\116\114\105\110\103","\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \075\101\121 \'\115\116\114\105\110\103\' \101\120\112\101\099\116\101\100\044 \103\111\116 \'"..(typeof(J).."\'"))assert(F~=nil,"\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \073\110\100\101\120 \101\120\112\101\099\116\101\100\044 \103\111\116 \'"..(typeof(F).."\'"))assert(typeof(P)=="\116\097\098\108\101"or P==nil,"\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \068\097\116\097 \'\116\097\098\108\101\' \111\114 \'\100\105\099\116\105\111\110\097\114\121\' \101\120\112\101\099\116\101\100\044 \103\111\116 \'"..(typeof(P).."\'"))if table.find(A.Current,F)then return end table.insert(A.Current,F)if P==nil or P.___PlayingCards then local O=M.DataStoreService:GetDataStore(J,F)local d=0 local U,h=nil,nil repeat U,h=pcall(function()O:UpdateAsync(J..("\058"..F),function()return P end)end)if not U then k.wait(6)d=d+1 end until U or d==A.RetryCount table.remove(A.Current,table.find(A.Current,F))return U end table.remove(A.Current,table.find(A.Current,F))warn("\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \070\097\105\108\101\100 \116\111 \115\097\118\101",F,"\111\110 \107\101\121",J)return false end function A.Load(k,J,F)assert(typeof(J)=="\115\116\114\105\110\103","\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \075\101\121 \'\115\116\114\105\110\103\' \101\120\112\101\099\116\101\100\044 \103\111\116 \'"..(typeof(J).."\'"))assert(F~=nil,"\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \073\110\100\101\120 \101\120\112\101\099\116\101\100\044 \103\111\116 \'"..(typeof(F).."\'"))if table.find(A.Current,F)then return end table.insert(A.Current,F)if A.Cache[J]then local k={}local P=M.DataStoreService:GetDataStore(J,F)local O,d=pcall(function()k=P:GetAsync(J..("\058"..F))end)table.remove(A.Current,table.find(A.Current,F))if not O then k=U(A.Cache[J])k.___PlayingCards=false return k,false end if k==nil then k=U(A.Cache[J])k.___PlayingCards=true return k,true end k.___PlayingCards=true return k,true end table.remove(A.Current,table.find(A.Current,F))warn("\091\068\073\067\069 \068\065\084\065\083\084\079\082\069\093\058 \070\097\105\108\101\100 \116\111 \108\111\097\100",F,"\111\110 \107\101\121",J)return false end return A
--[[
	@Author: Gavin "Mullets" Rosenthal
	@Desc: the internal for saving/loading/clearing
--]]

--// logic
local Methods = {}
Methods.RetryCount = 5
Methods.Cache = {}
Methods.Events = {}
Methods.Current = {}
Methods.Internal = {
	['Fire'] = 'Fire';
	['Hook'] = 'Hook';
}

--// services
local Services = setmetatable({}, {__index = function(cache, serviceName)
    cache[serviceName] = game:GetService(serviceName)
    return cache[serviceName]
end})

--// variables
local Modules = script.Parent
local MsgService = require(Modules:WaitForChild('MsgService'))
local Manager = require(Modules:WaitForChild('Manager'))

local IsStudio = Services['RunService']:IsStudio()
local IsServer = Services['RunService']:IsServer()
local IsClient = Services['RunService']:IsClient()

--// functions
local function DeepCopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[DeepCopy(orig_key)] = DeepCopy(orig_value)
        end
        setmetatable(copy, DeepCopy(getmetatable(orig)))
    else
        copy = orig
    end
    return copy
end

function Methods.SetDefault(key,data)
	if key ~= nil and data ~= nil then
		Methods.Cache[key] = data
	end
end

function Methods:Clear(key,index,data)
	assert(typeof(key) == 'string',"[DICE DATASTORE]: Key 'string' expected, got '".. typeof(key) .."'")
	assert(index ~= nil,"[DICE DATASTORE]: Index expected, got '".. typeof(index) .."'")
	table.insert(Methods.Current,index)	
	
	local datastore = Services['DataStoreService']:GetDataStore(key,index)
	local retry = 0
	local success,err = nil,nil
	repeat
		success,err = pcall(function()
			datastore:RemoveAsync(key..':'..index)
		end)
		
		if not success then
			Manager.wait(6)
			retry = retry + 1
		end
	until success or retry == Methods.RetryCount
	
	table.remove(Methods.Current,table.find(Methods.Current,index))
	return success
end

function Methods:Save(key,index,data)
	assert(typeof(key) == 'string',"[DICE DATASTORE]: Key 'string' expected, got '".. typeof(key) .."'")
	assert(index ~= nil,"[DICE DATASTORE]: Index expected, got '".. typeof(index) .."'")
	assert(typeof(data) == 'table' or data == nil,"[DICE DATASTORE]: Data 'table' or 'dictionary' expected, got '".. typeof(data) .."'")
	if table.find(Methods.Current,index) then return end
	table.insert(Methods.Current,index)
	
	if data == nil or data['___PlayingCards'] then
		local datastore = Services['DataStoreService']:GetDataStore(key,index)
		local retry = 0
		local success,err = nil,nil
		repeat
			success,err = pcall(function()
				datastore:UpdateAsync(key..':'..index,function()
					return data
				end)
			end)
			if not success then
				Manager.wait(6)
				retry = retry + 1
			end
		until success or retry == Methods.RetryCount
		
		table.remove(Methods.Current,table.find(Methods.Current,index))
		return success
	end
	
	table.remove(Methods.Current,table.find(Methods.Current,index))
	warn('[DICE DATASTORE]: Failed to save',index,'on key',key)
	return false
end

function Methods:Load(key,index)
	assert(typeof(key) == 'string',"[DICE DATASTORE]: Key 'string' expected, got '".. typeof(key) .."'")
	assert(index ~= nil,"[DICE DATASTORE]: Index expected, got '".. typeof(index) .."'")
	if table.find(Methods.Current,index) then return end
	table.insert(Methods.Current,index)
	
	if Methods.Cache[key] then
		local results = {}
		local datastore = Services['DataStoreService']:GetDataStore(key,index)
		local success,err = pcall(function()
			results = datastore:GetAsync(key..':'..index)
		end)
		
		table.remove(Methods.Current,table.find(Methods.Current,index))
		if not success then
			results = DeepCopy(Methods.Cache[key])
			results['___PlayingCards'] = false
			return results,false
		end
		if results == nil then
			results = DeepCopy(Methods.Cache[key])
			results['___PlayingCards'] = true
			return results,true
		end
		results['___PlayingCards'] = true
		return results,true
	end
	
	table.remove(Methods.Current,table.find(Methods.Current,index))
	warn('[DICE DATASTORE]: Failed to load',index,'on key',key)
	return false
end

return Methods