Refactor assetManager, renamed assetManager to assetStorage, renamed AssetT to AssetDataT, added better error handling in authentication service, continued working on dynamic asset loading for both maps and map editor
This commit is contained in:
@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div v-if="isLoaded">
|
||||
<ZoneTiles @tilemap:create="tileMap = $event" />
|
||||
</div>
|
||||
<ZoneTiles @tilemap:create="tileMap = $event" />
|
||||
<ZoneObjects v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
|
||||
<ZoneEventTiles v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
|
||||
|
||||
@ -16,11 +14,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useScene } from 'phavuer'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { onUnmounted, ref } from 'vue'
|
||||
import { useGameStore } from '@/stores/gameStore'
|
||||
import { useZoneEditorStore } from '@/stores/zoneEditorStore'
|
||||
import { type AssetT, type Zone } from '@/types'
|
||||
import { type Zone } from '@/types'
|
||||
|
||||
// Components
|
||||
import Toolbar from '@/components/gameMaster/zoneEditor/partials/Toolbar.vue'
|
||||
@ -32,14 +29,10 @@ import TeleportModal from '@/components/gameMaster/zoneEditor/partials/TeleportM
|
||||
import ZoneTiles from '@/components/gameMaster/zoneEditor/ZoneTiles.vue'
|
||||
import ZoneObjects from '@/components/gameMaster/zoneEditor/ZoneObjects.vue'
|
||||
import ZoneEventTiles from '@/components/gameMaster/zoneEditor/ZoneEventTiles.vue'
|
||||
import config from '@/config'
|
||||
import { loadZoneTileTexture } from '@/composables/zoneComposable'
|
||||
|
||||
const scene = useScene()
|
||||
const gameStore = useGameStore()
|
||||
const zoneEditorStore = useZoneEditorStore()
|
||||
const tileMap = ref(null as Phaser.Tilemaps.Tilemap | null)
|
||||
const isLoaded = ref(false)
|
||||
|
||||
function save() {
|
||||
if (!zoneEditorStore.zone) return
|
||||
@ -65,14 +58,6 @@ function save() {
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const tiles: AssetT[] = await fetch(config.server_endpoint + '/assets/list_tiles').then((response) => response.json())
|
||||
for (const tile of tiles) {
|
||||
await loadZoneTileTexture(scene, tile.key, tile.updatedAt)
|
||||
}
|
||||
isLoaded.value = true
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
zoneEditorStore.reset()
|
||||
})
|
||||
|
@ -7,13 +7,15 @@ import config from '@/config'
|
||||
import { useScene } from 'phavuer'
|
||||
import { useZoneEditorStore } from '@/stores/zoneEditorStore'
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { createTileArray, FlattenZoneArray, getTile, placeTile, setLayerTiles } from '@/composables/zoneComposable'
|
||||
import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/zoneComposable'
|
||||
import Controls from '@/components/utilities/Controls.vue'
|
||||
import { unduplicateArray } from '@/utilities'
|
||||
import { useGameStore } from '@/stores/gameStore'
|
||||
import type { AssetDataT } from '@/types'
|
||||
|
||||
const emit = defineEmits(['tilemap:create'])
|
||||
|
||||
const scene = useScene()
|
||||
const gameStore = useGameStore()
|
||||
const zoneEditorStore = useZoneEditorStore()
|
||||
const zoneTilemap = createTilemap()
|
||||
const tiles = createTileLayer()
|
||||
@ -41,10 +43,10 @@ function createTilemap() {
|
||||
* A Tileset is a combination of a single image containing the tiles and a container for data about each tile.
|
||||
*/
|
||||
function createTileLayer() {
|
||||
const tilesArray = unduplicateArray(FlattenZoneArray(zoneEditorStore.zone?.tiles ?? []))
|
||||
const tilesArray = gameStore.getLoadedAssetsByGroup('tiles')
|
||||
|
||||
const tilesetImages = Array.from(tilesArray).map((tile: any, index: number) => {
|
||||
return zoneTilemap.addTilesetImage(tile, tile, config.tile_size.x, config.tile_size.y, 1, 2, index + 1, { x: 0, y: -config.tile_size.y })
|
||||
const tilesetImages = Array.from(tilesArray).map((tile: AssetDataT, index: number) => {
|
||||
return zoneTilemap.addTilesetImage(tile.key, tile.key, config.tile_size.x, config.tile_size.y, 1, 2, index + 1, { x: 0, y: -config.tile_size.y })
|
||||
}) as any
|
||||
|
||||
// Add blank tile
|
||||
|
@ -5,8 +5,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { Image, useScene } from 'phavuer'
|
||||
import { calculateIsometricDepth, loadZoneObjectTexture, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
|
||||
import type { ZoneObject } from '@/types'
|
||||
import { calculateIsometricDepth, loadTexture, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
|
||||
import type { AssetDataT, ZoneObject } from '@/types'
|
||||
|
||||
const props = defineProps<{
|
||||
tilemap: Phaser.Tilemaps.Tilemap
|
||||
@ -26,7 +26,14 @@ const imageProps = computed(() => ({
|
||||
originX: Number(props.zoneObject.object.originY)
|
||||
}))
|
||||
|
||||
loadZoneObjectTexture(scene, props.zoneObject.object.id, props.zoneObject.object.updatedAt)
|
||||
loadTexture(scene, {
|
||||
key: props.zoneObject.object.id,
|
||||
data: '/assets/objects/' + props.zoneObject.object.id + '.png',
|
||||
group: 'objects',
|
||||
updatedAt: props.zoneObject.object.updatedAt,
|
||||
frameWidth: props.zoneObject.object.frameWidth,
|
||||
frameHeight: props.zoneObject.object.frameHeight
|
||||
} as AssetDataT)
|
||||
.then((loaded) => {
|
||||
isTextureLoaded.value = loaded
|
||||
})
|
||||
|
@ -5,8 +5,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { Image, useScene } from 'phavuer'
|
||||
import { calculateIsometricDepth, loadZoneObjectTexture, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
|
||||
import type { ZoneObject } from '@/types'
|
||||
import { calculateIsometricDepth, loadTexture, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
|
||||
import type { AssetDataT, ZoneObject } from '@/types'
|
||||
|
||||
const props = defineProps<{
|
||||
tilemap: Phaser.Tilemaps.Tilemap
|
||||
@ -26,7 +26,14 @@ const imageProps = computed(() => ({
|
||||
originX: Number(props.zoneObject.object.originY)
|
||||
}))
|
||||
|
||||
loadZoneObjectTexture(scene, props.zoneObject.object.id, props.zoneObject.object.updatedAt)
|
||||
loadTexture(scene, {
|
||||
key: props.zoneObject.object.id,
|
||||
data: '/assets/objects/' + props.zoneObject.object.id + '.png',
|
||||
group: 'objects',
|
||||
updatedAt: props.zoneObject.object.updatedAt,
|
||||
frameWidth: props.zoneObject.object.frameWidth,
|
||||
frameHeight: props.zoneObject.object.frameHeight
|
||||
} as AssetDataT)
|
||||
.then((loaded) => {
|
||||
isTextureLoaded.value = loaded
|
||||
})
|
||||
|
34
src/composables/game/scene/loaderComposable.ts
Normal file
34
src/composables/game/scene/loaderComposable.ts
Normal file
@ -0,0 +1,34 @@
|
||||
export function createSceneLoader(scene: Phaser.Scene) {
|
||||
const width = scene.cameras.main.width
|
||||
const height = scene.cameras.main.height
|
||||
|
||||
const progressBox = scene.add.graphics()
|
||||
const progressBar = scene.add.graphics()
|
||||
progressBox.fillStyle(0x222222, 0.8)
|
||||
progressBox.fillRect(width / 2 - 180, height / 2, 320, 50)
|
||||
|
||||
const loadingText = scene.make.text({
|
||||
x: width / 2,
|
||||
y: height / 2 - 50,
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
font: '20px monospace',
|
||||
// @ts-ignore
|
||||
fill: '#ffffff'
|
||||
}
|
||||
})
|
||||
loadingText.setOrigin(0.5, 0.5)
|
||||
|
||||
scene.load.on(Phaser.Loader.Events.PROGRESS, function (value: any) {
|
||||
progressBar.clear()
|
||||
progressBar.fillStyle(0x368f8b, 1)
|
||||
progressBar.fillRect(width / 2 - 180 + 10, height / 2 + 10, 300 * value, 30)
|
||||
})
|
||||
|
||||
scene.load.on(Phaser.Loader.Events.COMPLETE, function () {
|
||||
progressBar.destroy()
|
||||
progressBox.destroy()
|
||||
loadingText.destroy()
|
||||
return true
|
||||
})
|
||||
}
|
@ -31,7 +31,7 @@ export function useGamePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilema
|
||||
const { worldX, worldY } = pointer
|
||||
updateWaypoint(worldX, worldY)
|
||||
|
||||
if (gameStore.isPlayerDraggingCamera) {
|
||||
if (gameStore.game.isPlayerDraggingCamera) {
|
||||
const distance = Phaser.Math.Distance.Between(pointerStartPosition.value.x, pointerStartPosition.value.y, pointer.x, pointer.y)
|
||||
|
||||
if (distance > dragThreshold) {
|
||||
|
@ -26,7 +26,7 @@ export function useZoneEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser.
|
||||
}
|
||||
|
||||
function dragZone(pointer: Phaser.Input.Pointer) {
|
||||
if (gameStore.isPlayerDraggingCamera) {
|
||||
if (gameStore.game.isPlayerDraggingCamera) {
|
||||
const { x, y, prevPosition } = pointer
|
||||
const { scrollX, scrollY, zoom } = camera
|
||||
camera.setScroll(scrollX - (x - prevPosition.x) / zoom, scrollY - (y - prevPosition.y) / zoom)
|
||||
|
@ -3,8 +3,9 @@ import Tilemap = Phaser.Tilemaps.Tilemap
|
||||
import TilemapLayer = Phaser.Tilemaps.TilemapLayer
|
||||
import Tileset = Phaser.Tilemaps.Tileset
|
||||
import Tile = Phaser.Tilemaps.Tile
|
||||
import { useAssetManager } from '@/managers/assetManager'
|
||||
import type { AssetT, Zone as ZoneT } from '@/types'
|
||||
import type { AssetDataT, Zone as ZoneT } from '@/types'
|
||||
import { AssetStorage } from '@/storage/assetStorage'
|
||||
import { useGameStore } from '@/stores/gameStore'
|
||||
|
||||
export function getTile(layer: TilemapLayer | Tilemap, x: number, y: number): Tile | undefined {
|
||||
const tile = layer.getTileAtWorldXY(x, y)
|
||||
@ -86,59 +87,40 @@ export function FlattenZoneArray(tiles: string[][]) {
|
||||
}
|
||||
|
||||
export async function loadZoneTilesIntoScene(zone: ZoneT, scene: Phaser.Scene) {
|
||||
const tileArray: AssetT[] = await fetch(config.server_endpoint + '/assets/list_tiles/' + zone.id).then((response) => response.json())
|
||||
console.log(tileArray)
|
||||
// Fetch the list of tiles from the server
|
||||
const tileArray: AssetDataT[] = await fetch(config.server_endpoint + '/assets/list_tiles/' + zone.id).then((response) => response.json())
|
||||
|
||||
// Load each tile into the scene
|
||||
for (const tile of tileArray) {
|
||||
await loadZoneTileTexture(scene, tile.key, tile.updatedAt)
|
||||
await loadTexture(scene, tile)
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadZoneTileTexture(scene: Phaser.Scene, textureId: string, updatedAt: Date): Promise<boolean> {
|
||||
const assetManager = useAssetManager
|
||||
export async function loadTexture(scene: Phaser.Scene, assetData: AssetDataT): Promise<boolean> {
|
||||
const gameStore = useGameStore()
|
||||
const assetStorage = new AssetStorage()
|
||||
|
||||
// Check if the texture is already loaded in Phaser
|
||||
if (scene.textures.exists(textureId)) {
|
||||
if (scene.textures.exists(assetData.key)) {
|
||||
return true
|
||||
}
|
||||
|
||||
let assetData = await assetManager.getAsset(textureId)
|
||||
// Check if the asset is already cached
|
||||
let asset = await assetStorage.get(assetData.key)
|
||||
|
||||
if (!assetData) {
|
||||
await assetManager.downloadAsset(textureId, `/assets/tiles/${textureId}.png`, 'tiles', updatedAt)
|
||||
assetData = await assetManager.getAsset(textureId)
|
||||
// If asset is not found, download it
|
||||
if (!asset) {
|
||||
await assetStorage.download(assetData)
|
||||
asset = await assetStorage.get(assetData.key)
|
||||
}
|
||||
|
||||
if (assetData) {
|
||||
// If asset is found, add it to the scene
|
||||
if (asset) {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
scene.textures.addBase64(textureId, assetData.data)
|
||||
scene.textures.once(`addtexture-${textureId}`, () => {
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export async function loadZoneObjectTexture(scene: Phaser.Scene, textureId: string, updatedAt: Date): Promise<boolean> {
|
||||
const assetManager = useAssetManager
|
||||
|
||||
// Check if the texture is already loaded in Phaser
|
||||
if (scene.textures.exists(textureId)) {
|
||||
return true
|
||||
}
|
||||
|
||||
let assetData = await assetManager.getAsset(textureId)
|
||||
|
||||
if (!assetData) {
|
||||
await assetManager.downloadAsset(textureId, `/assets/objects/${textureId}.png`, 'objects', updatedAt)
|
||||
assetData = await assetManager.getAsset(textureId)
|
||||
}
|
||||
|
||||
if (assetData) {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
scene.textures.addBase64(textureId, assetData.data)
|
||||
scene.textures.once(`addtexture-${textureId}`, () => {
|
||||
console.log(asset.data)
|
||||
scene.textures.addBase64(asset.key, asset.data)
|
||||
scene.textures.once(`addtexture-${asset.key}`, () => {
|
||||
gameStore.game.loadedAssets.push(asset)
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
|
@ -1,81 +0,0 @@
|
||||
import config from '@/config'
|
||||
import Dexie from 'dexie'
|
||||
|
||||
class AssetManager extends Dexie {
|
||||
assets!: Dexie.Table<
|
||||
{
|
||||
key: string
|
||||
data: Blob
|
||||
group: string
|
||||
updatedAt: Date
|
||||
frameCount?: number
|
||||
frameWidth?: number
|
||||
frameHeight?: number
|
||||
},
|
||||
string
|
||||
>
|
||||
|
||||
constructor() {
|
||||
super('Assets')
|
||||
this.version(1).stores({
|
||||
assets: 'key, group'
|
||||
})
|
||||
}
|
||||
|
||||
async downloadAsset(key: string, url: string, group: string, updatedAt: Date, frameCount?: number, frameWidth?: number, frameHeight?: number) {
|
||||
try {
|
||||
// Check if the asset already exists, then check if updatedAt is newer
|
||||
const asset = await this.assets.get(key)
|
||||
if (asset && asset.updatedAt > updatedAt) {
|
||||
return
|
||||
}
|
||||
|
||||
// Download the asset
|
||||
const response = await fetch(config.server_endpoint + url)
|
||||
const blob = await response.blob()
|
||||
|
||||
// Store the asset in the database
|
||||
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) {
|
||||
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) {
|
||||
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 deleteAsset(key: string) {
|
||||
try {
|
||||
await this.assets.delete(key)
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete asset ${key}:`, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const useAssetManager = new AssetManager()
|
@ -32,10 +32,8 @@ import CharacterProfile from '@/components/gui/CharacterProfile.vue'
|
||||
import Effects from '@/components/Effects.vue'
|
||||
import Minimap from '@/components/gui/Minimap.vue'
|
||||
import AwaitLoaderPlugin from 'phaser3-rex-plugins/plugins/awaitloader-plugin'
|
||||
import { useAssetManager } from '@/managers/assetManager'
|
||||
|
||||
const gameStore = useGameStore()
|
||||
const assetManager = useAssetManager
|
||||
|
||||
const gameConfig = {
|
||||
name: config.name,
|
||||
|
@ -16,8 +16,8 @@
|
||||
<script setup lang="ts" async>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import config from '@/config'
|
||||
import type { AssetT as ServerAsset } from '@/types'
|
||||
import { useAssetManager } from '@/managers/assetManager'
|
||||
import type { AssetDataT as ServerAsset } from '@/types'
|
||||
import { useAssetManager } from '@/storage/assetStorage'
|
||||
import { useGameStore } from '@/stores/gameStore'
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,8 @@ import { useGameStore } from '@/stores/gameStore'
|
||||
import { useZoneEditorStore } from '@/stores/zoneEditorStore'
|
||||
import ZoneEditor from '@/components/gameMaster/zoneEditor/ZoneEditor.vue'
|
||||
import AwaitLoaderPlugin from 'phaser3-rex-plugins/plugins/awaitloader-plugin'
|
||||
import { loadZoneTilesIntoScene, loadZoneTileTexture } from '@/composables/zoneComposable'
|
||||
import type { AssetT, Tile } from '@/types'
|
||||
import { loadTexture } from '@/composables/zoneComposable'
|
||||
import type { AssetDataT } from '@/types'
|
||||
|
||||
const gameStore = useGameStore()
|
||||
const zoneEditorStore = useZoneEditorStore()
|
||||
@ -65,6 +65,20 @@ 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')
|
||||
|
||||
/**
|
||||
* Because Phaser can't load tiles after the scene with map in it is created,
|
||||
* we need to load and cache all the tiles first.
|
||||
* Then load them into the scene.
|
||||
*/
|
||||
scene.load.rexAwait(async function (successCallback: any) {
|
||||
const tiles: AssetDataT[] = await fetch(config.server_endpoint + '/assets/list_tiles').then((response) => response.json())
|
||||
for await (const tile of tiles) {
|
||||
await loadTexture(scene, tile)
|
||||
}
|
||||
|
||||
successCallback()
|
||||
})
|
||||
}
|
||||
|
||||
const createScene = async (scene: Phaser.Scene) => {}
|
||||
|
@ -9,6 +9,9 @@ export async function register(username: string, email: string, password: string
|
||||
useCookies().set('token', response.data.token as string)
|
||||
return { success: true, token: response.data.token }
|
||||
} catch (error: any) {
|
||||
if (typeof error.response.data === 'undefined') {
|
||||
return { error: 'Could not connect to server' }
|
||||
}
|
||||
return { error: error.response.data.message }
|
||||
}
|
||||
}
|
||||
@ -30,6 +33,9 @@ export async function resetPassword(email: string) {
|
||||
const response = await axios.post(`${config.server_endpoint}/reset-password`, { email })
|
||||
return { success: true, token: response.data.token }
|
||||
} catch (error: any) {
|
||||
if (typeof error.response.data === 'undefined') {
|
||||
return { error: 'Could not connect to server' }
|
||||
}
|
||||
return { error: error.response.data.message }
|
||||
}
|
||||
}
|
||||
|
69
src/storage/assetStorage.ts
Normal file
69
src/storage/assetStorage.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import config from '@/config'
|
||||
import Dexie from 'dexie'
|
||||
import type { AssetDataT } from '@/types'
|
||||
|
||||
export class AssetStorage {
|
||||
private db: Dexie
|
||||
|
||||
constructor() {
|
||||
this.db = new Dexie('assets')
|
||||
this.db.version(1).stores({
|
||||
assets: 'key, group'
|
||||
})
|
||||
}
|
||||
|
||||
async download(asset: AssetDataT) {
|
||||
try {
|
||||
// Check if the asset already exists, then check if updatedAt is newer
|
||||
const _asset = await this.db.table('assets').get(asset.key)
|
||||
if (_asset && _asset.updatedAt > asset.updatedAt) {
|
||||
return
|
||||
}
|
||||
|
||||
// Download the asset
|
||||
const response = await fetch(config.server_endpoint + asset.data)
|
||||
const blob = await response.blob()
|
||||
|
||||
// Store the asset in the database
|
||||
await this.db.table('assets').put({ key: asset.key, data: blob, group: asset.group, updatedAt: asset.updatedAt, frameCount: asset.frameCount, frameWidth: asset.frameWidth, frameHeight: asset.frameHeight })
|
||||
} catch (error) {
|
||||
console.error(`Failed to add asset ${asset.key}:`, error)
|
||||
}
|
||||
}
|
||||
|
||||
async get(key: string) {
|
||||
try {
|
||||
const asset = await this.db.table('assets').get(key)
|
||||
if (asset) {
|
||||
return {
|
||||
...asset,
|
||||
data: URL.createObjectURL(asset.data) // Convert blob to data URL
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to retrieve asset ${key}:`, error)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async getByGroup(group: string) {
|
||||
try {
|
||||
const assets = await this.db.table('assets').where('group').equals(group).toArray()
|
||||
return assets.map((asset) => ({
|
||||
...asset,
|
||||
data: URL.createObjectURL(asset.data) // Convert blob to data URL
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error(`Failed to retrieve assets for group ${group}:`, error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
async delete(key: string) {
|
||||
try {
|
||||
await this.db.table('assets').delete(key)
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete asset ${key}:`, error)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +1,48 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { io, Socket } from 'socket.io-client'
|
||||
import type { Asset, Character, Notification, User, WorldSettings } from '@/types'
|
||||
import type { AssetDataT, Character, Notification, User, WorldSettings } from '@/types'
|
||||
import config from '@/config'
|
||||
import { useCookies } from '@vueuse/integrations/useCookies'
|
||||
import { getDomain } from '@/utilities'
|
||||
|
||||
export const useGameStore = defineStore('game', {
|
||||
state: () => {
|
||||
return {
|
||||
notifications: [] as Notification[],
|
||||
isAssetsLoaded: false,
|
||||
loadedAssets: [] as string[],
|
||||
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: {
|
||||
game: {
|
||||
isAssetsLoaded: false,
|
||||
loadedAssets: [] as AssetDataT[],
|
||||
isPlayerDraggingCamera: false,
|
||||
isCameraFollowingCharacter: false
|
||||
},
|
||||
uiSettings: {
|
||||
isChatOpen: false,
|
||||
isCharacterProfileOpen: false,
|
||||
isGmPanelOpen: false,
|
||||
isPasswordResetOpen: false
|
||||
isGmPanelOpen: false
|
||||
}
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
getLoadedAssets: (state) => {
|
||||
return state.game.loadedAssets
|
||||
},
|
||||
getLoadedAsset: (state) => {
|
||||
return (key: string) => state.game.loadedAssets.find((asset) => asset.key === key)
|
||||
},
|
||||
getLoadedAssetsByGroup: (state) => {
|
||||
return (group: string) => state.game.loadedAssets.filter((asset) => asset.group === group)
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
addNotification(notification: Notification) {
|
||||
if (!notification.id) {
|
||||
@ -54,17 +65,8 @@ export const useGameStore = defineStore('game', {
|
||||
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
|
||||
this.game.isPlayerDraggingCamera = moving
|
||||
},
|
||||
toggleChat() {
|
||||
this.uiSettings.isChatOpen = !this.uiSettings.isChatOpen
|
||||
@ -72,9 +74,6 @@ export const useGameStore = defineStore('game', {
|
||||
toggleCharacterProfile() {
|
||||
this.uiSettings.isCharacterProfileOpen = !this.uiSettings.isCharacterProfileOpen
|
||||
},
|
||||
togglePasswordReset() {
|
||||
this.uiSettings.isPasswordResetOpen = !this.uiSettings.isPasswordResetOpen
|
||||
},
|
||||
initConnection() {
|
||||
this.connection = io(config.server_endpoint, {
|
||||
secure: !config.development,
|
||||
@ -108,17 +107,19 @@ export const useGameStore = defineStore('game', {
|
||||
domain: getDomain()
|
||||
})
|
||||
|
||||
this.isAssetsLoaded = false
|
||||
this.connection = null
|
||||
this.token = null
|
||||
this.user = null
|
||||
this.character = null
|
||||
this.uiSettings.isGmPanelOpen = false
|
||||
this.isPlayerDraggingCamera = false
|
||||
this.gameSettings.isCameraFollowingCharacter = false
|
||||
|
||||
this.game.isAssetsLoaded = false
|
||||
this.game.loadedAssets = []
|
||||
this.game.isPlayerDraggingCamera = false
|
||||
this.game.isCameraFollowingCharacter = false
|
||||
|
||||
this.uiSettings.isChatOpen = false
|
||||
this.uiSettings.isCharacterProfileOpen = false
|
||||
this.uiSettings.isPasswordResetOpen = false
|
||||
this.uiSettings.isGmPanelOpen = false
|
||||
|
||||
this.world.date = new Date()
|
||||
this.world.isRainEnabled = false
|
||||
|
@ -4,9 +4,9 @@ export type Notification = {
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type AssetT = {
|
||||
export type AssetDataT = {
|
||||
key: string
|
||||
url: string
|
||||
data: string
|
||||
group: 'tiles' | 'objects' | 'sprites' | 'sprite_animations' | 'sound' | 'music' | 'ui' | 'font' | 'other'
|
||||
updatedAt: Date
|
||||
frameCount?: number
|
||||
|
@ -22,4 +22,4 @@ export function getDomain() {
|
||||
}
|
||||
|
||||
return window.location.hostname.split('.').slice(-2).join('.')
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user