147 lines
5.5 KiB
JavaScript
147 lines
5.5 KiB
JavaScript
|
|
import { createInitialState, punteggio, servizio, setVinti } from './gameState.js'
|
||
|
|
|
||
|
|
export function createWsMixin(role) {
|
||
|
|
return {
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
ws: null,
|
||
|
|
wsConnected: false,
|
||
|
|
isConnecting: false,
|
||
|
|
reconnectTimeout: null,
|
||
|
|
reconnectAttempts: 0,
|
||
|
|
maxReconnectDelay: 30000,
|
||
|
|
state: createInitialState(),
|
||
|
|
}
|
||
|
|
},
|
||
|
|
computed: {
|
||
|
|
punt() { return punteggio(this.state.sp.striscia) },
|
||
|
|
servHome() { return servizio(this.state.sp.striscia) },
|
||
|
|
set() { return setVinti(this.state.sp.striscia) },
|
||
|
|
},
|
||
|
|
mounted() {
|
||
|
|
this.connectWebSocket()
|
||
|
|
if (import.meta.hot) {
|
||
|
|
import.meta.hot.on('vite:beforeUpdate', () => {
|
||
|
|
if (this.reconnectTimeout) {
|
||
|
|
clearTimeout(this.reconnectTimeout)
|
||
|
|
this.reconnectTimeout = null
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
},
|
||
|
|
beforeUnmount() {
|
||
|
|
if (this.reconnectTimeout) {
|
||
|
|
clearTimeout(this.reconnectTimeout)
|
||
|
|
this.reconnectTimeout = null
|
||
|
|
}
|
||
|
|
if (this.ws) {
|
||
|
|
this.ws.onclose = null
|
||
|
|
this.ws.onerror = null
|
||
|
|
this.ws.onmessage = null
|
||
|
|
this.ws.onopen = null
|
||
|
|
try {
|
||
|
|
if (this.ws.readyState === WebSocket.OPEN) {
|
||
|
|
this.ws.close(1000, 'Component unmounting')
|
||
|
|
} else if (this.ws.readyState === WebSocket.CONNECTING) {
|
||
|
|
this.ws.close()
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
console.error(`[${role}] Error closing WebSocket:`, err)
|
||
|
|
}
|
||
|
|
this.ws = null
|
||
|
|
}
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
connectWebSocket() {
|
||
|
|
if (this.isConnecting) return
|
||
|
|
if (this.ws) {
|
||
|
|
this.ws.onclose = null
|
||
|
|
this.ws.onerror = null
|
||
|
|
this.ws.onmessage = null
|
||
|
|
this.ws.onopen = null
|
||
|
|
try {
|
||
|
|
if (this.ws.readyState === WebSocket.OPEN) {
|
||
|
|
this.ws.close(1000, 'Reconnecting')
|
||
|
|
} else if (this.ws.readyState === WebSocket.CONNECTING) {
|
||
|
|
this.ws.close()
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
console.error(`[${role}] Error closing previous WebSocket:`, err)
|
||
|
|
}
|
||
|
|
this.ws = null
|
||
|
|
}
|
||
|
|
|
||
|
|
this.isConnecting = true
|
||
|
|
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||
|
|
const params = new URLSearchParams(location.search)
|
||
|
|
const defaultHost = (location.hostname === 'localhost' || location.hostname === '::1')
|
||
|
|
? `127.0.0.1${location.port ? `:${location.port}` : ''}`
|
||
|
|
: location.host
|
||
|
|
const wsUrl = `${protocol}//${params.get('wsHost') || defaultHost}/ws`
|
||
|
|
|
||
|
|
try {
|
||
|
|
this.ws = new WebSocket(wsUrl)
|
||
|
|
} catch (err) {
|
||
|
|
console.error(`[${role}] Failed to create WebSocket:`, err)
|
||
|
|
this.isConnecting = false
|
||
|
|
this.scheduleReconnect()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
this.ws.onopen = () => {
|
||
|
|
this.isConnecting = false
|
||
|
|
this.wsConnected = true
|
||
|
|
this.reconnectAttempts = 0
|
||
|
|
try {
|
||
|
|
this.ws?.send(JSON.stringify({ type: 'register', role }))
|
||
|
|
} catch (err) {
|
||
|
|
console.error(`[${role}] Failed to register:`, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this.ws.onmessage = (event) => {
|
||
|
|
try {
|
||
|
|
const msg = JSON.parse(event.data)
|
||
|
|
if (msg.type === 'state') this.state = msg.state
|
||
|
|
else this.onWsMessage?.(msg)
|
||
|
|
} catch (e) {
|
||
|
|
console.error(`[${role}] Error parsing message:`, e)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this.ws.onclose = (event) => {
|
||
|
|
this.isConnecting = false
|
||
|
|
this.wsConnected = false
|
||
|
|
if (event.code !== 1000 && event.code !== 1001) this.scheduleReconnect()
|
||
|
|
}
|
||
|
|
|
||
|
|
this.ws.onerror = () => {
|
||
|
|
this.isConnecting = false
|
||
|
|
this.wsConnected = false
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
scheduleReconnect() {
|
||
|
|
if (this.reconnectTimeout) return
|
||
|
|
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay)
|
||
|
|
this.reconnectAttempts++
|
||
|
|
this.reconnectTimeout = setTimeout(() => {
|
||
|
|
this.reconnectTimeout = null
|
||
|
|
this.connectWebSocket()
|
||
|
|
}, delay)
|
||
|
|
},
|
||
|
|
|
||
|
|
sendWs(msg) {
|
||
|
|
if (!this.wsConnected || this.ws?.readyState !== WebSocket.OPEN) return false
|
||
|
|
try {
|
||
|
|
this.ws.send(JSON.stringify(msg))
|
||
|
|
return true
|
||
|
|
} catch (err) {
|
||
|
|
console.error(`[${role}] Failed to send:`, err)
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|