Skip to content

Conversation

@MitchZinck
Copy link
Contributor

@MitchZinck MitchZinck commented Jan 27, 2026

If this PR fixes an issue, link it below. If not, delete these two lines.
Resolves #2566

Description:

  • Save lobby settings as a preset and pick from dropdown, stored in localstorage
  • Auto-load last used preset
  • Show users in lobby changes to presets, automatically load saved preset for all users when joining
  • Align server difficulty setting with client
Screenshot 2026-01-26 at 10 44 20 PM

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

Please put your Discord username so you can be contacted if a bug or regression is found:

mitchfz

@CLAassistant
Copy link

CLAassistant commented Jan 27, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

Walkthrough

Adds a lobby presets feature: client-side preset store with CRUD and auto-apply, host modal UI and handlers for saving/loading/deleting presets, tests and a storage shim for testing, plus a server default change (game difficulty set to Easy).

Changes

Cohort / File(s) Summary
Localization strings
resources/lang/en.json
Added 13 new host_modal.presets_* keys for preset UI labels and feedback messages.
Preset persistence layer
src/client/LobbyPresets.ts
New module: zod schemas and types, localStorage-backed store, APIs: listPresets, upsertPreset, deletePreset, setLastUsedPresetId, setAutoApplyLastUsed, with validation and storage error handling.
Host modal integration
src/client/HostLobbyModal.ts
Major feature: preset UI, state and handlers; build/apply game config patch helpers; updated createLobby(creatorClientID, gameConfig) signature; auto-apply last-used preset logic; reset-on-close behavior; UI feedback.
Server defaults
src/server/GameManager.ts
Default game difficulty changed from Medium to Easy.
Tests: presets
tests/client/LobbyPresets.test.ts
New tests for upsertPreset (update vs create), deletePreset, and clearing lastUsedPresetId, using fake timers.
Tests: storage shim
tests/setup.ts
Added in-memory StorageLike mock and ensureWebStorage to polyfill localStorage/sessionStorage for tests.
Package manifest
package.json
Lines added (likely dependencies/devDependencies updated); manifest changed.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Modal as HostLobbyModal
    participant Presets as LobbyPresets
    participant Storage as localStorage
    participant Server as GameServer

    User->>Modal: Open host modal
    Modal->>Presets: listPresets()
    Presets->>Storage: read LOBBY_PRESET_STORAGE_KEY
    Storage-->>Presets: stored JSON
    Presets-->>Modal: presets array
    Modal->>Modal: render preset selector

    User->>Modal: Select preset
    Modal->>Presets: get preset by id
    Presets-->>Modal: preset config
    Modal->>Modal: applyGameConfigPatch(config)

    User->>Modal: Save preset (name)
    Modal->>Modal: buildGameConfigPatch()
    Modal->>Presets: upsertPreset(name, config)
    Presets->>Storage: saveLobbyPresetStore()
    Storage-->>Presets: persisted
    Presets-->>Modal: saved preset

    User->>Modal: Create lobby
    Modal->>Modal: buildFullGameConfig()
    Modal->>Server: POST /createLobby with gameConfig
    Server-->>Modal: game created
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🌱 Presets planted in the modal sun,
Save a name, apply with a run.
Local store hums, settings kept neat,
Click create — the lobby's complete. 🎮

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the feature: saving lobby settings as presets, auto-loading last used presets, showing preset changes to users, and aligning server difficulty with client.
Linked Issues check ✅ Passed The PR implements all core requirements from issue #2566: presets system with UI (dropdown selection, save/delete buttons), localStorage persistence, auto-load functionality, text localization in en.json, UI screenshots, and tests.
Out of Scope Changes check ✅ Passed All changes directly support the presets feature: new LobbyPresets module, HostLobbyModal integration, localization strings, test coverage, and a minor difficulty default fix. No unrelated changes detected.
Title check ✅ Passed The title 'feat: Lobby presets' directly and concisely describes the main feature addition in this changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/client/HostLobbyModal.ts`:
- Around line 1217-1229: In syncPresetsFromStore, avoid pre-selecting last-used
preset when auto-apply is off: set this.autoApplyLastUsedPreset from
store.autoApplyLastUsed first, then compute selectionId so it is
preferredSelectionId if provided, otherwise use store.lastUsedPresetId only when
store.autoApplyLastUsed is true; otherwise leave selectionId undefined. Update
assignment to this.selectedPresetId and this.presetNameInput to use that
selectionId/selectedPreset logic (references: syncPresetsFromStore,
autoApplyLastUsedPreset, preferredSelectionId, store.lastUsedPresetId,
selectedPresetId, presetNameInput).

@github-project-automation github-project-automation bot moved this from Triage to Development in OpenFront Release Management Jan 27, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/client/HostLobbyModal.ts`:
- Around line 1157-1165: When the preset lookup fails in HostLobbyModal
(loadLobbyPresetStore + preset lookup using this.selectedPresetId), clear the
stale UI state: set this.selectedPresetId = undefined (already done) and also
clear any "last-used" preset state and input control bound to the preset
selection (e.g., reset lastUsedPresetId or the form input controlling the
preset) before returning; keep the existing showMessage(translateText(...),
"red") behavior so the user is notified and the UI remains consistent.
🧹 Nitpick comments (3)
src/client/LobbyPresets.ts (2)

31-51: Clear invalid stored data so future loads recover cleanly.

If JSON/schema parsing fails, the bad payload stays and every load re-parses. Removing the key once avoids repeated failures and allows clean recovery.

♻️ Suggested tweak
   try {
     const parsed = JSON.parse(raw);
     const result = LobbyPresetStoreSchema.safeParse(parsed);
     if (result.success) {
       return result.data;
     }
+    localStorage.removeItem(LOBBY_PRESET_STORAGE_KEY);
   } catch {
+    localStorage.removeItem(LOBBY_PRESET_STORAGE_KEY);
     return emptyLobbyPresetStore();
   }

71-72: Return a copy to avoid accidental mutation.

Returning the internal array lets callers mutate it without saving, which can create confusing state.

♻️ Suggested tweak
 export function listPresets(): LobbyPreset[] {
-  return loadLobbyPresetStore().presets;
+  return [...loadLobbyPresetStore().presets];
 }
tests/client/LobbyPresets.test.ts (1)

1-13: Avoid hardcoding the storage key in tests.

Using the shared constant prevents drift if the key changes. This needs the constant exported from LobbyPresets.

♻️ Suggested tweak
 import {
   deletePreset,
   loadLobbyPresetStore,
   setAutoApplyLastUsed,
   setLastUsedPresetId,
   upsertPreset,
+  LOBBY_PRESET_STORAGE_KEY,
 } from "../../src/client/LobbyPresets";
@@
-    localStorage.removeItem("lobbyPresets.v1");
+    localStorage.removeItem(LOBBY_PRESET_STORAGE_KEY);

@MitchZinck MitchZinck marked this pull request as ready for review January 27, 2026 04:16
@MitchZinck MitchZinck requested a review from a team as a code owner January 27, 2026 04:16
@MitchZinck MitchZinck changed the title 2566 - Lobby presets feat: Lobby presets Jan 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Development

Development

Successfully merging this pull request may close these issues.

2 participants