VRChat can remember things about a player between visits. The API it gives you for that is a
key-value store with a method per type: `SetInt`, `GetInt`, `TryGetInt`, and the same three again
for each of sixteen types.

Three things about it go wrong quietly.

**You have to remember which method wrote a key.** Read `"level"` with `GetString` when it was
written with `SetInt` and nothing complains — you get an empty string and carry on.

**`GetInt` returns zero for a key nobody wrote,** which is also what a saved zero looks like. A
shop that gives newcomers a starting balance cannot tell a new player from one who spent
everything.

**Saved data is not there yet in `Start`.** It arrives a moment after the player does. Read too
early and you get defaults rather than an error, so the world behaves perfectly in the Editor,
where there is nothing to restore, and greets a returning player as a stranger.

This package is two verbs and a base class:

```csharp
public class Shop : SaveBehaviour
{
    private int coins;

    public override void OnSaveReady()
    {
        coins = Save.Get("coins", 100);
    }

    public void Buy(int price)
    {
        coins = coins - price;
        Save.Set("coins", coins);
    }
}
```

The value decides the rest. `Save.Set("name", "ada")` stores a string and `Save.Set("coins", 5)`
stores an integer, without you naming either. Reading takes the value you want when nothing is
saved, which is the same value you would have written in the `if` below a `TryGet` — and having
to write it is what separates "never saved" from "saved as nothing".

`OnSaveReady` runs at the only moment reading means anything. Put your loading there instead of
in `Start` and the ordering stops being something you have to remember.

## What is here

| | |
|---|---|
| `Save` | Set and Get, for every type VRChat stores |
| `SaveBehaviour` | `OnSaveReady`, which runs when the data is real |
| `PlayerObjects` | Finding the copy of an object that belongs to a player |
| `Storage` | How much of a player's allowance the world has spent |
