- Creado nuevo proyecto Nuxt 4 con estructura app/ - Servidor Colyseus separado para evitar problemas con decoradores - Migrado GameRoom y toda la lógica del juego - Implementado cliente con composables useGameClient - Panel de administración funcional - Componentes Vue migrados (HomeScreen, GameScreen, PlayerCard, etc) - Configuración para ejecutar ambos servidores (npm run dev:all)
176 lines
3.9 KiB
TypeScript
176 lines
3.9 KiB
TypeScript
import { ref, onUnmounted } from 'vue'
|
|
|
|
export interface AdminStats {
|
|
connectedPlayers: number
|
|
activeGames: number
|
|
currentRound: string
|
|
gameState: string
|
|
players: any[]
|
|
rooms: any[]
|
|
timestamp?: number
|
|
}
|
|
|
|
export const useAdminService = () => {
|
|
const stats = ref<AdminStats>({
|
|
connectedPlayers: 0,
|
|
activeGames: 0,
|
|
currentRound: 'waiting',
|
|
gameState: 'waiting_for_players',
|
|
players: [],
|
|
rooms: []
|
|
})
|
|
|
|
const isConnected = ref(false)
|
|
const error = ref<string | null>(null)
|
|
|
|
let eventSource: EventSource | null = null
|
|
|
|
const connect = () => {
|
|
if (eventSource) {
|
|
console.warn('Already connected to admin stream')
|
|
return
|
|
}
|
|
|
|
try {
|
|
eventSource = new EventSource('/api/admin/stream')
|
|
|
|
eventSource.onopen = () => {
|
|
console.log('Connected to admin stream')
|
|
isConnected.value = true
|
|
error.value = null
|
|
}
|
|
|
|
eventSource.onmessage = (event) => {
|
|
try {
|
|
const data = JSON.parse(event.data)
|
|
stats.value = data
|
|
} catch (err) {
|
|
console.error('Failed to parse admin stats:', err)
|
|
error.value = 'Failed to parse stats data'
|
|
}
|
|
}
|
|
|
|
eventSource.onerror = (err) => {
|
|
console.error('Admin stream error:', err)
|
|
isConnected.value = false
|
|
error.value = 'Connection lost'
|
|
|
|
// Attempt to reconnect after 5 seconds
|
|
setTimeout(() => {
|
|
if (!eventSource) return
|
|
console.log('Attempting to reconnect to admin stream...')
|
|
disconnect()
|
|
connect()
|
|
}, 5000)
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to connect to admin stream:', err)
|
|
error.value = 'Failed to connect'
|
|
isConnected.value = false
|
|
}
|
|
}
|
|
|
|
const disconnect = () => {
|
|
if (eventSource) {
|
|
eventSource.close()
|
|
eventSource = null
|
|
isConnected.value = false
|
|
console.log('Disconnected from admin stream')
|
|
}
|
|
}
|
|
|
|
const kickPlayer = async (playerId: string) => {
|
|
try {
|
|
const response = await $fetch('/api/admin/kick-player', {
|
|
method: 'POST',
|
|
body: { playerId }
|
|
})
|
|
return response
|
|
} catch (err) {
|
|
console.error('Failed to kick player:', err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
const pauseGame = async () => {
|
|
try {
|
|
const response = await $fetch('/api/admin/pause-game', {
|
|
method: 'POST'
|
|
})
|
|
return response
|
|
} catch (err) {
|
|
console.error('Failed to pause game:', err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
const resumeGame = async () => {
|
|
try {
|
|
const response = await $fetch('/api/admin/resume-game', {
|
|
method: 'POST'
|
|
})
|
|
return response
|
|
} catch (err) {
|
|
console.error('Failed to resume game:', err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
const kickAllPlayers = async () => {
|
|
try {
|
|
const response = await $fetch('/api/admin/kick-all-players', {
|
|
method: 'POST'
|
|
})
|
|
return response
|
|
} catch (err) {
|
|
console.error('Failed to kick all players:', err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
const advanceRound = async () => {
|
|
try {
|
|
const response = await $fetch('/api/admin/advance-round', {
|
|
method: 'POST'
|
|
})
|
|
return response
|
|
} catch (err) {
|
|
console.error('Failed to advance round:', err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
const previousRound = async () => {
|
|
try {
|
|
const response = await $fetch('/api/admin/previous-round', {
|
|
method: 'POST'
|
|
})
|
|
return response
|
|
} catch (err) {
|
|
console.error('Failed to go to previous round:', err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
// Clean up on unmount
|
|
onUnmounted(() => {
|
|
disconnect()
|
|
})
|
|
|
|
return {
|
|
// State
|
|
stats: readonly(stats),
|
|
isConnected: readonly(isConnected),
|
|
error: readonly(error),
|
|
|
|
// Methods
|
|
connect,
|
|
disconnect,
|
|
kickPlayer,
|
|
pauseGame,
|
|
resumeGame,
|
|
kickAllPlayers,
|
|
advanceRound,
|
|
previousRound
|
|
}
|
|
} |