diff --git a/package-lock.json b/package-lock.json
index fc3e187..c91e10e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"@vueuse/core": "^10.5.0",
"@vueuse/integrations": "^10.5.0",
"axios": "^1.7.7",
+ "dexie": "^4.0.8",
"phaser": "^3.86.0",
"pinia": "^2.1.6",
"socket.io-client": "^4.8.0",
@@ -3549,6 +3550,12 @@
"node": ">=0.10"
}
},
+ "node_modules/dexie": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/dexie/-/dexie-4.0.8.tgz",
+ "integrity": "sha512-1G6cJevS17KMDK847V3OHvK2zei899GwpDiqfEXHP1ASvme6eWJmAp9AU4s1son2TeGkWmC0g3y8ezOBPnalgQ==",
+ "license": "Apache-2.0"
+ },
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -3884,9 +3891,9 @@
}
},
"node_modules/eslint-plugin-vue": {
- "version": "9.29.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.0.tgz",
- "integrity": "sha512-hamyjrBhNH6Li6R1h1VF9KHfshJlKgKEg3ARbGTn72CMNDSMhWbgC7NdkRDEh25AFW+4SDATzyNM+3gWuZii8g==",
+ "version": "9.29.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.1.tgz",
+ "integrity": "sha512-MH/MbVae4HV/tM8gKAVWMPJbYgW04CK7SuzYRrlNERpxbO0P3+Zdsa2oAcFBW6xNu7W6lIkGOsFAMCRTYmrlWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index 63b3c51..b54fe60 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"@vueuse/core": "^10.5.0",
"@vueuse/integrations": "^10.5.0",
"axios": "^1.7.7",
+ "dexie": "^4.0.8",
"phaser": "^3.86.0",
"pinia": "^2.1.6",
"socket.io-client": "^4.8.0",
diff --git a/public/assets/music/click-btn.mp3 b/public/assets/music/click-btn.mp3
new file mode 100644
index 0000000..6ef1729
Binary files /dev/null and b/public/assets/music/click-btn.mp3 differ
diff --git a/public/assets/music/login.mp3 b/public/assets/music/login.mp3
new file mode 100644
index 0000000..1943d41
Binary files /dev/null and b/public/assets/music/login.mp3 differ
diff --git a/src/App.vue b/src/App.vue
index d188312..ba67548 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -15,6 +15,7 @@ import GmPanel from '@/components/gameMaster/GmPanel.vue'
import Login from '@/screens/Login.vue'
import Characters from '@/screens/Characters.vue'
import Game from '@/screens/Game.vue'
+import Loading from '@/screens/Loading.vue'
import ZoneEditor from '@/screens/ZoneEditor.vue'
import { computed } from 'vue'
@@ -22,16 +23,11 @@ const gameStore = useGameStore()
const zoneEditorStore = useZoneEditorStore()
const currentScreen = computed(() => {
+ if (!gameStore.isAssetsLoaded) return Loading
if (!gameStore.connection) return Login
if (!gameStore.token) return Login
if (!gameStore.character) return Characters
if (zoneEditorStore.active) return ZoneEditor
return Game
})
-
-// Disable right click
-addEventListener('contextmenu', (event) => event.preventDefault())
-
-// Disable pinch zoom
-addEventListener('gesturestart', (event) => event.preventDefault())
diff --git a/src/components/gameMaster/zoneEditor/ZoneEditor.vue b/src/components/gameMaster/zoneEditor/ZoneEditor.vue
index dc9ee28..6dad5d4 100644
--- a/src/components/gameMaster/zoneEditor/ZoneEditor.vue
+++ b/src/components/gameMaster/zoneEditor/ZoneEditor.vue
@@ -14,11 +14,9 @@
\ No newline at end of file
diff --git a/src/screens/ZoneEditor.vue b/src/screens/ZoneEditor.vue
index 239d036..b4b463e 100644
--- a/src/screens/ZoneEditor.vue
+++ b/src/screens/ZoneEditor.vue
@@ -16,7 +16,6 @@ import { Game, Scene } from 'phavuer'
import { useGameStore } from '@/stores/gameStore'
import { useZoneEditorStore } from '@/stores/zoneEditorStore'
import ZoneEditor from '@/components/gameMaster/zoneEditor/ZoneEditor.vue'
-import { loadAssets } from '@/composables/zoneComposable'
const gameStore = useGameStore()
const zoneEditorStore = useZoneEditorStore()
@@ -93,11 +92,6 @@ const preloadScene = async (scene: Phaser.Scene) => {
scene.load.image('TELEPORT', '/assets/zone/tp_tile.png')
scene.load.image('blank_tile', '/assets/zone/blank_tile.png')
scene.load.image('waypoint', '/assets/waypoint.png')
-
- /**
- * Load the assets into the Phaser scene
- */
- await loadAssets(scene)
}
const createScene = async (scene: Phaser.Scene) => {
diff --git a/src/services/authentication.ts b/src/services/authentication.ts
index 1fed2d3..4ccb044 100644
--- a/src/services/authentication.ts
+++ b/src/services/authentication.ts
@@ -1,9 +1,8 @@
import axios from 'axios'
import config from '@/config'
-import { useGameStore } from '@/stores/gameStore'
import { useCookies } from '@vueuse/integrations/useCookies'
-export async function register(username: string, password: string, gameStore = useGameStore()) {
+export async function register(username: string, password: string) {
try {
const response = await axios.post(`${config.server_endpoint}/register`, { username, password })
useCookies().set('token', response.data.token as string)
@@ -13,13 +12,13 @@ export async function register(username: string, password: string, gameStore = u
}
}
-export async function login(username: string, password: string, gameStore = useGameStore()) {
+export async function login(username: string, password: string) {
try {
const response = await axios.post(`${config.server_endpoint}/login`, { username, password })
useCookies().set('token', response.data.token as string, {
// for whole domain
// @TODO : #190
- domain: window.location.hostname.split('.').slice(-2).join('.')
+ // domain: window.location.hostname.split('.').slice(-2).join('.')
})
return { success: true, token: response.data.token }
} catch (error: any) {
diff --git a/src/stores/gameStore.ts b/src/stores/gameStore.ts
index df3ca75..c6737fd 100644
--- a/src/stores/gameStore.ts
+++ b/src/stores/gameStore.ts
@@ -7,9 +7,8 @@ import { useCookies } from '@vueuse/integrations/useCookies'
export const useGameStore = defineStore('game', {
state: () => {
return {
- loginMessage: null as string | null,
notifications: [] as Notification[],
- assets: [] as Asset[],
+ isAssetsLoaded: false,
token: '' as string | null,
connection: null as Socket | null,
user: null as User | null,
@@ -47,54 +46,6 @@ export const useGameStore = defineStore('game', {
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
},
@@ -152,15 +103,15 @@ export const useGameStore = defineStore('game', {
})
},
disconnectSocket() {
- if (this.connection) this.connection.disconnect()
+ this.connection?.disconnect()
useCookies().remove('token', {
// for whole domain
// @TODO : #190
- domain: window.location.hostname.split('.').slice(-2).join('.')
+ // domain: window.location.hostname.split('.').slice(-2).join('.')
})
- this.assets = []
+ // this.isAssetsLoaded = false
this.connection = null
this.token = null
this.user = null
diff --git a/src/types.ts b/src/types.ts
index a784736..0ffa1d8 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -4,10 +4,11 @@ export type Notification = {
message?: string
}
-export type Asset = {
+export type AssetT = {
key: string
url: string
group: 'tiles' | 'objects' | 'sprites' | 'sprite_animations' | 'sound' | 'music' | 'ui' | 'font' | 'other'
+ updatedAt: Date
frameCount?: number
frameWidth?: number
frameHeight?: number
diff --git a/src/utilities/assets.ts b/src/utilities/assets.ts
new file mode 100644
index 0000000..e33db9d
--- /dev/null
+++ b/src/utilities/assets.ts
@@ -0,0 +1,101 @@
+import config from '@/config';
+import Dexie from 'dexie';
+
+interface Asset {
+ key: string;
+ data: Blob;
+ group: string;
+ updatedAt: Date;
+ frameCount?: number;
+ frameWidth?: number;
+ frameHeight?: number;
+}
+
+interface AssetWithUrl extends Omit {
+ data: string;
+}
+
+class AssetManager extends Dexie {
+ assets!: Dexie.Table;
+
+ constructor() {
+ super('AssetManager');
+ this.version(1).stores({
+ assets: 'key, group'
+ });
+ }
+
+ async getAssetCount(): Promise {
+ try {
+ const count = await this.assets.count();
+ return count;
+ } catch (error) {
+ console.error('Failed to get asset count:', error);
+ return 0;
+ }
+ }
+
+ async addAsset(
+ key: string,
+ url: string,
+ group: string,
+ updatedAt: Date,
+ frameCount?: number,
+ frameWidth?: number,
+ frameHeight?: number
+ ): Promise {
+ try {
+ const response = await fetch(config.server_endpoint + url);
+ const blob = await response.blob();
+ await this.assets.put({ key, data: blob, group, updatedAt, frameCount, frameWidth, frameHeight });
+ } catch (error) {
+ console.error(`Failed to add asset ${key}:`, error);
+ }
+ }
+
+ async getAsset(key: string): Promise {
+ try {
+ const asset = await this.assets.get(key);
+ if (asset) {
+ return {
+ ...asset,
+ data: URL.createObjectURL(asset.data)
+ };
+ }
+ } catch (error) {
+ console.error(`Failed to retrieve asset ${key}:`, error);
+ }
+ return null;
+ }
+
+ async getAssetsByGroup(group: string): Promise {
+ try {
+ const assets = await this.assets.where('group').equals(group).toArray();
+ return assets.map(asset => ({
+ ...asset,
+ data: URL.createObjectURL(asset.data)
+ }));
+ } catch (error) {
+ console.error(`Failed to retrieve assets for group ${group}:`, error);
+ return [];
+ }
+ }
+
+ async clearAssets(): Promise {
+ try {
+ await this.assets.clear();
+ } catch (error) {
+ console.error('Failed to clear assets:', error);
+ }
+ }
+
+ async deleteAsset(key: string): Promise {
+ try {
+ await this.assets.delete(key);
+ } catch (error) {
+ console.error(`Failed to delete asset ${key}:`, error);
+ }
+ }
+}
+
+export const useAssetManager = new AssetManager();
\ No newline at end of file