MWSE/sdk/Room.js

125 lines
4.0 KiB
JavaScript

import MWSEEventTarget from './EventTarget.js';
import { RoomInfo } from './RoomInfo.js';
export default class Room extends MWSEEventTarget {
constructor(mwse) {
super();
this.mwse = mwse;
this.peers = new Map();
this.info = new RoomInfo(this);
this.options = undefined;
this.config = undefined;
this.roomId = undefined;
this.accessType = undefined;
this.joinType = undefined;
this.name = undefined;
this.owner = undefined;
}
setRoomOptions(options) {
if (typeof options === 'string') {
this.roomId = options;
} else {
const defaults = {
joinType: 'free',
ifexistsJoin: true,
accessType: 'private',
notifyActionInvite: true,
notifyActionJoined: true,
notifyActionEjected: true,
autoFetchInfo: true
};
this.config = Object.assign(defaults, options);
}
}
setRoomId(uuid) {
this.roomId = uuid;
}
async createRoom(roomOptions) {
const config = this.config || roomOptions;
const result = await this.mwse.EventPooling.request({ type: 'create-room', ...config });
if (result.status === 'fail') {
if (result.message === 'ALREADY-EXISTS' && this.config?.ifexistsJoin) {
return this.join();
}
throw new Error(result.message || result.messages);
}
this.options = { ...this.config, ...result.room };
this.roomId = result.room.id;
this.mwse.rooms.set(this.roomId, this);
}
async join() {
const result = await this.mwse.EventPooling.request({
type: 'joinroom',
name: this.config.name,
credential: this.config.credential,
autoFetchInfo: this.config.autoFetchInfo || false
});
if (result.status === 'fail') throw new Error(result.message);
this.options = { ...this.config, ...result.room };
if (result.info) this.info.info = result.info;
this.roomId = result.room.id;
this.mwse.rooms.set(this.roomId, this);
}
async eject() {
const { type } = await this.mwse.EventPooling.request({
type: 'ejectroom',
roomId: this.roomId
});
this.peers.clear();
if (type === 'success') this.mwse.rooms.delete(this.roomId);
}
async send(pack, wom = false, handshake = false) {
if (!this.mwse.writable) {
console.warn('MWSE: socket is not writable');
return;
}
if (handshake) {
const { type } = await this.mwse.EventPooling.request({
type: 'pack/room', pack, to: this.roomId, wom, handshake
});
if (type === 'fail') throw new Error('Cannot send message to room');
} else {
// WOM broadcast — fire-and-forget, no waiter (#33).
this.mwse.EventPooling.only({ type: 'pack/room', pack, to: this.roomId, wom, handshake });
}
}
async fetchPeers(filter, onlyNumber = false) {
if (onlyNumber) {
const { count } = await this.mwse.EventPooling.request({
type: 'room/peer-count',
roomId: this.roomId,
filter: filter || {}
});
return count;
}
const { status, peers } = await this.mwse.EventPooling.request({
type: 'room-peers',
roomId: this.roomId,
filter: filter || {}
});
if (status === 'fail') throw new Error('Cannot fetch peers from room');
const result = [];
for (const peerId of peers) {
const peer = this.mwse.peer(peerId, true);
result.push(peer);
this.peers.set(peerId, peer);
}
return result;
}
}