mlpcardgame/src/network/Client.ts

106 lines
2.8 KiB
TypeScript

import EventEmitter from "eventemitter3";
import Vue from "vue";
import { NetworkMessage, PasswordResponse, PeerMetadata, RoomInfo } from "./types";
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;
this.emit("handshake");
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;
}
// Only mutate player list if we have one
// This is because rename messages can be received during the initial
// handshake, to signal a forced name change before joining.
if (this.players) {
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;
}
Vue.set(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.emit("player-left", data.name);
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;