some progress

This commit is contained in:
Evert Prants 2023-06-25 18:18:48 +03:00
parent c4c25f554c
commit 3084fefc4f
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
6 changed files with 96 additions and 18 deletions

View File

@ -22,8 +22,6 @@ export class GameplayComponent extends EngineComponent {
public world!: World;
public cleanUpEvents?: () => void;
public characters: Humanoid[] = [];
public controls!: ThirdPersonCamera;
public character!: Humanoid;
public movementSpeed = 16;
@ -35,6 +33,9 @@ export class GameplayComponent extends EngineComponent {
};
public jump = false;
private prevVelocity = new Vector3();
private prevJump = false;
private move = new Vector3();
private look = new Vector3();
private server = new GameSocket(this.events);
@ -72,18 +73,30 @@ export class GameplayComponent extends EngineComponent {
this.character?.localToWorld(this.look);
this.character?.setVelocity(this.move);
const look = this.move.clone().normalize();
if (this.move.length()) {
this.character?.setLook(look);
}
this.events.emit('sendPlayer', {
velocity: this.move,
lookAt: look,
});
let jump = false;
if (this.jump) {
jump = true;
this.jump = false;
this.character?.jump();
}
if (!this.move.equals(this.prevVelocity) || jump !== this.prevJump) {
this.events.emit('sendPlayer', {
playerId: this.uuid,
velocity: this.move,
lookAt: look,
jump,
});
}
this.prevVelocity.copy(this.move);
this.prevJump = jump;
}
override dispose(): void {
@ -94,12 +107,16 @@ export class GameplayComponent extends EngineComponent {
name: string,
pos?: Vector3,
rot?: Quaternion,
uuid?: string
uuid?: string,
objectUUID?: string
) {
const char = await instanceCharacterObject(name, pos, uuid);
const char = await instanceCharacterObject(name, pos);
const ctrl = getCharacterController(char);
if (uuid) ctrl.uuid = uuid;
if (objectUUID) char.uuid = objectUUID;
this.world.add(char);
this.characters.push(ctrl);
if (rot) char.quaternion.copy(rot);
@ -158,7 +175,8 @@ export class GameplayComponent extends EngineComponent {
event.playerName,
event.position,
event.rotation,
event.playerId
event.playerId,
event.objectUUID
);
};

View File

@ -181,11 +181,21 @@ export class LevelComponent extends EngineComponent {
Object.assign(this.environment, environmentDefaults);
};
const queueFreeEvent = (obj: Object3D | string) => {
const object =
typeof obj === 'string'
? this.world.getObjectByProperty('uuid', obj)
: obj;
if (!object) return;
this.events.emit('remove', { object });
};
this.events.addListener('change', changeEvent);
this.events.addListener('remove', removeEvent);
this.events.addListener('reparent', reparentEvent);
this.events.addListener('instance', instanceEvent);
this.events.addListener('reset', resetEvent);
this.events.addListener('queueFree', queueFreeEvent);
return () => {
this.events.removeEventListener('change', changeEvent);
@ -193,6 +203,7 @@ export class LevelComponent extends EngineComponent {
this.events.removeEventListener('reparent', reparentEvent);
this.events.removeEventListener('instance', instanceEvent);
this.events.removeEventListener('reset', resetEvent);
this.events.removeEventListener('queueFree', queueFreeEvent);
};
}
}

View File

@ -6,7 +6,7 @@ import { Humanoid } from '../gameobjects/humanoid.object';
import { PhysicsObject } from '../gameobjects/physics.object';
import { GameObject } from '../types/game-object';
import type Rapier from '@dimforge/rapier3d';
import { ServerTransformEvent } from '..';
import { PlayerEvent, ServerTransformEvent } from '../types/events';
export class PhysicsWorldComponent extends EngineComponent {
public name = PhysicsWorldComponent.name;
@ -17,6 +17,7 @@ export class PhysicsWorldComponent extends EngineComponent {
private cleanUpEvents?: Function;
private sceneInitialized = false;
private trackedObjects: PhysicsTicking[] = [];
private physicsTick?: ReturnType<typeof setInterval>;
initialize(): void {
this.world = this.renderer.scene.getObjectByName('World') as World;
@ -30,6 +31,7 @@ export class PhysicsWorldComponent extends EngineComponent {
}
dispose(): void {
clearInterval(this.physicsTick);
this.cleanUpEvents?.call(this);
this.physicsWorld.removeCharacterController(this.characterPhysics);
for (const object of this.trackedObjects) object.dispose();
@ -71,16 +73,28 @@ export class PhysicsWorldComponent extends EngineComponent {
object.rigidBody?.setAngvel(event.angularVelocity, false);
};
const characterMoveEvent = (event: PlayerEvent) => {
const object = this.trackedObjects.find(
(obj) => event.playerId === obj.uuid
) as Humanoid;
if (!object) return;
object.setVelocity(event.velocity);
object.setLook(event.lookAt);
if (event.jump) object.jump();
};
this.events.addListener('loadComplete', worldLoadEvent);
this.events.addListener('sceneJoin', sceneJoinEvent);
this.events.addListener('sceneLeave', sceneLeaveEvent);
this.events.addListener('serverTransform', serverTransformEvent);
this.events.addListener('moveCharacter', characterMoveEvent);
return () => {
this.events.removeEventListener('loadComplete', worldLoadEvent);
this.events.removeEventListener('sceneJoin', sceneJoinEvent);
this.events.removeEventListener('sceneLeave', sceneLeaveEvent);
this.events.removeEventListener('serverTransform', serverTransformEvent);
this.events.removeEventListener('moveCharacter', characterMoveEvent);
};
}
@ -124,11 +138,15 @@ export class PhysicsWorldComponent extends EngineComponent {
root.traverse((object) => {
if (trackedObjects.some((item) => item.uuid === object.uuid)) {
physicsLeaveUUIDs.push(object.uuid);
if ((object as PhysicsObject).dispose) {
(object as PhysicsObject).dispose();
}
}
});
this.trackedObjects = this.trackedObjects.filter((object) =>
physicsLeaveUUIDs.includes(object.uuid)
this.trackedObjects = this.trackedObjects.filter(
(object) => !physicsLeaveUUIDs.includes(object.uuid)
);
}

View File

@ -37,7 +37,7 @@ export class GameSocket implements Disposable {
}
dispose(): void {
this.cleanUpEvents?.();
this.disconnect();
}
private onOpen() {
@ -71,6 +71,11 @@ export class GameSocket implements Disposable {
});
break;
}
case PacketType.STREAM_DESTROY: {
const objectUUID = incoming.read(String)!;
this.events.emit('queueFree', objectUUID);
break;
}
case PacketType.STREAM_TRANSFORM: {
const objectUUID = incoming.read(String)!;
const objectPos = incoming.read<Vector3>('vec3')!;
@ -109,12 +114,28 @@ export class GameSocket implements Disposable {
const playerName = incoming.read(String)!;
const position = incoming.read<Vector3>('vec3')!;
const rotation = incoming.read<Quaternion>('quat')!;
const objectUUID = incoming.read(String)!;
this.events.emit('spawnCharacter', {
playerId,
playerName,
position,
rotation,
objectUUID,
});
break;
}
case PacketType.PLAYER_MOVEMENT: {
const playerUUID = incoming.read(String)!;
const playerVelocity = incoming.read<Vector3>('vec3')!;
const playerLookAt = incoming.read<Vector3>('vec3')!;
const playerJump = incoming.read<boolean>('bool')!;
this.events.emit('moveCharacter', {
playerId: playerUUID,
velocity: playerVelocity,
lookAt: playerLookAt,
jump: playerJump,
});
break;
}
}
}
@ -141,15 +162,23 @@ export class GameSocket implements Disposable {
if (this.ws?.readyState !== WebSocket.OPEN) return;
this.ws.send(
new Packet(PacketType.PLAYER_MOVEMENT)
.write(event.playerId, String)
.write(event.velocity, 'vec3')
.write(event.lookAt, 'vec3')
.write(event.jump, 'bool')
.toBuffer()
);
};
const onBeforeUnload = () => {
this.disconnect();
};
this.events.on('sendPlayer', sendPlayerEvent);
window.addEventListener('beforeunload', onBeforeUnload);
return () => {
this.events.removeEventListener('sendPlayer', sendPlayerEvent);
window.removeEventListener('beforeunload', onBeforeUnload);
};
}
}

View File

@ -78,8 +78,10 @@ export interface ServerTransformEvent {
}
export interface PlayerEvent {
playerId?: string;
velocity: Vector3;
lookAt: Vector3;
jump: boolean;
}
export interface SpawnEvent {
@ -87,6 +89,7 @@ export interface SpawnEvent {
playerName: string;
position: Vector3;
rotation: Quaternion;
objectUUID: string;
}
export type EngineEvents = {
@ -102,7 +105,7 @@ export type EngineEvents = {
instance: (event: InstanceEvent) => void;
sceneJoin: (event: Object3D) => void;
sceneLeave: (event: Object3D) => void;
queueFree: (event: Object3D) => void;
queueFree: (event: Object3D | string) => void;
loadComplete: () => void;
physicsComplete: () => void;
initialized: () => void;
@ -110,6 +113,7 @@ export type EngineEvents = {
spawnCharacter: (event: SpawnEvent) => void;
sendPlayer: (event: PlayerEvent) => void;
moveCharacter: (event: PlayerEvent) => void;
serverConnect: () => void;
serverTransform: (obj: ServerTransformEvent) => void;
serverDisconnect: () => void;

View File

@ -38,8 +38,7 @@ export const loadBaseCharacter = async () => {
export const instanceCharacterObject = async (
name: string,
pos = new Vector3(0, 1, 0),
uuid?: string
pos = new Vector3(0, 1, 0)
) => {
const base = await loadBaseCharacter();
@ -83,7 +82,6 @@ export const instanceCharacterObject = async (
const controller = new Humanoid();
controller.position.set(0, 4.75, 0);
controller.archivable = false;
if (uuid) controller.uuid = uuid;
baseObject.add(controller);
baseObject.position.copy(pos);