-
Notifications
You must be signed in to change notification settings - Fork 703
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
Core: Add "CounterOption", use it for generic "StartInventory" and Witness "TrapWeights" #3756
base: main
Are you sure you want to change the base?
Conversation
Well, what did I do then |
Of note, this makes Subnautica fail differently if all values are set to 0. Previously it failed trying to generate the options, but now it would fail in Subnautica's own |
The same thing happens on main when you put In fact, the same should be true for all cases - "All 0s" will yield the same behavior as |
Ok, Exempt-Medic and I went over a lot of the cases of worlds using The big problem would be this:
as this would no longer work - Counter objects never KeyError. I think every other difference between a The only supported worlds using Happy to be proven wrong, in which case I can either amend the implementation of CounterOption, or drop the idea of changing StartInventory/ItemDict to a CounterOption if necessary. |
you're only doing the culling and negative erroring for ItemDict which is a subclass of CounterOption, so TrapWeights can have negative values which sounds unintended from your description. |
TrapWeights still has a Schema. On main, it is an OptionDict with a Schema, not an ItemDict. I had a PR open changing it to an ItemDict, but I closed that in favor of this. Update: TrapWeights no longer has a schema, as I added |
Options.py
Outdated
|
||
|
||
class CounterOption(OptionDict): | ||
min: typing.Optional[int] = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debatable but I think a default min of 1 probably has the most universal use cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about that? I'm aware of three options that use this or would want to use this, and two of them want min = 0.
Options.py
Outdated
def __init__(self, value: typing.Dict[str, int]): | ||
if any(item_count < 1 for item_count in value.values()): | ||
raise Exception("Cannot have non-positive item counts.") | ||
# Backwards compatibility: Cull 0s to make "in" checks behave the same as when this wasn't a CounterOption |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is just for back compat and verify is called after the option itself is initialized, min should probably be 1 and just leave the culling.
Separate conversation ig but it seems weird to leave in the culling at all since it's not like the actual option was getting those keys with 0 Val already
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh, hm, I definitely intended that for start_inventory, {"Sword": 0}
is a valid input now.
test_option_presets probably needs to updated from ItemDict to CounterOption. Also "options api.md" should probably include information on the new option type |
@@ -93,8 +93,8 @@ <h1>Player Options</h1> | |||
{% elif issubclass(option, Options.FreeText) %} | |||
{{ inputs.FreeText(option_name, option) }} | |||
|
|||
{% elif issubclass(option, Options.ItemDict) and option.verify_item_name %} | |||
{{ inputs.ItemDict(option_name, option) }} | |||
{% elif issubclass(option, Options.OptionCounter) and option.valid_keys %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change from verify_item_name to valid_keys makes StartInventory no longer appear anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gonna have to investigate that, because I thought verify_item_names
makes it build a valid_keys from the metaclass
Been a while since I tested this now tho
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it did not work the way I thought it did. StartInventory should be back & code is now more flexible but also significantly uglier :/
Code seems fine (I didn't test it :)) but the docs definitely should be updated as part of this PR. |
True, I'll mark this as waiting on author for docs changes |
The purpose of this is best explained here:
#3754
Basically, CounterOption is an option whose value is a collections.Counter.
This means that (unlike an OptionDict), the values are always ints.
This means they can be rendered on the Website using the same code as ItemDicts, as long as they have valid_keys defined.
In fact, the ItemDict class has been changed to be a subclass of the new CounterOption.
For backwards compatibility (ensuring that
in
checks resolve the same way as before), ItemDicts make sure to cull 0s first before making the Counter.This does make a change to Starting Inventory behavior:
starting_inventory = {"Sword": 0}
now behaves as if you had writtenstarting_inventory = {}
, instead of crashing. Imo this is an improvement, but your mileage may vary.Tested:
Webhost Player Options: "Export Options" button, "Generate Single-Player Game" button
Generate: With yamls with varying keys missing or present
Not tested:
Advanced Options Page
Thing I'm unsure about:
Whether the Utils.py change is safe