import { defineStore } from 'pinia' import { io, Socket } from 'socket.io-client' import type { Asset, Character, Notification, User, WorldSettings } from '@/types' import config from '@/config' import { useCookies } from '@vueuse/integrations/useCookies' export const useGameStore = defineStore('game', { state: () => { return { loginMessage: null as string | null, notifications: [] as Notification[], assets: [] as Asset[], token: '' as string | null, connection: null as Socket | null, user: null as User | null, character: null as Character | null, isPlayerDraggingCamera: false, world: { date: new Date(), isRainEnabled: false, isFogEnabled: false, fogDensity: 0.5 } as WorldSettings, gameSettings: { isCameraFollowingCharacter: false }, uiSettings: { isChatOpen: false, isUserPanelOpen: false, isGmPanelOpen: false } } }, getters: { getNotifications: (state: any) => state.notifications, getAssetByKey: (state) => { return (key: string) => state.assets.find((asset) => asset.key === key) } }, actions: { addNotification(notification: Notification) { if (!notification.id) { notification.id = Math.random().toString(16) } this.notifications.push(notification) }, removeNotification(id: string) { this.notifications = this.notifications.filter((notification: Notification) => notification.id !== id) }, setAssets(assets: Asset[]) { this.assets = assets }, addAsset(asset: Asset) { this.assets.push(asset) }, addAssets(assets: Asset[]) { this.assets = this.assets.concat(assets) }, async fetchSpriteAssets() { return fetch(config.server_endpoint + '/assets/sprites') .then((response) => response.json()) .then((assets) => { // Only add the sprites that are not already in the store this.addAssets(assets.filter((asset: Asset) => !this.getAssetByKey(asset.key))) return true }) .catch((error) => { console.error('Error fetching assets:', error) return false }) }, async fetchZoneAssets(zoneId: number) { return fetch(config.server_endpoint + '/assets/zone/' + zoneId) .then((response) => response.json()) .then((assets) => { // Only add the zones that are not already in the store this.addAssets(assets.filter((asset: Asset) => !this.getAssetByKey(asset.key))) return true }) .catch((error) => { console.error('Error fetching assets:', error) return false }) }, async fetchAllZoneAssets() { return fetch(config.server_endpoint + '/assets/zone') .then((response) => response.json()) .then((assets) => { // Only add the zones that are not already in the store this.addAssets(assets.filter((asset: Asset) => !this.getAssetByKey(asset.key))) return true }) .catch((error) => { console.error('Error fetching assets:', error) return false }) }, setToken(token: string) { this.token = token }, setUser(user: User | null) { this.user = user }, setCharacter(character: Character | null) { this.character = character }, toggleGmPanel() { this.uiSettings.isGmPanelOpen = !this.uiSettings.isGmPanelOpen }, togglePlayerDraggingCamera() { this.isPlayerDraggingCamera = !this.isPlayerDraggingCamera }, setPlayerDraggingCamera(moving: boolean) { this.isPlayerDraggingCamera = moving }, toggleCameraFollowingCharacter() { this.gameSettings.isCameraFollowingCharacter = !this.gameSettings.isCameraFollowingCharacter }, setCameraFollowingCharacter(following: boolean) { this.gameSettings.isCameraFollowingCharacter = following }, toggleChat() { this.uiSettings.isChatOpen = !this.uiSettings.isChatOpen }, toggleUserPanel() { this.uiSettings.isUserPanelOpen = !this.uiSettings.isUserPanelOpen }, initConnection() { this.connection = io(config.server_endpoint, { secure: !config.development, withCredentials: true, transports: ['websocket'], reconnectionAttempts: 5 }) // #99 - If we can't connect, disconnect this.connection.on('connect_error', () => { this.disconnectSocket() }) // Let the server know the user is logged in this.connection.emit('login') // set user this.connection.on('logged_in', (user: User) => { this.setUser(user) }) // When we can't reconnect, disconnect this.connection.on('reconnect_failed', () => { this.disconnectSocket() }) }, disconnectSocket() { if (this.connection) this.connection.disconnect() useCookies().remove('token', { // for whole domain // @TODO : #190 domain: window.location.hostname.split('.').slice(-2).join('.') }) this.assets = [] this.connection = null this.token = null this.user = null this.character = null this.uiSettings.isGmPanelOpen = false this.isPlayerDraggingCamera = false this.gameSettings.isCameraFollowingCharacter = false this.uiSettings.isChatOpen = false this.uiSettings.isUserPanelOpen = false this.world.date = new Date() this.world.isRainEnabled = false this.world.isFogEnabled = false this.world.fogDensity = 0.5 } } })