From 473c8074614cab38d67bb1b9a349325162c4f040 Mon Sep 17 00:00:00 2001 From: katboi01 Date: Sat, 12 Jul 2025 02:19:48 +0200 Subject: [PATCH] further refactor --- .gitignore | 3 +- Account/_emitLogin.ts | 21 ----- Account/_login.ts | 40 ++++++---- Account/_register.ts | 36 ++++++--- Account/accountSocket.ts | 5 +- Account/users.ts | 67 +++++----------- Characters/characters.ts | 29 +++++++ Classes/Incoming/levelUpdateClient.ts | 4 +- Classes/Incoming/levelUpdateHost.ts | 4 +- Classes/Incoming/lobbyJoin.ts | 4 +- Classes/Outgoing/accountResponses.ts | 20 +++++ Classes/Outgoing/characterDataPartial.ts | 40 ++++++++++ Classes/Outgoing/enemyDataPartial.ts | 17 ++++ Classes/Outgoing/levelStatePartial.ts | 63 +++++++++++++++ Classes/Outgoing/lobbyStatePartial.ts | 16 ++++ Classes/Outgoing/propDataPartial.ts | 28 +++++++ Classes/Outgoing/roomChangeResponse.ts | 8 ++ Classes/Outgoing/userDataPartial.ts | 10 +++ Classes/{playerData.ts => characterData.ts} | 39 +++------ Classes/enemyData.ts | 23 +++--- Classes/levelState.ts | 44 +++-------- Classes/lobbyState.ts | 66 ++++++---------- Classes/loginResponse.ts | 16 ---- Classes/playerInventory.ts | 4 + Classes/propData.ts | 19 ++--- Classes/roomChangeResponse.ts | 8 -- Classes/userData.ts | 16 +--- Database/dbcontroller.ts | 87 ++++++++++++++++++--- Items/_updateInventory.ts | 9 +-- Items/itemSocket.ts | 3 +- Level/_clear.ts | 5 +- Level/_enter.ts | 29 ++++--- Level/_playerUpdate.ts | 15 ++-- Level/_projectile.ts | 10 ++- Level/_update.ts | 13 ++- Level/levelSocket.ts | 13 +-- Lobby/_loadoutChanged.ts | 20 ++--- Lobby/_playerJoin.ts | 50 ++++++------ Lobby/lobbySocket.ts | 9 ++- Player/players.ts | 45 ----------- Quest/_update.ts | 11 ++- Quest/questSocket.ts | 3 +- endpoints.ts | 16 ++++ game.ts | 15 ++-- index.ts | 85 +++++++++----------- socketExtended.ts | 24 ++++++ 46 files changed, 637 insertions(+), 475 deletions(-) delete mode 100644 Account/_emitLogin.ts create mode 100644 Characters/characters.ts create mode 100644 Classes/Outgoing/accountResponses.ts create mode 100644 Classes/Outgoing/characterDataPartial.ts create mode 100644 Classes/Outgoing/enemyDataPartial.ts create mode 100644 Classes/Outgoing/levelStatePartial.ts create mode 100644 Classes/Outgoing/lobbyStatePartial.ts create mode 100644 Classes/Outgoing/propDataPartial.ts create mode 100644 Classes/Outgoing/roomChangeResponse.ts create mode 100644 Classes/Outgoing/userDataPartial.ts rename Classes/{playerData.ts => characterData.ts} (52%) delete mode 100644 Classes/loginResponse.ts delete mode 100644 Classes/roomChangeResponse.ts delete mode 100644 Player/players.ts create mode 100644 endpoints.ts create mode 100644 socketExtended.ts diff --git a/.gitignore b/.gitignore index c9c09bb..d0a07c1 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,5 @@ Thumbs.db dist/**/* # ignore yarn.lock -yarn.lock \ No newline at end of file +yarn.lock +Database/mydb.sqlite3 diff --git a/Account/_emitLogin.ts b/Account/_emitLogin.ts deleted file mode 100644 index e9ff019..0000000 --- a/Account/_emitLogin.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { loginResponse } from "../Classes/loginResponse.js"; -import { playerData } from "../Classes/playerData.js"; -import { userData } from "../Classes/userData.js"; - -export function emitLogin(socket, user : userData | null, player:playerData, registered:boolean = false){ - if(user != null){ - socket.emit("account/login", JSON.stringify(new loginResponse(true, user, player))); - socket.user = user - socket.player = player - if(registered){ - console.log(`User ${(user as userData).login} registerd and logged in`); - } - else{ - console.log(`User ${(user as userData).login} logged in`); - } - } - else{ - socket.emit("account/login", JSON.stringify(new loginResponse(false, null, null))); - console.log("Login Failed"); - } -} \ No newline at end of file diff --git a/Account/_login.ts b/Account/_login.ts index d1ae518..dfd0705 100644 --- a/Account/_login.ts +++ b/Account/_login.ts @@ -1,21 +1,33 @@ import { userData } from "../Classes/userData.js"; -import { players } from "../Player/players.js"; -import { emitLogin } from "./_emitLogin.js"; +import { characters } from "../Characters/characters.js"; import { users } from "./users.js"; +import { db } from "../index.js" +import { Socket } from "socket.io"; +import { loginResponse } from "../Classes/Outgoing/accountResponses.js"; +import { Endpoints } from "../endpoints.js"; -export function login(socket, data){ +export async function login(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); - let json : userData = JSON.parse(buff.toString('utf-8')); - if (!json.login || !json.password) return + let json : userData = JSON.parse(buff.toString('utf-8')); + if (!json.login || !json.password){ + console.log("login or password is missing") + return + } - let result = users.readUser(json.login, json.password); - let player = null - if(result != null){ - player = players.readPlayer(result.id) - if(player == null){ - player = players.createPlayer(result.id) - } - } + const user = await users.readUser(db, json.login, json.password); - emitLogin(socket, result, player); + if(user){ + console.log(`User ${user.login} logged in`); + const character = await characters.readCharacter(db, user.id); + const result = new loginResponse(user, character) + + socket.user = user + socket.character = character + socket.emit(Endpoints.Login, JSON.stringify(result)); + } + else{ + console.log(`User ${json.login} did not log in`); + const result = new loginResponse(null, null) + socket.emit(Endpoints.Login, JSON.stringify(result)); + } } \ No newline at end of file diff --git a/Account/_register.ts b/Account/_register.ts index aea2639..4eee402 100644 --- a/Account/_register.ts +++ b/Account/_register.ts @@ -1,18 +1,32 @@ import { userData } from "../Classes/userData.js"; -import { players } from "../Player/players.js"; -import { emitLogin } from "./_emitLogin.js"; import { users } from "./users.js"; +import { db } from "../index.js" +import { Socket } from "socket.io"; +import { loginResponse } from "../Classes/Outgoing/accountResponses.js"; +import { Endpoints } from "../endpoints.js"; +import { characters } from "../Characters/characters.js"; -export function register(socket, data){ +export async function register(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); - let json : userData = JSON.parse(buff.toString('utf-8')); - if (!json.login || !json.password) return + let json : userData = JSON.parse(buff.toString('utf-8')); + if (!json.login || !json.password){ + console.log("login or password is missing") + return + } - let result = users.createUser(json.login, json.password); - let player = null - if(result != null){ - player = players.createPlayer(result.id) - } + const user = await users.createUser(db, json.login, json.password); - emitLogin(socket, result, player); + if(user){ + console.log(`User ${user.login} registered`); + const character = await characters.createCharacter(db, user.id); + const result = new loginResponse(user, character) + socket.user = user + socket.character = character + socket.emit(Endpoints.Register, JSON.stringify(result)) + } + else{ + console.log(`User failed to register`); + const result = new loginResponse(null, null) + socket.emit(Endpoints.Register, JSON.stringify(result)) + } } \ No newline at end of file diff --git a/Account/accountSocket.ts b/Account/accountSocket.ts index 69aaaa2..f4e3789 100644 --- a/Account/accountSocket.ts +++ b/Account/accountSocket.ts @@ -1,12 +1,13 @@ import { register } from "./_register.js"; import { login } from "./_login.js"; +import { Endpoints } from "../endpoints.js"; export function registerAccountCallbacks(socket){ - socket.on('account/register', (data) => { + socket.on(Endpoints.Register, (data) => { register(socket, data) }); - socket.on('account/login', (data) => { + socket.on(Endpoints.Login, (data) => { login(socket, data) }); } \ No newline at end of file diff --git a/Account/users.ts b/Account/users.ts index 5054a6b..1244e0a 100644 --- a/Account/users.ts +++ b/Account/users.ts @@ -1,56 +1,25 @@ -import { game } from "../game.js"; import { userData } from "../Classes/userData.js"; +import { DatabaseController } from "../Database/dbcontroller.js"; export class users{ - static createUser(login, password){ - if (game.accountsDB.find(u=>u.login == login) != null){ - console.log(`User ${login} alread exists`); - return null; - } + static async createUser(db: DatabaseController, login : string, password : string){ + await db.run('INSERT INTO users (login, password) VALUES (?, ?)', [login, password]); + return await this.readUser(db, login, password) + } - var user = new userData(game.accountsDB.length, login, password); - game.accountsDB.push(user); + static async readUser(db: DatabaseController, login : string, password : string): Promise{ + let user = await db.select(`SELECT * FROM users WHERE login = ? AND password = ?`, [login, password]) + if (user.length > 0){ + let row = user[0] + return new userData({...row}) + } + else{ + return null + } + } + + static async readUserID(db: DatabaseController, id : number){ + let user = await db.select(`SELECT * FROM users WHERE id = ?`, [id]) return user; } - - static readUser(login, password){ - let user = game.accountsDB.find(u=>u.login == login && u.password == password) - if(user != null){ - return user; - } - return null; - } - - static readUserID(id : number){ - let user = game.accountsDB.filter(u=>u.id == id)[0]; - return user; - } - - static updateUser(userNew : userData){ - let user = this.readUserID(userNew.id); - let sum = Math.floor(Math.random() * 99999); - while(sum == userNew.checksum){ - sum = Math.floor(Math.random() * 99999); - } - userNew.checksum = sum; - game.accountsDB[game.accountsDB.indexOf(user)] = userNew; - } - - static saveUsers(fs){ - game.accountsDB.forEach(user => {user.save(fs)}); - } - - static loadUsers(fs){ - fs.mkdirSync(`Database/Users/`, { recursive: true }) - fs.readdir(`Database/Users/`, (err, files) => { - files.forEach(file => { - fs.readFile(`Database/Users/${file}`, (err, data) => { - if (err) throw err; - let user : userData = Object.assign(new userData(-1,"",""), JSON.parse(data)); - game.accountsDB.push(user); - console.log(`Loaded ${user.login}`); - }); - }); - }); - } } \ No newline at end of file diff --git a/Characters/characters.ts b/Characters/characters.ts new file mode 100644 index 0000000..f555437 --- /dev/null +++ b/Characters/characters.ts @@ -0,0 +1,29 @@ +import { characterData } from "../Classes/characterData.js"; +import { DatabaseController } from "../Database/dbcontroller.js"; + +export class characters{ + static async createCharacter(db: DatabaseController, userId : number){ + await db.run('INSERT INTO characters (user_id) VALUES (?)', [userId]); + return await this.readCharacter(db, userId) + } + + static async readCharacter(db: DatabaseController, userId : number): Promise{ + let player = await db.select(`SELECT * FROM characters WHERE user_id = ? LIMIT 1`, [userId]) + if (player.length > 0){ + let row = player[0] + return new characterData({ + ...row, + inventory: row.inventory ? JSON.parse(row.inventory) : undefined, + questBook: row.questBook ? JSON.parse(row.questBook) : undefined, + }) + } + else{ + return null + } + } + + static async savePlayer(db: DatabaseController, data: characterData){ + await db.run(`UPDATE characters SET (inventory, questBook) VALUES (?,?) WHERE id = ?`, + [JSON.stringify(data.inventory), JSON.stringify(data.questBook), data.id]) + } +} \ No newline at end of file diff --git a/Classes/Incoming/levelUpdateClient.ts b/Classes/Incoming/levelUpdateClient.ts index 389a0a9..10dd78e 100644 --- a/Classes/Incoming/levelUpdateClient.ts +++ b/Classes/Incoming/levelUpdateClient.ts @@ -1,5 +1,5 @@ -import { playerData } from "../playerData.js"; +import { characterData } from "../characterData.js"; export class levelUpdateClient{ - player : playerData + player : characterData } \ No newline at end of file diff --git a/Classes/Incoming/levelUpdateHost.ts b/Classes/Incoming/levelUpdateHost.ts index a2ddf8f..c8e837f 100644 --- a/Classes/Incoming/levelUpdateHost.ts +++ b/Classes/Incoming/levelUpdateHost.ts @@ -1,7 +1,7 @@ import { levelState } from "../levelState.js"; -import { playerData } from "../playerData.js"; +import { characterData } from "../characterData.js"; export class levelUpdateHost{ - player : playerData + player : characterData room : levelState } \ No newline at end of file diff --git a/Classes/Incoming/lobbyJoin.ts b/Classes/Incoming/lobbyJoin.ts index 4db9f27..e7456ae 100644 --- a/Classes/Incoming/lobbyJoin.ts +++ b/Classes/Incoming/lobbyJoin.ts @@ -1,5 +1,5 @@ -import { playerData } from "../playerData.js"; +import { characterData } from "../characterData.js"; export class lobbyJoin{ - player : playerData + player : characterData } \ No newline at end of file diff --git a/Classes/Outgoing/accountResponses.ts b/Classes/Outgoing/accountResponses.ts new file mode 100644 index 0000000..7ad92ad --- /dev/null +++ b/Classes/Outgoing/accountResponses.ts @@ -0,0 +1,20 @@ +import { characterData } from "../characterData.js"; +import { userData } from "../userData.js"; + +export class loginResponse{ + result : boolean + userData : userData + playerData : characterData + + constructor(user : userData, player : characterData){ + if (!user || !player){ + this.result = false; + this.userData = this.playerData = null; + } + else{ + this.result = true; + this.userData = user.makeSafe(); + this.playerData = player; + } + } +} \ No newline at end of file diff --git a/Classes/Outgoing/characterDataPartial.ts b/Classes/Outgoing/characterDataPartial.ts new file mode 100644 index 0000000..71ea120 --- /dev/null +++ b/Classes/Outgoing/characterDataPartial.ts @@ -0,0 +1,40 @@ +import { characterData } from "../characterData.js" +import { enemyDamageInfo } from "../enemyDamageInfo.js" +import { physicsObject } from "../physicsObject.js" +import { playerInventory } from "../playerInventory.js" + +export class characterDataStart{ + id : number + characterId : number + rigidbody : physicsObject = new physicsObject() + + constructor(data : characterData){ + this.id = data.id + this.characterId = data.characterId + this.rigidbody = physicsObject.characterOnly(data.rigidbody) + } +} + +export class characterDataUpdate{ + id : number + rigidbody : physicsObject = new physicsObject() + damageInfo : enemyDamageInfo[] = [] + + constructor(data : characterData){ + this.id = data.id + this.rigidbody = physicsObject.characterOnly(data.rigidbody) + if(data.damageInfo.length > 0){ + this.damageInfo = data.damageInfo + } + } +} + +export class characterDataInventory{ + id : number + inventory : playerInventory = new playerInventory() + + constructor(data : characterData){ + this.id = data.id + this.inventory = data.inventory + } +} \ No newline at end of file diff --git a/Classes/Outgoing/enemyDataPartial.ts b/Classes/Outgoing/enemyDataPartial.ts new file mode 100644 index 0000000..69253a6 --- /dev/null +++ b/Classes/Outgoing/enemyDataPartial.ts @@ -0,0 +1,17 @@ +import { enemyData } from "../enemyData.js"; +import { Stat } from "../itemData.js"; +import { physicsObject } from "../physicsObject.js"; + +export class enemyDataUpdate{ + id : number + templateId : number + rigidbody : physicsObject + stats : Stat[] = [] + + constructor(data : enemyData){ + this.id = data.id + this.templateId = data.templateId + this.rigidbody = physicsObject.characterOnly(data.rigidbody) + this.stats = data.stats + } +} \ No newline at end of file diff --git a/Classes/Outgoing/levelStatePartial.ts b/Classes/Outgoing/levelStatePartial.ts new file mode 100644 index 0000000..46a81db --- /dev/null +++ b/Classes/Outgoing/levelStatePartial.ts @@ -0,0 +1,63 @@ +import { enemyData } from "../enemyData.js" +import { levelState } from "../levelState.js" +import { propData } from "../propData.js" +import { characterDataStart, characterDataUpdate } from "./characterDataPartial.js" +import { enemyDataUpdate } from "./enemyDataPartial.js" +import { propDataStart, propDataUpdate } from "./propDataPartial.js" + +export class levelStateStart{ + id : string + seed : number = -1 + hostId : number = -1 + completed : boolean = false + isDungeon : boolean = false + enemies : enemyDataUpdate[] = [] + objects : propDataStart[] = [] + players : characterDataStart[] = [] + + constructor(data : levelState){ + this.id = data.id + this.seed = data.seed + this.hostId = data.hostId + this.completed = data.completed + this.isDungeon = data.isDungeon + this.enemies = data.enemies.map(e => e.copyStart()) + this.objects = data.objects.map(e => e.copyStart()) + this.players = data.players.map(pl=> pl.copyStart()) + } +} + +export class levelStateUpdate{ + id : string + seed : number = -1 + hostId : number = -1 + completed : boolean = false + isDungeon : boolean = false + enemies : enemyDataUpdate[] = [] + objects : propDataUpdate[] = [] + players : characterDataUpdate[] = [] + + constructor(data : levelState){ + this.id = data.id + this.seed = data.seed + this.hostId = data.hostId + this.completed = data.completed + this.enemies = data.enemies.map(e => e.copyUpdate()) + this.objects = data.objects.map(e => e.copyUpdate()) + this.players = data.players.map(pl=> pl.copyUpdate()) + } +} + +export class levelStateState{ + id : string + seed : number = -1 + hostId : number = -1 + completed : boolean = false + + constructor(data : levelState){ + this.id = data.id + this.seed = data.seed + this.hostId = data.hostId + this.completed = data.completed + } +} diff --git a/Classes/Outgoing/lobbyStatePartial.ts b/Classes/Outgoing/lobbyStatePartial.ts new file mode 100644 index 0000000..86ebae7 --- /dev/null +++ b/Classes/Outgoing/lobbyStatePartial.ts @@ -0,0 +1,16 @@ +import { dungeonData } from "../dungeonData.js"; +import { levelState } from "../levelState.js"; +import { lobbyState } from "../lobbyState.js"; +import { characterDataUpdate } from "./characterDataPartial.js"; + +export class lobbyStateLight{ + activeUsers : characterDataUpdate[] = [] + rooms : levelState[] = [] + dungeons : dungeonData[] = [] + + constructor(data : lobbyState){ + this.activeUsers = data.activeUsers.map(u=>u.character.copyUpdate()) + this.rooms = data.rooms + this.dungeons = data.dungeons + } +} \ No newline at end of file diff --git a/Classes/Outgoing/propDataPartial.ts b/Classes/Outgoing/propDataPartial.ts new file mode 100644 index 0000000..6593afc --- /dev/null +++ b/Classes/Outgoing/propDataPartial.ts @@ -0,0 +1,28 @@ +import { physicsObject } from "../physicsObject.js" +import { propData } from "../propData.js" + +export class propDataStart{ + id : number + templateId : number + rigidbody : physicsObject + components : any + + constructor(data : propData) { + this.id = data.id + this.templateId = data.templateId + this.rigidbody = physicsObject.copyStart(data.rigidbody) + this.components = data.components + } +} + +export class propDataUpdate{ + id : number + rigidbody : physicsObject + components : any + + constructor(data : propData) { + this.id = data.id + this.rigidbody = physicsObject.copyUpdate(data.rigidbody) + this.components = data.components + } +} \ No newline at end of file diff --git a/Classes/Outgoing/roomChangeResponse.ts b/Classes/Outgoing/roomChangeResponse.ts new file mode 100644 index 0000000..38ee9fc --- /dev/null +++ b/Classes/Outgoing/roomChangeResponse.ts @@ -0,0 +1,8 @@ +import { characterDataUpdate } from "./characterDataPartial.js" +import { levelStateStart, levelStateState } from "./levelStatePartial.js" + +export class roomChangeResponse{ + player : characterDataUpdate + newRoom : levelStateStart + previousRoom : levelStateState +} \ No newline at end of file diff --git a/Classes/Outgoing/userDataPartial.ts b/Classes/Outgoing/userDataPartial.ts new file mode 100644 index 0000000..2a864bf --- /dev/null +++ b/Classes/Outgoing/userDataPartial.ts @@ -0,0 +1,10 @@ +import { userData } from "../userData.js"; + +export class userDataSafe{ + id: number; + login: string; + + constructor(data : userData){ + Object.assign(this, data); + } +} \ No newline at end of file diff --git a/Classes/playerData.ts b/Classes/characterData.ts similarity index 52% rename from Classes/playerData.ts rename to Classes/characterData.ts index 159cf36..245e31f 100644 --- a/Classes/playerData.ts +++ b/Classes/characterData.ts @@ -1,9 +1,10 @@ import { enemyDamageInfo } from "./enemyDamageInfo.js"; +import { characterDataInventory, characterDataStart, characterDataUpdate } from "./Outgoing/characterDataPartial.js"; import { physicsObject } from "./physicsObject.js"; import { playerInventory } from "./playerInventory.js"; import { questBook } from "./questBook.js"; -export class playerData{ +export class characterData{ id : number level : number = 1 room : string = "0_0" @@ -13,50 +14,36 @@ export class playerData{ questBook : questBook = new questBook() damageInfo : enemyDamageInfo[] = [] - constructor(init?: Partial) { + constructor(init?: Partial) { Object.assign(this, init); this.questBook = new questBook(this.questBook) - } + this.inventory = new playerInventory(this.inventory) + } copyStart(){ - let player : any = {} - player.id = this.id - player.characterId = this.characterId - player.rigidbody = physicsObject.characterOnly(this.rigidbody) - return player + return new characterDataStart(this) } copyUpdate(){ - let player : any = {} - player.id = this.id - if(this.rigidbody == null){ - console.log(this) - } - player.rigidbody = physicsObject.characterOnly(this.rigidbody) - if(this.damageInfo.length > 0) player.damageInfo = this.damageInfo - return player + return new characterDataUpdate(this) } copyInventory(){ - let player : any = {} - player.id = this.id - player.inventory = this.inventory - return player + return new characterDataInventory(this) } getItemById(id : number){ let item = this.inventory.items.find(i=>i.id == id) return item } - + + resetDamageInfo(){ + this.damageInfo = [] + } + validateEquipment(){ if(this.inventory.equipment.length < 3){ this.inventory.equipment = [-1, -1, -1] } } - - save(fs){ - let data = JSON.stringify(this, null, 2); - fs.writeFileSync(`Database/Players/${this.id}.json`, data); - } } \ No newline at end of file diff --git a/Classes/enemyData.ts b/Classes/enemyData.ts index 2267cfe..bf76379 100644 --- a/Classes/enemyData.ts +++ b/Classes/enemyData.ts @@ -1,4 +1,5 @@ import { Stat } from "./itemData.js" +import { enemyDataUpdate } from "./Outgoing/enemyDataPartial.js" import { physicsObject } from "./physicsObject.js" export class enemyData{ @@ -7,21 +8,15 @@ export class enemyData{ rigidbody : physicsObject stats : Stat[] = [] - static copyStart(e: enemyData): any { - let enemy : any = {} - enemy.id = e.id - enemy.templateId = e.templateId - enemy.rigidbody = physicsObject.characterOnly(e.rigidbody) - enemy.stats = e.stats - return enemy + constructor(init?: Partial){ + Object.assign(this, init); + } + + copyStart() { + return new enemyDataUpdate(this) } - static copyUpdate(e: enemyData): any { - let enemy : any = {} - enemy.id = e.id - enemy.templateId = e.templateId - enemy.rigidbody = physicsObject.characterOnly(e.rigidbody) - enemy.stats = e.stats - return enemy + copyUpdate() { + return new enemyDataUpdate(this) } } \ No newline at end of file diff --git a/Classes/levelState.ts b/Classes/levelState.ts index 8b547ac..8a3c582 100644 --- a/Classes/levelState.ts +++ b/Classes/levelState.ts @@ -1,6 +1,7 @@ import { enemyData } from "./enemyData.js"; -import { playerData } from "./playerData.js"; +import { characterData } from "./characterData.js"; import { propData } from "./propData.js"; +import { levelStateStart, levelStateState as levelStateInfo, levelStateUpdate } from "./Outgoing/levelStatePartial.js"; export class levelState{ id : string @@ -10,7 +11,7 @@ export class levelState{ isDungeon : boolean = false enemies : enemyData[] = [] objects : propData[] = [] - players : playerData[] = [] + players : characterData[] = [] getRandomInt(max) { return Math.floor(Math.random() * max); @@ -24,37 +25,15 @@ export class levelState{ } copyStart(){ - let level : any = {} - level.id = this.id - level.seed = this.seed - level.hostId = this.hostId - level.completed = this.completed - level.isDungeon = this.isDungeon - if(this.enemies.length > 0) level.enemies = this.enemies.map(e => enemyData.copyStart(e)) - if(this.objects.length > 0) level.objects = this.objects.map(e => propData.copyPropStart(e)) - if(this.players.length > 0) level.players = this.players.map(pl=> pl.copyUpdate()) - return level + return new levelStateStart(this) } copyUpdate(){ - let level : any = {} - level.id = this.id - level.seed = this.seed - level.hostId = this.hostId - level.completed = this.completed - if(this.enemies.length > 0) level.enemies = this.enemies.map(e => enemyData.copyUpdate(e)) - if(this.objects.length > 0) level.objects = this.objects.map(e => propData.copyPropUpdate(e)) - if(this.players.length > 0) level.players = this.players.map(pl=> pl.copyUpdate()) - return level + return new levelStateUpdate(this) } copyState(){ - let level : any = {} - level.id = this.id - level.seed = this.seed - level.hostId = this.hostId - level.completed = this.completed - return level + return new levelStateInfo(this) } isHostValid(){ @@ -67,7 +46,7 @@ export class levelState{ return true } - addPlayer(player : playerData) : boolean{ + addPlayer(player : characterData) : boolean{ let playerIdx = this.players.findIndex(p=>p.id==player.id) if(playerIdx != -1) return false @@ -80,13 +59,10 @@ export class levelState{ return true } - removePlayer(id) : boolean{ - let playerIdx = this.players.findIndex(p=>p.id==id) - if(playerIdx == -1) return false - - this.players.splice(playerIdx,1) + removePlayer(player : characterData) : boolean{ + this.players = this.players.filter(p=> p !== player) - if(this.hostId == id){ + if(this.hostId == player.id){ if(this.players.length > 0){ this.hostId = this.players[0].id } diff --git a/Classes/lobbyState.ts b/Classes/lobbyState.ts index 5a73f67..5e34ae5 100644 --- a/Classes/lobbyState.ts +++ b/Classes/lobbyState.ts @@ -1,55 +1,32 @@ -import { playerData } from "../Classes/playerData.js"; +import { Socket } from "socket.io"; +import { characterData } from "./characterData.js"; import { dungeonData } from "./dungeonData.js"; import { levelState } from "./levelState.js"; -import { userData } from "./userData.js"; +import { lobbyStateLight } from "./Outgoing/lobbyStatePartial.js"; export class lobbyState{ - users : userData[] = []; - players : playerData[] = []; + activeUsers : Socket[] = [] rooms : levelState[] = [] dungeons : dungeonData[] = [] copyLight(){ - let lobby = Object.assign({}, this); - lobby.players = [] - lobby.users = [] - for (let i = 0; i < this.players.length; i++) { - lobby.players.push(this.players[i].copyUpdate()); - } - lobby.rooms = this.rooms - lobby.dungeons = this.dungeons - return lobby + return new lobbyStateLight(this) } - addUser(userData, playerData){ - let uIdx = this.users.findIndex(u=>u.id == userData.id) - let pIdx = this.players.findIndex(u=>u.id == playerData.id) - if(uIdx != -1 || pIdx != -1){ - console.log("User " + userData.login + " is already in the game!") + addUser(socket : Socket){ + let uIdx = this.activeUsers.findIndex(u=>u === socket) + if(uIdx != -1){ + console.log("User " + socket.user.login + " is already in the game!") return false; } - this.users.push(userData) - this.players.push(playerData) + this.activeUsers.push(socket) return true } - removeUser(id){ - let idx = this.users.findIndex(u=>u.id == id) - if(idx != -1){ - this.users.splice(idx, 1) - } - - idx = this.players.findIndex(u=>u.id == id) - if(idx != -1){ - let player = this.players[idx] - this.players.splice(idx, 1) - this.roomExit(player.room, player) - } - } - - findPlayer(id: number){ - return this.players.find(p=>p.id == id) + removeUser(socket : Socket){ + this.roomExit(socket.character.room, socket.character) + this.activeUsers = this.activeUsers.filter(u=>u !== socket) } getDungeonRoot(name){ @@ -75,13 +52,17 @@ export class lobbyState{ return room } + removeRoom(room : levelState){ + this.rooms = this.rooms.filter(r => r !== room) + } + createRoom(id : string, host : number){ let room = new levelState(id, host) this.rooms.push(room) return room } - roomEnter(targetRoom : levelState, player: playerData){ + roomEnter(targetRoom : levelState, player: characterData){ if(!targetRoom.isDungeon){ let room = this.getRoom(targetRoom.id, true) @@ -112,19 +93,17 @@ export class lobbyState{ return null } - roomExit(roomId : string, player: playerData){ + roomExit(roomId : string, player: characterData){ let room = this.getRoom(roomId, false) if(room != null){ - - if(room.removePlayer(player.id)){ + if(room.removePlayer(player)){ if(room.isDungeon){ let dungeon = this.getDungeon(this.getDungeonRoot(roomId), false) dungeon.playerCount -= 1; this.tryRemoveDungeon(room.id) } else if(room.hostId == -1){ - let roomIdx = this.rooms.indexOf(room) - this.rooms.splice(roomIdx, 1) + this.removeRoom(room) } } @@ -143,8 +122,7 @@ export class lobbyState{ if(dungeon.playerCount == 0){ this.dungeons.splice(dungeonIdx, 1) dungeon.rooms.forEach(room=>{ - let roomIdx = this.rooms.findIndex(r=>r.id == room.id) - this.rooms.splice(roomIdx, 1) + this.removeRoom(room) }) } diff --git a/Classes/loginResponse.ts b/Classes/loginResponse.ts deleted file mode 100644 index 66b85f4..0000000 --- a/Classes/loginResponse.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { playerData } from "./playerData.js" -import { userData } from "./userData.js" - -export class loginResponse{ - result : boolean - userData : userData - playerData : playerData - - constructor(result : boolean, user : userData, player : playerData){ - this.result = result; - if(result){ - this.userData = userData.makeSafe(user); - this.playerData = player; - } - } -} \ No newline at end of file diff --git a/Classes/playerInventory.ts b/Classes/playerInventory.ts index 5136e9a..7cda930 100644 --- a/Classes/playerInventory.ts +++ b/Classes/playerInventory.ts @@ -4,4 +4,8 @@ export class playerInventory{ weapon : number = -1 equipment : number[] = [-1,-1,-1] items : itemData[] = [] + + constructor(init?: Partial) { + Object.assign(this, init); + } } \ No newline at end of file diff --git a/Classes/propData.ts b/Classes/propData.ts index a512f60..d4832d5 100644 --- a/Classes/propData.ts +++ b/Classes/propData.ts @@ -1,3 +1,4 @@ +import { propDataStart, propDataUpdate } from "./Outgoing/propDataPartial.js" import { physicsObject } from "./physicsObject.js" export class propData{ @@ -6,21 +7,11 @@ export class propData{ rigidbody : physicsObject components : any - static copyPropStart(o: propData) { - let pObject = Object.assign({}, o) - pObject.rigidbody = physicsObject.copyStart(o.rigidbody) - return pObject + copyStart() { + return new propDataStart(this) } - static copyPropUpdate(o: propData) { - let pObject : any = {} - pObject.id = o.id - if(!physicsObject.isKinematic(o.rigidbody)){ - pObject.rigidbody = physicsObject.copyUpdate(o.rigidbody) - } - if(o.components != null){ - pObject.components = o.components - } - return pObject + copyUpdate() { + return new propDataUpdate(this) } } \ No newline at end of file diff --git a/Classes/roomChangeResponse.ts b/Classes/roomChangeResponse.ts deleted file mode 100644 index 437a942..0000000 --- a/Classes/roomChangeResponse.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { levelState } from "./levelState.js" -import { playerData } from "./playerData.js" - -export class roomChangeResponse{ - player : playerData - newRoom : levelState - previousRoom : levelState -} \ No newline at end of file diff --git a/Classes/userData.ts b/Classes/userData.ts index efe709b..825e3ca 100644 --- a/Classes/userData.ts +++ b/Classes/userData.ts @@ -4,22 +4,14 @@ export class userData{ login: string; password: string; - constructor(id:number, login:string, password:string){ - this.id = id; - this.login = login; - this.password = password; - this.checksum = 0; + constructor(init?: Partial){ + Object.assign(this, init); } - static makeSafe(user : userData){ - let safeUser : any = Object.assign({}, user); + makeSafe() : userData{ + let safeUser : userData = Object.assign({}, this); delete safeUser.password delete safeUser.checksum return safeUser } - - save(fs){ - let data = JSON.stringify(this, null, 2); - fs.writeFileSync(`Database/Users/${this.id}_${this.login}.json`, data); - } } \ No newline at end of file diff --git a/Database/dbcontroller.ts b/Database/dbcontroller.ts index f4cd8bd..aa04de7 100644 --- a/Database/dbcontroller.ts +++ b/Database/dbcontroller.ts @@ -1,11 +1,78 @@ -import Database from 'better-sqlite3'; -import { open } from 'sqlite' +import sqlite3 from 'sqlite3' +import { open, Database } from 'sqlite' -// this is a top-level await -(async () => { - // open the database - const db = await open({ - filename: '/tmp/database.db', - driver: Database - }) -})() \ No newline at end of file +export class DatabaseController { + private db: Database; + + private constructor(db: Database) { + this.db = db; + } + + static async create(filename = ':memory:'): Promise { + const db = await open({ + filename, + driver: sqlite3.Database + }); + let dbController = new DatabaseController(db); + dbController.basicSetup() + return dbController; + } + + async basicSetup(){ + await this.db.run(`CREATE TABLE IF NOT EXISTS characters ( + id INTEGER PRIMARY KEY, + user_id INTEGER NOT NULL UNIQUE, + level INTEGER DEFAULT 0, + inventory TEXT, + questBook TEXT + );`) + await this.db.run(`CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY, + login TEXT NOT NULL UNIQUE, + password TEXT NOT NULL + );`) + } + + async select(sql: string, params?: any[]): Promise { + const rows: unknown = await this.db.all(sql, params); + return Array.isArray(rows) ? (rows as T[]) : []; + } + + async get(sql: string, params?: any[]): Promise { + return this.db.get(sql, params); + } + + async run(sql: string, params?: any[]): Promise { + await this.db.run(sql, params); + } + + async close(): Promise { + await this.db.close(); + } +} + +// Usage example (you can put this in another file): + +// import { DatabaseController } from './db/DatabaseController'; + +// (async () => { +// const db = await DatabaseController.create('mydb.sqlite3'); + +// await db.run(`CREATE TABLE IF NOT EXISTS players ( +// id INTEGER PRIMARY KEY, +// level INTEGER NOT NULL, +// inventory TEXT, +// questBook TEXT +// );`) +// await db.run(`CREATE TABLE IF NOT EXISTS users ( +// id INTEGER PRIMARY KEY, +// login TEXT NOT NULL, +// password TEXT NOT NULL +// );`) + +// await db.run('CREATE TABLE IF NOT EXISTS friends (id INTEGER PRIMARY KEY, name TEXT)'); +// await db.run('INSERT INTO friends (name) VALUES (?)', ['Silver Fox']); +// const friends = await db.select('SELECT * FROM friends'); +// console.log(friends); // [{ id: 1, name: 'Silver Fox' }] +// await db.close(); +// })(); diff --git a/Items/_updateInventory.ts b/Items/_updateInventory.ts index e677110..3d07534 100644 --- a/Items/_updateInventory.ts +++ b/Items/_updateInventory.ts @@ -1,14 +1,13 @@ import { inventoryChange } from "../Classes/Incoming/inventoryChange.js"; import { itemData } from "../Classes/itemData.js"; -import { playerData } from "../Classes/playerData.js"; - -export function updateInventory(socket, data){ - if(!socket.hasOwnProperty("player")) return; +import { characterData } from "../Classes/characterData.js"; +import { Socket } from "socket.io"; +export function updateInventory(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); let data1 : inventoryChange[] = JSON.parse(buff.toString('utf-8')); - let player : playerData = socket.player + let player : characterData = socket.character let inventory = player.inventory data1.forEach(change=>{ diff --git a/Items/itemSocket.ts b/Items/itemSocket.ts index 9dc967c..6416bd4 100644 --- a/Items/itemSocket.ts +++ b/Items/itemSocket.ts @@ -1,7 +1,8 @@ +import { Endpoints } from "../endpoints.js"; import { updateInventory } from "./_updateInventory.js"; export function registerItemCallbacks(socket){ - socket.on('item/updateInventory', (data) => { + socket.on(Endpoints.UpdateInventory, (data) => { updateInventory(socket, data) }); } \ No newline at end of file diff --git a/Level/_clear.ts b/Level/_clear.ts index 3e4020b..1689ce3 100644 --- a/Level/_clear.ts +++ b/Level/_clear.ts @@ -1,11 +1,10 @@ +import { Endpoints } from "../endpoints.js"; import { game } from "../game.js"; export function clear(socket, data){ - if(!socket.hasOwnProperty("player")) return; - let buff = Buffer.from(data, 'base64'); let data1 : string = JSON.parse(buff.toString('utf-8')); let room = game.lobbyState.roomComplete(data1) - game.socketIO.emit("level/cleared", JSON.stringify(room.copyState())) + game.socketIO.emit(Endpoints.LevelCleared, JSON.stringify(room.copyState())) } \ No newline at end of file diff --git a/Level/_enter.ts b/Level/_enter.ts index 98f1d91..576956c 100644 --- a/Level/_enter.ts +++ b/Level/_enter.ts @@ -1,30 +1,29 @@ import { game } from "../game.js"; -import { playerData } from "../Classes/playerData.js"; -import { roomChangeResponse } from "../Classes/roomChangeResponse.js"; +import { characterData } from "../Classes/characterData.js"; +import { roomChangeResponse } from "../Classes/Outgoing/roomChangeResponse.js"; import { levelEnter } from "../Classes/Incoming/levelEnter.js"; +import { Socket } from "socket.io"; +import { Endpoints } from "../endpoints.js"; -export function enter(socket, data){ - if(!socket.hasOwnProperty("player")) return; - +export function enter(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); let data1 : levelEnter = JSON.parse(buff.toString('utf-8')); - let player : playerData = socket.player + let character : characterData = socket.character socket.join(data1.targetRoom.id) - let newRoom = game.lobbyState.roomEnter(data1.targetRoom, player) - player.room = newRoom.id + let newRoom = game.lobbyState.roomEnter(data1.targetRoom, character) + character.room = newRoom.id socket.leave(data1.previousRoom.id) - let oldRoom = game.lobbyState.roomExit(data1.previousRoom.id, player) + let oldRoom = game.lobbyState.roomExit(data1.previousRoom.id, character) let data2 = new roomChangeResponse() - data2.player = player.copyUpdate() + data2.player = character.copyUpdate() data2.newRoom = newRoom.copyStart() data2.previousRoom = oldRoom.copyState() + + let json = JSON.stringify(data2) - socket.emit("level/entered", JSON.stringify(data2)) - - data2.newRoom = newRoom.copyState() - - socket.broadcast.emit("level/entered", JSON.stringify(data2)) + socket.emit(Endpoints.LevelEntered, json) + socket.broadcast.emit(Endpoints.LevelEntered, json) } \ No newline at end of file diff --git a/Level/_playerUpdate.ts b/Level/_playerUpdate.ts index 38394ae..a2a3977 100644 --- a/Level/_playerUpdate.ts +++ b/Level/_playerUpdate.ts @@ -1,19 +1,20 @@ +import { Socket } from "socket.io"; import { levelUpdateClient } from "../Classes/Incoming/levelUpdateClient.js"; -import { playerData } from "../Classes/playerData.js"; +import { characterData } from "../Classes/characterData.js"; -export function playerUpdate(socket, data){ - if(!socket.hasOwnProperty("user")) return; +export function playerUpdate(socket : Socket, data){ + if(socket.user != null) return; let buff = Buffer.from(data, 'base64'); let data1 : levelUpdateClient = JSON.parse(buff.toString('utf-8')); - let player : playerData = socket.player - if(player == null){ + let character : characterData = socket.character + if(character == null){ console.log("Error! Player not spawned!") return } - player.rigidbody = data1.player.rigidbody + character.rigidbody = data1.player.rigidbody if(data1.player.hasOwnProperty("damageInfo")) - player.damageInfo = player.damageInfo.concat(data1.player.damageInfo) + character.damageInfo = character.damageInfo.concat(data1.player.damageInfo) } \ No newline at end of file diff --git a/Level/_projectile.ts b/Level/_projectile.ts index 632db3d..c404f4c 100644 --- a/Level/_projectile.ts +++ b/Level/_projectile.ts @@ -1,10 +1,12 @@ -import { playerData } from "../Classes/playerData.js"; +import { Socket } from "socket.io"; +import { characterData } from "../Classes/characterData.js"; +import { Endpoints } from "../endpoints.js"; -export function projectile(socket, data){ +export function projectile(socket : Socket, data){ if(!socket.hasOwnProperty("user")) return; let buff = Buffer.from(data, 'base64'); - let player : playerData = socket.player + let character : characterData = socket.character - socket.to(player.room).emit('level/projectile', buff.toString('utf-8')) + socket.to(character.room).emit(Endpoints.LevelProjectile, buff.toString('utf-8')) } \ No newline at end of file diff --git a/Level/_update.ts b/Level/_update.ts index 3ab37e6..6414a56 100644 --- a/Level/_update.ts +++ b/Level/_update.ts @@ -1,16 +1,15 @@ +import { Socket } from "socket.io"; import { levelUpdateHost } from "../Classes/Incoming/levelUpdateHost.js"; -import { playerData } from "../Classes/playerData.js"; +import { characterData } from "../Classes/characterData.js"; import { game } from "../game.js"; -export function update(socket, data){ - if(!socket.hasOwnProperty("player")) return; - +export function update(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); let data1 : levelUpdateHost = JSON.parse(buff.toString('utf-8')); - let player : playerData = socket.player + let character : characterData = socket.character let room = game.lobbyState.rooms.find(l=>l.id == data1.room.id) - if (room == null || room.hostId != player.id){ + if (room == null || room.hostId != character.id){ return } @@ -21,7 +20,7 @@ export function update(socket, data){ data1.room.enemies = [] } - player.rigidbody = data1.player.rigidbody + character.rigidbody = data1.player.rigidbody room.enemies = data1.room.enemies room.objects = data1.room.objects diff --git a/Level/levelSocket.ts b/Level/levelSocket.ts index 1d46fef..6de44c8 100644 --- a/Level/levelSocket.ts +++ b/Level/levelSocket.ts @@ -1,3 +1,4 @@ +import { Endpoints } from "../endpoints.js"; import { clear } from "./_clear.js"; import { enter } from "./_enter.js"; import { playerUpdate } from "./_playerUpdate.js"; @@ -5,23 +6,23 @@ import { projectile } from "./_projectile.js"; import { update } from "./_update.js"; export function registerLevelCallbacks(socket){ - socket.on('level/enter', (data) => { + socket.on(Endpoints.LevelEnter, (data) => { enter(socket, data) }); - socket.on('level/cleared', (data) => { + socket.on(Endpoints.LevelCleared, (data) => { clear(socket, data) }); - socket.on('level/update', (data) => { + socket.on(Endpoints.LevelUpdate, (data) => { update(socket, data) }); - socket.on('level/playerUpdate', (data) => { + socket.on(Endpoints.LevelPlayerUpdate, (data) => { playerUpdate(socket, data) }); - socket.on('level/projectile', (data) => { + socket.on(Endpoints.LevelProjectile, (data) => { projectile(socket, data) }); -} \ No newline at end of file +} diff --git a/Lobby/_loadoutChanged.ts b/Lobby/_loadoutChanged.ts index e30303b..b3bca42 100644 --- a/Lobby/_loadoutChanged.ts +++ b/Lobby/_loadoutChanged.ts @@ -1,16 +1,16 @@ -import { playerData } from "../Classes/playerData.js"; +import { Socket } from "socket.io"; +import { characterData } from "../Classes/characterData.js"; import { game } from "../game.js"; +import { Endpoints } from "../endpoints.js"; -export function loadoutChanged(socket, data){ - if(!socket.hasOwnProperty("player")) return; - +export function loadoutChanged(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); - let data1 : playerData = JSON.parse(buff.toString('utf-8')); + let data1 : characterData = JSON.parse(buff.toString('utf-8')); - let player : playerData = socket.player - player.inventory.weapon = data1.inventory.weapon - player.inventory.equipment = data1.inventory.equipment - player.validateEquipment() + let character : characterData = socket.character + character.inventory.weapon = data1.inventory.weapon + character.inventory.equipment = data1.inventory.equipment + character.validateEquipment() - socket.emit("lobby/loadoutChanged", JSON.stringify(player.copyInventory())) + socket.emit(Endpoints.LoadoutChanged, JSON.stringify(character.copyInventory())) } \ No newline at end of file diff --git a/Lobby/_playerJoin.ts b/Lobby/_playerJoin.ts index fc162c2..f6cbeb4 100644 --- a/Lobby/_playerJoin.ts +++ b/Lobby/_playerJoin.ts @@ -1,46 +1,50 @@ import { lobbyJoin } from "../Classes/Incoming/lobbyJoin.js"; import { levelState } from "../Classes/levelState.js"; import { lobbyMessage } from "../Classes/lobbyMessage.js"; -import { playerData } from "../Classes/playerData.js"; +import { characterData } from "../Classes/characterData.js"; import { userData } from "../Classes/userData.js"; import { game } from "../game.js"; +import { Socket } from "socket.io"; +import { Endpoints } from "../endpoints.js"; -export function playerJoin(socket, data){ - if(!socket.hasOwnProperty("player")) return; - +export function playerJoin(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); let data1 : lobbyJoin = JSON.parse(buff.toString('utf-8')); - let player : playerData = socket.player + let character : characterData = socket.character - player.room = "0_0" - player.characterId = data1.player.characterId - game.lobbyState.addUser(socket.user, player) - let spawnRoom = game.lobbyState.roomEnter(new levelState("0_0", -1), player) + console.log(character) + + character.room = "0_0" + character.characterId = data1.player.characterId + game.lobbyState.addUser(socket) + let spawnRoom = game.lobbyState.roomEnter(new levelState("0_0", -1), character) socket.join("0_0") let newUser = { - users:[userData.makeSafe(socket.user)], - players:[player.copyStart()], + users:[socket.user.makeSafe()], + players:[character.copyStart()], rooms:[] }; let existingUsers = { - users:game.lobbyState.users.map(u=> userData.makeSafe(u)), - players:game.lobbyState.players.map(p=>p.copyStart()), - rooms:[] + users:game.lobbyState.activeUsers.map(u=> u.user.makeSafe()), + players:game.lobbyState.activeUsers.map(p=>p.character.copyStart()), + rooms:game.lobbyState.rooms.map(room=>{ + if(room == spawnRoom) + return spawnRoom.copyStart() + else + return room.copyState() + }) } - - game.lobbyState.rooms.forEach(room=>{ - if(room == spawnRoom) - existingUsers.rooms.push(spawnRoom.copyStart()) - else - existingUsers.rooms.push(room.copyState()) - }) + + console.log(spawnRoom) + console.log(spawnRoom.copyStart()) + console.log(existingUsers) //send only player to all existing players - socket.broadcast.emit("lobby/playerJoin", JSON.stringify(newUser)); + socket.broadcast.emit(Endpoints.PlayerJoin, JSON.stringify(newUser)); //send all users to player (including player) - socket.emit("lobby/playerJoin", JSON.stringify(existingUsers)) + socket.emit(Endpoints.PlayerJoin, JSON.stringify(existingUsers)) game.addMessage(new lobbyMessage(socket.user.login + " joined")) } \ No newline at end of file diff --git a/Lobby/lobbySocket.ts b/Lobby/lobbySocket.ts index bbfe706..bb6df2d 100644 --- a/Lobby/lobbySocket.ts +++ b/Lobby/lobbySocket.ts @@ -1,17 +1,18 @@ +import { Endpoints } from "../endpoints.js"; import { loadoutChanged } from "./_loadoutChanged.js"; import { message } from "./_message.js"; import { playerJoin } from "./_playerJoin.js"; export function registerLobbyCallbacks(socket){ - socket.on('lobby/playerJoin', (data) => { + socket.on(Endpoints.PlayerJoin, (data) => { playerJoin(socket, data) }); - socket.on('lobby/loadoutChanged', (data) => { + socket.on(Endpoints.LoadoutChanged, (data) => { loadoutChanged(socket, data) }); - socket.on('lobby/message', (data) => { + socket.on(Endpoints.Message, (data) => { message(socket, data) }); -} \ No newline at end of file +} diff --git a/Player/players.ts b/Player/players.ts deleted file mode 100644 index 493a9f0..0000000 --- a/Player/players.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { game } from "../game.js"; -import { playerData } from "../Classes/playerData.js"; - -export class players{ - static createPlayer(id){ - if (players.readPlayer(id) != null){ - console.log(`Player ${id} alread exists`); - return null; - } - - var player = new playerData(); - player.id = id - game.playersDB.push(player); - return player; - } - - static readPlayer(id : number){ - let player = game.playersDB.find(u=>u.id == id); - return player; - } - - static savePlayers(fs){ - game.playersDB.forEach(player => {player.save(fs)}); - } - - static loadPlayers(fs){ - fs.mkdirSync(`Database/Players/`, { recursive: true }) - fs.readdir(`Database/Players/`, (err, files) => { - files.forEach(file => { - fs.readFile(`Database/Players/${file}`, (err, data) => { - if (err) throw err; - let player : playerData = new playerData(JSON.parse(data)); - game.playersDB.push(player); - player.inventory.items.forEach(i=>{ - if(i.id > game.itemCount){ - game.itemCount = i.id - } - }) - player.validateEquipment() - console.log(`Loaded pl ${player.id}`); - }); - }); - }); - } -} \ No newline at end of file diff --git a/Quest/_update.ts b/Quest/_update.ts index 400197f..d14f508 100644 --- a/Quest/_update.ts +++ b/Quest/_update.ts @@ -1,12 +1,11 @@ -import { playerData } from "../Classes/playerData.js"; +import { Socket } from "socket.io"; +import { characterData } from "../Classes/characterData.js"; import { questProgressData } from "../Classes/questProgressData.js"; -export function update(socket, data){ - if(!socket.hasOwnProperty("player")) return; - +export function update(socket : Socket, data){ let buff = Buffer.from(data, 'base64'); let data1 : questProgressData = JSON.parse(buff.toString('utf-8')); - let player : playerData = socket.player + let character : characterData = socket.character - player.questBook.updateQuest(data1) + character.questBook.updateQuest(data1) } \ No newline at end of file diff --git a/Quest/questSocket.ts b/Quest/questSocket.ts index ef61009..f9c7608 100644 --- a/Quest/questSocket.ts +++ b/Quest/questSocket.ts @@ -1,7 +1,8 @@ +import { Endpoints } from "../endpoints.js"; import { update } from "./_update.js"; export function registerQuestCallbacks(socket){ - socket.on('quest/update', (data) => { + socket.on(Endpoints.QuestUpdate, (data) => { update(socket, data) }); } \ No newline at end of file diff --git a/endpoints.ts b/endpoints.ts new file mode 100644 index 0000000..5e7675a --- /dev/null +++ b/endpoints.ts @@ -0,0 +1,16 @@ +export enum Endpoints{ + Login = "account/login", + Register = "account/register", + Message = 'lobby/message', + Messages = "lobby/messages", + PlayerJoin = "lobby/playerJoin", + LoadoutChanged = "lobby/loadoutChanged", + LevelEnter = 'level/enter', + LevelUpdate = 'level/update', + LevelCleared = 'level/cleared', + LevelEntered = "level/entered", + LevelProjectile = 'level/projectile', + LevelPlayerUpdate = 'level/playerUpdate', + UpdateInventory = 'item/updateInventory', + QuestUpdate = 'quest/update', +} \ No newline at end of file diff --git a/game.ts b/game.ts index 6284882..ff6d386 100644 --- a/game.ts +++ b/game.ts @@ -1,17 +1,12 @@ -import fs from 'fs'; -import { userData } from "./Classes/userData.js"; import { lobbyMessage } from "./Classes/lobbyMessage.js"; import { lobbyState } from "./Classes/lobbyState.js"; -import { playerData } from "./Classes/playerData.js"; import { persistentItemData } from "./Classes/itemData.js"; -import { levelState } from "./Classes/levelState.js"; +import { Socket } from 'socket.io'; +import { Endpoints } from "./endpoints.js"; export class game{ static socketIO : any - static itemCount : number = 0 - static accountsDB : userData[] = [] - static playersDB : playerData[] = [] static itemsDB : persistentItemData[] = [] static lobbyState : lobbyState = new lobbyState() @@ -25,7 +20,7 @@ export class game{ } game.messages.unshift(message) - game.socketIO.emit('lobby/messages', JSON.stringify(game.messages)) + game.socketIO.emit(Endpoints.Messages, JSON.stringify(game.messages)) } static getItemTemplate(templateId){ @@ -36,4 +31,8 @@ export class game{ } return item } + + static removeUser(socket : Socket) : void { + this.lobbyState.activeUsers = this.lobbyState.activeUsers.filter(u => u !== socket) + } } \ No newline at end of file diff --git a/index.ts b/index.ts index c665662..5deb041 100644 --- a/index.ts +++ b/index.ts @@ -1,26 +1,28 @@ -import fs from 'fs'; +import './socketExtended.js'; import express from 'express'; import { createServer } from 'http'; -import { Server as SocketIOServer } from 'socket.io'; - +import { Socket, Server as SocketIOServer } from 'socket.io'; import { game } from "./game.js"; -import { users } from "./Account/users.js"; -import { players } from "./Player/players.js"; +import { characters } from "./Characters/characters.js"; import { registerItemCallbacks } from "./Items/itemSocket.js"; import { registerLobbyCallbacks } from "./Lobby/lobbySocket.js"; import { registerAccountCallbacks } from "./Account/accountSocket.js"; import { registerLevelCallbacks } from "./Level/levelSocket.js"; import { registerQuestCallbacks } from "./Quest/questSocket.js"; +import { DatabaseController } from './Database/dbcontroller.js'; +import { SocketExtended } from './socketExtended.js'; +import { Endpoints } from './endpoints.js'; const app = express(); const port = 3000; const server = createServer(app); +export const db = await DatabaseController.create('./Database/mydb.sqlite3'); server.listen(port, () => { console.log(`Server listening at port ${port}`); }); -const io = new SocketIOServer(server, { +const io = game.socketIO = new SocketIOServer(server, { path: "/webmmo/", cors: { origin: '\*', @@ -28,10 +30,7 @@ const io = new SocketIOServer(server, { } }); -users.loadUsers(fs); -players.loadPlayers(fs); - -io.on('connection', (socket : any) => { +io.on('connection', (socket : SocketExtended) => { console.log("Got connection!"); socket.emit("connectSuccess", ""); @@ -41,18 +40,14 @@ io.on('connection', (socket : any) => { registerLevelCallbacks(socket); registerQuestCallbacks(socket); - socket.io = game.socketIO = io; + socket.io = io; socket.on("disconnect", () => { socket.disconnect() - if(socket.hasOwnProperty("player")){ - socket.player.save(fs) - } - if(socket.hasOwnProperty("user")){ - socket.user.save(fs) - game.lobbyState.removeUser(socket.user.id) - delete socket.user + if(socket.character != null){ + characters.savePlayer(db, socket.character) } + game.removeUser(socket) console.log(socket.id + " disconnected"); }); @@ -63,42 +58,37 @@ io.on('connection', (socket : any) => { //Send player updates to everyone setInterval(async () => { - let userCount = game.lobbyState.players.length + let userCount = game.lobbyState.activeUsers.length if(userCount > 0){ game.lobbyState.rooms.forEach(room=>{ let roomData = room.copyUpdate() - io.in(room.id).emit('level/update', JSON.stringify(roomData)) + io.in(room.id).emit(Endpoints.LevelUpdate, JSON.stringify(roomData)) }) - game.playersDB.forEach(p=>{ - p.damageInfo = [] + game.lobbyState.activeUsers.forEach(u=>{ + u.character.resetDamageInfo() }) } }, 1000/30) -setInterval(() => { - let lobbyState = game.lobbyState - console.clear() - console.log("Players:") - for(let i = 0; i < lobbyState.players.length; i++){ - console.log(lobbyState.players[i].id + " " + lobbyState.players[i].room) - } - console.log("Rooms:") - for(let i = 0; i < lobbyState.rooms.length; i++){ - console.log(lobbyState.rooms[i].id + " " + lobbyState.rooms[i].hostId) - lobbyState.rooms[i].objects.forEach(object => { - console.log("\t" + object.id + ": " + JSON.stringify(object.rigidbody)) - }); - } - console.log("Dungeon:") - for(let i = 0; i < lobbyState.dungeons.length; i++){ - console.log(lobbyState.dungeons[i].entranceId + " " + lobbyState.dungeons[i].playerCount) - } -}, 5000) - -setInterval(() => { - users.saveUsers(fs); - players.savePlayers(fs); -}, 1000 * 60 * 60 * 12) //twice a day +// setInterval(() => { +// let lobbyState = game.lobbyState +// console.clear() +// console.log("Players:") +// for(let i = 0; i < lobbyState.activeUsers.length; i++){ +// console.log(lobbyState.activeUsers[i].user.login + " " + lobbyState.activeUsers[i].character.room) +// } +// console.log("Rooms:") +// for(let i = 0; i < lobbyState.rooms.length; i++){ +// console.log(lobbyState.rooms[i].id + " " + lobbyState.rooms[i].hostId) +// lobbyState.rooms[i].objects.forEach(object => { +// console.log("\t" + object.id + ": " + JSON.stringify(object.rigidbody)) +// }); +// } +// console.log("Dungeon:") +// for(let i = 0; i < lobbyState.dungeons.length; i++){ +// console.log(lobbyState.dungeons[i].entranceId + " " + lobbyState.dungeons[i].playerCount) +// } +// }, 5000) process.on('uncaughtException', function (err) { console.log('Caught exception: ', err); @@ -108,8 +98,7 @@ process.on('SIGINT', function () { console.log('Ctrl-C...'); process.exit(2); }); + process.on('exit', function () { - users.saveUsers(fs); - players.savePlayers(fs); console.log("exitted"); }); \ No newline at end of file diff --git a/socketExtended.ts b/socketExtended.ts new file mode 100644 index 0000000..786492a --- /dev/null +++ b/socketExtended.ts @@ -0,0 +1,24 @@ +import { characterData } from "./Classes/characterData.js" +import { userData } from "./Classes/userData.js" +import { Socket, Server as SocketIOServer } from 'socket.io'; + +declare module 'socket.io' { + interface Socket { + io: SocketIOServer + user: userData + character: characterData + } +} + +export class SocketExtended extends Socket +{ + validateUser() : boolean + { + return this.user != null; + } + + validateCharacter() : boolean + { + return this.character != null; + } +}