aboutsummaryrefslogtreecommitdiff
path: root/webAO/client.b.js.map
diff options
context:
space:
mode:
Diffstat (limited to 'webAO/client.b.js.map')
-rw-r--r--webAO/client.b.js.map2
1 files changed, 1 insertions, 1 deletions
diff --git a/webAO/client.b.js.map b/webAO/client.b.js.map
index 7794698..238e89d 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","encodeChat","speaking","silent","side","ssfxname","zoom","ssfxdelay","objection","flash","color","track","_this2","hashCode","setInterval","sendCheck","target","document","getElementById","MutationObserver","mutations","mutation","children","addedNodes","node","tagName","style","getAttribute","hasAttribute","backgroundColor","observe","attributes","childList","character","song","e","display","client","joinServer","console","error","reason","code","textContent","cleanup","msg","data","debug","header","handler","warn","close","clearInterval","viewport","chatmsg","content","innerHTML","preanim","escape","nameplate","estring","replace","decodeBBCode","escapeHtml","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","parseInt","setTimeout","updateText","filename","callback","request","arr","Uint8Array","response","duration","String","fromCharCode","delay","_this3","transform","shout","1","2","3","$","effect","direction","toggle","fontSize","offsetHeight","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","unsafe","selectedEncoding","ch","charCodeAt","toString","slice","buffer","ArrayBuffer","result","Uint16Array","strLen","selectedDecoding","group","apply","window","trim","hash","ready","initialObservBBCode"],"mappings":"aACA,IAAAA,KAGA,SAAAC,EAAAC,GAGA,GAAAF,EAAAE,GACA,OAAAF,EAAAE,GAAAC,QAGA,IAAAC,EAAAJ,EAAAE,IACAG,EAAAH,EACAI,GAAA,EACAH,YAUA,OANAI,EAAAL,GAAAM,KAAAJ,EAAAD,QAAAC,IAAAD,QAAAF,GAGAG,EAAAE,GAAA,EAGAF,EAAAD,QAKAF,EAAAQ,EAAAF,EAGAN,EAAAS,EAAAV,EAGAC,EAAAU,EAAA,SAAAR,EAAAS,EAAAC,GACAZ,EAAAa,EAAAX,EAAAS,IACAG,OAAAC,eAAAb,EAAAS,GAA0CK,YAAA,EAAAC,IAAAL,KAK1CZ,EAAAkB,EAAA,SAAAhB,GACA,oBAAAiB,eAAAC,aACAN,OAAAC,eAAAb,EAAAiB,OAAAC,aAAwDC,MAAA,WAExDP,OAAAC,eAAAb,EAAA,cAAiDmB,OAAA,KAQjDrB,EAAAsB,EAAA,SAAAD,EAAAE,GAEA,GADA,EAAAA,IAAAF,EAAArB,EAAAqB,IACA,EAAAE,EAAA,OAAAF,EACA,KAAAE,GAAA,iBAAAF,QAAAG,WAAA,OAAAH,EACA,IAAAI,EAAAX,OAAAY,OAAA,MAGA,GAFA1B,EAAAkB,EAAAO,GACAX,OAAAC,eAAAU,EAAA,WAAyCT,YAAA,EAAAK,UACzC,EAAAE,GAAA,iBAAAF,EAAA,QAAAM,KAAAN,EAAArB,EAAAU,EAAAe,EAAAE,EAAA,SAAAA,GAAgH,OAAAN,EAAAM,IAAqBC,KAAA,KAAAD,IACrI,OAAAF,GAIAzB,EAAA6B,EAAA,SAAA1B,GACA,IAAAS,EAAAT,KAAAqB,WACA,WAA2B,OAAArB,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAH,EAAAU,EAAAE,EAAA,IAAAA,GACAA,GAIAZ,EAAAa,EAAA,SAAAiB,EAAAC,GAAsD,OAAAjB,OAAAkB,UAAAC,eAAA1B,KAAAuB,EAAAC,IAGtD/B,EAAAkC,EAAA,GAIAlC,IAAAmC,EAAA,8aCmzBgBC,eAYAC,YAsCAC,oBASAC,sBAQAC,oBAQAC,qBASAC,oBAWAC,aAWAC,cAqEAC,oBAaAC,gBA2CAC,aAgBAC,gBAcAC,iBAiBAC,eAeAC,cApqChB,IAAIC,KACJC,SAASC,OAAOC,OAAO,GAAGC,MAAM,KAAKC,QAAQ,SAASC,GACrDN,EAAUM,EAAKF,MAAM,KAAK,IAAME,EAAKF,MAAM,KAAK,KAKjD,IAAMG,EAAWP,EAAUQ,GACvBrC,EAAO6B,EAAU7B,KAEfsC,EAAUT,EAAUU,OAAS,4CAC7BC,EAAaF,EAAU,gBAMzBG,GAAa,EACb,uGAAuGC,KAAKC,UAAUC,aACzHH,GAAa,GAGd,IAAII,EAAiB,EACjBC,EAAgB,EAChBC,EAAoB,IAAIC,KAAK,GAE3BC,aACL,SAAAA,EAAYC,GAAS,IAAAC,EAAAC,KAAAC,EAAAD,KAAAH,GACpBG,KAAKE,KAAO,IAAIC,UAAU,QAAUL,GAEpCE,KAAKE,KAAKE,OAAY,SAACC,GAAD,OAASN,EAAKO,OAAOD,IAC3CL,KAAKE,KAAKK,QAAY,SAACF,GAAD,OAASN,EAAKS,QAAQH,IAC5CL,KAAKE,KAAKO,UAAY,SAACJ,GAAD,OAASN,EAAKW,UAAUL,IAC9CL,KAAKE,KAAKS,QAAY,SAACN,GAAD,OAASN,EAAKa,QAAQP,IAE5CL,KAAKa,MAAO,EAEZb,KAAKc,SAAW,EAChBd,KAAKe,QAAU,EAEff,KAAKgB,SACLhB,KAAKiB,UAELjB,KAAKkB,eAAiB,EAEtBlB,KAAKmB,aAAe,KAGpBnB,KAAKoB,UAAYjF,SAEjB6D,KAAKqB,UACJC,GAAc,SAACC,GAAD,OAAUxB,EAAKyB,SAASD,IACtCE,GAAc,SAACF,GAAD,OAAUxB,EAAK2B,SAASH,IACtCI,GAAc,SAACJ,GAAD,OAAUxB,EAAK6B,SAASL,IACtCM,IAAc,SAACN,GAAD,OAAUxB,EAAK+B,UAAUP,IACvCQ,GAAc,SAACR,GAAD,OAAUxB,EAAKiC,SAAST,IACtCU,GAAc,SAACV,GAAD,OAAUxB,EAAKmC,SAASX,IACtCY,GAAc,SAACZ,GAAD,OAAUxB,EAAKqC,SAASb,IACtCc,GAAc,SAACd,GAAD,OAAUxB,EAAKuC,SAASf,IACtCgB,GAAc,SAAChB,GAAD,OAAUxB,EAAKyC,SAASjB,IACtCkB,MAAc,SAAClB,GAAD,OAAUxB,EAAK2C,YAAYnB,IACzCoB,KAAc,SAACpB,GAAD,OAAUxB,EAAK6C,WAAWrB,IACxCsB,GAAc,SAACtB,GAAD,OAAUxB,EAAK+C,SAASvB,IACtCwB,IAAc,SAACxB,GAAD,OAAUxB,EAAKiD,UAAUzB,IACvC0B,GAAc,SAAC1B,GAAD,OAAUxB,EAAKmD,SAAS3B,IACtC4B,GAAc,SAAC5B,GAAD,OAAUxB,EAAKqD,SAAS7B,IACtC8B,GAAc,SAAC9B,GAAD,OAAUxB,EAAKuD,SAAS/B,IACtCgC,GAAc,SAAChC,GAAD,OAAUxB,EAAKyD,SAASjC,IACtCkC,WAAc,SAAClC,GAAD,OAAUxB,EAAK2D,iBAAiBnC,IAC9CoC,GAAc,SAACpC,GAAD,OAAUxB,EAAK6D,SAASrC,IACtCsC,MAAc,SAACtC,MAGhBvB,KAAK8D,oBAAsB,IAAIlE,KAAK,0CAOpC,OAAOI,KAAKgB,MAAMhB,KAAKe,0CAOvB,OAAOf,KAAKiB,OAAOjB,KAAKkB,+CAOjB6C,GACP/D,KAAKE,KAAK8D,KAAV,SAAwBhE,KAAKc,SAA7B,IAAyCmD,EAAWC,EAAWH,IAA/D,qCAeMI,EAAUnI,EAAMoI,EAAQL,EAASM,EAAMC,EAAUC,EAAMC,EAAWC,EAAW5D,EAAM6D,EAAOC,GAChG3E,KAAKE,KAAK8D,KACT,WAAWG,EAAX,IAAuBnI,EAAvB,IAA+BoI,EAA/B,IACIH,EAAWC,EAAWH,IAD1B,IACuCM,EADvC,IAC+CC,EAD/C,IAC2DC,EAD3D,IAEIvE,KAAKe,OAFT,IAEmByD,EAFnB,IAEgC9E,EAFhC,MAEmDmB,EAFnD,IAE2D6D,EAF3D,IAEoEC,EAFpE,8CAUcC,GACf5E,KAAKE,KAAK8D,KAAV,MAAqBY,EAArB,IAA8B5E,KAAKe,OAAnC,8CAUAf,KAAKE,KAAK8D,KAAK,6CAOH,IAAAa,EAAA7E,KACZA,KAAKE,KAAK8D,KAAV,MAAqBzE,UAAUC,UAAUsF,WAAzC,MACA9E,KAAKE,KAAK8D,KAAK,oBACfhE,KAAKmB,aAAe4D,YAAY,kBAAMF,EAAKG,aAAa,mDAQxD,IAAIC,EAASC,SAASC,eAAe,qBACtB,IAAIC,iBAAiB,SAASC,GAC3CA,EAAUvG,QAAQ,SAASwG,GAC5B,IAAIC,EAAWD,EAASE,WACP,OAAbD,GACHA,EAASzG,QAAS,SAAS2G,GACN,KAAhBA,EAAKC,QACRD,EAAKE,MAAMhB,MAAQc,EAAKG,aAAa,KACZ,KAAhBH,EAAKC,UACVD,EAAKI,aAAa,KACrBJ,EAAKE,MAAMG,gBAAkBL,EAAKG,aAAa,MAE/CH,EAAKE,MAAMG,gBAAkB,SAC7BL,EAAKE,MAAMhB,MAAQ,gBAQfoB,QAAQd,GADHe,YAAY,EAAKC,WAAW,0CAQ7BC,GACblG,KAAKE,KAAK8D,KAAV,MAAqBhE,KAAKc,SAA1B,IAAsCoF,EAAtC,4CAOSC,GACTnG,KAAKE,KAAK8D,KAAV,MAAqBmC,uCAOrBnG,KAAKE,KAAK8D,KAAV,MAAqBhE,KAAKe,OAA1B,qCAMMqF,GAEO,UAATxJ,GACHsI,SAASC,eAAe,kBAAkBQ,MAAMU,QAAU,OAC1DnB,SAASC,eAAe,qBAAqBQ,MAAMU,QAAU,QAE7DC,EAAOC,6CAQDH,GACPI,QAAQC,MAAR,8BAA4CL,EAAEM,OAA9C,KAAyDN,EAAEO,KAA3D,KACe,OAAXP,EAAEO,OACLzB,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,QACxDnB,SAASC,eAAe,YAAYyB,YAAcR,EAAEO,KACpD3G,KAAK6G,6CAQGT,GACT,IAAIU,EAAMV,EAAEW,KACZP,QAAQQ,MAAMF,GACd,IACIvF,EADQuF,EAAIjI,MAAM,KACL,GAAGA,MAAM,KACtBoI,EAAS1F,EAAK,GACd2F,EAAUlH,KAAKqB,SAAS4F,QACL,IAAZC,EACVA,EAAQ3F,GAERiF,QAAQW,KAAR,yBAAsCF,mCAQhCb,GACPI,QAAQC,MAAR,6BAA2CL,EAAEM,OAA7C,KAAwDN,EAAEO,KAA1D,KACAzB,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,QACxDnB,SAASC,eAAe,YAAYyB,YAAcR,EAAEO,KACpD3G,KAAK6G,4CAIL,IACC7G,KAAKE,KAAKkH,MAAM,MACf,MAAOhB,IAGTiB,cAAcrH,KAAKmB,+CAOXI,GAER,GAAIA,EAAK,IAAM+F,EAASC,QAAQC,QAAS,CACxCtC,SAASC,eAAe,qBAAqBsC,UAAY,GAwBzD,IAvBA,IAAIF,GAEHrB,WAAY,EACZwB,QAASC,OAAOpG,EAAK,IACrBqG,UAAWrG,EAAK,GAChBvF,KAAMuF,EAAK,GACX4C,SAAU,MAAQwD,OAAOpG,EAAK,IAC9B6C,OAAQ,MAAQuD,OAAOpG,EAAK,IAC5BiG,QAg/BJ,SAAsBK,GACrB,OAAOA,EACLC,QAAQ,OAAQ,QAChBA,QAAQ,cAAe,SACvBA,QAAQ,cAAe,SACvBA,QAAQ,gBAAiB,WACzBA,QAAQ,cAAe,WACvBA,QAAQ,gBAAiB,WACzBA,QAAQ,gBAAiB,WACzBA,QAAQ,yBAA0B,cAClCA,QAAQ,cAAe,SACvBA,QAAQ,0BAA2B,cACnCA,QAAQ,WAAY,QA5/BVC,CAAaC,EAAWC,EAAWC,EAAa3G,EAAK,OAC9D8C,KAAM9C,EAAK,GACX4G,MAAOR,OAAOpG,EAAK,IACnB6G,KAAM7G,EAAK,GAEX8G,SAAU9G,EAAK,IACfkD,UAAWlD,EAAK,IAChB+G,SAAU/G,EAAK,IACfV,KAAMU,EAAK,IACXmD,MAAOnD,EAAK,IACZoD,MAAOpD,EAAK,IACZgH,OAAO,GAIC9M,EAAI,EAAGA,EAAIuE,KAAKgB,MAAMwH,OAAQ/M,IACtC,GAAIuE,KAAKgB,MAAMvF,GAAGO,MAAQuF,EAAK,GAAI,CAClCgG,EAAQrB,UAAYzK,EACpB,MAIE8L,EAAQrB,WAAalG,KAAKe,QAqnBjC,WACCmE,SAASC,eAAe,mBAAmBzI,MAAQ,GAC/C+C,IACHyF,SAASC,eAAe,iBAAmB1F,GAAgBgJ,UAAY,gBACvEhJ,EAAiB,GAEdC,IACHwF,SAASC,eAAe,UAAYzF,GAAe+I,UAAY,gBAC/D/I,EAAgB,GA5nBdgJ,GAGDpB,EAASqB,IAAIpB,qCAQNhG,GACR,IAAMqH,EAAS1D,SAASC,eAAe,iBACvCyD,EAAOnB,WAAgBQ,EAAWC,EAAa3G,EAAK,KAApD,KAA6D0G,EAAWC,EAAa3G,EAAK,KAA1F,OACIqH,EAAOC,UAAYD,EAAOE,aAAe,KAC5CF,EAAOC,UAAYD,EAAOE,+CAQnBvH,GACR,IAAMkB,EAAQ6E,EAAS7E,OACvBA,EAAMsG,QACNtG,EAAMuG,IAAM5J,EAAamC,EAAK,GAC9BkB,EAAMwG,OACF1H,EAAK,IAAM,GAEd2H,EADgBlJ,KAAKgB,MAAMO,EAAK,IAAIvF,KACpC,qBAA6CuF,EAAK,IAElD2H,8BAAwC3H,EAAK,sCAQrCA,GACT+F,EAAS7E,MAAMsG,QACfzB,EAAS7E,MAAQ,IAAI0G,MAAMnJ,KAAKoB,UAAUG,EAAK,KAC/C,IAAMkB,EAAQ6E,EAAS7E,MAEvBA,EAAM2G,OAAS7H,EAAK,GACpBkB,EAAM4G,QAAS,IAAIzJ,MAAO0J,UAAY,IACtC7G,EAAM8G,iBAAiB,iBAAkB,WACxC9G,EAAM+G,aAAeC,WAAWhH,EAAM2G,SAAU,IAAIxJ,MAAO0J,UAAY,IAAO7G,EAAM4G,SAASK,QAAQ,GACrGjH,EAAMwG,SACJ,oCAQK1H,GACR2D,SAASC,eAAe,sBAAsBsC,UAAY,qBAAuBlG,EAAK,GACtFvB,KAAKE,KAAK8D,KAAK,OAAUzC,EAAK,GAAK,GAAM,GAAK,MAC9C,IAAK,IAAI9F,EAAI,EAAGA,EAAI8F,EAAKiH,OAAS,EAAG/M,IACpC,GAAIA,EAAI,GAAK,EAAG,CACf,IAAIkO,EAASpI,EAAK9F,GAAGoD,MAAM,KAC3BmB,KAAKgB,MAAMO,EAAK9F,EAAI,KACnBO,KAAQ2N,EAAO,GACfC,KAAQD,EAAO,GACfrB,SAAYqB,EAAO,GACnBE,KAAQ3K,EAAU,cAAgByI,OAAOgC,EAAO,IAAM,oDAWjDpI,GACR2D,SAASC,eAAe,sBAAsBsC,UAAY,qBAC1D,IAAK,IAAIhM,EAAI,EAAGA,EAAI8F,EAAKiH,OAAS,EAAG/M,IAAK,CACzC,IAAIkO,EAASpI,EAAK9F,GAAGoD,MAAM,KAC3BmB,KAAKgB,MAAMvF,EAAI,IACdO,KAAQ2N,EAAO,GACfC,KAAQD,EAAO,GACfrB,SAAYqB,EAAO,GACnBE,KAAQ3K,EAAU,cAAgByI,OAAOgC,EAAO,IAAM,kBAGxD3J,KAAKE,KAAK8D,KAAK,yCAUPzC,GACR2D,SAASC,eAAe,sBAAsBsC,UAAY,oBAAsBlG,EAAK,GAErFvB,KAAKE,KAAK8D,KAAK,yCAQPzC,GACR2D,SAASC,eAAe,sBAAsBsC,UAAY,iBAAmBlG,EAAK,GAClFvB,KAAKE,KAAK8D,KAAK,OAAUzC,EAAK,GAAK,GAAM,GAAK,MAE9C,IADA,IAAIuI,EAAa5E,SAASC,eAAe,oBAChC1J,EAAI,EAAGA,EAAI8F,EAAKiH,OAAS,EAAG/M,IACpC,GAAIA,EAAI,GAAK,EAAG,CACf,IAAIsO,EAAW7E,SAAS8E,cAAc,UACtCD,EAASE,KAAO1I,EAAK9F,GACrBqO,EAAWI,QAAQC,IAAIJ,qCAUjBxI,GACR2D,SAASC,eAAe,sBAAsBsC,UAAY,iBAE1D,IADA,IAAIqC,EAAa5E,SAASC,eAAe,oBAChC1J,EAAI,EAAGA,EAAI8F,EAAKiH,OAAS,EAAG/M,IAAK,CACzC,IAAIsO,EAAW7E,SAAS8E,cAAc,UACtCD,EAASE,KAAO1I,EAAK9F,GACrBqO,EAAWI,QAAQC,IAAIJ,GAExB/J,KAAKE,KAAK8D,KAAK,4CAQJzC,GACX,IAAK,IAAI9F,EAAI,EAAGA,EAAI8F,EAAKiH,OAAS,EAAG/M,IACpCuE,KAAKoB,UAAUG,EAAK,EAAI9F,IAAM8F,EAAK,EAAI9F,EAAI,sCAUlC8F,GACV2D,SAASC,eAAe,kBAAkBQ,MAAMU,QAAU,OAC1DnB,SAASC,eAAe,qBAAqBQ,MAAMU,QAAU,yCAOrD9E,GACR+F,EAAS8C,OAASzC,OAAOpG,EAAK,sCAGrBA,qCAQDA,GAGO,GAAXA,EAAK,GACR2D,SAASC,eAAe,qBAAqBQ,MAAM0E,KAAO,YAvd3C,GAudqE9I,EAAK,GAAK,GAAK,eAEnG2D,SAASC,eAAe,wBAAwBQ,MAAM0E,KAAO,YAzd9C,GAydwE9I,EAAK,GAAK,GAAK,gDAQ/FA,GACRvB,KAAKc,SAAWS,EAAK,oCAGbA,GACRvB,KAAKE,KAAK8D,KAAK,8CAQPzC,GACJlC,EACHW,KAAKE,KAAK8D,KAAK,cAEfhE,KAAKE,KAAK8D,KAAK,iDAQAzC,GAChB2D,SAASC,eAAe,oBAAoBsC,UAAY,GACxD,IAAK,IAAIhM,EAAI,EAAGA,EAAIuE,KAAKgB,MAAMwH,OAAQ/M,IAAK,CAC3C,GAAIA,EA3fmB,GA2fM,EAC5B,IAAI6O,EAAKpF,SAAS8E,cAAc,MAEjC,IAAIO,EAAKrF,SAAS8E,cAAc,MAC5BQ,SACAC,EAAWzK,KAAKgB,MAAMvF,GAAGoO,KAE5BW,EADkB,MAAfjJ,EAAK9F,EAAI,GACE,QAEA,GAEf8O,EAAG9C,UAAY,wBAAwB+C,EAAxB,cAAiD/O,EAAjD,UACNgP,EADM,UACYzK,KAAKgB,MAAMvF,GAAGO,KAD1B,uBACqDP,EADrD,iCAGf6O,EAAGI,YAAYH,GACX9O,EA1gBmB,GA0gBM,GAC5ByJ,SAASC,eAAe,oBAAoBuF,YAAYJ,GAG1DK,EAAiB,wCAOTpJ,GACRvB,KAAKe,OAASQ,EAAK,GACnB2D,SAASC,eAAe,qBAAqBQ,MAAMU,QAAU,OAC7D,IAAIuE,EAAK5K,KAAK4K,KACV3J,EAASjB,KAAKiB,OACd4J,EAAM,IAAIC,eACdD,EAAIE,KAAK,MAAO7L,EAAU,cAAgByI,OAAO3H,KAAK4K,KAAK5O,MAAQ,aAAa,GAChF6O,EAAIG,aAAe,OACnBH,EAAII,OAAS,SAAU7E,GACtB,GAAmB,KAAfpG,KAAKkL,OAAe,CACvB,IAAIC,EAAWnL,KAAKoL,aAChBC,EAAWC,EAAIC,MAAMJ,GACzBP,EAAGvG,KAAOgH,EAASG,QAAQnH,KAC3B,IAAK,IAAI5I,EAAI,EAAGA,EAAI4P,EAASI,SAASC,OAAQjQ,IAAK,CAClD,IAAIkQ,EAAYN,EAASI,SAAShQ,GAAGoD,MAAM,KACvC+M,EAAO,IACPC,EAAQ,SACmB,IAApBR,EAASS,SACnBF,EAAOP,EAASS,OAAOrQ,SAEO,IAApB4P,EAASU,SACnBF,EAAQR,EAASU,OAAOtQ,IAEzBwF,EAAOxF,IACNmO,KAAM+B,EAAU,GAChBxH,SAAUwH,EAAU,GACpBvH,OAAQuH,EAAU,GAClBpH,KAAMoH,EAAU,GAChBK,IAAKJ,EACLK,SAAUJ,EACVK,WAAYhN,EAAU,cAAgByI,OAAOiD,EAAG5O,MAAQ,mBAAqBP,EAAI,WACjF0Q,UAAWjN,EAAU,cAAgByI,OAAOiD,EAAG5O,MAAQ,mBAAqBP,EAAI,WAEjFyJ,SAASC,eAAe,cAAcsC,WAAa,aAAexG,EAAOxF,GAAGyQ,WAAa,aAAezQ,EAAI,UAAYwF,EAAOxF,GAAGmO,KAAO,gDAAkDnO,EAAI,MAEhM4C,EAAY,KAGdwM,EAAI7G,gBAIAoI,aACL,SAAAA,IAAcnM,EAAAD,KAAAoM,GACbpM,KAAKqM,QAAU,GACfrM,KAAKuH,SACJgB,OAAS,EACTf,QAAW,GACX/C,UAAa,IACb0D,MAAS,GACTmE,cAAgB,EAChBC,eAAiB,EACjBlI,KAAQ,KACRM,MAAS,IACT0D,SAAY,EACZmE,aAAgB,GAEjBxM,KAAKyM,KAAO,IAAItD,MAAMjK,EAAU,mCAChCc,KAAKyM,KAAKC,OAAS,GAKnB1M,KAAK2M,aAAe,IAAIC,MAAM,GAC9B,IAAK,IAAInR,EAAI,EAAGA,EAAIuE,KAAK2M,aAAanE,OAAQ/M,IAC7CuE,KAAK2M,aAAalR,GAAK,IAAI0N,MAAMjK,EAAU,mCAC3Cc,KAAK2M,aAAalR,GAAGiR,OAAS,GAE/B1M,KAAK6M,mBAAqB,EAE1B7M,KAAK8M,SAAW,IAAI3D,MAAMjK,EAAU,mCACpCc,KAAK+M,UAAY,EAEjB/M,KAAKyC,MAAQ,IAAI0G,MACjBnJ,KAAKyC,MAAMwG,OAEXjJ,KAAKgN,QAAU,KAEfhN,KAAKoK,OAAS,MAEdpK,KAAKiN,WAAa,EAClBjN,KAAKkN,UAAY,EAEjBlN,KAAKmN,YAAa,kDAQlB,OAAOnN,KAAKmN,iDAOCT,GACb,IAAK,IAAIjR,EAAI,EAAGA,EAAIuE,KAAK2M,aAAanE,OAAQ/M,IAC7CuE,KAAK2M,aAAalR,GAAGiR,OAASA,qCAQ/B,OAAUxN,EAAV,cAA+Bc,KAAKoK,OAApC,gCAOG7C,GACHvH,KAAKuH,QAAUA,EACf2B,EAAY3B,EAAQC,QAASD,EAAQK,WACrC+C,EAAiBpD,EAAQlD,MACzBrE,KAAKqM,QAAU,GACfrM,KAAK+M,UAAY,EACjB/M,KAAKkN,UAAY,EACjBlN,KAAKmN,YAAa,EAClBC,aAAapN,KAAKgN,SAEK,KAAnBzF,EAAQG,QACXH,EAAQiF,aAAexM,KAAKqN,cAAcnO,EAAU,cAAgByI,OAAOJ,EAAQvL,MAAQ,IAAMuL,EAAQG,QAAU,OAAO1H,KAAKsN,aAE/HtN,KAAKsN,YAAY,uCAQPC,GACXjG,EAASC,QAAQiF,aAAegB,SAASD,GACzCjG,EAAS0F,QAAUS,WAAW,kBAAMnG,EAASoG,cA9pBvB,0CAsqBTC,EAASC,GAEtB,IAAIC,EAAU,IAAI/C,eAClB+C,EAAQ9C,KAAK,MAAO4C,GAAU,GAC9BE,EAAQ7C,aAAe,cACvB6C,EAAQtE,iBAAiB,OAAQ,WAOhC,IANA,IAAIuE,EAAM,IAAIC,WAAWF,EAAQG,UAIjCC,EAAW,EAEFxS,EAAI,EAAGA,EAAIqS,EAAItF,OAAQ/M,IAI/B,GAHOyS,OAAOC,aAAcL,EAAIrS,IAGlB,IAAVqS,EAAIrS,IACU,KAAdqS,EAAIrS,EAAI,IACM,GAAdqS,EAAIrS,EAAI,IACM,GAAdqS,EAAIrS,EAAI,GAAY,CAEtB,IAAI2S,EAASN,EAAIrS,EAAI,IAAM,EAAmB,IAAbqS,EAAIrS,EAAI,GAIzCwS,GAAYG,EAAQ,EAAI,GAAMA,EAIjCR,EAAoB,GAAXK,KAEVJ,EAAQ7J,4CAQI,IAAAqK,EAAArO,KAYZ,GAVyB,GAArBA,KAAKuH,QAAQ1G,KAChBqE,SAASC,eAAe,eAAeQ,MAAM2I,UAAY,aAEzDpJ,SAASC,eAAe,eAAeQ,MAAM2I,UAAY,YAGtDtO,KAAKmN,aACRnN,KAAKgN,QAAUS,WAAW,kBAAMY,EAAKX,cAttBhB,KAytBlB1N,KAAKuH,QAAQgB,MAAO,CAEvBrD,SAASC,eAAe,qBAAqBQ,MAAMG,gBAAkB,cAErEZ,SAASC,eAAe,eAAeQ,MAAMU,QAAU,OACvDnB,SAASC,eAAe,eAAeQ,MAAMU,QAAU,OAEvD,IAMIkI,GALHC,EAAK,SACLC,EAAK,YACLC,EAAK,YAGa1O,KAAKuH,QAAQ9C,gBACX,IAAV8J,GACVrJ,SAASC,eAAe,gBAAgB6D,IAAM9J,EAAU,QAAUqP,EAAQ,OACzE,IAAIpF,MAASjK,EAAb,eAAmCc,KAAKuH,QAAQvL,KAAhD,IAAwDuS,EAAxD,QAAsEtF,OACvEjJ,KAAKiN,WAAa,KAElBjN,KAAKiN,WAAa,EAGnBjN,KAAKuH,QAAQgB,OAAQ,EACrBvI,KAAKuH,QAAQ+E,cAAe,EAG7B,GAAGtM,KAAKkN,WAAalN,KAAKiN,YAAcjN,KAAKuH,QAAQ+E,aAE1B,GAAtBtM,KAAKuH,QAAQ7C,OAEhB1E,KAAK8M,SAAS/D,QACd/I,KAAK+M,UAAY,EACjB/M,KAAK8M,SAAS9D,IAAM9J,EAAU,8BAC9Bc,KAAK8M,SAAS7D,OACd0F,EAAE,sBAAsBC,OAAQ,SAASC,UAAY,QACrB,GAAtB7O,KAAKuH,QAAQ7C,QAEvBQ,SAASC,eAAe,qBAAqBQ,MAAMG,gBAAkB,QACrE9F,KAAK8M,SAAS/D,QACd/I,KAAK+M,UAAY,EACjB/M,KAAK8M,SAAS9D,IAAM9J,EAAU,qCAC9Bc,KAAK8M,SAAS7D,OACd0F,EAAE,sBAAsBC,OAAO,YAI7B5O,KAAKuH,QAAQiF,aAAe,IAC9BtH,SAASC,eAAe,gBAAgB6D,IAAM,GAC9C2B,EAAiB3K,KAAKuH,QAAQlD,MAC9Ba,SAASC,eAAe,eAAe6D,IAAM9J,EAAU,cAAgByI,OAAO3H,KAAKuH,QAAQvL,MAAQ,IAAMgE,KAAKuH,QAAQG,QAAU,QAEjI1H,KAAKuH,QAAQ+E,cAAe,EAC5BtM,KAAKuH,QAAQgF,eAAgB,OACvB,GAAIvM,KAAKkN,WAAalN,KAAKiN,WAAajN,KAAKuH,QAAQiF,eAAiBxM,KAAKuH,QAAQ+E,aACzF,GAAItM,KAAKuH,QAAQgF,cAAe,CAC/BoC,EAAE,gBAAgBG,OAAQ,QAC1BH,EAAE,gBAAgBG,OAAO,QAAQD,UAAY,SACb,GAA7B7O,KAAKuH,QAAQiF,eACftH,SAASC,eAAe,gBAAgB6D,IAAM,GAC9C2B,EAAiB3K,KAAKuH,QAAQlD,OAE/Ba,SAASC,eAAe,eAAe6D,IAAM9J,EAAU,cAAgByI,OAAO3H,KAAKuH,QAAQvL,MAAQ,IAAMgE,KAAKuH,QAAQpD,SAAW,OACjIe,SAASC,eAAe,eAAeQ,MAAMoJ,SAAkE,GAAtD7J,SAASC,eAAe,eAAe6J,aAAsB,KACtH9J,SAASC,eAAe,eAAeQ,MAAMoJ,SAAkE,IAAtD7J,SAASC,eAAe,eAAe6J,aAAuB,KACvH9J,SAASC,eAAe,eAAesC,UAAY,MAAQO,EAAWhI,KAAKuH,QAAQK,WAAa,OAEhG,IASIqH,EAAa,YARhBC,EAAK,UACLV,EAAK,UACLC,EAAK,UACLC,EAAK,UACLS,EAAK,UACLC,EAAK,UACLC,EAAK,WAE+BrP,KAAKuH,QAAQ5C,QAAU,WAC5DO,SAASC,eAAe,qBAAqBQ,MAAQsJ,EACrDjP,KAAKuH,QAAQgF,eAAgB,EAEzBvM,KAAKqM,SAAWrM,KAAKuH,QAAQC,UAChCtC,SAASC,eAAe,eAAe6D,IAAM9J,EAAU,cAAgByI,OAAO3H,KAAKuH,QAAQvL,MAAQ,IAAMgE,KAAKuH,QAAQnD,OAAS,OAC/HpE,KAAKmN,YAAa,EAClBC,aAAapN,KAAKgN,eAGfhN,KAAKqM,SAAWrM,KAAKuH,QAAQC,UACwB,KAApDxH,KAAKuH,QAAQC,QAAQ8H,OAAOtP,KAAKqM,QAAQ7D,UAC5CxI,KAAK2M,aAAa3M,KAAK6M,oBAAoB5D,OAC3CjJ,KAAK6M,qBACL7M,KAAK6M,oBAAsB7M,KAAK2M,aAAanE,QAE9CxI,KAAKqM,QAAUrM,KAAKuH,QAAQC,QAAQ+H,UAAU,EAAGvP,KAAKqM,QAAQ7D,OAAS,GACvEtD,SAASC,eAAe,qBAAqBsC,UAAYzH,KAAKqM,QAC1DrM,KAAKqM,SAAWrM,KAAKuH,QAAQC,UAChCxH,KAAKkN,UAAY,EACjBlN,KAAKmN,YAAa,EAClBjI,SAASC,eAAe,eAAe6D,IAAM9J,EAAU,cAAgByI,OAAO3H,KAAKuH,QAAQvL,MAAQ,IAAMgE,KAAKuH,QAAQnD,OAAS,OAC/HgJ,aAAapN,KAAKgN,YAMjBhN,KAAK+M,WAAa/M,KAAKuH,QAAQc,SAAWrI,KAAKiN,YAAcjN,KAAKkN,YACtElN,KAAK8M,SAAS/D,QACd/I,KAAK+M,UAAY,EACS,KAAtB/M,KAAKuH,QAAQY,OAAsC,KAAtBnI,KAAKuH,QAAQY,QAC7CnI,KAAK8M,SAAS9D,IAAM9J,EAAU,kBAAoByI,OAAO3H,KAAKuH,QAAQY,OAAS,OAC/EnI,KAAK8M,SAAS7D,SAGhBjJ,KAAKkN,UAAYlN,KAAKkN,UAx0BA,YA40BlB5B,iFACQvE,GACZ,IAAIyI,GACHC,QAAS,6BACTC,MAAO,oCACPC,QAAS,YAENjT,KAEA+S,EAAU,KAmBd,OApBY1I,EAAKlI,MAAM,cAEjBC,QAAQ,SAAS8Q,GACtB,IAAIJ,EAAMG,QAAQrQ,KAAKsQ,IAEG,GAAfA,EAAKpH,OAET,GAAIgH,EAAME,MAAMpQ,KAAKsQ,GAAO,CAClC,IAAIC,EAAQD,EAAKC,MAAML,EAAME,OACzBD,EACH/S,EAAM+S,GAASI,EAAM,IAAMA,EAAM,GAEjCnT,EAAMmT,EAAM,IAAMA,EAAM,QAEnB,GAAIL,EAAMC,QAAQnQ,KAAKsQ,GAAO,CACpC,IAAIC,EAAQD,EAAKC,MAAML,EAAMC,SAC7B/S,EAAMmT,EAAM,OACZJ,EAAUI,EAAM,MAGXnT,WAQF,SAASe,EAAWqS,GACL,IAAjBA,EAAMC,UACTzJ,EAAO0J,QAAQ9K,SAASC,eAAe,sBAAsBzI,OAC7DwI,SAASC,eAAe,sBAAsBzI,MAAQ,IASjD,SAASgB,EAAQoS,GACvB,GAAqB,IAAjBA,EAAMC,QAAe,CACxB,IAAIE,EAAS3J,EAAOsE,KAChBsF,EAAQ5J,EAAO6J,UACfC,EAAW9J,EAAOzF,KAAO,EAAE,EAC3BwP,EAAUnL,SAASC,eAAe,aAAazI,MAC/C4H,EAAW,IACXE,EAAY,IACZU,SAASC,eAAe,WAAWmL,UACtChM,EAAW4L,EAAMlE,IACjBxH,EAAY0L,EAAMjE,UAEnB3F,EAAOiK,OAAOL,EAAM/L,SAAU8L,EAAOjU,KAAMkU,EAAM9L,OAAQc,SAASC,eAAe,mBAAmBzI,MAAOuT,EAAO5L,KAAMC,EAAU4L,EAAM3L,KAAMC,EAAW9E,EAAe0Q,EAAQ3Q,EAAgB4Q,IA0B3L,SAAS1S,EAAgBmS,GAC/B,IAAIU,EAAYtL,SAASC,eAAe,oBAAoBzI,MAC5D4J,EAAOmK,gBAAgBD,GAOjB,SAAS5S,IACf0J,EAAS7E,MAAMiK,OAASxH,SAASC,eAAe,kBAAkBzI,MAAQ,IAOpE,SAASmB,IACfyJ,EAASwF,SAASJ,OAASxH,SAASC,eAAe,kBAAkBzI,MAAQ,IAOvE,SAASoB,IACfwJ,EAASoJ,cAAcxL,SAASC,eAAe,kBAAkBzI,MAAQ,KAQnE,SAASqB,EAAgB+R,GAC/BxJ,EAAOqK,gBACPzL,SAASC,eAAe,qBAAqBQ,MAAMU,QAAU,QAC7DnB,SAASC,eAAe,cAAcsC,UAAY,GAQ5C,SAASzJ,EAAS4S,GAGxB,OAFAA,EAAMjQ,QAAU,GAChBiQ,EAAM5H,IAAM,yBACL,EAQD,SAAS/K,EAAU2S,GAGzB,OAFAA,EAAMjQ,QAAU,GAChBiQ,EAAM5H,IAAM,yBACL,EAoBR,SAAS2B,EAAiBkG,GACzB,IAAIC,EACAC,EAAWzJ,EAAS0J,WAGxB,OAFA9L,SAASC,eAAe,aAAaQ,MAAMU,QAAU,OACrDnB,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,OAChDwK,GACP,IAAK,MACJ3L,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,mBACzD7L,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,QACxDnB,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,kBACzDD,EAAY,UACZ,MACD,IAAK,MACJ5L,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,sBACzD7L,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,QACxDnB,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,sBACzDD,EAAY,cACZ,MACD,IAAK,MACJ5L,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,kBACzDD,EAAY,UACZ,MACD,IAAK,MACJ5L,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,qBACzDD,EAAY,cACZ,MACD,IAAK,MACJ5L,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,mBACzD7L,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,QACxDnB,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,cACzDD,EAAY,cACZ,MACD,IAAK,MACJ5L,SAASC,eAAe,gBAAgB6D,IAAM+H,EAAW,iBACzDD,EAAY,cAGe,GAAzBxJ,EAASC,QAAQa,OACpBlD,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,OACxDnB,SAASC,eAAe,gBAAgB6D,IAAM9J,EAAU,kBAAoB4R,EAAY,mBAOnF,SAAS5S,IACfoI,EAAOO,WACPP,EAAS,IAAIzG,EAAOb,MAEnBpC,EAAO,OACPsI,SAASC,eAAe,gBAAgBQ,MAAMU,QAAU,QAQnD,SAASlI,IACfmI,EAAOC,aASR,SAAS2C,EAAY+H,GAAqC,IAA9BjV,EAA8BkV,UAAA1I,OAAA,QAAA2I,IAAAD,UAAA,GAAAA,UAAA,GAAvB,GAAIE,EAAmBF,UAAA1I,OAAA,QAAA2I,IAAAD,UAAA,GAAAA,UAAA,GAAZ,IAAItR,KAC3CyR,EAAQnM,SAAS8E,cAAc,KAC/BsH,EAAYpM,SAAS8E,cAAc,QAOzC,GANAsH,EAAUC,GAAK,aACfD,EAAU5G,YAAYxF,SAASsM,eAAexV,IAC9CqV,EAAM3G,YAAY4G,GAClBD,EAAM3G,YAAYxF,SAASsM,eAAeP,IAGtCtR,EAAkB8R,eAAiBL,EAAKK,aAAc,CACzD,IAAMC,EAAYxM,SAAS8E,cAAc,QACzC0H,EAAUH,GAAK,aACfG,EAAUC,UAAYP,EAAKQ,wBAAmBT,GAC7CU,KAAM,UACNC,OAAQ,YAETT,EAAM3G,YAAYgH,GAGnB,IAAMK,EAAY7M,SAASC,eAAe,cAC1C4M,EAAUrH,YAAY2G,GAElBU,EAAUlJ,UAAYkJ,EAAUjJ,aAAe,MAClDiJ,EAAUlJ,UAAYkJ,EAAUjJ,cAGjCnJ,EAAoB,IAAIC,KAOlB,SAASxB,EAAS4T,GACpBA,EAAa,IAChB1L,EAAO2L,cAAcD,IAGrB9M,SAASC,eAAe,qBAAqBQ,MAAMU,QAAU,OAC7DnB,SAASC,eAAe,mBAAmBQ,MAAMU,QAAU,OAC3DnB,SAASC,eAAe,cAAcQ,MAAMU,QAAU,QASjD,SAAShI,EAAY6T,IACE,GAAzB5L,EAAOpF,gBACVgE,SAASC,eAAe,OAASmB,EAAOpF,eAAe8H,IAAM1C,EAAO6J,UAAUjE,YAE/E5F,EAAOpF,cAAgBgR,EACvBhN,SAASC,eAAe,OAAS+M,GAAKlJ,IAAM1C,EAAO6J,UAAUhE,UASvD,SAAS7N,EAAasQ,GACxBA,GAAUnP,GACbyF,SAASC,eAAe,iBAAmByJ,GAAQnG,UAAY,gBAC/DhJ,EAAiB,IAEjByF,SAASC,eAAe,iBAAmByJ,GAAQnG,UAAY,qBAC3DhJ,IACHyF,SAASC,eAAe,iBAAmB1F,GAAgBgJ,UAAY,iBAExEhJ,EAAiBmP,GAQZ,SAASrQ,IACX+H,EAAOzF,KACVqE,SAASC,eAAe,eAAesD,UAAY,gBAEnDvD,SAASC,eAAe,eAAesD,UAAY,qBAEpDnC,EAAOzF,MAAQyF,EAAOzF,KAShB,SAASrC,EAAY+P,GACvBA,GAAS7O,GACZwF,SAASC,eAAe,UAAYoJ,GAAO9F,UAAY,gBACvD/I,EAAgB,IAEhBwF,SAASC,eAAe,UAAYoJ,GAAO9F,UAAY,qBACnD/I,IACHwF,SAASC,eAAe,UAAYzF,GAAe+I,UAAY,iBAEhE/I,EAAgB6O,GAWlB,SAASvG,EAAWmK,GACnB,OAAOA,EACLrK,QAAQ,KAAM,SACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,UACdA,QAAQ,KAAM,UAOjB,SAAS7D,EAAW4D,GACnB,OAAOA,EACLC,QAAQ,KAAM,WACdA,QAAQ,KAAM,SACdA,QAAQ,KAAM,aACdA,QAAQ,MAAO,YAOlB,SAASI,EAAaL,GACrB,OAAOA,EACLC,QAAQ,WAAY,KACpBA,QAAQ,SAAU,KAClBA,QAAQ,aAAc,KACtBA,QAAQ,YAAa,KAOxB,SAAS5D,EAAW2D,GACnB,IAAIuK,EAAmBlN,SAASC,eAAe,mBAAmBzI,MAClE,GAAwB,WAApB0V,EAEH,OAAOvK,EAAQC,QAAQ,WAAY,SAASuK,GAC3C,MAAO,OAAS,MAAQA,EAAGC,aAAaC,SAAS,KAAKC,OAAO,KACxD,GAAwB,SAApBJ,EAA4B,CAItC,IAFA,IAAIK,EAAS,IAAIC,YAA2B,EAAf7K,EAAQW,QACjCmK,EAAS,IAAIC,YAAYH,GACpBhX,EAAE,EAAGoX,EAAOhL,EAAQW,OAAQ/M,EAAIoX,EAAQpX,IAChDkX,EAAOlX,GAAKoM,EAAQyK,WAAW7W,GAEhC,OAAOyS,OAAOyE,GAEd,OAAO9K,EAQT,SAASI,EAAWJ,GACnB,IAAIiL,EAAmB5N,SAASC,eAAe,mBAAmBzI,MAClE,MAAwB,WAApBoW,EAEUjL,EAAQC,QAAQ,oBAAqB,SAAU+H,EAAOkD,GAClE,OAAO7E,OAAOC,aAAaX,SAASuF,EAAO,OACd,SAApBD,EAEH5E,OAAOC,aAAa6E,MAAM,KAAM,IAAIJ,YAAY/K,EAAQhJ,MAAM,OAE9DgJ,EAzXToL,OAAOxV,WAAaA,EAqBpBwV,OAAOvV,QAAUA,EA2BjBuV,OAAOtV,gBAAkBA,EAQzBsV,OAAOrV,kBAAoBA,EAQ3BqV,OAAOpV,gBAAkBA,EAQzBoV,OAAOnV,iBAAmBA,EAW1BmV,OAAOlV,gBAAkBA,EAWzBkV,OAAOjV,SAAWA,EAWlBiV,OAAOhV,UAAYA,EAwEnBgV,OAAO/U,gBAAkBA,EAQzB+U,OAAO9U,YAAcA,EAkDrB8U,OAAO7U,SAAWA,EAalB6U,OAAO5U,YAAcA,EAmBrB4U,OAAO3U,aAAeA,EAatB2U,OAAO1U,WAAaA,EAmBpB0U,OAAOzU,YAAcA,OAuGiB,IAA3B0P,OAAO7Q,UAAU6V,OAExBhF,OAAO7Q,UAAU6V,KAAO,WAEpB,OAAOhF,OAAOlO,MAAM8H,QAAQ,aAAc,MAKlDoG,OAAO7Q,UAAUyH,SAAW,WAC3B,IAAcrJ,EAAV0X,EAAO,EACX,GAAoB,IAAhBnT,KAAKwI,OAAc,OAAO2K,EAC9B,IAAK1X,EAAI,EAAGA,EAAIuE,KAAKwI,OAAQ/M,IAE3B0X,GAAUA,GAAQ,GAAKA,EADfnT,KAAKsS,WAAW7W,GAExB0X,GAAQ,EAEV,OAAOA,GAQR,IAAI7M,EAAS,IAAIzG,EAAOb,GACpBsI,EAAW,IAAI8E,EAEnBuC,EAAEzJ,UAAUkO,MAAM,WACjB9M,EAAO+M","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\t\r\n\t/**\r\n\t * Create observer to detect BBCode elements\r\n\t * then manipulate them.\r\n\t */\r\n\tinitialObservBBCode() {\r\n\t\tvar target = document.getElementById(\"client_inner_chat\");\r\n\t\tvar observer = new MutationObserver(function(mutations) {\r\n\t\t mutations.forEach(function(mutation) {\r\n\t\t\tvar children = mutation.addedNodes;\r\n\t\t\tif (children !== null) {\r\n\t\t\t\tchildren.forEach( function(node) {\r\n\t\t\t\t\tif (node.tagName == \"C\") {\r\n\t\t\t\t\t\tnode.style.color = node.getAttribute(\"a\");\r\n\t\t\t\t\t} else if(node.tagName == \"M\"){\r\n\t\t\t\t\t\tif (node.hasAttribute('a')) {\r\n\t\t\t\t\t\t\tnode.style.backgroundColor = node.getAttribute(\"a\");\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnode.style.backgroundColor = \"yellow\";\r\n\t\t\t\t\t\t\tnode.style.color = \"black\";\r\n\t\t\t\t\t\t}\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\tvar config = {attributes: true,childList: true};\r\n\t\tobserver.observe(target,config);\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: decodeBBCode(escapeHtml(decodeChat(unescapeChat(args[5])))), // Escape HTML tag, Use BBCode Only!\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\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)\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, \"&amp;\")\r\n\t\t.replace(/</g, \"&lt;\")\r\n\t\t.replace(/>/g, \"&gt;\")\r\n\t\t.replace(/\"/g, \"&quot;\")\r\n\t\t.replace(/'/g, \"&#039;\");\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 * Decoding text on client side.\r\n * @param {string} estring the string to be decoded\r\n */\r\nfunction decodeBBCode(estring) {\r\n\treturn estring\r\n\t\t.replace(/\\\\n/g, \"<br>\") // Newline \\n\r\n\t\t.replace(/\\[(\\/?)b\\]/g, \"<$1b>\") // Bold [b][/b]\r\n\t\t.replace(/\\[(\\/?)i\\]/g, \"<$1i>\") // Italic [i][/i]\r\n\t\t.replace(/\\[(\\/?)del\\]/g, \"<$1del>\") // Deleted [del][/del]\r\n\t\t.replace(/\\[(\\/?)u\\]/g, \"<$1ins>\") // Underline [u][/u]\r\n\t\t.replace(/\\[(\\/?)sub\\]/g, \"<$1sub>\") // Subscript [sub][/sub]\r\n\t\t.replace(/\\[(\\/?)sup\\]/g, \"<$1sup>\") // Superscript [sup][/sup]\r\n\t\t.replace(/\\[m=([#a-zA-Z0-9]+)\\]/g, '<m a=\"$1\">') // Markup [m=#0ff]\r\n\t\t.replace(/\\[(\\/?)m\\]/g, '<$1m>') // [m][/m]\r\n\t\t.replace(/\\[c=?([#a-zA-Z0-9]+)\\]/g, '<c a=\"$1\">') // Color [c=red]\r\n\t\t.replace(/\\[\\/c\\]/g, '</c>'); // [/c]\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\r\n$(document).ready(function(){\r\n\tclient.initialObservBBCode();\r\n});\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","pickevidence","addevidence","editevidence","delevidence","cancelevidence","findEvidenceIcon","updateEvidenceIcon","toggleaffect","toggleflip","togglepresent","togglemenu","toggleshout","queryDict","location","search","substr","split","forEach","item","serverIP","ip","AO_HOST","asset","MUSIC_HOST","oldLoading","test","navigator","userAgent","selectedEffect","selectedMenu","selectedShout","lastICMessageTime","Date","Client","address","_this","this","_classCallCheck","serv","WebSocket","onopen","evt","onOpen","onclose","onClose","onmessage","onMessage","onerror","onError","flip","presentable","playerID","charID","chars","emotes","evidences","selectedEmote","selectedEvidence","checkUpdater","musicList","handlers","MS","args","handleMS","CT","handleCT","MC","handleMC","RMC","handleRMC","CI","handleCI","SC","handleSC","EI","handleEI","LE","handleLE","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","evidence","flash","color","desc","img","id","track","_this2","hashCode","setInterval","sendCheck","evidence_select","document","getElementById","add","Option","evidence_arr","length","target","MutationObserver","mutations","mutation","children","addedNodes","node","tagName","style","getAttribute","hasAttribute","backgroundColor","observe","attributes","childList","character","song","e","display","client","joinServer","console","error","reason","code","textContent","cleanup","msg","data","debug","header","handler","warn","close","clearInterval","viewport","chatmsg","content","innerHTML","preanim","escape","nameplate","estring","replace","decodeBBCode","escapeHtml","decodeChat","unescapeChat","sound","type","snddelay","isnew","className","resetICParams","say","oocLog","scrollTop","scrollHeight","pause","src","play","appendICLog","Audio","totime","offset","getTime","addEventListener","currentTime","parseFloat","toFixed","chargs","icon","arg","filename","evidence_box","hmusiclist","newentry","createElement","text","options","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","parseInt","setTimeout","updateText","callback","request","arr","Uint8Array","response","duration","String","fromCharCode","delay","_this3","transform","opacity","height","shout","1","2","3","$","effect","direction","backgroundImage","right","left","animate","marginLeft","marginRight","toggle","fontSize","offsetHeight","stylecolor","0","4","5","6","charAt","substring","regex","section","param","comment","line","match","event","keyCode","sendOOC","mychar","myemo","myEmote","myevi","myEvidence","myflip","mycolor","checked","sendIC","playtrack","sendMusicChange","setBlipVolume","sendLeaveRoom","image","position","standname","bgfolder","bgFolder","toadd","arguments","undefined","time","entry","nameField","createTextNode","getMinutes","timeStamp","innerText","toLocaleTimeString","hour","minute","clientLog","ccharacter","sendCharacter","emo","icon_id","selectedIndex","sendPE","sendEE","sendDE","evidence_filename","evidence_iconbox","menu","unsafe","selectedEncoding","ch","charCodeAt","toString","slice","buffer","ArrayBuffer","result","Uint16Array","strLen","selectedDecoding","group","apply","window","trim","hash","ready","initialObservBBCode","loadResources"],"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 selectedMenu = 1;\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\t\tthis.presentable = 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 = [];\t\t\r\n\t\tthis.evidences = [];\r\n\r\n\t\tthis.selectedEmote = -1;\r\n\t\tthis.selectedEvidence = 0;\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\"LE\": (args) => this.handleLE(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\t\r\n\t/**\r\n\t * Gets the player's currently selected evidence if presentable.\r\n\t */\r\n\tmyEvidence() {\r\n\t\treturn (this.presentable)? this.selectedEvidence : 0;\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, evidence, 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}#${evidence}#${flip}#${flash}#${color}#%`\r\n\t\t);\r\n\t}\r\n\t\r\n\t/**\r\n\t * Sends add evidence command.\r\n\t * @param {string} evidence name\r\n\t * @param {string} evidence description\r\n\t * @param {string} evidence image filename\r\n\t */\r\n\tsendPE(name, desc, img) {\r\n\t\tthis.serv.send(`PE#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`);\r\n\t}\r\n\t\r\n\t/**\r\n\t * Sends edit evidence command.\r\n\t * @param {string} evidence id\r\n\t * @param {string} evidence name\r\n\t * @param {string} evidence description\r\n\t * @param {string} evidence image filename\r\n\t */\r\n\tsendEE(id, name, desc, img) {\r\n\t\tthis.serv.send(`EE#${id}#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`);\r\n\t}\r\n\t\r\n\t/**\r\n\t * Sends delete evidence command.\r\n\t * @param {string} evidence id\r\n\t */\r\n\tsendDE(id, name, desc, img) {\r\n\t\tthis.serv.send(`DE#${id}#%`);\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\t\r\n\t/**\r\n\t * Load game resources.\r\n\t */\r\n\tloadResources() {\r\n\t\t// Load evidence array to select\r\n\t\tvar evidence_select = document.getElementById(\"evi_select\");\r\n\t\tevidence_select.add(new Option(\"Custom\", 0));\r\n\t\tfor(let i = 1; i <= evidence_arr.length; i++) {\r\n\t\t evidence_select.add(new Option(evidence_arr[i - 1]));\r\n\t\t}\t\t\r\n\t\t// TODO: Cache some resources\r\n\t\t\r\n\t}\r\n\t\r\n\t/**\r\n\t * Create observer to detect BBCode elements\r\n\t * then manipulate them.\r\n\t */\r\n\tinitialObservBBCode() {\r\n\t\tvar target = document.getElementById(\"client_inner_chat\");\r\n\t\tvar observer = new MutationObserver(function(mutations) {\r\n\t\t mutations.forEach(function(mutation) {\r\n\t\t\tvar children = mutation.addedNodes;\r\n\t\t\tif (children !== null) {\r\n\t\t\t\tchildren.forEach( function(node) {\r\n\t\t\t\t\tif (node.tagName == \"C\") {\r\n\t\t\t\t\t\tnode.style.color = node.getAttribute(\"a\");\r\n\t\t\t\t\t} else if(node.tagName == \"M\"){\r\n\t\t\t\t\t\tif (node.hasAttribute('a')) {\r\n\t\t\t\t\t\t\tnode.style.backgroundColor = node.getAttribute(\"a\");\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnode.style.backgroundColor = \"yellow\";\r\n\t\t\t\t\t\t\tnode.style.color = \"black\";\r\n\t\t\t\t\t\t}\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\tvar config = {attributes: true,childList: true};\r\n\t\tobserver.observe(target,config);\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: decodeBBCode(escapeHtml(decodeChat(unescapeChat(args[5])))), // Escape HTML tag, Use BBCode Only!\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\t\r\n\t/**\r\n\t * Handles incoming evidence list, all evidences at once\r\n\t * item per packet.\r\n\t * \r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleLE(args) {\r\n\t\tthis.evidences = [];\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tvar arg = args[i].split(\"&\");\r\n\t\t\tthis.evidences[i - 1] = {\r\n\t\t\t\t\"name\": escapeHtml(decodeChat(unescapeChat(arg[0]))),\r\n\t\t\t\t\"desc\": escapeHtml(decodeChat(unescapeChat(arg[1]))),\r\n\t\t\t\t\"filename\": escape(arg[2]),\r\n\t\t\t\t\"icon\": AO_HOST + \"evidence/\" + escape(arg[2])\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tvar evidence_box = document.getElementById(\"evidences\");\r\n\t\tevidence_box.innerHTML = \"\";\r\n\t\tfor(let i = 1; i <= this.evidences.length; i++){\r\n\t\t\tevidence_box.innerHTML += '<img src=\"' + this.evidences[i - 1].icon + \r\n\t\t\t\t'\" id=\"evi_' + i +'\" alt=\"' + this.evidences[i - 1].name +\r\n\t\t\t\t'\" class=\"client_button\" ' +\r\n\t\t\t\t'onclick=\"pickevidence('+ i +')\">';\t\t\t\t\t\t\t\t\r\n\t\t}\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}\t\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\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)\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 and evidence 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\tdocument.getElementById(\"client_evi\").style.opacity = \"0\";\r\n\t\t\tdocument.getElementById(\"client_evi\").style.height = \"0%\";\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 = \"misc/placeholder.gif\";\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\tif(this.chatmsg.evidence > 0){\r\n\t\t\t\t\t// Prepare evidence\r\n\t\t\t\t\tdocument.getElementById(\"client_evi\").style.backgroundImage = \"url('\"+ client.evidences[this.chatmsg.evidence - 1].icon +\"')\";\r\n\t\t\t\t\r\n\t\t\t\t\tif (this.chatmsg.side == 'def'){\r\n\t\t\t\t\t\t// Only def show evidence on right\r\n\t\t\t\t\t\tdocument.getElementById(\"client_evi\").style.right = \"1.5em\";\r\n\t\t\t\t\t\tdocument.getElementById(\"client_evi\").style.left = \"initial\";\r\n\t\t\t\t\t\t$( \"#client_evi\" ).animate({\r\n\t\t\t\t\t\t\theight: \"30%\",\r\n\t\t\t\t\t\t\topacity: 1,\r\n\t\t\t\t\t\t\tmarginLeft: \"10.6in\"\r\n\t\t\t\t\t\t}, 250 );\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tdocument.getElementById(\"client_evi\").style.right = \"initial\";\r\n\t\t\t\t\t\tdocument.getElementById(\"client_evi\").style.left = \"1.5em\";\r\n\t\t\t\t\t\t$( \"#client_evi\" ).animate({\r\n\t\t\t\t\t\t\theight: \"30%\",\r\n\t\t\t\t\t\t\topacity: 1,\r\n\t\t\t\t\t\t\tmarginRight: \"10.6in\"\r\n\t\t\t\t\t\t}, 250 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\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 = \"misc/placeholder.gif\";\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 myevi = client.myEvidence();\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, myevi, 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 evidence for in-character chat.\r\n * @param {string} evidence the evidence to be presented\r\n */\r\nexport function pickevidence(evidence) {\r\n\tif (client.selectedEvidence != evidence) {\r\n\t\t//Update selected evidence\t\t\r\n\t\tif(client.selectedEvidence > 0){\r\n\t\t\tdocument.getElementById(\"evi_\" + client.selectedEvidence).className = \"client_button\";\r\n\t\t}\r\n\t\tdocument.getElementById(\"evi_\" + evidence).className = \"client_button dark\";\r\n\t\tclient.selectedEvidence = evidence;\r\n\t\t\r\n\t\t// Show evidence on information window\r\n\t\tdocument.getElementById(\"evi_name\").value = client.evidences[evidence - 1].name;\r\n\t\tdocument.getElementById(\"evi_desc\").value = client.evidences[evidence - 1].desc;\r\n\r\n\t\t//Update Icon\r\n\t\tlet icon_id = findEvidenceIcon(evidence);\r\n\t\tdocument.getElementById(\"evi_select\").selectedIndex = icon_id;\r\n\t\tif (icon_id == 0){\t\t\t\r\n\t\t\tdocument.getElementById(\"evi_filename\").value = client.evidences[evidence - 1].filename;\r\n\t\t}\r\n\t\tupdateEvidenceIcon();\r\n\t\t\r\n\t\t// Update button\r\n\t\tdocument.getElementById(\"evi_add\").className = \"client_button hover_button inactive\";\r\n\t\tdocument.getElementById(\"evi_edit\").className = \"client_button hover_button\";\r\n\t\tdocument.getElementById(\"evi_cancel\").className = \"client_button hover_button\";\r\n\t\tdocument.getElementById(\"evi_del\").className = \"client_button hover_button\";\r\n\t} else {\r\n\t\tcancelevidence();\r\n\t}\r\n}\r\nwindow.pickevidence = pickevidence;\r\n\r\n/**\r\n * Add evidence.\r\n */\r\nexport function addevidence() {\r\n\tlet evidence_select = document.getElementById('evi_select');\r\n\tclient.sendPE( document.getElementById('evi_name').value,\r\n\t\tdocument.getElementById('evi_desc').value,\r\n\t\t(evidence_select.selectedIndex == 0)? \r\n\t\t\tdocument.getElementById('evi_filename').value : \r\n\t\t\tevidence_select.options[evidence_select.selectedIndex].text \r\n\t\t);\r\n\tcancelevidence();\r\n}\r\nwindow.addevidence = addevidence;\r\n\r\n/**\r\n * Edit selected evidence.\r\n */\r\nexport function editevidence() {\r\n\tlet evidence_select = document.getElementById('evi_select');\r\n\tlet id = parseInt(client.selectedEvidence) - 1;\r\n\tclient.sendEE( id, \r\n\t\tdocument.getElementById('evi_name').value,\r\n\t\tdocument.getElementById('evi_desc').value,\r\n\t\t(evidence_select.selectedIndex == 0)? \r\n\t\t\tdocument.getElementById('evi_filename').value : \r\n\t\t\tevidence_select.options[evidence_select.selectedIndex].text \r\n\t\t);\r\n\tcancelevidence();\r\n}\r\nwindow.editevidence = editevidence;\r\n\r\n/**\r\n * Delete selected evidence.\r\n */\r\nexport function delevidence() {\r\n\tlet id = parseInt(client.selectedEvidence) - 1;\r\n\tclient.sendDE(id);\r\n\tcancelevidence();\r\n}\r\nwindow.delevidence = delevidence;\r\n\r\n/**\r\n * Cancel evidence selection.\r\n */\r\nexport function cancelevidence() {\r\n\t//Clear evidence data\r\n\tif(client.selectedEvidence > 0){\r\n\t\tdocument.getElementById(\"evi_\" + client.selectedEvidence).className = \"client_button\";\r\n\t}\r\n\tclient.selectedEvidence = 0;\r\n\t\r\n\t// Clear evidence on information window\r\n\tdocument.getElementById(\"evi_select\").selectedIndex = 0;\r\n\tupdateEvidenceIcon(); // Update icon widget\r\n\tdocument.getElementById(\"evi_filename\").value = \"\";\r\n\tdocument.getElementById(\"evi_name\").value = \"\";\r\n\tdocument.getElementById(\"evi_desc\").value = \"\";\r\n\tdocument.getElementById(\"evi_icon\").style.backgroundImage = \"url('misc/empty.png')\"; //Clear icon\r\n\t\r\n\t// Update button\r\n\tdocument.getElementById(\"evi_add\").className = \"client_button hover_button\";\r\n\tdocument.getElementById(\"evi_edit\").className = \"client_button hover_button inactive\";\r\n\tdocument.getElementById(\"evi_cancel\").className = \"client_button hover_button inactive\";\r\n\tdocument.getElementById(\"evi_del\").className = \"client_button hover_button inactive\";\r\n}\r\nwindow.cancelevidence = cancelevidence;\r\n\r\n/**\r\n * Find evidence icon in select box via id.\r\n * @param {integer} id the id of evidence\r\n */\r\nexport function findEvidenceIcon(id) {\r\n\t\t//Find if icon alraedy existed in select box\r\n\t\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\t\tfor (let i = 1; i < evidence_select.length; ++i){\r\n\t\t\tif (evidence_select.options[i].value == client.evidences[id - 1].filename){\r\n\t\t\t return i;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn 0;\r\n}\r\nwindow.findEvidenceIcon = findEvidenceIcon;\r\n\r\n/**\r\n * Update evidence icon.\r\n */\r\nexport function updateEvidenceIcon() {\r\n\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\tlet evidence_filename = document.getElementById(\"evi_filename\");\r\n\tlet evidence_iconbox = document.getElementById(\"evi_icon\");\r\n\t\r\n\tif (evidence_select.selectedIndex == 0) {\r\n\t\tevidence_filename.style.display = \"initial\";\r\n\t\tevidence_iconbox.style.backgroundImage = \"url('\" + AO_HOST + 'evidence/' + evidence_filename.value + \"')\";\r\n\t} else {\r\n\t\tevidence_filename.value = \"\";\r\n\t\tevidence_filename.style.display = \"none\";\r\n\t\tevidence_iconbox.style.backgroundImage = \"url('\" + AO_HOST + 'evidence/' + evidence_select.value + \"')\" ;\r\n\t}\r\n}\r\nwindow.updateEvidenceIcon = updateEvidenceIcon;\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 * Toggle presentable for presenting evidence in-character chat.\r\n */\r\nexport function togglepresent() {\r\n\tif (client.presentable) {\r\n\t\tdocument.getElementById(\"button_present\").className = \"client_button\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_present\").className = \"client_button dark\";\r\n\t}\r\n\tclient.presentable = !client.presentable;\r\n}\r\nwindow.togglepresent = togglepresent;\r\n\r\n/**\r\n * Highlights and selects a menu.\r\n * @param {string} menu the menu to be selected\r\n */\r\nexport function togglemenu(menu) {\r\n\tif (menu != selectedMenu) {\r\n\t\tdocument.getElementById(\"menu_\" + menu).className = \"menu_icon active\";\r\n\t\tdocument.getElementById(\"content_\" + menu).className = \"menu_content active\";\r\n\t\tdocument.getElementById(\"menu_\" + selectedMenu).className = \"menu_icon\";\r\n\t\tdocument.getElementById(\"content_\" + selectedMenu).className = \"menu_content\";\r\n\t\tselectedMenu = menu;\r\n\t}\r\n}\r\nwindow.togglemenu = togglemenu;\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, \"&amp;\")\r\n\t\t.replace(/</g, \"&lt;\")\r\n\t\t.replace(/>/g, \"&gt;\")\r\n\t\t.replace(/\"/g, \"&quot;\")\r\n\t\t.replace(/'/g, \"&#039;\");\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 * Decoding text on client side.\r\n * @param {string} estring the string to be decoded\r\n */\r\nfunction decodeBBCode(estring) {\r\n\treturn estring\r\n\t\t.replace(/\\\\n/g, \"<br>\") // Newline \\n\r\n\t\t.replace(/\\[(\\/?)b\\]/g, \"<$1b>\") // Bold [b][/b]\r\n\t\t.replace(/\\[(\\/?)i\\]/g, \"<$1i>\") // Italic [i][/i]\r\n\t\t.replace(/\\[(\\/?)del\\]/g, \"<$1del>\") // Deleted [del][/del]\r\n\t\t.replace(/\\[(\\/?)u\\]/g, \"<$1ins>\") // Underline [u][/u]\r\n\t\t.replace(/\\[(\\/?)sub\\]/g, \"<$1sub>\") // Subscript [sub][/sub]\r\n\t\t.replace(/\\[(\\/?)sup\\]/g, \"<$1sup>\") // Superscript [sup][/sup]\r\n\t\t.replace(/\\[m=([#a-zA-Z0-9]+)\\]/g, '<m a=\"$1\">') // Markup [m=#0ff]\r\n\t\t.replace(/\\[(\\/?)m\\]/g, '<$1m>') // [m][/m]\r\n\t\t.replace(/\\[c=?([#a-zA-Z0-9]+)\\]/g, '<c a=\"$1\">') // Color [c=red]\r\n\t\t.replace(/\\[\\/c\\]/g, '</c>'); // [/c]\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\r\n$(document).ready(function(){\r\n\tclient.initialObservBBCode();\r\n\tclient.loadResources(); \r\n});\r\n"],"sourceRoot":""} \ No newline at end of file