Merge pull request #11 from jhalitaksoy/feature/user-status
Feature/user status
This commit is contained in:
commit
e53c7bcffc
@ -8,3 +8,4 @@ export const channel_on_game_crashed = "on_game_crashed"
|
|||||||
export const channel_on_game_user_leave = "on_game_user_leave"
|
export const channel_on_game_user_leave = "on_game_user_leave"
|
||||||
export const channel_ping = "ping"
|
export const channel_ping = "ping"
|
||||||
export const channel_pong = "pong"
|
export const channel_pong = "pong"
|
||||||
|
export const channel_on_user_connection_change = "channel_on_user_connection_change"
|
||||||
@ -9,11 +9,13 @@ import {
|
|||||||
channel_on_game_crashed,
|
channel_on_game_crashed,
|
||||||
channel_on_game_start,
|
channel_on_game_start,
|
||||||
channel_on_game_update,
|
channel_on_game_update,
|
||||||
channel_on_game_user_leave
|
channel_on_game_user_leave,
|
||||||
|
channel_on_user_connection_change
|
||||||
} from "../consts/channel_names";
|
} from "../consts/channel_names";
|
||||||
import { GameMove } from "../models/GameMove";
|
import { GameMove } from "../models/GameMove";
|
||||||
import { GameCrashManager } from "./GameCrashManager";
|
import { GameCrashManager } from "./GameCrashManager";
|
||||||
import { MatchMaker } from "../matchmaker/MatchMaker";
|
import { MatchMaker } from "../matchmaker/MatchMaker";
|
||||||
|
import { UserConnectionInfo } from "../models/UserConnectionInfo";
|
||||||
|
|
||||||
export class GameManager {
|
export class GameManager {
|
||||||
gameStore: GameStore;
|
gameStore: GameStore;
|
||||||
@ -30,6 +32,7 @@ export class GameManager {
|
|||||||
private initialize() {
|
private initialize() {
|
||||||
this.listenOnPlayersPaired();
|
this.listenOnPlayersPaired();
|
||||||
this.listenRtmtMessages();
|
this.listenRtmtMessages();
|
||||||
|
this.listenUserConnectionChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
private listenRtmtMessages() {
|
private listenRtmtMessages() {
|
||||||
@ -108,6 +111,16 @@ export class GameManager {
|
|||||||
public startGame(game: MancalaGame) {
|
public startGame(game: MancalaGame) {
|
||||||
this.rtmt.sendMessage(game.player1Id, channel_on_game_start, game);
|
this.rtmt.sendMessage(game.player1Id, channel_on_game_start, game);
|
||||||
this.rtmt.sendMessage(game.player2Id, channel_on_game_start, game);
|
this.rtmt.sendMessage(game.player2Id, channel_on_game_start, game);
|
||||||
|
this.sendUserConnectionInfo(game, game.player1Id);
|
||||||
|
this.sendUserConnectionInfo(game, game.player2Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendUserConnectionInfo(game: MancalaGame, playerId: string, isOnline?: boolean) {
|
||||||
|
//todo: reimplement when watch game feature added
|
||||||
|
const _isOnline = isOnline === undefined ? this.rtmt.isClientOnline(playerId) : isOnline;
|
||||||
|
const otherUser = game.player1Id === playerId ? game.player2Id : game.player1Id;
|
||||||
|
const userConnectionInfo: UserConnectionInfo = { userId: playerId, isOnline: _isOnline };
|
||||||
|
this.rtmt.sendMessage(otherUser, channel_on_user_connection_change, userConnectionInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteGame(game: MancalaGame) {
|
public deleteGame(game: MancalaGame) {
|
||||||
@ -116,4 +129,17 @@ export class GameManager {
|
|||||||
this.gameStore.remove(game.player2Id);
|
this.gameStore.remove(game.player2Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private listenUserConnectionChange() {
|
||||||
|
this.rtmt.listenOnClientConnectionChange((clientId: string, isOnline: boolean) => {
|
||||||
|
const game = this.gameStore.get(clientId);
|
||||||
|
if (game) {
|
||||||
|
this.sendUserConnectionInfo(game, clientId, isOnline);
|
||||||
|
if (isOnline) {
|
||||||
|
const otherUser = game.player1Id === clientId ? game.player2Id : game.player1Id;
|
||||||
|
this.sendUserConnectionInfo(game, otherUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
6
src/models/User.ts
Normal file
6
src/models/User.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface User {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
isOnline: boolean;
|
||||||
|
isAnonymous: boolean;
|
||||||
|
}
|
||||||
4
src/models/UserConnectionInfo.ts
Normal file
4
src/models/UserConnectionInfo.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface UserConnectionInfo {
|
||||||
|
userId: string;
|
||||||
|
isOnline: boolean;
|
||||||
|
}
|
||||||
@ -1,8 +1,10 @@
|
|||||||
export type Bytes = Buffer
|
export type Bytes = Buffer
|
||||||
export type OnMessage = (clientID: string, message: Object) => any
|
export type OnMessage = (clientID: string, message: Object) => any
|
||||||
|
export type OnClientConnectionChange = (clientID: string, isOnline : boolean) => any
|
||||||
|
|
||||||
export interface RTMT {
|
export interface RTMT {
|
||||||
sendMessage: (clientID: string, channel: string, message: Object) => any;
|
sendMessage: (clientID: string, channel: string, message: Object) => any;
|
||||||
listenMessage: (channel: string, callback: OnMessage) => any;
|
listenMessage: (channel: string, callback: OnMessage) => any;
|
||||||
isClientOnline(clientID: string): boolean;
|
isClientOnline(clientID: string): boolean;
|
||||||
|
listenOnClientConnectionChange(onUserConnectionChange: OnClientConnectionChange): void;
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { decode, encode } from "./encode_decode_message"
|
import { decode, encode } from "./encode_decode_message"
|
||||||
import { Bytes, OnMessage, RTMT } from "./rtmt"
|
import { Bytes, OnClientConnectionChange, OnMessage, RTMT } from "./rtmt"
|
||||||
|
|
||||||
import WebSocket from "ws"
|
import WebSocket from "ws"
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
@ -17,6 +17,8 @@ export class RTMTWS implements RTMT {
|
|||||||
|
|
||||||
private pingInterval?: NodeJS.Timeout = undefined;
|
private pingInterval?: NodeJS.Timeout = undefined;
|
||||||
|
|
||||||
|
onUserConnectionChange?: OnClientConnectionChange;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.messageChannels = new Map<String, OnMessage>()
|
this.messageChannels = new Map<String, OnMessage>()
|
||||||
this.wsServer = null
|
this.wsServer = null
|
||||||
@ -32,6 +34,7 @@ export class RTMTWS implements RTMT {
|
|||||||
const regexResult = req.url.split(RegExp("\/\?userKey="));
|
const regexResult = req.url.split(RegExp("\/\?userKey="));
|
||||||
const clientID = regexResult[1]
|
const clientID = regexResult[1]
|
||||||
this.clients.set(clientID, ws)
|
this.clients.set(clientID, ws)
|
||||||
|
this.onUserConnectionChange?.(clientID, true);
|
||||||
ws.on("message", (messageBytes: string) => {
|
ws.on("message", (messageBytes: string) => {
|
||||||
this.onWebSocketMessage(clientID, messageBytes)
|
this.onWebSocketMessage(clientID, messageBytes)
|
||||||
})
|
})
|
||||||
@ -39,6 +42,7 @@ export class RTMTWS implements RTMT {
|
|||||||
ws.on("close", (code: number, reason: string) => {
|
ws.on("close", (code: number, reason: string) => {
|
||||||
console.log("WS Closed! code : " + code + " reason : " + reason);
|
console.log("WS Closed! code : " + code + " reason : " + reason);
|
||||||
this.clients.delete(clientID)
|
this.clients.delete(clientID)
|
||||||
|
this.onUserConnectionChange?.(clientID, false);
|
||||||
})
|
})
|
||||||
|
|
||||||
ws.on("error", (err: Error) => {
|
ws.on("error", (err: Error) => {
|
||||||
@ -130,4 +134,8 @@ export class RTMTWS implements RTMT {
|
|||||||
isClientOnline(clientID: string): boolean {
|
isClientOnline(clientID: string): boolean {
|
||||||
return this.clients.has(clientID);
|
return this.clients.has(clientID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listenOnClientConnectionChange(onUserConnectionChange: OnClientConnectionChange) {
|
||||||
|
this.onUserConnectionChange = onUserConnectionChange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user