forked from noxious/client
Fixed characters not showing after logging in, added loading screen before showing characters, worked on GM tools
This commit is contained in:
parent
2f7153fbfe
commit
3e003962dc
1
public/assets/icons/loading-icon1.svg
Normal file
1
public/assets/icons/loading-icon1.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_z9k8{transform-origin:center;animation:spinner_StKS .75s infinite linear}@keyframes spinner_StKS{100%{transform:rotate(360deg)}}</style><path d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z" opacity=".25"/><path d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z" class="spinner_z9k8"/></svg>
|
After Width: | Height: | Size: 537 B |
1
public/assets/icons/loading-icon2.svg
Normal file
1
public/assets/icons/loading-icon2.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_qM83{animation:spinner_8HQG 1.05s infinite}.spinner_oXPr{animation-delay:.1s}.spinner_ZTLf{animation-delay:.2s}@keyframes spinner_8HQG{0%,57.14%{animation-timing-function:cubic-bezier(0.33,.66,.66,1);transform:translate(0)}28.57%{animation-timing-function:cubic-bezier(0.33,0,.66,.33);transform:translateY(-6px)}100%{transform:translate(0)}}</style><circle class="spinner_qM83" cx="4" cy="12" r="3"/><circle class="spinner_qM83 spinner_oXPr" cx="12" cy="12" r="3"/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="3"/></svg>
|
After Width: | Height: | Size: 635 B |
@ -18,13 +18,12 @@ import Game from '@/components/Game.vue'
|
||||
const screen: Ref<string> = ref('login')
|
||||
const socket = useSocketStore()
|
||||
|
||||
socket.$subscribe(
|
||||
(mutation, state) => {
|
||||
socket.$subscribe((mutation, state) => {
|
||||
if (!state.connection) {
|
||||
screen.value = 'login'
|
||||
}
|
||||
|
||||
if (state.connection) {
|
||||
if (state.token && state.connection) {
|
||||
screen.value = 'characters'
|
||||
|
||||
if (state.character) {
|
||||
|
@ -16,12 +16,12 @@ body {
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, button, a {
|
||||
font-family: "Poppins";
|
||||
font-family: "Poppins", serif;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
p, span, li, label {
|
||||
font-family: "Inter";
|
||||
font-family: "Inter", serif;
|
||||
color: $white;
|
||||
}
|
||||
button, a {
|
||||
@ -37,6 +37,10 @@ button, input {
|
||||
button {
|
||||
text-align: center;
|
||||
|
||||
&.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.btn-cyan {
|
||||
background-color: rgba($cyan, 0.5);
|
||||
border: 1px solid $white;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="character-select-screen">
|
||||
<div class="ui-wrapper">
|
||||
<div class="characters-wrapper">
|
||||
<div class="characters-wrapper" v-if="!isLoading">
|
||||
<div v-for="character in characters" :key="character.id" class="character" :class="{ active: selected_character == character.id }">
|
||||
<input type="radio" :id="character.id" name="character" :value="character.id" v-model="selected_character" />
|
||||
<label :for="character.id">{{ character.name }}</label>
|
||||
@ -23,8 +23,13 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="loading-spinner">
|
||||
<img src="/assets/icons/loading-icon1.svg" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-wrapper">
|
||||
<div class="button-wrapper" v-if="!isLoading">
|
||||
<button class="btn-cyan" :disabled="!selected_character" @click="select_character()">
|
||||
PLAY
|
||||
<img draggable="false" src="/assets/icons/arrow.svg">
|
||||
@ -55,18 +60,26 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSocketStore } from '@/stores/socket'
|
||||
import { ref } from 'vue'
|
||||
import { onBeforeMount, onMounted, ref } from 'vue'
|
||||
import Modal from '@/components/utilities/Modal.vue'
|
||||
import {type Character as CharacterT} from '@/types'
|
||||
|
||||
const isLoading = ref(true)
|
||||
const characters = ref([])
|
||||
const socket = useSocketStore()
|
||||
const socket = useSocketStore();
|
||||
|
||||
// Fetch characters
|
||||
socket.getConnection.on('character:list', (data: any) => {
|
||||
characters.value = data
|
||||
})
|
||||
socket.getConnection.emit('character:list')
|
||||
|
||||
onMounted(() => {
|
||||
// wait 1.5 sec
|
||||
setTimeout(() => {
|
||||
socket.getConnection.emit('character:list')
|
||||
isLoading.value = false
|
||||
}, 1000)
|
||||
});
|
||||
|
||||
// Select character logics
|
||||
const selected_character = ref(null)
|
||||
@ -123,6 +136,14 @@ function create() {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.loading-spinner img {
|
||||
width: 5rem;
|
||||
// css color
|
||||
filter: invert(1);
|
||||
// white
|
||||
filter: invert(80%);
|
||||
}
|
||||
|
||||
.characters-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -32,6 +32,7 @@ import { login, register } from '@/services/authentication'
|
||||
import { useNotificationStore } from '@/stores/notifications'
|
||||
import ZoneEditor from '@/components/utilities/zoneEditor/ZoneEditor.vue'
|
||||
import Modal from '@/components/utilities/Modal.vue'
|
||||
import { useSocketStore } from '@/stores/socket'
|
||||
|
||||
const bgm = ref('bgm')
|
||||
if (bgm.value.paused) {
|
||||
@ -39,6 +40,7 @@ if (bgm.value.paused) {
|
||||
window.addEventListener('keydown', () => bgm.value.play())
|
||||
}
|
||||
|
||||
const socket = useSocketStore()
|
||||
const notifications = useNotificationStore()
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
@ -55,7 +57,11 @@ async function loginFunc() {
|
||||
|
||||
if (response.success === undefined) {
|
||||
notifications.addNotification({ message: response.error })
|
||||
return
|
||||
}
|
||||
|
||||
socket.setToken(response.token)
|
||||
socket.initConnection();
|
||||
}
|
||||
|
||||
async function registerFunc() {
|
||||
@ -70,7 +76,11 @@ async function registerFunc() {
|
||||
|
||||
if (response.success === undefined) {
|
||||
notifications.addNotification({ message: response.error })
|
||||
return
|
||||
}
|
||||
|
||||
socket.setToken(response.token)
|
||||
socket.initConnection();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -45,9 +45,7 @@ const properties = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => properties.isModalOpen,
|
||||
(value) => {
|
||||
watch(() => properties.isModalOpen, (value) => {
|
||||
isModalOpenRef.value = value
|
||||
}
|
||||
)
|
||||
@ -124,6 +122,16 @@ const stopDrag = () => {
|
||||
isDragging.value = false
|
||||
}
|
||||
|
||||
watch(() => properties.modalWidth, (value) => {
|
||||
width.value = value
|
||||
}
|
||||
)
|
||||
|
||||
watch(() => properties.modalHeight, (value) => {
|
||||
height.value = value
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
addEventListener('mousemove', drag)
|
||||
addEventListener('mouseup', stopDrag)
|
||||
@ -142,13 +150,11 @@ onUnmounted(() => {
|
||||
|
||||
|
||||
// Make sure modal doesn't go off screen
|
||||
watch(
|
||||
() => x.value, (value) => {
|
||||
watch(() => x.value, (value) => {
|
||||
if (value < 0) { x.value = 0 } else if (value + width.value > window.innerWidth) { x.value = window.innerWidth - width.value }
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => y.value, (value) => {
|
||||
watch(() => y.value, (value) => {
|
||||
if (value < 0) { y.value = 0 } else if (value + height.value > window.innerHeight) { y.value = window.innerHeight - height.value }
|
||||
}
|
||||
)
|
||||
|
@ -1,10 +1,15 @@
|
||||
<template>
|
||||
<Modal :isModalOpen="true">
|
||||
<Modal :isModalOpen="true" :closable="false" :modal-width="200" :modal-height="260">
|
||||
<template #modalHeader>
|
||||
<h3 class="modal-title">GM tools</h3>
|
||||
</template>
|
||||
<template #modalBody>
|
||||
<p></p>
|
||||
<div class="content">
|
||||
<button class="btn-cyan w-full" type="button">Zone manager</button>
|
||||
<button class="btn-cyan w-full" type="button">Player manager</button>
|
||||
<button class="btn-cyan w-full" type="button">Item manager</button>
|
||||
<button class="btn-cyan w-full" type="button">NPC manager</button>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
@ -12,3 +17,11 @@
|
||||
import ZoneEditor from '@/components/utilities/zoneEditor/ZoneEditor.vue'
|
||||
import Modal from '@/components/utilities/Modal.vue'
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
</style>
|
@ -7,8 +7,7 @@ export async function register(username: string, password: string, socketStore =
|
||||
try {
|
||||
const response = await axios.post(`${config.server_endpoint}/register`, { username, password })
|
||||
useCookies().set('token', response.data.token as string)
|
||||
await socketStore.setupSocketConnection()
|
||||
return { success: true }
|
||||
return { success: true, token: response.data.token}
|
||||
} catch (error: any) {
|
||||
return { error: error.response.data.message }
|
||||
}
|
||||
@ -18,8 +17,7 @@ export async function login(username: string, password: string, socketStore = us
|
||||
try {
|
||||
const response = await axios.post(`${config.server_endpoint}/login`, { username, password })
|
||||
useCookies().set('token', response.data.token as string)
|
||||
await socketStore.setupSocketConnection()
|
||||
return { success: true }
|
||||
return { success: true, token: response.data.token}
|
||||
} catch (error: any) {
|
||||
return { error: error.response.data.message }
|
||||
}
|
||||
|
@ -6,17 +6,19 @@ import type { Character, User } from '@/types'
|
||||
|
||||
export const useSocketStore: StoreDefinition = defineStore('socket', {
|
||||
state: () => ({
|
||||
token: '' as string | null,
|
||||
connection: null as Socket | null,
|
||||
user: null as User | null,
|
||||
character: null as Character | null
|
||||
}),
|
||||
getters: {
|
||||
getToken: (state: any) => state.token as string,
|
||||
getConnection: (state: any) => state.connection as Socket,
|
||||
getUser: (state: any) => state.user as User,
|
||||
getCharacter: (state: any) => state.character as Character
|
||||
},
|
||||
actions: {
|
||||
setupSocketConnection() {
|
||||
initConnection() {
|
||||
this.connection = io(config.server_endpoint, {
|
||||
withCredentials: true,
|
||||
transports: ['websocket'],
|
||||
@ -27,7 +29,7 @@ export const useSocketStore: StoreDefinition = defineStore('socket', {
|
||||
this.connection.emit('login')
|
||||
|
||||
// set user
|
||||
this.connection.on('login', (user: User) => {
|
||||
this.connection.on('logged_in', (user: User) => {
|
||||
this.setUser(user)
|
||||
})
|
||||
|
||||
@ -43,11 +45,15 @@ export const useSocketStore: StoreDefinition = defineStore('socket', {
|
||||
this.connection.disconnect()
|
||||
this.connection = null
|
||||
|
||||
this.token = null
|
||||
this.user = null
|
||||
this.character = null
|
||||
|
||||
useCookies().remove('token')
|
||||
},
|
||||
setToken(token: string) {
|
||||
this.token = token
|
||||
},
|
||||
setUser(user: User | null) {
|
||||
this.user = user
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user