feat: Migración completa de SnatchGame a Nuxt 4
- 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)
This commit is contained in:
176
nuxt-snatchgame/app/composables/useAdminService.ts
Normal file
176
nuxt-snatchgame/app/composables/useAdminService.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user