@@ -5,7 +5,8 @@ import Reversi from '../../../../../games/reversi/core';
|
||||
import * as maps from '../../../../../games/reversi/maps';
|
||||
import Channel from '../../channel';
|
||||
import { ReversiGame } from '../../../../../models/entities/games/reversi/game';
|
||||
import { ReversiGames } from '../../../../../models';
|
||||
import { ReversiGames, Users } from '../../../../../models';
|
||||
import { User } from '../../../../../models/entities/user';
|
||||
|
||||
export default class extends Channel {
|
||||
public readonly chName = 'gamesReversiGame';
|
||||
@@ -13,17 +14,58 @@ export default class extends Channel {
|
||||
public static requireCredential = false;
|
||||
|
||||
private gameId: ReversiGame['id'] | null = null;
|
||||
private watchers: Record<User['id'], Date> = {};
|
||||
private emitWatchersIntervalId: any;
|
||||
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
this.gameId = params.gameId;
|
||||
|
||||
// Subscribe game stream
|
||||
this.subscriber.on(`reversiGameStream:${this.gameId}`, data => {
|
||||
this.subscriber.on(`reversiGameStream:${this.gameId}`, this.onEvent);
|
||||
this.emitWatchersIntervalId = setInterval(this.emitWatchers, 5000);
|
||||
|
||||
const game = await ReversiGames.findOne(this.gameId!);
|
||||
if (game == null) throw new Error('game not found');
|
||||
|
||||
// 観戦者イベント
|
||||
this.watch(game);
|
||||
}
|
||||
|
||||
@autobind
|
||||
private onEvent(data: any) {
|
||||
if (data.type === 'watching') {
|
||||
const id = data.body;
|
||||
this.watchers[id] = new Date();
|
||||
} else {
|
||||
this.send(data);
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
private async emitWatchers() {
|
||||
const now = new Date();
|
||||
|
||||
// Remove not watching users
|
||||
for (const [userId, date] of Object.entries(this.watchers)) {
|
||||
if (now.getTime() - date.getTime() > 5000) delete this.watchers[userId];
|
||||
}
|
||||
|
||||
const users = await Users.packMany(Object.keys(this.watchers), null, { detail: false });
|
||||
|
||||
this.send({
|
||||
type: 'watchers',
|
||||
body: users,
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
public dispose() {
|
||||
// Unsubscribe events
|
||||
this.subscriber.off(`reversiGameStream:${this.gameId}`, this.onEvent);
|
||||
clearInterval(this.emitWatchersIntervalId);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public onMessage(type: string, body: any) {
|
||||
switch (type) {
|
||||
@@ -314,5 +356,17 @@ export default class extends Channel {
|
||||
if (crc32.toString() !== game.crc32) {
|
||||
this.send('rescue', await ReversiGames.pack(game, this.user));
|
||||
}
|
||||
|
||||
// ついでに観戦者イベントを発行
|
||||
this.watch(game);
|
||||
}
|
||||
|
||||
@autobind
|
||||
private watch(game: ReversiGame) {
|
||||
if (this.user != null) {
|
||||
if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) {
|
||||
publishReversiGameStream(this.gameId!, 'watching', this.user.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user