Advertisement
Guest User

Server-Sided Datastore Module

a guest
Aug 5th, 2024
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.56 KB | None | 0 0
  1. --// Author(s): MohhayScripts
  2. --// Version: 1.2.0
  3.  
  4. --// Services
  5.  
  6. local Players = game:GetService("Players")
  7. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  8. local RunService = game:GetService("RunService")
  9. local ServerStorage = game:GetService("ServerStorage")
  10.  
  11. --// Modules
  12.  
  13. local Astronet = require(ServerStorage.AstronetServer)
  14.  
  15. local ProfileService = Astronet.Require("ProfileService")
  16. local ReplicaService = Astronet.Require("ReplicaService")
  17. local ProfileTemplate = Astronet.Require("ProfileTemplate")
  18.  
  19. local Logger = Astronet.Require("Logger").attach(script.Name)
  20. local Promise = Astronet.Require("Promise")
  21.  
  22. local Settings = require(ReplicatedStorage.Settings)
  23.  
  24. --// Types
  25.  
  26. --// Variables
  27.  
  28. local ProfileStore = ProfileService.GetProfileStore("PlayerData", ProfileTemplate)
  29. local ProfileClassToken = ReplicaService.NewClassToken("PlayerProfile")
  30.  
  31.  
  32. local PlayerProfiles = {} -- [player] = {Profile = profile, Replica = replica, _player = Player}
  33.  
  34.  
  35. --// Functions
  36.  
  37. local function PlayerAdded(Player)
  38.     local Profile = ProfileStore:LoadProfileAsync("Player_" .. Player.UserId)
  39.  
  40.     if Profile ~= nil then
  41.         Profile:AddUserId(Player.UserId) -- GDPR compliance
  42.         Profile:Reconcile() -- Fill in missing variables from ProfileTemplate (optional)
  43.  
  44.         Profile:ListenToRelease(function()
  45.             PlayerProfiles[Player].Replica:Destroy()
  46.             PlayerProfiles[Player] = nil
  47.             -- The profile could've been loaded on another Roblox server:
  48.             Player:Kick("Another server is trying to load your data. Please close all instances of Roblox and rejoin the game if this was unintentional!")
  49.         end)
  50.  
  51.         if Player:IsDescendantOf(Players) == true then
  52.             -- A profile has been successfully loaded:
  53.             -- do something with profile
  54.             local player_profile = {
  55.                 Profile = Profile,
  56.                 Replica = ReplicaService.NewReplica({
  57.                     ClassToken = ProfileClassToken,
  58.                     Tags = {Player = Player},
  59.                     Data = Profile.Data,
  60.                     Replication = "All",
  61.                 }),
  62.                 _player = Player,
  63.             }
  64.             setmetatable(player_profile, Profile)
  65.             PlayerProfiles[Player] = player_profile
  66.         else
  67.             -- Player left before the profile loaded:
  68.             Profile:Release()
  69.         end
  70.     else
  71.         -- The profile couldn't be loaded possibly due to other
  72.         --   Roblox servers trying to load this profile at the same time:
  73.         Player:Kick("Failed to load data, another server is trying to load your data at the same time. Please rejoin the game after a few seconds!")
  74.     end
  75. end
  76.  
  77. --// Init
  78.  
  79. local DataService = {}
  80.  
  81. function DataService:GetData(Player: Player): typeof(ProfileTemplate) | nil
  82.     local playerProfile = PlayerProfiles[Player]
  83.  
  84.     if not playerProfile or not playerProfile.Profile then
  85.         Logger.error(`{Player.Name} playerProfile or playerProfile.Profile does not exist. [playerProfile: {if playerProfile then Logger.parse(playerProfile) else "nil"};]`)
  86.         return
  87.     end
  88.  
  89.     return playerProfile.Profile.Data
  90. end
  91.  
  92. function DataService:GetDataPromise(Player: Player) -- Promise variant of DataService:GetData()
  93.     local playerProfile = PlayerProfiles[Player]
  94.  
  95.     if playerProfile ~= nil and playerProfile.Profile ~= nil then
  96.         return Promise.resolve(playerProfile.Profile.Data)
  97.     end
  98.  
  99.     return Promise.new(function(resolve, _reject, onCancel)
  100.         local heartbeat
  101.         local function OnDone()
  102.             heartbeat:Disconnect()
  103.         end
  104.         local function Update()
  105.             local v = PlayerProfiles[Player]
  106.             if v ~= nil and v.Profile ~= nil then
  107.                 OnDone()
  108.                 resolve(v.Profile.Data)
  109.             end
  110.         end
  111.         heartbeat = RunService.Heartbeat:Connect(Update)
  112.         onCancel(OnDone)
  113.     end):timeout(20)
  114. end
  115.  
  116. function DataService:GetDataByKey(Player: Player, key: string): any | nil
  117.     local playerProfile = PlayerProfiles[Player]
  118.  
  119.     if not playerProfile or not playerProfile.Profile or not playerProfile.Profile.Data[key] then
  120.         Logger.error(`{Player.Name} playerProfile or playerProfile.Profile or playerProfile.Profile.Data[{key}] does not exist. [playerProfile: {if playerProfile then Logger.parse(playerProfile) else "nil"};]`)
  121.         return
  122.     end
  123.  
  124.     return playerProfile.Profile.Data[key]
  125. end
  126.  
  127. function DataService:GetDataByKeyPromise(Player: Player, key: string) -- Promise variant of DataService:GetDataByKey()
  128.     local playerProfile = PlayerProfiles[Player]
  129.  
  130.     if playerProfile ~= nil and playerProfile.Profile ~= nil and playerProfile.Profile.Data[key] ~= nil then
  131.         return Promise.resolve(playerProfile.Profile.Data[key])
  132.     end
  133.  
  134.     return Promise.new(function(resolve, _reject, onCancel)
  135.         local heartbeat
  136.         local function OnDone()
  137.             heartbeat:Disconnect()
  138.         end
  139.         local function Update()
  140.             local v = PlayerProfiles[Player]
  141.             if v ~= nil and v.Profile ~= nil and v.Profile.Data[key] ~= nil then
  142.                 OnDone()
  143.                 resolve(v.Profile.Data[key])
  144.             end
  145.         end
  146.         heartbeat = RunService.Heartbeat:Connect(Update)
  147.         onCancel(OnDone)
  148.     end):timeout(20)
  149. end
  150.  
  151. function DataService:SetData(Player: Player, data: {any}): ()
  152.     local playerProfile = PlayerProfiles[Player]
  153.  
  154.     if not playerProfile or not playerProfile.Profile then
  155.         Logger.error(`Failed to set data because {Player.Name} playerProfile or playerProfile.Profile does not exist.`)
  156.     end
  157.  
  158.     PlayerProfiles[Player].Profile.Data = data
  159.     Logger.info(`Successfully saved data to {Player.Name} playerProfile.Profile.Data.`)
  160. end
  161.  
  162. function DataService:SetDataByKey(Player: Player, key: string, value: any): ()
  163.     local playerProfile = PlayerProfiles[Player]
  164.  
  165.     if not playerProfile or not playerProfile.Profile or not playerProfile.Profile.Data[key] then
  166.         Logger.error(`Failed to set data because {Player.Name} playerProfile or playerProfile.Profile or playerProfile.Profile.Data[{key}] does not exist. [playerProfile: {if playerProfile then Logger.parse(playerProfile) else "nil"};]`)
  167.         return
  168.     end
  169.  
  170.     playerProfile.Profile.Data[key] = value
  171.     Logger.info(`Successfully saved data to {Player.Name} playerProfile.Profile.Data[{key}].`)
  172. end
  173.  
  174. function DataService:Init()
  175.     if RunService:IsStudio() and Settings.ProfileService.Mock then
  176.         ProfileStore = ProfileStore.Mock
  177.     end
  178.  
  179.     Players.PlayerAdded:Connect(PlayerAdded)
  180.  
  181.     for _, Player in Players:GetPlayers() do
  182.         task.spawn(PlayerAdded, Player)
  183.     end
  184.  
  185.     Players.PlayerRemoving:Connect(function(Player)
  186.         local Profile = PlayerProfiles[Player]
  187.  
  188.         if Profile ~= nil then
  189.             Profile.Profile:Release()
  190.         end
  191.     end)
  192. end
  193.  
  194. return DataService
  195.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement