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 { ConfigModule } from '@nestjs/config';
import { world } from './config/world.config';
import { server } from './config/server.config';
@Module({
imports: [
ConfigModule.forRoot({
load: [world],
load: [server, world],
}),
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 {
ConnectedSocket,
MessageBody,
@ -8,6 +9,7 @@ import {
WebSocketGateway,
WebSocketServer,
} from '@nestjs/websockets';
import { Request } from 'express';
import { Packet } from 'src/net/packet';
import { PlayerStoreService } from 'src/player/player-store.service';
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 { Server } from 'ws';
@WebSocketGateway(8256, {
cors: {
origin: '*',
},
})
@WebSocketGateway()
export class EventsGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
private readonly logger = new Logger(EventsGateway.name);
constructor(
private readonly players: PlayerStoreService,
private readonly world: WorldService,
@ -59,6 +59,9 @@ export class EventsGateway
.toBuffer(),
);
}
this.logger.log(
`Client ${client.id} (${client.ip}) has logged in as ${player.name} (${player.id})`,
);
await this.world.initializePlayer(player);
}
@ -68,14 +71,19 @@ export class EventsGateway
}
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.ip = request.socket.remoteAddress;
this.logger.log(`Client ${client.id} connected from ${client.ip}.`);
}
handleDisconnect(client: PlayerSocket) {
this.logger.log(`Client ${client.id} (${client.ip}) disconnected.`);
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 _grounded = true;
private _lookAt = new Vector3(0, 0, 1);
private _lookAtTarget = new Vector3(0, 0, 1);
private _currentLookAt = new Vector3(0, 0, 1);
private _animState = 0;
@ -108,7 +109,7 @@ export class Humanoid extends GameObject implements PhysicsTicking {
}
setLook(vector: Vector3) {
this._lookAt.lerp(vector, 0.15);
this._lookAtTarget.copy(vector);
}
jump() {
@ -147,6 +148,7 @@ export class Humanoid extends GameObject implements PhysicsTicking {
// Apply look vector
this._currentLookAt.copy(this.parent!.position);
this._lookAt.lerp(this._lookAtTarget, 0.15);
this._currentLookAt.add(this._lookAt);
this.parent?.lookAt(this._currentLookAt);

View File

@ -1,12 +1,24 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { WsAdapter } from './net/ws-adapter';
import { ConfigService } from '@nestjs/config';
import { Logger } from '@nestjs/common';
async function bootstrap() {
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);
console.log(`Application is running on: ${await app.getUrl()}`);
app.enableCors({
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();

View File

@ -6,10 +6,18 @@ import { mergeMap, filter } from 'rxjs/operators';
import { Packet } from './packet';
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 {
return new WebSocket.Server({ port, ...options });
return new WebSocket.Server({
port: this.port || port,
...options,
cors: { origin: this.cors },
});
}
bindClientConnect(

View File

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

View File

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

View File

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

View File

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

View File

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