reiniciar por room, finished ya no estorba, control total desde el dashboard
This commit is contained in:
@@ -110,6 +110,13 @@
|
|||||||
<option value="G5">G5</option>
|
<option value="G5">G5</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
@click="$emit('restartRoom', room.roomId)"
|
||||||
|
class="btn btn-restart"
|
||||||
|
title="Reiniciar estado (mantiene variante)"
|
||||||
|
>
|
||||||
|
🔄 Reiniciar
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="$emit('closeRoom', room.roomId)"
|
@click="$emit('closeRoom', room.roomId)"
|
||||||
class="btn btn-close"
|
class="btn btn-close"
|
||||||
@@ -168,6 +175,7 @@ defineEmits<{
|
|||||||
viewRoomModal: [roomId: string];
|
viewRoomModal: [roomId: string];
|
||||||
closeRoom: [roomId: string];
|
closeRoom: [roomId: string];
|
||||||
changeVariant: [roomId: string, variant: string];
|
changeVariant: [roomId: string, variant: string];
|
||||||
|
restartRoom: [roomId: string];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function getRoomDetails(roomId: string) {
|
function getRoomDetails(roomId: string) {
|
||||||
@@ -279,6 +287,19 @@ function getReadableTextColor(hex?: string): string {
|
|||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-restart {
|
||||||
|
background: #1976d2;
|
||||||
|
color: white;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-restart:hover {
|
||||||
|
background: #1565c0;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
.variant-selector-container {
|
.variant-selector-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 4px;
|
margin: 0 4px;
|
||||||
@@ -528,4 +549,4 @@ function getReadableTextColor(hex?: string): string {
|
|||||||
max-width: 150px;
|
max-width: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -160,6 +160,7 @@
|
|||||||
@view-room-modal="openRoomModal"
|
@view-room-modal="openRoomModal"
|
||||||
@close-room="closeRoom"
|
@close-room="closeRoom"
|
||||||
@change-variant="changeRoomVariant"
|
@change-variant="changeRoomVariant"
|
||||||
|
@restart-room="restartRoom"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Cards View -->
|
<!-- Cards View -->
|
||||||
|
|||||||
@@ -527,14 +527,17 @@ adminRouter.get("/admin/uuids-with-names", async (req: Request, res: Response) =
|
|||||||
|
|
||||||
// SSE endpoint for real-time dashboard updates
|
// SSE endpoint for real-time dashboard updates
|
||||||
adminRouter.get("/dashboard-stream", (req: Request, res: Response) => {
|
adminRouter.get("/dashboard-stream", (req: Request, res: Response) => {
|
||||||
// Set SSE headers
|
// Set SSE headers (hardened for reverse proxies)
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
'Content-Type': 'text/event-stream',
|
'Content-Type': 'text/event-stream',
|
||||||
'Cache-Control': 'no-cache',
|
'Cache-Control': 'no-cache, no-transform', // avoid proxy transformations
|
||||||
'Connection': 'keep-alive',
|
'Connection': 'keep-alive',
|
||||||
'Access-Control-Allow-Origin': '*',
|
'Access-Control-Allow-Origin': '*',
|
||||||
'Access-Control-Allow-Headers': 'Cache-Control'
|
'Access-Control-Allow-Headers': 'Cache-Control',
|
||||||
|
'X-Accel-Buffering': 'no' // hint nginx to disable buffering
|
||||||
});
|
});
|
||||||
|
// Flush headers immediately so proxies establish the stream
|
||||||
|
try { (res as any).flushHeaders?.(); } catch {}
|
||||||
|
|
||||||
// Add client to our set
|
// Add client to our set
|
||||||
sseClients.add(res);
|
sseClients.add(res);
|
||||||
|
|||||||
@@ -73,13 +73,9 @@ export class GameRoom extends Room<GameState> {
|
|||||||
// Reset to round 1 and clear decisions when variant changes
|
// Reset to round 1 and clear decisions when variant changes
|
||||||
this.state.currentRound = 1;
|
this.state.currentRound = 1;
|
||||||
this.state.resetRound();
|
this.state.resetRound();
|
||||||
// Reset game status if it was finished
|
// Update metadata with new variant and round (don't special-case FINISHED)
|
||||||
if (this.state.gameStatus === GameStatus.FINISHED) {
|
|
||||||
this.state.gameStatus = GameStatus.PLAYING;
|
|
||||||
}
|
|
||||||
// Update metadata with new variant and round
|
|
||||||
this.setMetadata({
|
this.setMetadata({
|
||||||
gameStatus: this.state.gameStatus === GameStatus.WAITING ? 'waiting' : 'playing',
|
gameStatus: this.state.gameStatus === GameStatus.WAITING ? 'waiting' : (this.state.gameStatus === GameStatus.PAUSED ? 'paused' : (this.state.gameStatus === GameStatus.FINISHED ? 'finished' : 'playing')),
|
||||||
currentRound: this.state.currentRound,
|
currentRound: this.state.currentRound,
|
||||||
currentVariant: this.state.currentVariant
|
currentVariant: this.state.currentVariant
|
||||||
});
|
});
|
||||||
@@ -478,20 +474,6 @@ export class GameRoom extends Room<GameState> {
|
|||||||
});
|
});
|
||||||
// Notify dashboard of game end
|
// Notify dashboard of game end
|
||||||
broadcastDashboardUpdate();
|
broadcastDashboardUpdate();
|
||||||
|
|
||||||
// Clear UUID -> current room mapping and reconnection tokens for participants
|
|
||||||
try {
|
|
||||||
const { NameManager } = require("../utils/nameManager");
|
|
||||||
const toClear: string[] = [];
|
|
||||||
this.state.players.forEach((p) => {
|
|
||||||
const u = (p as any)?.uuid;
|
|
||||||
if (u) toClear.push(u);
|
|
||||||
});
|
|
||||||
toClear.forEach(u => {
|
|
||||||
NameManager.getInstance().clearCurrentRoom(u);
|
|
||||||
NameManager.getInstance().clearReconnectToken(u);
|
|
||||||
});
|
|
||||||
} catch {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveP2Action() {
|
private resolveP2Action() {
|
||||||
@@ -583,12 +565,9 @@ export class GameRoom extends Room<GameState> {
|
|||||||
this.state.currentRound = 1;
|
this.state.currentRound = 1;
|
||||||
this.state.resetRound();
|
this.state.resetRound();
|
||||||
|
|
||||||
if (this.state.gameStatus === GameStatus.FINISHED) {
|
// Update metadata without altering FINISHED status
|
||||||
this.state.gameStatus = GameStatus.PLAYING;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setMetadata({
|
this.setMetadata({
|
||||||
gameStatus: this.state.gameStatus === GameStatus.WAITING ? 'waiting' : 'playing',
|
gameStatus: this.state.gameStatus === GameStatus.WAITING ? 'waiting' : (this.state.gameStatus === GameStatus.PAUSED ? 'paused' : (this.state.gameStatus === GameStatus.FINISHED ? 'finished' : 'playing')),
|
||||||
currentRound: this.state.currentRound,
|
currentRound: this.state.currentRound,
|
||||||
currentVariant: this.state.currentVariant
|
currentVariant: this.state.currentVariant
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -80,8 +80,7 @@ export class LobbyRoom extends Room<LobbyState> {
|
|||||||
if (currentRoomId) {
|
if (currentRoomId) {
|
||||||
const rooms = await matchMaker.query({ roomId: currentRoomId });
|
const rooms = await matchMaker.query({ roomId: currentRoomId });
|
||||||
const room = rooms[0];
|
const room = rooms[0];
|
||||||
const status = room?.metadata?.gameStatus || "waiting";
|
if (room) {
|
||||||
if (room && status !== "finished") {
|
|
||||||
const token = NameManager.getInstance().getReconnectToken(uuid);
|
const token = NameManager.getInstance().getReconnectToken(uuid);
|
||||||
if (token) { client.send("resumeReconnection", { token }); }
|
if (token) { client.send("resumeReconnection", { token }); }
|
||||||
else { client.send("resumeGame", { roomId: currentRoomId }); }
|
else { client.send("resumeGame", { roomId: currentRoomId }); }
|
||||||
@@ -146,8 +145,7 @@ export class LobbyRoom extends Room<LobbyState> {
|
|||||||
if (currentRoomId) {
|
if (currentRoomId) {
|
||||||
const rooms = await matchMaker.query({ roomId: currentRoomId });
|
const rooms = await matchMaker.query({ roomId: currentRoomId });
|
||||||
const room = rooms[0];
|
const room = rooms[0];
|
||||||
const status = room?.metadata?.gameStatus || "waiting";
|
if (room) {
|
||||||
if (room && status !== "finished") {
|
|
||||||
const token = NameManager.getInstance().getReconnectToken(options.uuid);
|
const token = NameManager.getInstance().getReconnectToken(options.uuid);
|
||||||
if (token) {
|
if (token) {
|
||||||
client.send("resumeReconnection", { token });
|
client.send("resumeReconnection", { token });
|
||||||
|
|||||||
Reference in New Issue
Block a user