Add Modes#1041
Conversation
d6ea4ee to
b24bc6d
Compare
cef7eea to
e59088f
Compare
|
Marked as draft because I tested and this isn't working as-is. With BAR on branch pr/5074 and BYAR-Chobby on branch pr/1041 clicking on Skirmish does nothing and produces the following error: |
6a15372 to
f2c74d8
Compare
|
Converting this to draft again. It is technically ready for review (and entirely functional) on this side but the BAR side is not quite feature complete yet so holding off until the whole package is ready to go. |
f2c74d8 to
7c97c3f
Compare
3e7771b to
b4c8803
Compare
d17cddd to
f2c842d
Compare
|
|
||
| isProgrammaticUpdate = true | ||
| if not allowRanked then | ||
| localModoptions["ranked_game"] = "0" |
There was a problem hiding this comment.
When a mode has allowRanked false this forces ranked_game to '0', but I don't see anywhere that sets it back when you switch to a mode that does allow ranked. So if I pick a non-ranked mode and then switch back to a ranked one, won't ranked_game stay at '0'? And since it goes out through SetModOptions as a normal value change, I think it actually gets sent to the host, not just shown locally. It's also easy to miss because SetRankedModeAllowed just below doesn't seem to be defined anywhere, so nothing updates the battle-room UI. Could this restore ranked_game on the allowRanked path?
| end | ||
|
|
||
| if mode.modOptions then | ||
| for optKey, rule in pairs(mode.modOptions) do |
There was a problem hiding this comment.
This only sets or clears lockedOptions for keys that are in the new mode's modOptions, and lockedOptions itself looks like it's only reset when the window is first created, not here. So if mode A locks an option and you then switch to a Customize/retain mode that doesn't list it, won't that key keep its old lockedOptions entry and then get overwritten with the server value on Accept? I think someone who had set that option would see it silently revert. Would resetting lockedOptions at the top of applyMode, the same way modeLocked is rebuilt, fix it?
| mode_key = params[1] | ||
| kv_params = params[2:] | ||
|
|
||
| category_data = _as_dict(_modes().get('categories')).get(category) |
There was a problem hiding this comment.
This calls .get('categories') straight on whatever _modes() returns. If the fetched or cached json is ever not an object (a list, say), won't that throw an AttributeError right into the perl bridge? The accesses below it go through _as_dict but this first one doesn't. Could the top level be wrapped the same way?
| if isinstance(spec, dict) and spec.get('locked') | ||
| ) | ||
| for (key, _val) in settings: | ||
| if key in locked_keys: |
There was a problem hiding this comment.
The user's key gets lowercased up at line 209, but locked_keys is built from the mod_options keys as-is. So if a mode locks 'ResourceMult' and someone passes resourcemult=something, won't this check miss it and apply the override anyway? I think BAR option names are all lowercase in practice so it may not bite today, but it makes the lock weaker than it looks. Lowercasing both sides would close it.
|
|
||
| for url in urls: | ||
| try: | ||
| with urllib.request.urlopen(url, timeout=_FETCH_TIMEOUT) as resp: |
There was a problem hiding this comment.
This is a synchronous urlopen on what I understand is SPADS's single thread, with a 5s timeout and up to two URLs, so a slow or unreachable release could stall the host for around 10s on the first !mode after a rehost. From what I can see the vote-eligibility check reaches it too, which a normal player can trigger. It's once per version so not constant, but a multi-second freeze of the autohost still seems bad. Could this be backgrounded or moved to load time?
|
I'm not deep in the SPADS side or a lot of this Lua, so some of this might be me misreading it.
|
Add the server-side ModeCommand SPADS plugin backing the Chobby sharing tab. !mode <category> <key> [opt=val ...] expands a mode preset to its full modoption set (a bare !mode applies the whole preset) and levels each option identically to the built-in bSet, rejecting unknown option keys instead of silently setting them. Game-mode/preset data is fetched directly via the plugin and pinned to a short-sha game version, reading the host-regenerated game_modes.json (which replaces the committed sharing_presets.json; the generated file is gitignored). The plugin records the selector key so the client can reflect an externally-set mode.
Add the sharing tab to the modoptions panel and battle room: pick a sharing mode, route the category change through the !mode plugin, and reflect a mode set externally (live-refreshing the panel when it changes under us). Mode descriptions show as hover tooltips. Introduce a shared ModeResolver (libs/liblobby/lobby/moderesolver.lua) that resolves a mode + user deviations to a full modoption set, used by both the panel and skirmish so single-player expands a mode locally with the same logic the SPADS plugin mirrors server-side. !mode deviations are scoped to the mode's own options, and only deviations are sent (guarded against the 256-char say cap). Rounding/retain fixes along the way: round number values to their step in the editbox seed, locked overlay, and summary; honor retainValues for non-sticky modes; reset category to defaults when switching mode; hide subsection headers with no visible options; and stop leaking subheader/separator pseudo-rows as modoptions.
GetDesyncGameStates logged "Failed to load" then fell through to string.len(infolog) on a nil result. Wrap processing in the else branch so a failed VFS.LoadFile just logs and skips.
Configuration.password is false when rememberPassword is off; the old unconditional auto-login passed that boolean to lobby:Login, which then gsub'd a boolean in TextEraseNewline. Gate auto-login on a string password (or steamMode) so manual login still works.
Closes #1040
Summary
Creates a dedicated Sharing tab that loads the game's
modes/sharing/*.luapresets, applies per-mode values/locks/visibility, and shows ranked eligibility. Enables clean separation between sharing policy configuration and gadget implementation.Changes
ModeConfigpresets frommodes/sharing/ranked=truefor every sharing mode)Screenshot of BAR changes without this PR
Related PRs
BAR: beyond-all-reason/Beyond-All-Reason#5704
Architecture: beyond-all-reason/Beyond-All-Reason#8018
Issue: #1040
Why
Moves sharing configuration from scattered individual modoptions to coherent, mode-driven policies. Players choose high-level intent (Enabled, Disabled, Easy Tax, Tech Core, Customize) rather than manually configuring multiple interdependent options.
Screenshots
(See the bar PR)
LLM Disclosure
The Chobby part of this PR was generated with grok-code-fast-1. I’d already written and reviewed and had a JSON version, then manually implemented the lua sharing mode type, each of the modes and modoption changes on the BAR side. I asked the model to update Chobby to match the new declarative format—needed only minor fixes, and it performed well. LGTM after full review.