mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:20:47 +00:00
Can select map on private lobbies
This commit is contained in:
@@ -46,7 +46,7 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v
|
||||
console.log('lobby: game started')
|
||||
onjoin()
|
||||
const gameConfig = {
|
||||
map: GameMap.World,
|
||||
map: message.config?.gameMap || lobbyConfig.map,
|
||||
clientID: clientID,
|
||||
gameID: lobbyConfig.gameID,
|
||||
ip: lobbyConfig.ip,
|
||||
@@ -93,6 +93,7 @@ export class GameRunner {
|
||||
private intervalID: NodeJS.Timeout
|
||||
|
||||
private isProcessingTurn = false
|
||||
private hasJoined = false
|
||||
|
||||
constructor(
|
||||
private id: ClientID,
|
||||
@@ -125,6 +126,7 @@ export class GameRunner {
|
||||
};
|
||||
const onmessage = (message: ServerMessage) => {
|
||||
if (message.type == "start") {
|
||||
this.hasJoined = true
|
||||
console.log("starting game!")
|
||||
for (const turn of message.turns) {
|
||||
if (turn.turnNumber < this.turns.length) {
|
||||
@@ -134,6 +136,9 @@ export class GameRunner {
|
||||
}
|
||||
}
|
||||
if (message.type == "turn") {
|
||||
if (!this.hasJoined) {
|
||||
return
|
||||
}
|
||||
if (this.turns.length != message.turn.turnNumber) {
|
||||
console.error(`got wrong turn have turns ${this.turns.length}, received turn ${message.turn.turnNumber}`)
|
||||
} else {
|
||||
|
||||
@@ -111,7 +111,7 @@ export class HostLobbyModal extends LitElement {
|
||||
<div>
|
||||
<label for="map-select">Map: </label>
|
||||
<select id="map-select" @change=${this.handleMapChange}>
|
||||
${Object.entries(new Set())
|
||||
${Object.entries(GameMap)
|
||||
.filter(([key]) => isNaN(Number(key)))
|
||||
.map(([key, value]) => html`
|
||||
<option value=${value} ?selected=${this.selectedMap === value}>
|
||||
@@ -152,8 +152,17 @@ export class HostLobbyModal extends LitElement {
|
||||
this.copySuccess = false;
|
||||
}
|
||||
|
||||
private handleMapChange(e: Event) {
|
||||
private async handleMapChange(e: Event) {
|
||||
this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap;
|
||||
console.log(`updating map to ${this.selectedMap}`)
|
||||
const response = await fetch(`/private_lobby/${this.lobbyId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({gameMap: this.selectedMap})
|
||||
});
|
||||
|
||||
}
|
||||
private async startGame() {
|
||||
console.log(`Starting private game with map: ${GameMap[this.selectedMap]}`);
|
||||
@@ -166,6 +175,7 @@ export class HostLobbyModal extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private async copyToClipboard() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(this.lobbyId);
|
||||
@@ -180,6 +190,7 @@ export class HostLobbyModal extends LitElement {
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function createLobby(): Promise<Lobby> {
|
||||
try {
|
||||
const response = await fetch('/private_lobby', {
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
import {z} from 'zod';
|
||||
import {PlayerType} from './game/Game';
|
||||
import {GameMap, PlayerType} from './game/Game';
|
||||
|
||||
export type GameID = string
|
||||
export type ClientID = string
|
||||
@@ -27,6 +27,7 @@ export type EmojiIntent = z.infer<typeof EmojiIntentSchema>
|
||||
export type DonateIntent = z.infer<typeof DonateIntentSchema>
|
||||
|
||||
export type Turn = z.infer<typeof TurnSchema>
|
||||
export type GameConfig = z.infer<typeof GameConfigSchema>
|
||||
|
||||
export type ClientMessage = ClientIntentMessage | ClientJoinMessage | ClientLeaveMessage
|
||||
export type ServerMessage = ServerSyncMessage | ServerStartGameMessage
|
||||
@@ -49,6 +50,10 @@ export interface Lobby {
|
||||
numClients?: number;
|
||||
}
|
||||
|
||||
const GameConfigSchema = z.object({
|
||||
gameMap: z.nativeEnum(GameMap)
|
||||
})
|
||||
|
||||
const EmojiSchema = z.string().refine(
|
||||
(val) => {
|
||||
return /\p{Emoji}/u.test(val);
|
||||
@@ -170,7 +175,8 @@ export const ServerTurnMessageSchema = ServerBaseMessageSchema.extend({
|
||||
export const ServerStartGameMessageSchema = ServerBaseMessageSchema.extend({
|
||||
type: z.literal('start'),
|
||||
// Turns the client missed if they are late to the game.
|
||||
turns: z.array(TurnSchema)
|
||||
turns: z.array(TurnSchema),
|
||||
config: GameConfigSchema
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {Config} from "../core/configuration/Config";
|
||||
import {ClientID, GameID} from "../core/Schemas";
|
||||
import {ClientID, GameConfig, GameID} from "../core/Schemas";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import {Client} from "./Client";
|
||||
import {GamePhase, GameServer} from "./GameServer";
|
||||
import {GameMap} from "../core/game/Game";
|
||||
|
||||
|
||||
|
||||
@@ -27,9 +28,18 @@ export class GameManager {
|
||||
game.addClient(client, lastTurn)
|
||||
}
|
||||
|
||||
updateGameConfig(gameID: GameID, gameConfig: GameConfig) {
|
||||
const game = this.games.find(g => g.id == gameID)
|
||||
if (game == null) {
|
||||
console.warn(`game ${gameID} not found`)
|
||||
return
|
||||
}
|
||||
game.updateGameConfig(gameConfig)
|
||||
}
|
||||
|
||||
createPrivateGame(): string {
|
||||
const id = genSmallGameID()
|
||||
this.games.push(new GameServer(id, Date.now(), false, this.config))
|
||||
this.games.push(new GameServer(id, Date.now(), false, this.config, {gameMap: GameMap.World}))
|
||||
return id
|
||||
}
|
||||
|
||||
@@ -58,7 +68,7 @@ export class GameManager {
|
||||
if (now > this.lastNewLobby + this.config.gameCreationRate()) {
|
||||
this.lastNewLobby = now
|
||||
const id = uuidv4()
|
||||
lobbies.push(new GameServer(id, now, true, this.config))
|
||||
lobbies.push(new GameServer(id, now, true, this.config, {gameMap: GameMap.World}))
|
||||
}
|
||||
|
||||
active.filter(g => !g.hasStarted() && g.isPublic).forEach(g => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {ClientMessage, ClientMessageSchema, Intent, ServerStartGameMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn} from "../core/Schemas";
|
||||
import {ClientMessage, ClientMessageSchema, GameConfig, Intent, ServerStartGameMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn} from "../core/Schemas";
|
||||
import {Config} from "../core/configuration/Config";
|
||||
import {Client} from "./Client";
|
||||
import WebSocket from 'ws';
|
||||
@@ -23,13 +23,21 @@ export class GameServer {
|
||||
|
||||
private endTurnIntervalID
|
||||
|
||||
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
public readonly createdAt: number,
|
||||
public readonly isPublic: boolean,
|
||||
private config: Config,
|
||||
private gameConfig: GameConfig,
|
||||
) { }
|
||||
|
||||
public updateGameConfig(gameConfig: GameConfig): void {
|
||||
if (gameConfig.gameMap != null) {
|
||||
this.gameConfig.gameMap = gameConfig.gameMap
|
||||
}
|
||||
}
|
||||
|
||||
public addClient(client: Client, lastTurn: number) {
|
||||
console.log(`game ${this.id} adding client ${client.id}`)
|
||||
slog('client_joined_game', `client ${client.id} (re)joining game ${this.id}`, {
|
||||
@@ -93,7 +101,8 @@ export class GameServer {
|
||||
ws.send(JSON.stringify(ServerStartGameMessageSchema.parse(
|
||||
{
|
||||
type: "start",
|
||||
turns: this.turns.slice(lastTurn)
|
||||
turns: this.turns.slice(lastTurn),
|
||||
config: this.gameConfig
|
||||
}
|
||||
)))
|
||||
}
|
||||
@@ -137,7 +146,7 @@ export class GameServer {
|
||||
if (!this.isPublic) {
|
||||
if (this._hasStarted) {
|
||||
if (this.clients.length == 0) {
|
||||
console.log(`game ${this.id} is finisehd`)
|
||||
console.log()
|
||||
return GamePhase.Finished
|
||||
} else {
|
||||
return GamePhase.Active
|
||||
|
||||
@@ -23,8 +23,6 @@ app.use(express.static(path.join(__dirname, '../../out')));
|
||||
app.use(express.json())
|
||||
const gm = new GameManager(getConfig())
|
||||
|
||||
const privateGames = new Map<string, GameServer>()
|
||||
|
||||
// New GET endpoint to list lobbies
|
||||
app.get('/lobbies', (req, res) => {
|
||||
const now = Date.now()
|
||||
@@ -35,6 +33,7 @@ app.get('/lobbies', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.post('/private_lobby', (req, res) => {
|
||||
const id = gm.createPrivateGame()
|
||||
console.log('creating private lobby with id ${id}')
|
||||
@@ -48,8 +47,9 @@ app.post('/start_private_lobby/:id', (req, res) => {
|
||||
gm.startPrivateGame(req.params.id)
|
||||
});
|
||||
|
||||
|
||||
app.put('/private_lobby/:id', (req, res) => {
|
||||
const lobbyID = req.params.id
|
||||
gm.updateGameConfig(lobbyID, {gameMap: req.body.gameMap})
|
||||
});
|
||||
|
||||
app.get('/lobby/:id/exists', (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user