1export class Pigeon { 2 constructor( pigeons, createPigeonCallback, removePigeonCallback, updatePigeonCallback, updateSpeakerCallback, syncReadyCallback ) { 3 this.pigeons = pigeons 4 this.pigeonsSet = new Set() 5 this.createPigeon = createPigeonCallback 6 this.removePigeon = removePigeonCallback 7 this.updatePigeon = updatePigeonCallback 8 this.updateSpeaker = updateSpeakerCallback 9 this.syncReady = syncReadyCallback 10 this.synced = false 11 this.clockDelta = 0 12 this.lastPositionSyncedTime = Date.now() 13 this.connectToServer() 14 this.position = {} 15 this.emojis = ['ð', 'ð', 'ð', 'ð', 'âº', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð³', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð£', 'ð¢', 'ð', 'ð', 'ðª', 'ð¥', 'ð°', 'ð ', 'ð', 'ð©', 'ð«', 'ð¨', 'ð±', 'ð ', 'ð¡', 'ð¤', 'ð', 'ð', 'ð', 'ð·', 'ð', 'ð´', 'ðµ', 'ð²', 'ð', 'ð¦', 'ð§', 'ð', 'ð¿', 'ð®', 'ð¬', 'ð', 'ð', 'ð¯', 'ð¶', 'ð', 'ð', 'ð', 'ð²', 'ð³', 'ð®', 'ð·', 'ð', 'ð¶', 'ð¦', 'ð§', 'ð¨', 'ð©', 'ð´', 'ðµ', 'ð±', 'ð¼', 'ð¸', 'ðº', 'ð¸', 'ð»', 'ð½', 'ð¼', 'ð', 'ð¿', 'ð¹', 'ð¾', 'ð¹', 'ðº', 'ð', 'ð', 'ð', 'ð', 'ð½', 'ð¶', 'ðº', 'ð±', 'ð', 'ð¹', 'ð°', 'ð¸', 'ð¯', 'ð¨', 'ð»', 'ð·', 'ð½', 'ð®', 'ð', 'ðµ', 'ð', 'ð´', 'ð', 'ð', 'ð¼', 'ð§', 'ð¦', 'ð¤', 'ð¥', 'ð£', 'ð', 'ð', 'ð¢', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð ', 'ð', 'ð¬', 'ð³', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð ', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð', 'ð²', 'ð¡', 'ð', 'ð«', 'ðª', 'ð', 'ð', 'ð©'] 16 this.emoji = this.emojis[Math.floor( Math.random() * this.emojis.length )] 17 this.speaker = null 18 this.lastSpeech = null 19 } 20 21 connectToServer() { 22 try { 23 this.ws = new WebSocket( "wss://pigeon-room.deno.dev/pigeon/?address=handmade-movement-public-viewing" ) 24 25 this.ws.addEventListener( 'message', ( e ) => { 26 const receivedMsg = JSON.parse( e.data ) 27 , { to = undefined, body, type, from = undefined, timestamp } = receivedMsg 28 29 if ( type == 'init' ) { 30 this.id = body.id 31 32 //console.dir( e.data ) 33 34 if ( Object.keys( body.clients ).length > 2 ) { 35 for ( const id of body.clients ) { 36 if ( id != body.id ) { 37 this.pigeons[id] = this.createPigeon( id ) 38 this.pigeonsSet.add( id ) 39 this.requestEmoji( id ) 40 this.requestLastSpeech( id ) 41 } 42 } 43 // console.log( 'there are pigeons', body.clients ) 44 } else { 45 // console.log( 'the first pigeon' ) 46 } 47 48 this.clockDelta = Date.now() - timestamp 49 this.broadcastEmoji() 50 51 this.synced = true 52 this.syncReady() 53 54 // console.log( this.emoji, 'clockDelta: ' + this.clockDelta ) 55 } 56 57 if ( type == 'position' ) { 58 this.pigeons[from].position.set( body.x, body.y, body.z ) 59 } 60 61 if ( type == 'emoji' ) { 62 //if ( this.pigeons[from].emoji != body.emoji ) { 63 this.updatePigeon( from, body.emoji ) 64 //} 65 } 66 67 if ( type == 'sendYourEmoji' ) { 68 this.sendMsg( { 69 to: from, 70 type: 'emoji', 71 body: { 72 emoji: this.emoji, 73 } 74 } ) 75 } 76 77 if ( type == 'sendYourLastSpeech' ) { 78 if ( this.lastSpeech ) { 79 this.sendMsg( { 80 to: from, 81 type: 'speak', 82 body: { 83 word: this.lastSpeech, 84 } 85 } ) 86 } 87 } 88 89 if ( type == 'speak' ) { 90 wordBaloon.innerText = body.word 91 this.updateSpeaker( from ) 92 this.speaker = from 93 // console.log( 'receive a word', from, body.word ) 94 } 95 96 if ( type == 'clientOpen' ) { 97 // console.log( 'open', body.id ) 98 this.pigeons[body.id] = this.createPigeon( body.id ) 99 this.pigeonsSet.add( body.id ) 100 this.requestEmoji( body.id ) 101 } 102 103 if ( type == 'clientClose' ) { 104 this.removePigeon( body.id ) 105 this.pigeonsSet.delete( body.id ) 106 delete this.pigeons[body.id] 107 // console.log( 'close', body.id ) 108 if ( this.speaker == body.id ) { 109 this.updateSpeaker( this.speaker ) 110 this.speaker = null 111 wordBaloon.innerText = '' 112 } 113 } 114 115 if ( type == 'ping' ) { 116 if ( from === undefined ) this.pong( 'all' ) 117 if ( from === 'host' ) this.pong( 'host' ) 118 } 119 120 if ( type == 'pong' ) console.log( 'pong' ) 121 } ) 122 123 this.ws.addEventListener( 'open', ( e ) => { 124 // console.log( 'ws open' ) 125 } ) 126 127 this.ws.addEventListener( 'close', ( e ) => { 128 if ( this.ws.readyState != 0 ) { 129 this.connectToServer() 130 } 131 } ) 132 133 this.ws.addEventListener( 'error', ( e ) => { 134 if ( this.ws.readyState != 0 ) { 135 this.connectToServer() 136 } 137 } ) 138 } catch ( err ) { 139 // console.log( err, "Failed to connect to server ... exiting" ) 140 } 141 } 142 143 sendMsg( _msg ) { 144 const msg = _msg 145 if ( !Array.isArray( msg.to ) ) msg.to = new Array( msg.to ) 146 try { 147 const msgString = JSON.stringify( msg ) 148 this.ws.send( msgString ) 149 } 150 catch ( error ) { 151 return false 152 } 153 } 154 155 ping( to ) { 156 this.sendMsg( { 157 to: to, 158 type: 'ping', 159 body: '' 160 } ) 161 } 162 163 pong( to ) { 164 this.sendMsg( { 165 to: to, 166 type: 'pong', 167 body: '' 168 } ) 169 } 170 171 boradcastCameraPosition( x, y, z ) { 172 if ( this.position.x != x || this.position.y != y || this.position.z != z || ( Date.now() - this.lastPositionSyncedTime ) > 1000 ) { 173 this.sendMsg( { 174 to: 'others', 175 type: 'position', 176 body: { 177 x: x, 178 y: y, 179 z: z, 180 } 181 } ) 182 183 this.position.x = x 184 this.position.y = y 185 this.position.z = z 186 187 this.lastPositionSyncedTime = Date.now() 188 } 189 } 190 191 requestEmoji( id ) { 192 this.sendMsg( { 193 to: id, 194 type: 'sendYourEmoji', 195 body: {} 196 } ) 197 } 198 199 broadcastEmoji() { 200 this.sendMsg( { 201 to: 'others', 202 type: 'emoji', 203 body: { 204 emoji: this.emoji, 205 } 206 } ) 207 } 208 209 speak( speech ) { 210 this.sendMsg( { 211 to: 'others', 212 type: 'speak', 213 body: { 214 word: speech, 215 } 216 } ) 217 218 this.lastSpeech = speech 219 } 220 221 requestLastSpeech( id ) { 222 this.sendMsg( { 223 to: id, 224 type: 'sendYourLastSpeech', 225 body: {} 226 } ) 227 } 228}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.