1
0
forked from noxious/client

Worked on commands, notifications

This commit is contained in:
Dennis Postma 2024-06-01 19:36:27 +02:00
parent b58df15ae0
commit ef12c61ea9
16 changed files with 136 additions and 76 deletions

44
env.d.ts vendored
View File

@ -1,45 +1 @@
/// <reference types="vite/client" />
export type User = {
id: number;
username: string;
password: string;
characters: Character[];
};
export type Character = {
id: number;
userId: number;
user: User;
name: string;
hitpoints: number;
mana: number;
level: number;
experience: number;
role: string;
position_x: number;
position_y: number;
rotation: number;
zoneId: number;
zone: Zone;
chats: Chat[];
};
export type Zone = {
id: number;
name: string;
width: number;
height: number;
tiles: Record<string, any>;
characters: Character[];
chats: Chat[];
};
export type Chat = {
id: number;
characterId: number;
character: Character;
zoneId: number;
zone: Zone;
message: string;
createdAt: Date;
};

View File

@ -1,4 +1,5 @@
<template>
<Notifications />
<Login v-if="screen === 'login'" />
<Register v-if="screen === 'register'" />
<Characters v-if="screen === 'characters'" />
@ -8,6 +9,7 @@
<script setup lang="ts">
import { type Ref, ref } from 'vue'
import { useSocketStore } from '@/stores/socket'
import Notifications from '@/components/utilities/Notifications.vue'
import Login from '@/components/screens/Login.vue'
import Register from '@/components/screens/Register.vue'
import Characters from '@/components/screens/Characters.vue'

View File

@ -1,4 +1,5 @@
<template>
<Notifications />
<div class="game-container">
<div class="top-ui">
<Hud />

View File

@ -1,7 +1,7 @@
<template>
<TilemapLayer v-if="zoneStore.isLoaded" :tilemap="tileMap" :tileset="zoneStore.getTiles" ref="tilemapLayer" :layerIndex="0" :cull-padding-x="10" :cull-padding-y="10" />
<Controls :layer="layer" />
<Player :layer="layer" />
<Character :layer="layer" />
<Container v-if="zoneStore.isLoaded && zoneStore.getPlayers.length > 0">
<Character :layer="layer" v-for="player in zoneStore.getPlayers" :key="player.id" :player="player" />
</Container>

View File

@ -13,8 +13,9 @@
<div class="buttons-wrapper">
<button @click="select_character()">Play</button>
<button @click="isModalOpen = true">Create New</button>
<button @click="delete_character()">Delete</button>
<button @click="isModalOpen = true">Create New</button>
<!-- @TODO : Add a confirmation dialog -->
<button v-if="selected_character" @click="delete_character()">Delete</button>
</div>
</div>
</div>
@ -58,17 +59,15 @@ const characters = ref([]);
const selected_character = ref(null);
function select_character() {
console.log(selected_character.value);
if (selected_character.value) {
socket.getConnection.emit('character:connect', {character_id: selected_character.value});
socket.getConnection.on('character:connect', (data: Character) => socket.setCharacter(data));
}
if (!selected_character.value) return;
socket.getConnection.emit('character:connect', {character_id: selected_character.value});
socket.getConnection.on('character:connect', (data: Character) => socket.setCharacter(data));
}
// Delete character logics
function delete_character() {
if (selected_character.value) {
socket.getConnection.emit('character:delete', {character_id: selected_character.value});
}
if (!selected_character.value) return;
socket.getConnection.emit('character:delete', {character_id: selected_character.value});
}
// Create character logics

View File

@ -25,11 +25,11 @@
<img src="/assets/bglogin.png" id="bg-img" alt="New Quest login background" />
</template>
<script setup>
import { onMounted, ref } from 'vue'
<script setup lang="ts">
import { ref } from 'vue'
import { useSocketStore } from '@/stores/socket.ts'
import {login, register} from '@/services/authentication.ts'
import { useCookies } from '@vueuse/integrations/useCookies'
import { useNotificationStore } from '@/stores/notifications'
const bgm = ref('bgm');
if (bgm.value.paused) {
@ -38,6 +38,7 @@ if (bgm.value.paused) {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const notifications = useNotificationStore()
const socket = useSocketStore();
const username = ref('');
const password = ref('');
@ -45,7 +46,7 @@ const password = ref('');
async function loginFunc() {
// check if username and password are valid
if (username.value === '' || password.value === '') {
alert('Please enter a valid username and password');
notifications.addNotification({ message: 'Please enter a valid username and password' });
return;
}
@ -53,7 +54,7 @@ async function loginFunc() {
const success = await login(username.value, password.value);
if (!success) {
alert('Invalid username or password');
notifications.addNotification({ message: 'Invalid username or password' });
}
// if (success) {}
@ -62,7 +63,7 @@ async function loginFunc() {
async function registerFunc() {
// check if username and password are valid
if (username.value === '' || password.value === '') {
alert('Please enter a valid username and password');
notifications.addNotification({ message: 'Please enter a valid username and password' });
return;
}
@ -70,7 +71,7 @@ async function registerFunc() {
const success = await register(username.value, password.value);
if (!success) {
alert('Username already exists');
notifications.addNotification({ message: 'Username already exists' });
}
// if (success) {}

View File

@ -1,12 +1,13 @@
<template>
<Container>
<Text
:text="'Hello world'"
:text="props.player?.name"
:x="position.x - 50"
:y="position.y - 80"
:style="{
fontFamily: 'Helvetica, Arial',
color: '#42B883',
fontSize: '26px',
fontSize: '20px',
fontStyle: 'bold',
strokeThickness: 8,
stroke: '#213547'

View File

@ -0,0 +1 @@
<template></template>

View File

@ -0,0 +1 @@
<template></template>

View File

@ -42,6 +42,12 @@ const x = ref(0);
const y = ref(0);
const isDragging = ref(false);
// set modal position center of the screen
onMounted(() => {
x.value = (window.innerWidth / 2) - 150;
y.value = (window.innerHeight / 2) - 100;
});
const startDrag = (event: MouseEvent) => {
isDragging.value = true;
startX = event.clientX;

View File

@ -0,0 +1,28 @@
<template>
<div class="notifications">
<Modal v-for="notification in notifications.getNotifications" :key="notification.id" :isModalOpen="true" @modal:close="closeNotification(notification.id)">
<template #modal-body>
<p>{{ notification.message }}</p>
</template>
</Modal>
</div>
</template>
<script setup lang="ts">
import { useNotificationStore } from '@/stores/notifications'
import { useSocketStore } from '@/stores/socket'
import Modal from '@/components/utilities/Modal.vue'
const notifications = useNotificationStore();
const socket = useSocketStore();
if (socket.getConnection) {
socket.getConnection.on('notification', (data: any) => {
notifications.addNotification(data);
});
}
function closeNotification(id: string) {
notifications.removeNotification(id);
}
</script>

View File

@ -1,6 +1,6 @@
export default interface IPlayer {
readonly id: number;
username: string;
name: string;
coords: {
x: number;
y: number;

View File

@ -2,12 +2,12 @@ import type IPlayer from '@/engine/Player/IPlayer';
export default class Player implements IPlayer {
id: number;
username: string;
name: string;
coords: { x: number; y: number; };
constructor(id: number, username: string, coords: { x: number; y: number; }) {
constructor(id: number, name: string, coords: { x: number; y: number; }) {
this.id = id;
this.username = username;
this.name = name;
this.coords = coords;
}
}

View File

@ -0,0 +1,19 @@
import { defineStore, type StoreDefinition } from 'pinia'
import type { Notification } from '@/types'
export const useNotificationStore: StoreDefinition = defineStore('notifications', {
state: () => ({
notifications: [] as Notification[]
}),
getters: {
getNotifications: (state: any) => state.notifications
},
actions: {
addNotification(notification: Notification) {
this.notifications.push(notification);
},
removeNotification(index: number) {
this.notifications.splice(index, 1);
}
}
});

View File

@ -2,9 +2,10 @@ import { defineStore, type StoreDefinition } from 'pinia'
import { io, Socket } from 'socket.io-client';
import {useCookies} from '@vueuse/integrations/useCookies'
import config from '@/config';
import type { Character, User } from '../../env'
import type { Character, User } from '@/types'
import { useNotificationStore } from '@/stores/notifications'
export const useSocketStore: StoreDefinition<any> = defineStore('socket', {
export const useSocketStore: StoreDefinition = defineStore('socket', {
state: () => ({
connection: null as Socket | null,
user: null as User | null,
@ -36,12 +37,6 @@ export const useSocketStore: StoreDefinition<any> = defineStore('socket', {
console.log("Reconnect failed")
this.disconnectSocket();
})
this.connection.on('notification', (data: any) => {
if(data.error) console.error(data.error);
if (data.success) console.log(data.success);
if (data.message) console.log(data.message);
});
},
disconnectSocket() {
if (!this.connection) return;

50
src/types.ts Normal file
View File

@ -0,0 +1,50 @@
export type Notification = {
id?: number;
message: string;
type?: string;
};
export type User = {
id: number;
username: string;
password: string;
characters: Character[];
};
export type Character = {
id: number;
userId: number;
user: User;
name: string;
hitpoints: number;
mana: number;
level: number;
experience: number;
role: string;
position_x: number;
position_y: number;
rotation: number;
zoneId: number;
zone: Zone;
chats: Chat[];
};
export type Zone = {
id: number;
name: string;
width: number;
height: number;
tiles: Record<string, any>;
characters: Character[];
chats: Chat[];
};
export type Chat = {
id: number;
characterId: number;
character: Character;
zoneId: number;
zone: Zone;
message: string;
createdAt: Date;
};