testing idk

This commit is contained in:
Evert Prants 2023-07-01 10:09:15 +03:00
parent e2ec33f97c
commit 53181efb97
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
11 changed files with 81 additions and 28 deletions

View File

@ -2,11 +2,12 @@ import { Module } from '@nestjs/common';
import { EventsModule } from './events/events.module'; import { EventsModule } from './events/events.module';
import { ConfigModule } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config';
import { world } from './config/world.config'; import { world } from './config/world.config';
import { server } from './config/server.config';
@Module({ @Module({
imports: [ imports: [
ConfigModule.forRoot({ ConfigModule.forRoot({
load: [world], load: [server, world],
}), }),
EventsModule, EventsModule,
], ],

View File

@ -0,0 +1,7 @@
import { registerAs } from '@nestjs/config';
export const server = registerAs('server', () => ({
gatewayPort: Number(process.env.GATEWAY_PORT || 8256),
statusPort: Number(process.env.PORT || 8255),
corsOrigin: process.env.CORS_ORIGIN || '*',
}));

View File

@ -1,3 +1,4 @@
import { Logger } from '@nestjs/common';
import { import {
ConnectedSocket, ConnectedSocket,
MessageBody, MessageBody,
@ -8,6 +9,7 @@ import {
WebSocketGateway, WebSocketGateway,
WebSocketServer, WebSocketServer,
} from '@nestjs/websockets'; } from '@nestjs/websockets';
import { Request } from 'express';
import { Packet } from 'src/net/packet'; import { Packet } from 'src/net/packet';
import { PlayerStoreService } from 'src/player/player-store.service'; import { PlayerStoreService } from 'src/player/player-store.service';
import { PlayerSocket } from 'src/types/data-socket'; import { PlayerSocket } from 'src/types/data-socket';
@ -17,14 +19,12 @@ import { getRandomId } from 'src/utils/random';
import { WorldService } from 'src/world/world.service'; import { WorldService } from 'src/world/world.service';
import { Server } from 'ws'; import { Server } from 'ws';
@WebSocketGateway(8256, { @WebSocketGateway()
cors: {
origin: '*',
},
})
export class EventsGateway export class EventsGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{ {
private readonly logger = new Logger(EventsGateway.name);
constructor( constructor(
private readonly players: PlayerStoreService, private readonly players: PlayerStoreService,
private readonly world: WorldService, private readonly world: WorldService,
@ -59,6 +59,9 @@ export class EventsGateway
.toBuffer(), .toBuffer(),
); );
} }
this.logger.log(
`Client ${client.id} (${client.ip}) has logged in as ${player.name} (${player.id})`,
);
await this.world.initializePlayer(player); await this.world.initializePlayer(player);
} }
@ -68,14 +71,19 @@ export class EventsGateway
} }
afterInit(server: Server) { afterInit(server: Server) {
console.log('server init'); this.logger.log(
`>>> Game server is listening on port ${server.options.port} <<<`,
);
} }
handleConnection(client: PlayerSocket, ...args: any[]) { handleConnection(client: PlayerSocket, request: Request) {
client.id = getRandomId(); client.id = getRandomId();
client.ip = request.socket.remoteAddress;
this.logger.log(`Client ${client.id} connected from ${client.ip}.`);
} }
handleDisconnect(client: PlayerSocket) { handleDisconnect(client: PlayerSocket) {
this.logger.log(`Client ${client.id} (${client.ip}) disconnected.`);
this.world.playerQuit(client); this.world.playerQuit(client);
} }
} }

View File

@ -21,6 +21,7 @@ export class Humanoid extends GameObject implements PhysicsTicking {
private _appliedGravity = new Vector3(0, 0, 0); private _appliedGravity = new Vector3(0, 0, 0);
private _grounded = true; private _grounded = true;
private _lookAt = new Vector3(0, 0, 1); private _lookAt = new Vector3(0, 0, 1);
private _lookAtTarget = new Vector3(0, 0, 1);
private _currentLookAt = new Vector3(0, 0, 1); private _currentLookAt = new Vector3(0, 0, 1);
private _animState = 0; private _animState = 0;
@ -108,7 +109,7 @@ export class Humanoid extends GameObject implements PhysicsTicking {
} }
setLook(vector: Vector3) { setLook(vector: Vector3) {
this._lookAt.lerp(vector, 0.15); this._lookAtTarget.copy(vector);
} }
jump() { jump() {
@ -147,6 +148,7 @@ export class Humanoid extends GameObject implements PhysicsTicking {
// Apply look vector // Apply look vector
this._currentLookAt.copy(this.parent!.position); this._currentLookAt.copy(this.parent!.position);
this._lookAt.lerp(this._lookAtTarget, 0.15);
this._currentLookAt.add(this._lookAt); this._currentLookAt.add(this._lookAt);
this.parent?.lookAt(this._currentLookAt); this.parent?.lookAt(this._currentLookAt);

View File

@ -1,12 +1,24 @@
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import { WsAdapter } from './net/ws-adapter'; import { WsAdapter } from './net/ws-adapter';
import { ConfigService } from '@nestjs/config';
import { Logger } from '@nestjs/common';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
app.useWebSocketAdapter(new WsAdapter(app)); const config = app.get<ConfigService>(ConfigService);
const appPort = config.get<number>('server.statusPort');
const gatewayPort = config.get<number>('server.gatewayPort');
const corsOrigin = config.get('server.corsOrigin');
await app.listen(3000); app.enableCors({
console.log(`Application is running on: ${await app.getUrl()}`); origin: corsOrigin,
credentials: true,
});
app.useWebSocketAdapter(new WsAdapter(app, gatewayPort, corsOrigin));
await app.listen(appPort);
Logger.log(`Server status API: ${await app.getUrl()}`, 'bootstrap');
} }
bootstrap(); bootstrap();

View File

@ -6,10 +6,18 @@ import { mergeMap, filter } from 'rxjs/operators';
import { Packet } from './packet'; import { Packet } from './packet';
export class WsAdapter implements WebSocketAdapter { export class WsAdapter implements WebSocketAdapter {
constructor(private app: INestApplicationContext) {} constructor(
private app: INestApplicationContext,
private port: number,
private cors: string,
) {}
create(port: number, options: any = {}): any { create(port: number, options: any = {}): any {
return new WebSocket.Server({ port, ...options }); return new WebSocket.Server({
port: this.port || port,
...options,
cors: { origin: this.cors },
});
} }
bindClientConnect( bindClientConnect(

View File

@ -98,7 +98,9 @@ export class PlayerStoreService {
if (player.controller) { if (player.controller) {
player.controller.setVelocity(velocity); player.controller.setVelocity(velocity);
player.controller.setLook(lookAt); if (!(velocity.x === 0 && velocity.y === 0 && velocity.z === 0)) {
player.controller.setLook(lookAt);
}
if (jump) player.controller.jump(); if (jump) player.controller.jump();
return true; return true;
} }

View File

@ -2,4 +2,5 @@ import { WebSocket } from 'ws';
export interface PlayerSocket extends WebSocket { export interface PlayerSocket extends WebSocket {
id: string; id: string;
ip: string;
} }

View File

@ -9,7 +9,7 @@ export enum PacketType {
*/ */
STREAM_START, STREAM_START,
/** /**
* [][Asset Name][Asset Type][Buffer] * [][Asset Path][Asset Name][Asset Type][Buffer]
*/ */
STREAM_ASSET, STREAM_ASSET,
/** /**
@ -37,7 +37,7 @@ export enum PacketType {
*/ */
STREAM_CHAT, STREAM_CHAT,
/** /**
* [][Player ID:Player Name] * [][Player count][Player ID:Player Name]
*/ */
PLAYER_LIST, PLAYER_LIST,
/** /**
@ -57,9 +57,13 @@ export enum PacketType {
*/ */
PLAYER_MOVEMENT, PLAYER_MOVEMENT,
/** /**
* [][Chat Type][Chat Message] * [][Player ID][Chat Type][Chat Message]
*/ */
PLAYER_CHAT, PLAYER_CHAT,
/**
* [][Player ID][Object UUID][Event][JSON]
*/
PLAYER_EVENT,
/** /**
* [][Error type] * [][Error type]
*/ */

View File

@ -7,6 +7,9 @@ import { Object3D, Vector3 } from 'three';
import { GameObject } from 'src/game/game-object'; import { GameObject } from 'src/game/game-object';
import { PhysicsTicking } from 'src/physics'; import { PhysicsTicking } from 'src/physics';
const PHYSICS_STEPPING = 1000 / 60;
const PHYSICS_STEPPING_S = 1 / 60;
@Injectable() @Injectable()
export class PhysicsService { export class PhysicsService {
private world!: World; private world!: World;
@ -23,16 +26,16 @@ export class PhysicsService {
if (!this.running) return; if (!this.running) return;
this.physicsTicker = setInterval(() => { this.physicsTicker = setInterval(() => {
this.physicsWorld.step(); this.physicsWorld.step();
for (const object of this.trackedObjects) object.tick(0.016); for (const object of this.trackedObjects) object.tick(PHYSICS_STEPPING_S);
this.tickCallback?.(); this.tickCallback?.();
}, 16); }, PHYSICS_STEPPING);
} }
async start(world: World, cb?: () => void) { async start(world: World, cb?: () => void) {
this.world = world; this.world = world;
await RAPIER.init(); await RAPIER.init();
this.physicsWorld = new RAPIER.World(new Vector3(0, this.world.gravity, 0)); this.physicsWorld = new RAPIER.World(new Vector3(0, this.world.gravity, 0));
this.physicsWorld.timestep = 0.016; this.physicsWorld.timestep = PHYSICS_STEPPING_S;
this.running = true; this.running = true;
this.tickCallback = cb; this.tickCallback = cb;
this.initializePhysicsScene(); this.initializePhysicsScene();
@ -54,10 +57,7 @@ export class PhysicsService {
.write(object.uuid, String) .write(object.uuid, String)
.write(body.translation(), 'vec3') .write(body.translation(), 'vec3')
.write(body.rotation(), 'quat') .write(body.rotation(), 'quat')
.write( .write(body.linvel(), 'vec3')
object instanceof Humanoid ? body.nextTranslation() : body.linvel(),
'vec3',
)
.write(body.angvel(), 'vec3') .write(body.angvel(), 'vec3')
.toBuffer(), .toBuffer(),
); );

View File

@ -32,11 +32,11 @@ export class WorldService implements OnModuleInit {
this.logger.log('Loading world file from environment'); this.logger.log('Loading world file from environment');
this.loadWorld() this.loadWorld()
.then(() => { .then(() => {
this.logger.log('World file loaded'); this.logger.log('World file loaded!');
this.physics.start(this.world, () => { this.physics.start(this.world, () => {
if (this.broadcastTick >= 0.25) { this.broadcastWorldState();
if (this.broadcastTick >= 0.5) {
this.broadcastTick = 0; this.broadcastTick = 0;
this.broadcastWorldState();
return; return;
} }
this.broadcastTick += 0.016; this.broadcastTick += 0.016;
@ -71,6 +71,9 @@ export class WorldService implements OnModuleInit {
} }
public async initializePlayer(player: Player) { public async initializePlayer(player: Player) {
this.logger.debug(
`Initializing player ${player.name} (${player.id}), sending world file..`,
);
// Streaming start // Streaming start
player.send( player.send(
new Packet(PacketType.STREAM_START) new Packet(PacketType.STREAM_START)
@ -121,6 +124,10 @@ export class WorldService implements OnModuleInit {
this.players this.players
.getPlayerCharacterPackets(player) .getPlayerCharacterPackets(player)
.forEach((packet) => player.send(packet)); .forEach((packet) => player.send(packet));
this.logger.log(
`PLAYER ${player.name} (${player.id}) has joined the game!`,
);
} }
public removeObject(object: Object3D) { public removeObject(object: Object3D) {
@ -197,6 +204,7 @@ export class WorldService implements OnModuleInit {
); );
this.removeObject(player.controller); this.removeObject(player.controller);
this.removeObject(player.character); this.removeObject(player.character);
this.logger.log(`PLAYER ${player.name} (${player.id}) has left the game.`);
} }
private recursiveCreate(entry: SerializedObject, setParent?: Object3D) { private recursiveCreate(entry: SerializedObject, setParent?: Object3D) {