UNPKG

janusweb

Version:
445 lines (425 loc) 14.1 kB
elation.elements.define('janus-comms-panel', class extends elation.elements.base { create() { this.defineAttributes({ labelfont: { type: 'string', default: 'monospace' }, }); this.player = player; this.client = this.getClient(); this.janusweb = this.client.janusweb; this.elements = elation.elements.fromTemplate('janus.comms.panel', this); if (typeof room != 'undefined') { this.room = room; } } getClient() { var node = this; while (node) { if (node.tagName == 'JANUS-UI-MAIN') { return node.client; } node = node.parentNode } } }); elation.elements.define('janus-comms-status', class extends elation.elements.base { init() { super.init(); this.defineAttributes({ state: { type: 'string', default: 'disconnected' } }); } create() { this.player = player; this.userid = player.getNetworkUsername(); if (typeof room != 'undefined') { this.room = room; } if (janus.network) { this.server = janus.network.getServerForRoom(room); if (this.server) { this.server.addEventListener('connect', ev => this.handleServerConnect(ev)); this.server.addEventListener('connecting', ev => this.handleServerConnecting(ev)); this.server.addEventListener('disconnecting', ev => this.handleServerDisconnecting(ev)); this.server.addEventListener('disconnect', ev => this.handleServerDisconnect(ev)); if (this.server.status == 1) { this.state = 'connecting'; } else if (this.server.status == 2) { this.state = 'connected'; } } else if (room.private) { this.state = 'private'; } else { this.state = 'disconnected'; } } this.refresh(); //elation.events.add(player._target, 'username_change', (ev) => this.handleUsernameChange(ev)); } render() { this.innerHTML = ''; this.elements = this.fromTemplate('janus.comms.status', this); } handleUsernameChange(ev) { // Update the userid label if player's name changes this.elements.useridlabel.innerText = player.userid; } handleServerConnect(ev) { this.state = 'connected'; this.refresh(); } handleServerConnecting(ev) { this.state = 'connecting'; this.refresh(); } handleServerDisconnecting(ev) { this.state = 'disconnecting'; this.refresh(); } handleServerDisconnect(ev) { this.state = 'disconnected'; this.refresh(); } }); elation.elements.define('janus-comms-userlist', class extends elation.elements.ui.list { create() { this.defineAttributes({ labelfont: { type: 'string', default: 'monospace' }, }); this.player = player; if (typeof room != 'undefined') { this.room = room; } this.elements = elation.elements.fromTemplate('janus.comms.userlist', this); this.client = this.getClient(); this.janusweb = this.client.janusweb; this.userlist_room = this.elements.userlist_room; this.userlist_online = this.elements.userlist_online; this.userlist_friends = this.elements.userlist_friends; this.usermarkers = {}; elation.events.add(this.janusweb, 'room_load_start', (ev) => { this.updateRoom(ev.data || ev.element); }); elation.events.add(this.janusweb, 'room_change', (ev) => { let newroom = this.janusweb.rooms[this.janusweb.getRoomId(ev.data)]; if (newroom) this.updateRoom(newroom); }); elation.events.add(this.janusweb.network, 'janusweb_user_joined,janusweb_user_left,janusweb_user_disconnected', (ev) => this.updateUsers()); setTimeout(() => { //this.updateUsers(); this.updateRoom(room); }, 100); } getClient() { var node = this; while (node) { if (node.tagName == 'JANUS-UI-MAIN') { return node.client; } node = node.parentNode } } updateRoom(room) { this.room = room; //this.innerHTML = ''; if (!this.elements) { this.elements = elation.elements.fromTemplate('janus.comms.userlist', this); } this.userlist_room = this.userlist_room; this.userlist_online = this.userlist_online; this.userlist_friends = this.userlist_friends; if (room.private) { this.parentNode.elements.chat.open = false; this.elements.userlist_details.open = false; } else { this.parentNode.elements.chat.open = true; this.elements.userlist_details.open = true; } this.updateUsers(); elation.events.add(this.room, 'join', ev => { setTimeout(() => { this.updateUsers(); }, 1000); }); elation.events.add(this.room, 'room_active', ev => { this.updateUsers(); }); } updateUsers() { if (!janus.network) return; var remoteplayers = this.room.players; var users = Object.keys(remoteplayers); //users.unshift(player.userid); if (this.elements.roomusers) { this.elements.roomusers.value = users.length; } this.userlist_room = this.querySelector('ui-list[name="userlist_room"]'); if (this.userlist_room) { this.userlist_room.setItems(users); } for (let k in remoteplayers) { let p = remoteplayers[k]; if (this.usermarkers[k] && this.usermarkers[k].parent !== p.getProxyObject()) { this.usermarkers[k].die(); delete this.usermarkers[k]; } if (!this.usermarkers[k]) { this.usermarkers[k] = p.createObject('playerlabel', { player_name: k, pos: V(p.userid_pos), font: this.labelfont, }); this.usermarkers[k].start(); } } } setFont(fontname) { this.labelfont = fontname; for (let k in this.usermarkers) { this.usermarkers[k].setFont(fontname); } } }); elation.elements.define('janus-comms-chat', class extends elation.elements.base { init() { elation.events.add(janus.network, 'janusweb_user_chat', (ev) => this.handleUserChat(ev)); elation.events.add(janus.network, 'janusweb_user_joined', (ev) => this.handleUserJoined(ev)); elation.events.add(janus.network, 'janusweb_user_left', (ev) => this.handleUserLeft(ev)); elation.events.add(janus.network, 'janusweb_user_disconnected', (ev) => this.handleUserDisconnected(ev)); this.numunread = 0; } create() { this.elements = elation.elements.fromTemplate('janus.comms.chat', this); //this.elements.chatinput.addEventListener('accept', (ev) => this.sendMessage(ev.value)); this.elements.chatinput.onaccept = (ev) => { this.sendMessage(this.elements.chatinput.value); if (false && this.shouldreturnfocus) { player.enable(); this.shouldreturnfocus = false; } else { this.elements.chatinput.focus(); } } this.elements.chatinput.onfocus = (ev) => { this.elements.chatinput.placeholder = 'Type something!'; player.disable(); this.updateUnread(0, true); } this.elements.chatinput.onblur = (ev) => this.elements.chatinput.placeholder = 'Press T for text chat'; window.addEventListener('keydown', (ev) => { // FIXME - this should set up a bindable context in the engine's control system if (ev.keyCode == 84 && player.enabled) { this.elements.chatinput.focus(); // FIXME - we should only return focus to the player if the player was active when we focused the chat this.shouldreturnfocus = true; player.disable(); ev.preventDefault(); } }); elation.events.add(janus._target, 'clientprint', (ev) => this.handleClientPrint(ev.data)); elation.events.add(this.janusweb, 'room_load_start', (ev) => { this.updateRoom(ev.element); }); // FIXME - first element with the current design is a <detail> element, but this is fragile if that changes this.elements[0].addEventListener('toggle', (ev) => this.elements.chatinput.focus()); this.updateRoom(room); if (window.innerWidth < 760) { this.elements.toggle.open = false; } } scrollToBottom() { setTimeout(() => { this.elements.chatlist.scrollTop = this.elements.chatlist.scrollHeight; }, 100); } handleUserJoined(ev) { var data = ev.data; if (!this.elements || !this.elements.chatmessages) return; this.elements.chatmessages.add({ timestamp: new Date().getTime(), type: 'join', userId: data.id, message: 'has joined ' + (data.room.title || data.room.url), raw: false, }); this.scrollToBottom(); } handleUserLeft(ev) { var data = ev.data; if (!this.elements.chatmessages) return; this.elements.chatmessages.add({ timestamp: new Date().getTime(), type: 'part', userId: data.id, message: 'has left the room', raw: false, }); this.scrollToBottom(); } handleUserDisconnected(ev) { var data = ev.data; if (!this.elements.chatmessages) return; this.elements.chatmessages.add({ timestamp: new Date().getTime(), type: 'disconnect', userId: data.id, message: 'has disconnected', raw: false, }); this.scrollToBottom(); } handleUserChat(ev) { var data = ev.data; if (!this.elements.chatmessages) return; this.elements.chatmessages.add({ timestamp: new Date().getTime(), type: 'chat', userId: data.userId, message: data.message.data || data.message.message, raw: false, }); this.scrollToBottom(); this.updateUnread(1); } sendMessage(msg) { if (msg && msg.length > 0) { janus.network.send({'method': 'chat', data: msg}); if (!this.elements.chatmessages) return; let newmsg = this.elements.chatmessages.add({ timestamp: new Date().getTime(), type: 'selfchat', userId: player.userid, message: msg, raw: false, }); this.elements.chatinput.value = ''; this.scrollToBottom(); } } handleClientPrint(msg) { if (!this.elements.chatmessages) return; this.elements.chatmessages.add({ timestamp: new Date().getTime(), type: 'print', userId: 'room', message: msg[0], raw: false, }); this.scrollToBottom(); } updateUnread(incr=0, clear=false) { if (clear) { this.numunread = 0; } if (incr) { this.numunread += incr; } this.elements.unread.count = this.numunread; } updateRoom(newroom) { this.elements.toggle.open = !newroom.private; } }); elation.elements.define('janus-comms-voip', class extends elation.elements.base { init() { } create() { this.elements = elation.elements.fromTemplate('janus.comms.voip', this); } }); janus.registerElement('playerlabel', { player_name: '', font: 'monospace', threshold: .2, create() { this.currentcolor = V(255,255,255); this.canvas = document.createElement('canvas'); this.canvas.width = 512; this.canvas.height = 64; let imageid = this.player_name + '_playerlabel'; this.loadNewAsset('image', { id: imageid, canvas: this.canvas, hasalpha: true, srgb: false, }); this.label = this.createObject('object', { id: 'plane', //collision_id: 'cube', collision_scale: V(.85,7,.1), collision_pos: V(0,-3,0), collidable: false, pickable: true, scale: V(2,.25,1), image_id: imageid, billboard: 'y', lighting: false, opacity: .9, transparent: true, renderorder: 10, shadow_cast: false, }); this.updateCanvas(); this.label.addEventListener('mouseover', ev => this.handleMouseOver(ev)); this.label.addEventListener('mouseout', ev => this.handleMouseOut(ev)); this.label.addEventListener('click', ev => this.handleClick(ev)); console.log('create a player label', this.player_name, this); }, updateCanvas() { let ctx = this.canvas.getContext('2d'); let font = 'bold 60px "' + this.font + '"'; document.fonts.load(font).then(fonts => { ctx.font = font; let measure = ctx.measureText(this.player_name); let width = Math.pow(2, Math.ceil(Math.log(measure.width) / Math.log(2))); this.canvas.width = width; if (this.label) { let oldscale = this.label.scale.x; this.label.scale.x = width / this.canvas.height * this.label.scale.y; this.label.collision_scale = V(.85 / this.label.scale.x, 7, .1); // FIXME - shouldn't be hardcoded } ctx.font = font; ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); let c = this.currentcolor; // background color /* ctx.fillStyle = 'rgba(' + c.x + ', ' + c.y + ', ' + c.z + ', 0.1)'; ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); */ // text with shadow ctx.fillStyle = 'rgba(' + c.x + ', ' + c.y + ', ' + c.z + ', 1)'; ctx.shadowBlur = 2; ctx.shadowColor = 'rgba(0,0,0,1)'; ctx.fillText(this.player_name, (this.canvas.width - measure.width) / 2, this.canvas.height - 10); /* // outer border ctx.strokeStyle = 'rgba(' + c.x + ', ' + c.y + ', ' + c.z + ', 1)'; ctx.shadowColor = 'rgba(' + c.x + ', ' + c.y + ', ' + c.z + ', 1)'; ctx.strokeRect(0, 0, this.canvas.width, this.canvas.height); */ elation.events.fire({element: this.canvas, type: 'update'}); }); }, setFont(fontname) { this.font = fontname; this.updateCanvas(); }, setAudioSource(source) { console.log('got an audio source', source); }, setAudioVolume(volume) { let scale = 1 + (volume > this.threshold ? volume / 2.5 : 0); this.scale.set(scale, scale, scale); if (volume > this.threshold) { this.label.col = '#0f0'; if (this.colorreset) { clearTimeout(this.colorreset); } this.colorreset = setTimeout(() => { this.label.col = '#fff'; this.colorreset = false; }, 200); } }, handleMouseOver(ev) { this.currentcolor.set(0,255,0); this.updateCanvas(); }, handleMouseOut(ev) { this.currentcolor.set(255,255,255); this.updateCanvas(); }, handleClick(ev) { // Present some contextual UI for this user (mute, block, add friend, etc) } });