From 18629bfa646e4b0596a3c1ae9c6a3e3ba58347b9 Mon Sep 17 00:00:00 2001 From: Qube Date: Wed, 18 Jul 2018 21:40:26 +0700 Subject: Add pre-animation, flash, shake, flip, and text color + Fix shout order according to AO2 specification --- webAO/client.js | 177 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 156 insertions(+), 21 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 84bd9bd..76ced68 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -26,6 +26,7 @@ if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phon oldLoading = true; } +let selectedEffect = 0; let selectedShout = 0; let lastICMessageTime = new Date(0); @@ -37,6 +38,8 @@ class Client { this.serv.onclose = (evt) => this.onClose(evt); this.serv.onmessage = (evt) => this.onMessage(evt); this.serv.onerror = (evt) => this.onError(evt); + + this.flip = false; this.playerID = 1; this.charID = -1; @@ -111,11 +114,11 @@ class Client { * @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect * @param {string} objection the number of the shout to play */ - sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection) { + sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, flip, flash, color) { this.serv.send( `MS#chat#${speaking}#${name}#${silent}` + `#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` + - `#${this.charID}#${ssfxdelay}#${selectedShout}#0#0#0#0#%` + `#${this.charID}#${ssfxdelay}#${selectedShout}#0#${flip}#${flash}#${color}#%` ); } @@ -243,7 +246,7 @@ class Client { if (args[4] != viewport.chatmsg.content) { document.getElementById("client_inner_chat").innerHTML = ""; let chatmsg = { - pre: escape(args[2]), + // pre: escape(args[2]), character: -1, // Will do a linear search preanim: escape(args[2]), // XXX: why again? nameplate: args[3], // TODO: parse INI to get this info @@ -258,7 +261,7 @@ class Client { snddelay: args[10], objection: args[11], evidence: args[12], - // flip: args[13], + flip: args[13], flash: args[14], color: args[15], isnew: true, @@ -569,10 +572,12 @@ class Viewport { "content": "", "objection": "0", "sound": "", + "startpreanim": false, "startspeaking": false, "side": null, "color": "0", - "snddelay": 0 + "snddelay": 0, + "preanimdelay": 0 }; this.blip = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav'); this.blip.volume = 0.5; @@ -641,7 +646,61 @@ class Viewport { this.textTimer = 0; this._animating = true; clearTimeout(this.updater); - this.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL); + //If preanim existed then determine the length + if (chatmsg.preanim != "-") { + chatmsg.preanimdelay = this.getAnimLength(AO_HOST + 'characters/' + escape(chatmsg.name) + '/' + chatmsg.preanim + '.gif',this.initUpdater); + } else { + this.initUpdater(0) + } + } + + /** + * Intialize updater + * @param {int} animdelay the length of pre-animation + */ + initUpdater(animdelay){ + console.log(animdelay); + viewport.chatmsg.preanimdelay = parseInt(animdelay); + viewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL); + } + + /** + * Gets animation length. + * @param {string} filename the animation file name + * @param {function} callback the callback function + */ + getAnimLength(filename,callback) { + //Source (Thanks to Ryman): https://codepen.io/Ryman/pen/wzioA + var request = new XMLHttpRequest(); + request.open('GET', filename, true); + request.responseType = 'arraybuffer'; + request.addEventListener('load', function () { + var arr = new Uint8Array(request.response), + // Thanks to http://justinsomnia.org/2006/10/gif-animation-duration-calculation/ + // And http://www.w3.org/Graphics/GIF/spec-gif89a.txt + bin = '', + duration = 0; + + for (var i = 0; i < arr.length; i++) { + bin += String.fromCharCode( arr[i] ) + + // Find a Graphic Control Extension hex(21F904__ ____ __00) + if (arr[i] == 0x21 + && arr[i + 1] == 0xF9 + && arr[i + 2] == 0x04 + && arr[i + 7] == 0x00) { + // Swap 5th and 6th bytes to get the delay per frame + let delay = (arr[i + 5] << 8) | (arr[i + 4] & 0xFF) + + // Should be aware browsers have a minimum frame delay + // e.g. 6ms for IE, 2ms modern browsers (50fps) + duration += delay < 2 ? 10 : (delay+2) + } + } + // Return animation length + callback(duration * 10); + }); + request.send(); } /** @@ -650,41 +709,78 @@ class Viewport { * XXX: This relies on a global variable `this.chatmsg`! */ updateText() { - if (this.chatmsg.content.trim() == "") { - document.getElementById("client_name").style.display = "none"; - document.getElementById("client_chat").style.display = "none"; + // Flip the character + if (this.chatmsg.flip == 1){ + document.getElementById("client_char").style.transform = "scaleX(-1)"; } else { - document.getElementById("client_name").style.display = "block"; - document.getElementById("client_chat").style.display = "block"; + document.getElementById("client_char").style.transform = "scaleX(1)"; } - + if (this._animating) { this.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL); } if (this.chatmsg.isnew) { + // Reset screen background + document.getElementById("client_background").style.backgroundColor = "transparent"; + //Hide message window + document.getElementById("client_name").style.display = "none"; + document.getElementById("client_chat").style.display = "none"; + const shouts = { "1": "holdit", - "2": "takethat", - "3": "objection" + "2": "objection", + "3": "takethat" }; let shout = shouts[this.chatmsg.objection]; if (typeof shout !== "undefined") { - document.getElementById("client_char").src = AO_HOST + "misc/" + shout + ".gif"; + document.getElementById("client_shout").src = AO_HOST + "misc/" + shout + ".gif"; (new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play(); - this.shoutTimer = 800; + this.shoutTimer = 850; } else { this.shoutTimer = 0; } this.chatmsg.isnew = false; - this.chatmsg.startspeaking = true; + this.chatmsg.startpreanim = true; } - if (this.textTimer >= this.shoutTimer) { - if (this.chatmsg.startspeaking) { + if(this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) { + // Effect stuff + if (this.chatmsg.flash == 2){ + //Shake screen + this.sfxaudio.pause(); + this.sfxplayed = 1; + this.sfxaudio.src = AO_HOST + "sounds/general/sfx-stab.wav"; + this.sfxaudio.play(); + $('#client_gamewindow').effect( "shake",{"direction":"up"}); + } else if (this.chatmsg.flash == 1) { + //Flash screen + document.getElementById("client_background").style.backgroundColor = "white"; + this.sfxaudio.pause(); + this.sfxplayed = 1; + this.sfxaudio.src = AO_HOST + "sounds/general/sfx-realization.wav"; + this.sfxaudio.play(); + $('#client_gamewindow').effect("pulsate"); + } + + //Pre-animation stuff + if(this.chatmsg.preanimdelay > 0){ + document.getElementById("client_shout").src = ""; changeBackground(this.chatmsg.side); + document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.preanim + ".gif"; + } + this.chatmsg.startpreanim = false; + this.chatmsg.startspeaking = true; + } else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) { + if (this.chatmsg.startspeaking) { + $("#client_name").toggle( "fade" ); + $("#client_chat").toggle("drop",{"direction":"down"}); + if(this.chatmsg.preanimdelay == 0){ + document.getElementById("client_shout").src = ""; + changeBackground(this.chatmsg.side); + } document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.speaking + ".gif"; document.getElementById("client_name").style.fontSize = (document.getElementById("client_name").offsetHeight * 0.7) + "px"; document.getElementById("client_chat").style.fontSize = (document.getElementById("client_chat").offsetHeight * 0.25) + "px"; @@ -726,6 +822,7 @@ class Viewport { } } } + if (!this.sfxplayed && this.chatmsg.snddelay + this.shoutTimer >= this.textTimer) { this.sfxaudio.pause(); this.sfxplayed = 1; @@ -790,13 +887,15 @@ export function onEnter(event) { if (event.keyCode == 13) { let mychar = client.me(); let myemo = client.myEmote(); + let myflip = ((client.flip)? 1:0); + let mycolor = document.getElementById("textcolor").value; let ssfxname = "0"; let ssfxdelay = "0"; if (document.getElementById("sendsfx").checked) { ssfxname = myemo.sfx; ssfxdelay = myemo.sfxdelay; } - client.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById("client_inputbox").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout); + client.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById("client_inputbox").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout, myflip, selectedEffect, mycolor); } } window.onEnter = onEnter; @@ -808,10 +907,14 @@ window.onEnter = onEnter; */ function resetICParams() { document.getElementById("client_inputbox").value = ""; + if (selectedEffect) { + document.getElementById("button_effect_" + selectedEffect).className = "client_button"; + selectedEffect = 0; + } if (selectedShout) { document.getElementById("button_" + selectedShout).className = "client_button"; selectedShout = 0; - } + } } /** @@ -1024,6 +1127,38 @@ export function pickemotion(emo) { } window.pickemotion = pickemotion; +/** + * Highlights and selects an effect for in-character chat. + * If the same effect button is selected, then the effect is canceled. + * @param {string} effect the new effect to be selected + */ +export function toggleaffect(effect) { + if (effect == selectedEffect) { + document.getElementById("button_effect_" + effect).className = "client_button"; + selectedEffect = 0; + } else { + document.getElementById("button_effect_" + effect).className = "client_button dark"; + if (selectedEffect) { + document.getElementById("button_effect_" + selectedEffect).className = "client_button"; + } + selectedEffect = effect; + } +} +window.toggleaffect = toggleaffect; + +/** + * Toggle flip for in-character chat. + */ +export function toggleflip() { + if (client.flip) { + document.getElementById("button_flip").className = "client_button"; + } else { + document.getElementById("button_flip").className = "client_button dark"; + } + client.flip = !client.flip; +} +window.toggleflip = toggleflip; + /** * Highlights and selects a shout for in-character chat. * If the same shout button is selected, then the shout is canceled. -- cgit From 93c2650aac8a12797701d8ca6002db560d7b4529 Mon Sep 17 00:00:00 2001 From: Qube Date: Wed, 18 Jul 2018 23:12:29 +0700 Subject: Add client side encoding-decoding option (Unicode Escape and UTF-16 Array) --- webAO/client.js | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 76ced68..14b9a51 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -99,7 +99,7 @@ class Client { * @param {string} message the message to send */ sendOOC(message) { - this.serv.send(`CT#web${this.playerID}#${escapeChat(message)}#%`); + this.serv.send(`CT#web${this.playerID}#${escapeChat(encodeChat(message))}#%`); } /** @@ -117,7 +117,7 @@ class Client { sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, flip, flash, color) { this.serv.send( `MS#chat#${speaking}#${name}#${silent}` + - `#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` + + `#${escapeChat(encodeChat(message))}#${side}#${ssfxname}#${zoom}` + `#${this.charID}#${ssfxdelay}#${selectedShout}#0#${flip}#${flash}#${color}#%` ); } @@ -253,7 +253,7 @@ class Client { name: args[3], speaking: "(b)" + escape(args[4]), silent: "(a)" + escape(args[4]), - content: args[5], + content: decodeChat(unescapeChat(args[5])), side: args[6], sound: escape(args[7]), type: args[8], @@ -289,7 +289,7 @@ class Client { */ handleCT(args) { const oocLog = document.getElementById("client_ooclog"); - oocLog.innerHTML += `${args[1]}: ${args[2]}\r\n`; + oocLog.innerHTML += `${decodeChat(unescapeChat(args[1]))}: ${decodeChat(unescapeChat(args[2]))}\r\n`; if (oocLog.scrollTop > oocLog.scrollHeight - 60) { oocLog.scrollTop = oocLog.scrollHeight; } @@ -1205,6 +1205,60 @@ function escapeChat(estring) { .replace(/\$/g, ""); } +/** + * Unescapes a string to AO1 escape codes. + * @param {string} estring the string to be unescaped + */ +function unescapeChat(estring) { + return estring + .replace(//g, "#") + .replace(//g, "&") + .replace(//g, "%") + .replace(/\/g, "$"); +} + +/** + * Encoding text on client side. + * @param {string} estring the string to be encoded + */ +function encodeChat(estring) { + let selectedEncoding = document.getElementById("client_encoding").value; + if (selectedEncoding == "unicode") { + //Source: https://gist.github.com/mathiasbynens/1243213 + return estring.replace(/[^\0-~]/g, function(ch) { + return "\\u" + ("000" + ch.charCodeAt().toString(16)).slice(-4); }); + } else if (selectedEncoding == "utf16"){ + //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String + var buffer = new ArrayBuffer(estring.length*2); + var result = new Uint16Array(buffer); + for (var i=0, strLen=estring.length; i < strLen; i++) { + result[i] = estring.charCodeAt(i); + } + return String(result); + } else { + return estring; + } +} + +/** + * Decoding text on client side. + * @param {string} estring the string to be decoded + */ +function decodeChat(estring) { + let selectedDecoding = document.getElementById("client_decoding").value; + if (selectedDecoding == "unicode") { + //Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode + return estring.replace(/\\u([\d\w]{1,})/gi, function (match, group) { + return String.fromCharCode(parseInt(group, 16)); } ); + } else if (selectedDecoding == "utf16"){ + //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String + return String.fromCharCode.apply(null, new Uint16Array(estring.split(","))); + } else { + return estring; + } +} + + // TODO: Possibly safe to remove, since we are using a transpiler. if (typeof(String.prototype.trim) === "undefined") { -- cgit From 119a6b4f03fcd6defc68b504d9b529a9f0c562d0 Mon Sep 17 00:00:00 2001 From: Qube Date: Thu, 19 Jul 2018 00:27:30 +0700 Subject: Add BBCode --- webAO/client.js | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 14b9a51..9f87547 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -149,6 +149,35 @@ class Client { this.serv.send("ID#webAO#2.4.5#%"); this.checkUpdater = setInterval(() => this.sendCheck(), 5000); } + + /** + * Create observer to detect BBCode elements + * then manipulate them. + */ + initialObservBBCode() { + var target = document.getElementById("client_inner_chat"); + var observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + var children = mutation.addedNodes; + if (children !== null) { + children.forEach( function(node) { + if (node.tagName == "C") { + node.style.color = node.getAttribute("a"); + } else if(node.tagName == "M"){ + if (node.hasAttribute('a')) { + node.style.backgroundColor = node.getAttribute("a"); + } else { + node.style.backgroundColor = "yellow"; + node.style.color = "black"; + } + } + }); + } + }); + }); + var config = {attributes: true,childList: true}; + observer.observe(target,config); + } /** * Requests to play as a specified character. @@ -253,7 +282,7 @@ class Client { name: args[3], speaking: "(b)" + escape(args[4]), silent: "(a)" + escape(args[4]), - content: decodeChat(unescapeChat(args[5])), + content: decodeBBCode(escapeHtml(decodeChat(unescapeChat(args[5])))), // Escape HTML tag, Use BBCode Only! side: args[6], sound: escape(args[7]), type: args[8], @@ -659,7 +688,6 @@ class Viewport { * @param {int} animdelay the length of pre-animation */ initUpdater(animdelay){ - console.log(animdelay); viewport.chatmsg.preanimdelay = parseInt(animdelay); viewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL); } @@ -1258,6 +1286,25 @@ function decodeChat(estring) { } } +/** + * Decoding text on client side. + * @param {string} estring the string to be decoded + */ +function decodeBBCode(estring) { + return estring + .replace(/\\n/g, "
") // Newline \n + .replace(/\[(\/?)b\]/g, "<$1b>") // Bold [b][/b] + .replace(/\[(\/?)i\]/g, "<$1i>") // Italic [i][/i] + .replace(/\[(\/?)del\]/g, "<$1del>") // Deleted [del][/del] + .replace(/\[(\/?)u\]/g, "<$1ins>") // Underline [u][/u] + .replace(/\[(\/?)sub\]/g, "<$1sub>") // Subscript [sub][/sub] + .replace(/\[(\/?)sup\]/g, "<$1sup>") // Superscript [sup][/sup] + .replace(/\[m=([#a-zA-Z0-9]+)\]/g, '') // Markup [m=#0ff] + .replace(/\[(\/?)m\]/g, '<$1m>') // [m][/m] + .replace(/\[c=?([#a-zA-Z0-9]+)\]/g, '') // Color [c=red] + .replace(/\[\/c\]/g, ''); // [/c] +} + // TODO: Possibly safe to remove, since we are using a transpiler. if (typeof(String.prototype.trim) === "undefined") @@ -1287,3 +1334,7 @@ String.prototype.hashCode = function() { let client = new Client(serverIP); let viewport = new Viewport(); + +$(document).ready(function(){ + client.initialObservBBCode(); +}); -- cgit From 5b12a4d6572bca5ae73474f84362cc3507ae3f3c Mon Sep 17 00:00:00 2001 From: Qube Date: Thu, 19 Jul 2018 09:55:00 +0700 Subject: Fix escape decode and adjust pre-animation. --- webAO/client.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 9f87547..2d7964a 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -722,7 +722,7 @@ class Viewport { // Should be aware browsers have a minimum frame delay // e.g. 6ms for IE, 2ms modern browsers (50fps) - duration += delay < 2 ? 10 : (delay+2) + duration += delay < 2 ? 10 : (delay) } } // Return animation length @@ -1242,7 +1242,7 @@ function unescapeChat(estring) { .replace(//g, "#") .replace(//g, "&") .replace(//g, "%") - .replace(/\/g, "$"); + .replace(//g, "$"); } /** -- cgit From adf3cacdf2c6426a7eb7ea5fc500082992f357aa Mon Sep 17 00:00:00 2001 From: Qube Date: Thu, 19 Jul 2018 20:12:57 +0700 Subject: Add evidence and mainmenu --- webAO/client.js | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 287 insertions(+), 10 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 2d7964a..fd8289a 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -27,6 +27,7 @@ if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phon } let selectedEffect = 0; +let selectedMenu = 1; let selectedShout = 0; let lastICMessageTime = new Date(0); @@ -40,14 +41,17 @@ class Client { this.serv.onerror = (evt) => this.onError(evt); this.flip = false; + this.presentable = false; this.playerID = 1; this.charID = -1; this.chars = []; - this.emotes = []; + this.emotes = []; + this.evidences = []; this.selectedEmote = -1; + this.selectedEvidence = 0; this.checkUpdater = null; @@ -62,6 +66,7 @@ class Client { "CI": (args) => this.handleCI(args), "SC": (args) => this.handleSC(args), "EI": (args) => this.handleEI(args), + "LE": (args) => this.handleLE(args), "EM": (args) => this.handleEM(args), "SM": (args) => this.handleSM(args), "music": (args) => this.handlemusic(args), @@ -93,6 +98,13 @@ class Client { myEmote() { return this.emotes[this.selectedEmote]; } + + /** + * Gets the player's currently selected evidence if presentable. + */ + myEvidence() { + return (this.presentable)? this.selectedEvidence : 0; + } /** * Sends an out-of-character chat message. @@ -114,13 +126,42 @@ class Client { * @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect * @param {string} objection the number of the shout to play */ - sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, flip, flash, color) { + sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, evidence, flip, flash, color) { this.serv.send( `MS#chat#${speaking}#${name}#${silent}` + `#${escapeChat(encodeChat(message))}#${side}#${ssfxname}#${zoom}` + - `#${this.charID}#${ssfxdelay}#${selectedShout}#0#${flip}#${flash}#${color}#%` + `#${this.charID}#${ssfxdelay}#${selectedShout}#${evidence}#${flip}#${flash}#${color}#%` ); } + + /** + * Sends add evidence command. + * @param {string} evidence name + * @param {string} evidence description + * @param {string} evidence image filename + */ + sendPE(name, desc, img) { + this.serv.send(`PE#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); + } + + /** + * Sends edit evidence command. + * @param {string} evidence id + * @param {string} evidence name + * @param {string} evidence description + * @param {string} evidence image filename + */ + sendEE(id, name, desc, img) { + this.serv.send(`EE#${id}#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); + } + + /** + * Sends delete evidence command. + * @param {string} evidence id + */ + sendDE(id, name, desc, img) { + this.serv.send(`DE#${id}#%`); + } /** * Requests to change the music to the specified track. @@ -150,6 +191,20 @@ class Client { this.checkUpdater = setInterval(() => this.sendCheck(), 5000); } + /** + * Load game resources. + */ + loadResources() { + // Load evidence array to select + var evidence_select = document.getElementById("evi_select"); + evidence_select.add(new Option("Custom", 0)); + for(let i = 1; i <= evidence_arr.length; i++) { + evidence_select.add(new Option(evidence_arr[i - 1])); + } + // TODO: Cache some resources + + } + /** * Create observer to detect BBCode elements * then manipulate them. @@ -410,6 +465,34 @@ class Client { //serv.send("AE#" + (args[1] + 1) + "#%"); this.serv.send("RM#%"); } + + /** + * Handles incoming evidence list, all evidences at once + * item per packet. + * + * @param {Array} args packet arguments + */ + handleLE(args) { + this.evidences = []; + for (let i = 1; i < args.length - 1; i++) { + var arg = args[i].split("&"); + this.evidences[i - 1] = { + "name": escapeHtml(decodeChat(unescapeChat(arg[0]))), + "desc": escapeHtml(decodeChat(unescapeChat(arg[1]))), + "filename": escape(arg[2]), + "icon": AO_HOST + "evidence/" + escape(arg[2]) + } + } + + var evidence_box = document.getElementById("evidences"); + evidence_box.innerHTML = ""; + for(let i = 1; i <= this.evidences.length; i++){ + evidence_box.innerHTML += '' + this.evidences[i - 1].name +
+				''; + } + } /** * Handles incoming music information, containing multiple entries @@ -590,7 +673,7 @@ class Client { } }; xhr.send(); - } + } } class Viewport { @@ -751,10 +834,11 @@ class Viewport { if (this.chatmsg.isnew) { // Reset screen background document.getElementById("client_background").style.backgroundColor = "transparent"; - //Hide message window + //Hide message and evidence window document.getElementById("client_name").style.display = "none"; document.getElementById("client_chat").style.display = "none"; - + document.getElementById("client_evi").style.opacity = "0"; + document.getElementById("client_evi").style.height = "0%"; const shouts = { "1": "holdit", "2": "objection", @@ -795,7 +879,7 @@ class Viewport { //Pre-animation stuff if(this.chatmsg.preanimdelay > 0){ - document.getElementById("client_shout").src = ""; + document.getElementById("client_shout").src = "misc/placeholder.gif"; changeBackground(this.chatmsg.side); document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.preanim + ".gif"; } @@ -803,10 +887,34 @@ class Viewport { this.chatmsg.startspeaking = true; } else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) { if (this.chatmsg.startspeaking) { + if(this.chatmsg.evidence > 0){ + // Prepare evidence + document.getElementById("client_evi").style.backgroundImage = "url('"+ client.evidences[this.chatmsg.evidence - 1].icon +"')"; + + if (this.chatmsg.side == 'def'){ + // Only def show evidence on right + document.getElementById("client_evi").style.right = "1.5em"; + document.getElementById("client_evi").style.left = "initial"; + $( "#client_evi" ).animate({ + height: "30%", + opacity: 1, + marginLeft: "10.6in" + }, 250 ); + } else { + document.getElementById("client_evi").style.right = "initial"; + document.getElementById("client_evi").style.left = "1.5em"; + $( "#client_evi" ).animate({ + height: "30%", + opacity: 1, + marginRight: "10.6in" + }, 250 ); + } + } + $("#client_name").toggle( "fade" ); $("#client_chat").toggle("drop",{"direction":"down"}); if(this.chatmsg.preanimdelay == 0){ - document.getElementById("client_shout").src = ""; + document.getElementById("client_shout").src = "misc/placeholder.gif"; changeBackground(this.chatmsg.side); } document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.speaking + ".gif"; @@ -915,6 +1023,7 @@ export function onEnter(event) { if (event.keyCode == 13) { let mychar = client.me(); let myemo = client.myEmote(); + let myevi = client.myEvidence(); let myflip = ((client.flip)? 1:0); let mycolor = document.getElementById("textcolor").value; let ssfxname = "0"; @@ -923,7 +1032,7 @@ export function onEnter(event) { ssfxname = myemo.sfx; ssfxdelay = myemo.sfxdelay; } - client.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById("client_inputbox").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout, myflip, selectedEffect, mycolor); + client.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById("client_inputbox").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout, myevi, myflip, selectedEffect, mycolor); } } window.onEnter = onEnter; @@ -996,7 +1105,7 @@ window.changeCharacter = changeCharacter; */ export function imgError(image) { image.onerror = ""; - image.src = "/misc/placeholder.gif"; + image.src = "misc/placeholder.gif"; return true; } window.imgError = imgError; @@ -1155,6 +1264,145 @@ export function pickemotion(emo) { } window.pickemotion = pickemotion; +/** + * Highlights and selects an evidence for in-character chat. + * @param {string} evidence the evidence to be presented + */ +export function pickevidence(evidence) { + if (client.selectedEvidence != evidence) { + //Update selected evidence + if(client.selectedEvidence > 0){ + document.getElementById("evi_" + client.selectedEvidence).className = "client_button"; + } + document.getElementById("evi_" + evidence).className = "client_button dark"; + client.selectedEvidence = evidence; + + // Show evidence on information window + document.getElementById("evi_name").value = client.evidences[evidence - 1].name; + document.getElementById("evi_desc").value = client.evidences[evidence - 1].desc; + + //Update Icon + let icon_id = findEvidenceIcon(evidence); + document.getElementById("evi_select").selectedIndex = icon_id; + if (icon_id == 0){ + document.getElementById("evi_filename").value = client.evidences[evidence - 1].filename; + } + updateEvidenceIcon(); + + // Update button + document.getElementById("evi_add").className = "client_button hover_button inactive"; + document.getElementById("evi_edit").className = "client_button hover_button"; + document.getElementById("evi_cancel").className = "client_button hover_button"; + document.getElementById("evi_del").className = "client_button hover_button"; + } else { + cancelevidence(); + } +} +window.pickevidence = pickevidence; + +/** + * Add evidence. + */ +export function addevidence() { + let evidence_select = document.getElementById('evi_select'); + client.sendPE( document.getElementById('evi_name').value, + document.getElementById('evi_desc').value, + (evidence_select.selectedIndex == 0)? + document.getElementById('evi_filename').value : + evidence_select.options[evidence_select.selectedIndex].text + ); + cancelevidence(); +} +window.addevidence = addevidence; + +/** + * Edit selected evidence. + */ +export function editevidence() { + let evidence_select = document.getElementById('evi_select'); + let id = parseInt(client.selectedEvidence) - 1; + client.sendEE( id, + document.getElementById('evi_name').value, + document.getElementById('evi_desc').value, + (evidence_select.selectedIndex == 0)? + document.getElementById('evi_filename').value : + evidence_select.options[evidence_select.selectedIndex].text + ); + cancelevidence(); +} +window.editevidence = editevidence; + +/** + * Delete selected evidence. + */ +export function delevidence() { + let id = parseInt(client.selectedEvidence) - 1; + client.sendDE(id); + cancelevidence(); +} +window.delevidence = delevidence; + +/** + * Cancel evidence selection. + */ +export function cancelevidence() { + //Clear evidence data + if(client.selectedEvidence > 0){ + document.getElementById("evi_" + client.selectedEvidence).className = "client_button"; + } + client.selectedEvidence = 0; + + // Clear evidence on information window + document.getElementById("evi_select").selectedIndex = 0; + updateEvidenceIcon(); // Update icon widget + document.getElementById("evi_filename").value = ""; + document.getElementById("evi_name").value = ""; + document.getElementById("evi_desc").value = ""; + document.getElementById("evi_icon").style.backgroundImage = "url('misc/empty.png')"; //Clear icon + + // Update button + document.getElementById("evi_add").className = "client_button hover_button"; + document.getElementById("evi_edit").className = "client_button hover_button inactive"; + document.getElementById("evi_cancel").className = "client_button hover_button inactive"; + document.getElementById("evi_del").className = "client_button hover_button inactive"; +} +window.cancelevidence = cancelevidence; + +/** + * Find evidence icon in select box via id. + * @param {integer} id the id of evidence + */ +export function findEvidenceIcon(id) { + //Find if icon alraedy existed in select box + let evidence_select = document.getElementById("evi_select"); + for (let i = 1; i < evidence_select.length; ++i){ + if (evidence_select.options[i].value == client.evidences[id - 1].filename){ + return i; + } + } + return 0; +} +window.findEvidenceIcon = findEvidenceIcon; + +/** + * Update evidence icon. + */ +export function updateEvidenceIcon() { + let evidence_select = document.getElementById("evi_select"); + let evidence_filename = document.getElementById("evi_filename"); + let evidence_iconbox = document.getElementById("evi_icon"); + + if (evidence_select.selectedIndex == 0) { + evidence_filename.style.display = "initial"; + evidence_iconbox.style.backgroundImage = "url('" + AO_HOST + 'evidence/' + evidence_filename.value + "')"; + } else { + evidence_filename.value = ""; + evidence_filename.style.display = "none"; + evidence_iconbox.style.backgroundImage = "url('" + AO_HOST + 'evidence/' + evidence_select.value + "')" ; + } +} +window.updateEvidenceIcon = updateEvidenceIcon; + /** * Highlights and selects an effect for in-character chat. * If the same effect button is selected, then the effect is canceled. @@ -1187,6 +1435,34 @@ export function toggleflip() { } window.toggleflip = toggleflip; +/** + * Toggle presentable for presenting evidence in-character chat. + */ +export function togglepresent() { + if (client.presentable) { + document.getElementById("button_present").className = "client_button"; + } else { + document.getElementById("button_present").className = "client_button dark"; + } + client.presentable = !client.presentable; +} +window.togglepresent = togglepresent; + +/** + * Highlights and selects a menu. + * @param {string} menu the menu to be selected + */ +export function togglemenu(menu) { + if (menu != selectedMenu) { + document.getElementById("menu_" + menu).className = "menu_icon active"; + document.getElementById("content_" + menu).className = "menu_content active"; + document.getElementById("menu_" + selectedMenu).className = "menu_icon"; + document.getElementById("content_" + selectedMenu).className = "menu_content"; + selectedMenu = menu; + } +} +window.togglemenu = togglemenu; + /** * Highlights and selects a shout for in-character chat. * If the same shout button is selected, then the shout is canceled. @@ -1337,4 +1613,5 @@ let viewport = new Viewport(); $(document).ready(function(){ client.initialObservBBCode(); + client.loadResources(); }); -- cgit From 67d1e2252b8f46605d49a6c95c80475b890ec3b8 Mon Sep 17 00:00:00 2001 From: Qube Date: Fri, 20 Jul 2018 00:23:20 +0700 Subject: Add location section (Area selector and background change) + fix desk to 'bancodefensa' and 'bancoacusacion' when 'defensedesk' and 'prosecutiondesk' are not existed --- webAO/client.js | 126 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 108 insertions(+), 18 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index fd8289a..b2be1e6 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -201,6 +201,12 @@ class Client { for(let i = 1; i <= evidence_arr.length; i++) { evidence_select.add(new Option(evidence_arr[i - 1])); } + // Load background array to select + var background_select = document.getElementById("bg_select"); + background_select.add(new Option("Custom", 0)); + for(let i = 1; i <= background_arr.length; i++) { + background_select.add(new Option(background_arr[i - 1])); + } // TODO: Cache some resources } @@ -519,13 +525,38 @@ class Client { */ handleSM(args) { document.getElementById("client_loadingtext").innerHTML = "Loading Music "; - let hmusiclist = document.getElementById("client_musiclist"); + let hmusiclist = document.getElementById("client_musiclist"), flagAudio = false; + for (let i = 1; i < args.length - 1; i++) { - let newentry = document.createElement("OPTION"); - newentry.text = args[i]; - hmusiclist.options.add(newentry); + // Check when found the song for the first time + if(/\.(?:wav|mp3|mp4|ogg|mid)$/i.test(args[i]) && !flagAudio){ + flagAudio = true; + } + + if(flagAudio) { + // After reached the audio put everything in the music list + let newentry = document.createElement("OPTION"); + newentry.text = args[i]; + hmusiclist.options.add(newentry); + + } else { + // Create area button + let newarea = document.createElement("SPAN"); + newarea.className = "location-box"; + newarea.textContent = args[i]; + newarea.onclick = function(){ area_click(this) }; + document.getElementById("areas").appendChild(newarea); + } } - this.serv.send("RD#%"); + + // Move first audio title from area box to music list + let area_box = document.getElementById("areas"); + let audio_title = document.createElement("OPTION"); + audio_title.text = area_box.lastChild.textContent; + hmusiclist.insertBefore(audio_title, hmusiclist.firstChild); + area_box.removeChild(area_box.lastChild); // Remove from arae box + + this.serv.send("RD#%"); } /** @@ -556,6 +587,14 @@ class Client { */ handleBN(args) { viewport.bgname = escape(args[1]); + let bg_index = getIndexFromSelect("bg_select", escape(args[1])); + document.getElementById("bg_select").selectedIndex = bg_index; + updateBackgroundPreview(); + if(bg_index > 0){ + document.getElementById("bg_filename").value = escape(args[1]); + } + document.getElementById("bg_preview").src = AO_HOST + 'background/' + escape(args[1]) + "/defenseempty.png"; + } handleNBG(args) { @@ -1064,6 +1103,16 @@ export function musiclist_click(event) { } window.musiclist_click = musiclist_click; +/** + * Triggered when an item on the music list is clicked. + * @param {MouseEvent} event + */ +export function area_click(el) { + let playtrack = el.textContent; + client.sendMusicChange(playtrack); +} +window.area_click = area_click; + /** * Triggered by the music volume slider. */ @@ -1146,13 +1195,21 @@ function changeBackground(position) { case "def": document.getElementById("client_court").src = bgfolder + "defenseempty.png" document.getElementById("client_bench").style.display = "block"; - document.getElementById("client_bench").src = bgfolder + "defensedesk.png" + if(ImageExist(bgfolder + "defensedesk.png")){ + document.getElementById("client_bench").src = bgfolder + "defensedesk.png" + }else{ + document.getElementById("client_bench").src = bgfolder + "bancodefensa.png" + } standname = "defense"; break; case "pro": document.getElementById("client_court").src = bgfolder + "prosecutorempty.png" document.getElementById("client_bench").style.display = "block" - document.getElementById("client_bench").src = bgfolder + "prosecutiondesk.png" + if(ImageExist(bgfolder + "defensedesk.png")){ + document.getElementById("client_bench").src = bgfolder + "prosecutiondesk.png" + } else { + document.getElementById("client_bench").src = bgfolder + "bancoacusacion.png" + } standname = "prosecution"; break; case "hld": @@ -1282,7 +1339,7 @@ export function pickevidence(evidence) { document.getElementById("evi_desc").value = client.evidences[evidence - 1].desc; //Update Icon - let icon_id = findEvidenceIcon(evidence); + let icon_id = getIndexFromSelect("evi_select", client.evidences[evidence - 1].filename); document.getElementById("evi_select").selectedIndex = icon_id; if (icon_id == 0){ document.getElementById("evi_filename").value = client.evidences[evidence - 1].filename; @@ -1369,20 +1426,21 @@ export function cancelevidence() { window.cancelevidence = cancelevidence; /** - * Find evidence icon in select box via id. - * @param {integer} id the id of evidence + * Find index of anything in select box. + * @param {string} select_box the select element name + * @param {string} value the value that need to be compared */ -export function findEvidenceIcon(id) { +export function getIndexFromSelect(select_box, value) { //Find if icon alraedy existed in select box - let evidence_select = document.getElementById("evi_select"); - for (let i = 1; i < evidence_select.length; ++i){ - if (evidence_select.options[i].value == client.evidences[id - 1].filename){ - return i; + let select_element = document.getElementById(select_box); + for (let i = 1; i < select_element.length; ++i){ + if (select_element.options[i].value == value){ + return i; } } return 0; } -window.findEvidenceIcon = findEvidenceIcon; +window.getIndexFromSelect = getIndexFromSelect; /** * Update evidence icon. @@ -1395,14 +1453,46 @@ export function updateEvidenceIcon() { if (evidence_select.selectedIndex == 0) { evidence_filename.style.display = "initial"; evidence_iconbox.style.backgroundImage = "url('" + AO_HOST + 'evidence/' + evidence_filename.value + "')"; - } else { - evidence_filename.value = ""; + } else { evidence_filename.style.display = "none"; evidence_iconbox.style.backgroundImage = "url('" + AO_HOST + 'evidence/' + evidence_select.value + "')" ; } } window.updateEvidenceIcon = updateEvidenceIcon; +/** + * Change background. + */ +export function changeBackgroundOOC() { + let filename = "", background_select = document.getElementById("bg_select") + , bg_command = document.getElementById("bg_command").value; + if (background_select.selectedIndex == 0) { + filename = document.getElementById("bg_filename").value; + } else{ + filename = background_select.value; + } + client.sendOOC("/" + bg_command.replace("$1",filename)); +} +window.changeBackgroundOOC = changeBackgroundOOC; + +/** + * Update background preview. + */ +export function updateBackgroundPreview() { + let background_select = document.getElementById("bg_select"); + let background_filename = document.getElementById("bg_filename"); + let background_preview = document.getElementById("bg_preview"); + + if (background_select.selectedIndex == 0) { + background_filename.style.display = "initial"; + background_preview.src = AO_HOST + 'background/' + background_filename.value + "/defenseempty.png"; + } else { + background_filename.style.display = "none"; + background_preview.src = AO_HOST + 'background/' + background_select.value + "/defenseempty.png"; + } +} +window.updateBackgroundPreview = updateBackgroundPreview; + /** * Highlights and selects an effect for in-character chat. * If the same effect button is selected, then the effect is canceled. -- cgit From e2b70d9457ead36007b6b512496cf9ff532bf025 Mon Sep 17 00:00:00 2001 From: Qube Date: Fri, 20 Jul 2018 00:32:31 +0700 Subject: Fix handleBN --- webAO/client.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index b2be1e6..145a83b 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -590,8 +590,8 @@ class Client { let bg_index = getIndexFromSelect("bg_select", escape(args[1])); document.getElementById("bg_select").selectedIndex = bg_index; updateBackgroundPreview(); - if(bg_index > 0){ - document.getElementById("bg_filename").value = escape(args[1]); + if(bg_index == 0){ + document.getElementById("bg_filename").value = args[1]; } document.getElementById("bg_preview").src = AO_HOST + 'background/' + escape(args[1]) + "/defenseempty.png"; -- cgit From f2a436227ec386ec2497b980d738631f9f5b6a70 Mon Sep 17 00:00:00 2001 From: Qube Date: Fri, 20 Jul 2018 10:21:37 +0700 Subject: Fix evidence not show in def side --- webAO/client.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 145a83b..a9e95b5 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -936,16 +936,14 @@ class Viewport { document.getElementById("client_evi").style.left = "initial"; $( "#client_evi" ).animate({ height: "30%", - opacity: 1, - marginLeft: "10.6in" + opacity: 1 }, 250 ); } else { document.getElementById("client_evi").style.right = "initial"; document.getElementById("client_evi").style.left = "1.5em"; $( "#client_evi" ).animate({ height: "30%", - opacity: 1, - marginRight: "10.6in" + opacity: 1 }, 250 ); } } -- cgit From 1e55e05fc9ca04437abf7823e3ab50c131529bf0 Mon Sep 17 00:00:00 2001 From: Qube Date: Fri, 20 Jul 2018 20:57:37 +0700 Subject: Add witness testinomy, cross examination, call mod function + Fix animation sequence more reliable (using gify API to calculate animation duration) + Resign interface to gain more space. --- webAO/client.js | 376 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 325 insertions(+), 51 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index a9e95b5..68d7c7d 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -19,7 +19,7 @@ const MUSIC_HOST = AO_HOST + "sounds/music/"; const BAR_WIDTH = 90; const BAR_HEIGHT = 20; const CHAR_SELECT_WIDTH = 8; -const UPDATE_INTERVAL = 65; +const UPDATE_INTERVAL = 60; let oldLoading = false; if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) { @@ -45,10 +45,36 @@ class Client { this.playerID = 1; this.charID = -1; + this.testimonyID = 0; this.chars = []; this.emotes = []; this.evidences = []; + + this.resources = { + "holdit":{ + "src": "misc/holdit.gif", + "duration": 720 + }, + "objection":{ + "src": "misc/objection.gif", + "duration": 720 + }, + "takethat":{ + "src": "misc/takethat.gif", + "duration": 840 + }, + "witnesstestimony":{ + "src": "misc/witnesstestimony.gif", + "duration": 1560, + "sfx": "sounds/general/sfx-testimony.wav" + }, + "crossexamination":{ + "src": "misc/crossexamination.gif", + "duration": 1600, + "sfx": "sounds/general/sfx-testimony2.wav" + } + }; this.selectedEmote = -1; this.selectedEvidence = 0; @@ -71,9 +97,11 @@ class Client { "SM": (args) => this.handleSM(args), "music": (args) => this.handlemusic(args), "DONE": (args) => this.handleDONE(args), - "BN": (args) => this.handleBN(args), + "BN": (args) => this.handleBN(args), "NBG": (args) => this.handleNBG(args), "HP": (args) => this.handleHP(args), + "RT": (args) => this.handleRT(args), + "ZZ": (args) => this.handleZZ(args), "ID": (args) => this.handleID(args), "PN": (args) => this.handlePN(args), "SI": (args) => this.handleSI(args), @@ -159,9 +187,27 @@ class Client { * Sends delete evidence command. * @param {string} evidence id */ - sendDE(id, name, desc, img) { + sendDE(id) { this.serv.send(`DE#${id}#%`); } + + /** + * Sends call mod command. + * @param {string} message to mod + */ + sendZZ(msg) { + this.serv.send(`ZZ#${msg}#%`); + } + + /** + * Sends testimony command. + * @param {string} testimony type + */ + sendRT(testimony) { + if(this.chars[this.charID].side == "jud"){ + this.serv.send(`RT#${testimony}#%`); + } + } /** * Requests to change the music to the specified track. @@ -207,10 +253,60 @@ class Client { for(let i = 1; i <= background_arr.length; i++) { background_select.add(new Option(background_arr[i - 1])); } + // Calculate gif duration of shouts + let shouts = ["holdit", "objection", "takethat"]; + for (let i = 0; i < shouts.length; i++) { + let shout_src = AO_HOST + this.resources[shouts[i]]["src"]; + FileExist(shout_src, this.callbackLoadImageResources, shouts[i]); + } + + // Calculate gif duration of testimony + let testimony = ["witnesstestimony", "crossexamination"]; + for (let i = 0; i < testimony.length; i++) { + let testimony_src = AO_HOST + "themes/default/"+ testimony[i] +".gif"; + // Check iamge existed + FileExist(testimony_src, this.callbackLoadImageResources, testimony[i]); + // Check sfx existed + FileExist(AO_HOST + this.resources[testimony[i]]["sfx"], this.callbackLoadSFXResources, testimony[i]); + } // TODO: Cache some resources } + /** + * Callback for image resources. + * @param {boolean} result the image is existed or not + * @param {string} resource the resource name + * @param {string} src the url of resource + */ + callbackLoadImageResources(result, resource, src) { + if(result){ + client.resources[resource]["src"] = src; + viewport.getAnimLength(src,client.callbackGetResourceLength, resource); + } + } + + /** + * Callback for animation duration resource + * @param {integer} length the animation length + * @param {string} resource the resource name + */ + callbackGetResourceLength(length, resource) { + client.resources[resource]["duration"] = length; + } + + /** + * Callback for sfx resources. + * @param {boolean} result the audio is existed or not + * @param {string} resource the resource name + * @param {string} src the url of resource + */ + callbackLoadSFXResources(result, resource, src) { + if(result){ + client.resources[resource]["sfx"] = src; + } + } + /** * Create observer to detect BBCode elements * then manipulate them. @@ -594,7 +690,12 @@ class Client { document.getElementById("bg_filename").value = args[1]; } document.getElementById("bg_preview").src = AO_HOST + 'background/' + escape(args[1]) + "/defenseempty.png"; - + if(this.charID == -1){ + changeBackground("jud"); + } else { + changeBackground(this.chars[this.charID].side); + } + } handleNBG(args) { @@ -615,6 +716,47 @@ class Client { } } + /** + * Handles a testimony states. + * @param {Array} args packet arguments + */ + handleRT(args) { + if (args[1] == "testimony1") { + //Witness Testimony + this.testimonyID = 1; + } else { + //Cross Examination + this.testimonyID = 2; + } + viewport.initTestimonyUpdater(); + } + + /** + * Handles a call mod message. + * @param {Array} args packet arguments + */ + handleZZ(args) { + const oocLog = document.getElementById("client_ooclog"); + oocLog.innerHTML += `\$Alert: ${decodeChat(unescapeChat(args[1]))}\r\n`; + if (oocLog.scrollTop > oocLog.scrollHeight - 60) { + oocLog.scrollTop = oocLog.scrollHeight; + } + } + + /** + * Handles a change in the health bars' states. + * @param {Array} args packet arguments + */ + handleHP(args) { + // TODO (set by sD) + // Also, this is broken. + if (args[1] == 1) { + document.getElementById("client_defense_hp").style.clip = "rect(0px," + BAR_WIDTH * args[2] / 10 + "px," + BAR_HEIGHT + "px,0px)"; + } else { + document.getElementById("client_prosecutor_hp").style.clip = "rect(0px," + BAR_WIDTH * args[2] / 10 + "px," + BAR_HEIGHT + "px,0px)"; + } + } + /** * Handles the issuance of a player ID by the server. * @param {Array} args packet arguments @@ -665,8 +807,8 @@ class Client { if (i % CHAR_SELECT_WIDTH == 0) { document.getElementById("client_chartable").appendChild(tr); } - } - changeBackground("def"); + } + //changeBackground("def"); } /** @@ -679,6 +821,7 @@ class Client { let me = this.me(); let emotes = this.emotes; let xhr = new XMLHttpRequest(); + document.getElementById("client_emo").innerHTML = ""; // Clear emote box xhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true); xhr.responseType = 'text'; xhr.onload = function (e) { @@ -686,6 +829,7 @@ class Client { let linifile = this.responseText; let pinifile = INI.parse(linifile); me.side = pinifile.Options.side; + updateActionCommands(me.side); for (let i = 1; i < pinifile.Emotions.number; i++) { let emoteinfo = pinifile.Emotions[i].split('#'); let esfx = "0"; @@ -750,9 +894,11 @@ class Viewport { this.music.play(); this.updater = null; + this.testimonyUpdater = null; this.bgname = "gs4"; - + + this.testimonyTimer = 0; this.shoutTimer = 0; this.textTimer = 0; @@ -802,7 +948,7 @@ class Viewport { chatmsg.preanimdelay = this.getAnimLength(AO_HOST + 'characters/' + escape(chatmsg.name) + '/' + chatmsg.preanim + '.gif',this.initUpdater); } else { this.initUpdater(0) - } + } } /** @@ -814,45 +960,83 @@ class Viewport { viewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL); } + /** + * Intialize testimony updater + */ + initTestimonyUpdater(){ + if(client.testimonyID > 0){ + let testimony = ""; + if (client.testimonyID == 1) { + testimony = "witnesstestimony"; + } else if (client.testimonyID == 2) { + testimony = "crossexamination"; + } + (new Audio(client.resources[testimony]["sfx"])).play(); + this.testimonyTimer = 0; + document.getElementById("client_testimony").src = client.resources[testimony]["src"]; + this.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL); + } + } + /** * Gets animation length. * @param {string} filename the animation file name * @param {function} callback the callback function + * @param {object} param */ - getAnimLength(filename,callback) { - //Source (Thanks to Ryman): https://codepen.io/Ryman/pen/wzioA + getAnimLength(filename, callback, param) { var request = new XMLHttpRequest(); request.open('GET', filename, true); request.responseType = 'arraybuffer'; request.addEventListener('load', function () { - var arr = new Uint8Array(request.response), - // Thanks to http://justinsomnia.org/2006/10/gif-animation-duration-calculation/ - // And http://www.w3.org/Graphics/GIF/spec-gif89a.txt - bin = '', - duration = 0; - - for (var i = 0; i < arr.length; i++) { - bin += String.fromCharCode( arr[i] ) - - // Find a Graphic Control Extension hex(21F904__ ____ __00) - if (arr[i] == 0x21 - && arr[i + 1] == 0xF9 - && arr[i + 2] == 0x04 - && arr[i + 7] == 0x00) { - // Swap 5th and 6th bytes to get the delay per frame - let delay = (arr[i + 5] << 8) | (arr[i + 4] & 0xFF) - - // Should be aware browsers have a minimum frame delay - // e.g. 6ms for IE, 2ms modern browsers (50fps) - duration += delay < 2 ? 10 : (delay) - } - } + // Use gify API + // https://github.com/rfrench/gify + var gifInfo = gify.getInfo(request.response); + console.log(gifInfo["duration"]); // Return animation length - callback(duration * 10); + callback(gifInfo["duration"], param); }); request.send(); } - + + /** + * Updates the testimony overaly + */ + updateTestimony(){ + //Update timer + this.testimonyTimer = this.testimonyTimer + UPDATE_INTERVAL; + + if (client.testimonyID == 1) { + //Witness Testimony + if (this.testimonyTimer >= client.resources["witnesstestimony"]["duration"]){ + //Finish + this.disposeTestimony(); + } else { + this.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL); + } + } else if (client.testimonyID == 2) { + //Cross Examination + if (this.testimonyTimer >= client.resources["crossexamination"]["duration"]){ + //Finish + this.disposeTestimony(); + } else { + this.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL); + } + } else { + this.disposeTestimony(); + } + } + + /** + * Dispose the testimony overlay + */ + disposeTestimony(){ + client.testimonyID = 0; + this.testimonyTimer = 0; + document.getElementById("client_testimony").src = "misc/placeholder.gif"; + clearTimeout(this.testimonyUpdater); + } + /** * Updates the chatbox based on the given text. * @@ -886,7 +1070,7 @@ class Viewport { let shout = shouts[this.chatmsg.objection]; if (typeof shout !== "undefined") { - document.getElementById("client_shout").src = AO_HOST + "misc/" + shout + ".gif"; + document.getElementById("client_shout").src = client.resources[shout]["src"]; (new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play(); this.shoutTimer = 850; } else { @@ -1169,13 +1353,22 @@ export function demoError(image) { window.demoError = demoError; /** - * Checks if an image exists at the specified URI. + * Checks if an file exists at the specified URI. * @param {string} url the URI to be checked + * @param {function} callback the function to be called when finished + * @param {object} param */ -function ImageExist(url) { - var img = new Image(); - img.src = url; - return img.height != 0; +function FileExist(url,callback,param) { + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + callback(true, param, url); + } else { + callback(false, param, url); + } + }; + xhttp.open("GET", url, true); + xhttp.send(); } /** @@ -1193,21 +1386,13 @@ function changeBackground(position) { case "def": document.getElementById("client_court").src = bgfolder + "defenseempty.png" document.getElementById("client_bench").style.display = "block"; - if(ImageExist(bgfolder + "defensedesk.png")){ - document.getElementById("client_bench").src = bgfolder + "defensedesk.png" - }else{ - document.getElementById("client_bench").src = bgfolder + "bancodefensa.png" - } + FileExist(bgfolder + "defensedesk.png", callbackChangeBackground, position); standname = "defense"; break; case "pro": document.getElementById("client_court").src = bgfolder + "prosecutorempty.png" document.getElementById("client_bench").style.display = "block" - if(ImageExist(bgfolder + "defensedesk.png")){ - document.getElementById("client_bench").src = bgfolder + "prosecutiondesk.png" - } else { - document.getElementById("client_bench").src = bgfolder + "bancoacusacion.png" - } + FileExist(bgfolder + "defensedesk.png", callbackChangeBackground, position); standname = "prosecution"; break; case "hld": @@ -1235,6 +1420,30 @@ function changeBackground(position) { } } +/** + * Callback for desk resource + * + * Valid positions: `def, pro, hld, hlp, wit, jud` + * @param {boolean} result the image is existed or not + * @param {string} position the position to change into + */ +function callbackChangeBackground(result,position) { + let bgfolder = viewport.bgFolder(); + if (position == "def"){ + if(result){ + document.getElementById("client_bench").src = bgfolder + "defensedesk.png" + }else{ + document.getElementById("client_bench").src = bgfolder + "bancodefensa.png" + } + } else { + if(result){ + document.getElementById("client_bench").src = bgfolder + "prosecutiondesk.png" + } else { + document.getElementById("client_bench").src = bgfolder + "bancoacusacion.png" + } + } +} + /** * Triggered when the reconnect button is pushed. */ @@ -1459,7 +1668,28 @@ export function updateEvidenceIcon() { window.updateEvidenceIcon = updateEvidenceIcon; /** - * Change background. + * Update evidence icon. + */ +export function updateActionCommands(side) { + if(side == "jud"){ + document.getElementById("menu_wt").style.display = "inline-table"; + document.getElementById("menu_ce").style.display = "inline-table"; + } else { + document.getElementById("menu_wt").style.display = "none"; + document.getElementById("menu_ce").style.display = "none"; + } + //Update role selector + for(let i = 0, role_select = document.getElementById("role_select").options; i < role_select.length; i++){ + if(side == role_select[i].value){ + role_select.selectedIndex = i; + return; + } + } +} +window.updateActionCommands = updateActionCommands; + +/** + * Change background via OOC. */ export function changeBackgroundOOC() { let filename = "", background_select = document.getElementById("bg_select") @@ -1473,6 +1703,50 @@ export function changeBackgroundOOC() { } window.changeBackgroundOOC = changeBackgroundOOC; +/** + * Change role via OOC. + */ +export function changeRoleOOC() { + let role_select = document.getElementById("role_select") + , role_command = document.getElementById("role_command").value; + + client.sendOOC("/" + role_command.replace("$1",role_select.value)); + updateActionCommands(role_select.value); +} +window.changeRoleOOC = changeRoleOOC; + +/** + * Random character via OOC. + */ +export function randomCharacterOOC() { + client.sendOOC("/" + document.getElementById("randomchar_command").value); +} +window.randomCharacterOOC = randomCharacterOOC; + +/** + * Call mod. + */ +export function callmod() { + client.sendZZ(""); +} +window.callmod = callmod; + +/** + * Decalre witness testimony. + */ +export function initwt() { + client.sendRT("testimony1"); +} +window.initwt = initwt; + +/** + * Decalre cross examination. + */ +export function initce() { + client.sendRT("testimony2"); +} +window.initce = initce; + /** * Update background preview. */ -- cgit From c1730c3e16d088c03f27adab3ebfb4e6f7a37d1a Mon Sep 17 00:00:00 2001 From: Qube Date: Sat, 21 Jul 2018 01:00:48 +0700 Subject: Add penalty bars function and confirm dialog for "call mod" button. --- webAO/client.js | 113 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 25 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 68d7c7d..83c34ab 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -42,6 +42,8 @@ class Client { this.flip = false; this.presentable = false; + + this.hp = [0,0]; this.playerID = 1; this.charID = -1; @@ -191,6 +193,15 @@ class Client { this.serv.send(`DE#${id}#%`); } + /** + * Sends health point command. + * @param {int} side the position + * @param {int} hp the health point + */ + sendHP(side,hp) { + this.serv.send(`HP#${side}#${hp}#%`); + } + /** * Sends call mod command. * @param {string} message to mod @@ -707,13 +718,16 @@ class Client { * @param {Array} args packet arguments */ handleHP(args) { - // TODO (set by sD) - // Also, this is broken. + let percent_hp = args[2] * 10; if (args[1] == 1) { - document.getElementById("client_defense_hp").style.clip = "rect(0px," + BAR_WIDTH * args[2] / 10 + "px," + BAR_HEIGHT + "px,0px)"; + // Def hp + this.hp[0] = args[2]; + $("#client_defense_hp > .health-bar").animate({ 'width': percent_hp + "%" }, 500); } else { - document.getElementById("client_prosecutor_hp").style.clip = "rect(0px," + BAR_WIDTH * args[2] / 10 + "px," + BAR_HEIGHT + "px,0px)"; - } + // Pro hp + this.hp[1] = args[2]; + $("#client_prosecutor_hp > .health-bar").animate({ 'width': percent_hp + "%" }, 500); + } } /** @@ -743,20 +757,6 @@ class Client { } } - /** - * Handles a change in the health bars' states. - * @param {Array} args packet arguments - */ - handleHP(args) { - // TODO (set by sD) - // Also, this is broken. - if (args[1] == 1) { - document.getElementById("client_defense_hp").style.clip = "rect(0px," + BAR_WIDTH * args[2] / 10 + "px," + BAR_HEIGHT + "px,0px)"; - } else { - document.getElementById("client_prosecutor_hp").style.clip = "rect(0px," + BAR_WIDTH * args[2] / 10 + "px," + BAR_HEIGHT + "px,0px)"; - } - } - /** * Handles the issuance of a player ID by the server. * @param {Array} args packet arguments @@ -1672,11 +1672,11 @@ window.updateEvidenceIcon = updateEvidenceIcon; */ export function updateActionCommands(side) { if(side == "jud"){ - document.getElementById("menu_wt").style.display = "inline-table"; - document.getElementById("menu_ce").style.display = "inline-table"; + document.getElementById("judge_action").style.display = "inline-table"; + document.getElementById("no_action").style.display = "none"; } else { - document.getElementById("menu_wt").style.display = "none"; - document.getElementById("menu_ce").style.display = "none"; + document.getElementById("no_action").style.display = "inline-table"; + document.getElementById("judge_action").style.display = "none"; } //Update role selector for(let i = 0, role_select = document.getElementById("role_select").options; i < role_select.length; i++){ @@ -1726,8 +1726,8 @@ window.randomCharacterOOC = randomCharacterOOC; /** * Call mod. */ -export function callmod() { - client.sendZZ(""); +export function callmod() { + $( "#callmod_dialog" ).dialog( "open" ); } window.callmod = callmod; @@ -1747,6 +1747,38 @@ export function initce() { } window.initce = initce; +/** + * Add defense health point. + */ +export function addHPD() { + client.sendHP(1,String(parseInt(client.hp[0]) + 1)); +} +window.addHPD = addHPD; + +/** + * Reduce defense health point. + */ +export function redHPD() { + client.sendHP(1,String(parseInt(client.hp[0]) - 1)); +} +window.redHPD = redHPD; + +/** + * Add prosecution health point. + */ +export function addHPP() { + client.sendHP(2,String(parseInt(client.hp[1]) + 1)); +} +window.addHPP = addHPP; + +/** + * Reduce prosecution health point. + */ +export function redHPP() { + client.sendHP(2,String(parseInt(client.hp[1]) - 1)); +} +window.redHPP = redHPP; + /** * Update background preview. */ @@ -1976,4 +2008,35 @@ let viewport = new Viewport(); $(document).ready(function(){ client.initialObservBBCode(); client.loadResources(); + }); + +// Create dialog and link to button +$( function() { + $( "#callmod_dialog" ).dialog({ + autoOpen: false, + resizable: false, + show: { + effect: "drop", + direction:"down", + duration: 500 + }, + hide: { + effect: "drop", + direction:"down", + duration: 500 + }, + height: "auto", + width: 400, + modal: true, + buttons: { + "Sure": function() { + client.sendZZ(""); + $( this ).dialog( "close" ); + }, + Cancel: function() { + $( this ).dialog( "close" ); + } + } + }); +}); \ No newline at end of file -- cgit From 67443e853de53562fc8d85a9655324e246ef22ba Mon Sep 17 00:00:00 2001 From: Qube Date: Sat, 21 Jul 2018 11:25:30 +0700 Subject: Add jquery ui mobile support + bbcode description in guide. --- webAO/client.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 83c34ab..10e8c81 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -1965,8 +1965,8 @@ function decodeBBCode(estring) { .replace(/\\n/g, "
") // Newline \n .replace(/\[(\/?)b\]/g, "<$1b>") // Bold [b][/b] .replace(/\[(\/?)i\]/g, "<$1i>") // Italic [i][/i] - .replace(/\[(\/?)del\]/g, "<$1del>") // Deleted [del][/del] - .replace(/\[(\/?)u\]/g, "<$1ins>") // Underline [u][/u] + .replace(/\[(\/?)s\]/g, "<$1del>") // Strikethrough [s][/s] + .replace(/\[(\/?)u\]/g, "<$1u>") // Underline [u][/u] .replace(/\[(\/?)sub\]/g, "<$1sub>") // Subscript [sub][/sub] .replace(/\[(\/?)sup\]/g, "<$1sup>") // Superscript [sup][/sup] .replace(/\[m=([#a-zA-Z0-9]+)\]/g, '') // Markup [m=#0ff] -- cgit From bdf8f9f3391ee80ec7a3d99d62f845ac7dfa0f7e Mon Sep 17 00:00:00 2001 From: Qube Date: Sat, 21 Jul 2018 14:39:06 +0700 Subject: Add option to edit server chat name (a.k.a Fake name) and adjust settings menu. --- webAO/client.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 10e8c81..bd9a840 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -141,7 +141,7 @@ class Client { * @param {string} message the message to send */ sendOOC(message) { - this.serv.send(`CT#web${this.playerID}#${escapeChat(encodeChat(message))}#%`); + this.serv.send(`CT#${escapeChat(encodeChat(document.getElementById("OOC_name").value))}#${escapeChat(encodeChat(message))}#%`); } /** @@ -252,6 +252,8 @@ class Client { * Load game resources. */ loadResources() { + // Set to playerID to server chat name + document.getElementById("OOC_name").value = "web" + this.playerID; // Load evidence array to select var evidence_select = document.getElementById("evi_select"); evidence_select.add(new Option("Custom", 0)); -- cgit From 4cf6fb8e8609dbf84149d0410393f9e3436fea91 Mon Sep 17 00:00:00 2001 From: Qube Date: Sat, 21 Jul 2018 21:07:06 +0700 Subject: Convert all character animation name to lowercase if user use asset from default asset site. --- webAO/client.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index bd9a840..18363aa 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -823,6 +823,8 @@ class Client { let me = this.me(); let emotes = this.emotes; let xhr = new XMLHttpRequest(); + let isOfficialAssets = (AO_HOST == "http://assets.aceattorneyonline.com/base/"); + xhr.withCredentials = false; document.getElementById("client_emo").innerHTML = ""; // Clear emote box xhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true); xhr.responseType = 'text'; @@ -843,14 +845,14 @@ class Client { esfxd = pinifile.SoundT[i]; } emotes[i] = { - desc: emoteinfo[0], - speaking: emoteinfo[1], - silent: emoteinfo[2], + desc: (isOfficialAssets)? emoteinfo[0].toLowerCase() : emoteinfo[0], + speaking: (isOfficialAssets)? emoteinfo[1].toLowerCase() : emoteinfo[1], + silent: (isOfficialAssets)? emoteinfo[2].toLowerCase() : emoteinfo[2], zoom: emoteinfo[3], - sfx: esfx, + sfx: (isOfficialAssets)? esfx.toLowerCase() : esfx, sfxdelay: esfxd, - button_off: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_off.png', - button_on: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_on.png' + button_off: AO_HOST + 'characters/' + ((isOfficialAssets)? escape(me.name).toLowerCase() : escape(me.name)) + '/emotions/button' + i + '_off.png', + button_on: AO_HOST + 'characters/' + ((isOfficialAssets)? escape(me.name).toLowerCase() : escape(me.name)) + '/emotions/button' + i + '_on.png' }; document.getElementById("client_emo").innerHTML += "" + emotes[i].desc + ""; } -- cgit From 2f18d565cb06de3826aee13fd07356adf29d9cbc Mon Sep 17 00:00:00 2001 From: gameboyprinter Date: Mon, 20 Aug 2018 18:46:00 -0500 Subject: refactor part 1 --- webAO/client.js | 683 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 359 insertions(+), 324 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 18363aa..feafde3 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -1,11 +1,11 @@ /* * Glorious webAO - * made by sD, refactored by oldmud0 + * made by sD, refactored by oldmud0 and Qubrick * credits to aleks for original idea and source -*/ + */ let queryDict = {}; -location.search.substr(1).split("&").forEach(function(item) { +location.search.substr(1).split("&").forEach(function (item) { queryDict[item.split("=")[0]] = item.split("=")[1] }); @@ -35,43 +35,43 @@ class Client { constructor(address) { this.serv = new WebSocket("ws://" + address); - this.serv.onopen = (evt) => this.onOpen(evt); - this.serv.onclose = (evt) => this.onClose(evt); + this.serv.onopen = (evt) => this.onOpen(evt); + this.serv.onclose = (evt) => this.onClose(evt); this.serv.onmessage = (evt) => this.onMessage(evt); - this.serv.onerror = (evt) => this.onError(evt); - + this.serv.onerror = (evt) => this.onError(evt); + this.flip = false; this.presentable = false; - - this.hp = [0,0]; + + this.hp = [0, 0]; this.playerID = 1; this.charID = -1; this.testimonyID = 0; this.chars = []; - this.emotes = []; + this.emotes = []; this.evidences = []; - + this.resources = { - "holdit":{ + "holdit": { "src": "misc/holdit.gif", "duration": 720 }, - "objection":{ + "objection": { "src": "misc/objection.gif", "duration": 720 }, - "takethat":{ + "takethat": { "src": "misc/takethat.gif", "duration": 840 }, - "witnesstestimony":{ + "witnesstestimony": { "src": "misc/witnesstestimony.gif", "duration": 1560, "sfx": "sounds/general/sfx-testimony.wav" }, - "crossexamination":{ + "crossexamination": { "src": "misc/crossexamination.gif", "duration": 1600, "sfx": "sounds/general/sfx-testimony2.wav" @@ -87,29 +87,29 @@ class Client { this.musicList = Object(); this.handlers = { - "MS": (args) => this.handleMS(args), - "CT": (args) => this.handleCT(args), - "MC": (args) => this.handleMC(args), - "RMC": (args) => this.handleRMC(args), - "CI": (args) => this.handleCI(args), - "SC": (args) => this.handleSC(args), - "EI": (args) => this.handleEI(args), - "LE": (args) => this.handleLE(args), - "EM": (args) => this.handleEM(args), - "SM": (args) => this.handleSM(args), - "music": (args) => this.handlemusic(args), - "DONE": (args) => this.handleDONE(args), - "BN": (args) => this.handleBN(args), - "NBG": (args) => this.handleNBG(args), - "HP": (args) => this.handleHP(args), - "RT": (args) => this.handleRT(args), - "ZZ": (args) => this.handleZZ(args), - "ID": (args) => this.handleID(args), - "PN": (args) => this.handlePN(args), - "SI": (args) => this.handleSI(args), + "MS": (args) => this.handleMS(args), + "CT": (args) => this.handleCT(args), + "MC": (args) => this.handleMC(args), + "RMC": (args) => this.handleRMC(args), + "CI": (args) => this.handleCI(args), + "SC": (args) => this.handleSC(args), + "EI": (args) => this.handleEI(args), + "LE": (args) => this.handleLE(args), + "EM": (args) => this.handleEM(args), + "SM": (args) => this.handleSM(args), + "music": (args) => this.handlemusic(args), + "DONE": (args) => this.handleDONE(args), + "BN": (args) => this.handleBN(args), + "NBG": (args) => this.handleNBG(args), + "HP": (args) => this.handleHP(args), + "RT": (args) => this.handleRT(args), + "ZZ": (args) => this.handleZZ(args), + "ID": (args) => this.handleID(args), + "PN": (args) => this.handlePN(args), + "SI": (args) => this.handleSI(args), "CharsCheck": (args) => this.handleCharsCheck(args), - "PV": (args) => this.handlePV(args), - "CHECK": (args) => {} + "PV": (args) => this.handlePV(args), + "CHECK": (args) => {} } this._lastTimeICReceived = new Date(0); @@ -128,12 +128,12 @@ class Client { myEmote() { return this.emotes[this.selectedEmote]; } - + /** * Gets the player's currently selected evidence if presentable. */ myEvidence() { - return (this.presentable)? this.selectedEvidence : 0; + return this.presentable ? this.selectedEvidence : 0; } /** @@ -153,8 +153,12 @@ class Client { * @param {string} side the name of the side in the background * @param {string} ssfxname the name of the sound effect * @param {string} zoom whether or not to zoom - * @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect + * @param {number} ssfxdelay the delay (in milliseconds) to play the sound effect * @param {string} objection the number of the shout to play + * @param {string} evidence the filename of evidence to show + * @param {number} flip change to 1 to reverse sprite for position changes + * @param {string} flash screen flash effect + * @param {string} color text color */ sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, evidence, flip, flash, color) { this.serv.send( @@ -163,7 +167,7 @@ class Client { `#${this.charID}#${ssfxdelay}#${selectedShout}#${evidence}#${flip}#${flash}#${color}#%` ); } - + /** * Sends add evidence command. * @param {string} evidence name @@ -173,10 +177,10 @@ class Client { sendPE(name, desc, img) { this.serv.send(`PE#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); } - + /** * Sends edit evidence command. - * @param {string} evidence id + * @param {number} evidence id * @param {string} evidence name * @param {string} evidence description * @param {string} evidence image filename @@ -184,24 +188,24 @@ class Client { sendEE(id, name, desc, img) { this.serv.send(`EE#${id}#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); } - + /** * Sends delete evidence command. - * @param {string} evidence id + * @param {number} evidence id */ sendDE(id) { this.serv.send(`DE#${id}#%`); } - + /** * Sends health point command. - * @param {int} side the position - * @param {int} hp the health point + * @param {number} side the position + * @param {number} hp the health point */ - sendHP(side,hp) { + sendHP(side, hp) { this.serv.send(`HP#${side}#${hp}#%`); } - + /** * Sends call mod command. * @param {string} message to mod @@ -209,13 +213,13 @@ class Client { sendZZ(msg) { this.serv.send(`ZZ#${msg}#%`); } - + /** * Sends testimony command. * @param {string} testimony type */ sendRT(testimony) { - if(this.chars[this.charID].side == "jud"){ + if (this.chars[this.charID].side == "jud") { this.serv.send(`RT#${testimony}#%`); } } @@ -247,7 +251,7 @@ class Client { this.serv.send("ID#webAO#2.4.5#%"); this.checkUpdater = setInterval(() => this.sendCheck(), 5000); } - + /** * Load game resources. */ @@ -255,37 +259,37 @@ class Client { // Set to playerID to server chat name document.getElementById("OOC_name").value = "web" + this.playerID; // Load evidence array to select - var evidence_select = document.getElementById("evi_select"); + const evidence_select = document.getElementById("evi_select"); evidence_select.add(new Option("Custom", 0)); - for(let i = 1; i <= evidence_arr.length; i++) { - evidence_select.add(new Option(evidence_arr[i - 1])); - } + evidence_arr.forEach(evidence => { + evidence_select.add(new Option(evidence)); + }); // Load background array to select - var background_select = document.getElementById("bg_select"); + const background_select = document.getElementById("bg_select"); background_select.add(new Option("Custom", 0)); - for(let i = 1; i <= background_arr.length; i++) { - background_select.add(new Option(background_arr[i - 1])); - } + background_arr.forEach(background => { + background_select.add(new Option(background)); + }); // Calculate gif duration of shouts - let shouts = ["holdit", "objection", "takethat"]; + const shouts = ["holdit", "objection", "takethat"]; for (let i = 0; i < shouts.length; i++) { let shout_src = AO_HOST + this.resources[shouts[i]]["src"]; - FileExist(shout_src, this.callbackLoadImageResources, shouts[i]); + FileExist(shout_src, this.callbackLoadImageResources, shouts[i]); } - + // Calculate gif duration of testimony - let testimony = ["witnesstestimony", "crossexamination"]; + const testimony = ["witnesstestimony", "crossexamination"]; for (let i = 0; i < testimony.length; i++) { - let testimony_src = AO_HOST + "themes/default/"+ testimony[i] +".gif"; - // Check iamge existed + const testimony_src = `${AO_HOST}themes/default/${testimony[i]}.gif`; + // Check image existed FileExist(testimony_src, this.callbackLoadImageResources, testimony[i]); // Check sfx existed FileExist(AO_HOST + this.resources[testimony[i]]["sfx"], this.callbackLoadSFXResources, testimony[i]); - } + } // TODO: Cache some resources - + } - + /** * Callback for image resources. * @param {boolean} result the image is existed or not @@ -293,21 +297,21 @@ class Client { * @param {string} src the url of resource */ callbackLoadImageResources(result, resource, src) { - if(result){ + if (result) { client.resources[resource]["src"] = src; - viewport.getAnimLength(src,client.callbackGetResourceLength, resource); - } + viewport.getAnimLength(src, client.callbackGetResourceLength, resource); + } } - + /** * Callback for animation duration resource * @param {integer} length the animation length * @param {string} resource the resource name */ callbackGetResourceLength(length, resource) { - client.resources[resource]["duration"] = length; + client.resources[resource]["duration"] = length; } - + /** * Callback for sfx resources. * @param {boolean} result the audio is existed or not @@ -315,38 +319,41 @@ class Client { * @param {string} src the url of resource */ callbackLoadSFXResources(result, resource, src) { - if(result){ + if (result) { client.resources[resource]["sfx"] = src; - } - } - + } + } + /** * Create observer to detect BBCode elements * then manipulate them. */ initialObservBBCode() { - var target = document.getElementById("client_inner_chat"); - var observer = new MutationObserver(function(mutations) { - mutations.forEach(function(mutation) { - var children = mutation.addedNodes; - if (children !== null) { - children.forEach( function(node) { - if (node.tagName == "C") { - node.style.color = node.getAttribute("a"); - } else if(node.tagName == "M"){ - if (node.hasAttribute('a')) { - node.style.backgroundColor = node.getAttribute("a"); - } else { - node.style.backgroundColor = "yellow"; - node.style.color = "black"; + const target = document.getElementById("client_inner_chat"); + const observer = new MutationObserver(function (mutations) { + mutations.forEach(function (mutation) { + var children = mutation.addedNodes; + if (children !== null) { + children.forEach(function (node) { + if (node.tagName == "C") { + node.style.color = node.getAttribute("a"); + } else if (node.tagName == "M") { + if (node.hasAttribute('a')) { + node.style.backgroundColor = node.getAttribute("a"); + } else { + node.style.backgroundColor = "yellow"; + node.style.color = "black"; + } } - } - }); - } - }); + }); + } + }); }); - var config = {attributes: true,childList: true}; - observer.observe(target,config); + const config = { + attributes: true, + childList: true + }; + observer.observe(target, config); } /** @@ -436,6 +443,15 @@ class Client { clearInterval(this.checkUpdater); } + /** + * + * @param {string} msg chat message to prepare for display + */ + prepChat(msg){ + // TODO: make this less awful + return decodeBBCode(escapeHtml(decodeChat(unescapeChat(msg)))); + } + /** * Handles an in-character chat message. * @param {*} args packet arguments @@ -452,7 +468,7 @@ class Client { name: args[3], speaking: "(b)" + escape(args[4]), silent: "(a)" + escape(args[4]), - content: decodeBBCode(escapeHtml(decodeChat(unescapeChat(args[5])))), // Escape HTML tag, Use BBCode Only! + content: prepChat(args[5]), // Escape HTML tag, Use BBCode Only! side: args[6], sound: escape(args[7]), type: args[8], @@ -522,7 +538,7 @@ class Client { // Music offset + drift from song loading music.totime = args[1]; music.offset = new Date().getTime() / 1000; - music.addEventListener('loadedmetadata', function() { + music.addEventListener('loadedmetadata', function () { music.currentTime += parseFloat(music.totime + (new Date().getTime() / 1000 - music.offset)).toFixed(3); music.play(); }, false); @@ -580,7 +596,7 @@ class Client { //serv.send("AE#" + (args[1] + 1) + "#%"); this.serv.send("RM#%"); } - + /** * Handles incoming evidence list, all evidences at once * item per packet. @@ -590,7 +606,7 @@ class Client { handleLE(args) { this.evidences = []; for (let i = 1; i < args.length - 1; i++) { - var arg = args[i].split("&"); + const arg = args[i].split("&"); this.evidences[i - 1] = { "name": escapeHtml(decodeChat(unescapeChat(arg[0]))), "desc": escapeHtml(decodeChat(unescapeChat(arg[1]))), @@ -598,14 +614,15 @@ class Client { "icon": AO_HOST + "evidence/" + escape(arg[2]) } } - - var evidence_box = document.getElementById("evidences"); + + const evidence_box = document.getElementById("evidences"); evidence_box.innerHTML = ""; - for(let i = 1; i <= this.evidences.length; i++){ - evidence_box.innerHTML += '' + this.evidences[i - 1].name +
-				''; + for (let i = 1; i <= this.evidences.length; i++) { + evidence_box.innerHTML += `${this.evidences[i - 1].name}`; } } @@ -634,38 +651,41 @@ class Client { */ handleSM(args) { document.getElementById("client_loadingtext").innerHTML = "Loading Music "; - let hmusiclist = document.getElementById("client_musiclist"), flagAudio = false; - + const hmusiclist = document.getElementById("client_musiclist"); + let flagAudio = false; + for (let i = 1; i < args.length - 1; i++) { // Check when found the song for the first time - if(/\.(?:wav|mp3|mp4|ogg|mid)$/i.test(args[i]) && !flagAudio){ + if (/\.(?:wav|mp3|mp4|ogg|opus)$/i.test(args[i]) && !flagAudio) { flagAudio = true; } - - if(flagAudio) { + + if (flagAudio) { // After reached the audio put everything in the music list let newentry = document.createElement("OPTION"); newentry.text = args[i]; hmusiclist.options.add(newentry); - + } else { // Create area button let newarea = document.createElement("SPAN"); newarea.className = "location-box"; - newarea.textContent = args[i]; - newarea.onclick = function(){ area_click(this) }; + newarea.textContent = args[i]; + newarea.onclick = function () { + area_click(this) + }; document.getElementById("areas").appendChild(newarea); } } - + // Move first audio title from area box to music list let area_box = document.getElementById("areas"); let audio_title = document.createElement("OPTION"); audio_title.text = area_box.lastChild.textContent; hmusiclist.insertBefore(audio_title, hmusiclist.firstChild); area_box.removeChild(area_box.lastChild); // Remove from arae box - - this.serv.send("RD#%"); + + this.serv.send("RD#%"); } /** @@ -696,19 +716,19 @@ class Client { */ handleBN(args) { viewport.bgname = escape(args[1]); - let bg_index = getIndexFromSelect("bg_select", escape(args[1])); + const bg_index = getIndexFromSelect("bg_select", escape(args[1])); document.getElementById("bg_select").selectedIndex = bg_index; updateBackgroundPreview(); - if(bg_index == 0){ + if (bg_index == 0) { document.getElementById("bg_filename").value = args[1]; } document.getElementById("bg_preview").src = AO_HOST + 'background/' + escape(args[1]) + "/defenseempty.png"; - if(this.charID == -1){ + if (this.charID == -1) { changeBackground("jud"); } else { changeBackground(this.chars[this.charID].side); } - + } handleNBG(args) { @@ -720,18 +740,22 @@ class Client { * @param {Array} args packet arguments */ handleHP(args) { - let percent_hp = args[2] * 10; + const percent_hp = args[2] * 10; if (args[1] == 1) { // Def hp this.hp[0] = args[2]; - $("#client_defense_hp > .health-bar").animate({ 'width': percent_hp + "%" }, 500); + $("#client_defense_hp > .health-bar").animate({ + 'width': percent_hp + "%" + }, 500); } else { // Pro hp this.hp[1] = args[2]; - $("#client_prosecutor_hp > .health-bar").animate({ 'width': percent_hp + "%" }, 500); - } + $("#client_prosecutor_hp > .health-bar").animate({ + 'width': percent_hp + "%" + }, 500); + } } - + /** * Handles a testimony states. * @param {Array} args packet arguments @@ -746,7 +770,7 @@ class Client { } viewport.initTestimonyUpdater(); } - + /** * Handles a call mod message. * @param {Array} args packet arguments @@ -758,7 +782,7 @@ class Client { oocLog.scrollTop = oocLog.scrollHeight; } } - + /** * Handles the issuance of a player ID by the server. * @param {Array} args packet arguments @@ -809,7 +833,7 @@ class Client { if (i % CHAR_SELECT_WIDTH == 0) { document.getElementById("client_chartable").appendChild(tr); } - } + } //changeBackground("def"); } @@ -823,7 +847,6 @@ class Client { let me = this.me(); let emotes = this.emotes; let xhr = new XMLHttpRequest(); - let isOfficialAssets = (AO_HOST == "http://assets.aceattorneyonline.com/base/"); xhr.withCredentials = false; document.getElementById("client_emo").innerHTML = ""; // Clear emote box xhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true); @@ -844,23 +867,29 @@ class Client { if (typeof pinifile.SoundT !== 'undefined') { esfxd = pinifile.SoundT[i]; } + // Make sure the asset server is case insensitive, or that everything on it is lowercase emotes[i] = { - desc: (isOfficialAssets)? emoteinfo[0].toLowerCase() : emoteinfo[0], - speaking: (isOfficialAssets)? emoteinfo[1].toLowerCase() : emoteinfo[1], - silent: (isOfficialAssets)? emoteinfo[2].toLowerCase() : emoteinfo[2], + desc: emoteinfo[0].toLowerCase(), + speaking: emoteinfo[1].toLowerCase(), + silent: emoteinfo[2].toLowerCase(), zoom: emoteinfo[3], - sfx: (isOfficialAssets)? esfx.toLowerCase() : esfx, + sfx: esfx.toLowerCase(), sfxdelay: esfxd, - button_off: AO_HOST + 'characters/' + ((isOfficialAssets)? escape(me.name).toLowerCase() : escape(me.name)) + '/emotions/button' + i + '_off.png', - button_on: AO_HOST + 'characters/' + ((isOfficialAssets)? escape(me.name).toLowerCase() : escape(me.name)) + '/emotions/button' + i + '_on.png' + button_off: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_off.png`, + button_on: AO_HOST + `'characters/${escape(me.name).toLowerCase()}/emotions/button${i}_on.png` }; - document.getElementById("client_emo").innerHTML += "" + emotes[i].desc + ""; + document.getElementById("client_emo").innerHTML += + `${emotes[i].desc}`; } pickemotion(1); } }; xhr.send(); - } + } } class Viewport { @@ -901,7 +930,7 @@ class Viewport { this.testimonyUpdater = null; this.bgname = "gs4"; - + this.testimonyTimer = 0; this.shoutTimer = 0; this.textTimer = 0; @@ -949,39 +978,39 @@ class Viewport { clearTimeout(this.updater); //If preanim existed then determine the length if (chatmsg.preanim != "-") { - chatmsg.preanimdelay = this.getAnimLength(AO_HOST + 'characters/' + escape(chatmsg.name) + '/' + chatmsg.preanim + '.gif',this.initUpdater); + chatmsg.preanimdelay = this.getAnimLength(`${AO_HOST}characters/${escape(chatmsg.name)}/${chatmsg.preanim}.gif`, this.initUpdater); } else { - this.initUpdater(0) + this.initUpdater(0); } } - + /** * Intialize updater - * @param {int} animdelay the length of pre-animation + * @param {number} animdelay the length of pre-animation */ - initUpdater(animdelay){ - viewport.chatmsg.preanimdelay = parseInt(animdelay); + initUpdater(animdelay) { + viewport.chatmsg.preanimdelay = parseInt(animdelay); viewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL); } - + /** * Intialize testimony updater */ - initTestimonyUpdater(){ - if(client.testimonyID > 0){ + initTestimonyUpdater() { + if (client.testimonyID > 0) { let testimony = ""; if (client.testimonyID == 1) { - testimony = "witnesstestimony"; + testimony = "witnesstestimony"; } else if (client.testimonyID == 2) { testimony = "crossexamination"; } (new Audio(client.resources[testimony]["sfx"])).play(); this.testimonyTimer = 0; document.getElementById("client_testimony").src = client.resources[testimony]["src"]; - this.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL); + this.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL); } } - + /** * Gets animation length. * @param {string} filename the animation file name @@ -1002,25 +1031,25 @@ class Viewport { }); request.send(); } - + /** * Updates the testimony overaly */ - updateTestimony(){ + updateTestimony() { //Update timer this.testimonyTimer = this.testimonyTimer + UPDATE_INTERVAL; - + if (client.testimonyID == 1) { //Witness Testimony - if (this.testimonyTimer >= client.resources["witnesstestimony"]["duration"]){ + if (this.testimonyTimer >= client.resources["witnesstestimony"]["duration"]) { //Finish this.disposeTestimony(); } else { this.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL); - } + } } else if (client.testimonyID == 2) { //Cross Examination - if (this.testimonyTimer >= client.resources["crossexamination"]["duration"]){ + if (this.testimonyTimer >= client.resources["crossexamination"]["duration"]) { //Finish this.disposeTestimony(); } else { @@ -1030,17 +1059,17 @@ class Viewport { this.disposeTestimony(); } } - + /** * Dispose the testimony overlay */ - disposeTestimony(){ + disposeTestimony() { client.testimonyID = 0; this.testimonyTimer = 0; document.getElementById("client_testimony").src = "misc/placeholder.gif"; clearTimeout(this.testimonyUpdater); - } - + } + /** * Updates the chatbox based on the given text. * @@ -1048,12 +1077,12 @@ class Viewport { */ updateText() { // Flip the character - if (this.chatmsg.flip == 1){ - document.getElementById("client_char").style.transform = "scaleX(-1)"; + if (this.chatmsg.flip == 1) { + document.getElementById("client_char").style.transform = "scaleX(-1)"; } else { document.getElementById("client_char").style.transform = "scaleX(1)"; } - + if (this._animating) { this.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL); } @@ -1085,15 +1114,17 @@ class Viewport { this.chatmsg.startpreanim = true; } - if(this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) { + if (this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) { // Effect stuff - if (this.chatmsg.flash == 2){ + if (this.chatmsg.flash == 2) { //Shake screen this.sfxaudio.pause(); this.sfxplayed = 1; this.sfxaudio.src = AO_HOST + "sounds/general/sfx-stab.wav"; this.sfxaudio.play(); - $('#client_gamewindow').effect( "shake",{"direction":"up"}); + $('#client_gamewindow').effect("shake", { + "direction": "up" + }); } else if (this.chatmsg.flash == 1) { //Flash screen document.getElementById("client_background").style.backgroundColor = "white"; @@ -1103,9 +1134,9 @@ class Viewport { this.sfxaudio.play(); $('#client_gamewindow').effect("pulsate"); } - + //Pre-animation stuff - if(this.chatmsg.preanimdelay > 0){ + if (this.chatmsg.preanimdelay > 0) { document.getElementById("client_shout").src = "misc/placeholder.gif"; changeBackground(this.chatmsg.side); document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.preanim + ".gif"; @@ -1114,31 +1145,33 @@ class Viewport { this.chatmsg.startspeaking = true; } else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) { if (this.chatmsg.startspeaking) { - if(this.chatmsg.evidence > 0){ + if (this.chatmsg.evidence > 0) { // Prepare evidence - document.getElementById("client_evi").style.backgroundImage = "url('"+ client.evidences[this.chatmsg.evidence - 1].icon +"')"; - - if (this.chatmsg.side == 'def'){ + document.getElementById("client_evi").style.backgroundImage = "url('" + client.evidences[this.chatmsg.evidence - 1].icon + "')"; + + if (this.chatmsg.side == 'def') { // Only def show evidence on right document.getElementById("client_evi").style.right = "1.5em"; document.getElementById("client_evi").style.left = "initial"; - $( "#client_evi" ).animate({ + $("#client_evi").animate({ height: "30%", opacity: 1 - }, 250 ); + }, 250); } else { document.getElementById("client_evi").style.right = "initial"; document.getElementById("client_evi").style.left = "1.5em"; - $( "#client_evi" ).animate({ + $("#client_evi").animate({ height: "30%", opacity: 1 - }, 250 ); + }, 250); } } - - $("#client_name").toggle( "fade" ); - $("#client_chat").toggle("drop",{"direction":"down"}); - if(this.chatmsg.preanimdelay == 0){ + + $("#client_name").toggle("fade"); + $("#client_chat").toggle("drop", { + "direction": "down" + }); + if (this.chatmsg.preanimdelay == 0) { document.getElementById("client_shout").src = "misc/placeholder.gif"; changeBackground(this.chatmsg.side); } @@ -1183,7 +1216,7 @@ class Viewport { } } } - + if (!this.sfxplayed && this.chatmsg.snddelay + this.shoutTimer >= this.textTimer) { this.sfxaudio.pause(); this.sfxplayed = 1; @@ -1206,7 +1239,7 @@ class INI { let value = {}; let lines = data.split(/\r\n|\r|\n/); let section = null; - lines.forEach(function(line) { + lines.forEach(function (line) { if (regex.comment.test(line)) { return; } else if (line.length == 0) { @@ -1249,7 +1282,7 @@ export function onEnter(event) { let mychar = client.me(); let myemo = client.myEmote(); let myevi = client.myEvidence(); - let myflip = ((client.flip)? 1:0); + let myflip = ((client.flip) ? 1 : 0); let mycolor = document.getElementById("textcolor").value; let ssfxname = "0"; let ssfxdelay = "0"; @@ -1276,7 +1309,7 @@ function resetICParams() { if (selectedShout) { document.getElementById("button_" + selectedShout).className = "client_button"; selectedShout = 0; - } + } } /** @@ -1294,7 +1327,7 @@ window.musiclist_click = musiclist_click; * @param {MouseEvent} event */ export function area_click(el) { - let playtrack = el.textContent; + let playtrack = el.textContent; client.sendMusicChange(playtrack); } window.area_click = area_click; @@ -1357,14 +1390,14 @@ export function demoError(image) { window.demoError = demoError; /** - * Checks if an file exists at the specified URI. + * Checks if a file exists at the specified URI. * @param {string} url the URI to be checked * @param {function} callback the function to be called when finished * @param {object} param */ -function FileExist(url,callback,param) { +function fileExists(url, callback, param) { var xhttp = new XMLHttpRequest(); - xhttp.onreadystatechange = function() { + xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { callback(true, param, url); } else { @@ -1431,20 +1464,20 @@ function changeBackground(position) { * @param {boolean} result the image is existed or not * @param {string} position the position to change into */ -function callbackChangeBackground(result,position) { +function callbackChangeBackground(result, position) { let bgfolder = viewport.bgFolder(); - if (position == "def"){ - if(result){ + if (position == "def") { + if (result) { document.getElementById("client_bench").src = bgfolder + "defensedesk.png" - }else{ + } else { document.getElementById("client_bench").src = bgfolder + "bancodefensa.png" } } else { - if(result){ + if (result) { document.getElementById("client_bench").src = bgfolder + "prosecutiondesk.png" } else { document.getElementById("client_bench").src = bgfolder + "bancoacusacion.png" - } + } } } @@ -1507,7 +1540,7 @@ function appendICLog(toadd, name = "", time = new Date()) { * Requests to play as a character. * @param {number} ccharacter the character ID; if this is a large number, then spectator is chosen instead. */ -export function pickchar(ccharacter) { +export function pickChar(ccharacter) { if (ccharacter < 1000) { client.sendCharacter(ccharacter); } else { @@ -1517,46 +1550,46 @@ export function pickchar(ccharacter) { document.getElementById("client_emo").style.display = "none"; } } -window.pickchar = pickchar; +window.pickChar = pickChar; /** * Highlights and selects an emotion for in-character chat. * @param {string} emo the new emotion to be selected */ -export function pickemotion(emo) { +export function pickEmotion(emo) { if (client.selectedEmote != -1) { document.getElementById("emo_" + client.selectedEmote).src = client.myEmote().button_off; } client.selectedEmote = emo document.getElementById("emo_" + emo).src = client.myEmote().button_on; } -window.pickemotion = pickemotion; +window.pickEmotion = pickEmotion; /** * Highlights and selects an evidence for in-character chat. * @param {string} evidence the evidence to be presented */ -export function pickevidence(evidence) { - if (client.selectedEvidence != evidence) { +export function pickEvidence(evidence) { + if (client.selectedEvidence !== evidence) { //Update selected evidence - if(client.selectedEvidence > 0){ + if (client.selectedEvidence > 0) { document.getElementById("evi_" + client.selectedEvidence).className = "client_button"; } document.getElementById("evi_" + evidence).className = "client_button dark"; client.selectedEvidence = evidence; - + // Show evidence on information window document.getElementById("evi_name").value = client.evidences[evidence - 1].name; document.getElementById("evi_desc").value = client.evidences[evidence - 1].desc; //Update Icon - let icon_id = getIndexFromSelect("evi_select", client.evidences[evidence - 1].filename); + let icon_id = getIndexFromSelect("evi_select", client.evidences[evidence - 1].filename); document.getElementById("evi_select").selectedIndex = icon_id; - if (icon_id == 0){ + if (icon_id == 0) { document.getElementById("evi_filename").value = client.evidences[evidence - 1].filename; } updateEvidenceIcon(); - + // Update button document.getElementById("evi_add").className = "client_button hover_button inactive"; document.getElementById("evi_edit").className = "client_button hover_button"; @@ -1566,60 +1599,60 @@ export function pickevidence(evidence) { cancelevidence(); } } -window.pickevidence = pickevidence; +window.pickEvidence = pickEvidence; /** * Add evidence. */ -export function addevidence() { +export function addEvidence() { let evidence_select = document.getElementById('evi_select'); - client.sendPE( document.getElementById('evi_name').value, + client.sendPE(document.getElementById('evi_name').value, document.getElementById('evi_desc').value, - (evidence_select.selectedIndex == 0)? - document.getElementById('evi_filename').value : - evidence_select.options[evidence_select.selectedIndex].text - ); + (evidence_select.selectedIndex == 0) ? + document.getElementById('evi_filename').value : + evidence_select.options[evidence_select.selectedIndex].text + ); cancelevidence(); } -window.addevidence = addevidence; +window.addEvidence = addEvidence; /** * Edit selected evidence. */ -export function editevidence() { +export function editEvidence() { let evidence_select = document.getElementById('evi_select'); let id = parseInt(client.selectedEvidence) - 1; - client.sendEE( id, + client.sendEE(id, document.getElementById('evi_name').value, document.getElementById('evi_desc').value, - (evidence_select.selectedIndex == 0)? - document.getElementById('evi_filename').value : - evidence_select.options[evidence_select.selectedIndex].text - ); + (evidence_select.selectedIndex == 0) ? + document.getElementById('evi_filename').value : + evidence_select.options[evidence_select.selectedIndex].text + ); cancelevidence(); } -window.editevidence = editevidence; +window.editEvidence = editEvidence; /** * Delete selected evidence. */ -export function delevidence() { +export function deleteEvidence() { let id = parseInt(client.selectedEvidence) - 1; client.sendDE(id); cancelevidence(); } -window.delevidence = delevidence; +window.deleteEvidence = deleteEvidence; /** * Cancel evidence selection. */ -export function cancelevidence() { +export function cancelEvidence() { //Clear evidence data - if(client.selectedEvidence > 0){ + if (client.selectedEvidence > 0) { document.getElementById("evi_" + client.selectedEvidence).className = "client_button"; } client.selectedEvidence = 0; - + // Clear evidence on information window document.getElementById("evi_select").selectedIndex = 0; updateEvidenceIcon(); // Update icon widget @@ -1627,14 +1660,14 @@ export function cancelevidence() { document.getElementById("evi_name").value = ""; document.getElementById("evi_desc").value = ""; document.getElementById("evi_icon").style.backgroundImage = "url('misc/empty.png')"; //Clear icon - + // Update button document.getElementById("evi_add").className = "client_button hover_button"; document.getElementById("evi_edit").className = "client_button hover_button inactive"; document.getElementById("evi_cancel").className = "client_button hover_button inactive"; document.getElementById("evi_del").className = "client_button hover_button inactive"; } -window.cancelevidence = cancelevidence; +window.cancelEvidence = cancelEvidence; /** * Find index of anything in select box. @@ -1642,14 +1675,14 @@ window.cancelevidence = cancelevidence; * @param {string} value the value that need to be compared */ export function getIndexFromSelect(select_box, value) { - //Find if icon alraedy existed in select box - let select_element = document.getElementById(select_box); - for (let i = 1; i < select_element.length; ++i){ - if (select_element.options[i].value == value){ - return i; - } + //Find if icon alraedy existed in select box + let select_element = document.getElementById(select_box); + for (let i = 1; i < select_element.length; ++i) { + if (select_element.options[i].value == value) { + return i; } - return 0; + } + return 0; } window.getIndexFromSelect = getIndexFromSelect; @@ -1660,13 +1693,13 @@ export function updateEvidenceIcon() { let evidence_select = document.getElementById("evi_select"); let evidence_filename = document.getElementById("evi_filename"); let evidence_iconbox = document.getElementById("evi_icon"); - - if (evidence_select.selectedIndex == 0) { + + if (evidence_select.selectedIndex === 0) { evidence_filename.style.display = "initial"; - evidence_iconbox.style.backgroundImage = "url('" + AO_HOST + 'evidence/' + evidence_filename.value + "')"; - } else { + evidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_filename.value})`; + } else { evidence_filename.style.display = "none"; - evidence_iconbox.style.backgroundImage = "url('" + AO_HOST + 'evidence/' + evidence_select.value + "')" ; + evidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_select.value})`; } } window.updateEvidenceIcon = updateEvidenceIcon; @@ -1675,7 +1708,7 @@ window.updateEvidenceIcon = updateEvidenceIcon; * Update evidence icon. */ export function updateActionCommands(side) { - if(side == "jud"){ + if (side == "jud") { document.getElementById("judge_action").style.display = "inline-table"; document.getElementById("no_action").style.display = "none"; } else { @@ -1683,11 +1716,11 @@ export function updateActionCommands(side) { document.getElementById("judge_action").style.display = "none"; } //Update role selector - for(let i = 0, role_select = document.getElementById("role_select").options; i < role_select.length; i++){ - if(side == role_select[i].value){ - role_select.selectedIndex = i; - return; - } + for (let i = 0, role_select = document.getElementById("role_select").options; i < role_select.length; i++) { + if (side == role_select[i].value) { + role_select.selectedIndex = i; + return; + } } } window.updateActionCommands = updateActionCommands; @@ -1696,14 +1729,15 @@ window.updateActionCommands = updateActionCommands; * Change background via OOC. */ export function changeBackgroundOOC() { - let filename = "", background_select = document.getElementById("bg_select") - , bg_command = document.getElementById("bg_command").value; + let filename = "", + background_select = document.getElementById("bg_select"), + bg_command = document.getElementById("bg_command").value; if (background_select.selectedIndex == 0) { - filename = document.getElementById("bg_filename").value; - } else{ + filename = document.getElementById("bg_filename").value; + } else { filename = background_select.value; } - client.sendOOC("/" + bg_command.replace("$1",filename)); + client.sendOOC("/" + bg_command.replace("$1", filename)); } window.changeBackgroundOOC = changeBackgroundOOC; @@ -1711,10 +1745,10 @@ window.changeBackgroundOOC = changeBackgroundOOC; * Change role via OOC. */ export function changeRoleOOC() { - let role_select = document.getElementById("role_select") - , role_command = document.getElementById("role_command").value; - - client.sendOOC("/" + role_command.replace("$1",role_select.value)); + let role_select = document.getElementById("role_select"), + role_command = document.getElementById("role_command").value; + + client.sendOOC("/" + role_command.replace("$1", role_select.value)); updateActionCommands(role_select.value); } window.changeRoleOOC = changeRoleOOC; @@ -1722,7 +1756,7 @@ window.changeRoleOOC = changeRoleOOC; /** * Random character via OOC. */ -export function randomCharacterOOC() { +export function randomCharacterOOC() { client.sendOOC("/" + document.getElementById("randomchar_command").value); } window.randomCharacterOOC = randomCharacterOOC; @@ -1730,56 +1764,56 @@ window.randomCharacterOOC = randomCharacterOOC; /** * Call mod. */ -export function callmod() { - $( "#callmod_dialog" ).dialog( "open" ); +export function callMod() { + $("#callmod_dialog").dialog("open"); } -window.callmod = callmod; +window.callMod = callMod; /** - * Decalre witness testimony. + * Declare witness testimony. */ -export function initwt() { +export function initWT() { client.sendRT("testimony1"); } -window.initwt = initwt; +window.initWT = initWT; /** - * Decalre cross examination. + * Declare cross examination. */ -export function initce() { +export function initCE() { client.sendRT("testimony2"); } -window.initce = initce; +window.initCE = initCE; /** - * Add defense health point. + * Increment defense health point. */ -export function addHPD() { - client.sendHP(1,String(parseInt(client.hp[0]) + 1)); +export function addHPD() { + client.sendHP(1, String(parseInt(client.hp[0]) + 1)); } window.addHPD = addHPD; /** - * Reduce defense health point. + * Decrement defense health point. */ -export function redHPD() { - client.sendHP(1,String(parseInt(client.hp[0]) - 1)); +export function redHPD() { + client.sendHP(1, String(parseInt(client.hp[0]) - 1)); } window.redHPD = redHPD; /** - * Add prosecution health point. + * Increment prosecution health point. */ -export function addHPP() { - client.sendHP(2,String(parseInt(client.hp[1]) + 1)); +export function addHPP() { + client.sendHP(2, String(parseInt(client.hp[1]) + 1)); } window.addHPP = addHPP; /** - * Reduce prosecution health point. + * Decrement prosecution health point. */ -export function redHPP() { - client.sendHP(2,String(parseInt(client.hp[1]) - 1)); +export function redHPP() { + client.sendHP(2, String(parseInt(client.hp[1]) - 1)); } window.redHPP = redHPP; @@ -1790,7 +1824,7 @@ export function updateBackgroundPreview() { let background_select = document.getElementById("bg_select"); let background_filename = document.getElementById("bg_filename"); let background_preview = document.getElementById("bg_preview"); - + if (background_select.selectedIndex == 0) { background_filename.style.display = "initial"; background_preview.src = AO_HOST + 'background/' + background_filename.value + "/defenseempty.png"; @@ -1806,7 +1840,7 @@ window.updateBackgroundPreview = updateBackgroundPreview; * If the same effect button is selected, then the effect is canceled. * @param {string} effect the new effect to be selected */ -export function toggleaffect(effect) { +export function toggleEffect(effect) { if (effect == selectedEffect) { document.getElementById("button_effect_" + effect).className = "client_button"; selectedEffect = 0; @@ -1818,12 +1852,12 @@ export function toggleaffect(effect) { selectedEffect = effect; } } -window.toggleaffect = toggleaffect; +window.toggleEffect = toggleEffect; /** * Toggle flip for in-character chat. */ -export function toggleflip() { +export function toggleFlip() { if (client.flip) { document.getElementById("button_flip").className = "client_button"; } else { @@ -1831,12 +1865,12 @@ export function toggleflip() { } client.flip = !client.flip; } -window.toggleflip = toggleflip; +window.toggleFlip = toggleFlip; /** * Toggle presentable for presenting evidence in-character chat. */ -export function togglepresent() { +export function togglePresent() { if (client.presentable) { document.getElementById("button_present").className = "client_button"; } else { @@ -1844,13 +1878,13 @@ export function togglepresent() { } client.presentable = !client.presentable; } -window.togglepresent = togglepresent; +window.togglePresent = togglePresent; /** * Highlights and selects a menu. * @param {string} menu the menu to be selected */ -export function togglemenu(menu) { +export function toggleMenu(menu) { if (menu != selectedMenu) { document.getElementById("menu_" + menu).className = "menu_icon active"; document.getElementById("content_" + menu).className = "menu_content active"; @@ -1859,14 +1893,14 @@ export function togglemenu(menu) { selectedMenu = menu; } } -window.togglemenu = togglemenu; +window.toggleMenu = toggleMenu; /** * Highlights and selects a shout for in-character chat. * If the same shout button is selected, then the shout is canceled. * @param {string} shout the new shout to be selected */ -export function toggleshout(shout) { +export function toggleShout(shout) { if (shout == selectedShout) { document.getElementById("button_" + shout).className = "client_button"; selectedShout = 0; @@ -1878,7 +1912,7 @@ export function toggleshout(shout) { selectedShout = shout; } } -window.toggleshout = toggleshout; +window.toggleShout = toggleShout; /** * Escapes a string to be HTML-safe. @@ -1927,13 +1961,14 @@ function encodeChat(estring) { let selectedEncoding = document.getElementById("client_encoding").value; if (selectedEncoding == "unicode") { //Source: https://gist.github.com/mathiasbynens/1243213 - return estring.replace(/[^\0-~]/g, function(ch) { - return "\\u" + ("000" + ch.charCodeAt().toString(16)).slice(-4); }); - } else if (selectedEncoding == "utf16"){ + return estring.replace(/[^\0-~]/g, function (ch) { + return "\\u" + ("000" + ch.charCodeAt().toString(16)).slice(-4); + }); + } else if (selectedEncoding == "utf16") { //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String - var buffer = new ArrayBuffer(estring.length*2); + var buffer = new ArrayBuffer(estring.length * 2); var result = new Uint16Array(buffer); - for (var i=0, strLen=estring.length; i < strLen; i++) { + for (var i = 0, strLen = estring.length; i < strLen; i++) { result[i] = estring.charCodeAt(i); } return String(result); @@ -1950,9 +1985,10 @@ function decodeChat(estring) { let selectedDecoding = document.getElementById("client_decoding").value; if (selectedDecoding == "unicode") { //Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode - return estring.replace(/\\u([\d\w]{1,})/gi, function (match, group) { - return String.fromCharCode(parseInt(group, 16)); } ); - } else if (selectedDecoding == "utf16"){ + return estring.replace(/\\u([\d\w]{1,})/gi, function (match, group) { + return String.fromCharCode(parseInt(group, 16)); + }); + } else if (selectedDecoding == "utf16") { //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String return String.fromCharCode.apply(null, new Uint16Array(estring.split(","))); } else { @@ -1981,22 +2017,21 @@ function decodeBBCode(estring) { // TODO: Possibly safe to remove, since we are using a transpiler. -if (typeof(String.prototype.trim) === "undefined") -{ - String.prototype.trim = function() - { - return String(this).replace(/^\s+|\s+$/g, ''); - }; +if (typeof (String.prototype.trim) === "undefined") { + String.prototype.trim = function () { + return String(this).replace(/^\s+|\s+$/g, ''); + }; } // Used for HDID calculation. -String.prototype.hashCode = function() { - var hash = 0, i, chr; +String.prototype.hashCode = function () { + var hash = 0, + i, chr; if (this.length === 0) return hash; for (i = 0; i < this.length; i++) { - chr = this.charCodeAt(i); - hash = ((hash << 5) - hash) + chr; - hash |= 0; // Convert to 32bit integer + chr = this.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer } return hash; }; @@ -2009,37 +2044,37 @@ String.prototype.hashCode = function() { let client = new Client(serverIP); let viewport = new Viewport(); -$(document).ready(function(){ +$(document).ready(function () { client.initialObservBBCode(); - client.loadResources(); - + client.loadResources(); + }); // Create dialog and link to button -$( function() { - $( "#callmod_dialog" ).dialog({ +$(function () { + $("#callmod_dialog").dialog({ autoOpen: false, resizable: false, show: { effect: "drop", - direction:"down", + direction: "down", duration: 500 }, hide: { effect: "drop", - direction:"down", + direction: "down", duration: 500 }, height: "auto", width: 400, modal: true, buttons: { - "Sure": function() { + Sure: function () { client.sendZZ(""); - $( this ).dialog( "close" ); + $(this).dialog("close"); }, - Cancel: function() { - $( this ).dialog( "close" ); + Cancel: function () { + $(this).dialog("close"); } } }); -- cgit From 077fcf719b1a9383b4170f33a77c95024d6f7188 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Mon, 3 Sep 2018 22:48:46 -0500 Subject: Continue code cleanup --- webAO/client.js | 176 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 88 insertions(+), 88 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index feafde3..dd1d7fa 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -14,7 +14,7 @@ location.search.substr(1).split("&").forEach(function (item) { const serverIP = queryDict.ip; let mode = queryDict.mode; -const AO_HOST = queryDict.asset || "http://assets.aceattorneyonline.com/base/"; +const AO_HOST = queryDict.asset || "http://s3.wasabisys.com/webao/base/"; const MUSIC_HOST = AO_HOST + "sounds/music/"; const BAR_WIDTH = 90; const BAR_HEIGHT = 20; @@ -248,7 +248,7 @@ class Client { */ joinServer() { this.serv.send(`HI#${navigator.userAgent.hashCode()}#%`); - this.serv.send("ID#webAO#2.4.5#%"); + this.serv.send("ID#webAO#2.3#%"); this.checkUpdater = setInterval(() => this.sendCheck(), 5000); } @@ -257,13 +257,16 @@ class Client { */ loadResources() { // Set to playerID to server chat name + // TODO: Make a text box for this! document.getElementById("OOC_name").value = "web" + this.playerID; + // Load evidence array to select const evidence_select = document.getElementById("evi_select"); evidence_select.add(new Option("Custom", 0)); evidence_arr.forEach(evidence => { evidence_select.add(new Option(evidence)); }); + // Load background array to select const background_select = document.getElementById("bg_select"); background_select.add(new Option("Custom", 0)); @@ -274,7 +277,7 @@ class Client { const shouts = ["holdit", "objection", "takethat"]; for (let i = 0; i < shouts.length; i++) { let shout_src = AO_HOST + this.resources[shouts[i]]["src"]; - FileExist(shout_src, this.callbackLoadImageResources, shouts[i]); + fileExists(shout_src, this.callbackLoadImageResources, shouts[i]); } // Calculate gif duration of testimony @@ -282,9 +285,9 @@ class Client { for (let i = 0; i < testimony.length; i++) { const testimony_src = `${AO_HOST}themes/default/${testimony[i]}.gif`; // Check image existed - FileExist(testimony_src, this.callbackLoadImageResources, testimony[i]); + fileExists(testimony_src, this.callbackLoadImageResources, testimony[i]); // Check sfx existed - FileExist(AO_HOST + this.resources[testimony[i]]["sfx"], this.callbackLoadSFXResources, testimony[i]); + fileExists(AO_HOST + this.resources[testimony[i]]["sfx"], this.callbackLoadSFXResources, testimony[i]); } // TODO: Cache some resources @@ -332,7 +335,7 @@ class Client { const target = document.getElementById("client_inner_chat"); const observer = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { - var children = mutation.addedNodes; + const children = mutation.addedNodes; if (children !== null) { children.forEach(function (node) { if (node.tagName == "C") { @@ -460,7 +463,7 @@ class Client { // TODO: this if-statement might be a bug. if (args[4] != viewport.chatmsg.content) { document.getElementById("client_inner_chat").innerHTML = ""; - let chatmsg = { + const chatmsg = { // pre: escape(args[2]), character: -1, // Will do a linear search preanim: escape(args[2]), // XXX: why again? @@ -579,7 +582,7 @@ class Client { "desc": chargs[1], "evidence": chargs[3], "icon": AO_HOST + "characters/" + escape(chargs[0]) + "/char_icon.png" - } + }; } this.serv.send("RM#%"); } @@ -612,7 +615,7 @@ class Client { "desc": escapeHtml(decodeChat(unescapeChat(arg[1]))), "filename": escape(arg[2]), "icon": AO_HOST + "evidence/" + escape(arg[2]) - } + }; } const evidence_box = document.getElementById("evidences"); @@ -622,7 +625,7 @@ class Client { id="evi_${i}" alt="${this.evidences[i - 1].name}" class="client_button" - onclick="pickevidence(${i})">`; + onclick="pickEvidence(${i})">`; } } @@ -672,7 +675,7 @@ class Client { newarea.className = "location-box"; newarea.textContent = args[i]; newarea.onclick = function () { - area_click(this) + area_click(this); }; document.getElementById("areas").appendChild(newarea); } @@ -777,7 +780,7 @@ class Client { */ handleZZ(args) { const oocLog = document.getElementById("client_ooclog"); - oocLog.innerHTML += `\$Alert: ${decodeChat(unescapeChat(args[1]))}\r\n`; + oocLog.innerHTML += `$Alert: ${decodeChat(unescapeChat(args[1]))}\r\n`; if (oocLog.scrollTop > oocLog.scrollHeight - 60) { oocLog.scrollTop = oocLog.scrollHeight; } @@ -814,20 +817,19 @@ class Client { */ handleCharsCheck(args) { document.getElementById("client_chartable").innerHTML = ""; + let tr; for (let i = 0; i < this.chars.length; i++) { if (i % CHAR_SELECT_WIDTH == 0) { - var tr = document.createElement('TR'); + tr = document.createElement('TR'); } - let td = document.createElement('TD'); - let icon_chosen; - let thispick = this.chars[i].icon; + const td = document.createElement('TD'); + let icon_chosen = ""; + const thispick = this.chars[i].icon; if (args[i + 1] == "-1") { icon_chosen = " dark"; - } else { - icon_chosen = ""; } td.innerHTML = `${this.chars[i].name}`; tr.appendChild(td); if (i % CHAR_SELECT_WIDTH == 0) { @@ -844,21 +846,21 @@ class Client { handlePV(args) { this.charID = args[3]; document.getElementById("client_charselect").style.display = "none"; - let me = this.me(); - let emotes = this.emotes; - let xhr = new XMLHttpRequest(); + const me = this.me(); + const emotes = this.emotes; + const xhr = new XMLHttpRequest(); xhr.withCredentials = false; document.getElementById("client_emo").innerHTML = ""; // Clear emote box xhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true); xhr.responseType = 'text'; xhr.onload = function (e) { if (this.status == 200) { - let linifile = this.responseText; - let pinifile = INI.parse(linifile); + const linifile = this.responseText; + const pinifile = INI.parse(linifile); me.side = pinifile.Options.side; updateActionCommands(me.side); for (let i = 1; i < pinifile.Emotions.number; i++) { - let emoteinfo = pinifile.Emotions[i].split('#'); + const emoteinfo = pinifile.Emotions[i].split('#'); let esfx = "0"; let esfxd = "0"; if (typeof pinifile.SoundN !== 'undefined') { @@ -883,9 +885,9 @@ class Client { id="emo_${i}" alt="${emotes[i].desc}" class="client_button" - onclick="pickemotion(${i})">`; + onclick="pickEmotion(${i})">`; } - pickemotion(1); + pickEmotion(1); } }; xhr.send(); @@ -1018,13 +1020,13 @@ class Viewport { * @param {object} param */ getAnimLength(filename, callback, param) { - var request = new XMLHttpRequest(); + const request = new XMLHttpRequest(); request.open('GET', filename, true); request.responseType = 'arraybuffer'; request.addEventListener('load', function () { // Use gify API // https://github.com/rfrench/gify - var gifInfo = gify.getInfo(request.response); + const gifInfo = gify.getInfo(request.response); console.log(gifInfo["duration"]); // Return animation length callback(gifInfo["duration"], param); @@ -1188,7 +1190,7 @@ class Viewport { "4": "#0000ff", "5": "#ffff00", "6": "#aa00aa" - } + }; let stylecolor = "color: " + (colors[this.chatmsg.color] || "#ffffff"); document.getElementById("client_inner_chat").style = stylecolor; this.chatmsg.startspeaking = false; @@ -1255,7 +1257,7 @@ class INI { let match = line.match(regex.section); value[match[1]] = {}; section = match[1]; - }; + } }); return value; } @@ -1396,7 +1398,7 @@ window.demoError = demoError; * @param {object} param */ function fileExists(url, callback, param) { - var xhttp = new XMLHttpRequest(); + const xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { callback(true, param, url); @@ -1415,41 +1417,41 @@ function fileExists(url, callback, param) { * @param {string} position the position to change into */ function changeBackground(position) { - var standname; - let bgfolder = viewport.bgFolder(); + let standname; + const bgfolder = viewport.bgFolder(); document.getElementById("client_fg").style.display = "none"; document.getElementById("client_bench").style.display = "none"; switch (position) { - case "def": - document.getElementById("client_court").src = bgfolder + "defenseempty.png" - document.getElementById("client_bench").style.display = "block"; - FileExist(bgfolder + "defensedesk.png", callbackChangeBackground, position); - standname = "defense"; - break; - case "pro": - document.getElementById("client_court").src = bgfolder + "prosecutorempty.png" - document.getElementById("client_bench").style.display = "block" - FileExist(bgfolder + "defensedesk.png", callbackChangeBackground, position); - standname = "prosecution"; - break; - case "hld": - document.getElementById("client_court").src = bgfolder + "helperstand.png" - standname = "defense"; - break; - case "hlp": - document.getElementById("client_court").src = bgfolder + "prohelperstand.png" - standname = "prosecution"; - break; - case "wit": - document.getElementById("client_court").src = bgfolder + "witnessempty.png" - document.getElementById("client_bench").style.display = "block" - document.getElementById("client_bench").src = bgfolder + "estrado.png" - standname = "prosecution"; - break; - case "jud": - document.getElementById("client_court").src = bgfolder + "judgestand.png" - standname = "prosecution"; - break; + case "def": + document.getElementById("client_court").src = bgfolder + "defenseempty.png"; + document.getElementById("client_bench").style.display = "block"; + fileExists(bgfolder + "defensedesk.png", callbackChangeBackground, position); + standname = "defense"; + break; + case "pro": + document.getElementById("client_court").src = bgfolder + "prosecutorempty.png"; + document.getElementById("client_bench").style.display = "block"; + fileExists(bgfolder + "defensedesk.png", callbackChangeBackground, position); + standname = "prosecution"; + break; + case "hld": + document.getElementById("client_court").src = bgfolder + "helperstand.png"; + standname = "defense"; + break; + case "hlp": + document.getElementById("client_court").src = bgfolder + "prohelperstand.png"; + standname = "prosecution"; + break; + case "wit": + document.getElementById("client_court").src = bgfolder + "witnessempty.png"; + document.getElementById("client_bench").style.display = "block"; + document.getElementById("client_bench").src = bgfolder + "estrado.png"; + standname = "prosecution"; + break; + case "jud": + document.getElementById("client_court").src = bgfolder + "judgestand.png"; + standname = "prosecution"; + break; } if (viewport.chatmsg.type == 5) { document.getElementById("client_bench").style.display = "none"; @@ -1468,15 +1470,15 @@ function callbackChangeBackground(result, position) { let bgfolder = viewport.bgFolder(); if (position == "def") { if (result) { - document.getElementById("client_bench").src = bgfolder + "defensedesk.png" + document.getElementById("client_bench").src = bgfolder + "defensedesk.png"; } else { - document.getElementById("client_bench").src = bgfolder + "bancodefensa.png" + document.getElementById("client_bench").src = bgfolder + "bancodefensa.png"; } } else { if (result) { - document.getElementById("client_bench").src = bgfolder + "prosecutiondesk.png" + document.getElementById("client_bench").src = bgfolder + "prosecutiondesk.png"; } else { - document.getElementById("client_bench").src = bgfolder + "bancoacusacion.png" + document.getElementById("client_bench").src = bgfolder + "bancoacusacion.png"; } } } @@ -1560,7 +1562,7 @@ export function pickEmotion(emo) { if (client.selectedEmote != -1) { document.getElementById("emo_" + client.selectedEmote).src = client.myEmote().button_off; } - client.selectedEmote = emo + client.selectedEmote = emo; document.getElementById("emo_" + emo).src = client.myEmote().button_on; } window.pickEmotion = pickEmotion; @@ -1596,7 +1598,7 @@ export function pickEvidence(evidence) { document.getElementById("evi_cancel").className = "client_button hover_button"; document.getElementById("evi_del").className = "client_button hover_button"; } else { - cancelevidence(); + cancelEvidence(); } } window.pickEvidence = pickEvidence; @@ -1608,11 +1610,11 @@ export function addEvidence() { let evidence_select = document.getElementById('evi_select'); client.sendPE(document.getElementById('evi_name').value, document.getElementById('evi_desc').value, - (evidence_select.selectedIndex == 0) ? - document.getElementById('evi_filename').value : - evidence_select.options[evidence_select.selectedIndex].text + evidence_select.selectedIndex == 0 ? + document.getElementById('evi_filename').value : + evidence_select.options[evidence_select.selectedIndex].text ); - cancelevidence(); + cancelEvidence(); } window.addEvidence = addEvidence; @@ -1625,11 +1627,11 @@ export function editEvidence() { client.sendEE(id, document.getElementById('evi_name').value, document.getElementById('evi_desc').value, - (evidence_select.selectedIndex == 0) ? - document.getElementById('evi_filename').value : - evidence_select.options[evidence_select.selectedIndex].text + evidence_select.selectedIndex == 0 ? + document.getElementById('evi_filename').value : + evidence_select.options[evidence_select.selectedIndex].text ); - cancelevidence(); + cancelEvidence(); } window.editEvidence = editEvidence; @@ -1639,7 +1641,7 @@ window.editEvidence = editEvidence; export function deleteEvidence() { let id = parseInt(client.selectedEvidence) - 1; client.sendDE(id); - cancelevidence(); + cancelEvidence(); } window.deleteEvidence = deleteEvidence; @@ -1676,7 +1678,7 @@ window.cancelEvidence = cancelEvidence; */ export function getIndexFromSelect(select_box, value) { //Find if icon alraedy existed in select box - let select_element = document.getElementById(select_box); + const select_element = document.getElementById(select_box); for (let i = 1; i < select_element.length; ++i) { if (select_element.options[i].value == value) { return i; @@ -1966,9 +1968,9 @@ function encodeChat(estring) { }); } else if (selectedEncoding == "utf16") { //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String - var buffer = new ArrayBuffer(estring.length * 2); - var result = new Uint16Array(buffer); - for (var i = 0, strLen = estring.length; i < strLen; i++) { + const buffer = new ArrayBuffer(estring.length * 2); + const result = new Uint16Array(buffer); + for (let i = 0, strLen = estring.length; i < strLen; i++) { result[i] = estring.charCodeAt(i); } return String(result); @@ -2025,11 +2027,10 @@ if (typeof (String.prototype.trim) === "undefined") { // Used for HDID calculation. String.prototype.hashCode = function () { - var hash = 0, - i, chr; + let hash = 0; if (this.length === 0) return hash; - for (i = 0; i < this.length; i++) { - chr = this.charCodeAt(i); + for (let i = 0; i < this.length; i++) { + const chr = this.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; // Convert to 32bit integer } @@ -2047,7 +2048,6 @@ let viewport = new Viewport(); $(document).ready(function () { client.initialObservBBCode(); client.loadResources(); - }); // Create dialog and link to button -- cgit From 8818ba99f804b1b1845a4757d67cc32d552956e1 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Sat, 8 Sep 2018 19:02:32 -0500 Subject: Continue major cleanup and style fixes --- webAO/client.js | 249 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 133 insertions(+), 116 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index dd1d7fa..426f5c0 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -2,11 +2,19 @@ * Glorious webAO * made by sD, refactored by oldmud0 and Qubrick * credits to aleks for original idea and source - */ +*/ + +// Uses the Gify library: +// https://github.com/rfrench/gify +// The following comment is needed for ESLint: +/* global gify */ + +import background_arr from "./backgrounds.js"; +import evidence_arr from "./evidence.js"; let queryDict = {}; location.search.substr(1).split("&").forEach(function (item) { - queryDict[item.split("=")[0]] = item.split("=")[1] + queryDict[item.split("=")[0]] = item.split("=")[1]; }); /* Server magic */ @@ -16,8 +24,6 @@ let mode = queryDict.mode; const AO_HOST = queryDict.asset || "http://s3.wasabisys.com/webao/base/"; const MUSIC_HOST = AO_HOST + "sounds/music/"; -const BAR_WIDTH = 90; -const BAR_HEIGHT = 20; const CHAR_SELECT_WIDTH = 8; const UPDATE_INTERVAL = 60; @@ -110,7 +116,7 @@ class Client { "CharsCheck": (args) => this.handleCharsCheck(args), "PV": (args) => this.handlePV(args), "CHECK": (args) => {} - } + }; this._lastTimeICReceived = new Date(0); } @@ -276,7 +282,7 @@ class Client { // Calculate gif duration of shouts const shouts = ["holdit", "objection", "takethat"]; for (let i = 0; i < shouts.length; i++) { - let shout_src = AO_HOST + this.resources[shouts[i]]["src"]; + let shout_src = AO_HOST + this.resources[shouts[i]]["src"].toLowerCase(); fileExists(shout_src, this.callbackLoadImageResources, shouts[i]); } @@ -287,7 +293,7 @@ class Client { // Check image existed fileExists(testimony_src, this.callbackLoadImageResources, testimony[i]); // Check sfx existed - fileExists(AO_HOST + this.resources[testimony[i]]["sfx"], this.callbackLoadSFXResources, testimony[i]); + fileExists(AO_HOST + this.resources[testimony[i]]["sfx"].toLowerCase(), this.callbackLoadSFXResources, testimony[i]); } // TODO: Cache some resources @@ -341,7 +347,7 @@ class Client { if (node.tagName == "C") { node.style.color = node.getAttribute("a"); } else if (node.tagName == "M") { - if (node.hasAttribute('a')) { + if (node.hasAttribute("a")) { node.style.backgroundColor = node.getAttribute("a"); } else { node.style.backgroundColor = "yellow"; @@ -415,8 +421,8 @@ class Client { onMessage(e) { let msg = e.data; console.debug(msg); - let lines = msg.split('%'); - let args = lines[0].split('#'); + let lines = msg.split("%"); + let args = lines[0].split("#"); let header = args[0]; let handler = this.handlers[header]; if (typeof handler !== "undefined") { @@ -447,7 +453,7 @@ class Client { } /** - * + * XXX: a nasty hack made by gameboyprinter. * @param {string} msg chat message to prepare for display */ prepChat(msg){ @@ -471,7 +477,7 @@ class Client { name: args[3], speaking: "(b)" + escape(args[4]), silent: "(a)" + escape(args[4]), - content: prepChat(args[5]), // Escape HTML tag, Use BBCode Only! + content: this.prepChat(args[5]), // Escape HTML tag, Use BBCode Only! side: args[6], sound: escape(args[7]), type: args[8], @@ -508,7 +514,7 @@ class Client { handleCT(args) { const oocLog = document.getElementById("client_ooclog"); oocLog.innerHTML += `${decodeChat(unescapeChat(args[1]))}: ${decodeChat(unescapeChat(args[2]))}\r\n`; - if (oocLog.scrollTop > oocLog.scrollHeight - 60) { + if (oocLog.scrollTop > oocLog.scrollHeight - 600) { oocLog.scrollTop = oocLog.scrollHeight; } } @@ -520,7 +526,7 @@ class Client { handleMC(args) { const music = viewport.music; music.pause(); - music.src = MUSIC_HOST + args[1]; + music.src = MUSIC_HOST + args[1].toLowerCase(); music.play(); if (args[2] >= 0) { let musicname = this.chars[args[2]].name; @@ -541,7 +547,7 @@ class Client { // Music offset + drift from song loading music.totime = args[1]; music.offset = new Date().getTime() / 1000; - music.addEventListener('loadedmetadata', function () { + music.addEventListener("loadedmetadata", function () { music.currentTime += parseFloat(music.totime + (new Date().getTime() / 1000 - music.offset)).toFixed(3); music.play(); }, false); @@ -562,7 +568,7 @@ class Client { "name": chargs[0], "desc": chargs[1], "evidence": chargs[3], - "icon": AO_HOST + "characters/" + escape(chargs[0]) + "/char_icon.png" + "icon": AO_HOST + "characters/" + escape(chargs[0].toLowerCase()) + "/char_icon.png" }; } } @@ -581,7 +587,7 @@ class Client { "name": chargs[0], "desc": chargs[1], "evidence": chargs[3], - "icon": AO_HOST + "characters/" + escape(chargs[0]) + "/char_icon.png" + "icon": AO_HOST + "characters/" + escape(chargs[0].toLowerCase()) + "/char_icon.png" }; } this.serv.send("RM#%"); @@ -614,7 +620,7 @@ class Client { "name": escapeHtml(decodeChat(unescapeChat(arg[0]))), "desc": escapeHtml(decodeChat(unescapeChat(arg[1]))), "filename": escape(arg[2]), - "icon": AO_HOST + "evidence/" + escape(arg[2]) + "icon": AO_HOST + "evidence/" + escape(arg[2].toLowerCase()) }; } @@ -665,13 +671,12 @@ class Client { if (flagAudio) { // After reached the audio put everything in the music list - let newentry = document.createElement("OPTION"); + const newentry = document.createElement("OPTION"); newentry.text = args[i]; hmusiclist.options.add(newentry); - } else { // Create area button - let newarea = document.createElement("SPAN"); + const newarea = document.createElement("SPAN"); newarea.className = "location-box"; newarea.textContent = args[i]; newarea.onclick = function () { @@ -681,12 +686,15 @@ class Client { } } - // Move first audio title from area box to music list - let area_box = document.getElementById("areas"); - let audio_title = document.createElement("OPTION"); - audio_title.text = area_box.lastChild.textContent; - hmusiclist.insertBefore(audio_title, hmusiclist.firstChild); - area_box.removeChild(area_box.lastChild); // Remove from arae box + // We need to check if the last area that we got was actually a category + // header for music. If it was, then move it over to the music list. + const area_box = document.getElementById("areas"); + if (area_box.lastChild.textContent.startsWith("=")) { + const audio_title = document.createElement("OPTION"); + audio_title.text = area_box.lastChild.textContent; + hmusiclist.insertBefore(audio_title, hmusiclist.firstChild); + area_box.removeChild(area_box.lastChild); + } this.serv.send("RD#%"); } @@ -725,7 +733,7 @@ class Client { if (bg_index == 0) { document.getElementById("bg_filename").value = args[1]; } - document.getElementById("bg_preview").src = AO_HOST + 'background/' + escape(args[1]) + "/defenseempty.png"; + document.getElementById("bg_preview").src = AO_HOST + "background/" + escape(args[1].toLowerCase()) + "/defenseempty.png"; if (this.charID == -1) { changeBackground("jud"); } else { @@ -748,13 +756,13 @@ class Client { // Def hp this.hp[0] = args[2]; $("#client_defense_hp > .health-bar").animate({ - 'width': percent_hp + "%" + "width": percent_hp + "%" }, 500); } else { // Pro hp this.hp[1] = args[2]; $("#client_prosecutor_hp > .health-bar").animate({ - 'width': percent_hp + "%" + "width": percent_hp + "%" }, 500); } } @@ -820,9 +828,9 @@ class Client { let tr; for (let i = 0; i < this.chars.length; i++) { if (i % CHAR_SELECT_WIDTH == 0) { - tr = document.createElement('TR'); + tr = document.createElement("TR"); } - const td = document.createElement('TD'); + const td = document.createElement("TD"); let icon_chosen = ""; const thispick = this.chars[i].icon; if (args[i + 1] == "-1") { @@ -830,7 +838,7 @@ class Client { } td.innerHTML = `${this.chars[i].name}`; + "onerror='demoError(this);'>"; tr.appendChild(td); if (i % CHAR_SELECT_WIDTH == 0) { document.getElementById("client_chartable").appendChild(tr); @@ -851,8 +859,8 @@ class Client { const xhr = new XMLHttpRequest(); xhr.withCredentials = false; document.getElementById("client_emo").innerHTML = ""; // Clear emote box - xhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true); - xhr.responseType = 'text'; + xhr.open("GET", AO_HOST + "characters/" + escape(this.me().name.toLowerCase()) + "/char.ini", true); + xhr.responseType = "text"; xhr.onload = function (e) { if (this.status == 200) { const linifile = this.responseText; @@ -860,13 +868,13 @@ class Client { me.side = pinifile.Options.side; updateActionCommands(me.side); for (let i = 1; i < pinifile.Emotions.number; i++) { - const emoteinfo = pinifile.Emotions[i].split('#'); + const emoteinfo = pinifile.Emotions[i].split("#"); let esfx = "0"; let esfxd = "0"; - if (typeof pinifile.SoundN !== 'undefined') { + if (typeof pinifile.SoundN !== "undefined") { esfx = pinifile.SoundN[i]; } - if (typeof pinifile.SoundT !== 'undefined') { + if (typeof pinifile.SoundT !== "undefined") { esfxd = pinifile.SoundT[i]; } // Make sure the asset server is case insensitive, or that everything on it is lowercase @@ -878,7 +886,7 @@ class Client { sfx: esfx.toLowerCase(), sfxdelay: esfxd, button_off: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_off.png`, - button_on: AO_HOST + `'characters/${escape(me.name).toLowerCase()}/emotions/button${i}_on.png` + button_on: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_on.png` }; document.getElementById("client_emo").innerHTML += ` this.updateTestimony(), UPDATE_INTERVAL); } } @@ -1021,11 +1031,9 @@ class Viewport { */ getAnimLength(filename, callback, param) { const request = new XMLHttpRequest(); - request.open('GET', filename, true); - request.responseType = 'arraybuffer'; - request.addEventListener('load', function () { - // Use gify API - // https://github.com/rfrench/gify + request.open("GET", filename, true); + request.responseType = "arraybuffer"; + request.addEventListener("load", function () { const gifInfo = gify.getInfo(request.response); console.log(gifInfo["duration"]); // Return animation length @@ -1068,7 +1076,7 @@ class Viewport { disposeTestimony() { client.testimonyID = 0; this.testimonyTimer = 0; - document.getElementById("client_testimony").src = "misc/placeholder.gif"; + document.getElementById("client_testimony").style.display = "none"; clearTimeout(this.testimonyUpdater); } @@ -1078,11 +1086,19 @@ class Viewport { * XXX: This relies on a global variable `this.chatmsg`! */ updateText() { + const nameBox = document.getElementById("client_name"); + const chatBox = document.getElementById("client_chat"); + const charSprite = document.getElementById("client_char"); + const eviBox = document.getElementById("client_evi"); + const background = document.getElementById("client_background"); + const shoutSprite = document.getElementById("client_shout"); + const chatBoxInner = document.getElementById("client_inner_chat"); + // Flip the character if (this.chatmsg.flip == 1) { - document.getElementById("client_char").style.transform = "scaleX(-1)"; + charSprite.style.transform = "scaleX(-1)"; } else { - document.getElementById("client_char").style.transform = "scaleX(1)"; + charSprite.style.transform = "scaleX(1)"; } if (this._animating) { @@ -1091,12 +1107,12 @@ class Viewport { if (this.chatmsg.isnew) { // Reset screen background - document.getElementById("client_background").style.backgroundColor = "transparent"; - //Hide message and evidence window - document.getElementById("client_name").style.display = "none"; - document.getElementById("client_chat").style.display = "none"; - document.getElementById("client_evi").style.opacity = "0"; - document.getElementById("client_evi").style.height = "0%"; + background.style.backgroundColor = "transparent"; + // Hide message and evidence window + nameBox.style.display = "none"; + chatBox.style.display = "none"; + eviBox.style.opacity = "0"; + eviBox.style.height = "0%"; const shouts = { "1": "holdit", "2": "objection", @@ -1105,8 +1121,8 @@ class Viewport { let shout = shouts[this.chatmsg.objection]; if (typeof shout !== "undefined") { - document.getElementById("client_shout").src = client.resources[shout]["src"]; - (new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play(); + shoutSprite.src = client.resources[shout]["src"]; + (new Audio(`${AO_HOST}characters/${this.chatmsg.name.toLowerCase()}/${shout}.wav`)).play(); this.shoutTimer = 850; } else { this.shoutTimer = 0; @@ -1124,24 +1140,24 @@ class Viewport { this.sfxplayed = 1; this.sfxaudio.src = AO_HOST + "sounds/general/sfx-stab.wav"; this.sfxaudio.play(); - $('#client_gamewindow').effect("shake", { + $("#client_gamewindow").effect("shake", { "direction": "up" }); } else if (this.chatmsg.flash == 1) { //Flash screen - document.getElementById("client_background").style.backgroundColor = "white"; + background.style.backgroundColor = "white"; this.sfxaudio.pause(); this.sfxplayed = 1; this.sfxaudio.src = AO_HOST + "sounds/general/sfx-realization.wav"; this.sfxaudio.play(); - $('#client_gamewindow').effect("pulsate"); + $("#client_gamewindow").effect("pulsate"); } //Pre-animation stuff if (this.chatmsg.preanimdelay > 0) { - document.getElementById("client_shout").src = "misc/placeholder.gif"; + shoutSprite.src = "misc/placeholder.gif"; changeBackground(this.chatmsg.side); - document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.preanim + ".gif"; + charSprite.src = AO_HOST + "characters/" + escape(this.chatmsg.name.toLowerCase()) + "/" + this.chatmsg.preanim.toLowerCase() + ".gif"; } this.chatmsg.startpreanim = false; this.chatmsg.startspeaking = true; @@ -1149,19 +1165,19 @@ class Viewport { if (this.chatmsg.startspeaking) { if (this.chatmsg.evidence > 0) { // Prepare evidence - document.getElementById("client_evi").style.backgroundImage = "url('" + client.evidences[this.chatmsg.evidence - 1].icon + "')"; + eviBox.style.backgroundImage = "url('" + client.evidences[this.chatmsg.evidence - 1].icon + "')"; - if (this.chatmsg.side == 'def') { + if (this.chatmsg.side == "def") { // Only def show evidence on right - document.getElementById("client_evi").style.right = "1.5em"; - document.getElementById("client_evi").style.left = "initial"; + eviBox.style.right = "1.5em"; + eviBox.style.left = "initial"; $("#client_evi").animate({ height: "30%", opacity: 1 }, 250); } else { - document.getElementById("client_evi").style.right = "initial"; - document.getElementById("client_evi").style.left = "1.5em"; + eviBox.style.right = "initial"; + eviBox.style.left = "1.5em"; $("#client_evi").animate({ height: "30%", opacity: 1 @@ -1169,18 +1185,12 @@ class Viewport { } } - $("#client_name").toggle("fade"); - $("#client_chat").toggle("drop", { - "direction": "down" - }); - if (this.chatmsg.preanimdelay == 0) { - document.getElementById("client_shout").src = "misc/placeholder.gif"; - changeBackground(this.chatmsg.side); - } - document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.speaking + ".gif"; - document.getElementById("client_name").style.fontSize = (document.getElementById("client_name").offsetHeight * 0.7) + "px"; - document.getElementById("client_chat").style.fontSize = (document.getElementById("client_chat").offsetHeight * 0.25) + "px"; - document.getElementById("client_name").innerHTML = "

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

"; + nameBox.style.display = "block"; + nameBox.style.fontSize = (nameBox.offsetHeight * 0.7) + "px"; + nameBox.innerHTML = "

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

"; + + chatBox.style.display = "block"; + chatBox.style.fontSize = (chatBox.offsetHeight * 0.25) + "px"; const colors = { "0": "#ffffff", @@ -1191,12 +1201,18 @@ class Viewport { "5": "#ffff00", "6": "#aa00aa" }; - let stylecolor = "color: " + (colors[this.chatmsg.color] || "#ffffff"); - document.getElementById("client_inner_chat").style = stylecolor; + chatBoxInner.style.color = colors[this.chatmsg.color] || "#ffffff"; this.chatmsg.startspeaking = false; + if (this.chatmsg.preanimdelay == 0) { + shoutSprite.src = "misc/placeholder.gif"; + changeBackground(this.chatmsg.side); + } + + charSprite.src = AO_HOST + "characters/" + escape(this.chatmsg.name.toLowerCase()) + "/" + this.chatmsg.speaking.toLowerCase() + ".gif"; + if (this.textnow == this.chatmsg.content) { - document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.silent + ".gif"; + charSprite.src = AO_HOST + "characters/" + escape(this.chatmsg.name.toLowerCase()) + "/" + this.chatmsg.silent.toLowerCase() + ".gif"; this._animating = false; clearTimeout(this.updater); } @@ -1208,11 +1224,11 @@ class Viewport { this.currentBlipChannel %= this.blipChannels.length; } this.textnow = this.chatmsg.content.substring(0, this.textnow.length + 1); - document.getElementById("client_inner_chat").innerHTML = this.textnow; + chatBoxInner.innerHTML = this.textnow; if (this.textnow == this.chatmsg.content) { this.textTimer = 0; this._animating = false; - document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.silent + ".gif"; + charSprite.src = AO_HOST + "characters/" + escape(this.chatmsg.name.toLowerCase()) + "/" + this.chatmsg.silent.toLowerCase() + ".gif"; clearTimeout(this.updater); } } @@ -1223,7 +1239,7 @@ class Viewport { this.sfxaudio.pause(); this.sfxplayed = 1; if (this.chatmsg.sound != "0" && this.chatmsg.sound != "1") { - this.sfxaudio.src = AO_HOST + "sounds/general/" + escape(this.chatmsg.sound) + ".wav"; + this.sfxaudio.src = AO_HOST + "sounds/general/" + escape(this.chatmsg.sound.toLowerCase()) + ".wav"; this.sfxaudio.play(); } } @@ -1235,7 +1251,7 @@ class INI { static parse(data) { let regex = { section: /^\s*\[\s*([^\]]*)\s*\]\s*$/, - param: /^\s*([\w\.\-\_]+)\s*=\s*(.*?)\s*$/, + param: /^\s*([\w.\-_]+)\s*=\s*(.*?)\s*$/, comment: /^\s*;.*$/ }; let value = {}; @@ -1531,7 +1547,7 @@ function appendICLog(toadd, name = "", time = new Date()) { const clientLog = document.getElementById("client_log"); clientLog.appendChild(entry); - if (clientLog.scrollTop > clientLog.scrollHeight - 600) { + if (clientLog.scrollTop > clientLog.scrollHeight - 800) { clientLog.scrollTop = clientLog.scrollHeight; } @@ -1607,11 +1623,11 @@ window.pickEvidence = pickEvidence; * Add evidence. */ export function addEvidence() { - let evidence_select = document.getElementById('evi_select'); - client.sendPE(document.getElementById('evi_name').value, - document.getElementById('evi_desc').value, + let evidence_select = document.getElementById("evi_select"); + client.sendPE(document.getElementById("evi_name").value, + document.getElementById("evi_desc").value, evidence_select.selectedIndex == 0 ? - document.getElementById('evi_filename').value : + document.getElementById("evi_filename").value : evidence_select.options[evidence_select.selectedIndex].text ); cancelEvidence(); @@ -1622,13 +1638,13 @@ window.addEvidence = addEvidence; * Edit selected evidence. */ export function editEvidence() { - let evidence_select = document.getElementById('evi_select'); + let evidence_select = document.getElementById("evi_select"); let id = parseInt(client.selectedEvidence) - 1; client.sendEE(id, - document.getElementById('evi_name').value, - document.getElementById('evi_desc').value, + document.getElementById("evi_name").value, + document.getElementById("evi_desc").value, evidence_select.selectedIndex == 0 ? - document.getElementById('evi_filename').value : + document.getElementById("evi_filename").value : evidence_select.options[evidence_select.selectedIndex].text ); cancelEvidence(); @@ -1698,10 +1714,10 @@ export function updateEvidenceIcon() { if (evidence_select.selectedIndex === 0) { evidence_filename.style.display = "initial"; - evidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_filename.value})`; + evidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_filename.value.toLowerCase()})`; } else { evidence_filename.style.display = "none"; - evidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_select.value})`; + evidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_select.value.toLowerCase()})`; } } window.updateEvidenceIcon = updateEvidenceIcon; @@ -1829,10 +1845,10 @@ export function updateBackgroundPreview() { if (background_select.selectedIndex == 0) { background_filename.style.display = "initial"; - background_preview.src = AO_HOST + 'background/' + background_filename.value + "/defenseempty.png"; + background_preview.src = AO_HOST + "background/" + background_filename.value.toLowerCase() + "/defenseempty.png"; } else { background_filename.style.display = "none"; - background_preview.src = AO_HOST + 'background/' + background_select.value + "/defenseempty.png"; + background_preview.src = AO_HOST + "background/" + background_select.value.toLowerCase() + "/defenseempty.png"; } } window.updateBackgroundPreview = updateBackgroundPreview; @@ -1956,18 +1972,19 @@ function unescapeChat(estring) { } /** - * Encoding text on client side. + * Encode text on client side. * @param {string} estring the string to be encoded */ function encodeChat(estring) { let selectedEncoding = document.getElementById("client_encoding").value; if (selectedEncoding == "unicode") { - //Source: https://gist.github.com/mathiasbynens/1243213 + // This approach works by escaping all special characters to Unicode escape sequences. + // Source: https://gist.github.com/mathiasbynens/1243213 return estring.replace(/[^\0-~]/g, function (ch) { return "\\u" + ("000" + ch.charCodeAt().toString(16)).slice(-4); }); } else if (selectedEncoding == "utf16") { - //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String + // Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String const buffer = new ArrayBuffer(estring.length * 2); const result = new Uint16Array(buffer); for (let i = 0, strLen = estring.length; i < strLen; i++) { @@ -1980,18 +1997,18 @@ function encodeChat(estring) { } /** - * Decoding text on client side. + * Decodes text on client side. * @param {string} estring the string to be decoded */ function decodeChat(estring) { let selectedDecoding = document.getElementById("client_decoding").value; if (selectedDecoding == "unicode") { - //Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode + // Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode return estring.replace(/\\u([\d\w]{1,})/gi, function (match, group) { return String.fromCharCode(parseInt(group, 16)); }); } else if (selectedDecoding == "utf16") { - //Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String + // Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String return String.fromCharCode.apply(null, new Uint16Array(estring.split(","))); } else { return estring; @@ -2011,17 +2028,17 @@ function decodeBBCode(estring) { .replace(/\[(\/?)u\]/g, "<$1u>") // Underline [u][/u] .replace(/\[(\/?)sub\]/g, "<$1sub>") // Subscript [sub][/sub] .replace(/\[(\/?)sup\]/g, "<$1sup>") // Superscript [sup][/sup] - .replace(/\[m=([#a-zA-Z0-9]+)\]/g, '') // Markup [m=#0ff] - .replace(/\[(\/?)m\]/g, '<$1m>') // [m][/m] - .replace(/\[c=?([#a-zA-Z0-9]+)\]/g, '') // Color [c=red] - .replace(/\[\/c\]/g, ''); // [/c] + .replace(/\[m=([#a-zA-Z0-9]+)\]/g, "") // Markup [m=#0ff] + .replace(/\[(\/?)m\]/g, "<$1m>") // [m][/m] + .replace(/\[c=?([#a-zA-Z0-9]+)\]/g, "") // Color [c=red] + .replace(/\[\/c\]/g, ""); // [/c] } // TODO: Possibly safe to remove, since we are using a transpiler. if (typeof (String.prototype.trim) === "undefined") { String.prototype.trim = function () { - return String(this).replace(/^\s+|\s+$/g, ''); + return String(this).replace(/^\s+|\s+$/g, ""); }; } -- cgit From 1db7474cbdcf13c586ee3fc446375d8a9d638a10 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Sat, 8 Sep 2018 21:12:16 -0500 Subject: Fix some more annoyances - Use createTextNode instead of escapeHtml - Add area change messages in IC log - Move "Call Mod" button to menu, replacing "Guide" which was mostly empty except for the BBCode reference (but you can surely look that up somewhere else, at least until more documentation for webAO has been produced) - Compact the evidence editor - Fix bug where the last emote was not displayed in the emotes list Some issues that remain: - Clients still cannot send special Unicode characters, but they can receive them correctly. - Shout animations run for longer than the GIF animation length. - Preanims sometimes play when they are not supposed to. - GoldenLayout panels cannot be dragged around for some reason. - The chatbox does not automatically scroll down. - When the game panel is maximized, the viewport should not exceed the size of the game panel. --- webAO/client.js | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'webAO/client.js') diff --git a/webAO/client.js b/webAO/client.js index 426f5c0..83db6f4 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -458,7 +458,7 @@ class Client { */ prepChat(msg){ // TODO: make this less awful - return decodeBBCode(escapeHtml(decodeChat(unescapeChat(msg)))); + return decodeBBCode(unescapeChat(decodeChat(msg))); } /** @@ -617,8 +617,8 @@ class Client { for (let i = 1; i < args.length - 1; i++) { const arg = args[i].split("&"); this.evidences[i - 1] = { - "name": escapeHtml(decodeChat(unescapeChat(arg[0]))), - "desc": escapeHtml(decodeChat(unescapeChat(arg[1]))), + "name": decodeChat(unescapeChat(arg[0])), + "desc": decodeChat(unescapeChat(arg[1])), "filename": escape(arg[2]), "icon": AO_HOST + "evidence/" + escape(arg[2].toLowerCase()) }; @@ -854,11 +854,14 @@ class Client { handlePV(args) { this.charID = args[3]; document.getElementById("client_charselect").style.display = "none"; + document.getElementById("client_inputbox").style.display = ""; const me = this.me(); const emotes = this.emotes; + const emotesList = document.getElementById("client_emo"); + emotesList.innerHTML = ""; // Clear emote box + emotesList.style.display = ""; const xhr = new XMLHttpRequest(); xhr.withCredentials = false; - document.getElementById("client_emo").innerHTML = ""; // Clear emote box xhr.open("GET", AO_HOST + "characters/" + escape(this.me().name.toLowerCase()) + "/char.ini", true); xhr.responseType = "text"; xhr.onload = function (e) { @@ -867,7 +870,7 @@ class Client { const pinifile = INI.parse(linifile); me.side = pinifile.Options.side; updateActionCommands(me.side); - for (let i = 1; i < pinifile.Emotions.number; i++) { + for (let i = 1; i <= pinifile.Emotions.number; i++) { const emoteinfo = pinifile.Emotions[i].split("#"); let esfx = "0"; let esfxd = "0"; @@ -888,7 +891,7 @@ class Client { button_off: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_off.png`, button_on: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_on.png` }; - document.getElementById("client_emo").innerHTML += + emotesList.innerHTML += `${emotes[i].desc}"; + + while (nameBox.hasChildNodes()) { + nameBox.removeChild(nameBox.firstChild); + } + nameBox.appendChild(document.createTextNode(this.chatmsg.nameplate)); chatBox.style.display = "block"; chatBox.style.fontSize = (chatBox.offsetHeight * 0.25) + "px"; @@ -1224,7 +1231,12 @@ class Viewport { this.currentBlipChannel %= this.blipChannels.length; } this.textnow = this.chatmsg.content.substring(0, this.textnow.length + 1); - chatBoxInner.innerHTML = this.textnow; + + while (chatBoxInner.hasChildNodes()) { + chatBoxInner.removeChild(chatBoxInner.firstChild); + } + chatBoxInner.appendChild(document.createTextNode(this.textnow)); + if (this.textnow == this.chatmsg.content) { this.textTimer = 0; this._animating = false; @@ -1335,18 +1347,23 @@ function resetICParams() { * @param {MouseEvent} event */ export function musiclist_click(event) { - let playtrack = document.getElementById("client_musiclist").value; + const playtrack = document.getElementById("client_musiclist").value; client.sendMusicChange(playtrack); } window.musiclist_click = musiclist_click; /** - * Triggered when an item on the music list is clicked. + * Triggered when an item on the area list is clicked. * @param {MouseEvent} event */ export function area_click(el) { - let playtrack = el.textContent; - client.sendMusicChange(playtrack); + const area = el.textContent; + client.sendMusicChange(area); + + const areaHr = document.createElement("div"); + areaHr.className = "hrtext"; + areaHr.textContent = `switched to ${el.textContent}`; + document.getElementById("client_log").appendChild(areaHr); } window.area_click = area_click; -- cgit