1
0
forked from noxious/client

npm run format

This commit is contained in:
Dennis Postma 2024-11-04 01:06:15 +01:00
parent f076661d4a
commit 89938b7f93
9 changed files with 408 additions and 408 deletions

View File

@ -1,156 +1,156 @@
<template> <template>
<div class="bg-gray-900 relative"> <div class="bg-gray-900 relative">
<div class="absolute bg-[url('/assets/shapes/select-screen-bg-shape.svg')] bg-no-repeat bg-center w-full h-full"></div> <div class="absolute bg-[url('/assets/shapes/select-screen-bg-shape.svg')] bg-no-repeat bg-center w-full h-full"></div>
<div class="ui-wrapper h-dvh flex flex-col justify-center items-center gap-20 px-10 sm:px-20"> <div class="ui-wrapper h-dvh flex flex-col justify-center items-center gap-20 px-10 sm:px-20">
<div class="filler"></div> <div class="filler"></div>
<div class="flex gap-14 w-full max-h-[650px] overflow-x-auto" v-if="!isLoading"> <div class="flex gap-14 w-full max-h-[650px] overflow-x-auto" v-if="!isLoading">
<!-- CHARACTER LIST --> <!-- CHARACTER LIST -->
<div v-for="character in characters" :key="character.id" class="group first:ml-auto last:mr-auto m-4 w-[170px] h-[275px] flex flex-col shrink-0 relative shadow-character" :class="{ active: selected_character == character.id }"> <div v-for="character in characters" :key="character.id" class="group first:ml-auto last:mr-auto m-4 w-[170px] h-[275px] flex flex-col shrink-0 relative shadow-character" :class="{ active: selected_character == character.id }">
<img src="/assets/ui-elements/ui-box-outer.svg" class="absolute w-full h-full" alt="UI box outer" /> <img src="/assets/ui-elements/ui-box-outer.svg" class="absolute w-full h-full" alt="UI box outer" />
<img src="/assets/ui-elements/ui-box-inner.svg" class="absolute left-2 bottom-2 w-[calc(100%_-_16px)] h-[calc(100%_-_40px)]" alt="UI box inner" /> <img src="/assets/ui-elements/ui-box-inner.svg" class="absolute left-2 bottom-2 w-[calc(100%_-_16px)] h-[calc(100%_-_40px)]" alt="UI box inner" />
<input class="opacity-0 h-full w-full absolute m-0 z-10" type="radio" :id="character.id" name="character" :value="character.id" v-model="selected_character" /> <input class="opacity-0 h-full w-full absolute m-0 z-10" type="radio" :id="character.id" name="character" :value="character.id" v-model="selected_character" />
<label class="font-bold absolute left-1/2 top-4 max-w-32 -translate-x-1/2 -translate-y-1/2 text-center text-ellipsis overflow-hidden whitespace-nowrap drop-shadow-text" :for="character.id">{{ character.name }}</label> <label class="font-bold absolute left-1/2 top-4 max-w-32 -translate-x-1/2 -translate-y-1/2 text-center text-ellipsis overflow-hidden whitespace-nowrap drop-shadow-text" :for="character.id">{{ character.name }}</label>
<button <button
class="delete bg-red w-8 h-8 p-[3px] rounded-full absolute -right-4 top-0 -translate-y-1/2 z-10 border-2 border-solid border-white hover:bg-red-300" class="delete bg-red w-8 h-8 p-[3px] rounded-full absolute -right-4 top-0 -translate-y-1/2 z-10 border-2 border-solid border-white hover:bg-red-300"
@click=" @click="
() => { () => {
deletingCharacter = character deletingCharacter = character
} }
" "
> >
<img draggable="false" src="/assets/icons/trashcan.svg" /> <img draggable="false" src="/assets/icons/trashcan.svg" />
</button> </button>
<div class="sprite-container flex flex-col items-center m-auto"> <div class="sprite-container flex flex-col items-center m-auto">
<img class="drop-shadow-20" draggable="false" src="/assets/avatar/default/0.png" /> <img class="drop-shadow-20" draggable="false" src="/assets/avatar/default/0.png" />
</div> </div>
<span class="absolute bottom-6 w-full text-center translate-y-1/2 z-10">Lvl. {{ character.level }}</span> <span class="absolute bottom-6 w-full text-center translate-y-1/2 z-10">Lvl. {{ character.level }}</span>
<div class="selected-character group-[.active]:max-w-[170px] absolute max-w-0 w-4/6 h-[3px] bg-gray-500 rounded-[3px] left-1/2 -bottom-4 -translate-x-1/2 transition-all ease-in-out duration-300"></div> <div class="selected-character group-[.active]:max-w-[170px] absolute max-w-0 w-4/6 h-[3px] bg-gray-500 rounded-[3px] left-1/2 -bottom-4 -translate-x-1/2 transition-all ease-in-out duration-300"></div>
</div> </div>
<div class="character new-character first:ml-auto mr-auto m-4 w-[170px] h-[275px] flex flex-col shrink-0 rounded-2xl relative bg-gray-500/50 bg-no-repeat shadow-character" v-if="characters.length < 4"> <div class="character new-character first:ml-auto mr-auto m-4 w-[170px] h-[275px] flex flex-col shrink-0 rounded-2xl relative bg-gray-500/50 bg-no-repeat shadow-character" v-if="characters.length < 4">
<button class="h-full w-full py-10 flex flex-col justify-between" @click="isModalOpen = true"> <button class="h-full w-full py-10 flex flex-col justify-between" @click="isModalOpen = true">
<div class="filler"></div> <div class="filler"></div>
<img class="w-24 h-24 m-auto" draggable="false" src="/assets/icons/plus-icon.svg" /> <img class="w-24 h-24 m-auto" draggable="false" src="/assets/icons/plus-icon.svg" />
<span class="self-center text-base absolute bottom-5 w-full text-center translate-y-1/2 z-10">Create new</span> <span class="self-center text-base absolute bottom-5 w-full text-center translate-y-1/2 z-10">Create new</span>
</button> </button>
</div> </div>
</div> </div>
<div v-else> <div v-else>
<img class="w-20 invert-80" src="/assets/icons/loading-icon1.svg" /> <img class="w-20 invert-80" src="/assets/icons/loading-icon1.svg" />
</div> </div>
<div class="button-wrapper flex gap-8" v-if="!isLoading"> <div class="button-wrapper flex gap-8" v-if="!isLoading">
<button <button
class="btn-red py-2 pr-2.5 pl-8 min-w-24 relative rounded text-xl flex gap-4 items-center transition-all ease-in-out duration-200 hover:gap-5 disabled:bg-red/50 disabled:hover:bg-opacity-50 disabled:cursor-not-allowed disabled:hover:gap-[15px]" class="btn-red py-2 pr-2.5 pl-8 min-w-24 relative rounded text-xl flex gap-4 items-center transition-all ease-in-out duration-200 hover:gap-5 disabled:bg-red/50 disabled:hover:bg-opacity-50 disabled:cursor-not-allowed disabled:hover:gap-[15px]"
@click.stop="gameStore.disconnectSocket()" @click.stop="gameStore.disconnectSocket()"
> >
<img class="h-8 drop-shadow-20 rotate-180" draggable="false" src="/assets/icons/arrow.svg" alt="Logout icon" /> <img class="h-8 drop-shadow-20 rotate-180" draggable="false" src="/assets/icons/arrow.svg" alt="Logout icon" />
</button> </button>
<button <button
class="btn-cyan py-2 px-2.5 pl-8 min-w-24 relative rounded text-xl flex gap-4 items-center transition-all ease-in-out duration-200 hover:gap-5 disabled:bg-cyan-800 disabled:hover:bg-opacity-50 disabled:cursor-not-allowed disabled:hover:gap-[15px]" class="btn-cyan py-2 px-2.5 pl-8 min-w-24 relative rounded text-xl flex gap-4 items-center transition-all ease-in-out duration-200 hover:gap-5 disabled:bg-cyan-800 disabled:hover:bg-opacity-50 disabled:cursor-not-allowed disabled:hover:gap-[15px]"
:disabled="!selected_character" :disabled="!selected_character"
@click="select_character()" @click="select_character()"
> >
PLAY PLAY
<img class="h-8 drop-shadow-20" draggable="false" src="/assets/icons/arrow.svg" alt="Play icon" /> <img class="h-8 drop-shadow-20" draggable="false" src="/assets/icons/arrow.svg" alt="Play icon" />
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<!-- CREATE CHARACTER MODAL --> <!-- CREATE CHARACTER MODAL -->
<Modal :isModalOpen="isModalOpen" @modal:close="isModalOpen = false" :modal-width="430" :modal-height="275"> <Modal :isModalOpen="isModalOpen" @modal:close="isModalOpen = false" :modal-width="430" :modal-height="275">
<template #modalHeader> <template #modalHeader>
<h3 class="m-0 font-medium text-white">Create your character</h3> <h3 class="m-0 font-medium text-white">Create your character</h3>
</template> </template>
<template #modalBody> <template #modalBody>
<div class="p-4 h-[calc(100%_-_32px)]"> <div class="p-4 h-[calc(100%_-_32px)]">
<form method="post" @submit.prevent="create" class="h-full flex flex-col justify-between"> <form method="post" @submit.prevent="create" class="h-full flex flex-col justify-between">
<div class="form-field-full"> <div class="form-field-full">
<label for="name" class="text-white">Nickname</label> <label for="name" class="text-white">Nickname</label>
<input class="input-field" v-model="name" name="name" id="name" placeholder="Enter a nickname.." /> <input class="input-field" v-model="name" name="name" id="name" placeholder="Enter a nickname.." />
</div> </div>
<div class="grid grid-flow-col justify-stretch gap-4"> <div class="grid grid-flow-col justify-stretch gap-4">
<button type="button" class="btn-empty py-1.5 px-4 inline-block" @click.prevent="isModalOpen = false">Cancel</button> <button type="button" class="btn-empty py-1.5 px-4 inline-block" @click.prevent="isModalOpen = false">Cancel</button>
<button class="btn-cyan py-1.5 px-4 inline-block" type="submit">Create</button> <button class="btn-cyan py-1.5 px-4 inline-block" type="submit">Create</button>
</div> </div>
</form> </form>
</div> </div>
</template> </template>
</Modal> </Modal>
<!-- DELETE CHARACTER MODAL --> <!-- DELETE CHARACTER MODAL -->
<ConfirmationModal v-if="deletingCharacter != null" :confirm-function="delete_character.bind(this, deletingCharacter.id)" :cancel-function="(() => (deletingCharacter = null)).bind(this)" confirm-button-text="Delete"> <ConfirmationModal v-if="deletingCharacter != null" :confirm-function="delete_character.bind(this, deletingCharacter.id)" :cancel-function="(() => (deletingCharacter = null)).bind(this)" confirm-button-text="Delete">
<template #modalHeader> <template #modalHeader>
<h3 class="m-0 font-medium text-white">Delete character?</h3> <h3 class="m-0 font-medium text-white">Delete character?</h3>
</template> </template>
<template #modalBody> <template #modalBody>
<p class="mt-0 mb-5 text-white text-lg"> <p class="mt-0 mb-5 text-white text-lg">
Do you want to permanently delete <span class="font-extrabold text-white">{{ deletingCharacter.name }}</span Do you want to permanently delete <span class="font-extrabold text-white">{{ deletingCharacter.name }}</span
>? >?
</p> </p>
</template> </template>
</ConfirmationModal> </ConfirmationModal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import { onBeforeUnmount, onMounted, ref } from 'vue' import { onBeforeUnmount, onMounted, ref } from 'vue'
import Modal from '@/components/utilities/Modal.vue' import Modal from '@/components/utilities/Modal.vue'
import { type Character as CharacterT } from '@/types' import { type Character as CharacterT } from '@/types'
import ConfirmationModal from '@/components/utilities/ConfirmationModal.vue' import ConfirmationModal from '@/components/utilities/ConfirmationModal.vue'
const gameStore = useGameStore() const gameStore = useGameStore()
const isLoading = ref(true) const isLoading = ref(true)
const characters = ref([] as CharacterT[]) const characters = ref([] as CharacterT[])
const deletingCharacter = ref(null as CharacterT | null) const deletingCharacter = ref(null as CharacterT | null)
// Fetch characters // Fetch characters
gameStore.connection?.on('character:list', (data: any) => { gameStore.connection?.on('character:list', (data: any) => {
characters.value = data characters.value = data
}) })
onMounted(async () => { onMounted(async () => {
// wait 0.75 sec // wait 0.75 sec
setTimeout(() => { setTimeout(() => {
gameStore.connection?.emit('character:list') gameStore.connection?.emit('character:list')
isLoading.value = false isLoading.value = false
}, 750) }, 750)
}) })
// Select character logics // Select character logics
const selected_character = ref(null) const selected_character = ref(null)
function select_character() { function select_character() {
if (!selected_character.value) return if (!selected_character.value) return
deletingCharacter.value = null deletingCharacter.value = null
gameStore.connection?.emit('character:connect', { character_id: selected_character.value }) gameStore.connection?.emit('character:connect', { character_id: selected_character.value })
gameStore.connection?.on('character:connect', (data: CharacterT) => gameStore.setCharacter(data)) gameStore.connection?.on('character:connect', (data: CharacterT) => gameStore.setCharacter(data))
} }
// Delete character logics // Delete character logics
function delete_character(character_id: number) { function delete_character(character_id: number) {
if (!character_id) return if (!character_id) return
deletingCharacter.value = null deletingCharacter.value = null
gameStore.connection?.emit('character:delete', { character_id: character_id }) gameStore.connection?.emit('character:delete', { character_id: character_id })
} }
// Create character logics // Create character logics
const isModalOpen = ref(false) const isModalOpen = ref(false)
const name = ref('') const name = ref('')
function create() { function create() {
gameStore.connection?.on('character:create:success', (data: CharacterT) => { gameStore.connection?.on('character:create:success', (data: CharacterT) => {
gameStore.setCharacter(data) gameStore.setCharacter(data)
isModalOpen.value = false isModalOpen.value = false
}) })
gameStore.connection?.emit('character:create', { name: name.value }) gameStore.connection?.emit('character:create', { name: name.value })
} }
onBeforeUnmount(() => { onBeforeUnmount(() => {
gameStore.connection?.off('character:list') gameStore.connection?.off('character:list')
gameStore.connection?.off('character:connect') gameStore.connection?.off('character:connect')
gameStore.connection?.off('character:create:success') gameStore.connection?.off('character:create:success')
}) })
</script> </script>

View File

@ -1,82 +1,82 @@
<template> <template>
<div class="flex justify-center items-center h-dvh relative"> <div class="flex justify-center items-center h-dvh relative">
<Game :config="gameConfig" @create="createGame"> <Game :config="gameConfig" @create="createGame">
<Scene name="main" @preload="preloadScene" @create="createScene"> <Scene name="main" @preload="preloadScene" @create="createScene">
<Menu /> <Menu />
<Hud /> <Hud />
<Hotkeys /> <Hotkeys />
<Minimap /> <Minimap />
<Zone /> <Zone />
<Chat /> <Chat />
<ExpBar /> <ExpBar />
<CharacterProfile /> <CharacterProfile />
<Effects /> <Effects />
</Scene> </Scene>
</Game> </Game>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import config from '@/config' import config from '@/config'
import 'phaser' import 'phaser'
import { Game, Scene } from 'phavuer' import { Game, Scene } from 'phavuer'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import Menu from '@/components/gui/Menu.vue' import Menu from '@/components/gui/Menu.vue'
import ExpBar from '@/components/gui/ExpBar.vue' import ExpBar from '@/components/gui/ExpBar.vue'
import Hud from '@/components/gui/Hud.vue' import Hud from '@/components/gui/Hud.vue'
import Zone from '@/components/zone/Zone.vue' import Zone from '@/components/zone/Zone.vue'
import Hotkeys from '@/components/gui/Hotkeys.vue' import Hotkeys from '@/components/gui/Hotkeys.vue'
import Chat from '@/components/gui/Chat.vue' import Chat from '@/components/gui/Chat.vue'
import CharacterProfile from '@/components/gui/CharacterProfile.vue' import CharacterProfile from '@/components/gui/CharacterProfile.vue'
import Effects from '@/components/Effects.vue' import Effects from '@/components/Effects.vue'
import Minimap from '@/components/gui/Minimap.vue' import Minimap from '@/components/gui/Minimap.vue'
import AwaitLoaderPlugin from 'phaser3-rex-plugins/plugins/awaitloader-plugin' import AwaitLoaderPlugin from 'phaser3-rex-plugins/plugins/awaitloader-plugin'
const gameStore = useGameStore() const gameStore = useGameStore()
const gameConfig = { const gameConfig = {
name: config.name, name: config.name,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
type: Phaser.AUTO, // AUTO, CANVAS, WEBGL, HEADLESS type: Phaser.AUTO, // AUTO, CANVAS, WEBGL, HEADLESS
resolution: 5, resolution: 5,
plugins: { plugins: {
global: [ global: [
{ {
key: 'rexAwaitLoader', key: 'rexAwaitLoader',
plugin: AwaitLoaderPlugin, plugin: AwaitLoaderPlugin,
start: true start: true
} }
] ]
} }
} }
const createGame = (game: Phaser.Game) => { const createGame = (game: Phaser.Game) => {
/** /**
* Resize the game when the window is resized * Resize the game when the window is resized
*/ */
addEventListener('resize', () => { addEventListener('resize', () => {
game.scale.resize(window.innerWidth, window.innerHeight) game.scale.resize(window.innerWidth, window.innerHeight)
}) })
// We don't support canvas mode, only WebGL // We don't support canvas mode, only WebGL
if (game.renderer.type === Phaser.CANVAS) { if (game.renderer.type === Phaser.CANVAS) {
gameStore.addNotification({ gameStore.addNotification({
title: 'Warning', title: 'Warning',
message: 'Your browser does not support WebGL. Please use a modern browser like Chrome, Firefox, or Edge.' message: 'Your browser does not support WebGL. Please use a modern browser like Chrome, Firefox, or Edge.'
}) })
gameStore.disconnectSocket() gameStore.disconnectSocket()
} }
} }
function preloadScene(scene: Phaser.Scene) { function preloadScene(scene: Phaser.Scene) {
/** /**
* Load the base assets into the Phaser scene * Load the base assets into the Phaser scene
*/ */
scene.load.image('blank_tile', '/assets/zone/blank_tile.png') scene.load.image('blank_tile', '/assets/zone/blank_tile.png')
scene.load.image('waypoint', '/assets/waypoint.png') scene.load.image('waypoint', '/assets/waypoint.png')
} }
function createScene(scene: Phaser.Scene) {} function createScene(scene: Phaser.Scene) {}
</script> </script>

View File

@ -1,25 +1,25 @@
<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">
<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"> <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">
<span class="text-white text-lg flex-1 text-center">Play</span> <span class="text-white text-lg flex-1 text-center">Play</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg> </svg>
</button> </button>
</div> </div>
</template> </template>
<script setup lang="ts" async> <script setup lang="ts" async>
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
const gameStore = useGameStore() const gameStore = useGameStore()
function continueBtnClick() { function continueBtnClick() {
// Play music // Play music
const audio = new Audio('/assets/music/login.mp3') const audio = new Audio('/assets/music/login.mp3')
audio.play() audio.play()
// Set isLoaded to true // Set isLoaded to true
gameStore.game.isLoaded = true gameStore.game.isLoaded = true
} }
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<!-- @TODO this must be shown over the login screen --> <!-- @TODO this must be shown over the login screen -->
<div class="relative max-lg:h-dvh flex flex-row-reverse"> <div class="relative max-lg:h-dvh flex flex-row-reverse">
<ResetPassword :isModalOpen="isPasswordResetFormShown" @close="() => isPasswordResetFormShown = false" /> <ResetPassword :isModalOpen="isPasswordResetFormShown" @close="() => (isPasswordResetFormShown = false)" />
<div class="lg:bg-gradient-to-l bg-gradient-to-b from-gray-900 to-transparent w-full lg:w-1/2 h-[35dvh] lg:h-dvh absolute left-0 max-lg:bottom-0 lg:top-0 z-10"></div> <div class="lg:bg-gradient-to-l bg-gradient-to-b from-gray-900 to-transparent w-full lg:w-1/2 h-[35dvh] lg:h-dvh absolute left-0 max-lg:bottom-0 lg:top-0 z-10"></div>
<div class="bg-[url('/assets/login/login-bg.png')] w-full lg:w-1/2 h-[35dvh] lg:h-dvh absolute left-0 max-lg:bottom-0 lg:top-0 bg-no-repeat bg-cover bg-center"></div> <div class="bg-[url('/assets/login/login-bg.png')] w-full lg:w-1/2 h-[35dvh] lg:h-dvh absolute left-0 max-lg:bottom-0 lg:top-0 bg-no-repeat bg-cover bg-center"></div>
<div class="bg-gray-900 z-20 w-full lg:w-1/2 h-[65dvh] lg:h-dvh relative"> <div class="bg-gray-900 z-20 w-full lg:w-1/2 h-[65dvh] lg:h-dvh relative">
@ -12,7 +12,7 @@
<img src="/assets/ui-elements/ui-box-inner.svg" class="absolute left-2 top-2 w-[calc(100%_-_16px)] h-[calc(100%_-_16px)] max-lg:hidden" alt="UI box inner" /> <img src="/assets/ui-elements/ui-box-inner.svg" class="absolute left-2 top-2 w-[calc(100%_-_16px)] h-[calc(100%_-_16px)] max-lg:hidden" alt="UI box inner" />
<!-- Login Form --> <!-- Login Form -->
<LoginForm v-if="currentForm === 'login' && !doesUrlHaveToken" @openResetPasswordModal="() => isPasswordResetFormShown = true" @switchToRegister="currentForm = 'register'" /> <LoginForm v-if="currentForm === 'login' && !doesUrlHaveToken" @openResetPasswordModal="() => (isPasswordResetFormShown = true)" @switchToRegister="currentForm = 'register'" />
<!-- Register Form --> <!-- Register Form -->
<RegisterForm v-if="currentForm === 'register' && !doesUrlHaveToken" @switchToLogin="currentForm = 'login'" /> <RegisterForm v-if="currentForm === 'register' && !doesUrlHaveToken" @switchToLogin="currentForm = 'login'" />

View File

@ -1,85 +1,85 @@
<template> <template>
<div class="flex justify-center items-center h-dvh relative"> <div class="flex justify-center items-center h-dvh relative">
<Game :config="gameConfig" @create="createGame"> <Game :config="gameConfig" @create="createGame">
<Scene name="main" @preload="preloadScene" @create="createScene"> <Scene name="main" @preload="preloadScene" @create="createScene">
<ZoneEditor :key="JSON.stringify(`${zoneEditorStore.zone?.id}_${zoneEditorStore.zone?.createdAt}_${zoneEditorStore.zone?.updatedAt}`)" /> <ZoneEditor :key="JSON.stringify(`${zoneEditorStore.zone?.id}_${zoneEditorStore.zone?.createdAt}_${zoneEditorStore.zone?.updatedAt}`)" />
</Scene> </Scene>
</Game> </Game>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import config from '@/config' import config from '@/config'
import 'phaser' import 'phaser'
import { Game, Scene } from 'phavuer' import { Game, Scene } from 'phavuer'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import { useZoneEditorStore } from '@/stores/zoneEditorStore' import { useZoneEditorStore } from '@/stores/zoneEditorStore'
import ZoneEditor from '@/components/gameMaster/zoneEditor/ZoneEditor.vue' import ZoneEditor from '@/components/gameMaster/zoneEditor/ZoneEditor.vue'
import AwaitLoaderPlugin from 'phaser3-rex-plugins/plugins/awaitloader-plugin' import AwaitLoaderPlugin from 'phaser3-rex-plugins/plugins/awaitloader-plugin'
import { loadTexture } from '@/composables/gameComposable' import { loadTexture } from '@/composables/gameComposable'
import type { AssetDataT } from '@/types' import type { AssetDataT } from '@/types'
const gameStore = useGameStore() const gameStore = useGameStore()
const zoneEditorStore = useZoneEditorStore() const zoneEditorStore = useZoneEditorStore()
const gameConfig = { const gameConfig = {
name: config.name, name: config.name,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
type: Phaser.AUTO, // AUTO, CANVAS, WEBGL, HEADLESS type: Phaser.AUTO, // AUTO, CANVAS, WEBGL, HEADLESS
resolution: 5, resolution: 5,
plugins: { plugins: {
global: [ global: [
{ {
key: 'rexAwaitLoader', key: 'rexAwaitLoader',
plugin: AwaitLoaderPlugin, plugin: AwaitLoaderPlugin,
start: true start: true
} }
] ]
} }
} }
const createGame = (game: Phaser.Game) => { const createGame = (game: Phaser.Game) => {
/** /**
* Resize the game when the window is resized * Resize the game when the window is resized
*/ */
addEventListener('resize', () => { addEventListener('resize', () => {
game.scale.resize(window.innerWidth, window.innerHeight) game.scale.resize(window.innerWidth, window.innerHeight)
}) })
// We don't support canvas mode, only WebGL // We don't support canvas mode, only WebGL
if (game.renderer.type === Phaser.CANVAS) { if (game.renderer.type === Phaser.CANVAS) {
gameStore.addNotification({ gameStore.addNotification({
title: 'Warning', title: 'Warning',
message: 'Your browser does not support WebGL. Please use a modern browser like Chrome, Firefox, or Edge.' message: 'Your browser does not support WebGL. Please use a modern browser like Chrome, Firefox, or Edge.'
}) })
gameStore.disconnectSocket() gameStore.disconnectSocket()
} }
} }
const preloadScene = async (scene: Phaser.Scene) => { const preloadScene = async (scene: Phaser.Scene) => {
/** /**
* Load the base assets into the Phaser scene * Load the base assets into the Phaser scene
*/ */
scene.load.image('BLOCK', '/assets/zone/bt_tile.png') scene.load.image('BLOCK', '/assets/zone/bt_tile.png')
scene.load.image('TELEPORT', '/assets/zone/tp_tile.png') scene.load.image('TELEPORT', '/assets/zone/tp_tile.png')
scene.load.image('blank_tile', '/assets/zone/blank_tile.png') scene.load.image('blank_tile', '/assets/zone/blank_tile.png')
scene.load.image('waypoint', '/assets/waypoint.png') scene.load.image('waypoint', '/assets/waypoint.png')
/** /**
* Because Phaser can't load tiles after the scene with map in it is created, * 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. * we need to load and cache all the tiles first.
* 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: AssetDataT[] = await fetch(config.server_endpoint + '/assets/list_tiles').then((response) => response.json()) const tiles: AssetDataT[] = await fetch(config.server_endpoint + '/assets/list_tiles').then((response) => response.json())
for await (const tile of tiles) { for await (const tile of tiles) {
await loadTexture(scene, tile) await loadTexture(scene, tile)
} }
successCallback() successCallback()
}) })
} }
const createScene = async (scene: Phaser.Scene) => {} const createScene = async (scene: Phaser.Scene) => {}
</script> </script>

View File

@ -66,4 +66,4 @@ async function loginFunc() {
gameStore.initConnection() gameStore.initConnection()
return true // Indicate success return true // Indicate success
} }
</script> </script>

View File

@ -65,4 +65,4 @@ async function newPasswordFunc() {
function cancelNewPassword() { function cancelNewPassword() {
window.location.href = '/' window.location.href = '/'
} }
</script> </script>

View File

@ -94,4 +94,4 @@ async function registerFunc() {
return return
} }
} }
</script> </script>

View File

@ -1,55 +1,55 @@
<template> <template>
<Modal @modal:close="() => emit('close')" :modal-width="400" :modal-height="300" :is-resizable="false"> <Modal @modal:close="() => emit('close')" :modal-width="400" :modal-height="300" :is-resizable="false">
<template #modalHeader> <template #modalHeader>
<h3 class="m-0 font-medium shrink-0 text-white">Reset Password</h3> <h3 class="m-0 font-medium shrink-0 text-white">Reset Password</h3>
</template> </template>
<template #modalBody> <template #modalBody>
<div class="h-[calc(100%_-_32px)] p-4"> <div class="h-[calc(100%_-_32px)] p-4">
<form class="h-full flex flex-col justify-between" @submit.prevent="resetPasswordFunc"> <form class="h-full flex flex-col justify-between" @submit.prevent="resetPasswordFunc">
<div class="flex flex-col relative"> <div class="flex flex-col relative">
<p>Fill in your email to receive a password reset request.</p> <p>Fill in your email to receive a password reset request.</p>
<input type="email" name="email" class="input-field" v-model="email" placeholder="E-mail" /> <input type="email" name="email" class="input-field" v-model="email" placeholder="E-mail" />
<span v-if="resetPasswordError" class="text-red-200 text-xs absolute top-full mt-1">{{ resetPasswordError }}</span> <span v-if="resetPasswordError" class="text-red-200 text-xs absolute top-full mt-1">{{ resetPasswordError }}</span>
</div> </div>
<div class="grid grid-flow-col justify-stretch gap-4"> <div class="grid grid-flow-col justify-stretch gap-4">
<button class="btn-empty py-1.5 px-4 min-w-24 inline-block" @click.stop="() => emit('close')">Cancel</button> <button class="btn-empty py-1.5 px-4 min-w-24 inline-block" @click.stop="() => emit('close')">Cancel</button>
<button class="btn-cyan py-1.5 px-4 min-w-24 inline-block" type="submit">Send mail</button> <button class="btn-cyan py-1.5 px-4 min-w-24 inline-block" type="submit">Send mail</button>
</div> </div>
</form> </form>
</div> </div>
</template> </template>
</Modal> </Modal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import { resetPassword } from '@/services/authentication' import { resetPassword } from '@/services/authentication'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import Modal from '@/components/utilities/Modal.vue' import Modal from '@/components/utilities/Modal.vue'
const emit = defineEmits(['close']) const emit = defineEmits(['close'])
const gameStore = useGameStore() const gameStore = useGameStore()
const email = ref('') const email = ref('')
const resetPasswordError = ref('') const resetPasswordError = ref('')
const isPasswordResetOpen = ref(false) const isPasswordResetOpen = ref(false)
async function resetPasswordFunc() { async function resetPasswordFunc() {
// check if email is valid // check if email is valid
if (email.value === '') { if (email.value === '') {
resetPasswordError.value = 'Please enter an email' resetPasswordError.value = 'Please enter an email'
return return
} }
// send reset password event to server // send reset password event to server
const response = await resetPassword(email.value) const response = await resetPassword(email.value)
if (response.success === undefined) { if (response.success === undefined) {
resetPasswordError.value = response.error resetPasswordError.value = response.error
return return
} }
emit('close') emit('close')
} }
</script> </script>