Hello, I am creating a game where you can place a gravestone and once you do it stays there forever. (saved in the players datastore through their UserID as a key using profile service). I don’t know how I would load all of the gravestones when a new server is created and without the player who own a gravestone in that said server.
Here is my code for saving if it helps at all
if Profile.Data["HasGrave"] == false then
local RandomPosition = GetRandomLocation(RegionPart).Position
local Success, Grave = PlaceGrave(RandomPosition)
if Success and Grave then -- Nothing blocking the grave
local Time = os.date("*t")
print("Placed grave!")
Profile.Data["HasGrave"] = true
Profile.Data["JoinDate"] = {
Month = Time.month;
Day = Time.day;
Year = Time.year
}
Profile.Data["GraveLocation"] = { -- Compress the data
X = math.round(RandomPosition.X / 0.001) * 0.001;
Y = math.round(RandomPosition.Y / 0.001) * 0.001;
Z = math.round(RandomPosition.Z / 0.001) * 0.001
}
end
else
print("Player already has a grave!")
end
Doing something like this is a bit tricky to do coherently with ProfileService, because of session-locking. If all you are doing is just building a graveyard from all the players in the server - that’s simple. Once you’ve loaded the data, just generate the gravestone from whatever information you’ve saved.
If you are creating a graveyard from every player that has ever played your game - this is more difficult and requires a thoughtful construction. It’s not great to save the data to all the players and then retrieve it, because ProfileService will error if you try to load a Profile that has not been released. This will happen if the player is in another server, because session-locking.
Okay, so what about saving all of the data to the server? Ex: :LoadProfileAsync("GlobalServerData", ...? You will run into the same session-locking issues here. If one server (presumably the first server) loads the server data, then other subsequent servers will not be able to load the data, because session-locking.
Two recommended solutions:
Use regular datastores for this. You won’t have to worry about session locking because it’s not applicable here. This would be your simplest approach.
Avoid session-lock constraints by loading the server data on only one server and communicating server data to all other servers via MessagingService. This is very tricky to implement properly, because you need to handle a bunch of edge cases. I would not recommend doing this unless the way you handle data is very much wrapped up in ProfileService and it would be a major pain to disentangle it all. If you would like to chat about this method, feel free to DM me. Contrary to my own advice, I have taken this approach in the past.
A third outside the box solution
MemoryStores. You won’t have every player ever who has played the game, but this might be attractive. Displaying every single player’s gravestone is probably not sustainable at scale, so this might be exactly what you are looking for.
Figured it out using regular datastore, I would just have to set up a rate limiting system because as the datastore increases in size the limits would become more likely to be reached
local function LoadGraves()
local success, pages = pcall(function()
return Datastore:ListKeysAsync()
end)
if success then
while true do
for _, key in pages:GetCurrentPage() do
local success, value = pcall(function()
return Datastore:GetAsync(key.KeyName)
end)
if success then
print("Key:", key, "Value:", value)
else
warn("Failed to get value for key:", key)
end
end
if pages.IsFinished then
break
end
pages:AdvanceToNextPageAsync()
end
else
warn("Failed to list keys in DataStore")
end
end