Improved folder and file structure, separated prisma schema into multiple ones, removed obsolete functions, worked on dynamic character sprite logics, general enhancements
This commit is contained in:
parent
7531385912
commit
4b81d7ff67
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- Added the required column `characterTypeId` to the `Character` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE `Character` ADD COLUMN `characterTypeId` INTEGER NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE `Sprite` ADD COLUMN `isAnimated` BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `CharacterSprite` (
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`characterTypeId` INTEGER NOT NULL,
|
||||
`spriteId` VARCHAR(191) NOT NULL,
|
||||
`action` ENUM('IDLE_LEFT', 'IDLE_DOWN', 'SIT_LEFT', 'SIT_DOWN', 'WALK_LEFT', 'WALK_DOWN', 'ATTACK_LEFT', 'ATTACK_DOWN') NOT NULL,
|
||||
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `CharacterType` (
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(191) NOT NULL,
|
||||
`gender` ENUM('MALE', 'FEMALE') NOT NULL,
|
||||
`race` ENUM('HUMAN', 'ELF', 'DWARF', 'ORC', 'GOBLIN') NOT NULL,
|
||||
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updatedAt` DATETIME(3) NOT NULL,
|
||||
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `CharacterSprite` ADD CONSTRAINT `CharacterSprite_characterTypeId_fkey` FOREIGN KEY (`characterTypeId`) REFERENCES `CharacterType`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `CharacterSprite` ADD CONSTRAINT `CharacterSprite_spriteId_fkey` FOREIGN KEY (`spriteId`) REFERENCES `Sprite`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `Character` ADD CONSTRAINT `Character_characterTypeId_fkey` FOREIGN KEY (`characterTypeId`) REFERENCES `CharacterType`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE `Character` MODIFY `characterTypeId` INTEGER NULL;
|
@ -1,153 +0,0 @@
|
||||
// CHEAT SHEET
|
||||
// 1. Create a new Prisma project
|
||||
// npx prisma init
|
||||
// 2. Create a new database schema
|
||||
// npx prisma db push
|
||||
// 3. Generate Prisma Client and type-safe models based on schema
|
||||
// npx prisma generate
|
||||
// 4. Create a new migration
|
||||
// npx prisma migrate dev --name [migration-name]
|
||||
// 5. Apply the migration
|
||||
// npx prisma migrate deploy
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "mysql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model Sprite {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
origin_x Decimal @default(0)
|
||||
origin_y Decimal @default(0)
|
||||
frameSpeed Int @default(0)
|
||||
frameWidth Int @default(0)
|
||||
frameHeight Int @default(0)
|
||||
isLooping Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Tile {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
tags Json?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Object {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
tags Json?
|
||||
origin_x Decimal @default(0)
|
||||
origin_y Decimal @default(0)
|
||||
isAnimated Boolean @default(false)
|
||||
frameSpeed Int @default(0)
|
||||
frameWidth Int @default(0)
|
||||
frameHeight Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
ZoneObject ZoneObject[]
|
||||
}
|
||||
|
||||
model Item {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
stackable Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
characters CharacterItem[]
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique
|
||||
password String
|
||||
characters Character[]
|
||||
}
|
||||
|
||||
model Character {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
name String @unique
|
||||
hitpoints Int @default(100)
|
||||
mana Int @default(100)
|
||||
level Int @default(1)
|
||||
experience Int @default(0)
|
||||
role String @default("player")
|
||||
position_x Int @default(0)
|
||||
position_y Int @default(0)
|
||||
rotation Int @default(0)
|
||||
zoneId Int @default(1)
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
chats Chat[]
|
||||
items CharacterItem[]
|
||||
}
|
||||
|
||||
model CharacterItem {
|
||||
id Int @id @default(autoincrement())
|
||||
characterId Int
|
||||
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
|
||||
itemId String
|
||||
item Item @relation(fields: [itemId], references: [id], onDelete: Cascade)
|
||||
quantity Int
|
||||
}
|
||||
|
||||
model Zone {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
width Int @default(10)
|
||||
height Int @default(10)
|
||||
tiles Json?
|
||||
pvp Boolean @default(false)
|
||||
zoneEventTiles ZoneEventTile[]
|
||||
zoneObjects ZoneObject[]
|
||||
characters Character[]
|
||||
chats Chat[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model ZoneObject {
|
||||
id String @id @default(uuid())
|
||||
zoneId Int
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
objectId String
|
||||
object Object @relation(fields: [objectId], references: [id], onDelete: Cascade)
|
||||
depth Int @default(0)
|
||||
position_x Int @default(0)
|
||||
position_y Int @default(0)
|
||||
}
|
||||
|
||||
enum ZoneEventTileType {
|
||||
BLOCK
|
||||
WARP
|
||||
NPC
|
||||
ITEM
|
||||
}
|
||||
|
||||
model ZoneEventTile {
|
||||
id String @id @default(uuid())
|
||||
zoneId Int
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
type ZoneEventTileType
|
||||
position_x Int
|
||||
position_y Int
|
||||
}
|
||||
|
||||
model Chat {
|
||||
id Int @id @default(autoincrement())
|
||||
characterId Int
|
||||
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
|
||||
zoneId Int
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
message String
|
||||
createdAt DateTime
|
||||
}
|
31
prisma/schema/schema.prisma
Normal file
31
prisma/schema/schema.prisma
Normal file
@ -0,0 +1,31 @@
|
||||
// CHEAT SHEET
|
||||
// 1. Create a new Prisma project
|
||||
// npx prisma init
|
||||
// 2. Create a new database schema
|
||||
// npx prisma db push
|
||||
// 3. Generate Prisma Client and type-safe models based on schema
|
||||
// npx prisma generate
|
||||
// 4. Create a new migration
|
||||
// npx prisma migrate dev --name [migration-name]
|
||||
// 5. Apply the migration
|
||||
// npx prisma migrate deploy
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
previewFeatures = ["prismaSchemaFolder"]
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "mysql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model Chat {
|
||||
id Int @id @default(autoincrement())
|
||||
characterId Int
|
||||
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
|
||||
zoneId Int
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
message String
|
||||
createdAt DateTime
|
||||
}
|
34
prisma/schema/sprite.prisma
Normal file
34
prisma/schema/sprite.prisma
Normal file
@ -0,0 +1,34 @@
|
||||
model Sprite {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
origin_x Decimal @default(0)
|
||||
origin_y Decimal @default(0)
|
||||
isAnimated Boolean @default(false)
|
||||
frameSpeed Int @default(0)
|
||||
frameWidth Int @default(0)
|
||||
frameHeight Int @default(0)
|
||||
isLooping Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
characterSprites CharacterSprite[]
|
||||
}
|
||||
|
||||
enum SpriteAction {
|
||||
IDLE_LEFT
|
||||
IDLE_DOWN
|
||||
SIT_LEFT
|
||||
SIT_DOWN
|
||||
WALK_LEFT
|
||||
WALK_DOWN
|
||||
ATTACK_LEFT
|
||||
ATTACK_DOWN
|
||||
}
|
||||
|
||||
model CharacterSprite {
|
||||
id Int @id @default(autoincrement())
|
||||
characterTypeId Int
|
||||
spriteId String
|
||||
action SpriteAction
|
||||
characterType CharacterType @relation(fields: [characterTypeId], references: [id], onDelete: Cascade)
|
||||
sprite Sprite @relation(fields: [spriteId], references: [id], onDelete: Cascade)
|
||||
}
|
60
prisma/schema/user.prisma
Normal file
60
prisma/schema/user.prisma
Normal file
@ -0,0 +1,60 @@
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique
|
||||
password String
|
||||
characters Character[]
|
||||
}
|
||||
|
||||
enum CharacterGender {
|
||||
MALE
|
||||
FEMALE
|
||||
}
|
||||
|
||||
enum CharacterRace {
|
||||
HUMAN
|
||||
ELF
|
||||
DWARF
|
||||
ORC
|
||||
GOBLIN
|
||||
}
|
||||
|
||||
model CharacterType {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
gender CharacterGender
|
||||
race CharacterRace
|
||||
characters Character[]
|
||||
characterSprites CharacterSprite[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Character {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
name String @unique
|
||||
hitpoints Int @default(100)
|
||||
mana Int @default(100)
|
||||
level Int @default(1)
|
||||
experience Int @default(0)
|
||||
role String @default("player")
|
||||
position_x Int @default(0)
|
||||
position_y Int @default(0)
|
||||
rotation Int @default(0)
|
||||
zoneId Int @default(1)
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
characterTypeId Int?
|
||||
characterType CharacterType? @relation(fields: [characterTypeId], references: [id], onDelete: Cascade)
|
||||
chats Chat[]
|
||||
items CharacterItem[]
|
||||
}
|
||||
|
||||
model CharacterItem {
|
||||
id Int @id @default(autoincrement())
|
||||
characterId Int
|
||||
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
|
||||
itemId String
|
||||
item Item @relation(fields: [itemId], references: [id], onDelete: Cascade)
|
||||
quantity Int
|
||||
}
|
74
prisma/schema/zone.prisma
Normal file
74
prisma/schema/zone.prisma
Normal file
@ -0,0 +1,74 @@
|
||||
model Tile {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
tags Json?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Object {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
tags Json?
|
||||
origin_x Decimal @default(0)
|
||||
origin_y Decimal @default(0)
|
||||
isAnimated Boolean @default(false)
|
||||
frameSpeed Int @default(0)
|
||||
frameWidth Int @default(0)
|
||||
frameHeight Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
ZoneObject ZoneObject[]
|
||||
}
|
||||
|
||||
model Item {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
stackable Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
characters CharacterItem[]
|
||||
}
|
||||
|
||||
model Zone {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
width Int @default(10)
|
||||
height Int @default(10)
|
||||
tiles Json?
|
||||
pvp Boolean @default(false)
|
||||
zoneEventTiles ZoneEventTile[]
|
||||
zoneObjects ZoneObject[]
|
||||
characters Character[]
|
||||
chats Chat[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model ZoneObject {
|
||||
id String @id @default(uuid())
|
||||
zoneId Int
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
objectId String
|
||||
object Object @relation(fields: [objectId], references: [id], onDelete: Cascade)
|
||||
depth Int @default(0)
|
||||
position_x Int @default(0)
|
||||
position_y Int @default(0)
|
||||
}
|
||||
|
||||
enum ZoneEventTileType {
|
||||
BLOCK
|
||||
WARP
|
||||
NPC
|
||||
ITEM
|
||||
}
|
||||
|
||||
model ZoneEventTile {
|
||||
id String @id @default(uuid())
|
||||
zoneId Int
|
||||
zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
||||
type ZoneEventTileType
|
||||
position_x Int
|
||||
position_y Int
|
||||
}
|
@ -29,7 +29,8 @@ export default function (socket: TSocket, io: Server) {
|
||||
const character: Character = await prisma.character.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
userId: user_id
|
||||
userId: user_id,
|
||||
// characterTypeId: 1 // @TODO set to chosen character type
|
||||
}
|
||||
})
|
||||
|
||||
@ -38,7 +39,8 @@ export default function (socket: TSocket, io: Server) {
|
||||
socket.emit('character:create:success')
|
||||
socket.emit('character:list', characters)
|
||||
} catch (error: any) {
|
||||
return socket.emit('notification', { message: error.errors[0]?.message ?? 'Invalid data' })
|
||||
console.log('character:create error', error)
|
||||
return socket.emit('notification', { message: 'Could not create character. Please try again (later).' })
|
||||
}
|
||||
})
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { TSocket } from '../../../utilities/Types'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import prisma from '../../../utilities/Prisma'
|
||||
|
||||
type Payload = {
|
||||
|
@ -42,7 +42,7 @@ export default function (socket: TSocket, io: Server) {
|
||||
return
|
||||
}
|
||||
|
||||
console.log(data);
|
||||
console.log(data)
|
||||
|
||||
await prisma.zone.update({
|
||||
where: {
|
||||
|
@ -45,25 +45,6 @@ class CharacterRepository {
|
||||
}
|
||||
}
|
||||
|
||||
async create(userId: number, name: string, role: 'player'): Promise<Character | null> {
|
||||
try {
|
||||
return await prisma.character.create({
|
||||
data: {
|
||||
userId,
|
||||
name,
|
||||
role,
|
||||
position_x: 0, // @TODO Set default registration values in the database
|
||||
position_y: 0, // @TODO Set default registration values in the database
|
||||
rotation: 0, // @TODO Set default registration values in the database
|
||||
zoneId: 1 // @TODO Set default registration values in the database
|
||||
}
|
||||
})
|
||||
} catch (error: any) {
|
||||
// Handle error
|
||||
throw new Error(`Failed to create character: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async updatePosition(id: number, position_x: number, position_y: number): Promise<Character | null> {
|
||||
try {
|
||||
return await prisma.character.update({
|
||||
@ -81,19 +62,6 @@ class CharacterRepository {
|
||||
}
|
||||
}
|
||||
|
||||
async delete(id: number): Promise<Character | null> {
|
||||
try {
|
||||
return await prisma.character.delete({
|
||||
where: {
|
||||
id
|
||||
}
|
||||
})
|
||||
} catch (error: any) {
|
||||
// Handle error
|
||||
throw new Error(`Failed to delete character: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async deleteByUserIdAndId(userId: number, characterId: number): Promise<Character | null> {
|
||||
try {
|
||||
return await prisma.character.delete({
|
||||
|
Loading…
x
Reference in New Issue
Block a user