From 005290d057dc18b6141af160b77d76fa07193d81 Mon Sep 17 00:00:00 2001 From: Hamcha Date: Wed, 4 Sep 2019 17:57:19 +0200 Subject: [PATCH] Add received handlers, force rename on name conflicts --- src/network/client.ts | 8 +++- src/network/local.ts | 19 ++++++++ src/network/peer.ts | 3 +- src/network/server.ts | 108 +++++++++++++++++++++++++++++------------- src/network/types.ts | 15 +++++- 5 files changed, 116 insertions(+), 37 deletions(-) create mode 100644 src/network/local.ts diff --git a/src/network/client.ts b/src/network/client.ts index 1b98418..50ace8a 100644 --- a/src/network/client.ts +++ b/src/network/client.ts @@ -1,6 +1,6 @@ import NetworkPeer from "./peer"; import { DataConnection } from "peerjs"; -import { PeerMetadata } from "./types"; +import { PeerMetadata, NetworkMessage } from "./types"; export default class PeerClient extends NetworkPeer { private connection: DataConnection; @@ -11,5 +11,11 @@ export default class PeerClient extends NetworkPeer { metadata, reliable: true }); + this.connection.on("open", () => { + console.info("Connected to server"); + }); + this.connection.on("data", this._received); } + + private _received(data: NetworkMessage) {} } diff --git a/src/network/local.ts b/src/network/local.ts new file mode 100644 index 0000000..4ee071a --- /dev/null +++ b/src/network/local.ts @@ -0,0 +1,19 @@ +import NetworkPeer from "./peer"; +import { DataConnection } from "peerjs"; +import { PeerMetadata, NetworkMessage } from "./types"; + +export default class LocalClient { + public metadata: PeerMetadata; + + public constructor(metadata: PeerMetadata) { + this.metadata = metadata; + } + + public receive(data: NetworkMessage) { + //TODO + } + + public send(data: NetworkMessage) { + //TODO + } +} diff --git a/src/network/peer.ts b/src/network/peer.ts index d4b8db3..7658fca 100644 --- a/src/network/peer.ts +++ b/src/network/peer.ts @@ -1,4 +1,5 @@ import Peer, { DataConnection } from "peerjs"; +import { NetworkMessage } from "./types"; export default class NetworkPeer { protected peer: Peer; @@ -9,7 +10,7 @@ export default class NetworkPeer { }); } - protected send(conn: DataConnection, data: T) { + protected send(conn: DataConnection, data: T) { //TODO Debugging support? conn.send(data); } diff --git a/src/network/server.ts b/src/network/server.ts index 92aa7b0..25e60f4 100644 --- a/src/network/server.ts +++ b/src/network/server.ts @@ -8,30 +8,53 @@ import { PasswordResponse, PeerMetadata, JoinMessage, - RoomInfoMessage + RoomInfoMessage, + Player, + NetworkMessage, + RenameMessage } from "./types"; +import LocalClient from "./local"; + +// Increment name, add number at the end if not present +// Examples: +// Guest -> Guest1 +// Guest1 -> Guest2 +// Guest9 -> Guest10 +function nextName(name: string): string { + let i = 1; + for (; i < name.length; i++) { + if (!isNaN(Number(name.slice(i - name.length)))) { + break; + } + } + return name.substr(0, i) + (Number(name.slice(i)) + 1); +} export default class PeerServer extends NetworkPeer { private room: Room; - public constructor(roomInfo: RoomInfo) { + public constructor(roomInfo: RoomInfo, local: LocalClient) { super(); + let players: Record = {}; + players[local.metadata.name] = { + kind: "local", + name: local.metadata.name, + client: local + }; this.room = { info: roomInfo, - players: { - //TODO Add local player - } + players }; this.peer.on("connection", this._connection); } - private async _connection(conn: DataConnection) { + private _connection(conn: DataConnection) { + const metadata = conn.metadata as PeerMetadata; + console.info("%s (%s) connected!", metadata.name, conn.label); + + // // Check if this connection should be allowed - console.info( - "%s (%s) connected!", - (conn.metadata as PeerMetadata).name, - conn.label - ); + // // Check if room is full if (this.playerCount >= this.room.info.max_players) { @@ -40,34 +63,48 @@ export default class PeerServer extends NetworkPeer { return; } + // Check if there is already a player called that way + if (this.room.players[metadata.name]) { + // Force rename + const newname = nextName(metadata.name); + this.send(conn, { + kind: "rename", + oldname: metadata.name, + newname: newname + }); + metadata.name = newname; + } + + // Check for password if (this.room.info.password != "") { + const checkPasswordResponse = (data: any) => { + try { + let resp = data as PasswordResponse; + if (resp.password != this.room.info.password) { + this.send(conn, { + kind: "error", + error: "invalid password" + }); + return; + } + conn.off("data", checkPasswordResponse); + this.addPlayer(conn); + } catch (e) { + this.send(conn, { + kind: "error", + error: "not a password" + }); + } + }; + this.send(conn, { kind: "password-req" }); - conn.on("data", this.checkPasswordResponse.bind(this, conn)); + conn.on("data", checkPasswordResponse); return; } this.addPlayer(conn); } - private checkPasswordResponse(conn: DataConnection, data: any) { - try { - let resp = data as PasswordResponse; - if (resp.password != this.room.info.password) { - this.send(conn, { - kind: "error", - error: "invalid password" - }); - return; - } - this.addPlayer(conn); - } catch (e) { - this.send(conn, { - kind: "error", - error: "not a password" - }); - } - } - private addPlayer(conn: DataConnection) { const playerName = conn.metadata.name; this.room.players[playerName] = { @@ -76,6 +113,9 @@ export default class PeerServer extends NetworkPeer { conn: conn }; + // Start listening for new messages + conn.on("data", this._received.bind(this, this.room.players[playerName])); + // Send the player info about the room this.send(conn, { kind: "room-info", @@ -93,17 +133,19 @@ export default class PeerServer extends NetworkPeer { }); } + private _received(player: Player, data: NetworkMessage) {} + private get playerCount(): number { return Object.keys(this.room.players).length; } - private broadcast(message: T) { + private broadcast(message: T) { for (const playerName in this.room.players) { const player = this.room.players[playerName]; if (player.kind == "remote") { this.send(player.conn, message); } else { - //TODO Local wrapper + player.client.receive(message); } } } diff --git a/src/network/types.ts b/src/network/types.ts index 24edf57..d8d0c47 100644 --- a/src/network/types.ts +++ b/src/network/types.ts @@ -1,8 +1,10 @@ import { DataConnection } from "peerjs"; +import LocalClient from "./local"; export interface LocalPlayer { kind: "local"; name: string; + client: LocalClient; } export interface NetworkPlayer { @@ -11,13 +13,15 @@ export interface NetworkPlayer { conn: DataConnection; } +export type Player = NetworkPlayer | LocalPlayer; + export interface PeerMetadata { name: string; } export interface Room { info: RoomInfo; - players: Record; + players: Record; } export interface RoomInfo { @@ -61,7 +65,8 @@ export type NetworkMessage = | PasswordResponse | ErrorMessage | RoomInfoMessage - | JoinMessage; + | JoinMessage + | RenameMessage; export interface PasswordRequest { kind: "password-req"; @@ -83,6 +88,12 @@ export interface JoinMessage { name: string; } +export interface RenameMessage { + kind: "rename"; + oldname: string; + newname: string; +} + export interface ErrorMessage { kind: "error"; error: string;