1
0
forked from noxious/server

Added online column to user and char. models, updated send chat message event to new format, removed unused code, fixed typo, replaced console.log()'s with logger

This commit is contained in:
Dennis Postma 2024-09-08 03:14:55 +02:00
parent 7682d1fd01
commit a64506d3ee
5 changed files with 56 additions and 43 deletions

View File

@ -41,6 +41,7 @@ CREATE TABLE `User` (
`id` INTEGER NOT NULL AUTO_INCREMENT, `id` INTEGER NOT NULL AUTO_INCREMENT,
`username` VARCHAR(191) NOT NULL, `username` VARCHAR(191) NOT NULL,
`password` VARCHAR(191) NOT NULL, `password` VARCHAR(191) NOT NULL,
`online` BOOLEAN NOT NULL DEFAULT false,
UNIQUE INDEX `User_username_key`(`username`), UNIQUE INDEX `User_username_key`(`username`),
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
@ -64,6 +65,7 @@ CREATE TABLE `Character` (
`id` INTEGER NOT NULL AUTO_INCREMENT, `id` INTEGER NOT NULL AUTO_INCREMENT,
`userId` INTEGER NOT NULL, `userId` INTEGER NOT NULL,
`name` VARCHAR(191) NOT NULL, `name` VARCHAR(191) NOT NULL,
`online` BOOLEAN NOT NULL DEFAULT false,
`hitpoints` INTEGER NOT NULL DEFAULT 100, `hitpoints` INTEGER NOT NULL DEFAULT 100,
`mana` INTEGER NOT NULL DEFAULT 100, `mana` INTEGER NOT NULL DEFAULT 100,
`level` INTEGER NOT NULL DEFAULT 1, `level` INTEGER NOT NULL DEFAULT 1,

View File

@ -2,6 +2,7 @@ model User {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
username String @unique username String @unique
password String password String
online Boolean @default(false)
characters Character[] characters Character[]
} }
@ -19,15 +20,15 @@ enum CharacterRace {
} }
model CharacterType { model CharacterType {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String name String
gender CharacterGender gender CharacterGender
race CharacterRace race CharacterRace
characters Character[] characters Character[]
spriteId String spriteId String
sprite Sprite @relation(fields: [spriteId], references: [id], onDelete: Cascade) sprite Sprite @relation(fields: [spriteId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
} }
model Character { model Character {
@ -35,19 +36,20 @@ model Character {
userId Int userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade)
name String @unique name String @unique
online Boolean @default(false)
hitpoints Int @default(100) hitpoints Int @default(100)
mana Int @default(100) mana Int @default(100)
level Int @default(1) level Int @default(1)
experience Int @default(0) experience Int @default(0)
alignment Int @default(50) alignment Int @default(50)
role String @default("player") role String @default("player")
positionX Int @default(0) positionX Int @default(0)
positionY Int @default(0) positionY Int @default(0)
rotation Int @default(0) rotation Int @default(0)
zoneId Int @default(1) zoneId Int @default(1)
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade) zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
characterTypeId Int? characterTypeId Int?
characterType CharacterType? @relation(fields: [characterTypeId], references: [id], onDelete: Cascade) characterType CharacterType? @relation(fields: [characterTypeId], references: [id], onDelete: Cascade)
chats Chat[] chats Chat[]
items CharacterItem[] items CharacterItem[]
} }

View File

@ -3,31 +3,52 @@ import { TSocket } from '../../utilities/types'
import CharacterRepository from '../../repositories/characterRepository' import CharacterRepository from '../../repositories/characterRepository'
import ZoneRepository from '../../repositories/zoneRepository' import ZoneRepository from '../../repositories/zoneRepository'
import { isCommand } from '../../utilities/chat' import { isCommand } from '../../utilities/chat'
import logger from '../../utilities/logger'
type TypePayload = { type TypePayload = {
message: string message: string
} }
export default function (socket: TSocket, io: Server) { export default class ChatMessageEvent {
socket.on('chat:send_message', async (data: TypePayload, callback: (response: boolean) => void) => { constructor(
try { private readonly io: Server,
if (!data.message) return private readonly socket: TSocket
if (isCommand(data.message)) return ) {}
const character = await CharacterRepository.getByUserAndId(socket.user?.id as number, socket.character?.id as number) public listen(): void {
if (!character) return this.socket.on('chat:send_message', this.handleChatMessage.bind(this))
}
private async handleChatMessage(data: TypePayload, callback: (response: boolean) => void): Promise<void> {
try {
if (!data.message || isCommand(data.message)) {
callback(false)
return
}
const character = await CharacterRepository.getByUserAndId(this.socket.user?.id as number, this.socket.character?.id as number)
if (!character) {
logger.error('chat:send_message error', 'Character not found')
callback(false)
return
}
const zone = await ZoneRepository.getById(character.zoneId) const zone = await ZoneRepository.getById(character.zoneId)
if (!zone) return if (!zone) {
logger.error('chat:send_message error', 'Zone not found')
callback(false)
return
}
callback(true) callback(true)
io.to(zone.id.toString()).emit('chat:message', { this.io.to(zone.id.toString()).emit('chat:message', {
character: character, character: character,
message: data.message message: data.message
}) })
} catch (error: any) { } catch (error: any) {
console.log(`---Error sending message: ${error.message}`) logger.error('chat:send_message error', error.message)
callback(false)
} }
}) }
} }

View File

@ -3,6 +3,7 @@ import { TSocket } from '../utilities/types'
import config from '../utilities/config' import config from '../utilities/config'
import UserRepository from '../repositories/userRepository' import UserRepository from '../repositories/userRepository'
import { User } from '@prisma/client' import { User } from '@prisma/client'
import logger from '../utilities/logger'
/** /**
* Socket io jwt auth middleware * Socket io jwt auth middleware
@ -11,7 +12,7 @@ import { User } from '@prisma/client'
*/ */
export async function Authentication(socket: TSocket, next: any) { export async function Authentication(socket: TSocket, next: any) {
if (!socket.request.headers.cookie) { if (!socket.request.headers.cookie) {
console.log('No cookie provided') logger.warn('No cookie provided')
return next(new Error('Authentication error')) return next(new Error('Authentication error'))
} }
@ -32,7 +33,7 @@ export async function Authentication(socket: TSocket, next: any) {
if (token) { if (token) {
verify(token, config.JWT_SECRET, async (err: any, decoded: any) => { verify(token, config.JWT_SECRET, async (err: any, decoded: any) => {
if (err) { if (err) {
console.log('err') logger.error('Invalid token')
return next(new Error('Authentication error')) return next(new Error('Authentication error'))
} }
@ -40,7 +41,7 @@ export async function Authentication(socket: TSocket, next: any) {
next() next()
}) })
} else { } else {
console.log('No token provided') logger.warn('No token provided')
next(new Error('Authentication error')) next(new Error('Authentication error'))
} }
} }

View File

@ -3,10 +3,9 @@ import { AStar } from '../../utilities/character/aStar'
import ZoneManager from '../../managers/zoneManager' import ZoneManager from '../../managers/zoneManager'
import prisma from '../../utilities/prisma' import prisma from '../../utilities/prisma'
import Rotation from '../../utilities/character/rotation' import Rotation from '../../utilities/character/rotation'
import logger from '../../utilities/logger'
export class CharacterMoveService { export class CharacterMoveService {
private moveTokens: Map<number, symbol> = new Map()
public async updatePosition(character: ExtendedCharacter, position: { x: number; y: number }, newZoneId?: number): Promise<void> { public async updatePosition(character: ExtendedCharacter, position: { x: number; y: number }, newZoneId?: number): Promise<void> {
Object.assign(character, { Object.assign(character, {
positionX: position.x, positionX: position.x,
@ -29,7 +28,7 @@ export class CharacterMoveService {
public async calculatePath(character: ExtendedCharacter, targetX: number, targetY: number): Promise<Array<{ x: number; y: number }> | null> { public async calculatePath(character: ExtendedCharacter, targetX: number, targetY: number): Promise<Array<{ x: number; y: number }> | null> {
const grid = await ZoneManager.getGrid(character.zoneId) const grid = await ZoneManager.getGrid(character.zoneId)
if (!grid?.length) { if (!grid?.length) {
console.error('character:move error', 'Grid not found or empty') logger.error('character:move error', 'Grid not found or empty')
return null return null
} }
@ -39,19 +38,7 @@ export class CharacterMoveService {
return AStar.findPath(start, end, grid) return AStar.findPath(start, end, grid)
} }
public startMovement(characterId: number): void {
this.moveTokens.set(characterId, Symbol('moveToken'))
}
public stopMovement(characterId: number): void {
this.moveTokens.delete(characterId)
}
public isMoving(characterId: number): boolean {
return this.moveTokens.has(characterId)
}
public async applyMovementDelay(): Promise<void> { public async applyMovementDelay(): Promise<void> {
await new Promise((resolve) => setTimeout(resolve, 210)) // 50ms delay between steps await new Promise((resolve) => setTimeout(resolve, 250)) // 250ms delay between steps
} }
} }