colorize
This commit is contained in:
parent
43c1fe0f96
commit
057425695e
Binary file not shown.
@ -1,7 +1,8 @@
|
|||||||
import e from 'express';
|
import e from 'express';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
|
import { Color } from 'three';
|
||||||
import { isMobileOrTablet } from '../common/helper';
|
import { isMobileOrTablet } from '../common/helper';
|
||||||
import { CompositePacket } from '../common/types/packet';
|
import { CharacterPacket, CompositePacket } from '../common/types/packet';
|
||||||
import { IcyNetUser } from '../common/types/user';
|
import { IcyNetUser } from '../common/types/user';
|
||||||
import { ThirdPersonCamera } from './object/camera';
|
import { ThirdPersonCamera } from './object/camera';
|
||||||
import { Chat } from './object/chat';
|
import { Chat } from './object/chat';
|
||||||
@ -19,6 +20,7 @@ export class Game {
|
|||||||
public thirdPersonCamera!: ThirdPersonCamera;
|
public thirdPersonCamera!: ThirdPersonCamera;
|
||||||
public joystick!: Joystick;
|
public joystick!: Joystick;
|
||||||
public chat!: Chat;
|
public chat!: Chat;
|
||||||
|
private character: CharacterPacket = {};
|
||||||
private party: string[] = [];
|
private party: string[] = [];
|
||||||
|
|
||||||
public renderer = new Renderer();
|
public renderer = new Renderer();
|
||||||
@ -43,6 +45,11 @@ export class Game {
|
|||||||
this.party = (localStorage.getItem('party')?.split('|') || []).filter(
|
this.party = (localStorage.getItem('party')?.split('|') || []).filter(
|
||||||
(item) => item,
|
(item) => item,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const colorGet = localStorage.getItem('color');
|
||||||
|
if (colorGet) {
|
||||||
|
this.character.color = colorGet;
|
||||||
|
}
|
||||||
// end of
|
// end of
|
||||||
|
|
||||||
this.chat.registerSendFunction((message) => {
|
this.chat.registerSendFunction((message) => {
|
||||||
@ -89,6 +96,7 @@ export class Game {
|
|||||||
this.me = user;
|
this.me = user;
|
||||||
|
|
||||||
const player = Player.fromUser(user, this.renderer.scene);
|
const player = Player.fromUser(user, this.renderer.scene);
|
||||||
|
player.setCharacter(this.character);
|
||||||
this.players.push(player);
|
this.players.push(player);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.thirdPersonCamera = new ThirdPersonCamera(
|
this.thirdPersonCamera = new ThirdPersonCamera(
|
||||||
@ -104,6 +112,8 @@ export class Game {
|
|||||||
if (isMobileOrTablet()) {
|
if (isMobileOrTablet()) {
|
||||||
this.joystick.show();
|
this.joystick.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.socket.emit('character', this.character);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('playerjoin', (user) => {
|
this.socket.on('playerjoin', (user) => {
|
||||||
@ -119,6 +129,7 @@ export class Game {
|
|||||||
const findPlayer = this.players.find((item) => item.user.id === user.id);
|
const findPlayer = this.players.find((item) => item.user.id === user.id);
|
||||||
if (findPlayer) {
|
if (findPlayer) {
|
||||||
this.renderer.scene.remove(findPlayer.container);
|
this.renderer.scene.remove(findPlayer.container);
|
||||||
|
findPlayer.dispose();
|
||||||
this.players.splice(this.players.indexOf(findPlayer), 1);
|
this.players.splice(this.players.indexOf(findPlayer), 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -150,6 +161,17 @@ export class Game {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.socket.on('playercharacter', (data) => {
|
||||||
|
const player = this.players.find((player) => player.user.id === data.id);
|
||||||
|
if (
|
||||||
|
player &&
|
||||||
|
player instanceof PlayerEntity &&
|
||||||
|
player.user.id !== this.me.id
|
||||||
|
) {
|
||||||
|
player.setCharacter(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.socket.on('chat', (event) => {
|
this.socket.on('chat', (event) => {
|
||||||
const player = this.players.find(
|
const player = this.players.find(
|
||||||
(item) => item.user.id === event.sender.id,
|
(item) => item.user.id === event.sender.id,
|
||||||
@ -167,7 +189,25 @@ export class Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private experimentalPlayerCmd(message: string, sender: IcyNetUser) {
|
private experimentalPlayerCmd(message: string, sender: IcyNetUser) {
|
||||||
if (message.startsWith('!party') && this.me.id === sender.id) {
|
if (this.me.id === sender.id) {
|
||||||
|
if (message.startsWith('!color')) {
|
||||||
|
const [cmd, color] = message.split(' ');
|
||||||
|
try {
|
||||||
|
const colorr = new Color(color);
|
||||||
|
if (!colorr) {
|
||||||
|
throw 'invalid';
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
this.chat.addMessage('Invalid color.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.player.setColor(color);
|
||||||
|
this.socket.emit('character', { color });
|
||||||
|
localStorage.setItem('color', color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.startsWith('!party')) {
|
||||||
const array = message.split(' ');
|
const array = message.split(' ');
|
||||||
const name = array.slice(2).join(' ');
|
const name = array.slice(2).join(' ');
|
||||||
|
|
||||||
@ -194,6 +234,7 @@ export class Game {
|
|||||||
|
|
||||||
localStorage.setItem('party', this.party.join('|'));
|
localStorage.setItem('party', this.party.join('|'));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
|
@ -2,6 +2,7 @@ import { IcyNetUser } from '../../common/types/user';
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { PonyEntity } from './pony';
|
import { PonyEntity } from './pony';
|
||||||
import {
|
import {
|
||||||
|
CharacterPacket,
|
||||||
FullStatePacket,
|
FullStatePacket,
|
||||||
PositionUpdatePacket,
|
PositionUpdatePacket,
|
||||||
} from '../../common/types/packet';
|
} from '../../common/types/packet';
|
||||||
@ -101,13 +102,17 @@ export class PlayerEntity extends PonyEntity {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addUncommittedChanges(packet: PositionUpdatePacket) {
|
public addUncommittedChanges(packet: FullStatePacket) {
|
||||||
const appendix = { ...packet, time: 0.1 };
|
const appendix = { ...packet, time: 0.1 };
|
||||||
this._updateQueue.push(appendix);
|
this._updateQueue.push(appendix);
|
||||||
if (!this._targetFrame) {
|
if (!this._targetFrame) {
|
||||||
this.setFromPacket(packet);
|
this.setFromPacket(packet);
|
||||||
this._targetFrame = appendix;
|
this._targetFrame = appendix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packet.character) {
|
||||||
|
this.setCharacter(packet.character);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(dt: number) {
|
public update(dt: number) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||||
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
||||||
|
import { Color, Mesh, MeshStandardMaterial } from 'three';
|
||||||
|
|
||||||
// Instantiate a loader
|
// Instantiate a loader
|
||||||
const loader = new GLTFLoader();
|
const loader = new GLTFLoader();
|
||||||
@ -26,6 +27,11 @@ class PonyModel {
|
|||||||
// temp: disable frustum culling for eyes
|
// temp: disable frustum culling for eyes
|
||||||
this.ponyModel.children[0].children[2].frustumCulled = false;
|
this.ponyModel.children[0].children[2].frustumCulled = false;
|
||||||
|
|
||||||
|
// (
|
||||||
|
// (this.ponyModel.children[0].children[1] as Mesh)
|
||||||
|
// .material as MeshStandardMaterial
|
||||||
|
// ).color = new Color(0xffffff);
|
||||||
|
|
||||||
resolve(gltf.scene);
|
resolve(gltf.scene);
|
||||||
|
|
||||||
// gltf.animations; // Array<THREE.AnimationClip>
|
// gltf.animations; // Array<THREE.AnimationClip>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils';
|
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils';
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import modelLoaderInstance from './pony-loader';
|
import modelLoaderInstance from './pony-loader';
|
||||||
import { FullStatePacket } from '../../common/types/packet';
|
import { CharacterPacket, FullStatePacket } from '../../common/types/packet';
|
||||||
import { NameTag } from './nametag';
|
import { NameTag } from './nametag';
|
||||||
import { CanvasUtils } from './canvas-utils';
|
import { CanvasUtils } from './canvas-utils';
|
||||||
|
import { Mesh, MeshStandardMaterial, Color } from 'three';
|
||||||
|
|
||||||
const nameTagBuilder = new CanvasUtils({
|
const nameTagBuilder = new CanvasUtils({
|
||||||
fill: false,
|
fill: false,
|
||||||
@ -19,6 +20,7 @@ export class PonyEntity {
|
|||||||
public mixer!: THREE.AnimationMixer;
|
public mixer!: THREE.AnimationMixer;
|
||||||
public container!: THREE.Object3D;
|
public container!: THREE.Object3D;
|
||||||
public model!: THREE.Object3D;
|
public model!: THREE.Object3D;
|
||||||
|
public material!: THREE.MeshStandardMaterial;
|
||||||
public walkAnimationState = 0;
|
public walkAnimationState = 0;
|
||||||
public idleAction: THREE.AnimationAction;
|
public idleAction: THREE.AnimationAction;
|
||||||
public walkAction: THREE.AnimationAction;
|
public walkAction: THREE.AnimationAction;
|
||||||
@ -27,6 +29,11 @@ export class PonyEntity {
|
|||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
this.model = (SkeletonUtils as any).clone(modelLoaderInstance.ponyModel);
|
this.model = (SkeletonUtils as any).clone(modelLoaderInstance.ponyModel);
|
||||||
|
this.material = (
|
||||||
|
(this.model.children[0].children[1] as Mesh)
|
||||||
|
.material as MeshStandardMaterial
|
||||||
|
).clone();
|
||||||
|
(this.model.children[0].children[1] as Mesh).material = this.material;
|
||||||
this.mixer = new THREE.AnimationMixer(this.model);
|
this.mixer = new THREE.AnimationMixer(this.model);
|
||||||
this.idleAction = this.mixer.clipAction(modelLoaderInstance.animations[0]);
|
this.idleAction = this.mixer.clipAction(modelLoaderInstance.animations[0]);
|
||||||
this.walkAction = this.mixer.clipAction(modelLoaderInstance.animations[2]);
|
this.walkAction = this.mixer.clipAction(modelLoaderInstance.animations[2]);
|
||||||
@ -47,6 +54,12 @@ export class PonyEntity {
|
|||||||
this.mixer.update(dt);
|
this.mixer.update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.model = null;
|
||||||
|
this.material.dispose();
|
||||||
|
this.nameTag?.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
public addNameTag(name: string) {
|
public addNameTag(name: string) {
|
||||||
this.nameTag = new NameTag(nameTagBuilder, name);
|
this.nameTag = new NameTag(nameTagBuilder, name);
|
||||||
this.nameTag.tag.position.set(0, 1.8, 0.5);
|
this.nameTag.tag.position.set(0, 1.8, 0.5);
|
||||||
@ -68,4 +81,14 @@ export class PonyEntity {
|
|||||||
this.walkAction.crossFadeTo(this.idleAction.reset(), 0.5, false).play();
|
this.walkAction.crossFadeTo(this.idleAction.reset(), 0.5, false).play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setColor(color: number | string) {
|
||||||
|
this.material.color = new Color(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setCharacter(packet: CharacterPacket) {
|
||||||
|
if (packet.color) {
|
||||||
|
this.setColor(packet.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@ export interface FullStatePacket {
|
|||||||
position?: number[];
|
position?: number[];
|
||||||
rotation?: (number | string)[];
|
rotation?: (number | string)[];
|
||||||
animState?: number;
|
animState?: number;
|
||||||
|
character?: CharacterPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CharacterPacket {
|
||||||
|
color?: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompositePacket extends IcyNetUser, FullStatePacket {}
|
export interface CompositePacket extends IcyNetUser, FullStatePacket {}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { Server, Socket } from 'socket.io';
|
import { Server, Socket } from 'socket.io';
|
||||||
import { RequestHandler } from 'express';
|
import { RequestHandler } from 'express';
|
||||||
import { IcyNetUser } from '../../common/types/user';
|
import { IcyNetUser } from '../../common/types/user';
|
||||||
import { PositionUpdatePacket } from '../../common/types/packet';
|
import {
|
||||||
|
CharacterPacket,
|
||||||
|
PositionUpdatePacket,
|
||||||
|
} from '../../common/types/packet';
|
||||||
|
|
||||||
const PLACEHOLDER_USER = (socket: Socket): IcyNetUser => {
|
const PLACEHOLDER_USER = (socket: Socket): IcyNetUser => {
|
||||||
const randomName = `player-${socket.id.substring(0, 8)}`;
|
const randomName = `player-${socket.id.substring(0, 8)}`;
|
||||||
@ -55,6 +58,7 @@ export class Game {
|
|||||||
position: [0, 0, 0],
|
position: [0, 0, 0],
|
||||||
rotation: [0, 0, 0, 'XYZ'],
|
rotation: [0, 0, 0, 'XYZ'],
|
||||||
animState: 0,
|
animState: 0,
|
||||||
|
character: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.emit(
|
socket.emit(
|
||||||
@ -78,6 +82,18 @@ export class Game {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('character', (info: CharacterPacket) => {
|
||||||
|
socket.data.playerinfo.character = {
|
||||||
|
...socket.data.playerinfo.character,
|
||||||
|
...info,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.io.emit('playercharacter', {
|
||||||
|
id: socket.data.user.id,
|
||||||
|
...socket.data.playerinfo.character,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('chat-send', (raw) => {
|
socket.on('chat-send', (raw) => {
|
||||||
const message = raw.trim().substring(0, 260);
|
const message = raw.trim().substring(0, 260);
|
||||||
this.io.emit('chat', { sender: publicUserInfo, message });
|
this.io.emit('chat', { sender: publicUserInfo, message });
|
||||||
|
Loading…
Reference in New Issue
Block a user