Dungeon mode

This commit is contained in:
Katboi01 2023-11-01 03:01:57 +01:00
parent d729c8dcbb
commit 6dc6bc5db8
16 changed files with 322 additions and 66 deletions

25
Classes/dungeonData.ts Normal file
View File

@ -0,0 +1,25 @@
import { game } from "../game"
import { levelState } from "./levelState"
export class dungeonData{
entranceId : string
rooms : levelState[] = []
playerCount : number = 0
constructor(id:string) {
this.entranceId = id
}
getRoom(roomId : string, create : boolean){
let room = this.rooms.find(r=>r.id == roomId)
if(room == null && create){
room = new levelState(roomId, -1)
room.isDungeon = true
this.rooms.push(room)
game.lobbyState.rooms.push(room)
}
return room
}
}

View File

@ -1,6 +1,7 @@
export class enemyDamageInfo{
sourceId : number
targetId : number
sourceId : number //player/enemy
targetId : number //player/enemy
targetName : string //physics objects
relativePosition : number[]
damage : number
knockback : number

View File

@ -1,11 +1,78 @@
import { enemyData } from "./enemyData";
import { physicsObject } from "./physicsObject";
import { playerData } from "./playerData";
import { userData } from "./userData";
export class levelState{
id : string
seed : number = -1
hostId : number = -1
enemies : enemyData[] = [];
objects : physicsObject[] = [];
completed : boolean = false
isDungeon : boolean = false
enemies : enemyData[] = []
objects : physicsObject[] = []
players : playerData[] = []
getRandomInt(max) {
return Math.floor(Math.random() * max);
}
constructor(id, hostId){
this.id = id
this.hostId = hostId
this.seed = this.getRandomInt(1000000)
this.completed = false
}
copyLight() {
let level : any = {}
level.id = this.id
level.seed = this.seed
level.hostId = this.hostId
level.completed = this.completed
level.enemies = this.enemies
level.objects = this.objects
level.players = this.players.map(pl=>pl.copyLight())
return level
}
isHostValid(){
if(this.hostId == -1) return false
if(this.players.length == 0) return false
let playerIdx = this.players.findIndex(p=>p.id==this.hostId)
if(playerIdx == -1) return false
return true
}
addPlayer(player : playerData) : boolean{
let playerIdx = this.players.findIndex(p=>p.id==player.id)
if(playerIdx != -1) return false
this.players.push(player)
if(this.hostId == -1){
this.hostId = this.players[0].id
}
return true
}
removePlayer(id) : boolean{
let playerIdx = this.players.findIndex(p=>p.id==id)
if(playerIdx == -1) return false
this.players.splice(playerIdx,1)
if(this.hostId == id){
if(this.players.length > 0){
this.hostId = this.players[0].id
}
else{
this.hostId = -1;
}
}
return true
}
}

View File

@ -1,4 +1,5 @@
import { playerData } from "../Classes/playerData";
import { dungeonData } from "./dungeonData";
import { levelState } from "./levelState";
import { userData } from "./userData";
@ -6,6 +7,7 @@ export class lobbyState{
users : userData[] = [];
players : playerData[] = [];
rooms : levelState[] = []
dungeons : dungeonData[] = []
copyLight(){
let lobby = Object.assign({}, this);
@ -15,6 +17,7 @@ export class lobbyState{
lobby.players.push(this.players[i].copyLight());
}
lobby.rooms = this.rooms
lobby.dungeons = this.dungeons
return lobby
}
@ -39,11 +42,112 @@ export class lobbyState{
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)
}
getDungeonRoot(name){
let split = name.split("_")
return split[0] + "_" + split[1] + "_0_0"
}
getDungeon(id : string, create : boolean){
let dungeon = this.dungeons.find(r=>r.entranceId == id)
if(dungeon == null && create){
dungeon = new dungeonData(id)
this.dungeons.push(dungeon)
}
return dungeon
}
getRoom(id: string, create : boolean){
let room = this.rooms.find(r=>r.id == id)
if(room == null && create){
room = new levelState(id, -1)
this.rooms.push(room)
}
return room
}
createRoom(id : string, host : number){
let room = new levelState(id, host)
this.rooms.push(room)
return room
}
roomEnter(targetRoom : levelState, player: playerData){
if(!targetRoom.isDungeon){
let room = this.getRoom(targetRoom.id, true)
room.addPlayer(player)
return room
}
else{
let dungeon = this.getDungeon(this.getDungeonRoot(targetRoom.id), true);
let room = dungeon.getRoom(targetRoom.id, true)
if(room.addPlayer(player)){
dungeon.playerCount += 1;
}
return room
}
}
roomComplete(roomId: string){
let room = this.getRoom(roomId, false)
if(room != null){
room.completed = true
return room
}
return null
}
roomExit(roomId : string, player: playerData){
let room = this.getRoom(roomId, false)
if(room != null){
if(room.removePlayer(player.id)){
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)
}
}
return room
}
return null
}
tryRemoveDungeon(roomId : string){
let dungeonIdx = this.dungeons.findIndex(r=>r.entranceId == this.getDungeonRoot(roomId))
if(dungeonIdx == -1) return false
let dungeon = this.dungeons[dungeonIdx]
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)
})
}
return true
}
}

View File

@ -1,8 +1,16 @@
export class physicsObject{
name : string
templateId : number
//array of floats [3]
kinematic : boolean
position : number[] = [0,0,0]
rotation : number[] = [0,0,0]
velocity : number[] = [0,0,0]
angularVelocity : number[] = [0,0,0]
static copyLight(o: physicsObject) {
let pObject = Object.assign({}, o)
return pObject
}
}

View File

@ -1,4 +1,3 @@
import { game } from "../game";
import { enemyDamageInfo } from "./enemyDamageInfo";
import { physicsObject } from "./physicsObject";
import { playerInventory } from "./playerInventory";
@ -15,8 +14,8 @@ export class playerData{
copyLight(){
let player : any = {}
player.id = this.id
player.room = this.room
player.rigidbody = this.rigidbody
//player.room = this.room
player.rigidbody = physicsObject.copyLight(this.rigidbody)
player.damageInfo = this.damageInfo
return player
}

View File

@ -0,0 +1,6 @@
import { levelState } from "./levelState"
export class roomChangeData{
previousRoom : string
targetRoom : levelState
}

View File

@ -0,0 +1,8 @@
import { levelState } from "./levelState"
import { playerData } from "./playerData"
export class roomChangeResponse{
player : playerData
newRoom : levelState
previousRoom : levelState
}

View File

@ -1,10 +1,8 @@
import { game } from "../game";
export function projectile(socket, data){
if(!socket.hasOwnProperty("user")) return;
let buff = Buffer.from(data, 'base64');
//let data1 = JSON.parse();
game.socketIO.emit('level/projectile', buff.toString('utf-8'))
socket.to(socket.player.room).emit('level/projectile', buff.toString('utf-8'))
}

View File

@ -10,9 +10,7 @@ export function update(socket, data){
let room = game.lobbyState.rooms.find(l=>l.id == data1.id)
if (room == null){
room = new levelState()
room.id = data1.id
game.lobbyState.rooms.push(room)
return
}
let player = socket.player

11
Lobby/_clearRoom.ts Normal file
View File

@ -0,0 +1,11 @@
import { game } from "../game";
export function clearRoom(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("lobby/cleared", JSON.stringify(room))
}

24
Lobby/_enter.ts Normal file
View File

@ -0,0 +1,24 @@
import { roomChangeData as roomChangeRequest } from "../Classes/roomChangeRequest";
import { roomChangeResponse } from "../Classes/roomChangeResponse";
import { game } from "../game";
export function enter(socket, data){
if(!socket.hasOwnProperty("player")) return;
let buff = Buffer.from(data, 'base64');
let data1 : roomChangeRequest = JSON.parse(buff.toString('utf-8'));
socket.join(data1.targetRoom.id)
let newRoom = game.lobbyState.roomEnter(data1.targetRoom, socket.player)
socket.player.room = newRoom.id
socket.leave(data1.previousRoom)
let oldRoom = game.lobbyState.roomExit(data1.previousRoom, socket.player)
let data2 = new roomChangeResponse()
data2.player = socket.player.copyLight()
data2.newRoom = newRoom.copyLight()
data2.previousRoom = oldRoom.copyLight()
game.socketIO.emit("lobby/entered", JSON.stringify(data2))
}

View File

@ -1,5 +1,5 @@
import { levelState } from "../Classes/levelState";
import { lobbyMessage } from "../Classes/lobbyMessage";
import { lobbyState } from "../Classes/lobbyState";
import { playerData } from "../Classes/playerData";
import { userData } from "../Classes/userData";
import { game } from "../game";
@ -13,9 +13,29 @@ export function playerJoin(socket, data){
socket.player.characterId = data1.characterId
game.lobbyState.addUser(socket.user, socket.player)
let newLobbyState : lobbyState = Object.assign({}, game.lobbyState);
newLobbyState.users = newLobbyState.users.map(u=> userData.makeSafe(u))
let newUser = {users:[userData.makeSafe(socket.user)], players:[socket.player], rooms:[]};
let existingUsers = {users:game.lobbyState.users.map(u=> userData.makeSafe(u)), players:[], rooms:[]}
game.lobbyState.players.forEach(player=>{
if(player.id == socket.player.id){
existingUsers.players.push(player)
}
else{
let newPlayer = Object.assign({}, player);
delete(newPlayer.inventory)
existingUsers.players.push(newPlayer)
}
})
let room = game.lobbyState.roomEnter(new levelState("0_0", -1), socket.player)
existingUsers.rooms = game.lobbyState.rooms
socket.join("0_0")
//send only player to all existing players
socket.broadcast.emit("lobby/playerJoin", JSON.stringify(newUser));
//send all users to player (including player)
socket.emit("lobby/playerJoin", JSON.stringify(existingUsers))
game.socketIO.emit("lobby/playerJoin", JSON.stringify(newLobbyState))
game.addMessage(new lobbyMessage(socket.user.login + " joined"))
}

View File

@ -9,10 +9,10 @@ export function playerUpdate(socket, data){
let player : playerData = socket.player
if(player == null){
console.log("Error! Player not spawned!")
return
}
else{
player.room = data1.room
player.rigidbody = data1.rigidbody
player.damageInfo = player.damageInfo.concat(data1.damageInfo)
}
player.room = data1.room
player.rigidbody = data1.rigidbody
player.damageInfo = player.damageInfo.concat(data1.damageInfo)
}

View File

@ -1,9 +1,19 @@
import { clearRoom } from "./_clearRoom";
import { enter } from "./_enter";
import { loadoutChanged } from "./_loadoutChanged";
import { message } from "./_message";
import { playerJoin } from "./_playerJoin";
import { playerUpdate } from "./_playerUpdate";
export function registerLobbyCallbacks(socket){
socket.on('lobby/enter', (data) => {
enter(socket, data)
});
socket.on('lobby/cleared', (data) => {
clearRoom(socket, data)
});
socket.on('lobby/playerJoin', (data) => {
playerJoin(socket, data)
});

View File

@ -6,7 +6,8 @@ import { registerItemCallbacks } from "./Items/itemSocket";
import { registerLobbyCallbacks } from "./Lobby/lobbySocket";
import { registerAccountCallbacks } from "./Account/accountSocket";
import { registerLevelCallbacks } from "./Level/levelSocket";
import { levelState } from "./Classes/levelState";
import { physicsObject } from "./Classes/physicsObject";
import { enemyData } from "./Classes/enemyData";
const express = require("express");
const app = express();
@ -54,50 +55,14 @@ io.on('connection', (socket) => {
});
//Send player updates to everyone
setInterval(() => {
setInterval(async () => {
let userCount = game.lobbyState.players.length
if(userCount > 0){
game.lobbyState.players.forEach(p=>{
let room = game.lobbyState.rooms.find(r=>r.id == p.room)
if (room == null){
room = new levelState()
room.id = p.room
game.lobbyState.rooms.push(room)
console.log("Added room " + room.id)
}
})
let removeRooms = []
for (let i = 0; i < game.lobbyState.rooms.length; i++){
let room = game.lobbyState.rooms[i]
game.lobbyState.rooms.forEach(room=>{
let roomData = room.copyLight()
//assign host to a room if there isn't one
if(room.hostId == -1){
let hostPlayer = game.lobbyState.players.find(p=>p.room == room.id)
if(hostPlayer != null){
room.hostId = hostPlayer.id
continue;
}
}
//verify if host is still in the room
let hostPlayer = game.lobbyState.players.find(p=>p.id == room.hostId)
if(hostPlayer == null || hostPlayer.room != room.id){
//if they aren't, find another
hostPlayer = game.lobbyState.players.find(p=>p.room == room.id)
if(hostPlayer != null){
room.hostId = hostPlayer.id
}
else{
room.hostId = -1
removeRooms.push(i)
}
}
}
for(let i = removeRooms.length - 1; i >= 0; i--){
console.log("no players in room " + game.lobbyState.rooms[removeRooms[i]] + ". removing.")
game.lobbyState.rooms.splice(removeRooms[i],1);
}
io.emit('lobby/update', JSON.stringify(game.lobbyState.copyLight()))
io.in(room.id).emit('lobby/update', JSON.stringify(roomData))
})
game.playersDB.forEach(p=>{
p.damageInfo = []
})
@ -105,7 +70,19 @@ setInterval(() => {
}, 1000/30)
setInterval(() => {
console.log("Players: " + game.lobbyState.players.length + ", users: " + game.lobbyState.users.length + ", rooms: " + game.lobbyState.rooms.length);
let lobbyState = game.lobbyState
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)
}
console.log("Dungeon:")
for(let i = 0; i < lobbyState.dungeons.length; i++){
console.log(lobbyState.dungeons[i].entranceId + " " + lobbyState.dungeons[i].playerCount)
}
}, 60 * 1000)
process.on('SIGINT', function () {