I’ve heard great things about ProfileService and I’ve been wanting to use it for a while now but since I’ve already written a lot of code with DataStore2, I’ve been hesitant on doing so.
I currently trust DataStore2 more than ProfileService but since item duplication is a major problem in DataStore2 (from what I’ve read) and ProfileService is “item duplication safe”, it might be the best for my game since my game heavily relies on the economy and having a duplication glitch can ruin the experience for most players.
What are your thoughts? Should I switch over to ProfileService or should I create a session-locking system with DataStore2 (if that even is possible)?
Do you plan on having a trading system? If not then you can stick with Datastore2, but if you are planning on having one you can either mod Datastore2 to fix item duplication or use the Profile service.
I do plan having a trading system. How would I counter item-duplication though? Should I make sure that all saving has been done before the player can join back?
From my knowledge the ProfileService stops item duplication by only using the UpdateAsync function, so it does not use GetAsync or SetAsync. On the webpage I linked you see the part where it says:
In cases where another game server updated the key in the short timespan between retrieving the key’s current value and setting the key’s value, UpdateAsync() will call the function again to ensure that no data is overwritten. The function will be called as many times as needed until the data is saved.
So i guess only using UpdateAsync will stop data from being overwritten while it is being saved thus preventing the item duplication issue, I could be wrong, I’m also in the process of making my own Datastore wrapper using both DS2 and the profile service.
In DataStore2’s API, :Update() is noted to be bugged so using the API member might cause some issues.
From what I know, the issue is being caused due to the player rejoining the server fast enough where :GetAsync() fires before :SetAsync() from the previous session. Wouldn’t a cooldown between the time a player leaves and the time the player joins back fix this issue or is there something I’m confused about?
Yes that’s the reason why item duplication occurs, you will have to find some to way to implement a cross-server cool down, because remember players can leave and join new servers. I’m not sure if the messaging service would also suffer from the same delay of publishing a message, but that is the only feasible service you could use for the cool down system. Also, I’m talking about UpdateAsync not the DS2 wrapper.
:UpdateAsync() wasn’t in DataStore2’s API so I got a bit confused.
I honestly can’t think of any working way to implement cross-server cooldown. I guess I could use ProfileService for storing the os.time() the player left and if they pass the cooldown, I could use :Get() on DataStore2 but I’m not so sure if that would work.
True. I really haven’t fully grasped the idea of datastores so sorry for the hiccups.
Does loading one key on a datastore load all of them? I was thinking about having one key meant for the cross-server cooldown and if they passed that, I would load in the key with the player’s data.
I would really love to use ProfileService but I still do not trust them as much as DataStore2. I might have to research more on both modules to get a good understanding which one’s benefits outweigh the other.
Your still relying on datastores for storing the cool down time, so traffic will prevent the latest time from saving, thus still allowing the player to rejoin quickly.
Dungeon quest uses DS2 and had a issue with item duplication, it is now patched, but the original DS2 module is still susceptible to duplication glitches.
I was thinking of “opening” and “closing” os.time() tables. Basically when a player joins in, a session is opened with their os.time() entry and when they leave, the table is closed with another os.time().
What I was thinking is that every time a player joins, if the table’s closing value is still nil (meaning it has not saved yet), it would yield until a value is set.
API calls can error. The reason why ProfileService waits about 80 seconds before “stealing” the session lock is because that should give the other server enough time to sort out the issues with any API errors. There’s still a possibility that it takes longer than 80 seconds for the previous server to sort out the errors. This is still the best and safest way to save player data in my opinion.
The reason why using :GetAsync and :SetAsync separately is bad is because you’re prone to 2x as many network errors as you are with using a single query to both fetch AND update your data. :GetAsync also has a lot of caching headaches that might interfere as well.
To answer OPs question, it’s really only worth it to switch if players in your game already found out how to duplicate items. I would highly advise to use this on all new games you make, but transitioning between data systems can create more issues than it solves if you do it incorrectly.
UpdateAsync doesn’t do much to prevent duplication. Little to nothing actually. Profile service features Profile Locking, which is actually what stops duplication. It’s impossible for ProfileService to not use GetAsync, as that’s the only way to get data without overwriting it.