<template> <div class="flex justify-center items-center h-dvh relative"> <Game :config="gameConfig" @create="createGame"> <Scene name="main" @preload="preloadScene"> <div v-if="!isLoaded" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-white text-3xl font-ui">Loading...</div> <div v-else> <Map :key="mapEditorStore.mapId" /> <Toolbar @save="save" @clear="clear" /> <MapList /> <TileList /> <ObjectList /> <MapSettings /> <TeleportModal /> </div> </Scene> </Game> </div> </template> <script setup lang="ts"> import config from '@/application/config' import 'phaser' import type { Map as MapT } from '@/application/types' import Map from '@/components/gameMaster/mapEditor/Map.vue' import MapList from '@/components/gameMaster/mapEditor/partials/MapList.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 TileList from '@/components/gameMaster/mapEditor/partials/TileList.vue' import Toolbar from '@/components/gameMaster/mapEditor/partials/Toolbar.vue' import { loadAllTilesIntoScene } from '@/composables/mapComposable' import { useGameStore } from '@/stores/gameStore' import { useMapEditorStore } from '@/stores/mapEditorStore' import { Game, Scene } from 'phavuer' import { ref } from 'vue' const gameStore = useGameStore() const mapEditorStore = useMapEditorStore() const isLoaded = ref(false) const currentMap = ref<MapT | null>(null) const gameConfig = { name: config.name, width: window.innerWidth, height: window.innerHeight, type: Phaser.AUTO, // AUTO, CANVAS, WEBGL, HEADLESS resolution: 5 } const createGame = (game: Phaser.Game) => { // Resize the game when the window is resized addEventListener('resize', () => { game.scale.resize(window.innerWidth, window.innerHeight) }) } const preloadScene = async (scene: Phaser.Scene) => { // Load the base assets into the Phaser scene scene.load.image('BLOCK', '/assets/map/bt_tile.png') scene.load.image('TELEPORT', '/assets/map/tp_tile.png') scene.load.image('blank_tile', '/assets/map/blank_tile.png') scene.load.image('waypoint', '/assets/waypoint.png') // Get all tiles from IndexedDB and load them into the scene await loadAllTilesIntoScene(scene) // Wait for all assets to be loaded before continuing await new Promise<void>((resolve) => { scene.load.on(Phaser.Loader.Events.COMPLETE, () => { resolve() }) isLoaded.value = true }) } function save() { if (!mapEditorStore.map) return const data = { mapId: mapEditorStore.map.id, name: mapEditorStore.mapSettings.name, width: mapEditorStore.mapSettings.width, height: mapEditorStore.mapSettings.height, tiles: mapEditorStore.map.tiles, pvp: mapEditorStore.map.pvp, mapEffects: mapEditorStore.map.mapEffects?.map(({ id, effect, strength }) => ({ id, effect, strength })) ?? [], mapEventTiles: mapEditorStore.map.mapEventTiles?.map(({ id, type, positionX, positionY, teleport }) => ({ id, type, positionX, positionY, teleport })) ?? [], placedMapObjects: mapEditorStore.map.placedMapObjects?.map(({ id, mapObject, depth, isRotated, positionX, positionY }) => ({ id, mapObject, depth, isRotated, positionX, positionY })) ?? [] } if (mapEditorStore.isSettingsModalShown) { mapEditorStore.toggleSettingsModal() } gameStore.connection?.emit('gm:map:update', data, (response: MapT) => { mapEditorStore.setMap(response) }) } function clear() { if (!mapEditorStore.map) return // Clear objects, event tiles and tiles mapEditorStore.map.placedMapObjects = [] mapEditorStore.map.mapEventTiles = [] mapEditorStore.triggerClearTiles() } </script>