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

Duplicate active game and settings instance in Vuex #1230

Merged
merged 4 commits into from
Feb 29, 2024

Conversation

anttimaki
Copy link
Collaborator

No description provided.

Copy link
Collaborator

@MythicManiac MythicManiac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, but again going to question the need for having all of this functionality in the same VueX modules. In my opinion there are distinctly different functionalities being mixed together right now that have no reason to be as highly coupled as they are.

Anyway, nothing I'd consider a blocker for merging

Comment on lines +594 to +596
static get defaultGame(): Game {
return this._gameList.find(value => value.internalFolderName === "RiskOfRain2")!;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just hardcode the pointer to this game instance? Why do we need to enumerate any lists? We know the exact value this should point to at build time, there's no need to leave room for uncertainty

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure why this has been implemented like this earlier. Took a quick peek now at the git history but that didn't provide much information. I can change the implementation if we think that's safe to do, but that'll have to wait until after my vacation.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fairly sure it was done this way because of uncertainty towards moving to a cloud based game list. If the game were to be removed then we'd return undefined rather than erroring on the .internalFolderName because _gameList.RiskOfRain2 wouldn't exist in the result

Comment on lines 175 to 182
const getDefaultGame = () => {
const defaultGame = GameManager.unsetGame();

// Don't trust the non-null asserted typing of .unsetGame().
if (defaultGame === undefined) {
throw new Error("GameManager.unsetGame() returned undefined");
// Don't trust the non-null asserted typing of GameManager.defaultGame.
if (GameManager.defaultGame === undefined) {
throw new Error("GameManager.defaultGame returned undefined");
}

return defaultGame;
return GameManager.defaultGame;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And as there's no need for uncertainty, this entire snippet can be removed

src/pages/Manager.vue Show resolved Hide resolved
@anttimaki anttimaki force-pushed the move-local-mod-list-store branch from 8fa0b21 to 25d0c82 Compare February 23, 2024 07:46
The old name was a bit confusing since it could be read as a method
that resets the active game stored in GameManager's internal state.
Set the game when user proceeds (or is automatically redirected) from
game selection screen. Update the settings whenever game is changed
properly via action. To ensure the settings are properly loaded, they
should be accessed via getter rather than directly from the state. This
is not ideal but we're constrained by the fact that actions are the
only part of Vuex that supports async operations and provides access to
both local and root state/getters/mutations/actions.

The change means that the GameManager is no longer the single source of
truth in the matter. This is a trade-off with eventually being able to
do more business logic in Vuex store instead of the UI components.
SearchAndSort now accesses only Vuex, which handles updating the local
state and the persistent settings storage.
- If profile/loadOrderingSettings is called in SearchAndSort, its
  sibling component LocalModList has already tried to access related
  settings
- Move resetting mod list when changing between profiles from Profiles
  component to Manager, since that seems to work too and feels like a
  more correct place for it
- Move modFilters/reset call from Manager's created to beforeCreate.
  The location doesn't really matter since the components that use the
  related settings aren't mounted initially, but for consistency's
  sake it's called in the same place as the rest
Base automatically changed from move-local-mod-list-store to develop February 23, 2024 07:56
@anttimaki
Copy link
Collaborator Author

going to question the need for having all of this functionality in the same VueX modules. In my opinion there are distinctly different functionalities being mixed together right now that have no reason to be as highly coupled as they are.

To clarify, are you referring to having the active game and settings in the root store? Or the new dispatchers in profile module? In either case, what would you suggest as a sensible structure?

Comment on lines +594 to +596
static get defaultGame(): Game {
return this._gameList.find(value => value.internalFolderName === "RiskOfRain2")!;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fairly sure it was done this way because of uncertainty towards moving to a cloud based game list. If the game were to be removed then we'd return undefined rather than erroring on the .internalFolderName because _gameList.RiskOfRain2 wouldn't exist in the result

Comment on lines +655 to +656
// Reset the mod list to prevent the previous profile's list
// flashing on the screen while a new profile's list is loaded.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually solve it? The beforeCreate is async and I'm not sure if Vue even awaits for this to complete before rendering

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about the race condition either, but I think it's safe to say this should at least improve the situation if nothing else

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ebkr might be correct and keeping the mod list resetting in Profiles.vue might be safer to avoid a race condition. I made the move here mostly because having Profiles.vue manage state on behalf of the Manager.vue is not ideal, but obviously less-than-ideal code that works is better. I'll look into this a bit more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm under the assumption that everything that relies on this would get re-rendered if it changes regardless if there's a race condition or not, so it wouldn't be a problem?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this by making the Vuex dispatch function sleep a bit if an empty array of mods was passed to it. As a result, when called in beforeCreate, it rendered the proper mod list first, and then once the sleep finished, rendered the view with empty mod list. So a totally artificial test and quite unlikely that earlier call with empty array would complete later than a later call with non-empty array. But theoretically possible since the first call isn't awaited, methinks?

@MythicManiac MythicManiac merged commit c823c70 into develop Feb 29, 2024
7 checks passed
@MythicManiac MythicManiac deleted the vuex-active-game branch February 29, 2024 17:36
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

Successfully merging this pull request may close these issues.

3 participants