diff options
Diffstat (limited to 'webAO/packets')
43 files changed, 1207 insertions, 28 deletions
diff --git a/webAO/packets/handlers/handleARUP.ts b/webAO/packets/handlers/handleARUP.ts new file mode 100644 index 0000000..97db9cc --- /dev/null +++ b/webAO/packets/handlers/handleARUP.ts @@ -0,0 +1,42 @@ +import { client } from "../../client"; +import { safeTags } from "../../encoding"; + +/** + * Handle the change of players in an area. + * @param {Array} args packet arguments + */ +export const handleARUP = (args: string[]) => { + args = args.slice(1); + for (let i = 0; i < args.length - 2; i++) { + if (client.areas[i]) { + // the server sends us ARUP before we even get the area list + const thisarea = document.getElementById(`area${i}`)!; + switch (Number(args[0])) { + case 0: // playercount + client.areas[i].players = Number(args[i + 1]); + break; + case 1: // status + client.areas[i].status = safeTags(args[i + 1]); + break; + case 2: + client.areas[i].cm = safeTags(args[i + 1]); + break; + case 3: + client.areas[i].locked = safeTags(args[i + 1]); + break; + } + + thisarea.className = `area-button area-${client.areas[ + i + ].status.toLowerCase()}`; + + thisarea.innerText = `${client.areas[i].name} (${client.areas[i].players}) [${client.areas[i].status}]`; + + thisarea.title = + `Players: ${client.areas[i].players}\n` + + `Status: ${client.areas[i].status}\n` + + `CM: ${client.areas[i].cm}\n` + + `Area lock: ${client.areas[i].locked}`; + } + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleASS.ts b/webAO/packets/handlers/handleASS.ts new file mode 100644 index 0000000..ea8a0d3 --- /dev/null +++ b/webAO/packets/handlers/handleASS.ts @@ -0,0 +1,10 @@ +import { setAOhost } from "../../client/aoHost"; + + +/** +* new asset url!! +* @param {Array} args packet arguments +*/ +export const handleASS = (args: string[]) => { + setAOhost(args[1]); +} diff --git a/webAO/packets/handlers/handleBB.ts b/webAO/packets/handlers/handleBB.ts new file mode 100644 index 0000000..c12c4f6 --- /dev/null +++ b/webAO/packets/handlers/handleBB.ts @@ -0,0 +1,11 @@ +import { safeTags } from "../../encoding"; + + +/** + * Handles the warning packet + * on client this spawns a message box you can't close for 2 seconds + * @param {Array} args ban reason + */ +export const handleBB = (args: string[]) => { + alert(safeTags(args[1])); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleBD.ts b/webAO/packets/handlers/handleBD.ts new file mode 100644 index 0000000..dbfb54b --- /dev/null +++ b/webAO/packets/handlers/handleBD.ts @@ -0,0 +1,14 @@ +import { setBanned } from "../../client"; +import { safeTags } from "../../encoding"; +import { handleBans } from '../../client/handleBans' + + +/** + * Handles the banned packet + * this one is sent when you try to reconnect but you're banned + * @param {Array} args ban reason + */ +export const handleBD = (args: string[]) => { + handleBans("Banned", safeTags(args[1])); + setBanned(true); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleBN.ts b/webAO/packets/handlers/handleBN.ts new file mode 100644 index 0000000..3c5d95f --- /dev/null +++ b/webAO/packets/handlers/handleBN.ts @@ -0,0 +1,84 @@ +import { client } from "../../client"; +import { AO_HOST } from "../../client/aoHost"; +import { safeTags } from "../../encoding"; +import { updateBackgroundPreview } from '../../dom/updateBackgroundPreview' +import { getIndexFromSelect } from '../../dom/getIndexFromSelect' +import tryUrls from "../../utils/tryUrls"; + + +/** + * Handles a background change. + * @param {Array} args packet arguments + */ + +export const handleBN = (args: string[]) => { + const bgFromArgs = safeTags(args[1]); + client.viewport.setBackgroundName(bgFromArgs); + const bgfolder = client.viewport.getBackgroundFolder(); + const bg_index = getIndexFromSelect( + "bg_select", + client.viewport.getBackgroundName() + ); + (<HTMLSelectElement>document.getElementById("bg_select")).selectedIndex = + bg_index; + updateBackgroundPreview(); + if (bg_index === 0) { + (<HTMLInputElement>document.getElementById("bg_filename")).value = + client.viewport.getBackgroundName(); + } + + tryUrls( + `${AO_HOST}background/${encodeURI(args[1].toLowerCase())}/defenseempty` + ).then((resp) => { + (<HTMLImageElement>document.getElementById("bg_preview")).src = resp; + }); + tryUrls(`${bgfolder}defensedesk`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_def_bench")).src = + resp; + }); + tryUrls(`${bgfolder}stand`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_wit_bench")).src = + resp; + }); + tryUrls(`${bgfolder}prosecutiondesk`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_pro_bench")).src = + resp; + }); + tryUrls(`${bgfolder}full`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_court")).src = resp; + }); + tryUrls(`${bgfolder}defenseempty`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_court_def")).src = + resp; + }); + tryUrls(`${bgfolder}transition_def`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_court_deft")).src = + resp; + }); + tryUrls(`${bgfolder}witnessempty`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_court_wit")).src = + resp; + }); + tryUrls(`${bgfolder}transition_pro`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_court_prot")).src = + resp; + }); + tryUrls(`${bgfolder}prosecutorempty`).then((resp) => { + (<HTMLImageElement>document.getElementById("client_court_pro")).src = + resp; + }); + + if (client.charID === -1) { + client.viewport.set_side({ + position: "jud", + showSpeedLines: false, + showDesk: true, + }); + } else { + client.viewport.set_side({ + position: client.chars[client.charID].side, + showSpeedLines: false, + showDesk: true, + }); + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleCC.ts b/webAO/packets/handlers/handleCC.ts new file mode 100644 index 0000000..36bcdc7 --- /dev/null +++ b/webAO/packets/handlers/handleCC.ts @@ -0,0 +1,9 @@ +import { client } from "../../client"; + +/** + * What? you want a character?? + * @param {Array} args packet arguments + */ +export const handleCC = (args: string[]) => { + client.sender.sendSelf(`PV#1#CID#${args[2]}#%`); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleCI.ts b/webAO/packets/handlers/handleCI.ts new file mode 100644 index 0000000..cb693bc --- /dev/null +++ b/webAO/packets/handlers/handleCI.ts @@ -0,0 +1,27 @@ +import { client } from '../../client' +import { handleCharacterInfo } from '../../client/handleCharacterInfo' +/** + * Handles incoming character information, bundling multiple characters + * per packet. + * CI#0#Phoenix&description&&&&#Miles ... + * @param {Array} args packet arguments + */ +export const handleCI = (args: string[]) => { + // Loop through the 10 characters that were sent + + for (let i = 2; i <= args.length - 2; i++) { + if (i % 2 === 0) { + document.getElementById( + "client_loadingtext" + )!.innerHTML = `Loading Character ${args[1]}/${client.char_list_length}`; + const chargs = args[i].split("&"); + const charid = Number(args[i - 1]); + (<HTMLProgressElement>( + document.getElementById("client_loadingbar") + )).value = charid; + setTimeout(() => handleCharacterInfo(chargs, charid), 500); + } + } + // Request the next pack + client.sender.sendServer(`AN#${Number(args[1]) / 10 + 1}#%`); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleCT.ts b/webAO/packets/handlers/handleCT.ts new file mode 100644 index 0000000..cff9b24 --- /dev/null +++ b/webAO/packets/handlers/handleCT.ts @@ -0,0 +1,17 @@ +import queryParser from '../../utils/queryParser' +import { prepChat } from '../../encoding' +let { mode } = queryParser(); + +/** + * Handles an out-of-character chat message. + * @param {Array} args packet arguments + */ +export const handleCT = (args: string[]) => { + if (mode !== "replay") { + const oocLog = document.getElementById("client_ooclog")!; + oocLog.innerHTML += `${prepChat(args[1])}: ${prepChat(args[2])}\r\n`; + if (oocLog.scrollTop > oocLog.scrollHeight - 600) { + oocLog.scrollTop = oocLog.scrollHeight; + } + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleCharsCheck.ts b/webAO/packets/handlers/handleCharsCheck.ts new file mode 100644 index 0000000..2d891ef --- /dev/null +++ b/webAO/packets/handlers/handleCharsCheck.ts @@ -0,0 +1,17 @@ +import { client } from "../../client"; + +/** + * Handles the list of all used and vacant characters. + * @param {Array} args list of all characters represented as a 0 for free or a -1 for taken + */ +export const handleCharsCheck = (args: string[]) => { + for (let i = 0; i < client.char_list_length; i++) { + const img = document.getElementById(`demo_${i}`)!; + + if (args[i + 1] === "-1") { + img.style.opacity = "0.25"; + } else if (args[i + 1] === "0") { + img.style.opacity = "1"; + } + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleDONE.ts b/webAO/packets/handlers/handleDONE.ts new file mode 100644 index 0000000..3cafd5e --- /dev/null +++ b/webAO/packets/handlers/handleDONE.ts @@ -0,0 +1,16 @@ +import queryParser from "../../utils/queryParser"; + +let { mode } = queryParser() + /** + * Handles the handshake completion packet, meaning the player + * is ready to select a character. + * + * @param {Array} args packet arguments + */ +export const handleDONE = (_args: string[]) => { + document.getElementById("client_loading")!.style.display = "none"; + if (mode === "watch") { + // Spectators don't need to pick a character + document.getElementById("client_waiting")!.style.display = "none"; + } + }
\ No newline at end of file diff --git a/webAO/packets/handlers/handleEI.ts b/webAO/packets/handlers/handleEI.ts new file mode 100644 index 0000000..428baf1 --- /dev/null +++ b/webAO/packets/handlers/handleEI.ts @@ -0,0 +1,30 @@ +import { client } from '../../client' +import { AO_HOST } from '../../client/aoHost'; +import { prepChat, safeTags } from '../../encoding'; + +/** + * Handles incoming evidence information, containing only one evidence + * item per packet. + * + * EI#id#name&description&type&image&##% + * + * @param {Array} args packet arguments + */ +export const handleEI = (args: string[]) => { + document.getElementById( + "client_loadingtext" + )!.innerHTML = `Loading Evidence ${args[1]}/${client.evidence_list_length}`; + const evidenceID = Number(args[1]); + (<HTMLProgressElement>document.getElementById("client_loadingbar")).value = + client.char_list_length + evidenceID; + + const arg = args[2].split("&"); + client.evidences[evidenceID] = { + name: prepChat(arg[0]), + desc: prepChat(arg[1]), + filename: safeTags(arg[3]), + icon: `${AO_HOST}evidence/${encodeURI(arg[3].toLowerCase())}`, + }; + + client.sender.sendServer("AE" + (evidenceID + 1) + "#%"); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleEM.ts b/webAO/packets/handlers/handleEM.ts new file mode 100644 index 0000000..5e49ea4 --- /dev/null +++ b/webAO/packets/handlers/handleEM.ts @@ -0,0 +1,43 @@ +import { client } from '../../client' +import { addTrack } from '../../client/addTrack'; +import { createArea } from '../../client/createArea'; +import { fix_last_area } from '../../client/fixLastArea'; +import { isAudio } from '../../client/isAudio'; +import { safeTags } from '../../encoding'; + +/** + * Handles incoming music information, containing multiple entries + * per packet. + * @param {Array} args packet arguments + */ +export const handleEM = (args: string[]) => { + document.getElementById("client_loadingtext")!.innerHTML = "Loading Music"; + if (args[1] === "0") { + client.resetMusicList(); + client.resetAreaList(); + client.musics_time = false; + } + + for (let i = 2; i < args.length - 1; i++) { + if (i % 2 === 0) { + const trackname = safeTags(args[i]); + const trackindex = Number(args[i - 1]); + (<HTMLProgressElement>( + document.getElementById("client_loadingbar") + )).value = + client.char_list_length + client.evidence_list_length + trackindex; + if (client.musics_time) { + addTrack(trackname); + } else if (isAudio(trackname)) { + client.musics_time = true; + fix_last_area(); + addTrack(trackname); + } else { + createArea(trackindex, trackname); + } + } + } + + // get the next batch of tracks + client.sender.sendServer(`AM#${Number(args[1]) / 10 + 1}#%`); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleFA.ts b/webAO/packets/handlers/handleFA.ts new file mode 100644 index 0000000..7a373e8 --- /dev/null +++ b/webAO/packets/handlers/handleFA.ts @@ -0,0 +1,15 @@ +import { client } from '../../client' +import { createArea } from '../../client/createArea'; +import { safeTags } from '../../encoding'; + +/** + * Handles updated area list + * @param {Array} args packet arguments + */ +export const handleFA = (args: string[]) => { + client.resetAreaList(); + + for (let i = 1; i < args.length - 1; i++) { + createArea(i - 1, safeTags(args[i])); + } +} diff --git a/webAO/packets/handlers/handleFL.ts b/webAO/packets/handlers/handleFL.ts new file mode 100644 index 0000000..378d5a9 --- /dev/null +++ b/webAO/packets/handlers/handleFL.ts @@ -0,0 +1,48 @@ +import { setExtraFeatures } from "../../client"; + + +/** + * With this the server tells us which features it supports + * @param {Array} args list of features + */ +export const handleFL = (args: string[]) => { + console.info("Server-supported features:"); + console.info(args); + setExtraFeatures(args); + + if (args.includes("yellowtext")) { + const colorselect = <HTMLSelectElement>( + document.getElementById("textcolor") + ); + + colorselect.options[colorselect.options.length] = new Option( + "Yellow", + "5" + ); + colorselect.options[colorselect.options.length] = new Option("Grey", "6"); + colorselect.options[colorselect.options.length] = new Option("Pink", "7"); + colorselect.options[colorselect.options.length] = new Option("Cyan", "8"); + } + + if (args.includes("cccc_ic_support")) { + document.getElementById("cccc")!.style.display = ""; + document.getElementById("pairing")!.style.display = ""; + } + + if (args.includes("flipping")) { + document.getElementById("button_flip")!.style.display = ""; + } + + if (args.includes("looping_sfx")) { + document.getElementById("button_shake")!.style.display = ""; + document.getElementById("2.7")!.style.display = ""; + } + + if (args.includes("effects")) { + document.getElementById("2.8")!.style.display = ""; + } + + if (args.includes("y_offset")) { + document.getElementById("y_offset")!.style.display = ""; + } +} diff --git a/webAO/packets/handlers/handleFM.ts b/webAO/packets/handlers/handleFM.ts new file mode 100644 index 0000000..fce10e3 --- /dev/null +++ b/webAO/packets/handlers/handleFM.ts @@ -0,0 +1,16 @@ +import { client } from "../../client"; +import { addTrack } from "../../client/addTrack"; +import { safeTags } from "../../encoding"; + +/** + * Handles updated music list + * @param {Array} args packet arguments + */ +export const handleFM = (args: string[]) => { + client.resetMusicList(); + + for (let i = 1; i < args.length - 1; i++) { + // Check when found the song for the first time + addTrack(safeTags(args[i])); + } +} diff --git a/webAO/packets/handlers/handleHI.ts b/webAO/packets/handlers/handleHI.ts new file mode 100644 index 0000000..b4f00a8 --- /dev/null +++ b/webAO/packets/handlers/handleHI.ts @@ -0,0 +1,14 @@ +import { client } from "../../client"; +const version = process.env.npm_package_version; + + +/** + * Handle the player + * @param {Array} args packet arguments + */ +export const handleHI = (_args: string[]) => { + client.sender.sendSelf(`ID#1#webAO#${version}#%`); + client.sender.sendSelf( + "FL#fastloading#yellowtext#cccc_ic_support#flipping#looping_sfx#effects#%" + ); +} diff --git a/webAO/packets/handlers/handleHP.ts b/webAO/packets/handlers/handleHP.ts new file mode 100644 index 0000000..f365590 --- /dev/null +++ b/webAO/packets/handlers/handleHP.ts @@ -0,0 +1,23 @@ +import { client } from "../../client"; + + + /** + * Handles a change in the health bars' states. + * @param {Array} args packet arguments + */ +export const handleHP = (args: string[]) => { + const percent_hp = Number(args[2]) * 10; + let healthbox; + if (args[1] === "1") { + // Def hp + client.hp[0] = Number(args[2]); + healthbox = document.getElementById("client_defense_hp"); + } else { + // Pro hp + client.hp[1] = Number(args[2]); + healthbox = document.getElementById("client_prosecutor_hp"); + } + (<HTMLElement>( + healthbox.getElementsByClassName("health-bar")[0] + )).style.width = `${percent_hp}%`; + }
\ No newline at end of file diff --git a/webAO/packets/handlers/handleID.ts b/webAO/packets/handlers/handleID.ts new file mode 100644 index 0000000..cd7b6ed --- /dev/null +++ b/webAO/packets/handlers/handleID.ts @@ -0,0 +1,24 @@ +import { client, setOldLoading } from "../../client"; + + +/** + * Identifies the server and issues a playerID + * @param {Array} args packet arguments + */ +export const handleID = (args: string[]) => { + client.playerID = Number(args[1]); + const serverSoftware = args[2].split("&")[0]; + let serverVersion; + if (serverSoftware === "serverD") { + serverVersion = args[2].split("&")[1]; + } else if (serverSoftware === "webAO") { + setOldLoading(false); + client.sender.sendSelf("PN#0#1#%"); + } else { + serverVersion = args[3]; + } + + if (serverSoftware === "serverD" && serverVersion === "1377.152") { + setOldLoading(true); + } // bugged version +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleJD.ts b/webAO/packets/handlers/handleJD.ts new file mode 100644 index 0000000..98d7988 --- /dev/null +++ b/webAO/packets/handlers/handleJD.ts @@ -0,0 +1,13 @@ +/** +* show/hide judge controls +* @param {number} show either a 1 or a 0 +*/ +export const handleJD = (args: string[]) => { + if (Number(args[1]) === 1) { + document.getElementById("judge_action")!.style.display = "inline-table"; + document.getElementById("no_action")!.style.display = "none"; + } else { + document.getElementById("judge_action")!.style.display = "none"; + document.getElementById("no_action")!.style.display = "inline-table"; + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleKB.ts b/webAO/packets/handlers/handleKB.ts new file mode 100644 index 0000000..b0aa2b2 --- /dev/null +++ b/webAO/packets/handlers/handleKB.ts @@ -0,0 +1,13 @@ +import { setBanned } from "../../client"; +import { safeTags } from "../../encoding"; +import { handleBans } from '../../client/handleBans' + +/** + * Handles the banned packet + * this one is sent when you are kicked off the server + * @param {Array} args ban reason + */ +export const handleKB = (args: string[]) => { + handleBans("Banned", safeTags(args[1])); + setBanned(true); +} diff --git a/webAO/packets/handlers/handleKK.ts b/webAO/packets/handlers/handleKK.ts new file mode 100644 index 0000000..c8a97b1 --- /dev/null +++ b/webAO/packets/handlers/handleKK.ts @@ -0,0 +1,10 @@ +import { safeTags } from "../../encoding"; +import { handleBans } from '../../client/handleBans' + +/** + * Handles the kicked packet + * @param {Array} args kick reason + */ +export const handleKK = (args: string[]) => { + handleBans("Kicked", safeTags(args[1])); +} diff --git a/webAO/packets/handlers/handleLE.ts b/webAO/packets/handlers/handleLE.ts new file mode 100644 index 0000000..1eaeb27 --- /dev/null +++ b/webAO/packets/handlers/handleLE.ts @@ -0,0 +1,35 @@ +import { client } from '../../client' +import { AO_HOST } from '../../client/aoHost'; +import { prepChat, safeTags } from '../../encoding'; + +/** + * Handles incoming evidence list, all evidences at once + * item per packet. + * + * @param {Array} args packet arguments + */ +export const handleLE = (args: string[]) => { + client.evidences = []; + for (let i = 1; i < args.length - 1; i++) { + (<HTMLProgressElement>( + document.getElementById("client_loadingbar") + )).value = client.char_list_length + i; + const arg = args[i].split("&"); + client.evidences[i - 1] = { + name: prepChat(arg[0]), + desc: prepChat(arg[1]), + filename: safeTags(arg[2]), + icon: `${AO_HOST}evidence/${encodeURI(arg[2].toLowerCase())}`, + }; + } + + const evidence_box = document.getElementById("evidences")!; + evidence_box.innerHTML = ""; + for (let i = 1; i <= client.evidences.length; i++) { + evidence_box.innerHTML += `<img src="${client.evidences[i - 1].icon}" + id="evi_${i}" + alt="${client.evidences[i - 1].name}" + class="evi_icon" + onclick="pickEvidence(${i})">`; + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleMC.ts b/webAO/packets/handlers/handleMC.ts new file mode 100644 index 0000000..aeb178d --- /dev/null +++ b/webAO/packets/handlers/handleMC.ts @@ -0,0 +1,43 @@ +import { prepChat } from "../../encoding"; +import { client } from '../../client' +import { AO_HOST } from "../../client/aoHost"; +import { appendICLog } from '../../client/appendICLog' + +/** + * Handles a music change to an arbitrary resource. + * @param {Array} args packet arguments + */ +export const handleMC = (args: string[]) => { + const track = prepChat(args[1]); + let charID = Number(args[2]); + const showname = args[3] || ""; + const looping = Boolean(args[4]); + const channel = Number(args[5]) || 0; + // const fading = Number(args[6]) || 0; // unused in web + + const music = client.viewport.music[channel]; + let musicname; + music.pause(); + if (track.startsWith("http")) { + music.src = track; + } else { + music.src = `${AO_HOST}sounds/music/${encodeURI(track.toLowerCase())}`; + } + music.loop = looping; + music.play(); + + try { + musicname = client.chars[charID].name; + } catch (e) { + charID = -1; + } + + if (charID >= 0) { + musicname = client.chars[charID].name; + appendICLog(`${musicname} changed music to ${track}`); + } else { + appendICLog(`The music was changed to ${track}`); + } + + document.getElementById("client_trackstatustext")!.innerText = track; +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleMM.ts b/webAO/packets/handlers/handleMM.ts new file mode 100644 index 0000000..077140f --- /dev/null +++ b/webAO/packets/handlers/handleMM.ts @@ -0,0 +1,8 @@ + +/** + * Handles the "MusicMode" packet + * @param {Array} args packet arguments + */ +export const handleMM = (_args: string[]) => { + // It's unused nowadays, as preventing people from changing the music is now serverside +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleMS.ts b/webAO/packets/handlers/handleMS.ts new file mode 100644 index 0000000..92d65db --- /dev/null +++ b/webAO/packets/handlers/handleMS.ts @@ -0,0 +1,165 @@ +import { client, extrafeatures, UPDATE_INTERVAL } from "../../client"; +import { handleCharacterInfo } from "../../client/handleCharacterInfo"; +import { resetICParams } from "../../client/resetICParams"; +import { prepChat, safeTags } from "../../encoding"; +import { handle_ic_speaking } from '../../viewport/utils/handleICSpeaking' +/** + * Handles an in-character chat message. + * @param {*} args packet arguments + */ +export const handleMS = (args: string[]) => { + // TODO: this if-statement might be a bug. + if (args[4] !== client.viewport.getChatmsg().content) { + document.getElementById("client_inner_chat")!.innerHTML = ""; + + const char_id = Number(args[9]); + const char_name = safeTags(args[3]); + + let msg_nameplate = args[3]; + let msg_blips = "male"; + let char_chatbox = "default"; + let char_muted = false; + + if (char_id < client.char_list_length && char_id >= 0) { + if (client.chars[char_id].name !== char_name) { + console.info( + `${client.chars[char_id].name} is iniediting to ${char_name}` + ); + const chargs = (`${char_name}&` + "iniediter").split("&"); + handleCharacterInfo(chargs, char_id); + } + } + + try { + msg_nameplate = client.chars[char_id].showname; + } catch (e) { + msg_nameplate = args[3]; + } + + try { + msg_blips = client.chars[char_id].blips; + } catch (e) { } + + try { + char_chatbox = client.chars[char_id].chat; + } catch (e) { + char_chatbox = "default"; + } + + try { + char_muted = client.chars[char_id].muted; + } catch (e) { + char_muted = false; + console.error("we're still missing some character data"); + } + + if (char_muted === false) { + let chatmsg = { + deskmod: Number(safeTags(args[1]).toLowerCase()), + preanim: safeTags(args[2]).toLowerCase(), // get preanim + nameplate: msg_nameplate, + chatbox: char_chatbox, + name: char_name, + sprite: safeTags(args[4]).toLowerCase(), + content: prepChat(args[5]), // Escape HTML tags + side: args[6].toLowerCase(), + sound: safeTags(args[7]).toLowerCase(), + blips: safeTags(msg_blips), + type: Number(args[8]), + charid: char_id, + snddelay: Number(args[10]), + objection: Number(args[11]), + evidence: Number(safeTags(args[12])), + flip: Number(args[13]), + flash: Number(args[14]), + color: Number(args[15]), + speed: UPDATE_INTERVAL, + }; + + if (extrafeatures.includes("cccc_ic_support")) { + const extra_cccc = { + showname: safeTags(args[16]), + other_charid: Number(args[17]), + other_name: safeTags(args[18]), + other_emote: safeTags(args[19]), + self_offset: args[20].split("<and>"), // HACK: here as well, client is fucked and uses this instead of & + other_offset: args[21].split("<and>"), + other_flip: Number(args[22]), + noninterrupting_preanim: Number(args[23]), + }; + chatmsg = Object.assign(extra_cccc, chatmsg); + + if (extrafeatures.includes("looping_sfx")) { + const extra_27 = { + looping_sfx: Number(args[24]), + screenshake: Number(args[25]), + frame_screenshake: safeTags(args[26]), + frame_realization: safeTags(args[27]), + frame_sfx: safeTags(args[28]), + }; + chatmsg = Object.assign(extra_27, chatmsg); + + if (extrafeatures.includes("effects")) { + const extra_28 = { + additive: Number(args[29]), + effects: args[30].split("|"), + }; + chatmsg = Object.assign(extra_28, chatmsg); + } else { + const extra_28 = { + additive: 0, + effects: ["", "", ""], + }; + chatmsg = Object.assign(extra_28, chatmsg); + } + } else { + const extra_27 = { + looping_sfx: 0, + screenshake: 0, + frame_screenshake: "", + frame_realization: "", + frame_sfx: "", + }; + chatmsg = Object.assign(extra_27, chatmsg); + const extra_28 = { + additive: 0, + effects: ["", "", ""], + }; + chatmsg = Object.assign(extra_28, chatmsg); + } + } else { + const extra_cccc = { + showname: "", + other_charid: 0, + other_name: "", + other_emote: "", + self_offset: [0, 0], + other_offset: [0, 0], + other_flip: 0, + noninterrupting_preanim: 0, + }; + chatmsg = Object.assign(extra_cccc, chatmsg); + const extra_27 = { + looping_sfx: 0, + screenshake: 0, + frame_screenshake: "", + frame_realization: "", + frame_sfx: "", + }; + chatmsg = Object.assign(extra_27, chatmsg); + const extra_28 = { + additive: 0, + effects: ["", "", ""], + }; + chatmsg = Object.assign(extra_28, chatmsg); + } + + // our own message appeared, reset the buttons + if (chatmsg.charid === client.charID) { + resetICParams(); + } + + handle_ic_speaking(chatmsg); // no await + } + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handlePN.ts b/webAO/packets/handlers/handlePN.ts new file mode 100644 index 0000000..1b66fb9 --- /dev/null +++ b/webAO/packets/handlers/handlePN.ts @@ -0,0 +1,9 @@ +import { client } from "../../client"; + +/** + * Indicates how many users are on this server + * @param {Array} args packet arguments + */ +export const handlePN = (_args: string[]) => { + client.sender.sendServer("askchaa#%"); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handlePV.ts b/webAO/packets/handlers/handlePV.ts new file mode 100644 index 0000000..3c669b9 --- /dev/null +++ b/webAO/packets/handlers/handlePV.ts @@ -0,0 +1,85 @@ +import { client } from "../../client"; +import fileExists from "../../utils/fileExists"; +import { updateActionCommands } from '../../dom/updateActionCommands' +import { pickEmotion } from '../../dom/pickEmotion' +import { AO_HOST } from "../../client/aoHost"; + +/** + * Handles the server's assignment of a character for the player to use. + * PV # playerID (unused) # CID # character ID + * @param {Array} args packet arguments + */ +export const handlePV = async (args: string[]) => { + client.charID = Number(args[3]); + document.getElementById("client_waiting")!.style.display = "none"; + document.getElementById("client_charselect")!.style.display = "none"; + + const me = client.chars[client.charID]; + client.selectedEmote = -1; + const { emotes } = client; + const emotesList = document.getElementById("client_emo")!; + emotesList.style.display = ""; + emotesList.innerHTML = ""; // Clear emote box + const ini = me.inifile; + me.side = ini.options.side; + updateActionCommands(me.side); + if (ini.emotions.number === 0) { + emotesList.innerHTML = `<span + id="emo_0" + alt="unavailable" + class="emote_button">No emotes available</span>`; + } else { + for (let i = 1; i <= ini.emotions.number; i++) { + try { + const emoteinfo = ini.emotions[i].split("#"); + let esfx; + let esfxd; + try { + esfx = ini.soundn[i] || "0"; + esfxd = Number(ini.soundt[i]) || 0; + } catch (e) { + console.warn("ini sound is completly missing"); + esfx = "0"; + esfxd = 0; + } + // Make sure the asset server is case insensitive, or that everything on it is lowercase + + emotes[i] = { + desc: emoteinfo[0].toLowerCase(), + preanim: emoteinfo[1].toLowerCase(), + emote: emoteinfo[2].toLowerCase(), + zoom: Number(emoteinfo[3]) || 0, + deskmod: Number(emoteinfo[4]) || 1, + sfx: esfx.toLowerCase(), + sfxdelay: esfxd, + frame_screenshake: "", + frame_realization: "", + frame_sfx: "", + button: `${AO_HOST}characters/${encodeURI( + me.name.toLowerCase() + )}/emotions/button${i}_off.png`, + }; + emotesList.innerHTML += `<img src=${emotes[i].button} + id="emo_${i}" + alt="${emotes[i].desc}" + title="${emotes[i].desc}" + class="emote_button" + onclick="pickEmotion(${i})">`; + } catch (e) { + console.error(`missing emote ${i}`); + } + } + pickEmotion(1); + } + + if ( + await fileExists( + `${AO_HOST}characters/${encodeURI(me.name.toLowerCase())}/custom.gif` + ) + ) { + document.getElementById("button_4")!.style.display = ""; + } else { + document.getElementById("button_4")!.style.display = "none"; + } + +} diff --git a/webAO/packets/handlers/handleRC.ts b/webAO/packets/handlers/handleRC.ts new file mode 100644 index 0000000..0b5679f --- /dev/null +++ b/webAO/packets/handlers/handleRC.ts @@ -0,0 +1,10 @@ +import { client } from "../../client"; +import vanilla_character_arr from "../../constants/characters.js"; + +/** + * we are asking ourselves what characters there are + * @param {Array} args packet arguments + */ +export const handleRC = (_args: string[]) => { + client.sender.sendSelf(`SC#${vanilla_character_arr.join("#")}#%`); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleRD.ts b/webAO/packets/handlers/handleRD.ts new file mode 100644 index 0000000..dde994c --- /dev/null +++ b/webAO/packets/handlers/handleRD.ts @@ -0,0 +1,18 @@ +import { client } from "../../client"; + + +/** + * we are asking ourselves what characters there are + * @param {Array} args packet arguments + */ +export const handleRD = (_args: string[]) => { + client.sender.sendSelf("BN#gs4#%"); + client.sender.sendSelf("DONE#%"); + const ooclog = <HTMLInputElement>document.getElementById("client_ooclog"); + ooclog.value = ""; + ooclog.readOnly = false; + + document.getElementById("client_oocinput")!.style.display = "none"; + document.getElementById("client_replaycontrols")!.style.display = + "inline-block"; +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleRM.ts b/webAO/packets/handlers/handleRM.ts new file mode 100644 index 0000000..c18821b --- /dev/null +++ b/webAO/packets/handlers/handleRM.ts @@ -0,0 +1,10 @@ +import {client} from '../../client' +import vanilla_music_arr from "../../constants/music.js"; + + /** + * we are asking ourselves what characters there are + * @param {Array} args packet arguments + */ +export const handleRM = (_args: string[]) => { + client.sender.sendSelf(`SM#${vanilla_music_arr.join("#")}#%`); + }
\ No newline at end of file diff --git a/webAO/packets/handlers/handleRMC.ts b/webAO/packets/handlers/handleRMC.ts new file mode 100644 index 0000000..ada1ad2 --- /dev/null +++ b/webAO/packets/handlers/handleRMC.ts @@ -0,0 +1,24 @@ +import { client } from '../../client' +// TODO BUG: +// this.viewport.music is an array. Therefore you must access elements +/** + * Handles a music change to an arbitrary resource, with an offset in seconds. + * @param {Array} args packet arguments + */ +export const handleRMC = (args: string[]) => { + client.viewport.music.pause(); + const { music } = client.viewport; + // Music offset + drift from song loading + music.totime = args[1]; + music.offset = new Date().getTime() / 1000; + music.addEventListener( + "loadedmetadata", + () => { + music.currentTime += parseFloat( + music.totime + (new Date().getTime() / 1000 - music.offset) + ).toFixed(3); + music.play(); + }, + false + ); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleRT.ts b/webAO/packets/handlers/handleRT.ts new file mode 100644 index 0000000..62ebb1e --- /dev/null +++ b/webAO/packets/handlers/handleRT.ts @@ -0,0 +1,25 @@ +import { client } from "../../client"; +import { initTestimonyUpdater } from '../../viewport/utils/initTestimonyUpdater' + +/** + * Handles a testimony states. + * @param {Array} args packet arguments + */ +export const handleRT = (args: string[]) => { + const judgeid = Number(args[2]); + switch (args[1]) { + case "testimony1": + client.testimonyID = 1; + break; + case "testimony2": + // Cross Examination + client.testimonyID = 2; + break; + case "judgeruling": + client.testimonyID = 3 + judgeid; + break; + default: + console.warn("Invalid testimony"); + } + initTestimonyUpdater(); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleSC.ts b/webAO/packets/handlers/handleSC.ts new file mode 100644 index 0000000..b42a4cd --- /dev/null +++ b/webAO/packets/handlers/handleSC.ts @@ -0,0 +1,38 @@ +import queryParser from "../../utils/queryParser"; + +import { client } from '../../client' +import { handleCharacterInfo } from "../../client/handleCharacterInfo"; +let { mode } = queryParser(); + +/** + * Handles incoming character information, containing all characters + * in one packet. + * @param {Array} args packet arguments + */ +export const handleSC = async (args: string[]) => { + const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); + + if (mode === "watch") { + // Spectators don't need to pick a character + document.getElementById("client_charselect")!.style.display = "none"; + } else { + document.getElementById("client_charselect")!.style.display = "block"; + } + + document.getElementById("client_loadingtext")!.innerHTML = + "Loading Characters"; + for (let i = 1; i < args.length - 1; i++) { + document.getElementById( + "client_loadingtext" + )!.innerHTML = `Loading Character ${i}/${client.char_list_length}`; + const chargs = args[i].split("&"); + const charid = i - 1; + (<HTMLProgressElement>( + document.getElementById("client_loadingbar") + )).value = charid; + await sleep(0.1); // TODO: Too many network calls without this. net::ERR_INSUFFICIENT_RESOURCES + handleCharacterInfo(chargs, charid); + } + // We're done with the characters, request the music + client.sender.sendServer("RM#%"); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleSI.ts b/webAO/packets/handlers/handleSI.ts new file mode 100644 index 0000000..b32fbc1 --- /dev/null +++ b/webAO/packets/handlers/handleSI.ts @@ -0,0 +1,41 @@ +import { client, extrafeatures, oldLoading } from "../../client"; + + +/** + * Received when the server announces its server info, + * but we use it as a cue to begin retrieving characters. + * @param {Array} args packet arguments + */ +export const handleSI = (args: string[]) => { + client.char_list_length = Number(args[1]); + client.char_list_length += 1; // some servers count starting from 0 some from 1... + client.evidence_list_length = Number(args[2]); + client.music_list_length = Number(args[3]); + + (<HTMLProgressElement>document.getElementById("client_loadingbar")).max = + client.char_list_length + + client.evidence_list_length + + client.music_list_length; + + // create the charselect grid, to be filled by the character loader + document.getElementById("client_chartable")!.innerHTML = ""; + + for (let i = 0; i < client.char_list_length; i++) { + const demothing = document.createElement("img"); + + demothing.className = "demothing"; + demothing.id = `demo_${i}`; + const demoonclick = document.createAttribute("onclick"); + demoonclick.value = `pickChar(${i})`; + demothing.setAttributeNode(demoonclick); + + document.getElementById("client_chartable")!.appendChild(demothing); + } + + // this is determined at the top of this file + if (!oldLoading && extrafeatures.includes("fastloading")) { + client.sender.sendServer("RC#%"); + } else { + client.sender.sendServer("askchar2#%"); + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleSM.ts b/webAO/packets/handlers/handleSM.ts new file mode 100644 index 0000000..08bf7e0 --- /dev/null +++ b/webAO/packets/handlers/handleSM.ts @@ -0,0 +1,41 @@ +import { client } from '../../client' +import { addTrack } from '../../client/addTrack' +import { isAudio } from '../../client/isAudio' +import { fix_last_area } from '../../client/fixLastArea' +import { createArea } from '../../client/createArea' +/** + * Handles incoming music information, containing all music in one packet. + * @param {Array} args packet arguments + */ +export const handleSM = (args: string[]) => { + document.getElementById("client_loadingtext")!.innerHTML = "Loading Music "; + client.resetMusicList(); + client.resetAreaList(); + + client.musics_time = false; + + for (let i = 1; i < args.length - 1; i++) { + // Check when found the song for the first time + const trackname = args[i]; + const trackindex = i - 1; + document.getElementById( + "client_loadingtext" + )!.innerHTML = `Loading Music ${i}/${client.music_list_length}`; + (<HTMLProgressElement>( + document.getElementById("client_loadingbar") + )).value = client.char_list_length + client.evidence_list_length + i; + if (client.musics_time) { + addTrack(trackname); + } else if (isAudio(trackname)) { + client.musics_time = true; + fix_last_area(); + addTrack(trackname); + } else { + createArea(trackindex, trackname); + } + + } + + // Music done, carry on + client.sender.sendServer("RD#%"); +} diff --git a/webAO/packets/handlers/handleSP.ts b/webAO/packets/handlers/handleSP.ts new file mode 100644 index 0000000..e176eeb --- /dev/null +++ b/webAO/packets/handlers/handleSP.ts @@ -0,0 +1,8 @@ +import { updateActionCommands } from '../../dom/updateActionCommands' +/** +* position change +* @param {string} pos new position +*/ +export const handleSP = (args: string[]) => { + updateActionCommands(args[1]); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleTI.ts b/webAO/packets/handlers/handleTI.ts new file mode 100644 index 0000000..e418088 --- /dev/null +++ b/webAO/packets/handlers/handleTI.ts @@ -0,0 +1,21 @@ +/** + * Handles a timer update + * @param {Array} args packet arguments + */ +export const handleTI = (args: string[]) => { + const timerid = Number(args[1]); + const type = Number(args[2]); + const timer_value = args[3]; + switch (type) { + case 0: + // + case 1: + document.getElementById(`client_timer${timerid}`)!.innerText = + timer_value; + case 2: + document.getElementById(`client_timer${timerid}`)!.style.display = ""; + case 3: + document.getElementById(`client_timer${timerid}`)!.style.display = + "none"; + } +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleZZ.ts b/webAO/packets/handlers/handleZZ.ts new file mode 100644 index 0000000..1c1cb1d --- /dev/null +++ b/webAO/packets/handlers/handleZZ.ts @@ -0,0 +1,23 @@ +import { client } from "../../client"; +import { AO_HOST } from "../../client/aoHost"; +import { prepChat } from "../../encoding"; + + +/** + * Handles a modcall + * @param {Array} args packet arguments + */ +export const handleZZ = (args: string[]) => { + const oocLog = document.getElementById("client_ooclog")!; + oocLog.innerHTML += `$Alert: ${prepChat(args[1])}\r\n`; + if (oocLog.scrollTop > oocLog.scrollHeight - 60) { + oocLog.scrollTop = oocLog.scrollHeight; + } + + client.viewport.getSfxAudio().pause(); + const oldvolume = client.viewport.getSfxAudio().volume; + client.viewport.getSfxAudio().volume = 1; + client.viewport.getSfxAudio().src = `${AO_HOST}sounds/general/sfx-gallery.opus`; + client.viewport.getSfxAudio().play(); + client.viewport.getSfxAudio().volume = oldvolume; +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleackMS.ts b/webAO/packets/handlers/handleackMS.ts new file mode 100644 index 0000000..dcca118 --- /dev/null +++ b/webAO/packets/handlers/handleackMS.ts @@ -0,0 +1,8 @@ +import { resetICParams } from '../../client/resetICParams' + +/** +* server got our message +*/ +export const handleackMS = () => { + resetICParams(); +}
\ No newline at end of file diff --git a/webAO/packets/handlers/handleaskchaa.ts b/webAO/packets/handlers/handleaskchaa.ts new file mode 100644 index 0000000..0f9e730 --- /dev/null +++ b/webAO/packets/handlers/handleaskchaa.ts @@ -0,0 +1,10 @@ +import { client } from "../../client"; +import vanilla_character_arr from "../../constants/characters.js"; + +/** + * What? you want a character list from me?? + * @param {Array} args packet arguments + */ +export const handleaskchaa = (_args: string[]) => { + client.sender.sendSelf(`SI#${vanilla_character_arr.length}#0#0#%`); +} diff --git a/webAO/packets/ms.js b/webAO/packets/ms.js deleted file mode 100644 index 26851bd..0000000 --- a/webAO/packets/ms.js +++ /dev/null @@ -1,28 +0,0 @@ -export default { - deskmod, - preanim, - name, - emote, - message, - side, - sfx_name, - emote_modifier, - sfx_delay, - objection_modifier, - evidence, - flip, - realization, - text_color, - showname, - other_charid, - self_hoffset, - self_yoffset, - noninterrupting_preanim, - looping_sfx, - screenshake, - frame_screenshake, - frame_realization, - frame_sfx, - additive, - effect, -}; diff --git a/webAO/packets/packetHandler.ts b/webAO/packets/packetHandler.ts new file mode 100644 index 0000000..a9b567a --- /dev/null +++ b/webAO/packets/packetHandler.ts @@ -0,0 +1,3 @@ +import { packets } from './packets' + +export const packetHandler = new Map(Object.entries(packets))
\ No newline at end of file diff --git a/webAO/packets/packets.ts b/webAO/packets/packets.ts new file mode 100644 index 0000000..79c43c1 --- /dev/null +++ b/webAO/packets/packets.ts @@ -0,0 +1,86 @@ +import { handleMS } from './handlers/handleMS'; +import { handleCT } from './handlers/handleCT' +import { handleMC } from './handlers/handleMC' +import { handleRMC } from './handlers/handleRMC' +import { handleFL } from './handlers/handleFL' +import { handleLE } from './handlers/handleLE' +import { handleEM } from './handlers/handleEM' +import { handleEI } from './handlers/handleEI' +import { handleSC } from './handlers/handleSC' +import { handleCI } from './handlers/handleCI' +import { handleFM } from './handlers/handleFM' +import { handleFA } from './handlers/handleFA' +import { handleSM } from './handlers/handleSM' +import { handleMM } from './handlers/handleMM' +import { handleBD } from './handlers/handleBD' +import { handleBB } from './handlers/handleBB' +import { handleKB } from './handlers/handleKB' +import { handleKK } from './handlers/handleKK' +import { handleDONE } from './handlers/handleDONE' +import { handleBN } from './handlers/handleBN' +import { handleHP } from './handlers/handleHP' +import { handleRT } from './handlers/handleRT' +import { handleTI } from './handlers/handleTI' +import { handleZZ } from './handlers/handleZZ' +import { handleHI } from './handlers/handleHI' +import { handleID } from './handlers/handleID' +import { handlePN } from './handlers/handlePN' +import { handleSI } from './handlers/handleSI' +import { handleARUP } from './handlers/handleARUP' +import { handleaskchaa } from './handlers/handleaskchaa' +import { handleCC } from './handlers/handleCC' +import { handleRC } from './handlers/handleRC' +import { handleRM } from './handlers/handleRM' +import { handleRD } from './handlers/handleRD' +import { handleCharsCheck } from './handlers/handleCharsCheck' +import { handlePV } from './handlers/handlePV' +import { handleASS } from './handlers/handleASS' +import { handleackMS } from './handlers/handleackMS' +import { handleSP } from './handlers/handleSP' +import { handleJD } from './handlers/handleJD' + +export const packets = { + "MS": handleMS, + "CT": handleCT, + "MC": handleMC, + "RMC": handleRMC, + "CI": handleCI, + "SC": handleSC, + "EI": handleEI, + "FL": handleFL, + "LE": handleLE, + "EM": handleEM, + "FM": handleFM, + "FA": handleFA, + "SM": handleSM, + "MM": handleMM, + "BD": handleBD, + "BB": handleBB, + "KB": handleKB, + "KK": handleKK, + "DONE": handleDONE, + "BN": handleBN, + "HP": handleHP, + "RT": handleRT, + "TI": handleTI, + "ZZ": handleZZ, + "HI": handleHI, + "ID": handleID, + "PN": handlePN, + "SI": handleSI, + "ARUP": handleARUP, + "askchaa": handleaskchaa, + "CC": handleCC, + "RC": handleRC, + "RM": handleRM, + "RD": handleRD, + "CharsCheck": handleCharsCheck, + "PV": handlePV, + "ASS": handleASS, + "ackMS": handleackMS, + "SP": handleSP, + "JD": handleJD, + "decryptor": () => { }, + "CHECK": () => { }, + "CH": () => { }, +}
\ No newline at end of file |
