icy3dw/src/server/game.ts

132 lines
3.7 KiB
TypeScript
Raw Normal View History

2022-04-09 11:29:54 +00:00
import { Server, Socket } from 'socket.io';
import { RequestHandler } from 'express';
2022-04-12 15:24:05 +00:00
import { IcyNetUser } from '../common/types/user';
2022-04-16 10:21:07 +00:00
import { Persistence } from './object/persistence';
2022-04-16 10:40:25 +00:00
import { Logger } from './object/logger';
2022-04-17 13:00:13 +00:00
import { ServerWorld } from './world/server-world';
import { ServerWorldLoader } from './world/server-world-loader';
import { ServerWorldManifest } from './world/server-world-manifest';
import { Player } from './object/player';
2022-05-15 10:54:15 +00:00
import {
ServerToClientEvents,
ClientToServerEvents,
} from '../common/types/socket';
import { InterServerEvents, SocketData } from './types/socket';
import { CompositePacket } from '../common/types/packet';
2022-04-09 11:29:54 +00:00
const PLACEHOLDER_USER = (socket: Socket): IcyNetUser => {
const randomName = `player-${socket.id.substring(0, 8)}`;
return {
2022-04-12 15:24:05 +00:00
id: Math.floor(Math.random() * 1000 + 1000),
2022-04-09 11:29:54 +00:00
username: randomName,
display_name: randomName,
uuid: socket.id,
accessToken: 'player',
};
};
export class Game {
2022-04-17 13:00:13 +00:00
private _players: Player[] = [];
2022-04-16 10:21:07 +00:00
private _db = new Persistence();
2022-04-16 10:40:25 +00:00
private _log = new Logger();
2022-04-17 13:00:13 +00:00
private _world!: ServerWorld;
2022-04-09 11:29:54 +00:00
2022-05-15 10:54:15 +00:00
constructor(
private io: Server<
ClientToServerEvents,
ServerToClientEvents,
InterServerEvents,
SocketData
>,
private session: RequestHandler,
) {}
2022-04-09 11:29:54 +00:00
async initialize() {
2022-04-17 13:00:13 +00:00
const manifest = await ServerWorldManifest.loadManifest();
this._world = new ServerWorld(new ServerWorldLoader(), manifest);
2022-04-16 10:21:07 +00:00
await this._db.initialize();
2022-04-17 13:00:13 +00:00
await this._world.initialize();
2022-04-16 10:40:25 +00:00
this._log.initialize();
2022-04-16 10:21:07 +00:00
2022-04-09 11:29:54 +00:00
this.io.use((socket, next) =>
this.session(socket.request as any, {} as any, next as any),
);
this.io.on('connection', (socket) => {
const session = (socket.request as any).session;
const user =
process.env.SKIP_LOGIN === 'true'
? PLACEHOLDER_USER(socket)
: (session?.passport?.user as IcyNetUser);
2022-04-17 13:00:13 +00:00
if (user && this._players.find((entry) => entry.user?.id === user.id)) {
2022-04-12 15:24:05 +00:00
socket.emit('error.duplicate');
return;
}
2022-04-09 12:57:20 +00:00
if (user) {
2022-04-17 13:00:13 +00:00
const player = new Player(socket, this._db, user);
this._players.push(player);
2022-04-09 11:29:54 +00:00
2022-04-17 13:00:13 +00:00
this._log.writeEvent('PlayerJoin', `<${user.display_name}:${user.id}>`);
2022-04-10 06:52:50 +00:00
2022-04-17 13:00:13 +00:00
socket.data.player = player;
player.initialize().then(() => {
// Send player list to new player
socket.emit(
2022-05-15 10:54:15 +00:00
'player.list',
2022-04-17 13:00:13 +00:00
this._players
.filter((player) => player.user)
.map((player) => ({
...player.getPublicUserProfile(),
2022-05-15 10:54:15 +00:00
...(player.toSave() as CompositePacket),
2022-04-17 13:00:13 +00:00
})),
);
2022-04-10 06:52:50 +00:00
});
2022-04-09 11:29:54 +00:00
2022-05-15 10:54:15 +00:00
socket.on('set.chat', (raw) => {
2022-04-10 12:54:29 +00:00
const message = raw.trim().substring(0, 280);
2022-04-16 10:40:25 +00:00
this._log.writeChat(user, message);
2022-05-15 10:54:15 +00:00
this.io.emit('player.chat', {
2022-04-17 13:00:13 +00:00
sender: player.getPublicUserProfile(),
message,
2022-04-16 10:21:07 +00:00
});
});
} else {
2022-05-15 10:54:15 +00:00
socket.emit('set.me', null);
2022-04-09 12:57:20 +00:00
}
socket.on('disconnect', () => {
if (user) {
2022-04-17 13:00:13 +00:00
const player = this._players.find(
(player) => player.user.id === user.id,
);
if (!player) {
return;
}
2022-05-15 10:54:15 +00:00
this.io.emit('player.leave', player.getPublicUserProfile());
2022-04-17 13:00:13 +00:00
2022-04-16 10:40:25 +00:00
this._log.writeEvent(
'PlayerLeave',
`<${user.display_name}:${user.id}>`,
);
2022-04-17 13:00:13 +00:00
player.dispose();
this._players.splice(this._players.indexOf(player), 1);
2022-04-09 12:57:20 +00:00
}
2022-04-09 11:29:54 +00:00
});
});
2022-04-09 14:49:30 +00:00
setInterval(() => {
2022-04-17 13:00:13 +00:00
this._players.forEach((player) => player.update(1000 / 60));
this.io.emit(
2022-05-15 10:54:15 +00:00
'player.update',
2022-04-17 13:00:13 +00:00
this._players.map((player) => player.toUpdatePacket()),
);
2022-04-09 16:06:53 +00:00
}, 1000 / 60);
2022-04-09 11:29:54 +00:00
}
}