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

WebHost, Core: Developer-defined game option presets. #2143

Merged
merged 15 commits into from
Nov 16, 2023

Conversation

ThePhar
Copy link
Member

@ThePhar ThePhar commented Sep 3, 2023

What is this fixing or adding?

Adds a new attribute on WebWorld called options_presets which is a Dict[preset_name: str, Dict[option_name: str, custom_value: any]] that world developers can use to define special option presets for games displaying on the WebHost. The default values for any Option-derived option is also automatically added to a "Defaults" preset for easy resetting of option presets. (no more manual clearing local storage!)

This also adds a new drop down for presets that will automatically set the settings accordingly for the player on the website. See below gif for an example.

This PR also makes a couple tweaks to Player Name field to remove default value and display the placeholder value instead, allowing players to use "Player" as a name if they so desire. Also tweaks the description property in the outputted YAML to include preset name, if one was used.

For an example, check out the presets I created for rogue_legacy in the Presets.py file. You will also note that any options that are not manually listed in the preset dictionary will use the default value on the Option-derived option instead, so you don't have to manually add every individual option if they're staying as a default.

Things that still need to be done:

  • Add error handling for if a developer goofs and types an invalid option name or option value.
  • Probably a unit test to check the above!

How was this tested?

Ran WebHost and test.

If this makes graphical changes, please attach screenshots.

Example of a game with presets defined:
presets

For games without custom presets defined:
image

@ThePhar ThePhar added is: enhancement Issues requesting new features or pull requests implementing new features. affects: webhost Issues/PRs that touch webhost and may need additional validation. labels Sep 3, 2023
const preset = localStorage.getItem(`${gameName}-preset`);
switch (preset) {
case "__default":
settings["description"] = `Generated by https://archipelago.gg with the default preset.`;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This case does exactly the same thing as the default case, it's therefore not necessary

Copy link
Member Author

Choose a reason for hiding this comment

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

Negative, because it would output Generated by https://archipelago.gg with the __default preset. because it uses the value (not the display name).

Copy link
Member Author

Choose a reason for hiding this comment

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

And I don't want that :P

Copy link
Collaborator

Choose a reason for hiding this comment

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

In that case, if __default and __custom include the leading underscores, would other presets also include it? Should it maybe get trimmed away here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Other preset names shouldn't have the leading underscores.

@nicholassaylor
Copy link
Contributor

Perhaps we can have "All Random" as one of the pre-fab presets for all games. That way, the dropdown isn't simply a reset button for games that don't have developer-provided presets.

@el-u
Copy link
Collaborator

el-u commented Sep 4, 2023

Perhaps we can have "All Random" as one of the pre-fab presets for all games. That way, the dropdown isn't simply a reset button for games that don't have developer-provided presets.

Since "All Random" is a terrible idea for my world, I would actually prefer not having anything that could encourage people to do that.
One could probably just hide the whole dropdown for worlds without custom presets.

@LegendaryLinux
Copy link
Member

I want to maintain player name not being allowed as "Player." It forces people to enter a name, and prevents name conflicts when people try to generate a game if multiple people forgot to put in a name.

@nicholassaylor
Copy link
Contributor

I want to maintain player name not being allowed as "Player." It forces people to enter a name, and prevents name conflicts when people try to generate a game if multiple people forgot to put in a name.

Taking a look at the changes, it appears that "Player" is no longer the default value in the player-name field and instead has placeholder text. Assuming we make this field required, I think we can both allow the slot name to be "Player" and force names to be entered when generating YAMLs on the site.

@LegendaryLinux
Copy link
Member

Eliminating the default value and requiring a value during validation is acceptable.

@LegendaryLinux LegendaryLinux self-assigned this Sep 12, 2023
Copy link
Member

@LegendaryLinux LegendaryLinux left a comment

Choose a reason for hiding this comment

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

We should hide the presets <select /> if only the default value exists. Other than that, this looks good and I'll approve.

@ThePhar
Copy link
Member Author

ThePhar commented Nov 13, 2023

I don't want to hide the presets because it allows an easy way to reset all settings BACK to default values. Hiding the box removes that functionality.

@ThePhar ThePhar changed the title WebHost: Developer-defined game option presets. WebHost, Core: Developer-defined game option presets. Nov 13, 2023
@ThePhar ThePhar added the affects: core Issues/PRs that touch core and may need additional validation. label Nov 13, 2023
# Conflicts:
#	WebHostLib/options.py
#	WebHostLib/static/assets/player-options.js
#	WebHostLib/static/styles/player-options.css
@ThePhar
Copy link
Member Author

ThePhar commented Nov 13, 2023

As of this last commit, the options now look like this:
image

@ThePhar ThePhar marked this pull request as ready for review November 13, 2023 05:00
@alwaysintreble
Copy link
Collaborator

I don't like the use of meta here as meta options already have actual defined functionality

@ThePhar
Copy link
Member Author

ThePhar commented Nov 13, 2023

I don't like the use of meta here as meta options already have actual defined functionality

I'm open to alternative names.

Edit: I just removed it. New layout below:
image

Comment on lines +125 to +126
if option_value == "random":
player_options["presetOptions"][preset_name][option_name] = option_value
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this codepath can only be reached if option_value is "random", just explicitly assign "random" here

Copy link
Member Author

Choose a reason for hiding this comment

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

option_value is "random". Why hardcode two strings, when one does the same thing?

WebHostLib/options.py Outdated Show resolved Hide resolved
worlds/rogue_legacy/__init__.py Outdated Show resolved Hide resolved
test/webhost/test_option_presets.py Outdated Show resolved Hide resolved
WebHostLib/templates/player-options.html Outdated Show resolved Hide resolved
WebHostLib/options.py Outdated Show resolved Hide resolved
test/webhost/test_option_presets.py Outdated Show resolved Hide resolved
WebHostLib/options.py Show resolved Hide resolved
@el-u
Copy link
Collaborator

el-u commented Nov 13, 2023

There's a bunch of option types (such as OptionList) for which trying to use them in a preset makes the WebHost fail to start.

@ThePhar
Copy link
Member Author

ThePhar commented Nov 13, 2023

There's a bunch of option types (such as OptionList) for which trying to use them in a preset makes the WebHost fail to start.

OptionList, OptionSet, OptionDict, and FreeText are not supported. As listed in the docs.

@ThePhar
Copy link
Member Author

ThePhar commented Nov 13, 2023

I suppose I could explicitly check for those in the test to ensure they're not used.

Copy link
Member

@LegendaryLinux LegendaryLinux 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. I sign off on the HTML / JS / CSS. Nice work, Phar.

test/webhost/test_option_presets.py Outdated Show resolved Hide resolved
test/webhost/test_option_presets.py Outdated Show resolved Hide resolved
)
else:
self.assertTrue(
option.name_lookup[option.value] == option_value,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could check that option.value is in option.name_lookup first (or just use get) instead of failing with KeyError

with self.subTest(game=game_name, preset=preset_name):
for option_name, option_value in preset.items():
try:
option = world_type.options_dataclass.type_hints[option_name].from_any(option_value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we call verify on the option here?

Copy link
Member Author

Choose a reason for hiding this comment

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

verify needs additional setup that I didn't think was necessary for this test.

@el-u
Copy link
Collaborator

el-u commented Nov 15, 2023

I have a bunch of options that don't work properly with this, but they are all custom classes and are caught by the test, so I guess it's fine.

@ThePhar ThePhar merged commit 79ad546 into ArchipelagoMW:main Nov 16, 2023
12 checks passed
@ThePhar ThePhar deleted the game_option_presets branch November 16, 2023 10:37
el-u added a commit to el-u/Archipelago that referenced this pull request Nov 16, 2023
remyjette added a commit to remyjette/Archipelago that referenced this pull request Jan 9, 2024
 ArchipelagoMW#1820 added the game name to template export, but when ArchipelagoMW#2143 began
overriding the description in Javascript to name the preset it removed
the game name.

Also while I was here I figured we might as well not hardcode
https://archipelago.gg, since it can be useful to know if a YAML was
generated by some other Web Host (for example
http://archipelago.gg:24242 if coming from the beta site)
Jouramie pushed a commit to Jouramie/Archipelago that referenced this pull request Feb 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects: core Issues/PRs that touch core and may need additional validation. affects: webhost Issues/PRs that touch webhost and may need additional validation. is: enhancement Issues requesting new features or pull requests implementing new features.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants