mlpcardgame/src/network/Client.ts

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;