This commit is contained in:
Dennis Postma 2024-08-22 20:00:37 +02:00
parent ff7664bae0
commit c4b50ec811
16 changed files with 97 additions and 80 deletions

View File

@ -25,8 +25,8 @@ CREATE TABLE `SpriteAction` (
`spriteId` VARCHAR(191) NOT NULL, `spriteId` VARCHAR(191) NOT NULL,
`action` VARCHAR(191) NOT NULL, `action` VARCHAR(191) NOT NULL,
`sprites` JSON NULL, `sprites` JSON NULL,
`origin_x` DECIMAL(65, 30) NOT NULL DEFAULT 0, `originX` DECIMAL(65, 30) NOT NULL DEFAULT 0,
`origin_y` DECIMAL(65, 30) NOT NULL DEFAULT 0, `originY` DECIMAL(65, 30) NOT NULL DEFAULT 0,
`isAnimated` BOOLEAN NOT NULL DEFAULT false, `isAnimated` BOOLEAN NOT NULL DEFAULT false,
`isLooping` BOOLEAN NOT NULL DEFAULT false, `isLooping` BOOLEAN NOT NULL DEFAULT false,
`frameWidth` INTEGER NOT NULL DEFAULT 0, `frameWidth` INTEGER NOT NULL DEFAULT 0,
@ -69,8 +69,8 @@ CREATE TABLE `Character` (
`level` INTEGER NOT NULL DEFAULT 1, `level` INTEGER NOT NULL DEFAULT 1,
`experience` INTEGER NOT NULL DEFAULT 0, `experience` INTEGER NOT NULL DEFAULT 0,
`role` VARCHAR(191) NOT NULL DEFAULT 'player', `role` VARCHAR(191) NOT NULL DEFAULT 'player',
`position_x` INTEGER NOT NULL DEFAULT 0, `positionX` INTEGER NOT NULL DEFAULT 0,
`position_y` INTEGER NOT NULL DEFAULT 0, `positionY` INTEGER NOT NULL DEFAULT 0,
`rotation` INTEGER NOT NULL DEFAULT 0, `rotation` INTEGER NOT NULL DEFAULT 0,
`zoneId` INTEGER NOT NULL DEFAULT 1, `zoneId` INTEGER NOT NULL DEFAULT 1,
`characterTypeId` INTEGER NULL, `characterTypeId` INTEGER NULL,
@ -105,8 +105,8 @@ CREATE TABLE `Object` (
`id` VARCHAR(191) NOT NULL, `id` VARCHAR(191) NOT NULL,
`name` VARCHAR(191) NOT NULL, `name` VARCHAR(191) NOT NULL,
`tags` JSON NULL, `tags` JSON NULL,
`origin_x` DECIMAL(65, 30) NOT NULL DEFAULT 0, `originX` DECIMAL(65, 30) NOT NULL DEFAULT 0,
`origin_y` DECIMAL(65, 30) NOT NULL DEFAULT 0, `originY` DECIMAL(65, 30) NOT NULL DEFAULT 0,
`isAnimated` BOOLEAN NOT NULL DEFAULT false, `isAnimated` BOOLEAN NOT NULL DEFAULT false,
`frameSpeed` INTEGER NOT NULL DEFAULT 0, `frameSpeed` INTEGER NOT NULL DEFAULT 0,
`frameWidth` INTEGER NOT NULL DEFAULT 0, `frameWidth` INTEGER NOT NULL DEFAULT 0,
@ -149,8 +149,8 @@ CREATE TABLE `ZoneObject` (
`zoneId` INTEGER NOT NULL, `zoneId` INTEGER NOT NULL,
`objectId` VARCHAR(191) NOT NULL, `objectId` VARCHAR(191) NOT NULL,
`depth` INTEGER NOT NULL DEFAULT 0, `depth` INTEGER NOT NULL DEFAULT 0,
`position_x` INTEGER NOT NULL DEFAULT 0, `positionX` INTEGER NOT NULL DEFAULT 0,
`position_y` INTEGER NOT NULL DEFAULT 0, `positionY` INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
@ -160,21 +160,21 @@ CREATE TABLE `ZoneEventTile` (
`id` VARCHAR(191) NOT NULL, `id` VARCHAR(191) NOT NULL,
`zoneId` INTEGER NOT NULL, `zoneId` INTEGER NOT NULL,
`type` ENUM('BLOCK', 'TELEPORT', 'NPC', 'ITEM') NOT NULL, `type` ENUM('BLOCK', 'TELEPORT', 'NPC', 'ITEM') NOT NULL,
`position_x` INTEGER NOT NULL, `positionX` INTEGER NOT NULL,
`position_y` INTEGER NOT NULL, `positionY` INTEGER NOT NULL,
`teleportId` VARCHAR(191) NULL,
UNIQUE INDEX `ZoneEventTile_teleportId_key`(`teleportId`),
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable -- CreateTable
CREATE TABLE `ZoneEventTileTeleport` ( CREATE TABLE `ZoneEventTileTeleport` (
`id` VARCHAR(191) NOT NULL, `id` VARCHAR(191) NOT NULL,
`zoneEventTileId` VARCHAR(191) NOT NULL,
`toZoneId` INTEGER NOT NULL, `toZoneId` INTEGER NOT NULL,
`toPosition_x` INTEGER NOT NULL, `toPositionX` INTEGER NOT NULL,
`toPosition_y` INTEGER NOT NULL, `toPositionY` INTEGER NOT NULL,
UNIQUE INDEX `ZoneEventTileTeleport_zoneEventTileId_key`(`zoneEventTileId`),
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
@ -215,7 +215,7 @@ ALTER TABLE `ZoneObject` ADD CONSTRAINT `ZoneObject_objectId_fkey` FOREIGN KEY (
ALTER TABLE `ZoneEventTile` ADD CONSTRAINT `ZoneEventTile_zoneId_fkey` FOREIGN KEY (`zoneId`) REFERENCES `Zone`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `ZoneEventTile` ADD CONSTRAINT `ZoneEventTile_zoneId_fkey` FOREIGN KEY (`zoneId`) REFERENCES `Zone`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE `ZoneEventTile` ADD CONSTRAINT `ZoneEventTile_teleportId_fkey` FOREIGN KEY (`teleportId`) REFERENCES `ZoneEventTileTeleport`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `ZoneEventTileTeleport` ADD CONSTRAINT `ZoneEventTileTeleport_zoneEventTileId_fkey` FOREIGN KEY (`zoneEventTileId`) REFERENCES `ZoneEventTile`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE `ZoneEventTileTeleport` ADD CONSTRAINT `ZoneEventTileTeleport_toZoneId_fkey` FOREIGN KEY (`toZoneId`) REFERENCES `Zone`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `ZoneEventTileTeleport` ADD CONSTRAINT `ZoneEventTileTeleport_toZoneId_fkey` FOREIGN KEY (`toZoneId`) REFERENCES `Zone`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -13,8 +13,8 @@ model SpriteAction {
sprite Sprite @relation(fields: [spriteId], references: [id], onDelete: Cascade) sprite Sprite @relation(fields: [spriteId], references: [id], onDelete: Cascade)
action String action String
sprites Json? sprites Json?
origin_x Decimal @default(0) originX Decimal @default(0)
origin_y Decimal @default(0) originY Decimal @default(0)
isAnimated Boolean @default(false) isAnimated Boolean @default(false)
isLooping Boolean @default(false) isLooping Boolean @default(false)
frameWidth Int @default(0) frameWidth Int @default(0)

View File

@ -40,8 +40,8 @@ model Character {
level Int @default(1) level Int @default(1)
experience Int @default(0) experience Int @default(0)
role String @default("player") role String @default("player")
position_x Int @default(0) positionX Int @default(0)
position_y 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)

View File

@ -10,8 +10,8 @@ model Object {
id String @id @default(uuid()) id String @id @default(uuid())
name String name String
tags Json? tags Json?
origin_x Decimal @default(0) originX Decimal @default(0)
origin_y Decimal @default(0) originY Decimal @default(0)
isAnimated Boolean @default(false) isAnimated Boolean @default(false)
frameSpeed Int @default(0) frameSpeed Int @default(0)
frameWidth Int @default(0) frameWidth Int @default(0)
@ -48,14 +48,14 @@ model Zone {
} }
model ZoneObject { model ZoneObject {
id String @id @default(uuid()) id String @id @default(uuid())
zoneId Int zoneId Int
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade) zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
objectId String objectId String
object Object @relation(fields: [objectId], references: [id], onDelete: Cascade) object Object @relation(fields: [objectId], references: [id], onDelete: Cascade)
depth Int @default(0) depth Int @default(0)
position_x Int @default(0) positionX Int @default(0)
position_y Int @default(0) positionY Int @default(0)
} }
enum ZoneEventTileType { enum ZoneEventTileType {
@ -66,21 +66,21 @@ enum ZoneEventTileType {
} }
model ZoneEventTile { model ZoneEventTile {
id String @id @default(uuid()) id String @id @default(uuid())
zoneId Int zoneId Int
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade) zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
type ZoneEventTileType type ZoneEventTileType
position_x Int positionX Int
position_y Int positionY Int
teleportId String? @unique teleport ZoneEventTileTeleport?
teleport ZoneEventTileTeleport? @relation("ZoneEventTileTeleport", fields: [teleportId], references: [id])
} }
model ZoneEventTileTeleport { model ZoneEventTileTeleport {
id String @id @default(uuid()) id String @id @default(uuid())
zoneEventTile ZoneEventTile? @relation("ZoneEventTileTeleport") zoneEventTileId String @unique
toZoneId Int zoneEventTile ZoneEventTile @relation(fields: [zoneEventTileId], references: [id], onDelete: Cascade)
toZone Zone @relation(fields: [toZoneId], references: [id], onDelete: Cascade) toZoneId Int
toPosition_x Int toZone Zone @relation(fields: [toZoneId], references: [id], onDelete: Cascade)
toPosition_y Int toPositionX Int
toPositionY Int
} }

View File

@ -30,7 +30,7 @@ export default function (socket: TSocket, io: Server) {
const character: Character = await prisma.character.create({ const character: Character = await prisma.character.create({
data: { data: {
name: data.name, name: data.name,
userId: user_id, userId: user_id
// characterTypeId: 1 // @TODO set to chosen character type // characterTypeId: 1 // @TODO set to chosen character type
} }
}) })

View File

@ -8,7 +8,7 @@ import Rotation from '../../utilities/player/rotation'
const moveTokens = new Map<number, symbol>() const moveTokens = new Map<number, symbol>()
export default function setupCharacterMove(socket: TSocket, io: Server) { export default function setupCharacterMove(socket: TSocket, io: Server) {
socket.on('character:move', async ({ position_x, position_y }: { position_x: number; position_y: number }) => { socket.on('character:move', async ({ positionX, positionY }: { positionX: number; positionY: number }) => {
const { character } = socket const { character } = socket
if (!character) return console.error('character:move error', 'Character not found') if (!character) return console.error('character:move error', 'Character not found')
@ -16,8 +16,8 @@ export default function setupCharacterMove(socket: TSocket, io: Server) {
const grid = await ZoneManager.getGrid(character.zoneId) const grid = await ZoneManager.getGrid(character.zoneId)
if (!grid?.length) return console.error('character:move error', 'Grid not found or empty') if (!grid?.length) return console.error('character:move error', 'Grid not found or empty')
const start = { x: Math.floor(character.position_x), y: Math.floor(character.position_y) } const start = { x: Math.floor(character.positionX), y: Math.floor(character.positionY) }
const end = { x: Math.floor(position_x), y: Math.floor(position_y) } const end = { x: Math.floor(positionX), y: Math.floor(positionY) }
if (isObstacle(end, grid)) return socket.emit('character:moveError', 'Destination is an obstacle') if (isObstacle(end, grid)) return socket.emit('character:moveError', 'Destination is an obstacle')
@ -80,17 +80,14 @@ const interpolatePosition = (start: { x: number; y: number }, end: { x: number;
const isObstacle = ({ x, y }: { x: number; y: number }, grid: number[][]) => { const isObstacle = ({ x, y }: { x: number; y: number }, grid: number[][]) => {
const gridX = Math.floor(x) const gridX = Math.floor(x)
const gridY = Math.floor(y) const gridY = Math.floor(y)
return grid[gridY]?.[gridX] === 1 || return grid[gridY]?.[gridX] === 1 || grid[gridY]?.[Math.ceil(x)] === 1 || grid[Math.ceil(y)]?.[gridX] === 1 || grid[Math.ceil(y)]?.[Math.ceil(x)] === 1
grid[gridY]?.[Math.ceil(x)] === 1 ||
grid[Math.ceil(y)]?.[gridX] === 1 ||
grid[Math.ceil(y)]?.[Math.ceil(x)] === 1
} }
async function updateCharacter(character: ExtendedCharacter, { x, y }: { x: number; y: number }, rotation: number) { async function updateCharacter(character: ExtendedCharacter, { x, y }: { x: number; y: number }, rotation: number) {
Object.assign(character, { position_x: x, position_y: y, rotation }) Object.assign(character, { positionX: x, positionY: y, rotation })
ZoneManager.updateCharacterInZone(character.zoneId, character) ZoneManager.updateCharacterInZone(character.zoneId, character)
await prisma.character.update({ await prisma.character.update({
where: { id: character.id }, where: { id: character.id },
data: { position_x: x, position_y: y, rotation } data: { positionX: x, positionY: y, rotation }
}) })
} }

View File

@ -6,8 +6,8 @@ type Payload = {
id: string id: string
name: string name: string
tags: string[] tags: string[]
origin_x: number originX: number
origin_y: number originY: number
isAnimated: boolean isAnimated: boolean
frameSpeed: number frameSpeed: number
frameWidth: number frameWidth: number
@ -33,8 +33,8 @@ export default function (socket: TSocket, io: Server) {
data: { data: {
name: data.name, name: data.name,
tags: data.tags, tags: data.tags,
origin_x: data.origin_x, originX: data.originX,
origin_y: data.origin_y, originY: data.originY,
isAnimated: data.isAnimated, isAnimated: data.isAnimated,
frameSpeed: data.frameSpeed, frameSpeed: data.frameSpeed,
frameWidth: data.frameWidth, frameWidth: data.frameWidth,

View File

@ -32,8 +32,8 @@ export default function (socket: TSocket, io: Server) {
data: { data: {
name: key, name: key,
tags: [], tags: [],
origin_x: 0, originX: 0,
origin_y: 0 originY: 0
} }
}) })

View File

@ -98,11 +98,11 @@ async function updateDatabase(id: string, name: string, processedActions: Proces
name, name,
spriteActions: { spriteActions: {
deleteMany: { spriteId: id }, deleteMany: { spriteId: id },
create: processedActions.map(({ action, sprites, origin_x, origin_y, isAnimated, isLooping, frameWidth, frameHeight, frameSpeed }) => ({ create: processedActions.map(({ action, sprites, originX, originY, isAnimated, isLooping, frameWidth, frameHeight, frameSpeed }) => ({
action, action,
sprites, sprites,
origin_x, originX,
origin_y, originY,
isAnimated, isAnimated,
isLooping, isLooping,
frameWidth, frameWidth,

View File

@ -1,7 +1,7 @@
import { Server } from 'socket.io' import { Server } from 'socket.io'
import { TSocket } from '../../../utilities/types' import { TSocket } from '../../../utilities/types'
import ZoneRepository from '../../../repositories/zoneRepository' import ZoneRepository from '../../../repositories/zoneRepository'
import { ZoneEventTile, ZoneObject } from '@prisma/client' import { ZoneEventTile, ZoneEventTileType, ZoneObject } from '@prisma/client'
import prisma from '../../../utilities/prisma' import prisma from '../../../utilities/prisma'
import zoneManager from '../../../managers/zoneManager' import zoneManager from '../../../managers/zoneManager'
@ -12,7 +12,16 @@ interface IPayload {
height: number height: number
tiles: string[][] tiles: string[][]
pvp: boolean pvp: boolean
zoneEventTiles: ZoneEventTile[] zoneEventTiles: {
type: ZoneEventTileType
positionX: number
positionY: number
teleport?: {
toZoneId: number
toPositionX: number
toPositionY: number
}
}[]
zoneObjects: ZoneObject[] zoneObjects: ZoneObject[]
} }
@ -62,8 +71,19 @@ export default function (socket: TSocket, io: Server) {
// Save new zone event tiles // Save new zone event tiles
create: data.zoneEventTiles.map((zoneEventTile) => ({ create: data.zoneEventTiles.map((zoneEventTile) => ({
type: zoneEventTile.type, type: zoneEventTile.type,
position_x: zoneEventTile.position_x, positionX: zoneEventTile.positionX,
position_y: zoneEventTile.position_y positionY: zoneEventTile.positionY,
...(zoneEventTile.type === 'TELEPORT' && zoneEventTile.teleport
? {
teleport: {
create: {
toZoneId: zoneEventTile.teleport.toZoneId,
toPositionX: zoneEventTile.teleport.toPositionX,
toPositionY: zoneEventTile.teleport.toPositionY
}
}
}
: {})
})) }))
}, },
zoneObjects: { zoneObjects: {
@ -74,8 +94,8 @@ export default function (socket: TSocket, io: Server) {
create: data.zoneObjects.map((zoneObject) => ({ create: data.zoneObjects.map((zoneObject) => ({
objectId: zoneObject.objectId, objectId: zoneObject.objectId,
depth: zoneObject.depth, depth: zoneObject.depth,
position_x: zoneObject.position_x, positionX: zoneObject.positionX,
position_y: zoneObject.position_y positionY: zoneObject.positionY
})) }))
} }
} }

View File

@ -63,7 +63,7 @@ class ZoneManager {
const loadedZone = this.loadedZones.find((loadedZone) => { const loadedZone = this.loadedZones.find((loadedZone) => {
return loadedZone.zone.id === zoneId return loadedZone.zone.id === zoneId
}) })
if (loadedZone && this.isPositionWalkable(zoneId, character.position_x, character.position_y)) { if (loadedZone && this.isPositionWalkable(zoneId, character.positionX, character.positionY)) {
loadedZone.characters.push(character) loadedZone.characters.push(character)
} }
} }
@ -114,7 +114,7 @@ class ZoneManager {
// Set the grid values based on the event tiles, these are strings // Set the grid values based on the event tiles, these are strings
eventTiles.forEach((eventTile) => { eventTiles.forEach((eventTile) => {
if (eventTile.type === 'BLOCK') { if (eventTile.type === 'BLOCK') {
grid[eventTile.position_y][eventTile.position_x] = 1 grid[eventTile.positionY][eventTile.positionX] = 1
} }
}) })

View File

@ -66,15 +66,15 @@ class CharacterRepository {
} }
} }
async updatePosition(id: number, position_x: number, position_y: number): Promise<Character | null> { async updatePosition(id: number, positionX: number, positionY: number): Promise<Character | null> {
try { try {
return await prisma.character.update({ return await prisma.character.update({
where: { where: {
id: id id: id
}, },
data: { data: {
position_x, positionX,
position_y positionY
} }
}) })
} catch (error: any) { } catch (error: any) {

View File

@ -29,7 +29,8 @@ class ZoneRepository {
include: { include: {
zoneEventTiles: { zoneEventTiles: {
include: { include: {
zone: true zone: true,
teleport: true
} }
}, },
zoneObjects: { zoneObjects: {

View File

@ -15,7 +15,6 @@ import { Authentication } from './middleware/authentication'
import { Dirent } from 'node:fs' import { Dirent } from 'node:fs'
import logger from './utilities/logger' import logger from './utilities/logger'
export class Server { export class Server {
private readonly app: Application private readonly app: Application
private readonly http: HTTPServer private readonly http: HTTPServer
@ -104,4 +103,4 @@ export class Server {
const server = new Server() const server = new Server()
server.start() server.start()
console.log('Server started') console.log('Server started')

View File

@ -12,9 +12,9 @@ const logger = pino({
formatters: { formatters: {
level: (label) => { level: (label) => {
return { level: label.toUpperCase() } return { level: label.toUpperCase() }
}, }
}, },
timestamp: pino.stdTimeFunctions.isoTime timestamp: pino.stdTimeFunctions.isoTime
}) })
export default logger export default logger

View File

@ -4,9 +4,9 @@ export type Node = Position & { parent?: Node; g: number; h: number; f: number }
export class AStar { export class AStar {
private static readonly DIRECTIONS = [ private static readonly DIRECTIONS = [
{ x: 0, y: -1 }, // Up { x: 0, y: -1 }, // Up
{ x: 0, y: 1 }, // Down { x: 0, y: 1 }, // Down
{ x: -1, y: 0 }, // Left { x: -1, y: 0 }, // Left
{ x: 1, y: 0 }, // Right { x: 1, y: 0 }, // Right
{ x: -1, y: -1 }, { x: -1, y: -1 },
{ x: -1, y: 1 }, { x: -1, y: 1 },
{ x: 1, y: -1 }, { x: 1, y: -1 },