Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version Updates #63

Open
2 tasks
Ishadijcks opened this issue Apr 9, 2021 · 3 comments
Open
2 tasks

Version Updates #63

Ishadijcks opened this issue Apr 9, 2021 · 3 comments

Comments

@Ishadijcks
Copy link
Contributor

Ishadijcks commented Apr 9, 2021

As your game grows, you will add and remove functionality. Your save files should be able to handle this and not crash when someone loads an older save

Now there are some considerations to be made. Previously loading went like this.

  • Get saveData from localstorage
  • Parse saveData in each feature, add defaults if missing data.
  • load(saveData).

Now the parsing step is missing, and we directly load the data from localstorage. You can still easily do defaults with

load(data: SaveData): void {
  this.money = data.money ?? this.money;
}

Which is fine. We will have to applyUpdates() between initialize() and load()

But I'm not sure all desired functionality, like refunding upgrades can still be achieved in the current state.

Possible API

new VersionUpdate('0.1.2'), (data, features) => {
  // Refund people who bought deleted upgrade
  if (data.exampleFeature.upgrades[1].level > 0) {
    features.wallet.gainMoney(3000);
  }
}

Requirements

  • List of old savefiles with their version, run a test that loads all of these into the current version and fails on any error.
  • Run a custom function per game version. This function takes in the save file and applies any changes that need to be made.
@HLXII
Copy link

HLXII commented Apr 10, 2021

I'm curious how you'd handle the case of depreciating a property but still requiring it for the version skew update.

So if I have data.exampleFeatureOne.listOfNum, which has been updated to be stored in data.exampleFeatureTwo.newList (not sure why you'd be moving save data to a new feature, but just a contrived example. This might be more relevant if you're converting from storing objects into some other storage method).

In the VersionUpdate method, if the data object is typed with the SaveData templates, you won't have access to the old listOfNum property anymore unless you typecast to any. Would that be the only solution?

@Ishadijcks
Copy link
Contributor Author

Ishadijcks commented Apr 10, 2021

You're right, the old data structure doesn't exist anymore. So I think your only action is to cast it to any and do

data.exampleFeatureTwo.newList = data.exampleFeatureOne?.listOfNum

Although I just realized another possible problem, if you move the same object 2 times:

versionB() {
  // This featureB doesn't exist, as we're at featureC
  data.featureB.x = data.featureA.x
}
versionC() {
  // Have to make sure that featureB was actually created
  data.featureC.x = data.featureB.x
}

So that might be tricky

not sure why you'd be moving save data to a new feature
It happens, sometimes you want to merge/split features.

@bbugh
Copy link

bbugh commented Apr 21, 2021

Having faced this as a professional game dev, a common pattern is to use a version field for the save games. Then when the save is loaded, you incrementally upgrade the save to each version. Like v2 would add a field, v3 would remove 2 fields, v4 adds a new feature. Along the way you transform the save based on the need of that version, and when you get to the end you have an up-to-date save you can pass in to the game. For example:

if (save.version < 2) {
    save.someField = 5
}

if (save.version < 3) { 
    save.anotherField = save.removedField * 5;
    delete save.removedField
}

if (save.version < latestSaveVersion) {
    save.version = latestSaveVersion
}  

startGameWithSave(save)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants