diff options
Diffstat (limited to 'webAO')
| -rw-r--r-- | webAO/client.b.js | 2 | ||||
| -rw-r--r-- | webAO/client.b.js.map | 2 | ||||
| -rw-r--r-- | webAO/client.html | 15 | ||||
| -rw-r--r-- | webAO/client.js | 62 |
4 files changed, 75 insertions, 6 deletions
diff --git a/webAO/client.b.js b/webAO/client.b.js index 5d762e5..b74c947 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 s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,n),s.l=!0,s.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)n.d(i,s,function(t){return e[t]}.bind(null,s));return i},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)}({3:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}t.onOOCEnter=y,t.onEnter=v,t.musiclist_click=_,t.changeMusicVolume=E,t.changeSFXVolume=I,t.changeBlipVolume=b,t.changeCharacter=B,t.imgError=k,t.demoError=w,t.ReconnectButton=C,t.RetryButton=T,t.pickchar=S,t.pickemotion=O,t.toggleaffect=L,t.toggleflip=N,t.toggleshout=H;var c={};location.search.substr(1).split("&").forEach(function(e){c[e.split("=")[0]]=e.split("=")[1]});var o=c.ip,a=c.mode,l=c.asset||"http://assets.aceattorneyonline.com/base/",r=l+"sounds/music/",u=!1;/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)&&(u=!0);var d=0,h=0,m=new Date(0),g=function(){function e(t){var n=this;s(this,e),this.serv=new WebSocket("ws://"+t),this.serv.onopen=function(e){return n.onOpen(e)},this.serv.onclose=function(e){return n.onClose(e)},this.serv.onmessage=function(e){return n.onMessage(e)},this.serv.onerror=function(e){return n.onError(e)},this.flip=!1,this.playerID=1,this.charID=-1,this.chars=[],this.emotes=[],this.selectedEmote=-1,this.checkUpdater=null,this.musicList=Object(),this.handlers={MS:function(e){return n.handleMS(e)},CT:function(e){return n.handleCT(e)},MC:function(e){return n.handleMC(e)},RMC:function(e){return n.handleRMC(e)},CI:function(e){return n.handleCI(e)},SC:function(e){return n.handleSC(e)},EI:function(e){return n.handleEI(e)},EM:function(e){return n.handleEM(e)},SM:function(e){return n.handleSM(e)},music:function(e){return n.handlemusic(e)},DONE:function(e){return n.handleDONE(e)},BN:function(e){return n.handleBN(e)},NBG:function(e){return n.handleNBG(e)},HP:function(e){return n.handleHP(e)},ID:function(e){return n.handleID(e)},PN:function(e){return n.handlePN(e)},SI:function(e){return n.handleSI(e)},CharsCheck:function(e){return n.handleCharsCheck(e)},PV:function(e){return n.handlePV(e)},CHECK:function(e){}},this._lastTimeICReceived=new Date(0)}return i(e,[{key:"me",value:function(){return this.chars[this.charID]}},{key:"myEmote",value:function(){return this.emotes[this.selectedEmote]}},{key:"sendOOC",value:function(e){this.serv.send("CT#web"+this.playerID+"#"+D(e)+"#%")}},{key:"sendIC",value:function(e,t,n,i,s,c,o,a,l,r,u,d){this.serv.send("MS#chat#"+e+"#"+t+"#"+n+"#"+D(i)+"#"+s+"#"+c+"#"+o+"#"+this.charID+"#"+a+"#"+h+"#0#"+r+"#"+u+"#"+d+"#%")}},{key:"sendMusicChange",value:function(e){this.serv.send("MC#"+e+"#"+this.charID+"#%")}},{key:"sendLeaveRoom",value:function(){this.serv.send("FC#%")}},{key:"joinServer",value:function(){var e=this;this.serv.send("HI#"+navigator.userAgent.hashCode()+"#%"),this.serv.send("ID#webAO#2.4.5#%"),this.checkUpdater=setInterval(function(){return e.sendCheck()},5e3)}},{key:"sendCharacter",value:function(e){this.serv.send("CC#"+this.playerID+"#"+e+"#web#%")}},{key:"sendMusic",value:function(e){this.serv.send("MC#"+e)}},{key:"sendCheck",value:function(){this.serv.send("CH#"+this.charID+"#%")}},{key:"onOpen",value:function(e){"watch"===a?(document.getElementById("client_loading").style.display="none",document.getElementById("client_charselect").style.display="none"):P.joinServer()}},{key:"onClose",value:function(e){console.error("The connection was closed: "+e.reason+" ("+e.code+")"),1001!==e.code&&(document.getElementById("client_error").style.display="block",document.getElementById("error_id").textContent=e.code,this.cleanup())}},{key:"onMessage",value:function(e){var t=e.data;console.debug(t);var n=t.split("%")[0].split("#"),i=n[0],s=this.handlers[i];void 0!==s?s(n):console.warn("Invalid packet header "+i)}},{key:"onError",value:function(e){console.error("A network error occurred: "+e.reason+" ("+e.code+")"),document.getElementById("client_error").style.display="block",document.getElementById("error_id").textContent=e.code,this.cleanup()}},{key:"cleanup",value:function(){try{this.serv.close(1001)}catch(e){}clearInterval(this.checkUpdater)}},{key:"handleMS",value:function(e){if(e[4]!=j.chatmsg.content){document.getElementById("client_inner_chat").innerHTML="";for(var t={character:-1,preanim:escape(e[2]),nameplate:e[3],name:e[3],speaking:"(b)"+escape(e[4]),silent:"(a)"+escape(e[4]),content:e[5],side:e[6],sound:escape(e[7]),type:e[8],snddelay:e[10],objection:e[11],evidence:e[12],flip:e[13],flash:e[14],color:e[15],isnew:!0},n=0;n<this.chars.length;n++)if(this.chars[n].name==e[3]){t.character=n;break}t.character==this.charID&&function(){document.getElementById("client_inputbox").value="",d&&(document.getElementById("button_effect_"+d).className="client_button",d=0);h&&(document.getElementById("button_"+h).className="client_button",h=0)}(),j.say(t)}}},{key:"handleCT",value:function(e){var t=document.getElementById("client_ooclog");t.innerHTML+=e[1]+": "+e[2]+"\r\n",t.scrollTop>t.scrollHeight-60&&(t.scrollTop=t.scrollHeight)}},{key:"handleMC",value:function(e){var t=j.music;(t.pause(),t.src=r+e[1],t.play(),e[2]>=0)?M(this.chars[e[2]].name+" changed music to "+e[1]):M("The music was changed to "+e[1])}},{key:"handleRMC",value:function(e){j.music.pause(),j.music=new Audio(this.musicList[e[1]]);var t=j.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<e.length-1;t++)if(t%2==0){var n=e[t].split("&");this.chars[e[t-1]]={name:n[0],desc:n[1],evidence:n[3],icon:l+"characters/"+escape(n[0])+"/char_icon.png"}}}},{key:"handleSC",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Characters";for(var t=1;t<e.length-1;t++){var n=e[t].split("&");this.chars[t-1]={name:n[0],desc:n[1],evidence:n[3],icon:l+"characters/"+escape(n[0])+"/char_icon.png"}}this.serv.send("RM#%")}},{key:"handleEI",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Evidence "+e[1],this.serv.send("RM#%")}},{key:"handleEM",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Music "+e[1],this.serv.send("AM#"+(e[1]/10+1)+"#%");for(var t=document.getElementById("client_musiclist"),n=2;n<e.length-1;n++)if(n%2==0){var i=document.createElement("OPTION");i.text=e[n],t.options.add(i)}}},{key:"handleSM",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Music ";for(var t=document.getElementById("client_musiclist"),n=1;n<e.length-1;n++){var i=document.createElement("OPTION");i.text=e[n],t.options.add(i)}this.serv.send("RD#%")}},{key:"handlemusic",value:function(e){for(var t=0;t<e.length/2;t++)this.musicList[e[2*t]]=e[2*t+1]}},{key:"handleDONE",value:function(e){document.getElementById("client_loading").style.display="none",document.getElementById("client_charselect").style.display="block"}},{key:"handleBN",value:function(e){j.bgname=escape(e[1])}},{key:"handleNBG",value:function(e){}},{key:"handleHP",value:function(e){1==e[1]?document.getElementById("client_defense_hp").style.clip="rect(0px,"+90*e[2]/10+"px,20px,0px)":document.getElementById("client_prosecutor_hp").style.clip="rect(0px,"+90*e[2]/10+"px,20px,0px)"}},{key:"handleID",value:function(e){this.playerID=e[1]}},{key:"handlePN",value:function(e){this.serv.send("askchaa#%")}},{key:"handleSI",value:function(e){u?this.serv.send("askchar2#%"):this.serv.send("RC#%")}},{key:"handleCharsCheck",value:function(e){document.getElementById("client_chartable").innerHTML="";for(var t=0;t<this.chars.length;t++){if(t%8==0)var n=document.createElement("TR");var i=document.createElement("TD"),s=void 0,c=this.chars[t].icon;s="-1"==e[t+1]?" dark":"",i.innerHTML="<img class='demothing"+s+"' id='demo_"+t+"' src='"+c+"' alt='"+this.chars[t].name+"' onclick='pickchar("+t+")' onerror='demoError(this);'>",n.appendChild(i),t%8==0&&document.getElementById("client_chartable").appendChild(n)}x("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,s=f.parse(i);t.side=s.Options.side;for(var c=1;c<s.Emotions.number;c++){var o=s.Emotions[c].split("#"),a="0",r="0";void 0!==s.SoundN&&(a=s.SoundN[c]),void 0!==s.SoundT&&(r=s.SoundT[c]),n[c]={desc:o[0],speaking:o[1],silent:o[2],zoom:o[3],sfx:a,sfxdelay:r,button_off:l+"characters/"+escape(t.name)+"/emotions/button"+c+"_off.png",button_on:l+"characters/"+escape(t.name)+"/emotions/button"+c+"_on.png"},document.getElementById("client_emo").innerHTML+="<img src='"+n[c].button_off+"' id='emo_"+c+"' alt='"+n[c].desc+"' class='client_button' onclick='pickemotion("+c+")'>"}O(1)}},i.send()}}]),e}(),p=function(){function e(){s(this,e),this.textnow="",this.chatmsg={isnew:!1,content:"",objection:"0",sound:"",startpreanim:!1,startspeaking:!1,side:null,color:"0",snddelay:0,preanimdelay: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.blipChannels.length;t++)this.blipChannels[t]=new Audio(l+"sounds/general/sfx-blipmale.wav"),this.blipChannels[t].volume=.5;this.currentBlipChannel=0,this.sfxaudio=new Audio(l+"sounds/general/sfx-blipmale.wav"),this.sfxplayed=0,this.music=new Audio,this.music.play(),this.updater=null,this.bgname="gs4",this.shoutTimer=0,this.textTimer=0,this._animating=!1}return i(e,[{key:"isAnimating",value:function(){return this._animating}},{key:"setBlipVolume",value:function(e){for(var t=0;t<this.blipChannels.length;t++)this.blipChannels[t].volume=e}},{key:"bgFolder",value:function(){return l+"background/"+this.bgname+"/"}},{key:"say",value:function(e){this.chatmsg=e,M(e.content,e.nameplate),x(e.side),this.textnow="",this.sfxplayed=0,this.textTimer=0,this._animating=!0,clearTimeout(this.updater),"-"!=e.preanim?e.preanimdelay=this.getAnimLength(l+"characters/"+escape(e.name)+"/"+e.preanim+".gif",this.initUpdater):this.initUpdater(0)}},{key:"initUpdater",value:function(e){console.log(e),j.chatmsg.preanimdelay=parseInt(e),j.updater=setTimeout(function(){return j.updateText()},65)}},{key:"getAnimLength",value:function(e,t){var n=new XMLHttpRequest;n.open("GET",e,!0),n.responseType="arraybuffer",n.addEventListener("load",function(){for(var e=new Uint8Array(n.response),i=0,s=0;s<e.length;s++)if(String.fromCharCode(e[s]),33==e[s]&&249==e[s+1]&&4==e[s+2]&&0==e[s+7]){var c=e[s+5]<<8|255&e[s+4];i+=c<2?10:c+2}t(10*i)}),n.send()}},{key:"updateText",value:function(){var e=this;if(1==this.chatmsg.flip?document.getElementById("client_char").style.transform="scaleX(-1)":document.getElementById("client_char").style.transform="scaleX(1)",this._animating&&(this.updater=setTimeout(function(){return e.updateText()},65)),this.chatmsg.isnew){document.getElementById("client_background").style.backgroundColor="transparent",document.getElementById("client_name").style.display="none",document.getElementById("client_chat").style.display="none";var t={1:"holdit",2:"objection",3:"takethat"}[this.chatmsg.objection];void 0!==t?(document.getElementById("client_shout").src=l+"misc/"+t+".gif",new Audio(l+"/characters/"+this.chatmsg.name+"/"+t+".wav").play(),this.shoutTimer=850):this.shoutTimer=0,this.chatmsg.isnew=!1,this.chatmsg.startpreanim=!0}if(this.textTimer>=this.shoutTimer&&this.chatmsg.startpreanim)2==this.chatmsg.flash?(this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=l+"sounds/general/sfx-stab.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("shake",{direction:"up"})):1==this.chatmsg.flash&&(document.getElementById("client_background").style.backgroundColor="white",this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=l+"sounds/general/sfx-realization.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("pulsate")),this.chatmsg.preanimdelay>0&&(document.getElementById("client_shout").src="",x(this.chatmsg.side),document.getElementById("client_char").src=l+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.preanim+".gif"),this.chatmsg.startpreanim=!1,this.chatmsg.startspeaking=!0;else if(this.textTimer>=this.shoutTimer+this.chatmsg.preanimdelay&&!this.chatmsg.startpreanim)if(this.chatmsg.startspeaking){$("#client_name").toggle("fade"),$("#client_chat").toggle("drop",{direction:"down"}),0==this.chatmsg.preanimdelay&&(document.getElementById("client_shout").src="",x(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="<p>"+function(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}(this.chatmsg.nameplate)+"</p>";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(){s(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 s=e.match(t.param);i?n[i][s[1]]=s[2]:n[s[1]]=s[2]}else if(t.section.test(e)){var c=e.match(t.section);n[c[1]]={},i=c[1]}}),n}}]),e}();function y(e){13==e.keyCode&&(P.sendOOC(document.getElementById("client_oocinputbox").value),document.getElementById("client_oocinputbox").value="")}function v(e){if(13==e.keyCode){var t=P.me(),n=P.myEmote(),i=P.flip?1:0,s=document.getElementById("textcolor").value,c="0",o="0";document.getElementById("sendsfx").checked&&(c=n.sfx,o=n.sfxdelay),P.sendIC(n.speaking,t.name,n.silent,document.getElementById("client_inputbox").value,t.side,c,n.zoom,o,h,i,d,s)}}function _(e){var t=document.getElementById("client_musiclist").value;P.sendMusicChange(t)}function E(){j.music.volume=document.getElementById("client_mvolume").value/100}function I(){j.sfxaudio.volume=document.getElementById("client_svolume").value/100}function b(){j.setBlipVolume(document.getElementById("client_bvolume").value/100)}function B(e){P.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 x(e){var t,n=j.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==j.chatmsg.type&&(document.getElementById("client_bench").style.display="none",document.getElementById("client_court").src=l+"themes/default/"+t+"_speedlines.gif")}function C(){P.cleanup(),(P=new g(o))&&(a="join",document.getElementById("client_error").style.display="none")}function T(){P.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,i=document.createElement("p"),s=document.createElement("span");if(s.id="iclog_name",s.appendChild(document.createTextNode(t)),i.appendChild(s),i.appendChild(document.createTextNode(e)),m.getMinutes()!==n.getMinutes()){var c=document.createElement("span");c.id="iclog_time",c.innerText=n.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"}),i.appendChild(c)}var o=document.getElementById("client_log");o.appendChild(i),o.scrollTop>o.scrollHeight-600&&(o.scrollTop=o.scrollHeight),m=new Date}function S(e){e<1e3?P.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!=P.selectedEmote&&(document.getElementById("emo_"+P.selectedEmote).src=P.myEmote().button_off),P.selectedEmote=e,document.getElementById("emo_"+e).src=P.myEmote().button_on}function L(e){e==d?(document.getElementById("button_effect_"+e).className="client_button",d=0):(document.getElementById("button_effect_"+e).className="client_button dark",d&&(document.getElementById("button_effect_"+d).className="client_button"),d=e)}function N(){P.flip?document.getElementById("button_flip").className="client_button":document.getElementById("button_flip").className="client_button dark",P.flip=!P.flip}function H(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 D(e){return e.replace(/#/g,"<pound>").replace(/&/g,"<and>").replace(/%/g,"<percent>").replace(/\$/g,"<dollar>")}window.onOOCEnter=y,window.onEnter=v,window.musiclist_click=_,window.changeMusicVolume=E,window.changeSFXVolume=I,window.changeBlipVolume=b,window.changeCharacter=B,window.imgError=k,window.demoError=w,window.ReconnectButton=C,window.RetryButton=T,window.pickchar=S,window.pickemotion=O,window.toggleaffect=L,window.toggleflip=N,window.toggleshout=H,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.length;e++)t=(t<<5)-t+this.charCodeAt(e),t|=0;return t};var P=new g(o),j=new p}}); +!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,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)n.d(i,c,function(t){return e[t]}.bind(null,c));return i},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)}({3:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}t.onOOCEnter=y,t.onEnter=v,t.musiclist_click=_,t.changeMusicVolume=E,t.changeSFXVolume=I,t.changeBlipVolume=b,t.changeCharacter=B,t.imgError=k,t.demoError=w,t.ReconnectButton=x,t.RetryButton=T,t.pickchar=S,t.pickemotion=O,t.toggleaffect=L,t.toggleflip=N,t.toggleshout=H;var s={};location.search.substr(1).split("&").forEach(function(e){s[e.split("=")[0]]=e.split("=")[1]});var o=s.ip,a=s.mode,r=s.asset||"http://assets.aceattorneyonline.com/base/",l=r+"sounds/music/",u=!1;/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)&&(u=!0);var d=0,h=0,m=new Date(0),g=function(){function e(t){var n=this;c(this,e),this.serv=new WebSocket("ws://"+t),this.serv.onopen=function(e){return n.onOpen(e)},this.serv.onclose=function(e){return n.onClose(e)},this.serv.onmessage=function(e){return n.onMessage(e)},this.serv.onerror=function(e){return n.onError(e)},this.flip=!1,this.playerID=1,this.charID=-1,this.chars=[],this.emotes=[],this.selectedEmote=-1,this.checkUpdater=null,this.musicList=Object(),this.handlers={MS:function(e){return n.handleMS(e)},CT:function(e){return n.handleCT(e)},MC:function(e){return n.handleMC(e)},RMC:function(e){return n.handleRMC(e)},CI:function(e){return n.handleCI(e)},SC:function(e){return n.handleSC(e)},EI:function(e){return n.handleEI(e)},EM:function(e){return n.handleEM(e)},SM:function(e){return n.handleSM(e)},music:function(e){return n.handlemusic(e)},DONE:function(e){return n.handleDONE(e)},BN:function(e){return n.handleBN(e)},NBG:function(e){return n.handleNBG(e)},HP:function(e){return n.handleHP(e)},ID:function(e){return n.handleID(e)},PN:function(e){return n.handlePN(e)},SI:function(e){return n.handleSI(e)},CharsCheck:function(e){return n.handleCharsCheck(e)},PV:function(e){return n.handlePV(e)},CHECK:function(e){}},this._lastTimeICReceived=new Date(0)}return i(e,[{key:"me",value:function(){return this.chars[this.charID]}},{key:"myEmote",value:function(){return this.emotes[this.selectedEmote]}},{key:"sendOOC",value:function(e){this.serv.send("CT#web"+this.playerID+"#"+D(P(e))+"#%")}},{key:"sendIC",value:function(e,t,n,i,c,s,o,a,r,l,u,d){this.serv.send("MS#chat#"+e+"#"+t+"#"+n+"#"+D(P(i))+"#"+c+"#"+s+"#"+o+"#"+this.charID+"#"+a+"#"+h+"#0#"+l+"#"+u+"#"+d+"#%")}},{key:"sendMusicChange",value:function(e){this.serv.send("MC#"+e+"#"+this.charID+"#%")}},{key:"sendLeaveRoom",value:function(){this.serv.send("FC#%")}},{key:"joinServer",value:function(){var e=this;this.serv.send("HI#"+navigator.userAgent.hashCode()+"#%"),this.serv.send("ID#webAO#2.4.5#%"),this.checkUpdater=setInterval(function(){return e.sendCheck()},5e3)}},{key:"sendCharacter",value:function(e){this.serv.send("CC#"+this.playerID+"#"+e+"#web#%")}},{key:"sendMusic",value:function(e){this.serv.send("MC#"+e)}},{key:"sendCheck",value:function(){this.serv.send("CH#"+this.charID+"#%")}},{key:"onOpen",value:function(e){"watch"===a?(document.getElementById("client_loading").style.display="none",document.getElementById("client_charselect").style.display="none"):R.joinServer()}},{key:"onClose",value:function(e){console.error("The connection was closed: "+e.reason+" ("+e.code+")"),1001!==e.code&&(document.getElementById("client_error").style.display="block",document.getElementById("error_id").textContent=e.code,this.cleanup())}},{key:"onMessage",value:function(e){var t=e.data;console.debug(t);var n=t.split("%")[0].split("#"),i=n[0],c=this.handlers[i];void 0!==c?c(n):console.warn("Invalid packet header "+i)}},{key:"onError",value:function(e){console.error("A network error occurred: "+e.reason+" ("+e.code+")"),document.getElementById("client_error").style.display="block",document.getElementById("error_id").textContent=e.code,this.cleanup()}},{key:"cleanup",value:function(){try{this.serv.close(1001)}catch(e){}clearInterval(this.checkUpdater)}},{key:"handleMS",value:function(e){if(e[4]!=V.chatmsg.content){document.getElementById("client_inner_chat").innerHTML="";for(var t={character:-1,preanim:escape(e[2]),nameplate:e[3],name:e[3],speaking:"(b)"+escape(e[4]),silent:"(a)"+escape(e[4]),content:j(A(e[5])),side:e[6],sound:escape(e[7]),type:e[8],snddelay:e[10],objection:e[11],evidence:e[12],flip:e[13],flash:e[14],color:e[15],isnew:!0},n=0;n<this.chars.length;n++)if(this.chars[n].name==e[3]){t.character=n;break}t.character==this.charID&&function(){document.getElementById("client_inputbox").value="",d&&(document.getElementById("button_effect_"+d).className="client_button",d=0);h&&(document.getElementById("button_"+h).className="client_button",h=0)}(),V.say(t)}}},{key:"handleCT",value:function(e){var t=document.getElementById("client_ooclog");t.innerHTML+=j(A(e[1]))+": "+j(A(e[2]))+"\r\n",t.scrollTop>t.scrollHeight-60&&(t.scrollTop=t.scrollHeight)}},{key:"handleMC",value:function(e){var t=V.music;(t.pause(),t.src=l+e[1],t.play(),e[2]>=0)?M(this.chars[e[2]].name+" changed music to "+e[1]):M("The music was changed to "+e[1])}},{key:"handleRMC",value:function(e){V.music.pause(),V.music=new Audio(this.musicList[e[1]]);var t=V.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<e.length-1;t++)if(t%2==0){var n=e[t].split("&");this.chars[e[t-1]]={name:n[0],desc:n[1],evidence:n[3],icon:r+"characters/"+escape(n[0])+"/char_icon.png"}}}},{key:"handleSC",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Characters";for(var t=1;t<e.length-1;t++){var n=e[t].split("&");this.chars[t-1]={name:n[0],desc:n[1],evidence:n[3],icon:r+"characters/"+escape(n[0])+"/char_icon.png"}}this.serv.send("RM#%")}},{key:"handleEI",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Evidence "+e[1],this.serv.send("RM#%")}},{key:"handleEM",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Music "+e[1],this.serv.send("AM#"+(e[1]/10+1)+"#%");for(var t=document.getElementById("client_musiclist"),n=2;n<e.length-1;n++)if(n%2==0){var i=document.createElement("OPTION");i.text=e[n],t.options.add(i)}}},{key:"handleSM",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Music ";for(var t=document.getElementById("client_musiclist"),n=1;n<e.length-1;n++){var i=document.createElement("OPTION");i.text=e[n],t.options.add(i)}this.serv.send("RD#%")}},{key:"handlemusic",value:function(e){for(var t=0;t<e.length/2;t++)this.musicList[e[2*t]]=e[2*t+1]}},{key:"handleDONE",value:function(e){document.getElementById("client_loading").style.display="none",document.getElementById("client_charselect").style.display="block"}},{key:"handleBN",value:function(e){V.bgname=escape(e[1])}},{key:"handleNBG",value:function(e){}},{key:"handleHP",value:function(e){1==e[1]?document.getElementById("client_defense_hp").style.clip="rect(0px,"+90*e[2]/10+"px,20px,0px)":document.getElementById("client_prosecutor_hp").style.clip="rect(0px,"+90*e[2]/10+"px,20px,0px)"}},{key:"handleID",value:function(e){this.playerID=e[1]}},{key:"handlePN",value:function(e){this.serv.send("askchaa#%")}},{key:"handleSI",value:function(e){u?this.serv.send("askchar2#%"):this.serv.send("RC#%")}},{key:"handleCharsCheck",value:function(e){document.getElementById("client_chartable").innerHTML="";for(var t=0;t<this.chars.length;t++){if(t%8==0)var n=document.createElement("TR");var i=document.createElement("TD"),c=void 0,s=this.chars[t].icon;c="-1"==e[t+1]?" dark":"",i.innerHTML="<img class='demothing"+c+"' id='demo_"+t+"' src='"+s+"' alt='"+this.chars[t].name+"' onclick='pickchar("+t+")' onerror='demoError(this);'>",n.appendChild(i),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,i=new XMLHttpRequest;i.open("GET",r+"characters/"+escape(this.me().name)+"/char.ini",!0),i.responseType="text",i.onload=function(e){if(200==this.status){var i=this.responseText,c=f.parse(i);t.side=c.Options.side;for(var s=1;s<c.Emotions.number;s++){var o=c.Emotions[s].split("#"),a="0",l="0";void 0!==c.SoundN&&(a=c.SoundN[s]),void 0!==c.SoundT&&(l=c.SoundT[s]),n[s]={desc:o[0],speaking:o[1],silent:o[2],zoom:o[3],sfx:a,sfxdelay:l,button_off:r+"characters/"+escape(t.name)+"/emotions/button"+s+"_off.png",button_on:r+"characters/"+escape(t.name)+"/emotions/button"+s+"_on.png"},document.getElementById("client_emo").innerHTML+="<img src='"+n[s].button_off+"' id='emo_"+s+"' alt='"+n[s].desc+"' class='client_button' onclick='pickemotion("+s+")'>"}O(1)}},i.send()}}]),e}(),p=function(){function e(){c(this,e),this.textnow="",this.chatmsg={isnew:!1,content:"",objection:"0",sound:"",startpreanim:!1,startspeaking:!1,side:null,color:"0",snddelay:0,preanimdelay:0},this.blip=new Audio(r+"sounds/general/sfx-blipmale.wav"),this.blip.volume=.5,this.blipChannels=new Array(6);for(var t=0;t<this.blipChannels.length;t++)this.blipChannels[t]=new Audio(r+"sounds/general/sfx-blipmale.wav"),this.blipChannels[t].volume=.5;this.currentBlipChannel=0,this.sfxaudio=new Audio(r+"sounds/general/sfx-blipmale.wav"),this.sfxplayed=0,this.music=new Audio,this.music.play(),this.updater=null,this.bgname="gs4",this.shoutTimer=0,this.textTimer=0,this._animating=!1}return i(e,[{key:"isAnimating",value:function(){return this._animating}},{key:"setBlipVolume",value:function(e){for(var t=0;t<this.blipChannels.length;t++)this.blipChannels[t].volume=e}},{key:"bgFolder",value:function(){return r+"background/"+this.bgname+"/"}},{key:"say",value:function(e){this.chatmsg=e,M(e.content,e.nameplate),C(e.side),this.textnow="",this.sfxplayed=0,this.textTimer=0,this._animating=!0,clearTimeout(this.updater),"-"!=e.preanim?e.preanimdelay=this.getAnimLength(r+"characters/"+escape(e.name)+"/"+e.preanim+".gif",this.initUpdater):this.initUpdater(0)}},{key:"initUpdater",value:function(e){console.log(e),V.chatmsg.preanimdelay=parseInt(e),V.updater=setTimeout(function(){return V.updateText()},65)}},{key:"getAnimLength",value:function(e,t){var n=new XMLHttpRequest;n.open("GET",e,!0),n.responseType="arraybuffer",n.addEventListener("load",function(){for(var e=new Uint8Array(n.response),i=0,c=0;c<e.length;c++)if(String.fromCharCode(e[c]),33==e[c]&&249==e[c+1]&&4==e[c+2]&&0==e[c+7]){var s=e[c+5]<<8|255&e[c+4];i+=s<2?10:s+2}t(10*i)}),n.send()}},{key:"updateText",value:function(){var e=this;if(1==this.chatmsg.flip?document.getElementById("client_char").style.transform="scaleX(-1)":document.getElementById("client_char").style.transform="scaleX(1)",this._animating&&(this.updater=setTimeout(function(){return e.updateText()},65)),this.chatmsg.isnew){document.getElementById("client_background").style.backgroundColor="transparent",document.getElementById("client_name").style.display="none",document.getElementById("client_chat").style.display="none";var t={1:"holdit",2:"objection",3:"takethat"}[this.chatmsg.objection];void 0!==t?(document.getElementById("client_shout").src=r+"misc/"+t+".gif",new Audio(r+"/characters/"+this.chatmsg.name+"/"+t+".wav").play(),this.shoutTimer=850):this.shoutTimer=0,this.chatmsg.isnew=!1,this.chatmsg.startpreanim=!0}if(this.textTimer>=this.shoutTimer&&this.chatmsg.startpreanim)2==this.chatmsg.flash?(this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=r+"sounds/general/sfx-stab.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("shake",{direction:"up"})):1==this.chatmsg.flash&&(document.getElementById("client_background").style.backgroundColor="white",this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=r+"sounds/general/sfx-realization.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("pulsate")),this.chatmsg.preanimdelay>0&&(document.getElementById("client_shout").src="",C(this.chatmsg.side),document.getElementById("client_char").src=r+"characters/"+escape(this.chatmsg.name)+"/"+this.chatmsg.preanim+".gif"),this.chatmsg.startpreanim=!1,this.chatmsg.startspeaking=!0;else if(this.textTimer>=this.shoutTimer+this.chatmsg.preanimdelay&&!this.chatmsg.startpreanim)if(this.chatmsg.startspeaking){$("#client_name").toggle("fade"),$("#client_chat").toggle("drop",{direction:"down"}),0==this.chatmsg.preanimdelay&&(document.getElementById("client_shout").src="",C(this.chatmsg.side)),document.getElementById("client_char").src=r+"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="<p>"+function(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}(this.chatmsg.nameplate)+"</p>";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=r+"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=r+"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=r+"sounds/general/"+escape(this.chatmsg.sound)+".wav",this.sfxaudio.play())),this.textTimer=this.textTimer+65}}]),e}(),f=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 y(e){13==e.keyCode&&(R.sendOOC(document.getElementById("client_oocinputbox").value),document.getElementById("client_oocinputbox").value="")}function v(e){if(13==e.keyCode){var t=R.me(),n=R.myEmote(),i=R.flip?1:0,c=document.getElementById("textcolor").value,s="0",o="0";document.getElementById("sendsfx").checked&&(s=n.sfx,o=n.sfxdelay),R.sendIC(n.speaking,t.name,n.silent,document.getElementById("client_inputbox").value,t.side,s,n.zoom,o,h,i,d,c)}}function _(e){var t=document.getElementById("client_musiclist").value;R.sendMusicChange(t)}function E(){V.music.volume=document.getElementById("client_mvolume").value/100}function I(){V.sfxaudio.volume=document.getElementById("client_svolume").value/100}function b(){V.setBlipVolume(document.getElementById("client_bvolume").value/100)}function B(e){R.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=V.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==V.chatmsg.type&&(document.getElementById("client_bench").style.display="none",document.getElementById("client_court").src=r+"themes/default/"+t+"_speedlines.gif")}function x(){R.cleanup(),(R=new g(o))&&(a="join",document.getElementById("client_error").style.display="none")}function T(){R.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,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)),m.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),m=new Date}function S(e){e<1e3?R.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!=R.selectedEmote&&(document.getElementById("emo_"+R.selectedEmote).src=R.myEmote().button_off),R.selectedEmote=e,document.getElementById("emo_"+e).src=R.myEmote().button_on}function L(e){e==d?(document.getElementById("button_effect_"+e).className="client_button",d=0):(document.getElementById("button_effect_"+e).className="client_button dark",d&&(document.getElementById("button_effect_"+d).className="client_button"),d=e)}function N(){R.flip?document.getElementById("button_flip").className="client_button":document.getElementById("button_flip").className="client_button dark",R.flip=!R.flip}function H(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 D(e){return e.replace(/#/g,"<pound>").replace(/&/g,"<and>").replace(/%/g,"<percent>").replace(/\$/g,"<dollar>")}function A(e){return e.replace(/<pound>/g,"#").replace(/<and>/g,"&").replace(/<percent>/g,"%").replace(/\<dollar>/g,"$")}function P(e){var t=document.getElementById("client_encoding").value;if("unicode"==t)return e.replace(/[^\0-~]/g,function(e){return"\\u"+("000"+e.charCodeAt().toString(16)).slice(-4)});if("utf16"==t){for(var n=new ArrayBuffer(2*e.length),i=new Uint16Array(n),c=0,s=e.length;c<s;c++)i[c]=e.charCodeAt(c);return String(i)}return e}function j(e){var t=document.getElementById("client_decoding").value;return"unicode"==t?e.replace(/\\u([\d\w]{1,})/gi,function(e,t){return String.fromCharCode(parseInt(t,16))}):"utf16"==t?String.fromCharCode.apply(null,new Uint16Array(e.split(","))):e}window.onOOCEnter=y,window.onEnter=v,window.musiclist_click=_,window.changeMusicVolume=E,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.toggleaffect=L,window.toggleflip=N,window.toggleshout=H,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.length;e++)t=(t<<5)-t+this.charCodeAt(e),t|=0;return t};var R=new g(o),V=new p}}); //# sourceMappingURL=client.b.js.map
\ No newline at end of file diff --git a/webAO/client.b.js.map b/webAO/client.b.js.map index 3f4563b..d54e9c7 100644 --- a/webAO/client.b.js.map +++ b/webAO/client.b.js.map @@ -1 +1 @@ -{"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","onOOCEnter","onEnter","musiclist_click","changeMusicVolume","changeSFXVolume","changeBlipVolume","changeCharacter","imgError","demoError","ReconnectButton","RetryButton","pickchar","pickemotion","toggleaffect","toggleflip","toggleshout","queryDict","location","search","substr","split","forEach","item","serverIP","ip","AO_HOST","asset","MUSIC_HOST","oldLoading","test","navigator","userAgent","selectedEffect","selectedShout","lastICMessageTime","Date","Client","address","_this","this","_classCallCheck","serv","WebSocket","onopen","evt","onOpen","onclose","onClose","onmessage","onMessage","onerror","onError","flip","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","music","handlemusic","DONE","handleDONE","BN","handleBN","NBG","handleNBG","HP","handleHP","ID","handleID","PN","handlePN","SI","handleSI","CharsCheck","handleCharsCheck","PV","handlePV","CHECK","_lastTimeICReceived","message","send","escapeChat","speaking","silent","side","ssfxname","zoom","ssfxdelay","objection","flash","color","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","preanim","escape","nameplate","sound","type","snddelay","evidence","isnew","length","className","resetICParams","say","oocLog","scrollTop","scrollHeight","pause","src","play","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","Viewport","textnow","startpreanim","startspeaking","preanimdelay","blip","volume","blipChannels","Array","currentBlipChannel","sfxaudio","sfxplayed","updater","shoutTimer","textTimer","_animating","clearTimeout","getAnimLength","initUpdater","animdelay","log","parseInt","setTimeout","updateText","filename","callback","request","arr","Uint8Array","response","duration","String","fromCharCode","delay","_this3","transform","backgroundColor","shout","1","2","3","$","effect","direction","toggle","fontSize","offsetHeight","unsafe","replace","escapeHtml","stylecolor","0","4","5","6","charAt","substring","regex","section","param","comment","line","match","event","keyCode","sendOOC","mychar","myemo","myEmote","myflip","mycolor","checked","sendIC","playtrack","sendMusicChange","setBlipVolume","sendLeaveRoom","image","position","standname","bgfolder","bgFolder","toadd","arguments","undefined","time","entry","nameField","id","createTextNode","getMinutes","timeStamp","innerText","toLocaleTimeString","hour","minute","clientLog","ccharacter","sendCharacter","emo","estring","window","trim","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 selectedEffect = 0;\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\t\t\r\n\t\tthis.flip = false;\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, flip, flash, color) {\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#${flip}#${flash}#${color}#%`\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\t// pre: 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\tflip: 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 = `<img class='demothing${icon_chosen}' id='demo_${i}' ` +\r\n\t\t\t\t`src='${thispick}' alt='${this.chars[i].name}' onclick='pickchar(${i})' ` +\r\n\t\t\t\t`onerror='demoError(this);'>`;\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 += \"<img src='\" + emotes[i].button_off + \"' id='emo_\" + i + \"' alt='\" + emotes[i].desc + \"' class='client_button' onclick='pickemotion(\" + i + \")'>\";\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\"startpreanim\": false,\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\t\"preanimdelay\": 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\t//If preanim existed then determine the length\r\n\t\tif (chatmsg.preanim != \"-\") {\r\n\t\t\tchatmsg.preanimdelay = this.getAnimLength(AO_HOST + 'characters/' + escape(chatmsg.name) + '/' + chatmsg.preanim + '.gif',this.initUpdater);\r\n\t\t} else {\r\n\t\t\tthis.initUpdater(0)\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t/**\r\n\t * Intialize updater\r\n\t * @param {int} animdelay the length of pre-animation \r\n\t */\r\n\tinitUpdater(animdelay){\r\n\t\tconsole.log(animdelay);\r\n\t\tviewport.chatmsg.preanimdelay = parseInt(animdelay); \r\n\t\tviewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\t\r\n\t/**\r\n\t * Gets animation length.\r\n\t * @param {string} filename the animation file name\r\n\t * @param {function} callback the callback function\r\n\t */\r\n\tgetAnimLength(filename,callback) {\r\n\t\t//Source (Thanks to Ryman): https://codepen.io/Ryman/pen/wzioA\r\n\t\tvar request = new XMLHttpRequest();\r\n\t\trequest.open('GET', filename, true);\r\n\t\trequest.responseType = 'arraybuffer';\r\n\t\trequest.addEventListener('load', function () {\r\n\t\t\tvar arr = new Uint8Array(request.response),\r\n\t\t\t// Thanks to http://justinsomnia.org/2006/10/gif-animation-duration-calculation/\r\n\t\t\t// And http://www.w3.org/Graphics/GIF/spec-gif89a.txt\r\n\t\t\tbin = '', \r\n\t\t\tduration = 0;\r\n\t\t\t\r\n\t\t\tfor (var i = 0; i < arr.length; i++) {\t\t\t\t\r\n\t\t\t\tbin += String.fromCharCode( arr[i] )\r\n\r\n\t\t\t\t// Find a Graphic Control Extension hex(21F904__ ____ __00)\r\n\t\t\t\tif (arr[i] == 0x21 \r\n\t\t\t\t && arr[i + 1] == 0xF9 \r\n\t\t\t\t && arr[i + 2] == 0x04 \r\n\t\t\t\t && arr[i + 7] == 0x00) {\r\n\t\t\t\t // Swap 5th and 6th bytes to get the delay per frame\r\n\t\t\t\t let delay = (arr[i + 5] << 8) | (arr[i + 4] & 0xFF)\r\n\t\t\t\t \r\n\t\t\t\t // Should be aware browsers have a minimum frame delay \r\n\t\t\t\t // e.g. 6ms for IE, 2ms modern browsers (50fps)\r\n\t\t\t\t duration += delay < 2 ? 10 : (delay+2)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// Return animation length\r\n\t\t\tcallback(duration * 10);\r\n\t\t});\r\n\t\trequest.send();\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\t// Flip the character\r\n\t\tif (this.chatmsg.flip == 1){\r\n\t\t\tdocument.getElementById(\"client_char\").style.transform = \"scaleX(-1)\"; \r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_char\").style.transform = \"scaleX(1)\";\r\n\t\t}\r\n\t\t\t\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\t// Reset screen background\r\n\t\t\tdocument.getElementById(\"client_background\").style.backgroundColor = \"transparent\";\r\n\t\t\t//Hide message window\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\t\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"objection\",\r\n\t\t\t\t\"3\": \"takethat\"\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_shout\").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 = 850;\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.startpreanim = true;\r\n\t\t}\r\n\r\n\t\tif(this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) {\r\n\t\t\t// Effect stuff\r\n\t\t\tif (this.chatmsg.flash == 2){\r\n\t\t\t\t//Shake screen\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-stab.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$('#client_gamewindow').effect( \"shake\",{\"direction\":\"up\"});\r\n\t\t\t} else if (this.chatmsg.flash == 1) {\r\n\t\t\t\t//Flash screen\r\n\t\t\t\tdocument.getElementById(\"client_background\").style.backgroundColor = \"white\";\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-realization.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$('#client_gamewindow').effect(\"pulsate\");\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//Pre-animation stuff\r\n\t\t\tif(this.chatmsg.preanimdelay > 0){\r\n\t\t\t\tdocument.getElementById(\"client_shout\").src = \"\";\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.preanim + \".gif\";\r\n\t\t\t}\r\n\t\t\tthis.chatmsg.startpreanim = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t} else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\t$(\"#client_name\").toggle( \"fade\" );\r\n\t\t\t\t$(\"#client_chat\").toggle(\"drop\",{\"direction\":\"down\"});\r\n\t\t\t\tif(this.chatmsg.preanimdelay == 0){\r\n\t\t\t\t\tdocument.getElementById(\"client_shout\").src = \"\";\r\n\t\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\t}\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 = \"<p>\" + escapeHtml(this.chatmsg.nameplate) + \"</p>\";\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\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 myflip = ((client.flip)? 1:0);\r\n\t\tlet mycolor = document.getElementById(\"textcolor\").value;\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, myflip, selectedEffect, mycolor);\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 (selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t}\r\n\tif (selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t}\t\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 an effect for in-character chat.\r\n * If the same effect button is selected, then the effect is canceled.\r\n * @param {string} effect the new effect to be selected\r\n */\r\nexport function toggleaffect(effect) {\r\n\tif (effect == selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button dark\";\r\n\t\tif (selectedEffect) {\r\n\t\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedEffect = effect;\r\n\t}\r\n}\r\nwindow.toggleaffect = toggleaffect;\r\n\r\n/**\r\n * Toggle flip for in-character chat.\r\n */\r\nexport function toggleflip() {\r\n\tif (client.flip) {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button dark\";\r\n\t}\r\n\tclient.flip = !client.flip;\r\n}\r\nwindow.toggleflip = toggleflip;\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\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, \"<pound>\")\r\n\t\t.replace(/&/g, \"<and>\")\r\n\t\t.replace(/%/g, \"<percent>\")\r\n\t\t.replace(/\\$/g, \"<dollar>\");\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","onOOCEnter","onEnter","musiclist_click","changeMusicVolume","changeSFXVolume","changeBlipVolume","changeCharacter","imgError","demoError","ReconnectButton","RetryButton","pickchar","pickemotion","toggleaffect","toggleflip","toggleshout","queryDict","location","search","substr","split","forEach","item","serverIP","ip","AO_HOST","asset","MUSIC_HOST","oldLoading","test","navigator","userAgent","selectedEffect","selectedShout","lastICMessageTime","Date","Client","address","_this","this","_classCallCheck","serv","WebSocket","onopen","evt","onOpen","onclose","onClose","onmessage","onMessage","onerror","onError","flip","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","music","handlemusic","DONE","handleDONE","BN","handleBN","NBG","handleNBG","HP","handleHP","ID","handleID","PN","handlePN","SI","handleSI","CharsCheck","handleCharsCheck","PV","handlePV","CHECK","_lastTimeICReceived","message","send","escapeChat","encodeChat","speaking","silent","side","ssfxname","zoom","ssfxdelay","objection","flash","color","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","preanim","escape","nameplate","decodeChat","unescapeChat","sound","type","snddelay","evidence","isnew","length","className","resetICParams","say","oocLog","scrollTop","scrollHeight","pause","src","play","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","Viewport","textnow","startpreanim","startspeaking","preanimdelay","blip","volume","blipChannels","Array","currentBlipChannel","sfxaudio","sfxplayed","updater","shoutTimer","textTimer","_animating","clearTimeout","getAnimLength","initUpdater","animdelay","log","parseInt","setTimeout","updateText","filename","callback","request","arr","Uint8Array","response","duration","String","fromCharCode","delay","_this3","transform","backgroundColor","shout","1","2","3","$","effect","direction","toggle","fontSize","offsetHeight","unsafe","replace","escapeHtml","stylecolor","0","4","5","6","charAt","substring","regex","section","param","comment","line","match","event","keyCode","sendOOC","mychar","myemo","myEmote","myflip","mycolor","checked","sendIC","playtrack","sendMusicChange","setBlipVolume","sendLeaveRoom","image","position","standname","bgfolder","bgFolder","toadd","arguments","undefined","time","entry","nameField","id","createTextNode","getMinutes","timeStamp","innerText","toLocaleTimeString","hour","minute","clientLog","ccharacter","sendCharacter","emo","estring","selectedEncoding","ch","charCodeAt","toString","slice","buffer","ArrayBuffer","result","Uint16Array","strLen","selectedDecoding","group","apply","window","trim","hash"],"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 selectedEffect = 0;\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\t\t\r\n\t\tthis.flip = false;\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(encodeChat(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, flip, flash, color) {\r\n\t\tthis.serv.send(\r\n\t\t\t`MS#chat#${speaking}#${name}#${silent}` +\r\n\t\t\t`#${escapeChat(encodeChat(message))}#${side}#${ssfxname}#${zoom}` +\r\n\t\t\t`#${this.charID}#${ssfxdelay}#${selectedShout}#0#${flip}#${flash}#${color}#%`\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\t// pre: 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: decodeChat(unescapeChat(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\tflip: 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 += `${decodeChat(unescapeChat(args[1]))}: ${decodeChat(unescapeChat(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 = `<img class='demothing${icon_chosen}' id='demo_${i}' ` +\r\n\t\t\t\t`src='${thispick}' alt='${this.chars[i].name}' onclick='pickchar(${i})' ` +\r\n\t\t\t\t`onerror='demoError(this);'>`;\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 += \"<img src='\" + emotes[i].button_off + \"' id='emo_\" + i + \"' alt='\" + emotes[i].desc + \"' class='client_button' onclick='pickemotion(\" + i + \")'>\";\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\"startpreanim\": false,\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\t\"preanimdelay\": 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\t//If preanim existed then determine the length\r\n\t\tif (chatmsg.preanim != \"-\") {\r\n\t\t\tchatmsg.preanimdelay = this.getAnimLength(AO_HOST + 'characters/' + escape(chatmsg.name) + '/' + chatmsg.preanim + '.gif',this.initUpdater);\r\n\t\t} else {\r\n\t\t\tthis.initUpdater(0)\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t/**\r\n\t * Intialize updater\r\n\t * @param {int} animdelay the length of pre-animation \r\n\t */\r\n\tinitUpdater(animdelay){\r\n\t\tconsole.log(animdelay);\r\n\t\tviewport.chatmsg.preanimdelay = parseInt(animdelay); \r\n\t\tviewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\t\r\n\t/**\r\n\t * Gets animation length.\r\n\t * @param {string} filename the animation file name\r\n\t * @param {function} callback the callback function\r\n\t */\r\n\tgetAnimLength(filename,callback) {\r\n\t\t//Source (Thanks to Ryman): https://codepen.io/Ryman/pen/wzioA\r\n\t\tvar request = new XMLHttpRequest();\r\n\t\trequest.open('GET', filename, true);\r\n\t\trequest.responseType = 'arraybuffer';\r\n\t\trequest.addEventListener('load', function () {\r\n\t\t\tvar arr = new Uint8Array(request.response),\r\n\t\t\t// Thanks to http://justinsomnia.org/2006/10/gif-animation-duration-calculation/\r\n\t\t\t// And http://www.w3.org/Graphics/GIF/spec-gif89a.txt\r\n\t\t\tbin = '', \r\n\t\t\tduration = 0;\r\n\t\t\t\r\n\t\t\tfor (var i = 0; i < arr.length; i++) {\t\t\t\t\r\n\t\t\t\tbin += String.fromCharCode( arr[i] )\r\n\r\n\t\t\t\t// Find a Graphic Control Extension hex(21F904__ ____ __00)\r\n\t\t\t\tif (arr[i] == 0x21 \r\n\t\t\t\t && arr[i + 1] == 0xF9 \r\n\t\t\t\t && arr[i + 2] == 0x04 \r\n\t\t\t\t && arr[i + 7] == 0x00) {\r\n\t\t\t\t // Swap 5th and 6th bytes to get the delay per frame\r\n\t\t\t\t let delay = (arr[i + 5] << 8) | (arr[i + 4] & 0xFF)\r\n\t\t\t\t \r\n\t\t\t\t // Should be aware browsers have a minimum frame delay \r\n\t\t\t\t // e.g. 6ms for IE, 2ms modern browsers (50fps)\r\n\t\t\t\t duration += delay < 2 ? 10 : (delay+2)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// Return animation length\r\n\t\t\tcallback(duration * 10);\r\n\t\t});\r\n\t\trequest.send();\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\t// Flip the character\r\n\t\tif (this.chatmsg.flip == 1){\r\n\t\t\tdocument.getElementById(\"client_char\").style.transform = \"scaleX(-1)\"; \r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_char\").style.transform = \"scaleX(1)\";\r\n\t\t}\r\n\t\t\t\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\t// Reset screen background\r\n\t\t\tdocument.getElementById(\"client_background\").style.backgroundColor = \"transparent\";\r\n\t\t\t//Hide message window\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\t\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"objection\",\r\n\t\t\t\t\"3\": \"takethat\"\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_shout\").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 = 850;\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.startpreanim = true;\r\n\t\t}\r\n\r\n\t\tif(this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) {\r\n\t\t\t// Effect stuff\r\n\t\t\tif (this.chatmsg.flash == 2){\r\n\t\t\t\t//Shake screen\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-stab.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$('#client_gamewindow').effect( \"shake\",{\"direction\":\"up\"});\r\n\t\t\t} else if (this.chatmsg.flash == 1) {\r\n\t\t\t\t//Flash screen\r\n\t\t\t\tdocument.getElementById(\"client_background\").style.backgroundColor = \"white\";\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-realization.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$('#client_gamewindow').effect(\"pulsate\");\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//Pre-animation stuff\r\n\t\t\tif(this.chatmsg.preanimdelay > 0){\r\n\t\t\t\tdocument.getElementById(\"client_shout\").src = \"\";\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.preanim + \".gif\";\r\n\t\t\t}\r\n\t\t\tthis.chatmsg.startpreanim = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t} else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\t$(\"#client_name\").toggle( \"fade\" );\r\n\t\t\t\t$(\"#client_chat\").toggle(\"drop\",{\"direction\":\"down\"});\r\n\t\t\t\tif(this.chatmsg.preanimdelay == 0){\r\n\t\t\t\t\tdocument.getElementById(\"client_shout\").src = \"\";\r\n\t\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\t}\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 = \"<p>\" + escapeHtml(this.chatmsg.nameplate) + \"</p>\";\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\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 myflip = ((client.flip)? 1:0);\r\n\t\tlet mycolor = document.getElementById(\"textcolor\").value;\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, myflip, selectedEffect, mycolor);\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 (selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t}\r\n\tif (selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t}\t\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 an effect for in-character chat.\r\n * If the same effect button is selected, then the effect is canceled.\r\n * @param {string} effect the new effect to be selected\r\n */\r\nexport function toggleaffect(effect) {\r\n\tif (effect == selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button dark\";\r\n\t\tif (selectedEffect) {\r\n\t\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedEffect = effect;\r\n\t}\r\n}\r\nwindow.toggleaffect = toggleaffect;\r\n\r\n/**\r\n * Toggle flip for in-character chat.\r\n */\r\nexport function toggleflip() {\r\n\tif (client.flip) {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button dark\";\r\n\t}\r\n\tclient.flip = !client.flip;\r\n}\r\nwindow.toggleflip = toggleflip;\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\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, \"<pound>\")\r\n\t\t.replace(/&/g, \"<and>\")\r\n\t\t.replace(/%/g, \"<percent>\")\r\n\t\t.replace(/\\$/g, \"<dollar>\");\r\n}\r\n\r\n/**\r\n * Unescapes a string to AO1 escape codes.\r\n * @param {string} estring the string to be unescaped\r\n */\r\nfunction unescapeChat(estring) {\r\n\treturn estring\r\n\t\t.replace(/<pound>/g, \"#\")\r\n\t\t.replace(/<and>/g, \"&\")\r\n\t\t.replace(/<percent>/g, \"%\")\r\n\t\t.replace(/\\<dollar>/g, \"$\");\r\n}\r\n\r\n/**\r\n * Encoding text on client side.\r\n * @param {string} estring the string to be encoded\r\n */\r\nfunction encodeChat(estring) {\r\n\tlet selectedEncoding = document.getElementById(\"client_encoding\").value;\r\n\tif (selectedEncoding == \"unicode\") {\r\n\t\t//Source: https://gist.github.com/mathiasbynens/1243213\r\n\t\treturn estring.replace(/[^\\0-~]/g, function(ch) {\r\n\t\t\treturn \"\\\\u\" + (\"000\" + ch.charCodeAt().toString(16)).slice(-4); });\r\n\t} else if (selectedEncoding == \"utf16\"){\r\n\t\t//Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\r\n\t\tvar buffer = new ArrayBuffer(estring.length*2);\r\n\t\tvar result = new Uint16Array(buffer);\r\n\t\tfor (var i=0, strLen=estring.length; i < strLen; i++) {\r\n\t\t\tresult[i] = estring.charCodeAt(i);\r\n\t\t}\r\n\t\treturn String(result);\r\n\t} else {\r\n\t\treturn estring;\r\n\t}\r\n}\r\n\r\n/**\r\n * Decoding text on client side.\r\n * @param {string} estring the string to be decoded\r\n */\r\nfunction decodeChat(estring) {\r\n\tlet selectedDecoding = document.getElementById(\"client_decoding\").value;\r\n\tif (selectedDecoding == \"unicode\") {\r\n\t\t//Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode\r\n return estring.replace(/\\\\u([\\d\\w]{1,})/gi, function (match, group) {\r\n\t\t\treturn String.fromCharCode(parseInt(group, 16)); } );\r\n\t} else if (selectedDecoding == \"utf16\"){\t\r\n\t\t//Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\r\n\t\treturn String.fromCharCode.apply(null, new Uint16Array(estring.split(\",\")));\r\n\t} else {\r\n\t\treturn estring;\r\n\t}\r\n}\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.html b/webAO/client.html index 8c54a77..4c34982 100644 --- a/webAO/client.html +++ b/webAO/client.html @@ -61,6 +61,21 @@ <template id="client_settings"> <meta name="frame-title" lang="en" content="Settings"> + <br><br> + <label for="client_encoding"> Client Side Chat Encoding:</label> + <select id="client_encoding" name="client_encoding"> + <option value="none">None</option> + <option value="unicode">Unicode</option> + <option value="utf16">UTF-16</option> + </select> + <br><br> + <label for="client_decoding"> Client Side Chat Decoding:</label> + <select id="client_decoding" name="client_decoding"> + <option value="none">None</option> + <option value="unicode">Unicode</option> + <option value="utf16">UTF-16</option> + </select> + <br><br> <div class="slider">Music<input id="client_mvolume" class="long" type="range" min="0" max="100" value="80" onchange="changeMusicVolume()"></div> <div class="slider">SFX <input id="client_svolume" class="long" type="range" min="0" max="100" value="70" onchange="changeSFXVolume()"></div> <div class="slider">Blip <input id="client_bvolume" class="long" type="range" min="0" max="100" value="60" onchange="changeBlipVolume()"></div> diff --git a/webAO/client.js b/webAO/client.js index 76ced68..14b9a51 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -99,7 +99,7 @@ class Client { * @param {string} message the message to send */ sendOOC(message) { - this.serv.send(`CT#web${this.playerID}#${escapeChat(message)}#%`); + this.serv.send(`CT#web${this.playerID}#${escapeChat(encodeChat(message))}#%`); } /** @@ -117,7 +117,7 @@ class Client { sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, flip, flash, color) { this.serv.send( `MS#chat#${speaking}#${name}#${silent}` + - `#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` + + `#${escapeChat(encodeChat(message))}#${side}#${ssfxname}#${zoom}` + `#${this.charID}#${ssfxdelay}#${selectedShout}#0#${flip}#${flash}#${color}#%` ); } @@ -253,7 +253,7 @@ class Client { name: args[3], speaking: "(b)" + escape(args[4]), silent: "(a)" + escape(args[4]), - content: args[5], + content: decodeChat(unescapeChat(args[5])), side: args[6], sound: escape(args[7]), type: args[8], @@ -289,7 +289,7 @@ class Client { */ handleCT(args) { const oocLog = document.getElementById("client_ooclog"); - oocLog.innerHTML += `${args[1]}: ${args[2]}\r\n`; + oocLog.innerHTML += `${decodeChat(unescapeChat(args[1]))}: ${decodeChat(unescapeChat(args[2]))}\r\n`; if (oocLog.scrollTop > oocLog.scrollHeight - 60) { oocLog.scrollTop = oocLog.scrollHeight; } @@ -1205,6 +1205,60 @@ function escapeChat(estring) { .replace(/\$/g, "<dollar>"); } +/** + * Unescapes a string to AO1 escape codes. + * @param {string} estring the string to be unescaped + */ +function unescapeChat(estring) { + return estring + .replace(/<pound>/g, "#") + .replace(/<and>/g, "&") + .replace(/<percent>/g, "%") + .replace(/\<dollar>/g, "$"); +} + +/** + * Encoding text on client side. + * @param {string} estring the string to be encoded + */ +function encodeChat(estring) { + let selectedEncoding = document.getElementById("client_encoding").value; + if (selectedEncoding == "unicode") { + //Source: https://gist.github.com/mathiasbynens/1243213 + return estring.replace(/[^\0-~]/g, function(ch) { + return "\\u" + ("000" + ch.charCodeAt().toString(16)).slice(-4); }); + } else if (selectedEncoding == "utf16"){ + //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String + var buffer = new ArrayBuffer(estring.length*2); + var result = new Uint16Array(buffer); + for (var i=0, strLen=estring.length; i < strLen; i++) { + result[i] = estring.charCodeAt(i); + } + return String(result); + } else { + return estring; + } +} + +/** + * Decoding text on client side. + * @param {string} estring the string to be decoded + */ +function decodeChat(estring) { + let selectedDecoding = document.getElementById("client_decoding").value; + if (selectedDecoding == "unicode") { + //Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode + return estring.replace(/\\u([\d\w]{1,})/gi, function (match, group) { + return String.fromCharCode(parseInt(group, 16)); } ); + } else if (selectedDecoding == "utf16"){ + //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String + return String.fromCharCode.apply(null, new Uint16Array(estring.split(","))); + } else { + return estring; + } +} + + // TODO: Possibly safe to remove, since we are using a transpiler. if (typeof(String.prototype.trim) === "undefined") { |
