UNPKG

board-game

Version:

an online board game engine

206 lines (204 loc) 7.42 kB
const extend = require('extend'); const Role = require('./role'); const Team = require('./team'); const Game = require('./game'); const Messages = require('./messages'); const Dispatcher = require('./dispatcher'); class Room extends Dispatcher { constructor(server, creator, settings) { super(); this.server = server; this.creator = creator; this.status = 'waiting'; let role = new (this.server.config.Role || Role)(this.server, this, creator); this.roles = [ role ]; this.teams = Team.createTeams(this.server, role); this.disposed = false; this.settings = extend(true, { publish: false }, settings); this.id = Room.newId(this.server); this.server.rooms.set(this.id, this); this.messages = new Messages(); console.log(`用户${ creator.name || creator.id }创建了游戏房间${ this.id }`); } dispose() { super.dispose(); this.disposed = true; this.teams.forEach(team => team.dispose()); this.roles = []; this.server.rooms.delete(this.id); this.server.roomIds.push(this.id); } join(player) { if (this.teams.every(team => team.emptyCount === 0)) throw '此房间人数已满'; if (this.status !== 'waiting') throw '此房间可能在游戏中,不能加入此房间'; let team = this.teams.reduce((s, t, i) => this.teams[s].emptyCount >= t.emptyCount ? s : i, 0); let index = this.teams[team].emptyIndex; let role = new (this.server.config.Role || Role)(this.server, this, player, team, index); this.roles.push(role); this.teams[team].add(role); player.room = this; console.log(`用户${ player.name || player.id }加入了游戏房间${ this.id }`); } exit(role, focus = false) { if (this.disposed || !focus && this.game) throw ''; if (!focus && this.creator === role.player) { this.dispose(); console.log(`用户${ role.player.name || role.player.id }解散了游戏房间${ this.id }`); } else { this.roles.splice(this.roles.indexOf(role), 1); this.teams[role.team].remove(role); if (this.game) this.game.exit(role); delete role.player.room; console.log(`用户${ role.player.name || role.player.id }退出了游戏房间${ this.id }`); if (this.creator === role.player) { if (this.roles.length) { this.creator = this.roles[0].player; } else { this.dispose(); } } } } start(role) { if (this.disposed) throw ''; if (!this.canStart) throw ''; if (this.creator.id !== role.player.id) throw ''; if (this.server.config.team && this.server.config.team.sort && this.status === 'waiting') { this.status = 'sorting'; } else { this.roles.forEach(role => role.confirm()); this.game = new (this.server.config.Game || Game)(this.server, this); this.status = 'gaming'; console.log(`游戏房间${ this.id }开始了新的游戏`); } } over() { if (!this.game) throw ''; delete this.game; this.status = 'waiting'; } move(role, team, index) { if (role.player === this.creator) { throw ''; } else { if (this.teams[team].roles[index] === true) { this.teams[role.team].roles[role.index] = true; this.teams[team].roles[index] = role; role.team = team; role.index = index; } else { throw ''; } } } disable(role, team, index) { if (role.player === this.creator && this.teams[team].roles[index] === true) { this.teams[team].roles[index] = false; } else { throw ''; } } enable(role, team, index) { if (role.player === this.creator && this.teams[team].roles[index] === false) { this.teams[team].roles[index] = true; } else { throw ''; } } kick(role, team, index) { if (role.player === this.creator) { if (this.teams[team].roles[index] instanceof Role) { this.teams[team].roles[index].exit(); } else { throw ''; } } else { throw ''; } } leave(force = false) { if (this.roles.every(role => role.player.leaved)) { if (this.roles.length > 1 || force) { if (this.game) this.game.over(); this.roles.forEach(role => this.exit(role)); } else { setTimeout(() => this.leave(true), 30000); } } } message(role, message) { this.messages.append({ role: role.data, message: message }); } get canStart() { let config = this.server.config; return !this.roles.some(role => role.player.leaved) && this.teams.every(team => team.count >= (config.team.min || 1)) && new Set(this.teams.map(team => team.count)).size === 1 && (!config.team.regroup || this.roles.length % Number(config.team.regroup) === 0); } get data() { return { id: this.id, creator: { id: this.creator.id, name: this.creator.name }, settings: this.settings, canStart: this.canStart, teams: this.teams.map(team => team.data), game: this.game && this.game.data, status: this.status, messages: [] } } get summary() { return { id: this.id, creator: { id: this.creator.id, name: this.creator.name }, length: this.teams.map(team => team.openCount).reduce((s, t) => s + t, 0), empty: this.teams.map(team => team.emptyCount).reduce((s, t) => s + t, 0), status: this.status } } static get(server, gameId) { if (server.rooms.has(gameId)) { return server.rooms.get(gameId); } else { throw '无此游戏房间'; } } static newId(server) { if (server.roomIds.length) return server.roomIds.pop(); let size = Math.max(server.rooms.size, 999); let base = 10; while (size % base !== size) base *= 10; while(true) { let id = String(parseInt(Math.random() * size) + base); if (!server.rooms.has(id)) return id; } } static list(server, page) { let list = []; let current = 0; page = page || 0; for (let room of server.rooms.values()) { if (room.settings.publish) { if (current >= page * 20) { list.push(room); } if (list.length === 20) { return list; } current++ } } return list; } } module.exports = Room;