diff options
| author | sD <stoned@derpymail.org> | 2019-12-25 18:17:04 +0100 |
|---|---|---|
| committer | sD <stoned@derpymail.org> | 2019-12-25 18:17:04 +0100 |
| commit | 25bf92857171e5d81daba41676ad23ea00eb8369 (patch) | |
| tree | d0e707c6d06a6754f1ab1947541332fa1208cadf /webAO | |
| parent | ab5a95dcdc622bb2c7cd35e2cc29c1881c882eb2 (diff) | |
| parent | 96220bf48024cf2722b45366bb176d6c1879fe7e (diff) | |
Merge branch 'master' into arup
Diffstat (limited to 'webAO')
| -rw-r--r-- | webAO/client.css | 23 | ||||
| -rw-r--r-- | webAO/client.js | 169 |
2 files changed, 143 insertions, 49 deletions
diff --git a/webAO/client.css b/webAO/client.css index 7a0d449..c22c0f9 100644 --- a/webAO/client.css +++ b/webAO/client.css @@ -246,6 +246,29 @@ img { color: white; } +.rainbow-text { + background-color: rgb(255, 255, 255); + background-image: repeating-linear-gradient(to right, + red 0% 8%, orange 8% 16%, yellow 16% 24%, green 24% 32%, blue 32% 40%, + red 40% 48%, orange 48% 56%, yellow 56% 64%, green 64% 72%, blue 72% 80%, + red 80% 88%, orange 88% 96%, yellow 96% 100% ); + background-size: 40% 40%; + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + animation: rainbow 4s linear infinite; + } + + @keyframes rainbow_alt { + 0%,100% {background-position: 0 0; } + 50% {background-position: 400% 0; } + } + + @keyframes rainbow { + 0% {background-position: 0 0; } + 100% {background-position: 400% 0; } + } + #client_inputbox { font-size: 21px; padding: 2px 10px; diff --git a/webAO/client.js b/webAO/client.js index 817277f..b66f9cc 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -57,11 +57,6 @@ console.info(`Your emulated HDID is ${hdid}`); let lastICMessageTime = new Date(0); -function safe_tags(str) { - if (str) - return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>') ; -} - class Client extends EventEmitter { constructor(address) { super(); @@ -184,12 +179,21 @@ class Client extends EventEmitter { } /** + * Hook for sending messages to the server + * @param {string} message the message to send + */ + sendServer(message) { + // console.log(message); + this.serv.send(message); + } + + /** * Sends an out-of-character chat message. * @param {string} message the message to send */ sendOOC(message) { setCookie("OOC_name",document.getElementById("OOC_name").value); - this.serv.send(`CT#${escapeChat(encodeChat(document.getElementById("OOC_name").value))}#${escapeChat(encodeChat(message))}#%`); + this.sendServer(`CT#${escapeChat(encodeChat(document.getElementById("OOC_name").value))}#${escapeChat(encodeChat(message))}#%`); } /** @@ -223,7 +227,7 @@ class Client extends EventEmitter { `#${escapeChat(encodeChat(message))}#${side}#${sfx_name}#${emote_modifier}` + `#${this.charID}#${sfx_delay}#${objection_modifier}#${evidence}#${flip}#${realization}#${text_color}#${extra_cccc}%` ); - this.serv.send( + this.sendServer( `MS#${deskmod}#${speaking}#${name}#${silent}` + `#${escapeChat(encodeChat(message))}#${side}#${sfx_name}#${emote_modifier}` + `#${this.charID}#${sfx_delay}#${objection_modifier}#${evidence}#${flip}#${realization}#${text_color}#${extra_cccc}%` @@ -237,7 +241,7 @@ class Client extends EventEmitter { * @param {string} evidence image filename */ sendPE(name, desc, img) { - this.serv.send(`PE#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); + this.sendServer(`PE#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); } /** @@ -248,7 +252,7 @@ class Client extends EventEmitter { * @param {string} evidence image filename */ sendEE(id, name, desc, img) { - this.serv.send(`EE#${id}#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); + this.sendServer(`EE#${id}#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`); } /** @@ -256,7 +260,7 @@ class Client extends EventEmitter { * @param {number} evidence id */ sendDE(id) { - this.serv.send(`DE#${id}#%`); + this.sendServer(`DE#${id}#%`); } /** @@ -265,7 +269,7 @@ class Client extends EventEmitter { * @param {number} hp the health point */ sendHP(side, hp) { - this.serv.send(`HP#${side}#${hp}#%`); + this.sendServer(`HP#${side}#${hp}#%`); } /** @@ -273,7 +277,7 @@ class Client extends EventEmitter { * @param {string} message to mod */ sendZZ(msg) { - this.serv.send(`ZZ#${msg}#%`); + this.sendServer(`ZZ#${msg}#%`); } /** @@ -282,7 +286,7 @@ class Client extends EventEmitter { */ sendRT(testimony) { if (this.chars[this.charID].side === "jud") { - this.serv.send(`RT#${testimony}#%`); + this.sendServer(`RT#${testimony}#%`); } } @@ -291,7 +295,7 @@ class Client extends EventEmitter { * @param {string} track the track ID */ sendMusicChange(track) { - this.serv.send(`MC#${track}#${this.charID}#%`); + this.sendServer(`MC#${track}#${this.charID}#%`); } /** @@ -301,7 +305,7 @@ class Client extends EventEmitter { * either the AO2 client or tsuserver. */ sendLeaveRoom() { - this.serv.send("FC#%"); + this.sendServer("FC#%"); } /** @@ -309,8 +313,8 @@ class Client extends EventEmitter { * to the server. */ joinServer() { - this.serv.send(`HI#${hdid}#%`); - this.serv.send("ID#webAO#2.3#%"); + this.sendServer(`HI#${hdid}#%`); + this.sendServer("ID#webAO#2.3#%"); this.checkUpdater = setInterval(() => this.sendCheck(), 5000); } @@ -355,7 +359,7 @@ class Client extends EventEmitter { */ sendCharacter(character) { if (this.chars[character].name) - this.serv.send(`CC#${this.playerID}#${character}#web#%`); + this.sendServer(`CC#${this.playerID}#${character}#web#%`); } /** @@ -363,14 +367,14 @@ class Client extends EventEmitter { * @param {number?} song the song to be played */ sendMusic(song) { - this.serv.send(`MC#${song}`); + this.sendServer(`MC#${song}`); } /** * Sends a keepalive packet. */ sendCheck() { - this.serv.send(`CH#${this.charID}#%`); + this.sendServer(`CH#${this.charID}#%`); } /** @@ -457,7 +461,7 @@ class Client extends EventEmitter { } let chatmsg = { - deskmod: safe_tags(args[1]).toLowerCase(), + deskmod: safe_tags(args[1]).toLowerCase(), preanim: safe_tags(args[2]).toLowerCase(), // get preanim nameplate: msg_nameplate, // TODO: there's a new feature that let's people choose the name that's displayed name: safe_tags(args[3]), @@ -556,6 +560,7 @@ class Client extends EventEmitter { * @param {Number} charid character ID */ async handleCharacterInfo(chargs, charid) { + if (chargs[0]) { let cini = {}; let icon = AO_HOST + "characters/" + encodeURI(chargs[0].toLowerCase()) + "/char_icon.png"; let img = document.getElementById(`demo_${charid}`); @@ -595,6 +600,11 @@ class Client extends EventEmitter { icon: icon, inifile: cini }; + } else { + console.warn("missing charid "+charid); + let img = document.getElementById(`demo_${charid}`); + img.style.display = "none"; + } } @@ -602,20 +612,21 @@ class Client extends EventEmitter { /** * Handles incoming character information, bundling multiple characters * per packet. + * CI#0#Phoenix&description&&&&#Miles ... * @param {Array} args packet arguments */ handleCI(args) { document.getElementById("client_loadingtext").innerHTML = "Loading Character " + args[1]; // Loop through the 10 characters that were sent - for (let i = 2; i < args.length - 1; i++) { + for (let i = 2; i <= args.length - 2; i++) { if (i % 2 === 0) { document.getElementById("client_loadingtext").innerHTML = `Loading Character ${i}/${this.char_list_length}`; const chargs = args[i].split("&"); - this.handleCharacterInfo(chargs, i-1); + this.handleCharacterInfo(chargs, args[i-1]); } } // Request the next pack - this.serv.send("AN#" + ((args[1] / 10) + 1) + "#%"); + this.sendServer("AN#" + ((args[1] / 10) + 1) + "#%"); } /** @@ -625,13 +636,13 @@ class Client extends EventEmitter { */ handleSC(args) { document.getElementById("client_loadingtext").innerHTML = "Loading Characters"; - for (let i = 1; i < args.length - 1; i++) { + for (let i = 1; i < args.length; i++) { document.getElementById("client_loadingtext").innerHTML = `Loading Character ${i}/${this.char_list_length}`; const chargs = args[i].split("&"); this.handleCharacterInfo(chargs, i-1); } // We're done with the characters, request the music - this.serv.send("RM#%"); + this.sendServer("RM#%"); } /** @@ -643,7 +654,7 @@ class Client extends EventEmitter { */ handleEI(args) { document.getElementById("client_loadingtext").innerHTML = `Loading Evidence ${args[1]}/${this.evidence_list_length}`; - this.serv.send("RM#%"); + this.sendServer("RM#%"); } /** @@ -682,7 +693,7 @@ class Client extends EventEmitter { */ handleEM(args) { document.getElementById("client_loadingtext").innerHTML = "Loading Music " + args[1]; - this.serv.send("AM#" + ((args[1] / 10) + 1) + "#%"); + this.sendServer("AM#" + ((args[1] / 10) + 1) + "#%"); const hmusiclist = document.getElementById("client_musiclist"); for (let i = 2; i < args.length - 1; i++) { if (i % 2 === 0) { @@ -751,14 +762,14 @@ class Client extends EventEmitter { } // Music done, carry on - this.serv.send("RD#%"); + this.sendServer("RD#%"); } /** * Handles the "MusicMode" packet * @param {Array} args packet arguments */ - handleMM(args) { + handleMM(_args) { // It's unused nowadays, as preventing people from changing the music is now serverside } @@ -881,6 +892,14 @@ class Client extends EventEmitter { */ handleID(args) { this.playerID = args[1]; + this.serverSoftware = args[2].split("&")[0]; + if (this.serverSoftware === "serverD") + this.serverVersion = args[2].split("&")[1]; + else + this.serverVersion = args[3]; + + if (this.serverSoftware === "serverD" && this.serverVersion === "1377.152") + oldLoading = true; // bugged version } /** @@ -888,7 +907,7 @@ class Client extends EventEmitter { * @param {Array} args packet arguments */ handlePN(_args) { - this.serv.send("askchaa#%"); + this.sendServer("askchaa#%"); } /** @@ -938,6 +957,7 @@ class Client extends EventEmitter { let colorselect = document.getElementById("textcolor"); colorselect.options[colorselect.options.length] = new Option("Yellow", 5); + colorselect.options[colorselect.options.length] = new Option("Rainbow", 6); colorselect.options[colorselect.options.length] = new Option("Pink", 7); colorselect.options[colorselect.options.length] = new Option("Cyan", 8); } @@ -954,7 +974,8 @@ class Client extends EventEmitter { * @param {Array} args packet arguments */ handleSI(args) { - this.char_list_length = args[1]; + this.char_list_length = Number(args[1]); + this.char_list_length += 1; // some servers count starting from 0 some from 1... this.evidence_list_length = args[2]; this.music_list_length = args[3]; @@ -976,10 +997,10 @@ class Client extends EventEmitter { } // this is determined at the top of this file - if (oldLoading) { - this.serv.send("askchar2#%"); + if (!oldLoading && extrafeatures.includes("fastloading")) { + this.sendServer("RC#%"); } else { - this.serv.send("RC#%"); + this.sendServer("askchar2#%"); } } @@ -1072,6 +1093,19 @@ class Viewport { "snddelay": 0, "preanimdelay": 0 }; + + this.colors = { + "0": "#ffffff", // white + "1": "#00ff00", // green + "2": "#ff0000", // red + "3": "#ffa500", // orange + "4": "#4596ff", // blue + "5": "#ffff00", // yellow + "6": "#fedcba", // 6 is rainbow. + "7": "#ffc0cb", // pink + "8": "#00ffff" // cyan + }; + this.blip = new Audio(AO_HOST + "sounds/general/sfx-blipmale.wav"); this.blip.volume = 0.5; @@ -1127,6 +1161,10 @@ class Viewport { /** * Sets a new emote. + * TODO: merge this and initUpdater + * This sets up everything before the tick() loops starts + * a lot of things can probably be moved here, like starting the shout animation if there is one + * TODO: the preanim logic, on the other hand, should probably be moved to tick() * @param {object} chatmsg the new chat message */ async say(chatmsg) { @@ -1263,6 +1301,43 @@ class Viewport { /** * Updates the chatbox based on the given text. * + * OK, here's the documentation on how this works: + * + * 1 flip + * For whatever reason it starts off by checking if the character is flipped, every time this is called + * This is probably a TODO to move this somewhere else + * + * 2 flip + * If the server supports it, the same is done for the paired character + * Both of these should probably be moved to say() + * + * 3 _animating + * If we're not done with this characters animation, i.e. his text isn't fully there, set a timeout for the next tick/step to happen + * + * 4 isnew + * This is run once for every new message + * The chatbox and evidence is hidden (TODO even if there is no shout) + * and if there is a shout it's audio starts playing + * + * 5 startpreanim + * If the shout timer is over it starts with the preanim + * The first thing it checks for is the shake effect (TODO on client this is handled by the @ symbol and not a flag ) + * Then is the flash/realization effect + * After that, the shout image is set to a transparent placeholder gif (TODO just hide it with CSS) + * and the main characters preanim gif is loaded + * If pairing is supported the paired character will just stand around with his idle sprite + * + * 6 preanimdelay over + * this animates the evidence popup and finally shows the character name and message box + * it sets the text color , changes the background (again TODO) and sets the character speaking sprite + * + * 7 textnow != content + * this adds a character to the textbox and stops the animations if the entire message is present in the textbox + * + * 8 sfx + * independent of the stuff above, this will play any sound effects specified by the emote the character sent. + * happens after the shout delay + an sfx delay that comes with the message packet + * * XXX: This relies on a global variable `this.chatmsg`! */ tick() { @@ -1301,6 +1376,7 @@ class Viewport { // Hide message and evidence window nameBox.style.display = "none"; chatBox.style.display = "none"; + chatBoxInner.className = ""; eviBox.style.opacity = "0"; eviBox.style.height = "0%"; const shouts = { @@ -1407,18 +1483,12 @@ class Viewport { chatBox.style.display = "block"; chatBox.style.fontSize = (chatBox.offsetHeight * 0.25) + "px"; - let colors = { - "0": "#ffffff", // white - "1": "#00ff00", // green - "2": "#ff0000", // red - "3": "#ffa500", // orange - "4": "#4596ff", // blue - "5": "#ffff00", // yellow - "6": "#fedcba", // 6 is rainbow. - "7": "#aac0cb", // pink - "8": "#00ffff" // cyan - }; - chatBoxInner.style.color = colors[this.chatmsg.color] || "#ffffff"; + if (this.chatmsg.color === "6") + chatBoxInner.className = "rainbow-text"; + else { + chatBoxInner.className = ""; + chatBoxInner.style.color = this.colors[this.chatmsg.color] || "#ffffff"; + } this.chatmsg.startspeaking = false; if (this.chatmsg.preanimdelay === 0) { @@ -2335,8 +2405,9 @@ window.toggleShout = toggleShout; * XXX: This is unnecessary if we use `createTextNode` instead! * @param {string} unsafe an unsanitized string */ -function escapeHtml(unsafe) { - return unsafe +function safe_tags(unsafe) { + if (unsafe) + return unsafe .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") |
