2022-04-09 11:29:54 +00:00
|
|
|
import { IcyNetUser } from '../../common/types/user';
|
|
|
|
import * as THREE from 'three';
|
|
|
|
import { PonyEntity } from './pony';
|
2022-04-09 14:49:30 +00:00
|
|
|
import {
|
2022-04-10 06:52:50 +00:00
|
|
|
CharacterPacket,
|
2022-04-09 14:49:30 +00:00
|
|
|
FullStatePacket,
|
|
|
|
PositionUpdatePacket,
|
|
|
|
} from '../../common/types/packet';
|
2022-04-09 12:57:20 +00:00
|
|
|
import { CanvasUtils } from './canvas-utils';
|
|
|
|
import { ChatBubble } from './chat-bubble';
|
|
|
|
|
2022-04-09 16:06:53 +00:00
|
|
|
const chatBuilder = new CanvasUtils({
|
|
|
|
rounded: true,
|
|
|
|
roundedRadius: 8,
|
|
|
|
});
|
2022-04-09 11:29:54 +00:00
|
|
|
|
|
|
|
export class PlayerEntity extends PonyEntity {
|
2022-04-09 14:49:30 +00:00
|
|
|
private _updateQueue: PositionUpdatePacket[] = [];
|
|
|
|
private _targetFrame: any = null;
|
|
|
|
private _lastFrame: any = null;
|
2022-04-09 12:57:20 +00:00
|
|
|
private _chats: ChatBubble[] = [];
|
|
|
|
|
2022-04-09 14:49:30 +00:00
|
|
|
private _p1 = new THREE.Vector3();
|
|
|
|
private _p2 = new THREE.Vector3();
|
|
|
|
private _q1 = new THREE.Vector3();
|
|
|
|
private _q2 = new THREE.Vector3();
|
|
|
|
|
|
|
|
private _pf = new THREE.Vector3();
|
|
|
|
private _qf = new THREE.Vector3();
|
|
|
|
|
2022-04-09 11:29:54 +00:00
|
|
|
constructor(public user: IcyNetUser) {
|
|
|
|
super();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static fromUser(user: IcyNetUser, scene: THREE.Scene): PlayerEntity {
|
|
|
|
const entity = new PlayerEntity(user);
|
|
|
|
entity.initialize();
|
|
|
|
entity.addNameTag(user.display_name);
|
|
|
|
scene.add(entity.container);
|
|
|
|
return entity;
|
|
|
|
}
|
|
|
|
|
|
|
|
public setVelocity(velocity: THREE.Vector3) {
|
|
|
|
this.velocity.copy(velocity);
|
|
|
|
}
|
|
|
|
|
|
|
|
public setAngularVelocity(velocity: THREE.Vector3) {
|
|
|
|
this.angularVelocity.copy(velocity);
|
|
|
|
}
|
|
|
|
|
|
|
|
public setPosition(pos: THREE.Vector3) {
|
|
|
|
this.container.position.copy(pos);
|
|
|
|
}
|
|
|
|
|
2022-04-09 12:57:20 +00:00
|
|
|
public addChat(message: string): void {
|
|
|
|
const lines = [];
|
|
|
|
let truncated = message;
|
|
|
|
|
|
|
|
while (truncated.length > 80) {
|
|
|
|
lines.push(truncated.substring(0, 80));
|
|
|
|
truncated = truncated.substring(80);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (truncated) {
|
|
|
|
lines.push(truncated);
|
|
|
|
}
|
|
|
|
|
|
|
|
const newChat = new ChatBubble(chatBuilder, lines);
|
|
|
|
|
|
|
|
this._chats.forEach((item) => {
|
2022-04-09 15:17:07 +00:00
|
|
|
const scaled = item.tag.scale.y;
|
|
|
|
item.tag.position.add(new THREE.Vector3(0, scaled, 0));
|
2022-04-09 12:57:20 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this._chats.unshift(newChat);
|
2022-04-09 15:17:07 +00:00
|
|
|
newChat.tag.position.set(0, 1.8 + this.nameTag.tag.scale.y + 0.15, 0.5);
|
2022-04-09 12:57:20 +00:00
|
|
|
this.container.add(newChat.tag);
|
|
|
|
|
|
|
|
if (this._chats.length > 3) {
|
|
|
|
this._chats.splice(3, this._chats.length - 1).forEach((item) => {
|
|
|
|
this.container.remove(item.tag);
|
|
|
|
item.dispose();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
const i = this._chats.indexOf(newChat);
|
|
|
|
|
|
|
|
if (i !== -1) {
|
|
|
|
this.container.remove(newChat.tag);
|
|
|
|
this._chats.splice(i, 1);
|
|
|
|
newChat.dispose();
|
|
|
|
}
|
|
|
|
}, 5000);
|
|
|
|
}
|
|
|
|
|
2022-04-09 11:29:54 +00:00
|
|
|
public setRotation(rot: THREE.Vector3 | THREE.Euler) {
|
|
|
|
this.container.rotation.copy(
|
|
|
|
rot instanceof THREE.Euler
|
|
|
|
? rot
|
|
|
|
: new THREE.Euler(rot.x, rot.y, rot.z, 'XYZ'),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-10 06:52:50 +00:00
|
|
|
public addUncommittedChanges(packet: FullStatePacket) {
|
2022-04-09 14:49:30 +00:00
|
|
|
const appendix = { ...packet, time: 0.1 };
|
|
|
|
this._updateQueue.push(appendix);
|
|
|
|
if (!this._targetFrame) {
|
|
|
|
this.setFromPacket(packet);
|
|
|
|
this._targetFrame = appendix;
|
|
|
|
}
|
2022-04-10 06:52:50 +00:00
|
|
|
|
|
|
|
if (packet.character) {
|
|
|
|
this.setCharacter(packet.character);
|
|
|
|
}
|
2022-04-09 11:29:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public update(dt: number) {
|
2022-04-09 14:49:30 +00:00
|
|
|
this.commitServerUpdate(dt);
|
2022-04-09 13:23:46 +00:00
|
|
|
super.update(dt);
|
2022-04-09 11:29:54 +00:00
|
|
|
}
|
|
|
|
|
2022-04-09 14:49:30 +00:00
|
|
|
private setFromPacket(packet: FullStatePacket | PositionUpdatePacket) {
|
|
|
|
if ((packet as FullStatePacket).velocity) {
|
|
|
|
this.setVelocity(
|
|
|
|
new THREE.Vector3().fromArray((packet as FullStatePacket).velocity),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((packet as FullStatePacket).angular) {
|
|
|
|
this.setAngularVelocity(
|
|
|
|
new THREE.Vector3().fromArray((packet as FullStatePacket).angular),
|
|
|
|
);
|
2022-04-09 11:29:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (packet.position) {
|
|
|
|
this.setPosition(new THREE.Vector3().fromArray(packet.position));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (packet.rotation) {
|
|
|
|
this.setRotation(new THREE.Euler().fromArray(packet.rotation));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (packet.animState) {
|
|
|
|
this.setWalkAnimationState(packet.animState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-09 14:49:30 +00:00
|
|
|
private commitServerUpdate(dt: number) {
|
|
|
|
if (this._updateQueue.length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < this._updateQueue.length; ++i) {
|
|
|
|
this._updateQueue[i].time -= dt;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (this._updateQueue.length > 0 && this._updateQueue[0].time <= 0.0) {
|
|
|
|
this._lastFrame = {
|
|
|
|
animState: this._targetFrame.animState,
|
|
|
|
position: this.container.position.toArray(),
|
|
|
|
rotation: this.container.rotation.toArray(),
|
|
|
|
};
|
|
|
|
this._targetFrame = this._updateQueue.shift();
|
|
|
|
this._targetFrame.time = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lerp the position and rotation
|
|
|
|
if (this._targetFrame && this._lastFrame) {
|
|
|
|
this._targetFrame.time += dt;
|
|
|
|
this._p1.fromArray(this._lastFrame.position);
|
|
|
|
this._p2.fromArray(this._targetFrame.position);
|
|
|
|
this._q1.fromArray(this._lastFrame.rotation);
|
|
|
|
this._q2.fromArray(this._targetFrame.rotation);
|
|
|
|
this._pf.copy(this._p1);
|
|
|
|
this._qf.copy(this._q1);
|
|
|
|
|
|
|
|
const t = Math.max(Math.min(this._targetFrame.time / 0.1, 1.0), 0.0);
|
|
|
|
this._pf.lerp(this._p2, t);
|
|
|
|
this._qf.lerp(this._q2, t);
|
|
|
|
|
|
|
|
this.setPosition(this._pf);
|
|
|
|
this.setRotation(this._qf);
|
|
|
|
this.setWalkAnimationState(this._lastFrame.animState);
|
|
|
|
}
|
2022-04-09 11:29:54 +00:00
|
|
|
}
|
|
|
|
}
|