Persistence

Share us your Persistence bugs and feedback here (one item per post).
Non-constructive and off-topic posts will be moved or deleted.
Preventing Persistence Exploits from Multiple VRChat Instances
The ability to open two instances of VRChat in separate windows under the same account, each being a different instance of the same world, creates significant issues for any game world that relies on persistence. I'll refer to the two windows as "Window 1" and "Window 2." Both are running the same world but in different instances. If a player performs an action in Window 1, such as getting a reward or losing progress, and the world saves that, they can simply close Window 1, switch to Window 2, and wait for the world to save their data. This will entirely overwrite the changes from Window 1, restoring their progress as if nothing had happened. This exact issue happens very commonly on mismanaged Minecraft servers, where you can have two instances open on the same server but in different subservers. This is most commonly used to duplicate items, which no RPG-style game world wants. An example in VRChat would be the world "Project Aincrad". If, in Window 1, Player 1 trades 10,000 in-game coins they have to Player 2 while Window 2 is up, then at the end of the trade, when the game forces them to save their persistence data, Player 1 in Window 1 will have 0 coins, Player 2 will have 10,000 coins, but Player 1 in Window 2 will still have the 10,000 coins, meaning that 10,000 coins have now turned into 20,000 Coins. I'm not very technical, so this is more of a guess for a potential solution, something like only allowing Window 1, or whichever window was first in that specific world, to be capable of changing the persistence data for that user and world.
26
·
tracked
Add option for Keys to be Local
Issue: Setting any value on playerdata (for example, a setting for the world) syncs all playerdata keys/values to all users (for example, SaveData), even ones that were not changed. I don't want to to sync certain keys, as they are very big and not commonly changed. I also don't need other players to be able to see certain keys. Context: So this is very similar to https://feedback.vrchat.com/persistence/p/user-private-persistence however my reasoning is completely different. I have a leaderboard system and a settings panel in my world and they both use persistence, they work perfectly fine, but I recently introduced a Save-Load system, which lets players save pickup locations and pen drawings to their player-data, so they can load it later. The issue comes because when something unrelated gets changed in the player-data, for example a value on the leaderboard. All of that player's persistent data still gets sent over the network, including the large save data, this creates a LOT of network lag and makes the instance unstable. Using persistence is the only way I can make sure everyone can use the save-load system. I cant rely on a simple text box export alone or using the debug logs, as some users are on quest and that makes it quite difficult to extract debug logs/save text. And debug logs get automatically deleted, so It's unreliable. Solution: My idea is to have a third, optional argument for PlayerData.Set<T>(), For example: instead of: PlayerData.SetBytes(Key, Value); We would have: PlayerData.SetBytes(Key, Value, true); The third argument would be 'Local' it defaults to false so people would not need to update all their existing scripts When it is true, it makes it so that key is marked as Local Only, and doesn't get sent to other players, ever. If somewhere else in the code, localplayer calls PlayerData.SetBytes(Key, Value, false); or without the third argument, it sets that variable back to global. I have included a mockup screenshot.
1
Add GetPlayerRestoreStatus Check
A Networking.GetPlayerRestoreStatus(GameObject) and PlayerData.GetPlayerRestoreStatus(VRCPlayerApi) that returns a custom enum with the values: Incompatible , Awaiting , Success , Failed , & NoDataToRestore . This would only work on networked objects that can store persistence data like PlayerData or PlayerObjects with an Enable Persistence component. Other objects will always return the Incompatible value. This would allow worlds to ask for a particular object's persistence status for many things: * Incompatible - This object does not support persistence. Use a PlayerObject with the Enable Persistence component. * Awaiting - Data has not been received from the server so the world knows to wait until a further update before trying to read/write persistence data for that object. * Success - Data was successfully restored from the server without any exceptions from VRChat's side. The world knows it is safe to read and write data to it. * Failed - Data restoration encountered an error on VRChat's side and data should not be manipulated for data loss. The world can present an error message and/or allow the player to clear their data. * NoDataToRestore - There was no data to restore from the server. The world knows this is a new player, a new update bringing a new persistent compatible object, or a player who has recently cleared their data. This also indicates to the world that this object is ready for writing new persistence data. Related: https://feedback.vrchat.com/persistence/p/add-persistence-data-status-event-or-status-parameter-for-onplayerrestored
0
Load More