102 lines
2.5 KiB
TypeScript
102 lines
2.5 KiB
TypeScript
import {
|
|
PeerMetadata,
|
|
NetworkMessage,
|
|
PasswordResponse,
|
|
RoomInfo
|
|
} from "./types";
|
|
import EventEmitter from "eventemitter3";
|
|
|
|
export abstract class Client extends EventEmitter {
|
|
public metadata: PeerMetadata;
|
|
public players!: string[];
|
|
public roomInfo!: RoomInfo;
|
|
|
|
public constructor(metadata: PeerMetadata) {
|
|
super();
|
|
this.metadata = metadata;
|
|
}
|
|
|
|
protected _received(data: NetworkMessage) {
|
|
this.emit("data", data);
|
|
switch (data.kind) {
|
|
// Server is sending over player list and room info
|
|
case "room-info":
|
|
this.roomInfo = data.room;
|
|
this.players = data.players;
|
|
break;
|
|
// Someone changed name (or was forced to)
|
|
case "rename":
|
|
if (data.oldname == this.metadata.name) {
|
|
// We got a name change!
|
|
this.metadata.name = data.newname;
|
|
} else {
|
|
let idx = this.players.indexOf(data.oldname);
|
|
if (idx < 0) {
|
|
// Weird
|
|
console.warn(
|
|
`Someone (${data.oldname}) changed name but wasn't on the player list`
|
|
);
|
|
this.players.push(data.newname);
|
|
break;
|
|
}
|
|
this.players[idx] = data.newname;
|
|
}
|
|
this.emit("rename", data.oldname, data.newname);
|
|
break;
|
|
// A new player joined the room (this includes us)
|
|
case "player-joined":
|
|
this.players.push(data.name);
|
|
this.emit("player-joined", data.name);
|
|
break;
|
|
case "player-left": {
|
|
let idx = this.players.indexOf(data.name);
|
|
if (idx < 0) {
|
|
// Weird
|
|
console.warn(
|
|
`Someone (${data.name}) left but wasn't on the player list`
|
|
);
|
|
break;
|
|
}
|
|
this.players.splice(idx, 1);
|
|
break;
|
|
}
|
|
case "password-req":
|
|
this.emit("password-required");
|
|
break;
|
|
default:
|
|
// For most cases, we can just use the kind as event type
|
|
this.emit(data.kind, data);
|
|
}
|
|
}
|
|
|
|
public password(password: string) {
|
|
this.send<PasswordResponse>({
|
|
kind: "password-resp",
|
|
password
|
|
});
|
|
}
|
|
|
|
public get name(): string {
|
|
return this.metadata.name;
|
|
}
|
|
|
|
public abstract send<T extends NetworkMessage>(data: T): void;
|
|
|
|
public leave(): void {
|
|
this.send({
|
|
kind: "leave-req"
|
|
});
|
|
}
|
|
|
|
public say(to: string | null, message: string) {
|
|
this.send({
|
|
kind: "chat",
|
|
from: this.name,
|
|
to: to ? to : "",
|
|
message
|
|
});
|
|
}
|
|
}
|
|
|
|
export default Client;
|