Skip to content

Commit

Permalink
Added load testing room and reorganized rooms as classes
Browse files Browse the repository at this point in the history
  • Loading branch information
ivancea committed Jul 30, 2024
1 parent 7a755f5 commit 13724c9
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 78 deletions.
14 changes: 0 additions & 14 deletions common/types/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,3 @@ export type Room = {
*/
maxPlayerAcceleration: number;
};

export function makeRoom(roomId: number): Room {
const roomSize = { x: 2000, y: 2000 };

return {
id: roomId,
maxPlayers: 5,
players: {},
size: roomSize,
gravity: { x: 0, y: 200 },
maxPlayerSpeed: 500,
maxPlayerAcceleration: 400,
};
}
12 changes: 9 additions & 3 deletions server/logic/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { getLogger } from "../logger";
import { Socket } from "../server";
import { getRoom, world } from "../world";
import { RoomController } from "./room-controller.base";
import { makeBotsRoom } from "./room-controller.bots";
import { makeNormalRoom } from "./room-controller.normal";
import { BotsRoom } from "./room-controller.bots";
import { NormalRoom } from "./room-controller.normal";

const roomControllers: Record<number, RoomController> = {};

Expand Down Expand Up @@ -58,14 +58,20 @@ export function findOrCreateRoomWithSpace(roomWithBots: boolean): Room {

world.rooms[newRoom.id] = newRoom;

assert(
Object.keys(newRoom.players).length < newRoom.maxPlayers,
"Room was created full",
);

return newRoom;
}

/**
* Creates a new room. Starts the room physics loop.
*/
function createRoom(roomWithBots: boolean): Room {
const { room, controller } = roomWithBots ? makeBotsRoom() : makeNormalRoom();
const controller = roomWithBots ? new BotsRoom() : new NormalRoom();
const room = controller.room;

world.rooms[room.id] = room;
roomControllers[room.id] = controller;
Expand Down
60 changes: 35 additions & 25 deletions server/logic/room-controller.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,41 @@ export type RoomController = {
destroy(): void;
};

export function makeBaseRoomController(room: Room): RoomController {
async function joinPlayer(socket: Socket, username: string) {
await server.addToRoom(socket, room);
export class BaseRoomController implements RoomController {
static makeRoom(roomId: number): Room {
return {
id: roomId,
maxPlayers: 5,
players: {},
size: { x: 2000, y: 2000 },
gravity: { x: 0, y: 200 },
maxPlayerSpeed: 500,
maxPlayerAcceleration: 400,
};
}

constructor(public room: Room) {}

async joinPlayer(socket: Socket, username: string) {
await server.addToRoom(socket, this.room);

const playerPosition = divide(room.size, 2); // TODO: Find an empty position
const playerPosition = divide(this.room.size, 2); // TODO: Find an empty position
const player = makePlayer(
socket.id,
room.id,
this.room.id,
username,
playerPosition,
makeFlailWeapon(playerPosition),
);

socketsById[socket.id] = socket;
playersById[socket.id] = player;
room.players[socket.id] = player;
this.room.players[socket.id] = player;

return player;
}

function disconnectPlayer(player: Player) {
disconnectPlayer(player: Player) {
const room = getRoom(player);

socketsById[player.id]?.disconnect();
Expand All @@ -51,22 +65,22 @@ export function makeBaseRoomController(room: Room): RoomController {
server.broadcastRoom(room).emit("playerLeft", { player });
}

function updateRoom(elapsedTime: number) {
updateRoom(elapsedTime: number) {
const damages: Damage[] = [];

const updateBotsSpan = getLogger().measureSpan("updateBots");
updateBots(room);
updateBots(this.room);
updateBotsSpan.end();

const applyPhysicsSpan = getLogger().measureSpan("applyPhysics");
applyPhysics(room, elapsedTime, (damage) => damages.push(damage));
applyPhysics(this.room, elapsedTime, (damage) => damages.push(damage));
applyPhysicsSpan.end();

const deadPlayerIds = new Set<string>();

// Apply damages
for (const damage of damages) {
const damagedPlayer = room.players[damage.damagedPlayerId];
const damagedPlayer = this.room.players[damage.damagedPlayerId];
assert(damagedPlayer, "Damaged player not found");

// TODO: Ignore damage if damaged by same source in the last N milliseconds
Expand All @@ -80,27 +94,23 @@ export function makeBaseRoomController(room: Room): RoomController {

// Remove dead players
for (const deadPlayerId of deadPlayerIds) {
const deadPlayer = room.players[deadPlayerId];
const deadPlayer = this.room.players[deadPlayerId];
assert(deadPlayer, "Damaged player not found");

server.broadcastRoom(room).emit("playerDied", { player: deadPlayer });
server
.broadcastRoom(this.room)
.emit("playerDied", { player: deadPlayer });

disconnectPlayer(deadPlayer);
this.disconnectPlayer(deadPlayer);
}

if (!Object.values(room.players).some((p) => !p.isBot)) {
delete world.rooms[room.id];
getLogger().info(`Deleted empty room ${room.id}`);
if (!Object.values(this.room.players).some((p) => !p.isBot)) {
delete world.rooms[this.room.id];
getLogger().info(`Deleted empty room ${this.room.id}`);
}

server.broadcastRoom(room).emit("roomUpdated", { room });
server.broadcastRoom(this.room).emit("roomUpdated", { room: this.room });
}

return {
room,
joinPlayer,
disconnectPlayer,
updateRoom,
destroy() {},
};
destroy() {}
}
46 changes: 21 additions & 25 deletions server/logic/room-controller.bots.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
import { makeBot } from "../../common/types/player";
import { makeRoom } from "../../common/types/room";
import { makeFlailWeapon } from "../../common/types/weapon";
import { world } from "../world";
import { makeBaseRoomController } from "./room-controller.base";
import { BaseRoomController } from "./room-controller.base";

export function makeBotsRoom() {
const room = makeRoom(world.nextRoomId++);
const base = makeBaseRoomController(room);
export class BotsRoom extends BaseRoomController {
constructor(botCount = 2) {
const room = BaseRoomController.makeRoom(world.nextRoomId++);

const botCount = 2;
for (let i = 0; i < botCount; i++) {
const botId = `_BOT_${i + 1}`;
const botName = `BOT ${i + 1}`;
const position = {
x: (room.size.x / (botCount + 1)) * (i + 1),
y: room.size.y / 2,
};
for (let i = 0; i < botCount; i++) {
const botId = `_BOT_${i + 1}`;
const botName = `BOT ${i + 1}`;
const position = {
x: (room.size.x / (botCount + 1)) * (i + 1),
y: room.size.y / 2,
};

room.players[botId] = makeBot(
botId,
room.id,
botName,
position,
makeFlailWeapon(position),
);
}
room.players[botId] = makeBot(
botId,
room.id,
botName,
position,
makeFlailWeapon(position),
);
}

return {
room,
controller: base,
};
super(room);
}
}
48 changes: 48 additions & 0 deletions server/logic/room-controller.load-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { makeBot, Player } from "../../common/types/player";
import { Room } from "../../common/types/room";
import { makeFlailWeapon } from "../../common/types/weapon";
import { world } from "../world";
import { BaseRoomController } from "./room-controller.base";

export class LoadTestRoom extends BaseRoomController {
static BOT_ID_PREFIX = "_BOT_";

constructor(private botCount: number) {
const room = {
...BaseRoomController.makeRoom(world.nextRoomId++),
maxPlayers: botCount + 1,
size: { x: 1000 * botCount, y: 1000 },
};

for (let i = 1; i <= botCount; i++) {
LoadTestRoom.addBot(i, botCount, room);
}

super(room);
}

disconnectPlayer(player: Player) {
super.disconnectPlayer(player);

const botIndex = Number(player.id.slice(LoadTestRoom.BOT_ID_PREFIX.length));

LoadTestRoom.addBot(botIndex, this.botCount, this.room);
}

static addBot(botNumber: number, botCount: number, room: Room) {
const botId = `${LoadTestRoom.BOT_ID_PREFIX}${botNumber}`;
const botName = `BOT ${botNumber}`;
const position = {
x: (room.size.x / (botCount + 1)) * botNumber,
y: room.size.y / 2,
};

room.players[botId] = makeBot(
botId,
room.id,
botName,
position,
makeFlailWeapon(position),
);
}
}
15 changes: 5 additions & 10 deletions server/logic/room-controller.normal.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { makeRoom } from "../../common/types/room";
import { world } from "../world";
import { makeBaseRoomController } from "./room-controller.base";
import { BaseRoomController } from "./room-controller.base";

export function makeNormalRoom() {
const room = makeRoom(world.nextRoomId++);
const base = makeBaseRoomController(room);

return {
room,
controller: base,
};
export class NormalRoom extends BaseRoomController {
constructor() {
super(BaseRoomController.makeRoom(world.nextRoomId++));
}
}
2 changes: 1 addition & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const __dirname = path.dirname(__filename);
export default (env) => {
let appVersion;

if (env.APP_VERSION) {
if (env?.APP_VERSION) {
appVersion = env.APP_VERSION;
} else {
const gitCommit = childProcess.execSync("git rev-parse HEAD").toString();
Expand Down

0 comments on commit 13724c9

Please sign in to comment.