mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-28 12:30:32 +00:00
Use WebSocket intent for lobby game configuration updates (#2761)
Fixes #2758 ## Description: This PR migrates lobby configuration updates from the HTTP PUT `/game/:id` endpoint to a WebSocket-based intent flow. The lobby creator is already authenticated via the game WebSocket, so updating configuration through intents removes redundant authentication and aligns with existing real-time lobby actions such as `kick_player` and `toggle_pause`. ## Changes Made - Added `update_game_config` WebSocket intent schema - Wired client → transport → server intent handling - Refactored `putGameConfig()` to emit WebSocket intent instead of HTTP fetch - Preserved all existing validation, partial-update semantics, and client-side debouncing - Left the REST endpoint untouched for backward compatibility ## Testing - All existing automated tests pass - Manual verification completed: - Lobby creator can update all lobby settings - Non-creators are rejected - Updates are rejected after game start - Bots slider debounce (300ms) remains intact - No `PUT /api/game/:id` requests are made from the lobby UI ## Checklist: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced
This commit is contained in:
@@ -753,44 +753,41 @@ export class HostLobbyModal extends LitElement {
|
||||
}
|
||||
|
||||
private async putGameConfig() {
|
||||
const config = await getServerConfigFromClient();
|
||||
const response = await fetch(
|
||||
`${window.location.origin}/${config.workerPath(this.lobbyId)}/api/game/${this.lobbyId}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("update-game-config", {
|
||||
detail: {
|
||||
config: {
|
||||
gameMap: this.selectedMap,
|
||||
gameMapSize: this.compactMap
|
||||
? GameMapSize.Compact
|
||||
: GameMapSize.Normal,
|
||||
difficulty: this.selectedDifficulty,
|
||||
bots: this.bots,
|
||||
infiniteGold: this.infiniteGold,
|
||||
donateGold: this.donateGold,
|
||||
infiniteTroops: this.infiniteTroops,
|
||||
donateTroops: this.donateTroops,
|
||||
instantBuild: this.instantBuild,
|
||||
randomSpawn: this.randomSpawn,
|
||||
gameMode: this.gameMode,
|
||||
disabledUnits: this.disabledUnits,
|
||||
playerTeams: this.teamCount,
|
||||
...(this.gameMode === GameMode.Team &&
|
||||
this.teamCount === HumansVsNations
|
||||
? {
|
||||
disableNations: false,
|
||||
}
|
||||
: {
|
||||
disableNations: this.disableNations,
|
||||
}),
|
||||
maxTimerValue:
|
||||
this.maxTimer === true ? this.maxTimerValue : undefined,
|
||||
} satisfies Partial<GameConfig>,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
gameMap: this.selectedMap,
|
||||
gameMapSize: this.compactMap
|
||||
? GameMapSize.Compact
|
||||
: GameMapSize.Normal,
|
||||
difficulty: this.selectedDifficulty,
|
||||
bots: this.bots,
|
||||
infiniteGold: this.infiniteGold,
|
||||
donateGold: this.donateGold,
|
||||
infiniteTroops: this.infiniteTroops,
|
||||
donateTroops: this.donateTroops,
|
||||
instantBuild: this.instantBuild,
|
||||
randomSpawn: this.randomSpawn,
|
||||
gameMode: this.gameMode,
|
||||
disabledUnits: this.disabledUnits,
|
||||
playerTeams: this.teamCount,
|
||||
...(this.gameMode === GameMode.Team &&
|
||||
this.teamCount === HumansVsNations
|
||||
? {
|
||||
disableNations: false,
|
||||
}
|
||||
: {
|
||||
disableNations: this.disableNations,
|
||||
}),
|
||||
maxTimerValue:
|
||||
this.maxTimer === true ? this.maxTimerValue : undefined,
|
||||
} satisfies Partial<GameConfig>),
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
private toggleUnit(unit: UnitType, checked: boolean): void {
|
||||
|
||||
Reference in New Issue
Block a user