From 93a4462c3c2f333f9bc54296847d628d6d46bdb1 Mon Sep 17 00:00:00 2001 From: stonedDiscord Date: Tue, 19 Mar 2019 16:46:06 +0100 Subject: update all this npm shit --- webAO/client.b.js | 2 +- webAO/client.b.js.map | 2 +- webAO/client.js | 11 ++++++++++- webAO/ui.b.js | 2 +- webAO/ui.b.js.map | 2 +- 5 files changed, 14 insertions(+), 5 deletions(-) (limited to 'webAO') diff --git a/webAO/client.b.js b/webAO/client.b.js index 9506442..f1d2850 100644 --- a/webAO/client.b.js +++ b/webAO/client.b.js @@ -1,2 +1,2 @@ -!function(e){var t={};function n(i){if(t[i])return t[i].exports;var c=t[i]={i:i,l:!1,exports:{}};return e[i].call(c.exports,c,c.exports,n),c.l=!0,c.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:i})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;nt.scrollHeight-60&&(t.scrollTop=t.scrollHeight)}},{key:"handleMC",value:function(e){var t=L.music;(t.pause(),t.src=r+e[1],t.play(),e[2]>=0)?T(this.chars[e[2]].name+" changed music to "+e[1]):T("The music was changed to "+e[1])}},{key:"handleRMC",value:function(e){L.music.pause(),L.music=new Audio(this.musicList[e[1]]);var t=L.music;t.totime=e[1],t.offset=(new Date).getTime()/1e3,t.addEventListener("loadedmetadata",function(){t.currentTime+=parseFloat(t.totime+((new Date).getTime()/1e3-t.offset)).toFixed(3),t.play()},!1)}},{key:"handleCI",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Character "+e[1],this.serv.send("AN#"+(e[1]/10+1)+"#%");for(var t=2;t",n.appendChild(i),t%8==0&&document.getElementById("client_chartable").appendChild(n)}w("def")}},{key:"handlePV",value:function(e){this.charID=e[3],document.getElementById("client_charselect").style.display="none";var t=this.me(),n=this.emotes,i=new XMLHttpRequest;i.open("GET",l+"characters/"+escape(this.me().name)+"/char.ini",!0),i.responseType="text",i.onload=function(e){if(200==this.status){var i=this.responseText,c=g.parse(i);t.side=c.Options.side;for(var s=1;s"}S(1)}},i.send()}}]),e}(),p=function(){function e(){c(this,e),this.textnow="",this.chatmsg={isnew:!1,content:"",objection:"0",sound:"",startspeaking:!1,side:null,color:"0",snddelay:0},this.blip=new Audio(l+"sounds/general/sfx-blipmale.wav"),this.blip.volume=.5,this.blipChannels=new Array(6);for(var t=0;t=this.shoutTimer)if(this.chatmsg.startspeaking){w(this.chatmsg.side),document.getElementById("client_char").src=l+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.speaking+".gif",document.getElementById("client_name").style.fontSize=.7*document.getElementById("client_name").offsetHeight+"px",document.getElementById("client_chat").style.fontSize=.25*document.getElementById("client_chat").offsetHeight+"px",document.getElementById("client_name").innerHTML="

"+this.chatmsg.nameplate.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")+"

";var n="color: "+({0:"#ffffff",1:"#00ff00",2:"#ff0000",3:"#ffaa00",4:"#0000ff",5:"#ffff00",6:"#aa00aa"}[this.chatmsg.color]||"#ffffff");document.getElementById("client_inner_chat").style=n,this.chatmsg.startspeaking=!1,this.textnow==this.chatmsg.content&&(document.getElementById("client_char").src=l+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.silent+".gif",this._animating=!1,clearTimeout(this.updater))}else this.textnow!=this.chatmsg.content&&(" "!=this.chatmsg.content.charAt(this.textnow.length)&&(this.blipChannels[this.currentBlipChannel].play(),this.currentBlipChannel++,this.currentBlipChannel%=this.blipChannels.length),this.textnow=this.chatmsg.content.substring(0,this.textnow.length+1),document.getElementById("client_inner_chat").innerHTML=this.textnow,this.textnow==this.chatmsg.content&&(this.textTimer=0,this._animating=!1,document.getElementById("client_char").src=l+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.silent+".gif",clearTimeout(this.updater)));!this.sfxplayed&&this.chatmsg.snddelay+this.shoutTimer>=this.textTimer&&(this.sfxaudio.pause(),this.sfxplayed=1,"0"!=this.chatmsg.sound&&"1"!=this.chatmsg.sound&&(this.sfxaudio.src=l+"sounds/general/"+escape(this.chatmsg.sound)+".wav",this.sfxaudio.play())),this.textTimer=this.textTimer+65}}]),e}(),g=function(){function e(){c(this,e)}return i(e,null,[{key:"parse",value:function(e){var t={section:/^\s*\[\s*([^\]]*)\s*\]\s*$/,param:/^\s*([\w\.\-\_]+)\s*=\s*(.*?)\s*$/,comment:/^\s*;.*$/},n={},i=null;return e.split(/\r\n|\r|\n/).forEach(function(e){if(!t.comment.test(e)&&0!=e.length)if(t.param.test(e)){var c=e.match(t.param);i?n[i][c[1]]=c[2]:n[c[1]]=c[2]}else if(t.section.test(e)){var s=e.match(t.section);n[s[1]]={},i=s[1]}}),n}}]),e}();function f(e){13==e.keyCode&&(H.sendOOC(document.getElementById("client_oocinputbox").value),document.getElementById("client_oocinputbox").value="")}function y(e){if(13==e.keyCode){var t=H.me(),n=H.myEmote(),i="0",c="0";document.getElementById("sendsfx").checked&&(i=n.sfx,c=n.sfxdelay),H.sendIC(n.speaking,t.name,n.silent,document.getElementById("client_inputbox").value,t.side,i,n.zoom,c,d)}}function v(e){var t=document.getElementById("client_musiclist").value;H.sendMusicChange(t)}function E(){L.music.volume=document.getElementById("client_mvolume").value/100}function _(){L.sfxaudio.volume=document.getElementById("client_svolume").value/100}function I(){L.setBlipVolume(document.getElementById("client_bvolume").value/100)}function k(e){H.sendLeaveRoom(),document.getElementById("client_charselect").style.display="block",document.getElementById("client_emo").innerHTML=""}function B(e){return e.onerror="",e.src="/misc/placeholder.gif",!0}function b(e){return e.onerror="",e.src="/misc/placeholder.png",!0}function w(e){var t,n=L.bgFolder();switch(document.getElementById("client_fg").style.display="none",document.getElementById("client_bench").style.display="none",e){case"def":document.getElementById("client_court").src=n+"defenseempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=n+"defensedesk.png",t="defense";break;case"pro":document.getElementById("client_court").src=n+"prosecutorempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=n+"prosecutiondesk.png",t="prosecution";break;case"hld":document.getElementById("client_court").src=n+"helperstand.png",t="defense";break;case"hlp":document.getElementById("client_court").src=n+"prohelperstand.png",t="prosecution";break;case"wit":document.getElementById("client_court").src=n+"witnessempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=n+"estrado.png",t="prosecution";break;case"jud":document.getElementById("client_court").src=n+"judgestand.png",t="prosecution"}5==L.chatmsg.type&&(document.getElementById("client_bench").style.display="none",document.getElementById("client_court").src=l+"themes/default/"+t+"_speedlines.gif")}function C(){H.cleanup(),(H=new m(o))&&(a="join",document.getElementById("client_error").style.display="none")}function x(){H.joinServer()}function T(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:new Date,i=document.createElement("p"),c=document.createElement("span");if(c.id="iclog_name",c.appendChild(document.createTextNode(t)),i.appendChild(c),i.appendChild(document.createTextNode(e)),h.getMinutes()!==n.getMinutes()){var s=document.createElement("span");s.id="iclog_time",s.innerText=n.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"}),i.appendChild(s)}var o=document.getElementById("client_log");o.appendChild(i),o.scrollTop>o.scrollHeight-600&&(o.scrollTop=o.scrollHeight),h=new Date}function M(e){e<1e3?H.sendCharacter(e):(document.getElementById("client_charselect").style.display="none",document.getElementById("client_inputbox").style.display="none",document.getElementById("client_emo").style.display="none")}function S(e){-1!=H.selectedEmote&&(document.getElementById("emo_"+H.selectedEmote).src=H.myEmote().button_off),H.selectedEmote=e,document.getElementById("emo_"+e).src=H.myEmote().button_on}function O(e){e==d?(document.getElementById("button_"+e).className="client_button",d=0):(document.getElementById("button_"+e).className="client_button dark",d&&(document.getElementById("button_"+d).className="client_button"),d=e)}function D(e){return e.replace(/#/g,"").replace(/&/g,"").replace(/%/g,"").replace(/\$/g,"")}window.onOOCEnter=f,window.onEnter=y,window.musiclist_click=v,window.changeMusicVolume=E,window.changeSFXVolume=_,window.changeBlipVolume=I,window.changeCharacter=k,window.imgError=B,window.demoError=b,window.ReconnectButton=C,window.RetryButton=x,window.pickchar=M,window.pickemotion=S,window.toggleshout=O,void 0===String.prototype.trim&&(String.prototype.trim=function(){return String(this).replace(/^\s+|\s+$/g,"")}),String.prototype.hashCode=function(){var e,t=0;if(0===this.length)return t;for(e=0;et.scrollHeight-60&&(t.scrollTop=t.scrollHeight)}},{key:"handleMC",value:function(e){var t=N.music;if(t.pause(),t.src=u+e[1],t.play(),e[2]>=0){var n=this.chars[e[2]].name;M("".concat(n," changed music to ").concat(e[1]))}else M("The music was changed to ".concat(e[1]))}},{key:"handleRMC",value:function(e){N.music.pause(),N.music=new Audio(this.musicList[e[1]]);var t=N.music;t.totime=e[1],t.offset=(new Date).getTime()/1e3,t.addEventListener("loadedmetadata",function(){t.currentTime+=parseFloat(t.totime+((new Date).getTime()/1e3-t.offset)).toFixed(3),t.play()},!1)}},{key:"handleCI",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Character "+e[1],this.serv.send("AN#"+(e[1]/10+1)+"#%");for(var t=2;t",n.appendChild(c),t%8==0&&document.getElementById("client_chartable").appendChild(n)}C("def")}},{key:"handlePV",value:function(e){this.charID=e[3],document.getElementById("client_charselect").style.display="none";var t=this.me(),n=this.emotes,c=new XMLHttpRequest;c.open("GET",l+"characters/"+escape(this.me().name)+"/char.ini",!0),c.responseType="text",c.onload=function(e){if(200==this.status){var c=this.responseText,i=f.parse(c);t.side=i.Options.side;for(var o=1;o"}O(1)}},c.send()}}]),e}(),g=function(){function e(){c(this,e),this.textnow="",this.chatmsg={isnew:!1,content:"",objection:"0",sound:"",startspeaking:!1,side:null,color:"0",snddelay:0},this.blip=new Audio(l+"sounds/general/sfx-blipmale.wav"),this.blip.volume=.5,this.blipChannels=new Array(6);for(var t=0;t=this.shoutTimer)if(this.chatmsg.startspeaking){C(this.chatmsg.side),document.getElementById("client_char").src=l+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.speaking+".gif",document.getElementById("client_name").style.fontSize=.7*document.getElementById("client_name").offsetHeight+"px",document.getElementById("client_chat").style.fontSize=.25*document.getElementById("client_chat").offsetHeight+"px",document.getElementById("client_name").innerHTML="

"+this.chatmsg.nameplate.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")+"

";var n="color: "+({0:"#ffffff",1:"#00ff00",2:"#ff0000",3:"#ffaa00",4:"#0000ff",5:"#ffff00",6:"#aa00aa"}[this.chatmsg.color]||"#ffffff");document.getElementById("client_inner_chat").style=n,this.chatmsg.startspeaking=!1,this.textnow==this.chatmsg.content&&(document.getElementById("client_char").src=l+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.silent+".gif",this._animating=!1,clearTimeout(this.updater))}else this.textnow!=this.chatmsg.content&&(" "!=this.chatmsg.content.charAt(this.textnow.length)&&(this.blipChannels[this.currentBlipChannel].play(),this.currentBlipChannel++,this.currentBlipChannel%=this.blipChannels.length),this.textnow=this.chatmsg.content.substring(0,this.textnow.length+1),document.getElementById("client_inner_chat").innerHTML=this.textnow,this.textnow==this.chatmsg.content&&(this.textTimer=0,this._animating=!1,document.getElementById("client_char").src=l+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.silent+".gif",clearTimeout(this.updater)));!this.sfxplayed&&this.chatmsg.snddelay+this.shoutTimer>=this.textTimer&&(this.sfxaudio.pause(),this.sfxplayed=1,"0"!=this.chatmsg.sound&&"1"!=this.chatmsg.sound&&(this.sfxaudio.src=l+"sounds/general/"+escape(this.chatmsg.sound)+".wav",this.sfxaudio.play())),this.textTimer=this.textTimer+65}}]),e}(),f=function(){function e(){c(this,e)}return o(e,null,[{key:"parse",value:function(e){var t={section:/^\s*\[\s*([^\]]*)\s*\]\s*$/,param:/^\s*([\w\.\-\_]+)\s*=\s*(.*?)\s*$/,comment:/^\s*;.*$/},n={},c=e.split(/\r\n|\r|\n/),i=null;return c.forEach(function(e){if(!t.comment.test(e)&&0!=e.length)if(t.param.test(e)){var c=e.match(t.param);i?n[i][c[1]]=c[2]:n[c[1]]=c[2]}else if(t.section.test(e)){var o=e.match(t.section);n[o[1]]={},i=o[1]}}),n}}]),e}();function y(e){13==e.keyCode&&(L.sendOOC(document.getElementById("client_oocinputbox").value),document.getElementById("client_oocinputbox").value="")}function v(e){if(13==e.keyCode){var t=L.me(),n=L.myEmote(),c="0",i="0";document.getElementById("sendsfx").checked&&(c=n.sfx,i=n.sfxdelay),L.sendIC(n.speaking,t.name,n.silent,document.getElementById("client_inputbox").value,t.side,c,n.zoom,i,h)}}function E(e){var t=document.getElementById("client_musiclist").value;L.sendMusicChange(t)}function _(){N.music.volume=document.getElementById("client_mvolume").value/100}function I(){N.sfxaudio.volume=document.getElementById("client_svolume").value/100}function B(){N.setBlipVolume(document.getElementById("client_bvolume").value/100)}function b(e){L.sendLeaveRoom(),document.getElementById("client_charselect").style.display="block",document.getElementById("client_emo").innerHTML=""}function k(e){return e.onerror="",e.src="/misc/placeholder.gif",!0}function w(e){return e.onerror="",e.src="/misc/placeholder.png",!0}function C(e){var t,n=N.bgFolder();switch(document.getElementById("client_fg").style.display="none",document.getElementById("client_bench").style.display="none",e){case"def":document.getElementById("client_court").src=n+"defenseempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=n+"defensedesk.png",t="defense";break;case"pro":document.getElementById("client_court").src=n+"prosecutorempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=n+"prosecutiondesk.png",t="prosecution";break;case"hld":document.getElementById("client_court").src=n+"helperstand.png",t="defense";break;case"hlp":document.getElementById("client_court").src=n+"prohelperstand.png",t="prosecution";break;case"wit":document.getElementById("client_court").src=n+"witnessempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=n+"estrado.png",t="prosecution";break;case"jud":document.getElementById("client_court").src=n+"judgestand.png",t="prosecution"}5==N.chatmsg.type&&(document.getElementById("client_bench").style.display="none",document.getElementById("client_court").src=l+"themes/default/"+t+"_speedlines.gif")}function x(){L.cleanup(),(L=new p(a))&&(r="join",document.getElementById("client_error").style.display="none")}function T(){L.joinServer()}function M(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:new Date,c=document.createElement("p"),i=document.createElement("span");if(i.id="iclog_name",i.appendChild(document.createTextNode(t)),c.appendChild(i),c.appendChild(document.createTextNode(e)),m.getMinutes()!==n.getMinutes()){var o=document.createElement("span");o.id="iclog_time",o.innerText=n.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"}),c.appendChild(o)}var s=document.getElementById("client_log");s.appendChild(c),s.scrollTop>s.scrollHeight-600&&(s.scrollTop=s.scrollHeight),m=new Date}function S(e){e<1e3?L.sendCharacter(e):(document.getElementById("client_charselect").style.display="none",document.getElementById("client_inputbox").style.display="none",document.getElementById("client_emo").style.display="none")}function O(e){-1!=L.selectedEmote&&(document.getElementById("emo_"+L.selectedEmote).src=L.myEmote().button_off),L.selectedEmote=e,document.getElementById("emo_"+e).src=L.myEmote().button_on}function D(e){e==h?(document.getElementById("button_"+e).className="client_button",h=0):(document.getElementById("button_"+e).className="client_button dark",h&&(document.getElementById("button_"+h).className="client_button"),h=e)}function H(e){return e.replace(/#/g,"").replace(/&/g,"").replace(/%/g,"").replace(/\$/g,"")}window.onOOCEnter=y,window.onEnter=v,window.musiclist_click=E,window.changeMusicVolume=_,window.changeSFXVolume=I,window.changeBlipVolume=B,window.changeCharacter=b,window.imgError=k,window.demoError=w,window.ReconnectButton=x,window.RetryButton=T,window.pickchar=S,window.pickemotion=O,window.toggleshout=D,void 0===String.prototype.trim&&(String.prototype.trim=function(){return String(this).replace(/^\s+|\s+$/g,"")}),String.prototype.hashCode=function(){var e,t=0;if(0===this.length)return t;for(e=0;e this.onOpen(evt);\r\n\t\tthis.serv.onclose = (evt) => this.onClose(evt);\r\n\t\tthis.serv.onmessage = (evt) => this.onMessage(evt);\r\n\t\tthis.serv.onerror = (evt) => this.onError(evt);\r\n\r\n\t\tthis.playerID = 1;\r\n\t\tthis.charID = -1;\r\n\r\n\t\tthis.chars = [];\r\n\t\tthis.emotes = [];\r\n\r\n\t\tthis.selectedEmote = -1;\r\n\r\n\t\tthis.checkUpdater = null;\r\n\r\n\t\t// Only used for RMC/`music` packets, not EM/SM/MC packets.\r\n\t\tthis.musicList = Object();\r\n\r\n\t\tthis.handlers = {\r\n\t\t\t\"MS\": (args) => this.handleMS(args),\r\n\t\t\t\"CT\": (args) => this.handleCT(args),\r\n\t\t\t\"MC\": (args) => this.handleMC(args),\r\n\t\t\t\"RMC\": (args) => this.handleRMC(args),\r\n\t\t\t\"CI\": (args) => this.handleCI(args),\r\n\t\t\t\"SC\": (args) => this.handleSC(args),\r\n\t\t\t\"EI\": (args) => this.handleEI(args),\r\n\t\t\t\"EM\": (args) => this.handleEM(args),\r\n\t\t\t\"SM\": (args) => this.handleSM(args),\r\n\t\t\t\"music\": (args) => this.handlemusic(args),\r\n\t\t\t\"DONE\": (args) => this.handleDONE(args),\r\n\t\t\t\"BN\": (args) => this.handleBN(args),\r\n\t\t\t\"NBG\": (args) => this.handleNBG(args),\r\n\t\t\t\"HP\": (args) => this.handleHP(args),\r\n\t\t\t\"ID\": (args) => this.handleID(args),\r\n\t\t\t\"PN\": (args) => this.handlePN(args),\r\n\t\t\t\"SI\": (args) => this.handleSI(args),\r\n\t\t\t\"CharsCheck\": (args) => this.handleCharsCheck(args),\r\n\t\t\t\"PV\": (args) => this.handlePV(args),\r\n\t\t\t\"CHECK\": (args) => {}\r\n\t\t}\r\n\r\n\t\tthis._lastTimeICReceived = new Date(0);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the current player's character.\r\n\t */\r\n\tme() {\r\n\t\treturn this.chars[this.charID];\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the player's currently selected emote.\r\n\t */\r\n\tmyEmote() {\r\n\t\treturn this.emotes[this.selectedEmote];\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an out-of-character chat message.\r\n\t * @param {string} message the message to send\r\n\t */\r\n\tsendOOC(message) {\r\n\t\tthis.serv.send(`CT#web${this.playerID}#${escapeChat(message)}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an in-character chat message.\r\n\t * @param {string} speaking who is speaking\r\n\t * @param {string} name the name of the current character\r\n\t * @param {string} silent whether or not it's silent\r\n\t * @param {string} message the message to be sent\r\n\t * @param {string} side the name of the side in the background\r\n\t * @param {string} ssfxname the name of the sound effect\r\n\t * @param {string} zoom whether or not to zoom\r\n\t * @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect\r\n\t * @param {string} objection the number of the shout to play\r\n\t */\r\n\tsendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection) {\r\n\t\tthis.serv.send(\r\n\t\t\t`MS#chat#${speaking}#${name}#${silent}` +\r\n\t\t\t`#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` +\r\n\t\t\t`#${this.charID}#${ssfxdelay}#${selectedShout}#0#0#0#0#%`\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to change the music to the specified track.\r\n\t * @param {string} track the track ID\r\n\t */\r\n\tsendMusicChange(track) {\r\n\t\tthis.serv.send(`MC#${track}#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to leave the room and free the character slot.\r\n\t * \r\n\t * Note: This packet is undocumented. It is not implemented by\r\n\t * either the AO2 client or tsuserver.\r\n\t */\r\n\tsendLeaveRoom() {\r\n\t\tthis.serv.send(\"FC#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Begins the handshake process by sending an identifier\r\n\t * to the server.\r\n\t */\r\n\tjoinServer() {\r\n\t\tthis.serv.send(`HI#${navigator.userAgent.hashCode()}#%`);\r\n\t\tthis.serv.send(\"ID#webAO#2.4.5#%\");\r\n\t\tthis.checkUpdater = setInterval(() => this.sendCheck(), 5000);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to play as a specified character.\r\n\t * @param {number} character the character ID\r\n\t */\r\n\tsendCharacter(character) {\r\n\t\tthis.serv.send(`CC#${this.playerID}#${character}#web#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to select a music track.\r\n\t * @param {number?} song the song to be played\r\n\t */\r\n\tsendMusic(song) {\r\n\t\tthis.serv.send(`MC#${song}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends a keepalive packet.\r\n\t */\r\n\tsendCheck() {\r\n\t\tthis.serv.send(`CH#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a connection is established to the server.\r\n\t */\r\n\tonOpen(e) {\r\n\t\t// XXX: Why does watching mean just SITTING there and doing nothing?\r\n\t\tif (mode === \"watch\") {\r\n\t\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\t} else {\r\n\t\t\tclient.joinServer();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when the connection to the server closes.\r\n\t * @param {CloseEvent} e\r\n\t */\r\n\tonClose(e) {\r\n\t\tconsole.error(`The connection was closed: ${e.reason} (${e.code})`);\r\n\t\tif (e.code !== 1001) {\r\n\t\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\t\tthis.cleanup();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a packet is received from the server.\r\n\t * @param {MessageEvent} e\r\n\t */\r\n\tonMessage(e) {\r\n\t\tlet msg = e.data;\r\n\t\tconsole.debug(msg);\r\n\t\tlet lines = msg.split('%');\r\n\t\tlet args = lines[0].split('#');\r\n\t\tlet header = args[0];\r\n\t\tlet handler = this.handlers[header];\r\n\t\tif (typeof handler !== \"undefined\") {\r\n\t\t\thandler(args);\r\n\t\t} else {\r\n\t\t\tconsole.warn(`Invalid packet header ${header}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when an network error occurs.\r\n\t * @param {ErrorEvent} e \r\n\t */\r\n\tonError(e) {\r\n\t\tconsole.error(`A network error occurred: ${e.reason} (${e.code})`);\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\tthis.cleanup();\r\n\t}\r\n\r\n\tcleanup() {\r\n\t\ttry {\r\n\t\t\tthis.serv.close(1001);\r\n\t\t} catch (e) {\r\n\t\t\t// I don't care if this errors\r\n\t\t}\r\n\t\tclearInterval(this.checkUpdater);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an in-character chat message.\r\n\t * @param {*} args packet arguments\r\n\t */\r\n\thandleMS(args) {\r\n\t\t// TODO: this if-statement might be a bug.\r\n\t\tif (args[4] != viewport.chatmsg.content) {\r\n\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = \"\";\r\n\t\t\tlet chatmsg = {\r\n\t\t\t\tpre: escape(args[2]),\r\n\t\t\t\tcharacter: -1, // Will do a linear search\r\n\t\t\t\tpreanim: escape(args[2]), // XXX: why again?\r\n\t\t\t\tnameplate: args[3], // TODO: parse INI to get this info\r\n\t\t\t\tname: args[3],\r\n\t\t\t\tspeaking: \"(b)\" + escape(args[4]),\r\n\t\t\t\tsilent: \"(a)\" + escape(args[4]),\r\n\t\t\t\tcontent: args[5],\r\n\t\t\t\tside: args[6],\r\n\t\t\t\tsound: escape(args[7]),\r\n\t\t\t\ttype: args[8],\r\n\t\t\t\t// charid: args[9],\r\n\t\t\t\tsnddelay: args[10],\r\n\t\t\t\tobjection: args[11],\r\n\t\t\t\tevidence: args[12],\r\n\t\t\t\t// flip: args[13],\r\n\t\t\t\tflash: args[14],\r\n\t\t\t\tcolor: args[15],\r\n\t\t\t\tisnew: true,\r\n\t\t\t};\r\n\r\n\t\t\t// The dreaded linear search...\r\n\t\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\t\tif (this.chars[i].name == args[3]) {\r\n\t\t\t\t\tchatmsg.character = i;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (chatmsg.character == this.charID) {\r\n\t\t\t\tresetICParams();\r\n\t\t\t}\r\n\r\n\t\t\tviewport.say(chatmsg);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an out-of-character chat message.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCT(args) {\r\n\t\tconst oocLog = document.getElementById(\"client_ooclog\");\r\n\t\toocLog.innerHTML += `${args[1]}: ${args[2]}\\r\\n`;\r\n\t\tif (oocLog.scrollTop > oocLog.scrollHeight - 60) {\r\n\t\t\toocLog.scrollTop = oocLog.scrollHeight;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleMC(args) {\r\n\t\tconst music = viewport.music;\r\n\t\tmusic.pause();\r\n\t\tmusic.src = MUSIC_HOST + args[1];\r\n\t\tmusic.play();\r\n\t\tif (args[2] >= 0) {\r\n\t\t\tlet musicname = this.chars[args[2]].name;\r\n\t\t\tappendICLog(`${musicname} changed music to ${args[1]}`);\r\n\t\t} else {\r\n\t\t\tappendICLog(`The music was changed to ${args[1]}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource, with an offset in seconds.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleRMC(args) {\r\n\t\tviewport.music.pause();\r\n\t\tviewport.music = new Audio(this.musicList[args[1]]);\r\n\t\tconst music = viewport.music;\r\n\t\t// Music offset + drift from song loading\r\n\t\tmusic.totime = args[1];\r\n\t\tmusic.offset = new Date().getTime() / 1000;\r\n\t\tmusic.addEventListener('loadedmetadata', function() {\r\n\t\t\tmusic.currentTime += parseFloat(music.totime + (new Date().getTime() / 1000 - music.offset)).toFixed(3);\r\n\t\t\tmusic.play();\r\n\t\t}, false);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, bundling multiple characters\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Character \" + args[1];\r\n\t\tthis.serv.send(\"AN#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\t\tthis.chars[args[i - 1]] = {\r\n\t\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, containing only one character\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSC(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Characters\";\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\tthis.chars[i - 1] = {\r\n\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming evidence information, containing only one evidence\r\n\t * item per packet.\r\n\t * \r\n\t * Mostly unimplemented in webAO.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Evidence \" + args[1];\r\n\t\t//serv.send(\"AE#\" + (args[1] + 1) + \"#%\");\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing multiple entries\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \" + args[1];\r\n\t\tthis.serv.send(\"AM#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\t\tnewentry.text = args[i];\r\n\t\t\t\thmusiclist.options.add(newentry);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing only one entry\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \";\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\tnewentry.text = args[i];\r\n\t\t\thmusiclist.options.add(newentry);\r\n\t\t}\r\n\t\tthis.serv.send(\"RD#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing all entries\r\n\t * in the same packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlemusic(args) {\r\n\t\tfor (let i = 0; i < args.length / 2; i++) {\r\n\t\t\tthis.musicList[args[2 * i]] = args[2 * i + 1];\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the handshake completion packet, meaning the player\r\n\t * is ready to select a character.\r\n\t * \r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleDONE(args) {\r\n\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a background change.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleBN(args) {\r\n\t\tviewport.bgname = escape(args[1]);\r\n\t}\r\n\r\n\thandleNBG(args) {\r\n\t\t// TODO (set by sD)\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a change in the health bars' states.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleHP(args) {\r\n\t\t// TODO (set by sD)\r\n\t\t// Also, this is broken.\r\n\t\tif (args[1] == 1) {\r\n\t\t\tdocument.getElementById(\"client_defense_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_prosecutor_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t}\r\n\t}\r\n\t\r\n\t/**\r\n\t * Handles the issuance of a player ID by the server.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleID(args) {\r\n\t\tthis.playerID = args[1];\r\n\t}\r\n\r\n\thandlePN(args) {\r\n\t\tthis.serv.send(\"askchaa#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Received when the server announces its server info,\r\n\t * but we use it as a cue to begin retrieving characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSI(args) {\r\n\t\tif (oldLoading) {\r\n\t\t\tthis.serv.send(\"askchar2#%\");\r\n\t\t} else {\r\n\t\t\tthis.serv.send(\"RC#%\");\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the list of all used and vacant characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCharsCheck(args) {\r\n\t\tdocument.getElementById(\"client_chartable\").innerHTML = \"\";\r\n\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tvar tr = document.createElement('TR');\r\n\t\t\t}\r\n\t\t\tlet td = document.createElement('TD');\r\n\t\t\tlet icon_chosen;\r\n\t\t\tlet thispick = this.chars[i].icon;\r\n\t\t\tif (args[i + 1] == \"-1\") {\r\n\t\t\t\ticon_chosen = \" dark\";\r\n\t\t\t} else {\r\n\t\t\t\ticon_chosen = \"\";\r\n\t\t\t}\r\n\t\t\ttd.innerHTML = `${this.chars[i].name}`;\r\n\t\t\ttr.appendChild(td);\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tdocument.getElementById(\"client_chartable\").appendChild(tr);\r\n\t\t\t}\r\n\t\t}\r\n\t\tchangeBackground(\"def\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the server's assignment of a character for the player to use.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlePV(args) {\r\n\t\tthis.charID = args[3];\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tlet me = this.me();\r\n\t\tlet emotes = this.emotes;\r\n\t\tlet xhr = new XMLHttpRequest();\r\n\t\txhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true);\r\n\t\txhr.responseType = 'text';\r\n\t\txhr.onload = function (e) {\r\n\t\t\tif (this.status == 200) {\r\n\t\t\t\tlet linifile = this.responseText;\r\n\t\t\t\tlet pinifile = INI.parse(linifile);\r\n\t\t\t\tme.side = pinifile.Options.side;\r\n\t\t\t\tfor (let i = 1; i < pinifile.Emotions.number; i++) {\r\n\t\t\t\t\tlet emoteinfo = pinifile.Emotions[i].split('#');\r\n\t\t\t\t\tlet esfx = \"0\";\r\n\t\t\t\t\tlet esfxd = \"0\";\r\n\t\t\t\t\tif (typeof pinifile.SoundN !== 'undefined') {\r\n\t\t\t\t\t\tesfx = pinifile.SoundN[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (typeof pinifile.SoundT !== 'undefined') {\r\n\t\t\t\t\t\tesfxd = pinifile.SoundT[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\temotes[i] = {\r\n\t\t\t\t\t\tdesc: emoteinfo[0],\r\n\t\t\t\t\t\tspeaking: emoteinfo[1],\r\n\t\t\t\t\t\tsilent: emoteinfo[2],\r\n\t\t\t\t\t\tzoom: emoteinfo[3],\r\n\t\t\t\t\t\tsfx: esfx,\r\n\t\t\t\t\t\tsfxdelay: esfxd,\r\n\t\t\t\t\t\tbutton_off: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_off.png',\r\n\t\t\t\t\t\tbutton_on: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_on.png'\r\n\t\t\t\t\t};\r\n\t\t\t\t\tdocument.getElementById(\"client_emo\").innerHTML += \"\" + emotes[i].desc + \"\";\r\n\t\t\t\t}\r\n\t\t\t\tpickemotion(1);\r\n\t\t\t}\r\n\t\t};\r\n\t\txhr.send();\r\n\t}\r\n}\r\n\r\nclass Viewport {\r\n\tconstructor() {\r\n\t\tthis.textnow = \"\";\r\n\t\tthis.chatmsg = {\r\n\t\t\t\"isnew\": false,\r\n\t\t\t\"content\": \"\",\r\n\t\t\t\"objection\": \"0\",\r\n\t\t\t\"sound\": \"\",\r\n\t\t\t\"startspeaking\": false,\r\n\t\t\t\"side\": null,\r\n\t\t\t\"color\": \"0\",\r\n\t\t\t\"snddelay\": 0\r\n\t\t};\r\n\t\tthis.blip = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.blip.volume = 0.5;\r\n\r\n\t\t// Allocate multiple blip audio channels to make blips less jittery\r\n\r\n\t\t// TODO: read blip type (\"gender\") from ini\r\n\t\tthis.blipChannels = new Array(6);\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i] = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\t\tthis.blipChannels[i].volume = 0.5;\r\n\t\t}\r\n\t\tthis.currentBlipChannel = 0;\r\n\r\n\t\tthis.sfxaudio = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.sfxplayed = 0;\r\n\r\n\t\tthis.music = new Audio();\r\n\t\tthis.music.play();\r\n\r\n\t\tthis.updater = null;\r\n\r\n\t\tthis.bgname = \"gs4\";\r\n\r\n\t\tthis.shoutTimer = 0;\r\n\t\tthis.textTimer = 0;\r\n\r\n\t\tthis._animating = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether or not the viewport is busy\r\n\t * performing a task (animating).\r\n\t */\r\n\tisAnimating() {\r\n\t\treturn this._animating;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the volume of the blip sound.\r\n\t * @param {number} volume\r\n\t */\r\n\tsetBlipVolume(volume) {\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i].volume = volume;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the path which the background is located in.\r\n\t */\r\n\tbgFolder() {\r\n\t\treturn `${AO_HOST}background/${this.bgname}/`;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a new emote.\r\n\t * @param {object} chatmsg the new chat message\r\n\t */\r\n\tsay(chatmsg) {\r\n\t\tthis.chatmsg = chatmsg;\r\n\t\tappendICLog(chatmsg.content, chatmsg.nameplate);\r\n\t\tchangeBackground(chatmsg.side);\r\n\t\tthis.textnow = '';\r\n\t\tthis.sfxplayed = 0;\r\n\t\tthis.textTimer = 0;\r\n\t\tthis._animating = true;\r\n\t\tclearTimeout(this.updater);\r\n\t\tthis.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the chatbox based on the given text.\r\n\t * \r\n\t * XXX: This relies on a global variable `this.chatmsg`!\r\n\t */\r\n\tupdateText() {\r\n\t\tif (this.chatmsg.content.trim() == \"\") {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"none\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"none\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"block\";\r\n\t\t}\r\n\r\n\t\tif (this._animating) {\r\n\t\t\tthis.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);\r\n\t\t}\r\n\r\n\t\tif (this.chatmsg.isnew) {\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"takethat\",\r\n\t\t\t\t\"3\": \"objection\"\r\n\t\t\t};\r\n\r\n\t\t\tlet shout = shouts[this.chatmsg.objection];\r\n\t\t\tif (typeof shout !== \"undefined\") {\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"misc/\" + shout + \".gif\";\r\n\t\t\t\t(new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play();\r\n\t\t\t\tthis.shoutTimer = 800;\r\n\t\t\t} else {\r\n\t\t\t\tthis.shoutTimer = 0;\r\n\t\t\t}\r\n\r\n\t\t\tthis.chatmsg.isnew = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t}\r\n\r\n\t\tif (this.textTimer >= this.shoutTimer) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.speaking + \".gif\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").style.fontSize = (document.getElementById(\"client_name\").offsetHeight * 0.7) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_chat\").style.fontSize = (document.getElementById(\"client_chat\").offsetHeight * 0.25) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").innerHTML = \"

\" + escapeHtml(this.chatmsg.nameplate) + \"

\";\r\n\r\n\t\t\t\tconst colors = {\r\n\t\t\t\t\t\"0\": \"#ffffff\",\r\n\t\t\t\t\t\"1\": \"#00ff00\",\r\n\t\t\t\t\t\"2\": \"#ff0000\",\r\n\t\t\t\t\t\"3\": \"#ffaa00\",\r\n\t\t\t\t\t\"4\": \"#0000ff\",\r\n\t\t\t\t\t\"5\": \"#ffff00\",\r\n\t\t\t\t\t\"6\": \"#aa00aa\"\r\n\t\t\t\t}\r\n\t\t\t\tlet stylecolor = \"color: \" + (colors[this.chatmsg.color] || \"#ffffff\");\r\n\t\t\t\tdocument.getElementById(\"client_inner_chat\").style = stylecolor;\r\n\t\t\t\tthis.chatmsg.startspeaking = false;\r\n\r\n\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.silent + \".gif\";\r\n\t\t\t\t\tthis._animating = false;\r\n\t\t\t\t\tclearTimeout(this.updater);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (this.textnow != this.chatmsg.content) {\r\n\t\t\t\t\tif (this.chatmsg.content.charAt(this.textnow.length) != \" \") {\r\n\t\t\t\t\t\tthis.blipChannels[this.currentBlipChannel].play();\r\n\t\t\t\t\t\tthis.currentBlipChannel++;\r\n\t\t\t\t\t\tthis.currentBlipChannel %= this.blipChannels.length;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.textnow = this.chatmsg.content.substring(0, this.textnow.length + 1);\r\n\t\t\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = this.textnow;\r\n\t\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\t\tthis.textTimer = 0;\r\n\t\t\t\t\t\tthis._animating = false;\r\n\t\t\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.silent + \".gif\";\r\n\t\t\t\t\t\tclearTimeout(this.updater);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!this.sfxplayed && this.chatmsg.snddelay + this.shoutTimer >= this.textTimer) {\r\n\t\t\tthis.sfxaudio.pause();\r\n\t\t\tthis.sfxplayed = 1;\r\n\t\t\tif (this.chatmsg.sound != \"0\" && this.chatmsg.sound != \"1\") {\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/\" + escape(this.chatmsg.sound) + \".wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.textTimer = this.textTimer + UPDATE_INTERVAL;\r\n\t}\r\n}\r\n\r\nclass INI {\r\n\tstatic parse(data) {\r\n\t\tlet regex = {\r\n\t\t\tsection: /^\\s*\\[\\s*([^\\]]*)\\s*\\]\\s*$/,\r\n\t\t\tparam: /^\\s*([\\w\\.\\-\\_]+)\\s*=\\s*(.*?)\\s*$/,\r\n\t\t\tcomment: /^\\s*;.*$/\r\n\t\t};\r\n\t\tlet value = {};\r\n\t\tlet lines = data.split(/\\r\\n|\\r|\\n/);\r\n\t\tlet section = null;\r\n\t\tlines.forEach(function(line) {\r\n\t\t\tif (regex.comment.test(line)) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (line.length == 0) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (regex.param.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.param);\r\n\t\t\t\tif (section) {\r\n\t\t\t\t\tvalue[section][match[1]] = match[2];\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvalue[match[1]] = match[2];\r\n\t\t\t\t}\r\n\t\t\t} else if (regex.section.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.section);\r\n\t\t\t\tvalue[match[1]] = {};\r\n\t\t\t\tsection = match[1];\r\n\t\t\t};\r\n\t\t});\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the out-of-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onOOCEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tclient.sendOOC(document.getElementById(\"client_oocinputbox\").value);\r\n\t\tdocument.getElementById(\"client_oocinputbox\").value = \"\";\r\n\t}\r\n}\r\nwindow.onOOCEnter = onOOCEnter;\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the in-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tlet mychar = client.me();\r\n\t\tlet myemo = client.myEmote();\r\n\t\tlet ssfxname = \"0\";\r\n\t\tlet ssfxdelay = \"0\";\r\n\t\tif (document.getElementById(\"sendsfx\").checked) {\r\n\t\t\tssfxname = myemo.sfx;\r\n\t\t\tssfxdelay = myemo.sfxdelay;\r\n\t\t}\r\n\t\tclient.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById(\"client_inputbox\").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout);\r\n\t}\r\n}\r\nwindow.onEnter = onEnter;\r\n\r\n/**\r\n * Resets the IC parameters for the player to enter a new chat message.\r\n * This should only be called when the player's previous chat message\r\n * was successfully sent/presented.\r\n */\r\nfunction resetICParams() {\r\n\tdocument.getElementById(\"client_inputbox\").value = \"\";\r\n\tif (selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when an item on the music list is clicked.\r\n * @param {MouseEvent} event\r\n */\r\nexport function musiclist_click(event) {\r\n\tlet playtrack = document.getElementById(\"client_musiclist\").value;\r\n\tclient.sendMusicChange(playtrack);\r\n}\r\nwindow.musiclist_click = musiclist_click;\r\n\r\n/**\r\n * Triggered by the music volume slider.\r\n */\r\nexport function changeMusicVolume() {\r\n\tviewport.music.volume = document.getElementById(\"client_mvolume\").value / 100;\r\n}\r\nwindow.changeMusicVolume = changeMusicVolume;\r\n\r\n/**\r\n * Triggered by the sound effect volume slider.\r\n */\r\nexport function changeSFXVolume() {\r\n\tviewport.sfxaudio.volume = document.getElementById(\"client_svolume\").value / 100;\r\n}\r\nwindow.changeSFXVolume = changeSFXVolume;\r\n\r\n/**\r\n * Triggered by the blip volume slider.\r\n */\r\nexport function changeBlipVolume() {\r\n\tviewport.setBlipVolume(document.getElementById(\"client_bvolume\").value / 100);\r\n}\r\nwindow.changeBlipVolume = changeBlipVolume;\r\n\r\n/**\r\n * Triggered when a character icon is clicked in the character selection menu.\r\n * @param {MouseEvent} event\r\n */\r\nexport function changeCharacter(event) {\r\n\tclient.sendLeaveRoom();\r\n\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\tdocument.getElementById(\"client_emo\").innerHTML = \"\";\r\n}\r\nwindow.changeCharacter = changeCharacter;\r\n\r\n/**\r\n * Triggered when there was an error loading a character sprite.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function imgError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.gif\";\r\n\treturn true;\r\n}\r\nwindow.imgError = imgError;\r\n\r\n/**\r\n * Triggered when there was an error loading a character icon.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function demoError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.png\";\r\n\treturn true;\r\n}\r\nwindow.demoError = demoError;\r\n\r\n/**\r\n * Checks if an image exists at the specified URI.\r\n * @param {string} url the URI to be checked\r\n */\r\nfunction ImageExist(url) {\r\n\tvar img = new Image();\r\n\timg.src = url;\r\n\treturn img.height != 0;\r\n}\r\n\r\n/**\r\n * Changes the viewport background based on a given position.\r\n * \r\n * Valid positions: `def, pro, hld, hlp, wit, jud`\r\n * @param {string} position the position to change into\r\n */\r\nfunction changeBackground(position) {\r\n\tvar standname;\r\n\tlet bgfolder = viewport.bgFolder();\r\n\tdocument.getElementById(\"client_fg\").style.display = \"none\";\r\n\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\tswitch (position) {\r\n\t\tcase \"def\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"defenseempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"defensedesk.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"pro\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prosecutorempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"prosecutiondesk.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"hld\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"helperstand.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"hlp\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prohelperstand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"wit\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"witnessempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"estrado.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"jud\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"judgestand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t}\r\n\tif (viewport.chatmsg.type == 5) {\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_court\").src = AO_HOST + \"themes/default/\" + standname + \"_speedlines.gif\";\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the reconnect button is pushed.\r\n */\r\nexport function ReconnectButton() {\r\n\tclient.cleanup();\r\n\tclient = new Client(serverIP);\r\n\tif (client) {\r\n\t\tmode = \"join\"; // HACK: see client.onOpen\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.ReconnectButton = ReconnectButton;\r\n\r\n/**\r\n * Triggered when the retry button is pushed (during the loading process).\r\n */\r\nexport function RetryButton() {\r\n\tclient.joinServer();\r\n}\r\nwindow.RetryButton = RetryButton;\r\n\r\n/**\r\n * Appends a message to the in-character chat log.\r\n * @param {string} toadd the string to be added\r\n * @param {string} name the name of the sender\r\n */\r\nfunction appendICLog(toadd, name = \"\", time = new Date()) {\r\n\tconst entry = document.createElement(\"p\");\r\n\tconst nameField = document.createElement(\"span\");\r\n\tnameField.id = \"iclog_name\";\r\n\tnameField.appendChild(document.createTextNode(name));\r\n\tentry.appendChild(nameField);\r\n\tentry.appendChild(document.createTextNode(toadd));\r\n\r\n\t// Only put a timestamp if the minute has changed.\r\n\tif (lastICMessageTime.getMinutes() !== time.getMinutes()) {\r\n\t\tconst timeStamp = document.createElement(\"span\");\r\n\t\ttimeStamp.id = \"iclog_time\";\r\n\t\ttimeStamp.innerText = time.toLocaleTimeString(undefined, {\r\n\t\t\thour: \"numeric\",\r\n\t\t\tminute: \"2-digit\"\r\n\t\t});\r\n\t\tentry.appendChild(timeStamp);\r\n\t}\r\n\r\n\tconst clientLog = document.getElementById(\"client_log\");\r\n\tclientLog.appendChild(entry);\r\n\r\n\tif (clientLog.scrollTop > clientLog.scrollHeight - 600) {\r\n\t\tclientLog.scrollTop = clientLog.scrollHeight;\r\n\t}\r\n\r\n\tlastICMessageTime = new Date();\r\n}\r\n\r\n/**\r\n * Requests to play as a character.\r\n * @param {number} ccharacter the character ID; if this is a large number, then spectator is chosen instead.\r\n */\r\nexport function pickchar(ccharacter) {\r\n\tif (ccharacter < 1000) {\r\n\t\tclient.sendCharacter(ccharacter);\r\n\t} else {\r\n\t\t// Spectator\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_inputbox\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_emo\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.pickchar = pickchar;\r\n\r\n/**\r\n * Highlights and selects an emotion for in-character chat.\r\n * @param {string} emo the new emotion to be selected\r\n */\r\nexport function pickemotion(emo) {\r\n\tif (client.selectedEmote != -1) {\r\n\t\tdocument.getElementById(\"emo_\" + client.selectedEmote).src = client.myEmote().button_off;\r\n\t}\r\n\tclient.selectedEmote = emo\r\n\tdocument.getElementById(\"emo_\" + emo).src = client.myEmote().button_on;\r\n}\r\nwindow.pickemotion = pickemotion;\r\n\r\n/**\r\n * Highlights and selects a shout for in-character chat.\r\n * If the same shout button is selected, then the shout is canceled.\r\n * @param {string} shout the new shout to be selected\r\n */\r\nexport function toggleshout(shout) {\r\n\tif (shout == selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button dark\";\r\n\t\tif (selectedShout) {\r\n\t\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedShout = shout;\r\n\t}\r\n}\r\nwindow.toggleshout = toggleshout;\r\n\r\n/**\r\n * Escapes a string to be HTML-safe.\r\n * \r\n * XXX: This is unnecessary if we use `createTextNode` instead!\r\n * @param {string} unsafe an unsanitized string\r\n */\r\nfunction escapeHtml(unsafe) {\r\n\treturn unsafe\r\n\t\t.replace(/&/g, \"&\")\r\n\t\t.replace(//g, \">\")\r\n\t\t.replace(/\"/g, \""\")\r\n\t\t.replace(/'/g, \"'\");\r\n}\r\n\r\n/**\r\n * Escapes a string to AO1 escape codes.\r\n * @param {string} estring the string to be escaped\r\n */\r\nfunction escapeChat(estring) {\r\n\treturn estring\r\n\t\t.replace(/#/g, \"\")\r\n\t\t.replace(/&/g, \"\")\r\n\t\t.replace(/%/g, \"\")\r\n\t\t.replace(/\\$/g, \"\");\r\n}\r\n\r\n// TODO: Possibly safe to remove, since we are using a transpiler.\r\nif (typeof(String.prototype.trim) === \"undefined\")\r\n{\r\n String.prototype.trim = function() \r\n {\r\n return String(this).replace(/^\\s+|\\s+$/g, '');\r\n };\r\n}\r\n\r\n// Used for HDID calculation.\r\nString.prototype.hashCode = function() {\r\n\tvar hash = 0, i, chr;\r\n\tif (this.length === 0) return hash;\r\n\tfor (i = 0; i < this.length; i++) {\r\n\t chr = this.charCodeAt(i);\r\n\t hash = ((hash << 5) - hash) + chr;\r\n\t hash |= 0; // Convert to 32bit integer\r\n\t}\r\n\treturn hash;\r\n};\r\n\r\n\r\n//\r\n// Client code\r\n//\r\n\r\nlet client = new Client(serverIP);\r\nlet viewport = new Viewport();\r\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./webAO/client.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","queryDict","location","search","substr","split","forEach","item","serverIP","ip","AO_HOST","asset","MUSIC_HOST","oldLoading","test","navigator","userAgent","selectedShout","lastICMessageTime","Date","Client","address","_this","this","_classCallCheck","serv","WebSocket","onopen","evt","onOpen","onclose","onClose","onmessage","onMessage","onerror","onError","playerID","charID","chars","emotes","selectedEmote","checkUpdater","musicList","handlers","MS","args","handleMS","CT","handleCT","MC","handleMC","RMC","handleRMC","CI","handleCI","SC","handleSC","EI","handleEI","EM","handleEM","SM","handleSM","BD","handleBD","music","handlemusic","DONE","handleDONE","BN","handleBN","NBG","handleNBG","HP","handleHP","ID","handleID","PN","handlePN","SI","handleSI","CharsCheck","handleCharsCheck","PV","handlePV","CHECK","_lastTimeICReceived","message","send","concat","escapeChat","speaking","silent","side","ssfxname","zoom","ssfxdelay","objection","track","_this2","hashCode","setInterval","sendCheck","character","song","e","document","getElementById","style","display","client","joinServer","console","error","reason","code","textContent","cleanup","msg","data","debug","header","handler","warn","close","clearInterval","viewport","chatmsg","content","innerHTML","pre","escape","preanim","nameplate","sound","type","snddelay","evidence","flash","color","isnew","length","className","say","oocLog","scrollTop","scrollHeight","pause","src","play","musicname","appendICLog","Audio","totime","offset","getTime","addEventListener","currentTime","parseFloat","toFixed","chargs","desc","icon","hmusiclist","newentry","createElement","text","options","add","bgname","clip","tr","td","icon_chosen","thispick","appendChild","changeBackground","me","xhr","XMLHttpRequest","open","responseType","onload","status","linifile","responseText","pinifile","INI","parse","Options","Emotions","number","emoteinfo","esfx","esfxd","SoundN","SoundT","sfx","sfxdelay","button_off","button_on","pickemotion","Viewport","textnow","startspeaking","blip","volume","blipChannels","Array","currentBlipChannel","sfxaudio","sfxplayed","updater","shoutTimer","textTimer","_animating","_this3","clearTimeout","setTimeout","updateText","_this4","trim","shout","1","2","3","fontSize","offsetHeight","replace","stylecolor","0","4","5","6","charAt","substring","regex","section","param","comment","lines","line","match","onOOCEnter","event","keyCode","sendOOC","onEnter","mychar","myemo","myEmote","checked","sendIC","musiclist_click","playtrack","sendMusicChange","changeMusicVolume","changeSFXVolume","changeBlipVolume","setBlipVolume","changeCharacter","sendLeaveRoom","imgError","image","demoError","position","standname","bgfolder","bgFolder","ReconnectButton","RetryButton","toadd","arguments","undefined","time","entry","nameField","id","createTextNode","getMinutes","timeStamp","innerText","toLocaleTimeString","hour","minute","clientLog","pickchar","ccharacter","sendCharacter","emo","toggleshout","estring","window","String","hash","charCodeAt"],"mappings":"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","file":"client.b.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 3);\n","/*\r\n * Glorious webAO\r\n * made by sD, refactored by oldmud0\r\n * credits to aleks for original idea and source\r\n*/\r\n\r\nlet queryDict = {};\r\nlocation.search.substr(1).split(\"&\").forEach(function(item) {\r\n\tqueryDict[item.split(\"=\")[0]] = item.split(\"=\")[1]\r\n});\r\n\r\n/* Server magic */\r\n\r\nconst serverIP = queryDict.ip;\r\nlet mode = queryDict.mode;\r\n\r\nconst AO_HOST = queryDict.asset || \"http://assets.aceattorneyonline.com/base/\";\r\nconst MUSIC_HOST = AO_HOST + \"sounds/music/\";\r\nconst BAR_WIDTH = 90;\r\nconst BAR_HEIGHT = 20;\r\nconst CHAR_SELECT_WIDTH = 8;\r\nconst UPDATE_INTERVAL = 65;\r\n\r\nlet oldLoading = false;\r\nif (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) {\r\n\toldLoading = true;\r\n}\r\n\r\nlet selectedShout = 0;\r\nlet lastICMessageTime = new Date(0);\r\n\r\nclass Client {\r\n\tconstructor(address) {\r\n\t\tthis.serv = new WebSocket(\"ws://\" + address);\r\n\r\n\t\tthis.serv.onopen = (evt) => this.onOpen(evt);\r\n\t\tthis.serv.onclose = (evt) => this.onClose(evt);\r\n\t\tthis.serv.onmessage = (evt) => this.onMessage(evt);\r\n\t\tthis.serv.onerror = (evt) => this.onError(evt);\r\n\r\n\t\tthis.playerID = 1;\r\n\t\tthis.charID = -1;\r\n\r\n\t\tthis.chars = [];\r\n\t\tthis.emotes = [];\r\n\r\n\t\tthis.selectedEmote = -1;\r\n\r\n\t\tthis.checkUpdater = null;\r\n\r\n\t\t// Only used for RMC/`music` packets, not EM/SM/MC packets.\r\n\t\tthis.musicList = Object();\r\n\r\n\t\tthis.handlers = {\r\n\t\t\t\"MS\": (args) => this.handleMS(args),\r\n\t\t\t\"CT\": (args) => this.handleCT(args),\r\n\t\t\t\"MC\": (args) => this.handleMC(args),\r\n\t\t\t\"RMC\": (args) => this.handleRMC(args),\r\n\t\t\t\"CI\": (args) => this.handleCI(args),\r\n\t\t\t\"SC\": (args) => this.handleSC(args),\r\n\t\t\t\"EI\": (args) => this.handleEI(args),\r\n\t\t\t\"EM\": (args) => this.handleEM(args),\r\n\t\t\t\"SM\": (args) => this.handleSM(args),\r\n\t\t\t\"BD\": (args) => this.handleBD(args),\r\n\t\t\t\"music\": (args) => this.handlemusic(args),\r\n\t\t\t\"DONE\": (args) => this.handleDONE(args),\r\n\t\t\t\"BN\": (args) => this.handleBN(args),\r\n\t\t\t\"NBG\": (args) => this.handleNBG(args),\r\n\t\t\t\"HP\": (args) => this.handleHP(args),\r\n\t\t\t\"ID\": (args) => this.handleID(args),\r\n\t\t\t\"PN\": (args) => this.handlePN(args),\r\n\t\t\t\"SI\": (args) => this.handleSI(args),\r\n\t\t\t\"CharsCheck\": (args) => this.handleCharsCheck(args),\r\n\t\t\t\"PV\": (args) => this.handlePV(args),\r\n\t\t\t\"CHECK\": (args) => {}\r\n\t\t}\r\n\r\n\t\tthis._lastTimeICReceived = new Date(0);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the current player's character.\r\n\t */\r\n\tme() {\r\n\t\treturn this.chars[this.charID];\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the player's currently selected emote.\r\n\t */\r\n\tmyEmote() {\r\n\t\treturn this.emotes[this.selectedEmote];\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an out-of-character chat message.\r\n\t * @param {string} message the message to send\r\n\t */\r\n\tsendOOC(message) {\r\n\t\tthis.serv.send(`CT#web${this.playerID}#${escapeChat(message)}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an in-character chat message.\r\n\t * @param {string} speaking who is speaking\r\n\t * @param {string} name the name of the current character\r\n\t * @param {string} silent whether or not it's silent\r\n\t * @param {string} message the message to be sent\r\n\t * @param {string} side the name of the side in the background\r\n\t * @param {string} ssfxname the name of the sound effect\r\n\t * @param {string} zoom whether or not to zoom\r\n\t * @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect\r\n\t * @param {string} objection the number of the shout to play\r\n\t */\r\n\tsendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection) {\r\n\t\tthis.serv.send(\r\n\t\t\t`MS#chat#${speaking}#${name}#${silent}` +\r\n\t\t\t`#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` +\r\n\t\t\t`#${this.charID}#${ssfxdelay}#${selectedShout}#0#0#0#0#%`\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to change the music to the specified track.\r\n\t * @param {string} track the track ID\r\n\t */\r\n\tsendMusicChange(track) {\r\n\t\tthis.serv.send(`MC#${track}#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to leave the room and free the character slot.\r\n\t * \r\n\t * Note: This packet is undocumented. It is not implemented by\r\n\t * either the AO2 client or tsuserver.\r\n\t */\r\n\tsendLeaveRoom() {\r\n\t\tthis.serv.send(\"FC#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Begins the handshake process by sending an identifier\r\n\t * to the server.\r\n\t */\r\n\tjoinServer() {\r\n\t\tthis.serv.send(`HI#${navigator.userAgent.hashCode()}#%`);\r\n\t\tthis.serv.send(\"ID#webAO#2.4.5#%\");\r\n\t\tthis.checkUpdater = setInterval(() => this.sendCheck(), 5000);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to play as a specified character.\r\n\t * @param {number} character the character ID\r\n\t */\r\n\tsendCharacter(character) {\r\n\t\tthis.serv.send(`CC#${this.playerID}#${character}#web#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to select a music track.\r\n\t * @param {number?} song the song to be played\r\n\t */\r\n\tsendMusic(song) {\r\n\t\tthis.serv.send(`MC#${song}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends a keepalive packet.\r\n\t */\r\n\tsendCheck() {\r\n\t\tthis.serv.send(`CH#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a connection is established to the server.\r\n\t */\r\n\tonOpen(e) {\r\n\t\t// XXX: Why does watching mean just SITTING there and doing nothing?\r\n\t\tif (mode === \"watch\") {\r\n\t\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\t} else {\r\n\t\t\tclient.joinServer();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when the connection to the server closes.\r\n\t * @param {CloseEvent} e\r\n\t */\r\n\tonClose(e) {\r\n\t\tconsole.error(`The connection was closed: ${e.reason} (${e.code})`);\r\n\t\tif (e.code !== 1001) {\r\n\t\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\t\tthis.cleanup();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a packet is received from the server.\r\n\t * @param {MessageEvent} e\r\n\t */\r\n\tonMessage(e) {\r\n\t\tlet msg = e.data;\r\n\t\tconsole.debug(msg);\r\n\t\tlet lines = msg.split('%');\r\n\t\tlet args = lines[0].split('#');\r\n\t\tlet header = args[0];\r\n\t\tlet handler = this.handlers[header];\r\n\t\tif (typeof handler !== \"undefined\") {\r\n\t\t\thandler(args);\r\n\t\t} else {\r\n\t\t\tconsole.warn(`Invalid packet header ${header}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when an network error occurs.\r\n\t * @param {ErrorEvent} e \r\n\t */\r\n\tonError(e) {\r\n\t\tconsole.error(`A network error occurred: ${e.reason} (${e.code})`);\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\tthis.cleanup();\r\n\t}\r\n\r\n\tcleanup() {\r\n\t\ttry {\r\n\t\t\tthis.serv.close(1001);\r\n\t\t} catch (e) {\r\n\t\t\t// I don't care if this errors\r\n\t\t}\r\n\t\tclearInterval(this.checkUpdater);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an in-character chat message.\r\n\t * @param {*} args packet arguments\r\n\t */\r\n\thandleMS(args) {\r\n\t\t// TODO: this if-statement might be a bug.\r\n\t\tif (args[4] != viewport.chatmsg.content) {\r\n\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = \"\";\r\n\t\t\tlet chatmsg = {\r\n\t\t\t\tpre: escape(args[2]),\r\n\t\t\t\tcharacter: -1, // Will do a linear search\r\n\t\t\t\tpreanim: escape(args[2]), // XXX: why again?\r\n\t\t\t\tnameplate: args[3], // TODO: parse INI to get this info\r\n\t\t\t\tname: args[3],\r\n\t\t\t\tspeaking: \"(b)\" + escape(args[4]),\r\n\t\t\t\tsilent: \"(a)\" + escape(args[4]),\r\n\t\t\t\tcontent: args[5],\r\n\t\t\t\tside: args[6],\r\n\t\t\t\tsound: escape(args[7]),\r\n\t\t\t\ttype: args[8],\r\n\t\t\t\t// charid: args[9],\r\n\t\t\t\tsnddelay: args[10],\r\n\t\t\t\tobjection: args[11],\r\n\t\t\t\tevidence: args[12],\r\n\t\t\t\t// flip: args[13],\r\n\t\t\t\tflash: args[14],\r\n\t\t\t\tcolor: args[15],\r\n\t\t\t\tisnew: true,\r\n\t\t\t};\r\n\r\n\t\t\t// The dreaded linear search...\r\n\t\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\t\tif (this.chars[i].name == args[3]) {\r\n\t\t\t\t\tchatmsg.character = i;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (chatmsg.character == this.charID) {\r\n\t\t\t\tresetICParams();\r\n\t\t\t}\r\n\r\n\t\t\tviewport.say(chatmsg);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an out-of-character chat message.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCT(args) {\r\n\t\tconst oocLog = document.getElementById(\"client_ooclog\");\r\n\t\toocLog.innerHTML += `${args[1]}: ${args[2]}\\r\\n`;\r\n\t\tif (oocLog.scrollTop > oocLog.scrollHeight - 60) {\r\n\t\t\toocLog.scrollTop = oocLog.scrollHeight;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleMC(args) {\r\n\t\tconst music = viewport.music;\r\n\t\tmusic.pause();\r\n\t\tmusic.src = MUSIC_HOST + args[1];\r\n\t\tmusic.play();\r\n\t\tif (args[2] >= 0) {\r\n\t\t\tlet musicname = this.chars[args[2]].name;\r\n\t\t\tappendICLog(`${musicname} changed music to ${args[1]}`);\r\n\t\t} else {\r\n\t\t\tappendICLog(`The music was changed to ${args[1]}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource, with an offset in seconds.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleRMC(args) {\r\n\t\tviewport.music.pause();\r\n\t\tviewport.music = new Audio(this.musicList[args[1]]);\r\n\t\tconst music = viewport.music;\r\n\t\t// Music offset + drift from song loading\r\n\t\tmusic.totime = args[1];\r\n\t\tmusic.offset = new Date().getTime() / 1000;\r\n\t\tmusic.addEventListener('loadedmetadata', function() {\r\n\t\t\tmusic.currentTime += parseFloat(music.totime + (new Date().getTime() / 1000 - music.offset)).toFixed(3);\r\n\t\t\tmusic.play();\r\n\t\t}, false);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, bundling multiple characters\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Character \" + args[1];\r\n\t\tthis.serv.send(\"AN#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\t\tthis.chars[args[i - 1]] = {\r\n\t\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, containing only one character\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSC(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Characters\";\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\tthis.chars[i - 1] = {\r\n\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming evidence information, containing only one evidence\r\n\t * item per packet.\r\n\t * \r\n\t * Mostly unimplemented in webAO.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Evidence \" + args[1];\r\n\t\t//serv.send(\"AE#\" + (args[1] + 1) + \"#%\");\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing multiple entries\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \" + args[1];\r\n\t\tthis.serv.send(\"AM#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\t\tnewentry.text = args[i];\r\n\t\t\t\thmusiclist.options.add(newentry);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing only one entry\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \";\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\tnewentry.text = args[i];\r\n\t\t\thmusiclist.options.add(newentry);\r\n\t\t}\r\n\t\tthis.serv.send(\"RD#%\");\r\n\t}\r\n\r\n/**\r\n\t * Handles the banned packet\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleBD(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Banned: \" + args[1];\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing all entries\r\n\t * in the same packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlemusic(args) {\r\n\t\tfor (let i = 0; i < args.length / 2; i++) {\r\n\t\t\tthis.musicList[args[2 * i]] = args[2 * i + 1];\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the handshake completion packet, meaning the player\r\n\t * is ready to select a character.\r\n\t * \r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleDONE(args) {\r\n\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a background change.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleBN(args) {\r\n\t\tviewport.bgname = escape(args[1]);\r\n\t}\r\n\r\n\thandleNBG(args) {\r\n\t\t// TODO (set by sD)\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a change in the health bars' states.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleHP(args) {\r\n\t\t// TODO (set by sD)\r\n\t\t// Also, this is broken.\r\n\t\tif (args[1] == 1) {\r\n\t\t\tdocument.getElementById(\"client_defense_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_prosecutor_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t}\r\n\t}\r\n\t\r\n\t/**\r\n\t * Handles the issuance of a player ID by the server.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleID(args) {\r\n\t\tthis.playerID = args[1];\r\n\t}\r\n\r\n\thandlePN(args) {\r\n\t\tthis.serv.send(\"askchaa#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Received when the server announces its server info,\r\n\t * but we use it as a cue to begin retrieving characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSI(args) {\r\n\t\tif (oldLoading) {\r\n\t\t\tthis.serv.send(\"askchar2#%\");\r\n\t\t} else {\r\n\t\t\tthis.serv.send(\"RC#%\");\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the list of all used and vacant characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCharsCheck(args) {\r\n\t\tdocument.getElementById(\"client_chartable\").innerHTML = \"\";\r\n\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tvar tr = document.createElement('TR');\r\n\t\t\t}\r\n\t\t\tlet td = document.createElement('TD');\r\n\t\t\tlet icon_chosen;\r\n\t\t\tlet thispick = this.chars[i].icon;\r\n\t\t\tif (args[i + 1] == \"-1\") {\r\n\t\t\t\ticon_chosen = \" dark\";\r\n\t\t\t} else {\r\n\t\t\t\ticon_chosen = \"\";\r\n\t\t\t}\r\n\t\t\ttd.innerHTML = `${this.chars[i].name}`;\r\n\t\t\ttr.appendChild(td);\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tdocument.getElementById(\"client_chartable\").appendChild(tr);\r\n\t\t\t}\r\n\t\t}\r\n\t\tchangeBackground(\"def\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the server's assignment of a character for the player to use.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlePV(args) {\r\n\t\tthis.charID = args[3];\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tlet me = this.me();\r\n\t\tlet emotes = this.emotes;\r\n\t\tlet xhr = new XMLHttpRequest();\r\n\t\txhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true);\r\n\t\txhr.responseType = 'text';\r\n\t\txhr.onload = function (e) {\r\n\t\t\tif (this.status == 200) {\r\n\t\t\t\tlet linifile = this.responseText;\r\n\t\t\t\tlet pinifile = INI.parse(linifile);\r\n\t\t\t\tme.side = pinifile.Options.side;\r\n\t\t\t\tfor (let i = 1; i < pinifile.Emotions.number; i++) {\r\n\t\t\t\t\tlet emoteinfo = pinifile.Emotions[i].split('#');\r\n\t\t\t\t\tlet esfx = \"0\";\r\n\t\t\t\t\tlet esfxd = \"0\";\r\n\t\t\t\t\tif (typeof pinifile.SoundN !== 'undefined') {\r\n\t\t\t\t\t\tesfx = pinifile.SoundN[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (typeof pinifile.SoundT !== 'undefined') {\r\n\t\t\t\t\t\tesfxd = pinifile.SoundT[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\temotes[i] = {\r\n\t\t\t\t\t\tdesc: emoteinfo[0],\r\n\t\t\t\t\t\tspeaking: emoteinfo[1],\r\n\t\t\t\t\t\tsilent: emoteinfo[2],\r\n\t\t\t\t\t\tzoom: emoteinfo[3],\r\n\t\t\t\t\t\tsfx: esfx,\r\n\t\t\t\t\t\tsfxdelay: esfxd,\r\n\t\t\t\t\t\tbutton_off: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_off.png',\r\n\t\t\t\t\t\tbutton_on: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_on.png'\r\n\t\t\t\t\t};\r\n\t\t\t\t\tdocument.getElementById(\"client_emo\").innerHTML += \"\" + emotes[i].desc + \"\";\r\n\t\t\t\t}\r\n\t\t\t\tpickemotion(1);\r\n\t\t\t}\r\n\t\t};\r\n\t\txhr.send();\r\n\t}\r\n}\r\n\r\nclass Viewport {\r\n\tconstructor() {\r\n\t\tthis.textnow = \"\";\r\n\t\tthis.chatmsg = {\r\n\t\t\t\"isnew\": false,\r\n\t\t\t\"content\": \"\",\r\n\t\t\t\"objection\": \"0\",\r\n\t\t\t\"sound\": \"\",\r\n\t\t\t\"startspeaking\": false,\r\n\t\t\t\"side\": null,\r\n\t\t\t\"color\": \"0\",\r\n\t\t\t\"snddelay\": 0\r\n\t\t};\r\n\t\tthis.blip = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.blip.volume = 0.5;\r\n\r\n\t\t// Allocate multiple blip audio channels to make blips less jittery\r\n\r\n\t\t// TODO: read blip type (\"gender\") from ini\r\n\t\tthis.blipChannels = new Array(6);\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i] = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\t\tthis.blipChannels[i].volume = 0.5;\r\n\t\t}\r\n\t\tthis.currentBlipChannel = 0;\r\n\r\n\t\tthis.sfxaudio = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.sfxplayed = 0;\r\n\r\n\t\tthis.music = new Audio();\r\n\t\tthis.music.play();\r\n\r\n\t\tthis.updater = null;\r\n\r\n\t\tthis.bgname = \"gs4\";\r\n\r\n\t\tthis.shoutTimer = 0;\r\n\t\tthis.textTimer = 0;\r\n\r\n\t\tthis._animating = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether or not the viewport is busy\r\n\t * performing a task (animating).\r\n\t */\r\n\tisAnimating() {\r\n\t\treturn this._animating;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the volume of the blip sound.\r\n\t * @param {number} volume\r\n\t */\r\n\tsetBlipVolume(volume) {\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i].volume = volume;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the path which the background is located in.\r\n\t */\r\n\tbgFolder() {\r\n\t\treturn `${AO_HOST}background/${this.bgname}/`;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a new emote.\r\n\t * @param {object} chatmsg the new chat message\r\n\t */\r\n\tsay(chatmsg) {\r\n\t\tthis.chatmsg = chatmsg;\r\n\t\tappendICLog(chatmsg.content, chatmsg.nameplate);\r\n\t\tchangeBackground(chatmsg.side);\r\n\t\tthis.textnow = '';\r\n\t\tthis.sfxplayed = 0;\r\n\t\tthis.textTimer = 0;\r\n\t\tthis._animating = true;\r\n\t\tclearTimeout(this.updater);\r\n\t\tthis.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the chatbox based on the given text.\r\n\t * \r\n\t * XXX: This relies on a global variable `this.chatmsg`!\r\n\t */\r\n\tupdateText() {\r\n\t\tif (this.chatmsg.content.trim() == \"\") {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"none\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"none\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"block\";\r\n\t\t}\r\n\r\n\t\tif (this._animating) {\r\n\t\t\tthis.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);\r\n\t\t}\r\n\r\n\t\tif (this.chatmsg.isnew) {\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"takethat\",\r\n\t\t\t\t\"3\": \"objection\"\r\n\t\t\t};\r\n\r\n\t\t\tlet shout = shouts[this.chatmsg.objection];\r\n\t\t\tif (typeof shout !== \"undefined\") {\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"misc/\" + shout + \".gif\";\r\n\t\t\t\t(new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play();\r\n\t\t\t\tthis.shoutTimer = 800;\r\n\t\t\t} else {\r\n\t\t\t\tthis.shoutTimer = 0;\r\n\t\t\t}\r\n\r\n\t\t\tthis.chatmsg.isnew = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t}\r\n\r\n\t\tif (this.textTimer >= this.shoutTimer) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.speaking + \".gif\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").style.fontSize = (document.getElementById(\"client_name\").offsetHeight * 0.7) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_chat\").style.fontSize = (document.getElementById(\"client_chat\").offsetHeight * 0.25) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").innerHTML = \"

\" + escapeHtml(this.chatmsg.nameplate) + \"

\";\r\n\r\n\t\t\t\tconst colors = {\r\n\t\t\t\t\t\"0\": \"#ffffff\",\r\n\t\t\t\t\t\"1\": \"#00ff00\",\r\n\t\t\t\t\t\"2\": \"#ff0000\",\r\n\t\t\t\t\t\"3\": \"#ffaa00\",\r\n\t\t\t\t\t\"4\": \"#0000ff\",\r\n\t\t\t\t\t\"5\": \"#ffff00\",\r\n\t\t\t\t\t\"6\": \"#aa00aa\"\r\n\t\t\t\t}\r\n\t\t\t\tlet stylecolor = \"color: \" + (colors[this.chatmsg.color] || \"#ffffff\");\r\n\t\t\t\tdocument.getElementById(\"client_inner_chat\").style = stylecolor;\r\n\t\t\t\tthis.chatmsg.startspeaking = false;\r\n\r\n\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.silent + \".gif\";\r\n\t\t\t\t\tthis._animating = false;\r\n\t\t\t\t\tclearTimeout(this.updater);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (this.textnow != this.chatmsg.content) {\r\n\t\t\t\t\tif (this.chatmsg.content.charAt(this.textnow.length) != \" \") {\r\n\t\t\t\t\t\tthis.blipChannels[this.currentBlipChannel].play();\r\n\t\t\t\t\t\tthis.currentBlipChannel++;\r\n\t\t\t\t\t\tthis.currentBlipChannel %= this.blipChannels.length;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.textnow = this.chatmsg.content.substring(0, this.textnow.length + 1);\r\n\t\t\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = this.textnow;\r\n\t\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\t\tthis.textTimer = 0;\r\n\t\t\t\t\t\tthis._animating = false;\r\n\t\t\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.silent + \".gif\";\r\n\t\t\t\t\t\tclearTimeout(this.updater);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!this.sfxplayed && this.chatmsg.snddelay + this.shoutTimer >= this.textTimer) {\r\n\t\t\tthis.sfxaudio.pause();\r\n\t\t\tthis.sfxplayed = 1;\r\n\t\t\tif (this.chatmsg.sound != \"0\" && this.chatmsg.sound != \"1\") {\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/\" + escape(this.chatmsg.sound) + \".wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.textTimer = this.textTimer + UPDATE_INTERVAL;\r\n\t}\r\n}\r\n\r\nclass INI {\r\n\tstatic parse(data) {\r\n\t\tlet regex = {\r\n\t\t\tsection: /^\\s*\\[\\s*([^\\]]*)\\s*\\]\\s*$/,\r\n\t\t\tparam: /^\\s*([\\w\\.\\-\\_]+)\\s*=\\s*(.*?)\\s*$/,\r\n\t\t\tcomment: /^\\s*;.*$/\r\n\t\t};\r\n\t\tlet value = {};\r\n\t\tlet lines = data.split(/\\r\\n|\\r|\\n/);\r\n\t\tlet section = null;\r\n\t\tlines.forEach(function(line) {\r\n\t\t\tif (regex.comment.test(line)) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (line.length == 0) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (regex.param.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.param);\r\n\t\t\t\tif (section) {\r\n\t\t\t\t\tvalue[section][match[1]] = match[2];\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvalue[match[1]] = match[2];\r\n\t\t\t\t}\r\n\t\t\t} else if (regex.section.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.section);\r\n\t\t\t\tvalue[match[1]] = {};\r\n\t\t\t\tsection = match[1];\r\n\t\t\t};\r\n\t\t});\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the out-of-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onOOCEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tclient.sendOOC(document.getElementById(\"client_oocinputbox\").value);\r\n\t\tdocument.getElementById(\"client_oocinputbox\").value = \"\";\r\n\t}\r\n}\r\nwindow.onOOCEnter = onOOCEnter;\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the in-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tlet mychar = client.me();\r\n\t\tlet myemo = client.myEmote();\r\n\t\tlet ssfxname = \"0\";\r\n\t\tlet ssfxdelay = \"0\";\r\n\t\tif (document.getElementById(\"sendsfx\").checked) {\r\n\t\t\tssfxname = myemo.sfx;\r\n\t\t\tssfxdelay = myemo.sfxdelay;\r\n\t\t}\r\n\t\tclient.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById(\"client_inputbox\").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout);\r\n\t}\r\n}\r\nwindow.onEnter = onEnter;\r\n\r\n/**\r\n * Resets the IC parameters for the player to enter a new chat message.\r\n * This should only be called when the player's previous chat message\r\n * was successfully sent/presented.\r\n */\r\nfunction resetICParams() {\r\n\tdocument.getElementById(\"client_inputbox\").value = \"\";\r\n\tif (selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when an item on the music list is clicked.\r\n * @param {MouseEvent} event\r\n */\r\nexport function musiclist_click(event) {\r\n\tlet playtrack = document.getElementById(\"client_musiclist\").value;\r\n\tclient.sendMusicChange(playtrack);\r\n}\r\nwindow.musiclist_click = musiclist_click;\r\n\r\n/**\r\n * Triggered by the music volume slider.\r\n */\r\nexport function changeMusicVolume() {\r\n\tviewport.music.volume = document.getElementById(\"client_mvolume\").value / 100;\r\n}\r\nwindow.changeMusicVolume = changeMusicVolume;\r\n\r\n/**\r\n * Triggered by the sound effect volume slider.\r\n */\r\nexport function changeSFXVolume() {\r\n\tviewport.sfxaudio.volume = document.getElementById(\"client_svolume\").value / 100;\r\n}\r\nwindow.changeSFXVolume = changeSFXVolume;\r\n\r\n/**\r\n * Triggered by the blip volume slider.\r\n */\r\nexport function changeBlipVolume() {\r\n\tviewport.setBlipVolume(document.getElementById(\"client_bvolume\").value / 100);\r\n}\r\nwindow.changeBlipVolume = changeBlipVolume;\r\n\r\n/**\r\n * Triggered when a character icon is clicked in the character selection menu.\r\n * @param {MouseEvent} event\r\n */\r\nexport function changeCharacter(event) {\r\n\tclient.sendLeaveRoom();\r\n\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\tdocument.getElementById(\"client_emo\").innerHTML = \"\";\r\n}\r\nwindow.changeCharacter = changeCharacter;\r\n\r\n/**\r\n * Triggered when there was an error loading a character sprite.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function imgError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.gif\";\r\n\treturn true;\r\n}\r\nwindow.imgError = imgError;\r\n\r\n/**\r\n * Triggered when there was an error loading a character icon.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function demoError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.png\";\r\n\treturn true;\r\n}\r\nwindow.demoError = demoError;\r\n\r\n/**\r\n * Checks if an image exists at the specified URI.\r\n * @param {string} url the URI to be checked\r\n */\r\nfunction ImageExist(url) {\r\n\tvar img = new Image();\r\n\timg.src = url;\r\n\treturn img.height != 0;\r\n}\r\n\r\n/**\r\n * Changes the viewport background based on a given position.\r\n * \r\n * Valid positions: `def, pro, hld, hlp, wit, jud`\r\n * @param {string} position the position to change into\r\n */\r\nfunction changeBackground(position) {\r\n\tvar standname;\r\n\tlet bgfolder = viewport.bgFolder();\r\n\tdocument.getElementById(\"client_fg\").style.display = \"none\";\r\n\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\tswitch (position) {\r\n\t\tcase \"def\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"defenseempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"defensedesk.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"pro\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prosecutorempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"prosecutiondesk.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"hld\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"helperstand.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"hlp\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prohelperstand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"wit\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"witnessempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"estrado.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"jud\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"judgestand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t}\r\n\tif (viewport.chatmsg.type == 5) {\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_court\").src = AO_HOST + \"themes/default/\" + standname + \"_speedlines.gif\";\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the reconnect button is pushed.\r\n */\r\nexport function ReconnectButton() {\r\n\tclient.cleanup();\r\n\tclient = new Client(serverIP);\r\n\tif (client) {\r\n\t\tmode = \"join\"; // HACK: see client.onOpen\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.ReconnectButton = ReconnectButton;\r\n\r\n/**\r\n * Triggered when the retry button is pushed (during the loading process).\r\n */\r\nexport function RetryButton() {\r\n\tclient.joinServer();\r\n}\r\nwindow.RetryButton = RetryButton;\r\n\r\n/**\r\n * Appends a message to the in-character chat log.\r\n * @param {string} toadd the string to be added\r\n * @param {string} name the name of the sender\r\n */\r\nfunction appendICLog(toadd, name = \"\", time = new Date()) {\r\n\tconst entry = document.createElement(\"p\");\r\n\tconst nameField = document.createElement(\"span\");\r\n\tnameField.id = \"iclog_name\";\r\n\tnameField.appendChild(document.createTextNode(name));\r\n\tentry.appendChild(nameField);\r\n\tentry.appendChild(document.createTextNode(toadd));\r\n\r\n\t// Only put a timestamp if the minute has changed.\r\n\tif (lastICMessageTime.getMinutes() !== time.getMinutes()) {\r\n\t\tconst timeStamp = document.createElement(\"span\");\r\n\t\ttimeStamp.id = \"iclog_time\";\r\n\t\ttimeStamp.innerText = time.toLocaleTimeString(undefined, {\r\n\t\t\thour: \"numeric\",\r\n\t\t\tminute: \"2-digit\"\r\n\t\t});\r\n\t\tentry.appendChild(timeStamp);\r\n\t}\r\n\r\n\tconst clientLog = document.getElementById(\"client_log\");\r\n\tclientLog.appendChild(entry);\r\n\r\n\tif (clientLog.scrollTop > clientLog.scrollHeight - 600) {\r\n\t\tclientLog.scrollTop = clientLog.scrollHeight;\r\n\t}\r\n\r\n\tlastICMessageTime = new Date();\r\n}\r\n\r\n/**\r\n * Requests to play as a character.\r\n * @param {number} ccharacter the character ID; if this is a large number, then spectator is chosen instead.\r\n */\r\nexport function pickchar(ccharacter) {\r\n\tif (ccharacter < 1000) {\r\n\t\tclient.sendCharacter(ccharacter);\r\n\t} else {\r\n\t\t// Spectator\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_inputbox\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_emo\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.pickchar = pickchar;\r\n\r\n/**\r\n * Highlights and selects an emotion for in-character chat.\r\n * @param {string} emo the new emotion to be selected\r\n */\r\nexport function pickemotion(emo) {\r\n\tif (client.selectedEmote != -1) {\r\n\t\tdocument.getElementById(\"emo_\" + client.selectedEmote).src = client.myEmote().button_off;\r\n\t}\r\n\tclient.selectedEmote = emo\r\n\tdocument.getElementById(\"emo_\" + emo).src = client.myEmote().button_on;\r\n}\r\nwindow.pickemotion = pickemotion;\r\n\r\n/**\r\n * Highlights and selects a shout for in-character chat.\r\n * If the same shout button is selected, then the shout is canceled.\r\n * @param {string} shout the new shout to be selected\r\n */\r\nexport function toggleshout(shout) {\r\n\tif (shout == selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button dark\";\r\n\t\tif (selectedShout) {\r\n\t\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedShout = shout;\r\n\t}\r\n}\r\nwindow.toggleshout = toggleshout;\r\n\r\n/**\r\n * Escapes a string to be HTML-safe.\r\n * \r\n * XXX: This is unnecessary if we use `createTextNode` instead!\r\n * @param {string} unsafe an unsanitized string\r\n */\r\nfunction escapeHtml(unsafe) {\r\n\treturn unsafe\r\n\t\t.replace(/&/g, \"&\")\r\n\t\t.replace(//g, \">\")\r\n\t\t.replace(/\"/g, \""\")\r\n\t\t.replace(/'/g, \"'\");\r\n}\r\n\r\n/**\r\n * Escapes a string to AO1 escape codes.\r\n * @param {string} estring the string to be escaped\r\n */\r\nfunction escapeChat(estring) {\r\n\treturn estring\r\n\t\t.replace(/#/g, \"\")\r\n\t\t.replace(/&/g, \"\")\r\n\t\t.replace(/%/g, \"\")\r\n\t\t.replace(/\\$/g, \"\");\r\n}\r\n\r\n// TODO: Possibly safe to remove, since we are using a transpiler.\r\nif (typeof(String.prototype.trim) === \"undefined\")\r\n{\r\n String.prototype.trim = function() \r\n {\r\n return String(this).replace(/^\\s+|\\s+$/g, '');\r\n };\r\n}\r\n\r\n// Used for HDID calculation.\r\nString.prototype.hashCode = function() {\r\n\tvar hash = 0, i, chr;\r\n\tif (this.length === 0) return hash;\r\n\tfor (i = 0; i < this.length; i++) {\r\n\t chr = this.charCodeAt(i);\r\n\t hash = ((hash << 5) - hash) + chr;\r\n\t hash |= 0; // Convert to 32bit integer\r\n\t}\r\n\treturn hash;\r\n};\r\n\r\n\r\n//\r\n// Client code\r\n//\r\n\r\nlet client = new Client(serverIP);\r\nlet viewport = new Viewport();\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/webAO/client.js b/webAO/client.js index 84bd9bd..d6d388e 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -14,7 +14,7 @@ location.search.substr(1).split("&").forEach(function(item) { const serverIP = queryDict.ip; let mode = queryDict.mode; -const AO_HOST = queryDict.asset || "http://assets.aceattorneyonline.com/base/"; +const AO_HOST = queryDict.asset || "http://s3.wasabisys.com/webao/base/"; const MUSIC_HOST = AO_HOST + "sounds/music/"; const BAR_WIDTH = 90; const BAR_HEIGHT = 20; @@ -61,6 +61,7 @@ class Client { "EI": (args) => this.handleEI(args), "EM": (args) => this.handleEM(args), "SM": (args) => this.handleSM(args), + "BD": (args) => this.handleBD(args), "music": (args) => this.handlemusic(args), "DONE": (args) => this.handleDONE(args), "BN": (args) => this.handleBN(args), @@ -413,6 +414,14 @@ class Client { this.serv.send("RD#%"); } +/** + * Handles the banned packet + * @param {Array} args packet arguments + */ + handleBD(args) { + document.getElementById("client_loadingtext").innerHTML = "Banned: " + args[1]; + } + /** * Handles incoming music information, containing all entries * in the same packet. diff --git a/webAO/ui.b.js b/webAO/ui.b.js index fb4146e..1c976b0 100644 --- a/webAO/ui.b.js +++ b/webAO/ui.b.js @@ -1,2 +1,2 @@ -!function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:i})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=3)}([,function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t,n){"use strict";(function(e){var n,i,o,s,r=function(){function e(e,t){for(var n=0;n]+)>)/gi,""))};var i=n(40),o=n.n(i),s=n(60),r=(n.n(s),"function"!=typeof/./&&"object"!=("undefined"==typeof Int8Array?"undefined":a(Int8Array))?function(e){return"function"==typeof e||!1}:function(e){return"[object Function]"===toString.call(e)})},function(e,t,n){var i=n(0),o="__all";t.a=o,t.b=function(){return function e(){h(this,e),this._mSubscriptions={},this._mSubscriptions[o]=[],this.on=function(e,t,n){if(!Object(i.h)(t))throw new Error("Tried to listen to event "+e+" with non-function callback "+t);this._mSubscriptions[e]||(this._mSubscriptions[e]=[]),this._mSubscriptions[e].push({fn:t,ctx:n})},this.emit=function(e){var t,n,i;i=Array.prototype.slice.call(arguments,1);var s=this._mSubscriptions[e];if(s)for(s=s.slice(),t=0;t'),s.childElementContainer=s.element,s._splitterSize=t.config.dimensions.borderWidth,s._splitterGrabSize=t.config.dimensions.borderGrabWidth,s._isColumn=e,s._dimension=e?"height":"width",s._splitter=[],s._splitterPosition=null,s._splitterMinPosition=null,s._splitterMaxPosition=null,s}return c(i,a.a),r(i,[{key:"addChild",value:function(e,t,i){var o,s,r,l;if(e=this.layoutManager._$normalizeContentItem(e,this),void 0===t&&(t=this.contentItems.length),0this.contentItems.length-this._isDocked())throw new Error("Can't dock child when it is last in "+this.config.type);var u={column:{first:"top",last:"bottom"},row:{first:"left",last:"right"}}[this.config.type][r?"last":"first"];e.header.position()!=u&&e.header.position(u),this._splitter[a]&&this._splitter[a].element.hide();var d=this._isDocked();for(l=0;ls(t)&&0=this.contentItems.length)){o=this._calculateAbsoluteSizes();for(var d=0;da)){for(e=l/a,c=l,d=0;dthis._splitterMinPosition&&ithis._nDistance||t(this._nY)>this._nDistance)&&(clearTimeout(this._timeout),this._startDrag()),this._bDragging&&this.emit("drag",this._nX,this._nY,e)}}},{key:"onMouseUp",value:function(e){null!=this._timeout&&(clearTimeout(this._timeout),this._eBody.removeClass("lm_dragging"),this._eElement.removeClass("lm_dragging"),this._oDocument.find("iframe").css("pointer-events",""),this._oDocument.unbind("mousemove touchmove",this._fMove),this._oDocument.unbind("mouseup touchend",this._fUp),!0===this._bDragging&&(this._bDragging=!1,this.emit("dragStop",e,this._nOriginalX+this._nX)))}},{key:"_startDrag",value:function(){this._bDragging=!0,this._eBody.addClass("lm_dragging"),this._eElement.addClass("lm_dragging"),this._oDocument.find("iframe").css("pointer-events","none"),this.emit("dragStart",this._nOriginalX,this._nOriginalY)}},{key:"_getCoordinates",value:function(e){return{x:(e=Object(o.e)(e)).pageX,y:e.pageY}}}]),t}();t.a=s},function(e,t,n){var i=n(9);e.exports=function(e){if(!i(e))throw TypeError(e+" is not an object!");return e}},function(e){e.exports=function(e){return"object"==(void 0===e?"undefined":a(e))?null!==e:"function"==typeof e}},function(e){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){var i=n(0);t.a=function(){function e(){if(h(this,e),this._keys=["settings","hasHeaders","constrainDragToContainer","selectionEnabled","dimensions","borderWidth","minItemHeight","minItemWidth","headerHeight","dragProxyWidth","dragProxyHeight","labels","close","maximise","minimise","popout","content","componentName","componentState","id","width","type","height","isClosable","title","popoutWholeStack","openPopouts","parentId","activeItemIndex","reorderEnabled","borderGrabWidth"],36'),o.childElementContainer=o.element,o._containerElement=i,o._containerElement.append(o.element),o}return c(t,i.a),r(t,[{key:"addChild",value:function(e){if(0'),o._activeContentItem=null;var s=e.config;return o._header={show:!0===s.settings.hasHeaders&&!1!==t.hasHeaders,popout:s.settings.showPopoutIcon&&s.labels.popout,maximise:s.settings.showMaximiseIcon&&s.labels.maximise,close:s.settings.showCloseIcon&&s.labels.close,minimise:s.labels.minimise},s.header&&Object(d.b)(o._header,s.header),t.header&&Object(d.b)(o._header,t.header),t.content&&t.content[0]&&t.content[0].header&&Object(d.b)(o._header,t.content[0].header),o._dropZones={},o._dropSegment=null,o._contentAreaDimensions=null,o._dropIndex=null,o.isStack=!0,o.childElementContainer=$('
'),o.header=new u.a(e,o),o.element.on("mouseleave mouseenter",Object(d.c)(function(e){this._docker&&this._docker.docked&&this.childElementContainer[this._docker.dimension]("mouseenter"==e.type?this._docker.realSize:0)},o)),o.element.append(o.header.element),o.element.append(o.childElementContainer),o._setupHeaderPosition(),o._$validateClosability(),o}return c(i,s.a),r(i,[{key:"dock",value:function(e){this._header.dock&&this.parent instanceof a.a&&this.parent.dock(this,e)}},{key:"setSize",value:function(){if("none"!==this.element.css("display")){var e=this._docker&&this._docker.docked,t={width:this.element.width(),height:this.element.height()};this._header.show&&(t[this._sided?"width":"height"]-=this.layoutManager.config.dimensions.headerHeight),e&&(t[this._docker.dimension]=this._docker.realSize),e&&"height"!=this._docker.dimension||this.childElementContainer.width(t.width),e&&"width"!=this._docker.dimension||this.childElementContainer.height(t.height);for(var n=0;nthis.contentItems.length&&(t-=1),e=this.layoutManager._$normalizeContentItem(e,this),s.a.prototype.addChild.call(this,e,t),this.childElementContainer.append(e.element),this.header.createTab(e,t),this.setActiveContentItem(e),this.callDownwards("setSize"),this._$validateClosability(),this.parent instanceof a.a&&this.parent._validateDocking(),this.emitBubblingEvent("stateChanged")}},{key:"removeChild",value:function(e,t){var i=Object(d.g)(e,this.contentItems);s.a.prototype.removeChild.call(this,e,t),this.header.removeTab(e),this.header.activeContentItem===e&&(0e&&i.y1t)return void("header"===n?(this._dropSegment="header",this._highlightHeaderDropZone(this._sided?t:e)):(this._resetHeaderDropZone(),this._highlightBodyDropZone(n)))}},{key:"_$getArea",value:function(){if("none"===this.element.css("display"))return null;var e=s.a.prototype._$getArea,t=e.call(this,this.header.element),n=e.call(this,this.childElementContainer),i=n.x2-n.x1,o=n.y2-n.y1;return this._contentAreaDimensions={header:{hoverArea:{x1:t.x1,y1:t.y1,x2:t.x2,y2:t.y2},highlightArea:{x1:t.x1,y1:t.y1,x2:t.x2,y2:t.y2}}},this._activeContentItem&&!1===this._activeContentItem.isComponent?t:0===this.contentItems.length?(this._contentAreaDimensions.body={hoverArea:{x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2},highlightArea:{x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2}},e.call(this,this.element)):(this._contentAreaDimensions.left={hoverArea:{x1:n.x1,y1:n.y1,x2:n.x1+.25*i,y2:n.y2},highlightArea:{x1:n.x1,y1:n.y1,x2:n.x1+.5*i,y2:n.y2}},this._contentAreaDimensions.top={hoverArea:{x1:n.x1+.25*i,y1:n.y1,x2:n.x1+.75*i,y2:n.y1+.5*o},highlightArea:{x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y1+.5*o}},this._contentAreaDimensions.right={hoverArea:{x1:n.x1+.75*i,y1:n.y1,x2:n.x2,y2:n.y2},highlightArea:{x1:n.x1+.5*i,y1:n.y1,x2:n.x2,y2:n.y2}},this._contentAreaDimensions.bottom={hoverArea:{x1:n.x1+.25*i,y1:n.y1+.5*o,x2:n.x1+.75*i,y2:n.y2},highlightArea:{x1:n.x1,y1:n.y1+.5*o,x2:n.x2,y2:n.y2}},e.call(this,this.element))}},{key:"_highlightHeaderDropZone",value:function(t){var n,i,o,s,r,a,l,c,h=this.header.tabs.length,u=!1;if(0===h)return l=this.header.element.offset(),void this.layoutManager.dropTargetIndicator.highlightArea({x1:l.left,x2:l.left+100,y1:l.top+this.header.element.height()-20,y2:l.top+this.header.element.height()});for(n=0;ns&&t
        '),!0===i.layoutManager.config.settings.selectionEnabled&&(i.element.addClass("lm_selectable"),i.element.on("click touchstart",Object(a.c)(i._onHeaderClick,i))),i.tabsContainer=i.element.find(".lm_tabs"),i.tabDropdownContainer=i.element.find(".lm_tabdropdown_list"),i.tabDropdownContainer.hide(),i.controlsContainer=i.element.find(".lm_controls"),i.parent=n,i.parent.on("resize",i._updateTabSizes,i),i.tabs=[],i.tabsMarkedForRemoval=[],i.activeContentItem=null,i.closeButton=null,i.dockButton=null,i.tabDropdownButton=null,i.hideAdditionalTabsDropdown=Object(a.c)(i._hideAdditionalTabsDropdown,i),$(document).mouseup(i.hideAdditionalTabsDropdown),i._lastVisibleTabIndex=-1,i._tabControlOffset=i.layoutManager.config.settings.tabControlOffset,i._createControls(),i}return c(t,i.b),r(t,[{key:"createTab",value:function(e,t){var n,i;for(i=0;ithis._lastVisibleTabIndex){for(o=this.tabs[this.parent.config.activeItemIndex],n=this.parent.config.activeItemIndex;0r){if(u)i===d&&(n.css({"z-index":"auto","margin-left":""}),this.tabsContainer.append(n));else if((c=0
        '),this.titleElement=this.element.find(".lm_title"),this.closeElement=this.element.find(".lm_close_tab"),this.closeElement[n.config.isClosable?"show":"hide"](),this.isActive=!1,this.setTitle(n.config.title),this.contentItem.on("titleChanged",this.setTitle,this),this._layoutManager=this.contentItem.layoutManager,!0===this._layoutManager.config.settings.reorderEnabled&&!0===n.config.reorderEnabled&&(this._dragListener=new i.a(this.element),this._dragListener.on("dragStart",this._onDragStart,this),this.contentItem.on("destroy",this._dragListener.destroy,this._dragListener)),this._onTabClickFn=Object(s.c)(this._onTabClick,this),this._onCloseClickFn=Object(s.c)(this._onCloseClick,this),this.element.on("mousedown touchstart",this._onTabClickFn),this.contentItem.config.isClosable?(this.closeElement.on("click touchstart",this._onCloseClickFn),this.closeElement.on("mousedown",this._onCloseMousedown)):this.closeElement.remove(),this.contentItem.tab=this,this.contentItem.emit("tab",this),this.contentItem.layoutManager.emit("tabCreated",this),this.contentItem.isComponent&&(this.contentItem.container.tab=this,this.contentItem.container.emit("tab",this))}return r(e,[{key:"setTitle",value:function(e){this.element.attr("title",Object(s.k)(e)),this.titleElement.html(e)}},{key:"setActive",value:function(e){e===this.isActive||(this.isActive=e,e?this.element.addClass("lm_active"):this.element.removeClass("lm_active"))}},{key:"_$destroy",value:function(){this.element.off("mousedown touchstart",this._onTabClickFn),this.closeElement.off("click touchstart",this._onCloseClickFn),this._dragListener&&(this.contentItem.off("destroy",this._dragListener.destroy,this._dragListener),this._dragListener.off("dragStart",this._onDragStart),this._dragListener=null),this.element.remove()}},{key:"_onDragStart",value:function(e,t){return this.header._canDestroy?(!0===this.contentItem.parent.isMaximised&&this.contentItem.parent.toggleMaximise(),void new o.a(e,t,this._dragListener,this._layoutManager,this.contentItem,this.header.parent)):null}},{key:"_onTabClick",value:function(e){if(0===e.button||"touchstart"===e.type){var t=this.header.parent.getActiveContentItem();this.contentItem!==t&&this.header.parent.setActiveContentItem(this.contentItem)}else 1===e.button&&this.contentItem.config.isClosable&&this._onCloseClick(e)}},{key:"_onCloseClick",value:function(e){e.stopPropagation(),this.header._canDestroy&&this.header.parent.removeChild(this.contentItem)}},{key:"_onCloseMousedown",value:function(e){e.stopPropagation()}}]),e}()},function(e,t,n){var i=n(1),o=n(0),s=function(e){function t(e,n,i,s,r,a){var c;h(this,t),(c=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this)))._dragListener=i,c._layoutManager=s,c._contentItem=r,c._originalParent=a,c._area=null,c._lastValidArea=null,c._dragListener.on("drag",c._onDrag,c),c._dragListener.on("dragStop",c._onDrop,c),c.element=$('
        '),a&&a._side&&(c._sided=a._sided,c.element.addClass("lm_"+a._side),0<=["right","bottom"].indexOf(a._side)&&c.element.find(".lm_content").after(c.element.find(".lm_header"))),c.element.css({left:e,top:n}),c.element.find(".lm_tab").attr("title",Object(o.k)(c._contentItem.config.title)),c.element.find(".lm_title").html(c._contentItem.config.title),c.childElementContainer=c.element.find(".lm_content"),c.childElementContainer.append(r.element),c._undisplayTree(),c._layoutManager._$calculateItemAreas(),c._setDimensions(),$(document.body).append(c.element);var u=c._layoutManager.container.offset();return c._minX=u.left,c._minY=u.top,c._maxX=c._layoutManager.container.width()+c._minX,c._maxY=c._layoutManager.container.height()+c._minY,c._width=c.element.width(),c._height=c.element.height(),c._setDropPosition(e,n),c}return c(t,i.b),r(t,[{key:"_onDrag",value:function(e,t,n){var i=(n=Object(o.e)(n)).pageX,s=n.pageY;(i>this._minX&&ithis._minY&&s'),this._header.on("destroy",this._$destroy,this),this._action=o,this.element.on("click touchstart",this._action),this._header.controlsContainer.append(this.element)}return r(e,[{key:"_$destroy",value:function(){this.element.off(),this.element.remove()}}]),e}()},function(e,t,n){var i=n(3),o=n(33),s=function(e){function t(e,n,i){h(this,t);var s=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n,i)),r=e.getComponent(s.config.componentName),a=$.extend(!0,{},s.config.componentState||{});return a.componentName=s.config.componentName,s.componentName=s.config.componentName,""===s.config.title&&(s.config.title=s.config.componentName),s.isComponent=!0,s.container=new o.a(s.config,s,e),s.instance=new r(s.container,a),s.element=s.container._element,s}return c(t,i.a),r(t,[{key:"close",value:function(){this.parent.removeChild(this)}},{key:"setSize",value:function(){"none"!==this.element.css("display")&&this.container._$setSize(this.element.width(),this.element.height())}},{key:"_$init",value:function(){i.a.prototype._$init.call(this),this.container.emit("open")}},{key:"_$hide",value:function(){this.container.hide(),i.a.prototype._$hide.call(this)}},{key:"_$show",value:function(){this.container.show(),i.a.prototype._$show.call(this)}},{key:"_$shown",value:function(){this.container.shown(),i.a.prototype._$shown.call(this)}},{key:"_$destroy",value:function(){this.container.emit("destroy",this),i.a.prototype._$destroy.call(this)}},{key:"_$getArea",value:function(){return null}}]),t}();t.a=s},function(e,t,n){var i=n(1),o=function(e){function t(e,n,i){var o;return h(this,t),(o=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this))).width=null,o.height=null,o.title=e.componentName,o.parent=n,o.layoutManager=i,o.isHidden=!1,o._config=e,o._element=$('
        '),o._contentElement=o._element.find(".lm_content"),o}return c(t,i.b),r(t,[{key:"getElement",value:function(){return this._contentElement}},{key:"hide",value:function(){this.emit("hide"),this.isHidden=!0,this._element.hide()}},{key:"show",value:function(){this.emit("show"),this.isHidden=!1,this._element.show(),(0!=this.height||0!=this.width)&&this.emit("shown")}},{key:"setSize",value:function(e,t){for(var n,i,o,s,r=this.parent,a=this;!r.isColumn&&!r.isRow;)if(a=r,(r=r.parent).isRoot)return!1;for(n=("height"===(i=r.isColumn?"height":"width")?t:e)/(this[i]*(1/(a.config[i]/100)))*100,o=(a.config[i]-n)/(r.contentItems.length-1),s=0;s'),n._creationTimeoutPassed=!1,n._subWindowsCreated=!1,n._dragSources=[],n._updatingColumnsResponsive=!1,n._firstLoad=!0,n.width=null,n.height=null,n.root=null,n.openPopouts=[],n.selectedItem=null,n.isSubWindow=!1,n.eventHub=new f.a(n),n.config=n._createConfig(e),n.container=t,n.dropTargetIndicator=null,n.transitionIndicator=null,n.tabDropPlaceholder=$('
        '),!0===n.isSubWindow&&$("body").css("visibility","hidden"),n._typeToItem={column:Object(C.c)(p.a,n,[!0]),row:Object(C.c)(p.a,n,[!1]),stack:g.a,component:y.a},n}return c(i,s.b),r(i,[{key:"minifyConfig",value:function(e){return(new d.a).minifyConfig(e)}},{key:"unminifyConfig",value:function(e){return(new d.a).unminifyConfig(e)}},{key:"registerComponent",value:function(e,t){if("function"!=typeof t)throw new Error("Please register a constructor function");if(void 0!==this._components[e])throw new Error("Component "+e+" is already registered");this._components[e]=t}},{key:"toConfig",value:function(e){var t,n,i;if(!1===this.isInitialised)throw new Error("Can't create config, layout not yet initialised");if(e&&!(e instanceof v.a))throw new Error("Root must be a ContentItem");for((t={settings:Object(C.b)({},this.config.settings),dimensions:Object(C.b)({},this.config.dimensions),labels:Object(C.b)({},this.config.labels)}).content=[],(n=function(e,t){var i,o;for(i in t.config)"content"!==i&&(e[i]=t.config[i]);if(t.contentItems.length)for(e.content=[],o=0;o(i=this._itemAreas[n]).x1&&ei.y1&&ti.surface&&(o=i.surface,s=i);return s}},{key:"_$createRootItemAreas",value:function(){var e={y2:0,x2:0,y1:"y2",x1:"x2"};for(var t in e){var n=this.root._$getArea();n.side=t,n[t]=e[t]?n[e[t]]-50:50,n.surface=(n.x2-n.x1)*(n.y2-n.y1),this._itemAreas.push(n)}}},{key:"_$calculateItemAreas",value:function(){var e,t,n=this._getAllContentItems();if(this._itemAreas=[],1!==n.length){for(this._$createRootItemAreas(),e=0;e
        ');e.click(Object(C.c)(function(){this.emit("popIn")},this)),document.title=Object(C.k)(this.config.content[0].title),$("head").append($("body link, body style, template, .gl_keep")),this.container=$("body").html("").css("visibility","visible").append(e),document.body.offsetHeight,window.__glInstance=this}},{key:"_createSubWindows",value:function(){var e,t;for(e=0;e=e)){var i=this.config.dimensions.minItemWidth;if(!(e*i<=this.width)){this._updatingColumnsResponsive=!0;for(var o,s=n(t(this.width/i),1),r=this.root.contentItems[0],a=this._findAllStackContainers()[0],l=0;ll;)i(a,n=t[l++])&&(~s(c,n)||c.push(n));return c}},function(e,t,n){var i=n(46);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==i(e)?e.split(""):Object(e)}},function(e){var t={}.toString;e.exports=function(e){return t.call(e).slice(8,-1)}},function(e,t,n){var i=n(17),o=n(48),s=n(49);e.exports=function(e){return function(t,n,r){var a,l=i(t),c=o(l.length),h=s(r,c);if(e&&n!=n){for(;c>h;)if((a=l[h++])!=a)return!0}else for(;c>h;h++)if((e||h in l)&&l[h]===n)return e||h||0;return!e&&-1}}},function(t,n,i){var o=i(18);t.exports=function(t){return 0(t=s(t))?n(t+i,0):e(t,i)}},function(e,t,n){var i=n(2),o=n(4),s="__core-js_shared__",r=o[s]||(o[s]={});(e.exports=function(e,t){return r[e]||(r[e]=void 0===t?{}:t)})("versions",[]).push({version:i.version,mode:n(51)?"pure":"global",copyright:"© 2018 Denis Pushkarev (zloirock.ru)"})},function(e){e.exports=!0},function(e){var t=0,n=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++t+n).toString(36))}},function(e,t,n){var i=n(21),o=n(2),s=n(10);e.exports=function(e,t){var n=(o.Object||{})[e]||Object[e],r={};r[e]=t(n),i(i.S+i.F*s(function(){n(1)}),"Object",r)}},function(e,t,n){var i=n(55);e.exports=function(e,t,n){return i(e),void 0===t?e:1===n?function(n){return e.call(t,n)}:2===n?function(n,i){return e.call(t,n,i)}:3===n?function(n,i,o){return e.call(t,n,i,o)}:function(){return e.apply(t,arguments)}}},function(e){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,n){var i=n(22),o=n(59);e.exports=n(5)?function(e,t,n){return i.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){e.exports=!n(5)&&!n(10)(function(){return 7!=Object.defineProperty(n(23)("div"),"a",{get:function(){return 7}}).a})},function(e,t,n){var i=n(9);e.exports=function(e,t){if(!i(e))return e;var n,o;if(t&&"function"==typeof(n=e.toString)&&!i(o=n.call(e)))return o;if("function"==typeof(n=e.valueOf)&&!i(o=n.call(e)))return o;if(!t&&"function"==typeof(n=e.toString)&&!i(o=n.call(e)))return o;throw TypeError("Can't convert object to primitive value")}},function(e){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){e.exports={default:n(61),__esModule:!0}},function(e,t,n){n(62);var i=n(2).Object;e.exports=function(e,t){return i.create(e,t)}},function(e,t,n){var i=n(21);i(i.S,"Object",{create:n(63)})},function(e,t,n){var i=n(8),o=n(64),s=n(20),r=n(19)("IE_PROTO"),a=function(){},l="prototype",c=function(){var e,t=n(23)("iframe"),i=s.length;for(t.style.display="none",n(65).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("