#world-persistence

1 messages ยท Page 1 of 1 (latest)

sonic swift
#

Nice.

keen tendon
#

Hooray! ๐ŸŽ‰

knotty ether
#

Hello

lone stirrup
#

heyyy

digital coral
#

Boo

ionic valve
#

finally :)

wary summit
visual sapphire
#

they said it wouldn't come out....

digital coral
unique rune
#

woooo it's happening

hoary current
#

is the persistance beta network compatible or no?

grizzled surge
#

exciting update!

weak siren
#

yaaay

olive tree
#

Finalllly

hardy narwhal
#

ah

ionic valve
hoary current
sonic swift
#

What worlds currently have persistence?

ivory bluff
#

What a pleasant surprise out of nowhere.

foggy mason
#

Patience paid off

abstract narwhal
#

Oh my god hi guys ๐Ÿ‘‹

storm maple
#

I'm really excited to see where this goes, save data is a really big component that I feel like VRChat games have been missing for a long time

echo hemlock
#

Whispers.
I'm so excited.

ionic valve
#

will worlds uploaded with persistence sdk work with live clients?

broken forge
#

ta-da!

elfin wren
ripe kindle
#

๐ŸŽ‰

lapis pier
#

Woke up, see open beta, smile

wary summit
novel flower
#

@granite river oh look your favorite feature is here

hoary current
ivory bluff
#

Wake up, Samurai. Itโ€™s time for Persistence Open Beta.

unique rune
#

time to get back to world-building

storm maple
#

some worlds have had workarounds, I have seen one save system I think and another using a "pass code" save system like the NES but it certainly has been very rare

elfin wren
#

Il push the settings saving for lsm tomorrow

wary summit
trim cradle
regal ivy
#

finally a way to save in idle home easily!!

dusky kindle
#

Less gooo

radiant wharf
#

The worlds mentioned in the Sep 19 dev update, do those work with the persistence beta right now?

wraith bolt
#

a

nova lichen
#

gues i tried to switch too early, still not showing

idle jackal
#

You know how painful it was to manually record stats and re apply it via code and scripts. now we can save space without all that BS.

wary summit
echo hemlock
#

I'm already predicting stats and leaderboards on every world. Whoever has the most of something, or perhaps a leaderboard for the amount of hours someone's stayed in a world, lol. Things're going to get competitive.

trim cradle
#

Unity why do you take so long to upload cat_cry

wary summit
idle jackal
trim cradle
ionic valve
wary summit
wraith bolt
#

whelp now to update the pool table

ionic valve
nova lichen
#

Btw is the persistence build network compatible like the open beta?

olive tree
wary summit
idle jackal
radiant wharf
pastel plume
#

Quick question as a world creator: is there an easy way to detect if persistence is available on the client in udon? Feature detection/version checking/something like that.

wary summit
shrewd sphinx
#

I actually don't see a way to save "world global" data like leaderboards

pastel plume
#

balls

idle jackal
pastel plume
wary summit
idle jackal
#

WAHOOO

pastel plume
#

I can possibly use a script crashing as a feature flag

idle jackal
#

Legends

trim cradle
nova lichen
#

Now there will be more sense to add way more complex customisation to worlds, even moving around the world furniture or even worlds that allow building your own world with a preset of objects to create ur own space

quartz raft
#

yippie

echo hemlock
cerulean lion
#

Finally a year and 3 months after the expected window

idle jackal
crisp grotto
#

So the persistence open beta is or isn't live compatible?

wary summit
wraith bolt
#

The main one I would say folks should do first will be to get their various cozy home worlds updated so that their settings are persisted.

radiant wharf
idle obsidian
#

I think for now handling things through a separate branch will have to do until you are ready to merge to your mainline build

#

If there's no way to differentiate between beta and stable (at least as easily)

wary summit
wraith bolt
#

Sidenote; whilst persistence itself is an important thing here, you lot should not sleep on player objects.

wary summit
idle jackal
ripe kindle
wary summit
trim cradle
#

It's in the SDK!

wraith bolt
#

I just grabbed the beta :slugcatnod:

idle jackal
wraith bolt
#

I can't believe I can't nodders here. The humanity.

wary summit
#

also the acronym is VCC not just CC. CC could be lots of things, credit card, closed captions, etc

radiant wharf
#

cheese cycler

cerulean lion
trim cradle
#

Cause I just posted my update for it lol

wary summit
wraith bolt
#

But yeah uh player objects are there to solve the constant pain point game devs have had with "I need to just have per-person data, why is this so flaky and horrible"

#

Even if you don't use persistence you should be migrating game code to them.

idle jackal
cerulean lion
#

Persistence isn't a community made thing, it's from VRChat

idle jackal
#

Read above

wary summit
idle jackal
#

Filters, tags exist. Make good use of it

wary summit
#

Persistence is not an external download, it already is part of the VCC. It's just a beta SDK

cerulean lion
#

how would you prevent people uploading malware to this "community tab"

#

text files are extremely small

gritty roost
#

It's time.

cerulean lion
#

there's a 100kb limit per person

wraith bolt
#

100kb compressed.

crisp grotto
wraith bolt
#

You can fit many Bee Movies into that

trim cradle
ripe kindle
echo hemlock
# trim cradle https://github.com/DrBlackRat/VRC-Picture-Loader/releases/tag/3.0.0

Really cool world to showcase it! I think having more personalized home worlds would be amazing, lol. Like a room editor to shape stuff just how you like it. It'd be neat to have like a picture book area or something with uploaded screenshots of friends, etc. Custom posters to decorate a room, idk. There's genuinely a lot you could do.

#

Hope someone gets on that, honestly.

trim cradle
#

That's the idea behind it :p

wraith bolt
crisp grotto
#

can't wait for worlds that already have string-based saving to implement regular saving via just saving that string themselves. A cool use case I can think of would be going to VRBricks and making a home world for yourself, and having that home world creation load in every time you hop in game.

wraith bolt
#

The old way was using player object pools and either hoping the prefab you got is stable over the network, or you rolled your own.

#

The new system just goes "nah it's natively supported, and you never have to worry about network ownership or any of that nonsense"

marble timber
wraith bolt
#

Basically this update isn't just persistence, it's the biggest Udon networking update since manual sync

#

hence why Phase and co have summoned me back from the void

marble timber
crisp grotto
wraith bolt
#

yes, it will make things far easier for you and far more stable.

radiant wharf
#

i hope that a button for saving the current position as a persistent spawn point becomes as ubiquitous as the mirror toggle

wraith bolt
#

We just don't need network ownership for player-scoped objects.

abstract narwhal
marble timber
wraith bolt
#

yuppers

marble timber
#

so no way to sneakily steal udon objects anymore during ownership transfers

wary summit
trim cradle
marble timber
quartz stump
#

the buttons should probably be greyed out and indicate that

#

yeh

wraith bolt
#

This also should hopefully allow for things like targetted RPCs eithout faff

marble timber
wraith bolt
#

because everyone has a guaranteed player object, it's not going to need anywhere near the level of cruft

abstract narwhal
wraith bolt
#

I for one welcome being able to show off games at Community Meetup without the lobby system guaranteed crashing.

#

Speaking of: is the lobby system official demo prefab gonna be updated

abstract narwhal
marble timber
#

ill do it rq

#

inb4 the canny gets flooded because of the very obvious known issues

#

LOL

trim cradle
#

Anyway here is a video I made showcasing the persistence stuff for my prefab (as well as some other changes that got into that update)
https://youtu.be/2j-NbM8QwFM

This is the biggest update for my VRChat Picture Loader yet!

Download: https://github.com/DrBlackRat/VRC-Picture-Loader

  • Added Persistence Support!
    • Added Persistence Prefab which allows you to add URL Inputs you want to use Persistence for
    • The Instance Creator can Save & Load Images
  • Added a Tablet Downloader
    • Compatc all in one s...
โ–ถ Play video
errant token
marble timber
abstract narwhal
#

smh, the mirror quality setting in the VRC Home World doesn't have persistence. :v

wraith bolt
#

Didn't you lot ship a lobby system example for Spookality?

#

in the examples?

olive tree
#

we did

wraith bolt
#

JoinZoneWithDisplay etc

#

yeah

#

Just checked the code. I was wondering if that was going to get updated/replaced by a more robust player objects thing

errant token
#

ah yes - I wanted so badly to make all the Spookality demos with Persistence but it wasn't ready yet

little echo
#

am i the only one with no sticker emoji submenu icon in the beta

errant token
#

Yes, we'll revisit those demos for possible updates once Persistence gets a full release

wraith bolt
#

Nice. Good to hear.

merry widget
#

It's finally here!!

olive tree
merry widget
#

Persisting for you!!

little echo
#

there is no showcase world like with physbones also?

trim cradle
#

not really now

#

You can just visit worlds others have made already

#

we should probably make a list

merry widget
#

a list or a playtest group might be fun!

wraith bolt
#

A row? ๐Ÿ‘๏ธ ๐Ÿ‘„ ๐Ÿ‘๏ธ

graceful compass
#

row is old nomenclature fsp, they're ~categories~ now

echo hemlock
manic dock
#

oh my god finally persistence im so happy

trim cradle
#

If anyone has a world with persistence in it feel free to drop a link in here, I'll try my best to pin them!

radiant wharf
#

500 vrchatillion years before this releases to live

marble timber
shut jolt
#

๐Ÿ‘€

#

it's here

marble timber
#

if anyone is curious how any of my stuff works under the hood just ask, im willing to provide as much source code as you need lol

wraith bolt
hardy narwhal
#

(I mean thread only with world links)

hardy narwhal
#

World Link

marble timber
#

my database code for OF may be like 1500 lines long...... ๐Ÿ’€

#

actually rn 1135 lines

#

got trimmed with some recent SDK updates

crisp grotto
#

Is there any available documentation on player objects and how to use those?

merry widget
little echo
#

@loud jungle im gonna be a jump pro

hardy narwhal
#

If you looking for worlds to test persistence,
Check here

For documentation, here

gritty roost
#

Ouhhh a list of worlds with persistence, I like it

kindred swan
#

Honestly this system will be god send for game worlds like terrors of nowhere

#

Being able to load in ur items/achievements/etc- instantly without using codes

unique rune
#

yep

marsh cairn
#

I can't wait for persistence to land in release

#

Let's gooo

wraith bolt
#

Is OnPlayerDataRestored fired if you or a joinee has no data?

marble timber
wary summit
wraith bolt
#

Nah I mistyped, it's 2am

#

Looks like my Udonsharp isn't picking up the override.

#

ah

#

I am stupid.

marsh cairn
#

how long does it take for a feature like this to eventually land in stable release?

wary summit
wraith bolt
#

checks types supported by persistence

wow, no byte[]

#

I can't believe you don't just want people to be uploading arbitrary data blobs ๐Ÿ˜›

marsh cairn
#

alr then, I'll be waiting

olive tree
#

they are supported in player objects tho

wraith bolt
#

my blobs!

#

Eh just means I'll probably just have to encode arbitrary data as JSON or something

hardy narwhal
crisp grotto
flat wasp
#

I already have a really stupid idea for a world

wary summit
#

Playerdata.setbytes

wraith bolt
#

Oh!

#

Bytes

#

I was expecting "SetByteArray"

wary summit
#

Fair

agile geyser
wraith bolt
#

Bit late to be suggesting api changes

#

๐Ÿ˜„

#

Yeah "trygetbyte", "trygetsbyte", "trygetbytes"

marble timber
#

Use a LSP lol

#

Btw if your working on a prefab, use player objects

#

Player data isnt really appropriate for prefabs for a variety of reasons

wraith bolt
#

For most of it, yes, but considering this is VRCBCE I'm working on

#

I'm going to need to support world-scoped data to an extent.

marsh cairn
marble timber
cerulean lion
marble timber
#

I suggest against player data as its less explicit since its global and not object tied

wraith bolt
#

Yes but I don't know how many pool tables someone is gonna have in their world

marble timber
#

(also any changes to any player data cause the whole thing to restync, while changes to individual player ovjects only sync that object

wraith bolt
#

But I'll need to properly design the real system

marble timber
wraith bolt
#

I'm anticipating world-scoped pool player data being in a separate pile of data to specific table data.

#

That may well end up turning out unwise

quaint night
#

the main problem is that the easiest API to use is most easy to shoot yourself in the foot with

marble timber
wraith bolt
#

True.

marble timber
#

You might be synching a massive ammount of data by just changing a int

wary summit
marble timber
#

I just disagree for any prefab creators since the world use case is unkown and you may cause massive network loads unintentionally

flat wasp
#

Maybe a small warning from the SDK when a prefab contains save data parameters?

marble timber
flat wasp
marble timber
#

Right but you dont know if thats the users prefab or a packages

flat wasp
#

And I'm sure you can detect when a package gets imported

marble timber
#

This is just moreso something prefab creators need to realize. Either that or player data gets fixed to not sync the whole thing everytime

wraith bolt
#

To be clear; I'm doing a full systematic rewrite of VRCBCE and sandboxing both networking and persistence inside of their own code, so I can put off deciding on a pattern firmly until later.

flat wasp
#

You can always just have a "don't show again for this prefab" type thing too

#

Or just like

#

Have it be a onetime thing

marble timber
wraith bolt
#

The entire point of the VRCBCE refactor is to avoid tying hard-to-change code into infra.

#

Infra and domain live in two boxes and I define communication between them. I'm extremely done with omega classes

marble timber
#

I mean yeah im using the same architechture for my setup. 1113 line database manager system lol

wraith bolt
#

Wish I had interfaces but eh, I'll cope with abstract classes

#

Skimming the logic for playerdata: it looks like it's entirely possible to clock how calamitious a data sync push would be

marble timber
#

Ig you could if you really wanted to

wraith bolt
#

So to code defensively, it would be best to do a scan of how much data is synced

valid kestrel
#

Perfect timing to lose power for a few weeks vrcTupCry
Gonna have a lot of fun with this when it returns

marble timber
#

Still waiting on the part of the api that lets us know when synching will be finished and how much world space is left :flop:

wraith bolt
#

ยฏ_(ใƒ„)_/ยฏ

#

I'll need cross-prefab persistence, though, that's a hard requirement.

marble timber
#

Kind of vital for prefabs imo since without it you cant inform the user if a save even worked or has finished and is safe to leave sadly

wraith bolt
#

Fun fact: we survived without clog checks for I think two years

#

:v

marble timber
#

It wasnt as critical as it is now

#

If i save a certain ammount of bytes, it can take up to a minute to save and theres no way to tell the player how long to wait reliably

wraith bolt
#

I somehow survived before the networking rewrite, too :v

maiden wharf
#

video players do seem broken between stable and persistence beta
no one on stable sees the videos i put in, nor are they able to add urls

cerulean solstice
#

Could persistence allow a global world leaderboard eg. Points scored in a game?
(All players that ever played the game across instances)

Local leaderboards would be pretty easy. I know that

marble timber
#

You only get data for users in your instance

cerulean solstice
# marble timber Sadly not at the moment

I think it would be neat to have a way to access all the data of every player that ever joined the world. But I can see this causing security and trust concerns

marble timber
cerulean solstice
wraith bolt
#

one second, backend engineer hat on

marble timber
#

Remember a world can store about like 10000 bytes IIRC compressed (dont trust the number i have here it may be higher, in bed rn lol)

wraith bolt
#

world-scoped dynamic data is probably actually easier than player-scoped data.

marble timber
#

But a leaderboard wouldnt work with that since it then becomes player scoped again essentially in size

wraith bolt
#

You're just saving a blob next to the manifest and assetbundle for the world and allowing read-write through some API.

marble timber
#

Its the potential size thats moreso the concern. All player data is stored on server, not locally

lusty moat
#

so wait I don't understand the difference between player data and player objects. Whats an example of what you would use one over the other?

wraith bolt
#

Yep, and potentially a very high read volume that would hurt if the blobs were on something like DDB.

marble timber
wraith bolt
#

Your main problem would be accepting legal ingest.

marble timber
#

Player objects are the way to go 90% of the time imo for reasons ive listed here already

wraith bolt
#

You can't really allow a scrote to hack the client and replace your world's persistent data with a dickbutt ascii.

marble timber
#

Player objects are duplicated for each player, and are owner locked aerver side to always be owned by their respective player. Any network synched variable is atuomatically saved on individual serialization of that player object, compared to player data that serailizes everything in it at once when anything in it changes

#

Player data is essentially the lazy quick way to do persistence TLDR (atleast in my opinion for most cases)

wraith bolt
#

I don't actually agree there from a architectural standard

#

I can agree on the technical debt/limitations side, that's a good point

#

But player data is agnostic of world setup

marble timber
#

If it was diff based it would be way nicer

wraith bolt
#

Suppose I'm refactoring a world I'm working on and I want to maintain all the data my players have.

#

If it's stored on a player object, that object has to remain rigid.

marble timber
#

Ehhh thats moreso a issue with the network id stuff being weird but yeah i get your point

wraith bolt
#

Yeah so just in general I think the model they've got is fine

unique rune
#

yeah versioned object persistence is quite hard

wraith bolt
#

Again as a seasoned practicioner of coping with VRChat world code

#

Important thing is to work flexibly

marble timber
#

Itd be nice if we could just have like string based network ids so i could namespace my objects and have them always be linked :/

#

Something like a playerdata key

quaint night
#

I mean that's what the global persistence data is, the API is just bad because every time someone wants to use it you need to tell them not to

lusty moat
#

yeah it is amusing they put out persistence when the network id tool is still broken after the last update

marble timber
wraith bolt
#

Yup, and if you cope/mald/seethe about it, it eventually will be improved

#

๐Ÿ˜„

marble timber
#

Its really just the unkownkness of what data cascade you might cause

#

cant wait for infinite loops based on player data being updated by one script making another script try to update its player data lol

#

Not sure if thats possible but sounds funny and that it might be

wraith bolt
#

To be fair, I think world creators will need to be the ones to have to worry about player data overload more than prefab authors

#

I'll need to very clearly outline what the persistence layer does and how it works regardless of what methods I implement

lusty moat
#

I feel like they need a "stupid mode" where you just put [persistent] or something before a variable and it figures out all the stuff in the background for how best to actually accomplish that

marble timber
marble timber
wraith bolt
#

I'd anticipate editor scripting people to step in and go "hmmmmmm" at this

marble timber
wraith bolt
#

There's some aspects of the problem I think can be spotted by automation, but given player data accepts unbounded strings and arrs

#

will be quite spoopy

marble timber
#

I mean im already doing cursed things, im just storing raw json string in a player object for the settings database

quaint night
pastel plume
#

Interesting bug.
If you're on the beta using persistence, and someone creates an instance for a world with persistence and you join them, you're unable to join said instance - "world version incompatible with this instance"
I'm going to go report a canny, but oops

hardy narwhal
pastel plume
#

Btw it doesn't matter who creates the instance, it's whoever joins first (i.e. master).

#

Also interestingly, when you have synced objects with non-beta users, they get the object instantiated, but never get OnPlayerRestored() called. Which makes some sense, but feels a little weird.

wraith bolt
#

Sidenote on the player data stuff

#

They can't just only fire diffs off to people

#

Diffs are inherently contextful. You have to issue complete sets of data or clients cannot guarantee data correctness

#

So instead you would need to break up PlayerData into individual items that have independent clocks etc. I can understand why that is hard.

#

Especially given this has to hook into the underlying world netcode which is already under massive pressure

pastel plume
#

Hm. One iffy thing - there's no way to declare persistent data that's not shared with other players. I want to ask for it but I assume there's a reason this hasn't been made available.

wraith bolt
#

No support for targeted network sync in Udon

pastel plume
#

No, I mean no network sync

#

Persistence that's uploaded to vrc's servers for the world, but isn't sent to other players at all

wraith bolt
#

You are still using the network, that is why it uses the same throttling code etc

#

I can only guess tho

pastel plume
#

Even if it is to prevent spamming uploading data to vrc, I feel like we should really be able to have persistent data/settings that aren't network replicated to users other than yourself.

#

Like if I have my own local playlists for a video player for example, and I wanted that to be private. (contrived example)

errant token
pastel plume
errant token
wraith bolt
#

It will be needed; it woukd actually solve the network dump problem with using PlayerData.

pastel plume
#

Can't find it, so will create it

#

doot

quaint night
#

it'd be better if it was the default

pastel plume
#

2 cannys and I've only touched the beta for like 15 minutes... This has to be a record for me. Usually it takes at least half an hour l m a o

quaint night
pastel plume
#

Fair, though I'd imagine it'd be easier to track as a separate canny.

quaint night
#

yeah it's good to have a canny for it

pastel plume
#

Oh, worth clarifying these behavioral questions btw - these all are exclusively for PlayerObjects, not PlayerData:

  • When you join an instance (as a non-master player), and get OnPlayerRestored on objects that aren't yours, can you generally be sure that the data has been received (and written to the heap) for all of that player's udon behaviors, or is this only valid for those objects that have had the event called on them thus far? (i.e. is the call deferred until all udon instances have had the data populated)
  • Is user data for other players in the instance loaded from vrchat's servers every time, or just read off the network for those already in the instance? It talks about state being overwritten if you read/write too early, but the exact lifecycle of data isn't clear here.
  • What is the actual event lifecycle when it comes to OnDeserialization vs OnPlayerRestored? Is there any guarantee of ordering for late joiners when it comes to these two events?
  • When saving data in pool objects, are all pool objects saved to vrc in one batch, or individually? Individually here mirroring how udon network sync works.
  • Will a failed serialization always also cause a save failure, or are there cases where one can succeed while the other fails?
digital scroll
#

is the persistence beta based off open beta or live?

#

ik live and beta are same currently but for future open beta updates

unique rune
#

also is the SDK based on the current beta (b3 I think?) or the release version?

errant token
digital scroll
#

ty ^.^

errant token
pastel plume
#

I'm not sure if this is reportable, cus it's technically correct, it's just confusing. If you have a persistent object that loads data, but it has never been changed in the instance, you get a restored event but not a deserialized event.

While this makes some sense, I feel like this is going to be a footgun for anything that's meant to apply some behavior based on property changes after data has come in from a remote.

#

I'm not sure it should be changed, but might be worth a "heads up" somewhere in the docs? Though I don't know if others would agree with me on that.

hearty kernel
#

Question regarding PlayerObject, lets say I have weapon A and weapon B, The root of the objects have their own scripts, but there is a child object in each that has a component called 'weapon_data' with persistence enabled, does it get affected per object or is it per component script?

#

so like
-Weapon A
--Data
-Weapon B
--Data

pastel plume
#

It's still recursive, but only from the persist component downwards (as far as I can tell from my own tests)

hearty kernel
#

What I am asking is it isolated from one another or do they share save data because same component

pastel plume
#

It works by network ID

#

So the logic that applies to network sync here is also used to pair up synced data (with some asterisks to personalize it per-player)

hearty kernel
#

Ah, so how do I make sure the network ID is consistant to make sure save data isn't lost?

#

Assuming network IDs change

pastel plume
#

As far as I can tell, as long as the network ID tool has the original objects the same, data won't be lost. Clientsim-side it seems to add a prefix per-player, not sure what happens vrc-side but it seems to behave in a similar fashion

#

This even remains working if you change what objects have the persist object on - say you persisted the entire tree, and then moved it to a child - the child would still retain its old data, the parent just won't load it.

Not sure if this means that the data will be deleted server-side after serializing data with the new layout, but based on the documentation I would assume so. Haven't tested that example yet.

wary summit
pastel plume
#

Wheee more cannies. One being wasteful with data for builtin components (vrcobjectsync saving far more data than it really should be), another being misbehavior on restoring (should sync really lerp on load? I don't think so :P)

grand lily
#

hey, i own a world i bought on gummroad, I'm wondering can someone do a easy explain how i add it to the world?

pastel plume
# grand lily hey, i own a world i bought on gummroad, I'm wondering can someone do a easy ex...

You will likely need prefabs that already have persistence in them, or write stuff yourself. It's early days, there's not a lot of pre-built persistence stuff, and the only thing you can persist without udon here is pickup positions - but only within the new player object system, which behaves differently to standard pickups/object pools, so you're going to want to wait for some prefabs to come out.

The behavior is likely to change too, so implementing anything for now is likely to break/change behavior in future up until release.

wary summit
# pastel plume This even remains working if you change what objects have the persist object on ...

If you fully deleted the structure and then re-created it with new objects, then it would lose all those network IDs and the next time you make a build, it will generate new, different IDs for all those objects. Once you do that, it will no longer be able to load the data that was associated with the old IDs.

That said, there are many ways you can reorganize the structure without breaking network IDs.

Once network IDs have been generated for a set of objects at least once, they will be stored in the VRCWorld as an array containing an integer and the reference to the gameobject. This means that it's natively resilient things like name changes, changing parent, adding children, or any other kind of change operation that is still the same object.

Even if you do delete some object with a network ID, that's still not the end of the world because you can always manually edit the VRCWorld's network IDs to reassign that ID to a new object, if you know what it was supposed to be.

Similarly, the network ID tool does the exact same thing except just faster and automatically, by encoding one set of IDs into some json and then using that json to automatically assign the objects in the world to the ID it's supposed to be. that said, there are known issues with the network ID utility right now, so it can't really be used. But rest assured that there's nothing the network ID utility is doing that can't be done manually.

Also, in regards to the persistence-specific behavior about what happens to your saved data - you're exactly correct, only the latest saved record will be stored, and so if you override an old save with a new one that didn't have those IDs, then the data associated with the old IDs will be lost for any player that visited the world on that build of your world.

fervent coral
#

Is using persistence to enforce moderation actions against users prohibited by the TOS of VRChat?

I personally could see alot of people using persistence for this specific reason

#

Say if someone made a world with a "blacklist" that made it so if certain users joined, they would be forced to a sort of "jail" area away from other users?

cerulean lion
#

You don't need persistence for that

#

and yes it's already been done/abused with Udon

fervent coral
cerulean lion
#

your example is just the normal udon blacklist

#

I wouldn't see how persistence can make it abusable even more

fervent coral
#

I guess

spice field
#

like persistence data is use user deletable so that would be bad for moderation

fervent coral
#

oh I didn't know that

#

thats neat I guess

pastel plume
#

Is there the ability to cause a data race between loading persistence and getting network data as a late joiner?
Like say I was serializing data constantly, and a user joins. They start loading persistant data from VRC, and before they get it, data is published on the network that differs. They then get the deserialization for that different data, and then get the data loaded from persistence.

After this occurs, will the player see the network's state, or the persistence state for the remote player doing this? To me they should see the network state, because otherwise you end up with a desync.

#

It's not clear if the load state is safe to deal with before you get remote data for remote players - if not, this seems like a potentially problematic bug which can't easily be worked around without a bunch of unnessecary code to restore network state.

#

Testing this is difficult given you need to cause a race condition, so I'm wondering if there's any word on how this works for remote players.

#

I want to raise a canny for this if it is an issue, but it's extremely annoying/difficult to test.

signal pilot
#

I guess the two sources, "owner client" and "data holding server" (I named them temporarily), are not placed in parallel but in series. If so, a race condition could not happen.

Anyway, I also want to hear from the dev team to clarify.

pastel plume
signal pilot
# pastel plume It's more a question of how the vrc client resolves this situation - I'd *hope* ...

I guess like:

  • The Owner client communicates only with the server. Also, the late joiner client communicates only with the server. (In other words, they are in series structurally)
  • When The server receives the variable value from the owner client, it saves it and distributes it to other clients.
  • When the late joiner client connects to the server, it receives the latest saved value.

So, from the view of the server

  • If the joining is before receiving new value, the joiner client will receive the old value first and soon receive the new value.
  • If the joining is after receiving the new value, the old value no longer exists on the server, so the joiner client will receive the new value only.
pastel plume
sage raptor
#

I would imagine there's actually 3 sources for persistent data: the client, the realtime networking server and one for storage. The storage would basically be just an extension of what manual sync currently does, so it can also save data if the instance is not running, while the realtime networking server would just send the last data it receives

timid kindle
#

what do you mean by this btw? what file? the persistence isn't saved in a file locally, it's saved on the servers

echo hemlock
#

Oh I misunderstood that, my bad

#

Was under the impression that it was stored on user's PC

#

Disregard my question

sage raptor
#

You didn't need to delete it, it would still be a valid question for modifying the data stored in memory, but thats much harder now

abstract narwhal
wraith bolt
#

They don't do a tonne, they just make sure that the networking between clients is passed about; over the years VRC has thrown more functionality onto them, but the servers don't really do much.

#

VRC data sharing in Udon over the network involves making a commit to a document on the network instance and that then gets replicated out. I'd assume that persistent information is schlepped around via this too, rather than working via client read-write to a backend service (which is how I'd write it, tbh)

#

Udon networking has always been quite painful just due to the nature of needing to make sure that server costs stay under control, and what at least appears from the outside to be tech debt; Unity, especially when VRChat wrote its older systems, was very bad at networked games.

feral condor
#

nvm it loaded xD

lime delta
lime delta
abstract narwhal
wraith bolt
#

( ๐Ÿ˜” )

unique rune
lime delta
#

(We checked it's nothing bad or large enough to need announcements, to be clear, just didn't get to making a full changelog since we wanted persistence out)

rapid obsidian
#

hi guys, iโ€™m so sorry if this is the wrong place to put this but, iโ€™m not sure where else to look or ask..

is there any documentation on the persistence stuff at all?

lime delta
rapid obsidian
#

thank you sm!!

unique rune
shrewd sphinx
#

Am I wrong or is there no way to make a global leaderboard? There is no way to get information about players who are not in the instance, and there is no player agnostic world data saving right?

trim cradle
#

persistence currently works on a player bases so no

#

You can only compare it to other people in the instance

wispy latch
#

spread the highscore disease

shrewd sphinx
wispy latch
shrewd sphinx
#

"with death of this instance the highscore will fade away until you meet the legend..."

wispy latch
#

Kinda, but I feel a lot of potential in the idea because it only takes one friend who visited a lot of publics to come to your friend instance and infect anyone who has not.

#

Like real life disease

#

Highscore Infection Virus (HIV)

wary summit
# pastel plume Is there the ability to cause a data race between loading persistence and gettin...

In that particular question, the answer is it shouldn't even be possible to do in the first place because you are not able to set playerdata for someone else or take ownership of someone else's playerobjects. This is not just an API lockout, but rather these objects are under a whole different photon mode where that is literally impossible. Moreover, if you are actively in the instance and serializing, the person joining will not get anything from storage about your data because it only does that when you first join.

That said, the race condition that is actually interesting would be you joining and then immediately spamming your data, and then worrying that you wouldn't get your own save data back. Even then, that should still work because the expected behavior of this is that:

  • other players already in the instance will receive your storage state before you ever have a chance to change it. Once you start changing it, it will override the storage state
  • late joiners will just see the most recently sent state
  • even if you're spamming outbound you should still receive back the storage deserialization because it was already on the way to you before you ever should have been able to start spamming

As for how this works in the backend, some of the speculation here is indeed already very close. You can think of it in two components:

  • the system that provides data from the vrchat API is not unlike another player who temporarily takes ownership over all your objects and sets the state to what it should be, then hands ownership back to you. This only needs to happen once when you join.
  • the server just holds onto the most recent state, and passes it on to the late joiner when they join. This most recent state may be the state from you, or it may be from vrchat. It doesn't care, it handles both the same.
wispy latch
#

Btw, I also had this question if player object instantiation is working on live or not. I assume it's not, but it would be really helpful if it did, for smoothly transitioning my worlds.

marble timber
wispy latch
#

Definitely need some kind of cap on it

#

Interesting, I checked the docs and it looks like it's 100kb on data AND 100kb on objects? And on top of that they compress it on their side. That's honestly a lot to work with

marble timber
#

Ehhhh

wispy latch
#

I guess it depends on what you want to do. I don't think you need 50k highscore entries for example. But you could probably fit a thousand or two if you really wanted to. That's honestly enough

storm maple
#

what extent of persistence is being added? will it be hard for creators to make full on save systems?

echo hemlock
#

How do I get the persistence beta? It isn't showing under steam, only open-beta, do I need to restart my steam to see it?

storm maple
#

also I remember back when roblox had much earlier save systems that there were issues where data could randomly be completely lost, will there potentially be issues where save data gets wiped without the player doing it?

wary summit
wary summit
# storm maple what extent of persistence is being added? will it be hard for creators to make ...

At the moment, this form of persistence allows data to be associated with players and can be accessed only when that player is in the instance. That's the exact type you need for personal save systems, so yes. What is not being added right now is saving the state of an entire instance (like a minecraft realm), or viewing save data of other players not in the instance (like a global leaderboard).

flat mist
#

Thatโ€™s a lotta data

wary summit
# pastel plume Oh, worth clarifying these behavioral questions btw - these all are exclusively ...
  • Yep, OnPlayerRestored is designed to say "all data for this player has been received from storage" or at least "if they had data, it would be here by now". This means that it should come after all OnDeserialization's for any player objects which had a saved state, and by the point you receive OnDeserialization it should be fully safe to read synced data from playerobjects and playerdata.
  • User data for other players is only loaded once when that player joins. The server then holds onto the most recent state, whether it came from you or loading from storage. If you send data too early, it will replace the data which came from storage, which will cause it to be lost.
  • OnPlayerRestored always comes after all other OnDeserializations that came from storage. If there is no data, you may not get any OnDeserializations but you will still get the OnPlayerRestored.
  • Each object inside a playerobject will sync independently. If you have multiple udonbehaviours on one object, they will go together. When you leave the instance, all of the data from those different objects are packaged up by the server into a single bundle and sent off to storage. Playerdata is also packaged up, and has a separate bundle.
  • Failing serialization means it fails to send. If it fails to send, then the server never gets it and it will not affect your saved data at all.
abstract narwhal
shut jolt
#

Pretty sure that world is just using string loader and some server sided shenanigans to do that lol

abstract narwhal
#

Ah figured. Didn't think to check there~

wary summit
#

Yeah I think the timing is just a coincidence and that's a totally different system. Probably works on live

hardy narwhal
#

ah

dusk brook
#

Hello, I read a bit the channel and just to be sure, it's really not possible to do a scoreboard with persistance ? In the documentation it's confusing me because it's saying "each world may store 100 KB of Player Data"

trim cradle
#

You can, but you can only access the data of players in the world

pastel plume
# wary summit In that particular question, the answer is it shouldn't even be possible to do i...

In this specific situation, the data race doesn't involve any kind of ownership transfer.

An example experimental setup here would be a single int on a script incrementing every frame and constantly requesting serialization - this being low enough data that it works approx every frame, managing to time ending this sequence perfectly so something goes wrong.

The failure mode here would be all other players in the instance seeing the correct final state, but a late joiner, who was joining while this occurs, seeing one or more deserialization events from the network, followed by loading from persisitence which may be in an old state. This would either fail by getting stale data only, or getting new data followed by stale data, and staying on stale data due to unfortunate timing.

I'm curious if this situation is ever possible. Depending on how persistence operates, this may be an impossible state to hit, however experimentally I've noticed you're able to get state updated without an OnDeserialization event if the object has never been touched in that instance - though I did notice a flaw in my methodology last night and plan to re-test today to validate that.

#

Basically in short I'm wondering if you can cause a race where your final state is stale due to in memory vs storage loading speeds.

wary summit
pastel plume
#

(When receiving data)

wary summit
#

It's not about priority, it's about which one gets there first. And yes, storage data always arrives before the player does. And that's a good thing because you want it to be ready to go asap

#

I'm not sure how that would be a problem. If you don't want that behavior you don't have to put enable persistence on those objects where it matters

#

Loading data from storage is actually not unlike an ownership transfer. The server takes ownership of your objects and sets the data according to your stored record, then hands it back to you. This all happens before you finish entering.

pastel plume
#

You get the data as it was before you joined, but any data received in that period never arrives.

#

Given that is already a problem in vrc, I'm wondering if a similar issue can occur with persistence loading.

#

My last test for this was months ago, but it's not hard for me to retest.

... Honestly I should probably raise a canny for it if I can still reproduce it. It isn't hard to trigger, if you're trying to do so.

#

First I gotta get out of bed though lmao

wary summit
#

Ok so you're taking an existing bug and extrapolating that it might exist in persistence? Well I'm not familiar with that particular bug, but I'll say that persistence is effectively also a big network update in general so it's possible that bug (if it existed) was fixed by default as part of persistence anyway

#

Regardless, if you have a hunch a bug exists, then yeah go test it

pastel plume
#

I'll go and check in both open beta and persistence beta.

#

Breaks game world sync all the time if your timing is unfortunate.

#

My theory here isn't that it's the same bug specifically, but it'd be in the same class of bug.

pastel plume
#

yep, still exists lmao (this is the old bug)

#

may drop the data altogether, but for now I've only tested the actual deserialization event (and arguably the event itself is what matters)

storm maple
pastel plume
#

... Theoretically you could implement that with a CRDT and a gossip protocol like system, so as players come and go they fill in the gaps and merge data. But that would be a lot.

#

would be funny as hell though

dusk tundra
#

I don't have anything productive to add, just want to express my excitement for persistence. This is HUGE! Could change VRChat in ways we can't even imagine yet. The future is going to be exciting.

pastel plume
#

Udonsharp is still updated in the SDK, but basically all public vrchat gh repos (issues etc) have been neglected. It's basically gone source-available by this point.

#

The one provided in the SDK is updated beyond the gh one

#

And the lord said "lol. lmao even."

errant token
#

We'd like to keep this channel focused on the Open Beta for Persistence, thanks!

wispy latch
pastel plume
rigid smelt
#

Hello I'm new here

wispy latch
covert blaze
#

Anyone taken a crack at saving player position yet?

pastel plume
#

Gonna update the canny for this

#

nvm too late can't do that lol, will just comment

wispy latch
pastel plume
wispy latch
round tangle
#

I can't seem to join the beta?

trim cradle
#

that usually fixes it ^^

round tangle
trim cradle
#

hm weird

#

Can you try verifying the game files?

round tangle
trim cradle
#

No Problem!

errant token
merry widget
#

I'm running a group instance for playtesting persistence in my world, if anyone is interested in joining!
[event over]

abstract narwhal
crisp grotto
spice field
#

The entirety of VRChat Persistence Player Data documentation page screams "don't use this"

When I test Player Data in-client, I feel like it would probably be faster to create a few hundred empty Player Objects per player than use Player Data
I am not the one who is going to try

โ–ถ Play video
errant token
spice field
#

don't have any programming experience myself so no clue

errant token
spice field
#

figured someone who was more knowledgeable in programming would have insight into that as it kind of seems like from the start of the tweet that it was a bit of a weird way to go about it

indigo sluice
#

i do gotta say tho. i'm confused. lots of function in the docs but now where the playerdata actually is located.. is it only accessible in OnPlayerDataUpdated? or am i just missing something.

#

like lots of mention to PlayerData but not where said player data is accessed/retrieved. unless i'm really just that blind and i'm reading over it..

indigo sluice
#

Though this leadds me to believe my IDE is not working correctly then

#

oh wait nope nvm found the issue, that code uses PlayerData.SetInt directly. but when i went off the assumption that PlayerData was a static it told me it was invalid. i didn't consider the fact that it might be in a different namespace. in this case the VRC.SDK3.Persistence all good now o/ thanks @errant token ๐Ÿ‘

errant token
#

Make sure to open Example Central from the menu under "VRChat SDK > ๐Ÿ  Example Central".

There are 10 persistence examples built with U# to get you started using PlayerData and PlayerObjects!

indigo sluice
#

curious though. if playerdata is only accessible from the client of the respective player. why is OnPlayerRestored seemingly sent for everyone? ๐Ÿค”

errant token
indigo sluice
#

oh ok i misunderstood then. good to know.

#

๐Ÿ‘

gray olive
indigo sluice
gray olive
indigo sluice
#

on that note though. success. player movement speed changes are now persistent in my RP world \o/

#

actually. important question. if I update a world with persistance. for people on the old client will running persistance methods break anything or will it just pass over them/do nothing?

gray olive
#

I wonder that too, whats the behavior with other client versions that dont have persistence

#

It wont be issue in future, but it importent for people who relese worlds with persistance right now

errant token
indigo sluice
#

all good. ๐Ÿ‘

#

guess i'll have to convince everyone to start using the persistance beta then ๐Ÿ‘€

storm maple
#

persistence could really potentially open up an explosive amount of possibilities, a game like Phantom Forces on Roblox for instance would not be possible without save data since there's so many things to unlock

compact remnant
jagged cloud
mild dragon
elfin wren
mild dragon
trim cradle
#

I find it weird that you need to login for the example stuff

astral sluice
#

Is it possible to save VrcUrls on a PlayerObject?

#

Would be nice for giving a User the possibility for his home worlds default music

trim cradle
#

That's what I am doing for my image loader for example

astral sluice
#

Nice

trim cradle
#

Saldy you can't use Player Data for that and only Player Objects.

astral sluice
trim cradle
agile perch
#

I am having an issue importing one of my models with the new SDK, the validations aren't showing up, and I have gotten this error that says " Cannot implicitly conver type System Collections Generic" And when I tried deleting it and readding it I get the same error.

I am using the 3.7.2 persistence beta.1

echo hemlock
#

When a player joins an instance, is it better to use OnPlayerDataUpdated or OnPlayerRestored?

#

cuz apparently OnPlayerJoined is called too early

errant token
errant token
echo hemlock
errant token
echo hemlock
broken wadi
#

when comes a persistant client version for quest? I can't use PCVR for testing vrcSad

wary summit
# spice field figured someone who was more knowledgeable in programming would have insight in...

It's important to note that that is the worst-case scenario of playerdata being loaded up to the max. It is fair to be frustrated, but also that's one of the reasons for those limits being set. And while those limits aren't going to be appropriate for larger data, I do think it's still totally fine to use for small amounts of data, and there are many many use cases where that is the case. I don't think it's fair to dismiss an entire feature in all use cases just because there's a small subsection of advanced use cases where it's not appropriate.

Playerdata and playerobjects go well together because they fit into two sides of the same coin. Playerdata is good for when you have basic, simple scripts that just need to save some data occasionally and they don't care where. Playerobjects are good for when you start needing objects per player, high frequency data, or large amounts of data.

Some people are looking at this and the only use cases they're interested in working on will immediately put them straight into playerobject territory, and that's great! That's what they're for! But that doesn't mean playerdata is useless. it's just designed for a different use case. And it's not the end of the world that a 5kb playerdata serializes a few extra times because a handful of different prefabs save to it when the user interacts with them.

echo hemlock
#

so wait I did read again and again and I realize its not possible to make a global leaderboard?

wary summit
echo hemlock
wary summit
wraith bolt
#

everything is possible

#

๐Ÿ˜”

cold echo
trim cradle
#

I mean you can already do that using Player Objects, but it's a bit pain to work with

signal pilot
#

I have an idea of leaderboards. You can make a leaderboard of the current instance. If you save it and refer to it in the next instance, you'll get a merged leaderboard of two instances, which ranks people you met in the game.
Also, you can read the leaderboard other players hold and merge them. By doing so, you can make a more large player-based leaderboard.

echo hemlock
#

unless one player saves everything into one string, but this will quickly going beyond the max limits

jagged cloud
# cold echo base64 encoded?

Yep, binary blob of everything I want saved in the world base64 encoded into a string for more compact storage.

#

It extends quite far down. Lol

wispy latch
#

And yep, that's my plan to, I'm going to make an infection system where people get infected with everyone else's highscore data. ๐Ÿฆ 

echo hemlock
wispy latch
#

Like yeah, you will have to join people, but chances are people who care about highscores will do so anyways

#

Per world persistence would obviously be more ideal

echo hemlock
#

thats really not ideal because that means you will have to use bot accounts to watch instances 24/24

#

they better have to add global persistence before half of the game is populated with bots only

cold echo
jagged cloud
signal pilot
trim cradle
echo hemlock
trim cradle
#

Interesting

#

why would they have that under Networking though

echo hemlock
#

That what I'm wondering as well, does it maintain a synchronized unique name list or is it just local?

trim cradle
#

Also, it has different parameters

echo hemlock
#

Yeah, the existing names parameter, which is why I am suspecting that Networking is providing the list of pre-existing names

trim cradle
#

maybe

echo hemlock
#

Also upvoting your feedback

round tangle
#

How can I clear the client sim persistence data?

rocky pulsar
abstract narwhal
#

Surprised I havenโ€™t come across anymore persistence test worlds. Was hoping to find more since the start of the beta then just the three so far~

abstract narwhal
#

Oh neat. Should probably have a better title for it though. Something likeโ€ฆ โ€œPersistence Test Worldsโ€

hardy narwhal
#

yeah, I renamed.

abstract narwhal
#

Yeah that should do I think.

hardy narwhal
#

hope so

marble timber
#

android beta channel when

hardy narwhal
marble timber
#

like a way to be on the beta on android

#

afaik its not possible rn

hardy narwhal
#

ah, I got point now.

#

maybe too early but yeah, in near feature could.

marble timber
#

I have a big pool of android users that I can be doing testing and UX dev with and I cant test with any of them rn ๐Ÿ˜ฆ

marble timber
#

(namely the ammount of time this has been in dev in closed beta)

hardy narwhal
#

ah...

#

already so many canny since become open beta so maybe once it's got clear some could be.

mossy stratus
#

Can you get player name and add it to a global world leaderboard with the beta or is it just saved settings?

marble timber
#

its per player

#

nothing is global

#

you only see current instance info

mossy stratus
#

interesting ๐Ÿ™‚

hardy narwhal
#

there is canny for it, I saw here earlier.

marble timber
#

with the current way its underlyingly wrote, not going to happen any time soon

#

IMO

mossy stratus
marble timber
#

?

abstract narwhal
#

@errant token, tested out that 'Persistence RPG' world you linked in the world thread and for some reason, it only worked some of the time. Other times it would either spawn me with the wrong position and/or rotation or Persistence just didn't kick in at all.
https://files.catbox.moe/mn0xmr.mp4

agile geyser
#

has anyone else ran into World version is incompatible with this instance.

subtle quest
#

Has anyone been running into weird bugs in non-persistence worlds while running the beta and hanging with people not on the beta? I encountered quite a few issues earlier today but have no idea if it was coincidence.

The first world I had issues with was The Pool Parlor (https://vrchat.com/home/world/wrld_99bdc4c6-b80c-49f3-aae0-5d67017d8340). First the pool table broke and a rejoin did not fix it. We ended up having to make a new instance. Then the world's player voice controls glitched out and made me mute on my friend's end. A rejoin did fix this.

The second world was GeoLocator (https://vrchat.com/home/world/wrld_8abba687-ebfd-4356-846d-d069976df375) where I joined on two non-beta using friends. I was working fine on their end but on my end everything related to those two was broken. Peaking into a logs there was a lot of UdonBehaviors crashing due to "Object reference not set to an instance of an object."

The final world before I went off the beta was Rumbleหธ Disaster Survival (https://vrchat.com/home/world/wrld_8e30e0e5-aae0-4452-9281-6832f5e49b06). The world itself seemed to work fine, but one of my friends didn't exist on my end. My other friend could see and talk to them, but on my end they weren't even showing in the player's in instance list. Also checking the logs they never triggered any on join/leave events.

echo hemlock
#

Is it just me or the LeaderBoard example just give up after the 2nd test?

#
Your script should either check if it is null or you should not destroy the object.
VRC.SDK3.ClientSim.ClientSimNetworkingUtilities+<>c__DisplayClass12_1.<ConfigureNetworkOnScene>b__1 (VRC.SDK3.Components.VRCPlayerObject pp) (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/Networking/ClientSimNetworkingUtilities.cs:67)```
#

nvm apparently every examples just only works once then they are all broken

hardy narwhal
vivid estuary
#

Yeth

subtle quest
# hardy narwhal There is canny which said, if master is on Open Beta, then non-beta joined insta...

Are you referencing https://feedback.vrchat.com/persistence/p/instance-breaks-when-persistence-beta-user-joins-persistence-enabled-world-creat ?

This canny seems to be referencing new, persistence-enabled worlds (the worlds I encountered issues with, at least as of yesterday, were last updated before persistence went into open beta). And the issue described is different from my own. This canny, however, seems closer to the issues I experienced: https://feedback.vrchat.com/persistence/p/other-players-and-incoming-networking-occasionally-do-not-work

Have 2 clients, one on persistence and one to not Create an instance, have your non-beta friend join first Join from beta Be kicked for "World version

A couple times now, only on p-test, I've encountered a bug where I am alone in an instance from my perspective.

hardy narwhal
#

ic

dawn elk
#

What if I made a world where you can paste avatar IDs into something and it would save them and then load them all on the pedestals every time you joined to make like a pseudo avatar favorites list or would making something like that against TOS since itโ€™s a VR chat plus feature to get more favorites?

bronze ledge
#

does anyone know if ios16promax works for vrc?

#

willing to test

abstract narwhal
dawn elk
#

hope so

abstract narwhal
#

Considering you can also just bookmark avatars in your browser.

cerulean lion
#

A18 Pro is basically an M1 chip in a phone, it's really overkill but it'll tackle majority of gaming and even some console games like resident evil

crisp grotto
alpine kettle
cerulean lion
echo hemlock
leaden flax
velvet barn
# echo hemlock I don't think it's different from prismic avatars world which is allowed

It's a little different in that it lets you specify favorites, but yeah, the fact that you still have to go to the world makes it not really the same as VRC+ since you still don't have access on the fly. Nothing about that should violate any existing TOS/guidelines.

Relatedly though, have had plans for implementing a favorites system in the search world for over a year now, had just been waiting on the persistence feature ๐Ÿ‘€

#

Built-in persistence also means I can ditch my hacky web request system for storing persistent world options. Excited this is finally here ๐Ÿ˜Š

upbeat dagger
#

Or a search history

elfin wren
upbeat dagger
#

I would have thought he was talking about an individual's session settings

elfin wren
velvet barn
velvet barn
# elfin wren How were you doing session identification?

In the original version, ip of request + hash sent from the user based on their username, which was combined and itself hashed on the server, and used a cookie to identify the session. This allowed multiple people on the same connection to be differentiated. But when they removed cookies from the request, I had to reimplement it, so it was no longer able to differentiate between users on the same IP. All still hashed though, nothing stored raw.

subtle quest
leaden flax
#

Idk if the world uses both

cerulean lion
abstract narwhal
#

Has nobody else uploaded any test worlds for persistence? I haven't found anymore then the small handful already out there. :v

velvet barn
hardy narwhal
crisp grotto
hardy narwhal
#

thinking same

fluid trellis
#

It uses player objects as a replacement of cyan laser's object pool, and player data to save data.

fluid trellis
hardy narwhal
#

oh....

ember bison
#

Seems like if you're not on the persistence beta and join a world that has persistence it will sometimes break and kick you out. Someone else had this issue when adding persistence to their world

echo hemlock
#

Got a weird problem, on the persistence beta if vrc disconnects me it loads me back in but I'll be alone, my friendswon't see me until we make a new instance, this problem has been really bad today I'm switching back to the regular open beta branch, it only happens with the persistence beta

trim cradle
#

Can we please get persistence in the home world so that we can turn the music off ๐Ÿ˜…

fluid trellis
#

The world works on persistence-beta

ornate mango
granite river
#

anyone notice that the linked persistence docs goes to a page not found?

hardy narwhal
#

huhh

hardy narwhal
#

seems gone...

#

@merry widget Seems persistence docs gone from provided website.

novel flower
pliant cipher
#

Sorry. Hungry.

hardy narwhal
#

odd...if I go from google, it works while direct link not works...

#

ahh, URL domain change...

#

pinned URL changed

novel flower
hardy narwhal
#

๐Ÿ˜‚

abstract narwhal
hardy narwhal
#

lol

errant token
hardy narwhal
#

thanks, I'm 1 finger away from ping you.

errant token
#

fixed now!

hardy narwhal
#

Thank you

magic basin
#

How I sign up for the beta

brittle pivot
#

From the PlayerData docs:

Keys cannot be deleted after being written.

Does this mean that world creators have no way of clearing any player data?

I know I can set the value to whatever is the smallest, but the key is still gonna exist forever, take space, and be synced to every other player until the user manually resets his player data?

verbal spire
#

What worlds support this feature currently?

verbal spire
#

thanks

calm vessel
echo hemlock
#

Hmm unironically, that's something Architech could actually do by rolling out an update to use this.

#

Basically so that the ProTV Prefab would have a toggle for a script to check the persistent to see if there is a toggle to disable autoplay.

#

The only problem with that is it basically messes with developer's access with the persistence storage. I could see people discussing on standardizing the storage access between prefab.

trim cradle
#

Not really, it should just be a different key

echo hemlock
#

That works

trim cradle
#

Or just completely independent if he ends up using Player Objects

subtle quest
#

Maybe they want to make sure people aren't doing shenanigans before giving the ability for scripts to delete save data

fast fable
#

whats this

sly trellis
#

wowwie

abstract narwhal
#

For now though, need to hop off this branch until it is patched. :v

junior goblet
#

(assuming that bug is fixed^) If i upgrade my world to the beta, will people who arent on the beta still be able to join it?
I've not tried any of the beta sdks before.

abstract narwhal
#

They will be able to join, they just won't be able to make use of persistence.

junior goblet
#

Thats fine. Ill just make sure to leave all the existing functionality as is and only add new features with persistence so it doesn't break any existing features. ๐Ÿ‘

mild dragon
abstract narwhal
#

Has that been reported on the canny?

mild dragon
#

No, because it is not a bug. Persistence is still in beta and should not be used in public worlds, if you do you should check that new methods are compatible with non-beta clients.

abstract narwhal
#

Mmmm fair enough.

hardy narwhal
ornate mango
hardy narwhal
#

alright, pin link replaced.

trim cradle
#

If you want to try out a few worlds with Persistence in them then check out this forum post!
https://ask.vrchat.com/t/a-list-of-worlds-using-persistence/27318

If you have made a world or prefab with Persistence feel free to post it in there as well!

Also, check out the Persistence Docs!

trim cradle
#

idk what you are talking about WhiteWolf_Sweat

hardy narwhal
trim cradle
#

I... I was making a joke because I edited the message and added the link yea

hardy narwhal
#

๐Ÿ˜‚

#

(didn't check it yet)

crude grove
#

got an example uploaded last night for others to see.
https://vxtwitter.com/jetdog8808_dev/status/1846982210739700213

junior goblet
#

Is there a way to check if persistence is available on a client? (on the beta) So that specific behaviors can be run / not run if its available

neat grotto
junior goblet
neat grotto
#

No. It's an event on UdonBehaviour which is recommended to wait to fire before trying to read or write persistent data

#

The event will not fire on clients without persistence

#

There's no way to try something without the behaviour crashing

junior goblet
#

Hmm, guess i could just have an empty persistence object that enables all the other ones when / if it's OnPlayerRestored succeeds.

hardy narwhal
fresh mica
#

you gotta stop asking about modding

#

against tos and against the server rules to talk about it

cobalt hatch
marble timber
upbeat dagger
#

Just got onto the persistence beta because of this world
https://vrchat.com/home/world/wrld_f2b1756f-fc8e-4f10-bfdc-6458f0424a09
Anyone know if it's working? It says it's in beta, which I assume is this beta. I don't know much about the persistence system so I'm unsure if I'm not doing something right or if this world isn't functioning. I simply did some stuff to progress and then rejoined to see if my progress persisted. It did not.

Friend-๏ผˆor self๏ผ‰ managed small supermarket serving friendly and floaty robotsโ€คโ€ควƒ ๏ผˆThere will be more groceries and decorative items once we wrap up beta โ„ stress testingวƒ๏ผ‰

abstract narwhal
upbeat dagger
#

Interesting, good to know! Thanks

long mirage
rocky frigate
rapid obsidian
#

hi guys, really just kinda curious, is there any usermade prefabs using this new open beta? Im assuming theres not, due to this being somewhat new haha, but just kinda curious if anyones dropped anything!!!

wary summit
rapid obsidian
wary summit
echo hemlock
#

Been integrating the persistence into my world, just not sure when Persistence would roll out into mainline VRChat, but I imagine it'll be soon.

abstract narwhal
#

I'm expecting Persistence to be ready for Live in sometime Mid to Late November.

#

It's a big update so will cook for at least a month's time.

subtle quest
abstract narwhal
#

Possibly.

alpine kettle
#

is this a beta issue?

abstract narwhal
#

@alpine kettle, this happens when someone on persistence-beta joins a persistence world, and the master of the instance is someone not on the persistence-beta.

alpine kettle
#

oh odd. didn't know @craggy cypress added persistence to his Sky Lanterns world

#

Tagging to double check that that's the case

craggy cypress
#

No I didn't

abstract narwhal
#

Hmm ๐Ÿค”

abstract narwhal
alpine kettle
#

If it's not a persistence enabled world, could it be because I made the instance, but my friend loaded in before me? (I'm on beta, they aren't)

abstract narwhal
#

possibly

lime delta
alpine kettle
abstract narwhal
#

I wonder if it's related to the fact of someone in the persistence-beta pressing the "Create Instance" button in-client and someone on a live or open beta client being the master of that instance. The only thing that clues me to this is specific text in the official persistence test worlds descriptions that says--

WARNING - Instances created via the web will NOT function correctly with persistenceโ€š you must create a new instance from the clientโ€ค

long mirage
#

Persistence beta is missing the thumbnail for the stickers and emojis

ornate mango
ornate mango
# rapid obsidian thanks for the recommendation? are there good places to find these?

There are a couple here, everyone is welcomed to add their own as well ratWICKED
https://ask.vrchat.com/t/persistent-worlds-showcase-share-your-favorites/27318

long mirage
ornate mango
dawn elk
abstract narwhal
dawn elk
#

it doesint show up untill u leve and come back

#

for now

abstract narwhal
#

Oh I see, there we go.

wispy latch
#

I know there are some issues with creating instances, but has anyone implemented both live and persistence saving side by side so far?

#

I have a thing I'm doing that I could do with persistence and just want to make sure I can just upload it with the new sdk so it works both on live and on the persistence branch as long as they create their own instances.

#

Or should I just wait for an update lol

haughty halo
wispy latch
# haughty halo still same problem. it look like it work but it dont work

You didn't change anything though ๐Ÿค”
Are you maybe using chat gpt or something? It's definitely not up to date with the new API. You could try giving it the example code or even the whole page and see if it can help you that way. The code example itself is pretty straight forward though.

haughty halo
#

i did break my world. so for now i just removing save data. try again other days

ornate mango
cunning hamlet
#

with persistence in beta, are one time purchases far off?

#

or are they already implemented

#

kind of like gamepasses on Roblox, buy once keep forever

ornate mango
trim cradle
#

Funny thing about player objects, since they litterally just use networking code my stuff works completely fine on both live and the persistence beta

#

And even if only the instance owner is on p-test my stuff will still work cause I'm doing everything on their client and then just use the networking I already had setup for it

subtle quest
radiant wharf
south night
#

I'm not sure if this should be obvious or not, but just incase, I noticed some weird oddities if you try to join a world built on 3.7.2 (NOT 3.7.2-persistence-beta.1), with the persistence beta client

#

I am guessing the persistence beta client hasn't been updated with the new Udon signing stuff?

#

was noticing some stuff using manual sync with OnPreSerialization() and OnDeserialization() no longer functioning
Edit: Fixed in OpenBeta Persistence Build 1534

lime delta
#

I think the persistence-beta branch is just slightly out-of-date on some features, so this could very well be the case, yes

haughty halo
#

I find that it crashed the world too so I recommend using the test world to get it to work. O.o

wispy latch
wispy latch
#

I guess I'll have to just try it out myself after I'm done with some other stuff. Maybe I'm being too hopeful here

trim cradle
wispy latch
south night
#

after more testing*... on the beta persistence client, the issue with manual sync with OnPreSerialization() and OnDeserialization() not working might not be world version specific
regardless of what version world I join (3.7.2, 3.7.2-persistence-beta.1, older than 3.7.2) I'm noticing issues with it not functioning at all

Edit: Fixed in OpenBeta Persistence Build 1534

tidal whale
#

Howโ€™s it going

elfin wren
#

what?

leaden flax
abstract narwhal
#

Wonder if persistence branch is gonna have any updates soon~

subtle quest
leaden flax
subtle quest
#

it's an old bug

leaden flax
#

But mine is persistence specific, didn't have these issues before...

subtle quest
#

might be new, then

leaden flax
#

I will check later on live to compare the client behavior

leaden flax
#

I tested the non-persistent version and to my surprise it is also a mess, the bug that was reported by orels is still present.

You really have to smack the [DefaultExecutionOrder(ExecutionOrder)] into every single class file for it to work.

I haven't tested that part on persistence again yet though...

#

this might explain some random bugs in my code that I could never reproduce...

subtle quest
#

Personally I've avoided using ExecutionOrder and designing my code without it instead

leaden flax
#

I rely heavily on it:

namespace TLP.UdonUtils.Runtime
{
    public static class TlpExecutionOrder
    {
        public const int Min = int.MinValue + 1_000_000;
        public const int Max = AudioEnd + 1;

        public const int DefaultOffset = 150_000;
        public const int DirectInputStart = -1_000 + DefaultOffset;
        public const int DirectInputEnd = -1 + DefaultOffset;
        public const int DefaultStart = 0 + DefaultOffset;
        public const int DefaultEnd = 999 + DefaultOffset;
        public const int VehicleMotionStart = 1_000 + DefaultOffset;
        public const int VehicleMotionEnd = 1_999 + DefaultOffset;
        public const int PlayerMotionStart = 2_000 + DefaultOffset;
        public const int PlayerMotionEnd = 2_999 + DefaultOffset;
        public const int WeaponsStart = 3_000 + DefaultOffset;
        public const int WeaponsEnd = 3_999 + DefaultOffset;
        public const int UiStart = 10_000 + DefaultOffset;
        public const int UiEnd = 10_999 + DefaultOffset;
        public const int AudioStart = 11_000 + DefaultOffset;
        public const int AudioEnd = 11_999 + DefaultOffset;
    }
}
stark nexus
#

As far as I can tell in U# DefaultExecutionOrder only applies to the order that Update/LateUpdate/FixedUpdate will fire on scripts

#

The directive that it transpiles into in UdonAssembly is even called .update_order

#

So checking the order in Start won't do much

quaint night
#

Start gets fired from Update internally so it's affected, see: ManagedUpdate() in UdonBehaviour.cs

stark nexus
#

Ah awesome, thanks for clarifying that

#

Good to know

#

And PostLateUpdate and the first OnEnable event from the looks of it

idle obsidian
#

Well, I am finally dipping my toes a bit into Persistence stuff. And it has been pretty confusing to try and handle saving lots of data for my world while trying to remain as optimized as possible and also readable and understandable.

I got like, dozens of achievements in my game, each one of them saving their state and date of unlock(through a bool and a long, though I could probably just rely on a single long since if there is data in that index, then the achievement must be unlocked but that's asides from the point rn)

I'm trying to not use some sort of jank system where I iterate over the amount of achievements and ask the PlayerData.GetLong() like, dozens of times. I wanted to use a mere byte array because that seems faster, one single call for the PlayerData and then process the byte array myself. However there is a lot of limits around trying to manipulate and use byte arrays effectively? Lots of work arounds and currently stumped

errant token
idle obsidian
#

Yeah, that seemed to let me compile U#, and it seeeems to have saved an array properly, now I am going to try and read it and see if it's fine

#

kind of forgot you usually use .Length on []arrays and not .Count()

#

Currently saving around 64 achievements so two arrays of bools and longs, and converting into byte arrays each

#

Okay, that seemed to work yeah

#

No weird issues

errant token
#

(as you theorized yourself)

idle obsidian
#

Yeah! Probably gonna do that. 100KB is a lot but, considering this is simply achievements, and I am still due to save a lot more data, I am not looking forward to and I'll have to save as much space as possible

I still wished there had been some sort of implicit way for the PlayerData class to convert any type array into a byte array under the hood :< But hey, I guess I learned something new today!

#

for example, I'll have to save every class stats for every game mode (like this thing int[][] class_gamemode_matchesPlayed )

#

But I think I have an idea on how I want to approach this, still using byte arrays and concatenating names for the keys

errant token
idle obsidian
#

Can you have multiple PlayerObject templates? And each with Persistence enabled on some scripts then?

#

This data does not change often, only when a match ends so there should be plenty of time for data to settle and send with ease.
Also since the players are part of a prefab to use for another world, I want to make sure I isolate the player elements from this "pvp mode" mini game so their PlayerObject only contain the essential

#

Again, unless there is a way to have multiple PlayerObject templates? Then I could consider using PlayerObjects instead for sure

trim cradle
#

Yeah you can mace multiple different player objects

idle obsidian
#

Well, I guess might as well do that now

#

That kind of makes me wonder what the use case for large data with PlayerData would be if I am switching over to PlayerObjects for having too much data :S

lime delta
#

We explicitly recommend against large data in PlayerData afaik, it's really only for small one-off settings

idle obsidian
#

Oh, this might need some updating then D: From the PlayerData doc page

#

I was like "This is large data, but doesn't update very frequently, so it should be fine"

#

But I was not aware of being able to instance many PlayerTemplates

So I could have one PlayerObject template for my Player stuff like their inventory, stats, etc
Another PlayerObject template for my mini-game stats and achievements
And lastly PlayerData for player settings and perhaps story flags

idle obsidian
#

I dont think I am of a fan of making an array of arrays that syncs :S Never done this before and not sure how I should even do this

int[][] class_gameMode_variable where the first index of the array determines the class, and the second determines the gamemode
How would I go about preparing this to be part of a synced PlayerObject for my mini-game data?

velvet barn
idle obsidian
#

parallel arrays? you mean the ones like int[,] like this?

#

I think I remember trying them out but I couldn't use them? I dont remember why but I just know I ran into a roadblock, something that maybe wasn't exposed or it did not like how I was initializing it

velvet barn
#
int[] gamemodeArray = new int[10];```
Just keep the lengths of both arrays in sync, and you can address each with the same index.
idle obsidian
#

wait I'm confused D:

#

this is only two arrays of ints right? that doesn't help me

#

because I need to store for every class, for every game mode

so knight_survival_bestScore
then knight_tdm_bestScore

and so on for every mode and then do
mage_survival_bestScore
mage_tdm_bestScore

for every class

#

and this for all my variables, bestScore, bestDamage, totalTime, etc

velvet barn
#

How many ints are you storing in the bottom-most array?

#

one int for class, one for gamemode. Any more?

idle obsidian
#

just those two, I guess the full thing is this

    public int[][] class_gamemodeGames;
    public int[][] class_gamemodeWins;
    public int[][] class_gamemodeScore;
    public float[][] class_gamemodeDamage;
    public int[][] class_gamemodeBestScore;
    public float[][] class_gamemodeBestDamage;
velvet barn
#

And the bottom-most array in each of those contains how many values representing what variables?

idle obsidian
#

contain the amount of game modes present in the game? And each contain well, the value that the variable is telling me

#

correct me if I am wrong, but isnt this what I am doing with these?

#

an array within an array, correct?

velvet barn
#

Yes. In the example there you have 3 elements in the bottom-array (S, TDM, B). Is that true for all the array variables you mentioned above? (class_gamemodeGames, class_gamemodeWins, class_gamemodeScore, class_gamemodeDamage, class_gamemodeBestScore, class_gamemodeBestDamage, etc?)

#

And are any of those bottommost values redundant across arrays?

idle obsidian
#

Yes, all of them have the same amount of classes and gameModes
and what do you mean by redundant? As if, there were other arrays that stored the same data? Or if any of these share values between themselves from the list from either? Both would be no

#

They are essentially the master data holders, they hold it all, and I access their data whenever I need.

velvet barn
#

In principle, the idea is that multidimensional arrays of consistent length can almost always be expressed as parallel arrays one dimension lower. Taking your above example, it could be rewritten as this:

#

Instead of a single 2d array with 3 slots in the bottom-most array, you could represent it as three 1d arrays with one slot each.

#

If you had 5 elements each in the bottom-most arrays of the multi-dimensional array, it could instead be represented as 5 single dimensional arrays, each of the same length as the top-most multidimensional array.

#

in other words, int[n][m]; allocates a total number of space equal to int[m]; ... int[m];, where there are n int arrays.

idle obsidian
#

This is going to be dozens of arrays by this logic :S I guess its worth noting that every game mode will have one total score, total dmg, and so on so...

#

I guess one benefit is that I am never going to serialize this data for anyone else, but that's going to be a loooooooot of arrays

velvet barn
#

That's fine, it may look like alot but it still scales. And your indexes across arrays remain consistent. Given you explaination, visualize it like this:

#

Each index in each array is your gamemode

#

so totalScore[gamemodeIndex] will return the totalScore value for that gamemode.

#

Would that work for your case?

#

Also has the benefit of letting you mix types in udon's limited array type mixing

idle obsidian
#

Oh, you skippe the 'class' ! The playerClass someone is using like Knight, Bandit, Mage etc

velvet barn
#

So it's score/dmg/etc, per class, per gamemode?

idle obsidian
#

Yes

velvet barn
#

That does get a bit trickier then since it sounds like you're working in a 3 dimensional array space

idle obsidian
#

Sorry if I didnt make myself clear

#

That's exactly what I was about to say

stark nexus
#

U# doesn't support multidimensional arrays, only jagged arrays

idle obsidian
#

It's essentially a 3D array

velvet barn
#

That's okay. That's why I was asking to try to understand ๐Ÿ˜…

velvet barn
idle obsidian
#

I have a feeling my system is going to end up pushing... A LOT of data

velvet barn
idle obsidian
#

Huh, I guess I was already doing parallel arrays then, yay haha

velvet barn
#

In that case, how many gamemodes and classes do you have?

idle obsidian
#

That can scale as I want to add more BUT
Classes = 8
Game Modes = 5

velvet barn
#

Right. Well it's a bit more manual, but if you smear out the gamemode dimension into their own variables, you could still manage to store the data as collections of 1d arrays, clustered by gamemode.

#

So this, then just make arrays for totalScoreGM2, etc

#

It's not ideal, but my I don't think udon can sync arrays of arrays, so it's either that or serialization as a string or something else

idle obsidian
#

You know, now that you mention a string...
Wonder if I can brute force save everything in a string that gets converted into a JSON/DataDictionary

#

or rather, convert everything into a datadictonary, then into a json, then into a string.... god

velvet barn
#

Especially if it's just when you save/load for persistence, that's probably the best way

idle obsidian
#

I cant believe I am about to do this

#

Because I could have arrays of strings, and those strings are just technically more arrays

#

Well here goes nothin'

velvet barn
#

Yup! Sometimes you gotta make do with what you've got to work with. And even if a bit roundabout, a possible solution is still better than no solution ๐Ÿ˜…

stark nexus
#

Gotta cope until Udon 2 comes out so we can store data in structs

idle obsidian
#

yeah no, I'll take this tbh! When I think about it, these strings would probably be like "[0,2,3,4,5]" so they are not even that big

velvet barn
#

What's a ulong except 8 bytes each up to 255 stuck together hehe

idle obsidian
#

Oh jesus...

#

I dont know if I am ready to bitpack things. First I want to make sure this works

velvet barn
#

Nah, bitpack all the things!

#

๐Ÿ˜›

stark nexus
#

Can also create a series of arrays int[] BestDamageGameMode0...int[] BestDamageGameModeN and use Get/SetProgramVariable to manipulate them

idle obsidian
#

!!

#

Yknow, that sounds like the Udon Jank way, but I WAS thinking about it

velvet barn
idle obsidian
#

oh

#

right that too

#

its essentially a 3D array

#

or 2D arrays on parallel

#

so uh, I'm not gonna write all of them down like that

#

Its okay, I appreciate this much help tho

velvet barn
#

Good luck!

wicked idol
#

any worlds that use this well? curious

velvet barn
# idle obsidian That can scale as I want to add more BUT Classes = 8 Game Modes = 5

It just occurred to me that if you only had 4 gamemodes, you could actually pull this off with arrays of vector4's, since those are an udon syncable type. Would effectively function as an 2d array where the bottom-most array is limited to 4 floats. https://creators.vrchat.com/worlds/udon/networking/

Multiplayer experiences are the heart of VRChat, so creating a world that reacts to players and synchronizes the data between them is key.

idle obsidian
#

Aawh, alas I wished

velvet barn
#

You could also use Color32 to act as 4 bytes (0-255) without having to bitpack

#

But yeah, just food for thought for anyone else who comes across this lol

idle obsidian
#

12 ints
2 floats
6 string[]
4 int[]
4 float[]

is the total tally of elements I need to serialize everything

#

I really hope I dont run into the problem I ran long time ago

#

Here's a quick question actually focused on Persistence. Does the PlayerObject with synced values... have to send a SerializationRequest in order for the data to save?

idle obsidian
#

Considering this is the only thing I got after only setting the variables... uh, not sure if its working lol

*Object is networked as Manual
*Object with the script has the PlayerObject component
*Object with the script has the Persistence component

idle obsidian
#

you have to requestserialization oh god

lime delta
#

Yes, data is persisted on the server where network data goes through, so if you don't serialize it, it won't be stored

idle obsidian
#

at first I was confused, but after that it makes sense

idle obsidian
#

Alright, I saw that my data was being written but not read. Turns out JSON numbers are stored as doubles whoops
But I think with this, I have managed to understand PlayerData and Objects, and how to work with them

#

Neat

idle obsidian
#

I have a new question. If I were to update the names of variables in this script, would they no longer get that data again?

#

As in, their previous data is lost?

lime delta
#

Yes, same rules as when you upload a new version of a world and someone in an instance rejoins.

idle obsidian
#

Gotcha, thank you :3

silent echo
idle obsidian
silent echo
#

Thanks! I believe the stats themselves are okay, the stats display itself may have some update issues as it's fairly new, but I will look into it. I certainly do probably still have some bugs lurking about.

idle obsidian
#

Oooh okay sure! Also forgot to mention that this only happened after my friend killed me and themselves using a pipebomb while we were selling scrap

elfin raft
#

Anyone else no longer able to visit players on the live client? I keep getting "World is incompatible with current platform" when trying to use the persistence beta client with regular instances now.

idle obsidian
#

Same here

south night
#

I assume this is because the persistence-beta doesn't support Udon Code Signing yet
if the world supports Udon Code Signing (3.7.2) and the instance master's game client supports it (live build), you probably won't be able to join

#

I would honestly only use the persistence-beta to test persistence related stuff right now

idle obsidian
#

oooo yknow, that's a pretty good point