forked from noxious/client
POC working new caching method - moved controllers folder, renamed assets to textures, fixed HTTP bug, formatted code
This commit is contained in:
parent
6e30a8530a
commit
c2db9b5469
@ -9,6 +9,7 @@
|
|||||||
import GmPanel from '@/components/gameMaster/GmPanel.vue'
|
import GmPanel from '@/components/gameMaster/GmPanel.vue'
|
||||||
import Characters from '@/components/screens/Characters.vue'
|
import Characters from '@/components/screens/Characters.vue'
|
||||||
import Game from '@/components/screens/Game.vue'
|
import Game from '@/components/screens/Game.vue'
|
||||||
|
import Loading from '@/components/screens/Loading.vue'
|
||||||
import Login from '@/components/screens/Login.vue'
|
import Login from '@/components/screens/Login.vue'
|
||||||
import MapEditor from '@/components/screens/MapEditor.vue'
|
import MapEditor from '@/components/screens/MapEditor.vue'
|
||||||
import BackgroundImageLoader from '@/components/utilities/BackgroundImageLoader.vue'
|
import BackgroundImageLoader from '@/components/utilities/BackgroundImageLoader.vue'
|
||||||
@ -21,6 +22,7 @@ const gameStore = useGameStore()
|
|||||||
const mapEditorStore = useMapEditorStore()
|
const mapEditorStore = useMapEditorStore()
|
||||||
|
|
||||||
const currentScreen = computed(() => {
|
const currentScreen = computed(() => {
|
||||||
|
if (!gameStore.game.isLoaded) return Loading
|
||||||
if (!gameStore.connection) return Login
|
if (!gameStore.connection) return Login
|
||||||
if (!gameStore.token) return Login
|
if (!gameStore.token) return Login
|
||||||
if (!gameStore.character) return Characters
|
if (!gameStore.character) return Characters
|
||||||
@ -37,6 +39,9 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// #209: Play sound when a button is pressed
|
// #209: Play sound when a button is pressed
|
||||||
|
/**
|
||||||
|
* @TODO: Not all button-like elements will actually be a button, so we need to find a better way to do this
|
||||||
|
*/
|
||||||
addEventListener('click', (event) => {
|
addEventListener('click', (event) => {
|
||||||
if (!(event.target instanceof HTMLButtonElement)) {
|
if (!(event.target instanceof HTMLButtonElement)) {
|
||||||
return
|
return
|
||||||
|
@ -12,9 +12,9 @@ export type HttpResponse<T> = {
|
|||||||
data?: T
|
data?: T
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AssetDataT = {
|
export type TextureData = {
|
||||||
key: string
|
key: string
|
||||||
data: string
|
data: string // URL or Base64 encoded blob
|
||||||
group: 'tiles' | 'map_objects' | 'sprites' | 'sprite_animations' | 'sound' | 'music' | 'ui' | 'font' | 'other'
|
group: 'tiles' | 'map_objects' | 'sprites' | 'sprite_animations' | 'sound' | 'music' | 'ui' | 'font' | 'other'
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
originX?: number
|
originX?: number
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { MapCharacter, mapLoadData, UUID } from '@/application/types'
|
import type { MapCharacter, mapLoadData, UUID } from '@/application/types'
|
||||||
import Characters from '@/components/game/map/Characters.vue'
|
import Characters from '@/components/game/map/Characters.vue'
|
||||||
import MapObjects from '@/components/game/map/PlacedMapObjects.vue'
|
|
||||||
import MapTiles from '@/components/game/map/MapTiles.vue'
|
import MapTiles from '@/components/game/map/MapTiles.vue'
|
||||||
|
import MapObjects from '@/components/game/map/PlacedMapObjects.vue'
|
||||||
import { loadMapTilesIntoScene } from '@/composables/mapComposable'
|
import { loadMapTilesIntoScene } from '@/composables/mapComposable'
|
||||||
import { useGameStore } from '@/stores/gameStore'
|
import { useGameStore } from '@/stores/gameStore'
|
||||||
import { useMapStore } from '@/stores/mapStore'
|
import { useMapStore } from '@/stores/mapStore'
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { AssetDataT, PlacedMapObject } from '@/application/types'
|
import type { PlacedMapObject, TextureData } from '@/application/types'
|
||||||
import { loadTexture } from '@/composables/gameComposable'
|
import { loadTexture } from '@/composables/gameComposable'
|
||||||
import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/mapComposable'
|
import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/mapComposable'
|
||||||
import { useGameStore } from '@/stores/gameStore'
|
import { useGameStore } from '@/stores/gameStore'
|
||||||
@ -30,12 +30,12 @@ const imageProps = computed(() => ({
|
|||||||
|
|
||||||
loadTexture(scene, {
|
loadTexture(scene, {
|
||||||
key: props.placedMapObject.mapObject.id,
|
key: props.placedMapObject.mapObject.id,
|
||||||
data: '/assets/map_objects/' + props.placedMapObject.mapObject.id + '.png',
|
data: '/textures/map_objects/' + props.placedMapObject.mapObject.id + '.png',
|
||||||
group: 'map_objects',
|
group: 'map_objects',
|
||||||
updatedAt: props.placedMapObject.mapObject.updatedAt,
|
updatedAt: props.placedMapObject.mapObject.updatedAt,
|
||||||
frameWidth: props.placedMapObject.mapObject.frameWidth,
|
frameWidth: props.placedMapObject.mapObject.frameWidth,
|
||||||
frameHeight: props.placedMapObject.mapObject.frameHeight
|
frameHeight: props.placedMapObject.mapObject.frameHeight
|
||||||
} as AssetDataT).catch((error) => {
|
} as TextureData).catch((error) => {
|
||||||
console.error('Error loading texture:', error)
|
console.error('Error loading texture:', error)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-full overflow-auto">
|
<div class="h-full overflow-auto">
|
||||||
<div class="relative p-2.5 flex flex-col items-center justify-center h-72 rounded-md default-border bg-gray">
|
<div class="relative p-2.5 flex flex-col items-center justify-center h-72 rounded-md default-border bg-gray">
|
||||||
<img class="max-h-56" :src="`${config.server_endpoint}/assets/map_objects/${selectedMapObject?.id}.png`" :alt="'Object ' + selectedMapObject?.id" />
|
<img class="max-h-56" :src="`${config.server_endpoint}/textures/map_objects/${selectedMapObject?.id}.png`" :alt="'Object ' + selectedMapObject?.id" />
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5 block">
|
<div class="mt-5 block">
|
||||||
<form class="flex gap-2.5 flex-wrap" @submit.prevent="saveObject">
|
<form class="flex gap-2.5 flex-wrap" @submit.prevent="saveObject">
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<a v-for="{ data: mapObject } in list" :key="mapObject.id" class="relative p-2.5 cursor-pointer block rounded hover:bg-cyan group" :class="{ 'bg-cyan': assetManagerStore.selectedMapObject?.id === mapObject.id }" @click="assetManagerStore.setSelectedMapObject(mapObject as MapObject)">
|
<a v-for="{ data: mapObject } in list" :key="mapObject.id" class="relative p-2.5 cursor-pointer block rounded hover:bg-cyan group" :class="{ 'bg-cyan': assetManagerStore.selectedMapObject?.id === mapObject.id }" @click="assetManagerStore.setSelectedMapObject(mapObject as MapObject)">
|
||||||
<div class="flex items-center gap-2.5">
|
<div class="flex items-center gap-2.5">
|
||||||
<div class="h-7 w-16 max-w-16 flex justify-center">
|
<div class="h-7 w-16 max-w-16 flex justify-center">
|
||||||
<img class="h-7" :src="`${config.server_endpoint}/assets/map_objects/${mapObject.id}.png`" alt="Object" />
|
<img class="h-7" :src="`${config.server_endpoint}/textures/map_objects/${mapObject.id}.png`" alt="Object" />
|
||||||
</div>
|
</div>
|
||||||
<span :class="{ 'text-white': assetManagerStore.selectedMapObject?.id === mapObject.id }">{{ mapObject.name }}</span>
|
<span :class="{ 'text-white': assetManagerStore.selectedMapObject?.id === mapObject.id }">{{ mapObject.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-full overflow-auto">
|
<div class="h-full overflow-auto">
|
||||||
<div class="relative p-2.5 flex flex-col items-center justify-center h-72 rounded-md default-border bg-gray">
|
<div class="relative p-2.5 flex flex-col items-center justify-center h-72 rounded-md default-border bg-gray">
|
||||||
<img class="max-h-72" :src="`${config.server_endpoint}/assets/tiles/${selectedTile?.id}.png`" :alt="'Tile ' + selectedTile?.id" />
|
<img class="max-h-72" :src="`${config.server_endpoint}/textures/tiles/${selectedTile?.id}.png`" :alt="'Tile ' + selectedTile?.id" />
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5 block">
|
<div class="mt-5 block">
|
||||||
<form class="flex gap-2.5 flex-wrap" @submit.prevent="saveTile">
|
<form class="flex gap-2.5 flex-wrap" @submit.prevent="saveTile">
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<a v-for="{ data: tile } in list" :key="tile.id" class="relative p-2.5 cursor-pointer block rounded hover:bg-cyan group" :class="{ 'bg-cyan': assetManagerStore.selectedTile?.id === tile.id }" @click="assetManagerStore.setSelectedTile(tile)">
|
<a v-for="{ data: tile } in list" :key="tile.id" class="relative p-2.5 cursor-pointer block rounded hover:bg-cyan group" :class="{ 'bg-cyan': assetManagerStore.selectedTile?.id === tile.id }" @click="assetManagerStore.setSelectedTile(tile)">
|
||||||
<div class="flex items-center gap-2.5">
|
<div class="flex items-center gap-2.5">
|
||||||
<div class="h-7 w-16 max-w-16 flex justify-center">
|
<div class="h-7 w-16 max-w-16 flex justify-center">
|
||||||
<img class="h-7" :src="`${config.server_endpoint}/assets/tiles/${tile.id}.png`" alt="Tile" />
|
<img class="h-7" :src="`${config.server_endpoint}/textures/tiles/${tile.id}.png`" alt="Tile" />
|
||||||
</div>
|
</div>
|
||||||
<span class="group-hover:text-white" :class="{ 'text-white': assetManagerStore.selectedTile?.id === tile.id }">{{ tile.name }}</span>
|
<span class="group-hover:text-white" :class="{ 'text-white': assetManagerStore.selectedTile?.id === tile.id }">{{ tile.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type Map } from '@/application/types'
|
import { type Map } from '@/application/types'
|
||||||
import MapEventTiles from '@/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue'
|
import MapEventTiles from '@/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue'
|
||||||
import MapObjects from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue'
|
|
||||||
import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue'
|
import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue'
|
||||||
|
import MapObjects from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue'
|
||||||
import MapList from '@/components/gameMaster/mapEditor/partials/MapList.vue'
|
import MapList from '@/components/gameMaster/mapEditor/partials/MapList.vue'
|
||||||
import MapSettings from '@/components/gameMaster/mapEditor/partials/MapSettings.vue'
|
|
||||||
import ObjectList from '@/components/gameMaster/mapEditor/partials/MapObjectList.vue'
|
import ObjectList from '@/components/gameMaster/mapEditor/partials/MapObjectList.vue'
|
||||||
|
import MapSettings from '@/components/gameMaster/mapEditor/partials/MapSettings.vue'
|
||||||
import TeleportModal from '@/components/gameMaster/mapEditor/partials/TeleportModal.vue'
|
import TeleportModal from '@/components/gameMaster/mapEditor/partials/TeleportModal.vue'
|
||||||
import TileList from '@/components/gameMaster/mapEditor/partials/TileList.vue'
|
import TileList from '@/components/gameMaster/mapEditor/partials/TileList.vue'
|
||||||
// Components
|
// Components
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import config from '@/application/config'
|
import config from '@/application/config'
|
||||||
import type { AssetDataT } from '@/application/types'
|
import type { TextureData } from '@/application/types'
|
||||||
import Controls from '@/components/utilities/Controls.vue'
|
import Controls from '@/components/utilities/Controls.vue'
|
||||||
import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/mapComposable'
|
import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/mapComposable'
|
||||||
import { useGameStore } from '@/stores/gameStore'
|
import { useGameStore } from '@/stores/gameStore'
|
||||||
@ -47,7 +47,7 @@ function createTileMap() {
|
|||||||
function createTileLayer() {
|
function createTileLayer() {
|
||||||
const tilesArray = gameStore.getLoadedAssetsByGroup('tiles')
|
const tilesArray = gameStore.getLoadedAssetsByGroup('tiles')
|
||||||
|
|
||||||
const tilesetImages = Array.from(tilesArray).map((tile: AssetDataT, index: number) => {
|
const tilesetImages = Array.from(tilesArray).map((tile: TextureData, index: number) => {
|
||||||
return tileMap.addTilesetImage(tile.key, tile.key, config.tile_size.x, config.tile_size.y, 1, 2, index + 1, { x: 0, y: -config.tile_size.y })
|
return tileMap.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
|
}) as any
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { AssetDataT, PlacedMapObject } from '@/application/types'
|
import type { PlacedMapObject, TextureData } from '@/application/types'
|
||||||
import { loadTexture } from '@/composables/gameComposable'
|
import { loadTexture } from '@/composables/gameComposable'
|
||||||
import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/mapComposable'
|
import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/mapComposable'
|
||||||
import { useGameStore } from '@/stores/gameStore'
|
import { useGameStore } from '@/stores/gameStore'
|
||||||
@ -34,12 +34,12 @@ const imageProps = computed(() => ({
|
|||||||
|
|
||||||
loadTexture(scene, {
|
loadTexture(scene, {
|
||||||
key: props.placedMapObject.mapObject.id,
|
key: props.placedMapObject.mapObject.id,
|
||||||
data: '/assets/map_objects/' + props.placedMapObject.mapObject.id + '.png',
|
data: '/textures/map_objects/' + props.placedMapObject.mapObject.id + '.png',
|
||||||
group: 'map_objects',
|
group: 'map_objects',
|
||||||
updatedAt: props.placedMapObject.mapObject.updatedAt,
|
updatedAt: props.placedMapObject.mapObject.updatedAt,
|
||||||
frameWidth: props.placedMapObject.mapObject.frameWidth,
|
frameWidth: props.placedMapObject.mapObject.frameWidth,
|
||||||
frameHeight: props.placedMapObject.mapObject.frameHeight
|
frameHeight: props.placedMapObject.mapObject.frameHeight
|
||||||
} as AssetDataT).catch((error) => {
|
} as TextureData).catch((error) => {
|
||||||
console.error('Error loading texture:', error)
|
console.error('Error loading texture:', error)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { MapObject, PlacedMapObject as PlacedMapObjectT } from '@/application/types'
|
import type { MapObject, PlacedMapObject as PlacedMapObjectT } from '@/application/types'
|
||||||
import { uuidv4 } from '@/application/utilities'
|
import { uuidv4 } from '@/application/utilities'
|
||||||
|
import PlacedMapObject from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObject.vue'
|
||||||
|
import SelectedPlacedMapObjectComponent from '@/components/gameMaster/mapEditor/partials/SelectedPlacedMapObject.vue'
|
||||||
import { getTile } from '@/composables/mapComposable'
|
import { getTile } from '@/composables/mapComposable'
|
||||||
import { useMapEditorStore } from '@/stores/mapEditorStore'
|
import { useMapEditorStore } from '@/stores/mapEditorStore'
|
||||||
import { useScene } from 'phavuer'
|
import { useScene } from 'phavuer'
|
||||||
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import PlacedMapObject from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObject.vue'
|
|
||||||
import SelectedPlacedMapObjectComponent from '@/components/gameMaster/mapEditor/partials/SelectedPlacedMapObject.vue'
|
|
||||||
|
|
||||||
const scene = useScene()
|
const scene = useScene()
|
||||||
const mapEditorStore = useMapEditorStore()
|
const mapEditorStore = useMapEditorStore()
|
||||||
@ -240,7 +240,7 @@ watch(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// { deep: true }
|
// { deep: true }
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<div v-for="(mapObject, index) in filteredMapObjects" :key="index" class="max-w-1/4 inline-block">
|
<div v-for="(mapObject, index) in filteredMapObjects" :key="index" class="max-w-1/4 inline-block">
|
||||||
<img
|
<img
|
||||||
class="border-2 border-solid max-w-full"
|
class="border-2 border-solid max-w-full"
|
||||||
:src="`${config.server_endpoint}/assets/map_objects/${mapObject.id}.png`"
|
:src="`${config.server_endpoint}/textures/map_objects/${mapObject.id}.png`"
|
||||||
alt="Object"
|
alt="Object"
|
||||||
@click="mapEditorStore.setSelectedMapObject(mapObject)"
|
@click="mapEditorStore.setSelectedMapObject(mapObject)"
|
||||||
:class="{
|
:class="{
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<div v-for="group in groupedTiles" :key="group.parent.id" class="flex flex-col items-center justify-center relative">
|
<div v-for="group in groupedTiles" :key="group.parent.id" class="flex flex-col items-center justify-center relative">
|
||||||
<img
|
<img
|
||||||
class="max-w-full max-h-full border-2 border-solid cursor-pointer transition-all duration-300"
|
class="max-w-full max-h-full border-2 border-solid cursor-pointer transition-all duration-300"
|
||||||
:src="`${config.server_endpoint}/assets/tiles/${group.parent.id}.png`"
|
:src="`${config.server_endpoint}/textures/tiles/${group.parent.id}.png`"
|
||||||
:alt="group.parent.name"
|
:alt="group.parent.name"
|
||||||
@click="openGroup(group)"
|
@click="openGroup(group)"
|
||||||
@load="() => processTile(group.parent)"
|
@load="() => processTile(group.parent)"
|
||||||
@ -50,7 +50,7 @@
|
|||||||
<div class="flex flex-col items-center justify-center">
|
<div class="flex flex-col items-center justify-center">
|
||||||
<img
|
<img
|
||||||
class="max-w-full max-h-full border-2 border-solid cursor-pointer transition-all duration-300"
|
class="max-w-full max-h-full border-2 border-solid cursor-pointer transition-all duration-300"
|
||||||
:src="`${config.server_endpoint}/assets/tiles/${selectedGroup.parent.id}.png`"
|
:src="`${config.server_endpoint}/textures/tiles/${selectedGroup.parent.id}.png`"
|
||||||
:alt="selectedGroup.parent.name"
|
:alt="selectedGroup.parent.name"
|
||||||
@click="selectTile(selectedGroup.parent.id)"
|
@click="selectTile(selectedGroup.parent.id)"
|
||||||
:class="{
|
:class="{
|
||||||
@ -63,7 +63,7 @@
|
|||||||
<div v-for="childTile in selectedGroup.children" :key="childTile.id" class="flex flex-col items-center justify-center">
|
<div v-for="childTile in selectedGroup.children" :key="childTile.id" class="flex flex-col items-center justify-center">
|
||||||
<img
|
<img
|
||||||
class="max-w-full max-h-full border-2 border-solid cursor-pointer transition-all duration-300"
|
class="max-w-full max-h-full border-2 border-solid cursor-pointer transition-all duration-300"
|
||||||
:src="`${config.server_endpoint}/assets/tiles/${childTile.id}.png`"
|
:src="`${config.server_endpoint}/textures/tiles/${childTile.id}.png`"
|
||||||
:alt="childTile.name"
|
:alt="childTile.name"
|
||||||
@click="selectTile(childTile.id)"
|
@click="selectTile(childTile.id)"
|
||||||
:class="{
|
:class="{
|
||||||
@ -169,7 +169,7 @@ function processTile(tile: Tile) {
|
|||||||
tileColorData.value.set(tile.id, getDominantColor(imageData))
|
tileColorData.value.set(tile.id, getDominantColor(imageData))
|
||||||
tileEdgeData.value.set(tile.id, getEdgeComplexity(imageData))
|
tileEdgeData.value.set(tile.id, getEdgeComplexity(imageData))
|
||||||
}
|
}
|
||||||
img.src = `${config.server_endpoint}/assets/tiles/${tile.id}.png`
|
img.src = `${config.server_endpoint}/textures/tiles/${tile.id}.png`
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDominantColor(imageData: ImageData) {
|
function getDominantColor(imageData: ImageData) {
|
||||||
|
@ -74,7 +74,7 @@
|
|||||||
v-for="hair in characterHairs"
|
v-for="hair in characterHairs"
|
||||||
class="relative flex justify-center items-center bg-gray default-border w-[18px] h-[18px] p-2 rounded-sm hover:bg-gray-500 hover:border-gray-400 focus-visible:outline-none focus-visible:border-gray-300 focus-visible:bg-gray-500 has-[:checked]:bg-cyan has-[:checked]:border-transparent"
|
class="relative flex justify-center items-center bg-gray default-border w-[18px] h-[18px] p-2 rounded-sm hover:bg-gray-500 hover:border-gray-400 focus-visible:outline-none focus-visible:border-gray-300 focus-visible:bg-gray-500 has-[:checked]:bg-cyan has-[:checked]:border-transparent"
|
||||||
>
|
>
|
||||||
<img class="h-4 object-contain" :src="config.server_endpoint + '/assets/sprites/' + hair.sprite.id + '/front.png'" alt="Hair sprite" />
|
<img class="h-4 object-contain" :src="config.server_endpoint + '/textures/sprites/' + hair.sprite?.id + '/front.png'" alt="Hair sprite" />
|
||||||
<input type="radio" name="hair" :value="hair.id" v-model="selectedHairId" class="h-full w-full absolute left-0 top-0 m-0 z-10 hover:cursor-pointer focus-visible:outline-offset-0 focus-visible:outline-white" />
|
<input type="radio" name="hair" :value="hair.id" v-model="selectedHairId" class="h-full w-full absolute left-0 top-0 m-0 z-10 hover:cursor-pointer focus-visible:outline-offset-0 focus-visible:outline-white" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,7 +82,5 @@ function preloadScene(scene: Phaser.Scene) {
|
|||||||
|
|
||||||
function createScene(scene: Phaser.Scene) {}
|
function createScene(scene: Phaser.Scene) {}
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {})
|
||||||
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,25 +1,79 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col justify-center items-center h-dvh relative">
|
<div class="flex flex-col justify-center items-center h-dvh relative col">
|
||||||
<button @click="continueBtnClick" class="w-32 h-12 rounded-full bg-gray-500 flex items-center justify-between px-4 hover:bg-gray-600 transition-colors">
|
<svg width="40" height="40" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<span class="text-white text-lg flex-1 text-center">Play</span>
|
<circle cx="4" cy="12" r="3" fill="white">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<animate id="spinner_qFRN" begin="0;spinner_OcgL.end+0.25s" attributeName="cy" calcMode="spline" dur="0.6s" values="12;6;12" keySplines=".33,.66,.66,1;.33,0,.66,.33" />
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
</circle>
|
||||||
</svg>
|
<circle cx="12" cy="12" r="3" fill="white">
|
||||||
</button>
|
<animate begin="spinner_qFRN.begin+0.1s" attributeName="cy" calcMode="spline" dur="0.6s" values="12;6;12" keySplines=".33,.66,.66,1;.33,0,.66,.33" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="20" cy="12" r="3" fill="white">
|
||||||
|
<animate id="spinner_OcgL" begin="spinner_qFRN.begin+0.2s" attributeName="cy" calcMode="spline" dur="0.6s" values="12;6;12" keySplines=".33,.66,.66,1;.33,0,.66,.33" />
|
||||||
|
</circle>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" async>
|
<script setup lang="ts" async>
|
||||||
|
import config from '@/application/config'
|
||||||
|
import type { HttpResponse, MapObject } from '@/application/types'
|
||||||
|
import { MapObjectStorage } from '@/dexie/mapObjects'
|
||||||
|
import { MapStorage } from '@/dexie/maps'
|
||||||
|
// import type { Map } from '@/application/types'
|
||||||
|
import type { Map } from '@/dexie/maps'
|
||||||
import { useGameStore } from '@/stores/gameStore'
|
import { useGameStore } from '@/stores/gameStore'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
const gameStore = useGameStore()
|
const gameStore = useGameStore()
|
||||||
|
|
||||||
function continueBtnClick() {
|
const mapStorage = new MapStorage()
|
||||||
// Play music
|
const mapObjectStorage = new MapObjectStorage()
|
||||||
const audio = new Audio('/assets/music/login.mp3')
|
|
||||||
audio.play()
|
|
||||||
|
|
||||||
|
const totalItems = ref(0)
|
||||||
|
const currentItem = ref(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download map cache from the server and add them to the storage
|
||||||
|
*/
|
||||||
|
async function downloadMaps() {
|
||||||
|
// Request to download maps
|
||||||
|
const request = await fetch(config.server_endpoint + '/cache/maps')
|
||||||
|
const response = (await request.json()) as HttpResponse<Map[]>
|
||||||
|
if (!response.success) {
|
||||||
|
console.error('Failed to download maps:', response.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const maps = response.data ?? ([] as Map[])
|
||||||
|
|
||||||
|
// Add maps to storage
|
||||||
|
for (const map of maps) {
|
||||||
|
await mapStorage.add(map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download map objects cache from the server and add them to the storage
|
||||||
|
*/
|
||||||
|
async function downloadMapObjects() {
|
||||||
|
// Request to download map objects
|
||||||
|
const request = await fetch(config.server_endpoint + '/cache/map_objects')
|
||||||
|
const response = (await request.json()) as HttpResponse<MapObject[]>
|
||||||
|
if (!response.success) {
|
||||||
|
console.error('Failed to download map objects:', response.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapObjects = response.data ?? ([] as MapObject[])
|
||||||
|
|
||||||
|
// Add map objects to storage
|
||||||
|
for (const mapObject of mapObjects) {
|
||||||
|
await mapObjectStorage.add(mapObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all([downloadMaps(), downloadMapObjects()]).then(() => {
|
||||||
// Set isLoaded to true
|
// Set isLoaded to true
|
||||||
gameStore.game.isLoaded = true
|
gameStore.game.isLoaded = true
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import config from '@/application/config'
|
import config from '@/application/config'
|
||||||
import 'phaser'
|
import 'phaser'
|
||||||
import type { AssetDataT } from '@/application/types'
|
import type { TextureData } from '@/application/types'
|
||||||
import MapEditor from '@/components/gameMaster/mapEditor/MapEditor.vue'
|
import MapEditor from '@/components/gameMaster/mapEditor/MapEditor.vue'
|
||||||
import { loadTexture } from '@/composables/gameComposable'
|
import { loadTexture } from '@/composables/gameComposable'
|
||||||
import { useGameStore } from '@/stores/gameStore'
|
import { useGameStore } from '@/stores/gameStore'
|
||||||
@ -72,7 +72,7 @@ const preloadScene = async (scene: Phaser.Scene) => {
|
|||||||
* Then load them into the scene.
|
* Then load them into the scene.
|
||||||
*/
|
*/
|
||||||
scene.load.rexAwait(async function (successCallback: any) {
|
scene.load.rexAwait(async function (successCallback: any) {
|
||||||
const tiles: { data: AssetDataT[] } = await fetch(config.server_endpoint + '/assets/list_tiles').then((response) => response.json())
|
const tiles: { data: TextureData[] } = await fetch(config.server_endpoint + '/assets/list_tiles').then((response) => response.json())
|
||||||
|
|
||||||
for await (const tile of tiles?.data ?? []) {
|
for await (const tile of tiles?.data ?? []) {
|
||||||
await loadTexture(scene, tile)
|
await loadTexture(scene, tile)
|
||||||
|
@ -1,58 +1,58 @@
|
|||||||
import { Assets } from '@/dexie/assets'
|
|
||||||
import config from '@/application/config'
|
import config from '@/application/config'
|
||||||
import type { AssetDataT, HttpResponse, Sprite, SpriteAction } from '@/application/types'
|
import type { HttpResponse, Sprite, SpriteAction, TextureData } from '@/application/types'
|
||||||
|
import { Textures } from '@/dexie/textures'
|
||||||
import { useGameStore } from '@/stores/gameStore'
|
import { useGameStore } from '@/stores/gameStore'
|
||||||
|
|
||||||
const textureLoadingPromises = new Map<string, Promise<boolean>>()
|
const textureLoadingPromises = new Map<string, Promise<boolean>>()
|
||||||
|
|
||||||
export async function loadTexture(scene: Phaser.Scene, assetData: AssetDataT): Promise<boolean> {
|
export async function loadTexture(scene: Phaser.Scene, textureData: TextureData): Promise<boolean> {
|
||||||
const gameStore = useGameStore()
|
const gameStore = useGameStore()
|
||||||
const assetStorage = new Assets()
|
const textures = new Textures()
|
||||||
|
|
||||||
// Check if the texture is already loaded in Phaser
|
// Check if the texture is already loaded in Phaser
|
||||||
if (gameStore.game.loadedAssets.find((asset) => asset.key === assetData.key)) {
|
if (gameStore.game.loadedAssets.find((asset) => asset.key === textureData.key)) {
|
||||||
return Promise.resolve(true)
|
return Promise.resolve(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's already a loading promise for this texture, return it
|
// If there's already a loading promise for this texture, return it
|
||||||
if (textureLoadingPromises.has(assetData.key)) {
|
if (textureLoadingPromises.has(textureData.key)) {
|
||||||
return await textureLoadingPromises.get(assetData.key)!
|
return await textureLoadingPromises.get(textureData.key)!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new loading promise
|
// Create new loading promise
|
||||||
const loadingPromise = (async () => {
|
const loadingPromise = (async () => {
|
||||||
// Check if the asset is already cached
|
// Check if the asset is already cached
|
||||||
let asset = await assetStorage.get(assetData.key)
|
let texture = await textures.get(textureData.key)
|
||||||
|
|
||||||
// If asset is not found, download it
|
// If asset is not found, download it
|
||||||
if (!asset) {
|
if (!texture) {
|
||||||
await assetStorage.download(assetData)
|
await textures.download(textureData)
|
||||||
asset = await assetStorage.get(assetData.key)
|
texture = await textures.get(textureData.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If asset is found, add it to the scene
|
// If asset is found, add it to the scene
|
||||||
if (asset) {
|
if (texture) {
|
||||||
return new Promise<boolean>((resolve) => {
|
return new Promise<boolean>((resolve) => {
|
||||||
// Remove existing texture if it exists
|
// Remove existing texture if it exists
|
||||||
if (scene.textures.exists(asset.key)) {
|
if (scene.textures.exists(texture.key)) {
|
||||||
scene.textures.remove(asset.key)
|
scene.textures.remove(texture.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
scene.textures.addBase64(asset.key, asset.data)
|
scene.textures.addBase64(texture.key, texture.data)
|
||||||
scene.textures.once(`addtexture-${asset.key}`, () => {
|
scene.textures.once(`addtexture-${texture.key}`, () => {
|
||||||
gameStore.game.loadedAssets.push(assetData)
|
gameStore.game.loadedAssets.push(textureData)
|
||||||
textureLoadingPromises.delete(assetData.key) // Clean up the promise
|
textureLoadingPromises.delete(textureData.key) // Clean up the promise
|
||||||
resolve(true)
|
resolve(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
textureLoadingPromises.delete(assetData.key) // Clean up the promise
|
textureLoadingPromises.delete(textureData.key) // Clean up the promise
|
||||||
return Promise.resolve(false)
|
return Promise.resolve(false)
|
||||||
})()
|
})()
|
||||||
|
|
||||||
// Store the loading promise
|
// Store the loading promise
|
||||||
textureLoadingPromises.set(assetData.key, loadingPromise)
|
textureLoadingPromises.set(textureData.key, loadingPromise)
|
||||||
return loadingPromise
|
return loadingPromise
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ export async function loadSpriteTextures(scene: Phaser.Scene, sprite_id: string)
|
|||||||
frameWidth: sprite_action.frameWidth,
|
frameWidth: sprite_action.frameWidth,
|
||||||
frameHeight: sprite_action.frameHeight,
|
frameHeight: sprite_action.frameHeight,
|
||||||
frameRate: sprite_action.frameRate
|
frameRate: sprite_action.frameRate
|
||||||
} as AssetDataT)
|
} as TextureData)
|
||||||
|
|
||||||
// If the sprite is not animated, skip
|
// If the sprite is not animated, skip
|
||||||
if (!sprite_action.isAnimated) continue
|
if (!sprite_action.isAnimated) continue
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import config from '@/application/config'
|
import config from '@/application/config'
|
||||||
import type { AssetDataT, HttpResponse, UUID } from '@/application/types'
|
import type { HttpResponse, TextureData, UUID } from '@/application/types'
|
||||||
|
import { unduplicateArray } from '@/application/utilities'
|
||||||
import { loadTexture } from '@/composables/gameComposable'
|
import { loadTexture } from '@/composables/gameComposable'
|
||||||
|
import { MapStorage } from '@/dexie/maps'
|
||||||
|
|
||||||
import Tilemap = Phaser.Tilemaps.Tilemap
|
import Tilemap = Phaser.Tilemaps.Tilemap
|
||||||
import TilemapLayer = Phaser.Tilemaps.TilemapLayer
|
import TilemapLayer = Phaser.Tilemaps.TilemapLayer
|
||||||
@ -86,11 +88,22 @@ export function FlattenMapArray(tiles: string[][]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function loadMapTilesIntoScene(map_id: UUID, scene: Phaser.Scene) {
|
export async function loadMapTilesIntoScene(map_id: UUID, scene: Phaser.Scene) {
|
||||||
// Fetch the list of tiles from the server
|
const mapStorage = new MapStorage()
|
||||||
const tileArray: HttpResponse<AssetDataT[]> = await fetch(config.server_endpoint + '/assets/list_tiles/' + map_id).then((response) => response.json())
|
const map = await mapStorage.get(map_id)
|
||||||
|
if (!map) return
|
||||||
|
|
||||||
|
const tileArray = unduplicateArray(FlattenMapArray(map.tiles))
|
||||||
|
|
||||||
|
console.log(tileArray)
|
||||||
|
|
||||||
// Load each tile into the scene
|
// Load each tile into the scene
|
||||||
for (const tile of tileArray.data ?? []) {
|
for (const tile of tileArray) {
|
||||||
await loadTexture(scene, tile)
|
const textureData = {
|
||||||
|
key: tile,
|
||||||
|
data: '/textures/tiles/' + tile + '.png',
|
||||||
|
group: 'tiles',
|
||||||
|
updatedAt: map.updatedAt // @TODO: Fix this
|
||||||
|
} as TextureData
|
||||||
|
await loadTexture(scene, textureData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,111 +1,88 @@
|
|||||||
|
import type { MapObject } from '@/application/types'
|
||||||
import Dexie from 'dexie'
|
import Dexie from 'dexie'
|
||||||
import type { UUID } from '@/application/types'
|
|
||||||
// import type { Map } from '@/application/types'
|
|
||||||
|
|
||||||
export type Map = {
|
export class MapObjectStorage {
|
||||||
id: UUID; // or string, depending on your ID type
|
|
||||||
name: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
tiles: any[]; // You might want to be more specific about the tiles type
|
|
||||||
pvp: boolean;
|
|
||||||
updatedAt: Date;
|
|
||||||
placedMapObjects: {
|
|
||||||
id: UUID; // or string
|
|
||||||
mapObject: UUID; // or string
|
|
||||||
depth: number;
|
|
||||||
isRotated: boolean;
|
|
||||||
positionX: number;
|
|
||||||
positionY: number;
|
|
||||||
}[];
|
|
||||||
mapEffects: {
|
|
||||||
effect: string; // or specific enum/type if available
|
|
||||||
strength: number;
|
|
||||||
}[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export class MapStorage {
|
|
||||||
private dexie: Dexie
|
private dexie: Dexie
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.dexie = new Dexie('maps')
|
this.dexie = new Dexie('map_objects')
|
||||||
this.dexie.version(1).stores({
|
this.dexie.version(1).stores({
|
||||||
maps: 'id, name, createdAt, updatedAt'
|
map_objects: 'id, name, createdAt, updatedAt'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(map: Map, overwrite = false) {
|
async add(mapObject: MapObject, overwrite = false) {
|
||||||
try {
|
try {
|
||||||
// Check if map already exists, don't add if it does and overwrite is false
|
// Check if map object already exists, don't add if it does and overwrite is false
|
||||||
const existingMap = await this.get(map.id)
|
const existingMapObject = await this.get(mapObject.id)
|
||||||
if (existingMap && !overwrite) return
|
if (existingMapObject && !overwrite) return
|
||||||
|
|
||||||
await this.dexie.table('maps').put({
|
await this.dexie.table('map_objects').put({
|
||||||
...map
|
...mapObject
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to add map ${map.id}:`, error)
|
console.error(`Failed to add map object ${mapObject.id}:`, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: string): Promise<Map | null> {
|
async get(id: string): Promise<MapObject | null> {
|
||||||
try {
|
try {
|
||||||
const map = await this.dexie.table('maps').get(id)
|
const mapObject = await this.dexie.table('map_objects').get(id)
|
||||||
return map || null
|
return mapObject || null
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to retrieve map ${id}:`, error)
|
console.error(`Failed to retrieve map object ${id}:`, error)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAll(): Promise<Map[]> {
|
async getAll(): Promise<MapObject[]> {
|
||||||
try {
|
try {
|
||||||
return await this.dexie.table('maps').toArray()
|
return await this.dexie.table('map_objects').toArray()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to retrieve all maps:', error)
|
console.error('Failed to retrieve all map objects:', error)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByName(name: string): Promise<Map[]> {
|
async getByName(name: string): Promise<MapObject[]> {
|
||||||
try {
|
try {
|
||||||
return await this.dexie.table('maps').where('name').equals(name).toArray()
|
return await this.dexie.table('map_objects').where('name').equals(name).toArray()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to retrieve maps with name ${name}:`, error)
|
console.error(`Failed to retrieve map objects with name ${name}:`, error)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string) {
|
async delete(id: string) {
|
||||||
try {
|
try {
|
||||||
await this.dexie.table('maps').delete(id)
|
await this.dexie.table('map_objects').delete(id)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to delete map ${id}:`, error)
|
console.error(`Failed to delete map object ${id}:`, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear() {
|
async clear() {
|
||||||
try {
|
try {
|
||||||
await this.dexie.table('maps').clear()
|
await this.dexie.table('map_objects').clear()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to clear maps storage:', error)
|
console.error('Failed to clear map objects storage:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(id: string, updates: Partial<Map>) {
|
async update(id: string, updates: Partial<MapObject>) {
|
||||||
try {
|
try {
|
||||||
const map = await this.get(id)
|
const mapObject = await this.get(id)
|
||||||
if (!map) return false
|
if (!mapObject) return false
|
||||||
|
|
||||||
const updatedMap = {
|
const updatedMapObject = {
|
||||||
...map,
|
...mapObject,
|
||||||
...updates
|
...updates
|
||||||
}
|
}
|
||||||
await this.add(updatedMap)
|
await this.add(updatedMapObject)
|
||||||
return true
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to update map ${id}:`, error)
|
console.error(`Failed to update map object ${id}:`, error)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,28 @@
|
|||||||
import Dexie from 'dexie'
|
import Dexie from 'dexie'
|
||||||
import { Map } from '@/application/types'
|
|
||||||
|
// import type { Map } from '@/application/types'
|
||||||
|
|
||||||
|
export type Map = {
|
||||||
|
id: string // or string, depending on your ID type
|
||||||
|
name: string
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
tiles: any[] // You might want to be more specific about the tiles type
|
||||||
|
pvp: boolean
|
||||||
|
updatedAt: Date
|
||||||
|
placedMapObjects: {
|
||||||
|
id: string // or string
|
||||||
|
mapObject: string // or string
|
||||||
|
depth: number
|
||||||
|
isRotated: boolean
|
||||||
|
positionX: number
|
||||||
|
positionY: number
|
||||||
|
}[]
|
||||||
|
mapEffects: {
|
||||||
|
effect: string // or specific enum/type if available
|
||||||
|
strength: number
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
export class MapStorage {
|
export class MapStorage {
|
||||||
private dexie: Dexie
|
private dexie: Dexie
|
||||||
@ -11,8 +34,12 @@ export class MapStorage {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(map: Map) {
|
async add(map: Map, overwrite = false) {
|
||||||
try {
|
try {
|
||||||
|
// Check if map already exists, don't add if it does and overwrite is false
|
||||||
|
const existingMap = await this.get(map.id)
|
||||||
|
if (existingMap && !overwrite) return
|
||||||
|
|
||||||
await this.dexie.table('maps').put({
|
await this.dexie.table('maps').put({
|
||||||
...map
|
...map
|
||||||
})
|
})
|
||||||
@ -68,18 +95,17 @@ export class MapStorage {
|
|||||||
async update(id: string, updates: Partial<Map>) {
|
async update(id: string, updates: Partial<Map>) {
|
||||||
try {
|
try {
|
||||||
const map = await this.get(id)
|
const map = await this.get(id)
|
||||||
if (map) {
|
if (!map) return false
|
||||||
const updatedMap = {
|
|
||||||
...map,
|
const updatedMap = {
|
||||||
...updates
|
...map,
|
||||||
}
|
...updates
|
||||||
await this.add(updatedMap)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
await this.add(updatedMap)
|
||||||
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to update map ${id}:`, error)
|
console.error(`Failed to update map ${id}:`, error)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,81 +1,81 @@
|
|||||||
import config from '@/application/config'
|
import config from '@/application/config'
|
||||||
import type { AssetDataT } from '@/application/types'
|
import type { TextureData } from '@/application/types'
|
||||||
import Dexie from 'dexie'
|
import Dexie from 'dexie'
|
||||||
|
|
||||||
export class Assets {
|
export class Textures {
|
||||||
private dexie: Dexie
|
private dexie: Dexie
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.dexie = new Dexie('assets')
|
this.dexie = new Dexie('textures')
|
||||||
this.dexie.version(1).stores({
|
this.dexie.version(1).stores({
|
||||||
assets: 'key, group'
|
textures: 'key, group'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async download(asset: AssetDataT) {
|
async download(texture: TextureData) {
|
||||||
try {
|
try {
|
||||||
// Check if the asset already exists, then check if updatedAt is newer
|
// Check if the texture already exists, then check if updatedAt is newer
|
||||||
const _asset = await this.dexie.table('assets').get(asset.key)
|
const _texture = await this.dexie.table('textures').get(texture.key)
|
||||||
if (_asset && _asset.updatedAt > asset.updatedAt) {
|
if (_texture && _texture.updatedAt > texture.updatedAt) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download the asset
|
// Download the texture
|
||||||
const response = await fetch(config.server_endpoint + asset.data)
|
const response = await fetch(config.server_endpoint + texture.data)
|
||||||
const blob = await response.blob()
|
const blob = await response.blob()
|
||||||
|
|
||||||
// Store the asset in the database
|
// Store the texture in the database
|
||||||
await this.dexie.table('assets').put({
|
await this.dexie.table('textures').put({
|
||||||
key: asset.key,
|
key: texture.key,
|
||||||
data: blob,
|
data: blob,
|
||||||
group: asset.group,
|
group: texture.group,
|
||||||
updatedAt: asset.updatedAt,
|
updatedAt: texture.updatedAt,
|
||||||
originX: asset.originX,
|
originX: texture.originX,
|
||||||
originY: asset.originY,
|
originY: texture.originY,
|
||||||
isAnimated: asset.isAnimated,
|
isAnimated: texture.isAnimated,
|
||||||
frameRate: asset.frameRate,
|
frameRate: texture.frameRate,
|
||||||
frameWidth: asset.frameWidth,
|
frameWidth: texture.frameWidth,
|
||||||
frameHeight: asset.frameHeight,
|
frameHeight: texture.frameHeight,
|
||||||
frameCount: asset.frameCount
|
frameCount: texture.frameCount
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to add asset ${asset.key}:`, error)
|
console.error(`Failed to add texture ${texture.key}:`, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(key: string) {
|
async get(key: string) {
|
||||||
try {
|
try {
|
||||||
const asset = await this.dexie.table('assets').get(key)
|
const texture = await this.dexie.table('textures').get(key)
|
||||||
if (asset) {
|
if (texture) {
|
||||||
return {
|
return {
|
||||||
...asset,
|
...texture,
|
||||||
data: URL.createObjectURL(asset.data) // Convert blob to data URL
|
data: URL.createObjectURL(texture.data) // Convert blob to data URL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to retrieve asset ${key}:`, error)
|
console.error(`Failed to retrieve texture ${key}:`, error)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByGroup(group: string) {
|
async getByGroup(group: string) {
|
||||||
try {
|
try {
|
||||||
const assets = await this.dexie.table('assets').where('group').equals(group).toArray()
|
const textures = await this.dexie.table('textures').where('group').equals(group).toArray()
|
||||||
return assets.map((asset) => ({
|
return textures.map((texture) => ({
|
||||||
...asset,
|
...texture,
|
||||||
data: URL.createObjectURL(asset.data) // Convert blob to data URL
|
data: URL.createObjectURL(texture.data) // Convert blob to data URL
|
||||||
}))
|
}))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to retrieve assets for group ${group}:`, error)
|
console.error(`Failed to retrieve textures for group ${group}:`, error)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(key: string) {
|
async delete(key: string) {
|
||||||
try {
|
try {
|
||||||
await this.dexie.table('assets').delete(key)
|
await this.dexie.table('textures').delete(key)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to delete asset ${key}:`, error)
|
console.error(`Failed to delete texture ${key}:`, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import config from '@/application/config'
|
import config from '@/application/config'
|
||||||
import type { AssetDataT, Character, Notification, User, WorldSettings } from '@/application/types'
|
import type { Character, Notification, TextureData, User, WorldSettings } from '@/application/types'
|
||||||
import { getDomain } from '@/application/utilities'
|
import { getDomain } from '@/application/utilities'
|
||||||
import { useCookies } from '@vueuse/integrations/useCookies'
|
import { useCookies } from '@vueuse/integrations/useCookies'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
@ -22,7 +22,7 @@ export const useGameStore = defineStore('game', {
|
|||||||
game: {
|
game: {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isLoaded: false, // isLoaded is currently being used to determine if the player has interacted with the game
|
isLoaded: false, // isLoaded is currently being used to determine if the player has interacted with the game
|
||||||
loadedAssets: [] as AssetDataT[],
|
loadedAssets: [] as TextureData[],
|
||||||
isPlayerDraggingCamera: false,
|
isPlayerDraggingCamera: false,
|
||||||
isCameraFollowingCharacter: false
|
isCameraFollowingCharacter: false
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url';
|
import { fileURLToPath, URL } from 'node:url';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import vue from '@vitejs/plugin-vue';
|
import vue from '@vitejs/plugin-vue';
|
||||||
import VueDevTools from 'vite-plugin-vue-devtools'
|
|
||||||
import viteCompression from 'vite-plugin-compression'
|
import viteCompression from 'vite-plugin-compression'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue';
|
import vue from '@vitejs/plugin-vue';
|
||||||
import VueDevTools from 'vite-plugin-vue-devtools'
|
|
||||||
import viteCompression from 'vite-plugin-compression';
|
import viteCompression from 'vite-plugin-compression';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user