aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--webAO/client.ts478
-rw-r--r--webAO/client/addTrack.ts15
-rw-r--r--webAO/client/appendICLog.ts57
-rw-r--r--webAO/client/checkCallword.ts17
-rw-r--r--webAO/client/createArea.ts30
-rw-r--r--webAO/client/fetchLists.ts60
-rw-r--r--webAO/client/fixLastArea.ts15
-rw-r--r--webAO/client/handleBans.ts17
-rw-r--r--webAO/client/handleCharacterInfo.ts105
-rw-r--r--webAO/client/isAudio.ts6
-rw-r--r--webAO/client/isLowMemory.ts10
-rw-r--r--webAO/client/loadResources.ts79
-rw-r--r--webAO/client/resetICParams.ts21
-rw-r--r--webAO/client/saveChatLogHandle.ts26
-rw-r--r--webAO/client/sender/sendOOC.ts4
-rw-r--r--webAO/dom/iniEdit.ts3
-rw-r--r--webAO/dom/showNameClick.ts2
-rw-r--r--webAO/packets/handlers/handleBD.ts5
-rw-r--r--webAO/packets/handlers/handleCI.ts3
-rw-r--r--webAO/packets/handlers/handleEM.ts14
-rw-r--r--webAO/packets/handlers/handleFA.ts3
-rw-r--r--webAO/packets/handlers/handleFM.ts4
-rw-r--r--webAO/packets/handlers/handleKB.ts5
-rw-r--r--webAO/packets/handlers/handleKK.ts5
-rw-r--r--webAO/packets/handlers/handleMC.ts3
-rw-r--r--webAO/packets/handlers/handleMS.ts226
-rw-r--r--webAO/packets/handlers/handleSC.ts3
-rw-r--r--webAO/packets/handlers/handleSM.ts15
-rw-r--r--webAO/packets/handlers/handleackMS.ts2
-rw-r--r--webAO/viewport.ts25
30 files changed, 643 insertions, 615 deletions
diff --git a/webAO/client.ts b/webAO/client.ts
index e92489c..8b2f691 100644
--- a/webAO/client.ts
+++ b/webAO/client.ts
@@ -3,36 +3,18 @@
* made by sD, refactored by oldmud0 and Qubrick
* credits to aleks for original idea and source
*/
-
+import { isLowMemory } from './client/isLowMemory'
import FingerprintJS from "@fingerprintjs/fingerprintjs";
-import vanilla_background_arr from "./constants/backgrounds.js";
-import vanilla_evidence_arr from "./constants/evidence.js";
-import {sender, ISender} from './client/sender/index'
-import iniParse from "./iniParse";
-import getCookie from "./utils/getCookie";
-import setCookie from "./utils/setCookie";
-import fileExists from "./utils/fileExists.js";
+import { sender, ISender } from './client/sender/index'
import queryParser from "./utils/queryParser";
import getResources from "./utils/getResources.js";
-import downloadFile from "./services/downloadFile";
import masterViewport, { Viewport } from "./viewport";
import { EventEmitter } from "events";
-import { area_click } from './dom/areaClick'
import { onReplayGo } from './dom/onReplayGo'
-import { escapeChat, safeTags, unescapeChat } from "./encoding";
-import { setChatbox } from "./dom/setChatbox";
-import { request } from "./services/request.js";
-import {
- changeShoutVolume,
- changeSFXVolume,
- changeTestimonyVolume,
-} from "./dom/changeVolume.js";
-import { getFilenameFromPath } from "./utils/paths";
import { packetHandler } from './packets/packetHandler'
-import { showname_click } from './dom/showNameClick'
+import { loadResources } from './client/loadResources'
import { AO_HOST } from './client/aoHost'
-
-const version = process.env.npm_package_version;
+import { fetchBackgroundList, fetchEvidenceList } from './client/fetchLists'
let { ip: serverIP, mode, theme } = queryParser();
let THEME: string = theme || "default";
@@ -77,38 +59,25 @@ export const setBanned = (val: boolean) => {
}
let hdid: string;
-function isLowMemory() {
- if (
- /webOS|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|PlayStation|Nintendo|Opera Mini/i.test(
- navigator.userAgent
- )
- ) {
- oldLoading = true;
- }
-}
-
const fpPromise = FingerprintJS.load();
-const connect = (address: string) => {
-}
fpPromise
.then((fp) => fp.get())
.then((result) => {
hdid = result.visitorId;
- console.log("NEW CLIENT");
- // Create the new client and connect it
client = new Client(serverIP);
client.connect()
-
- isLowMemory();
+ client.isLowMemory();
client.loadResources();
});
export const delay = (ms: number) => new Promise((res) => setTimeout(res, ms));
-let lastICMessageTime = new Date(0);
-
+export let lastICMessageTime = new Date(0);
+export const setLastICMessageTime = (val: Date) => {
+ lastICMessageTime = val
+}
class Client extends EventEmitter {
serv: any;
hp: number[];
@@ -134,6 +103,8 @@ class Client extends EventEmitter {
_lastTimeICReceived: any;
viewport: Viewport;
connect: () => void;
+ loadResources: () => void
+ isLowMemory: () => void
constructor(address: string) {
super();
@@ -175,6 +146,8 @@ class Client extends EventEmitter {
this.sender = sender
this.viewport = masterViewport(this);
this._lastTimeICReceived = new Date(0);
+ loadResources
+ isLowMemory
}
/**
@@ -200,8 +173,6 @@ class Client extends EventEmitter {
: 0;
}
-
-
/**
* Hook for sending messages to the client
* @param {string} message the message to send
@@ -216,7 +187,6 @@ class Client extends EventEmitter {
* to the server.
*/
joinServer() {
- console.log(this.sender)
this.sender.sendServer(`HI#${hdid}#%`);
this.sender.sendServer("ID#webAO#webAO#%");
if (mode !== "replay") {
@@ -225,78 +195,6 @@ class Client extends EventEmitter {
}
/**
- * Load game resources and stored settings.
- */
- loadResources() {
- document.getElementById("client_version").innerText = `version ${version}`;
-
- // Load background array to select
- const background_select = <HTMLSelectElement>(
- document.getElementById("bg_select")
- );
- background_select.add(new Option("Custom", "0"));
- vanilla_background_arr.forEach((background) => {
- background_select.add(new Option(background));
- });
-
- // Load evidence array to select
- const evidence_select = <HTMLSelectElement>(
- document.getElementById("evi_select")
- );
- evidence_select.add(new Option("Custom", "0"));
- vanilla_evidence_arr.forEach((evidence) => {
- evidence_select.add(new Option(evidence));
- });
-
- // Read cookies and set the UI to its values
- (<HTMLInputElement>document.getElementById("OOC_name")).value =
- getCookie("OOC_name") ||
- `web${String(Math.round(Math.random() * 100 + 10))}`;
-
- // Read cookies and set the UI to its values
- const cookietheme = getCookie("theme") || "default";
-
- (<HTMLOptionElement>(
- document.querySelector(`#client_themeselect [value="${cookietheme}"]`)
- )).selected = true;
- this.viewport.reloadTheme();
-
- const cookiechatbox = getCookie("chatbox") || "dynamic";
-
- (<HTMLOptionElement>(
- document.querySelector(`#client_chatboxselect [value="${cookiechatbox}"]`)
- )).selected = true;
- setChatbox(cookiechatbox);
-
- (<HTMLInputElement>document.getElementById("client_mvolume")).value =
- getCookie("musicVolume") || "1";
- this.viewport.changeMusicVolume();
- (<HTMLAudioElement>document.getElementById("client_sfxaudio")).volume =
- Number(getCookie("sfxVolume")) || 1;
- changeSFXVolume();
- (<HTMLAudioElement>document.getElementById("client_shoutaudio")).volume =
- Number(getCookie("shoutVolume")) || 1;
- changeShoutVolume();
- (<HTMLAudioElement>(
- document.getElementById("client_testimonyaudio")
- )).volume = Number(getCookie("testimonyVolume")) || 1;
- changeTestimonyVolume();
- (<HTMLInputElement>document.getElementById("client_bvolume")).value =
- getCookie("blipVolume") || "1";
- this.viewport.changeBlipVolume();
-
- (<HTMLInputElement>document.getElementById("ic_chat_name")).value =
- getCookie("ic_chat_name");
- (<HTMLInputElement>document.getElementById("showname")).checked = Boolean(
- getCookie("showname")
- );
- showname_click(null);
-
- (<HTMLInputElement>document.getElementById("client_callwords")).value =
- getCookie("callwords");
- }
-
- /**
* Triggered when a connection is established to the server.
*/
onOpen(_e: Event) {
@@ -335,7 +233,6 @@ class Client extends EventEmitter {
packetHandler.has(packetHeader)
? packetHandler.get(packetHeader)(splitPacket)
: console.warn(`Invalid packet header ${packetHeader}`);
-
}
/**
@@ -353,7 +250,6 @@ class Client extends EventEmitter {
*/
cleanup() {
clearInterval(this.checkUpdater);
-
this.serv.close();
}
@@ -383,129 +279,6 @@ class Client extends EventEmitter {
}
}
- saveChatlogHandle = async () => {
- const clientLog = document.getElementById("client_log");
- const icMessageLogs = clientLog.getElementsByTagName("p");
- const messages = [];
-
- for (let i = 0; i < icMessageLogs.length; i++) {
- const SHOWNAME_POSITION = 0;
- const TEXT_POSITION = 2;
- const showname = icMessageLogs[i].children[SHOWNAME_POSITION].innerHTML;
- const text = icMessageLogs[i].children[TEXT_POSITION].innerHTML;
- const message = `${showname}: ${text}`;
- messages.push(message);
- }
- const d = new Date();
- let ye = new Intl.DateTimeFormat("en", { year: "numeric" }).format(d);
- let mo = new Intl.DateTimeFormat("en", { month: "short" }).format(d);
- let da = new Intl.DateTimeFormat("en", { day: "2-digit" }).format(d);
-
- const filename = `chatlog-${da}-${mo}-${ye}`.toLowerCase();
- downloadFile(messages.join("\n"), filename);
-
- // Reset Chatbox to Empty
- (<HTMLInputElement>document.getElementById("client_inputbox")).value = "";
- };
-
- /**
- * Handles the incoming character information, and downloads the sprite + ini for it
- * @param {Array} chargs packet arguments
- * @param {Number} charid character ID
- */
- async handleCharacterInfo(chargs: string[], charid: number) {
- const img = <HTMLImageElement>document.getElementById(`demo_${charid}`);
- if (chargs[0]) {
- let cini: any = {};
- const getCharIcon = async () => {
- const extensions = [".png", ".webp"];
- img.alt = chargs[0];
- const charIconBaseUrl = `${AO_HOST}characters/${encodeURI(
- chargs[0].toLowerCase()
- )}/char_icon`;
- for (let i = 0; i < extensions.length; i++) {
- const fileUrl = charIconBaseUrl + extensions[i];
- const exists = await fileExists(fileUrl);
- if (exists) {
- img.alt = chargs[0];
- img.title = chargs[0];
- img.src = fileUrl;
- return;
- }
- }
- };
- getCharIcon();
-
- // If the ini doesn't exist on the server this will throw an error
- try {
- const cinidata = await request(
- `${AO_HOST}characters/${encodeURI(chargs[0].toLowerCase())}/char.ini`
- );
- cini = iniParse(cinidata);
- } catch (err) {
- cini = {};
- img.classList.add("noini");
- console.warn(`character ${chargs[0]} is missing from webAO`);
- // If it does, give the user a visual indication that the character is unusable
- }
-
- const mute_select = <HTMLSelectElement>(
- document.getElementById("mute_select")
- );
- mute_select.add(new Option(safeTags(chargs[0]), String(charid)));
- const pair_select = <HTMLSelectElement>(
- document.getElementById("pair_select")
- );
- pair_select.add(new Option(safeTags(chargs[0]), String(charid)));
-
- // sometimes ini files lack important settings
- const default_options = {
- name: chargs[0],
- showname: chargs[0],
- side: "def",
- blips: "male",
- chat: "",
- category: "",
- };
- cini.options = Object.assign(default_options, cini.options);
-
- // sometimes ini files lack important settings
- const default_emotions = {
- number: 0,
- };
- cini.emotions = Object.assign(default_emotions, cini.emotions);
-
- this.chars[charid] = {
- name: safeTags(chargs[0]),
- showname: safeTags(cini.options.showname),
- desc: safeTags(chargs[1]),
- blips: safeTags(cini.options.blips).toLowerCase(),
- gender: safeTags(cini.options.gender).toLowerCase(),
- side: safeTags(cini.options.side).toLowerCase(),
- chat:
- cini.options.chat === ""
- ? safeTags(cini.options.category).toLowerCase()
- : safeTags(cini.options.chat).toLowerCase(),
- evidence: chargs[3],
- icon: img.src,
- inifile: cini,
- muted: false,
- };
-
- if (
- this.chars[charid].blips === "male" &&
- this.chars[charid].gender !== "male" &&
- this.chars[charid].gender !== ""
- ) {
- this.chars[charid].blips = this.chars[charid].gender;
- }
-
- } else {
- console.warn(`missing charid ${charid}`);
- img.style.display = "none";
- }
- }
-
resetMusicList() {
this.musics = [];
document.getElementById("client_musiclist").innerHTML = "";
@@ -515,231 +288,10 @@ class Client extends EventEmitter {
this.areas = [];
document.getElementById("areas").innerHTML = "";
- this.fetchBackgroundList();
- this.fetchEvidenceList();
- }
-
- async fetchBackgroundList() {
- try {
- const bgdata = await request(`${AO_HOST}backgrounds.json`);
- const bg_array = JSON.parse(bgdata);
- // the try catch will fail before here when there is no file
-
- const bg_select = <HTMLSelectElement>document.getElementById("bg_select");
- bg_select.innerHTML = "";
-
- bg_select.add(new Option("Custom", "0"));
- bg_array.forEach((background: string) => {
- bg_select.add(new Option(background));
- });
- } catch (err) {
- console.warn("there was no backgrounds.json file");
- }
- }
-
- async fetchCharacterList() {
- try {
- const chardata = await request(`${AO_HOST}characters.json`);
- const char_array = JSON.parse(chardata);
- // the try catch will fail before here when there is no file
-
- const char_select = <HTMLSelectElement>(
- document.getElementById("client_ininame")
- );
- char_select.innerHTML = "";
-
- char_array.forEach((character: string) => {
- char_select.add(new Option(character));
- });
- } catch (err) {
- console.warn("there was no characters.json file");
- }
- }
-
- async fetchEvidenceList() {
- try {
- const evidata = await request(`${AO_HOST}evidence.json`);
- const evi_array = JSON.parse(evidata);
- // the try catch will fail before here when there is no file
-
- const evi_select = <HTMLSelectElement>(
- document.getElementById("evi_select")
- );
- evi_select.innerHTML = "";
-
- evi_array.forEach((evi: string) => {
- evi_select.add(new Option(evi));
- });
- evi_select.add(new Option("Custom", "0"));
- } catch (err) {
- console.warn("there was no evidence.json file");
- }
- }
-
- isAudio(trackname: string) {
- const audioEndings = [".wav", ".mp3", ".ogg", ".opus"];
- return (
- audioEndings.filter((ending) => trackname.endsWith(ending)).length === 1
- );
+ fetchBackgroundList();
+ fetchEvidenceList();
}
- addTrack(trackname: string) {
- const newentry = <HTMLOptionElement>document.createElement("OPTION");
- const songName = getFilenameFromPath(trackname);
- newentry.text = unescapeChat(songName);
- newentry.value = trackname;
- (<HTMLSelectElement>(
- document.getElementById("client_musiclist")
- )).options.add(newentry);
- this.musics.push(trackname);
- }
-
- createArea(id: number, name: string) {
- const thisarea = {
- name,
- players: 0,
- status: "IDLE",
- cm: "",
- locked: "FREE",
- };
-
- this.areas.push(thisarea);
-
- // Create area button
- const newarea = document.createElement("SPAN");
- newarea.className = "area-button area-default";
- newarea.id = `area${id}`;
- newarea.innerText = thisarea.name;
- newarea.title =
- `Players: ${thisarea.players}\n` +
- `Status: ${thisarea.status}\n` +
- `CM: ${thisarea.cm}\n` +
- `Area lock: ${thisarea.locked}`;
- newarea.onclick = function () {
- area_click(newarea);
- };
-
- document.getElementById("areas").appendChild(newarea);
- }
-
- /**
- * Area list fuckery
- */
- fix_last_area() {
- if (this.areas.length > 0) {
- const malplaced = this.areas.pop().name;
- const areas = document.getElementById("areas");
- areas.removeChild(areas.lastChild);
- this.addTrack(malplaced);
- }
- }
-
- /**
- * Handles the kicked packet
- * @param {string} type is it a kick or a ban
- * @param {string} reason why
- */
- handleBans(type: string, reason: string) {
- document.getElementById("client_error").style.display = "flex";
- document.getElementById(
- "client_errortext"
- ).innerHTML = `${type}:<br>${reason.replace(/\n/g, "<br />")}`;
- (<HTMLElement>(
- document.getElementsByClassName("client_reconnect")[0]
- )).style.display = "none";
- (<HTMLElement>(
- document.getElementsByClassName("client_reconnect")[1]
- )).style.display = "none";
- }
-}
-
-/**
- * Resets the IC parameters for the player to enter a new chat message.
- * This should only be called when the player's previous chat message
- * was successfully sent/presented.
- */
-export function resetICParams() {
- (<HTMLInputElement>document.getElementById("client_inputbox")).value = "";
- document.getElementById("button_flash").className = "client_button";
- document.getElementById("button_shake").className = "client_button";
-
- (<HTMLInputElement>document.getElementById("sendpreanim")).checked = false;
- (<HTMLInputElement>document.getElementById("sendsfx")).checked = false;
-
- if (selectedShout) {
- document.getElementById(`button_${selectedShout}`).className =
- "client_button";
- selectedShout = 0;
- }
-}
-
-/**
- * Appends a message to the in-character chat log.
- * @param {string} msg the string to be added
- * @param {string} name the name of the sender
- */
-export function appendICLog(
- msg: string,
- showname = "",
- nameplate = "",
- time = new Date()
-) {
- const entry = document.createElement("p");
- const shownameField = document.createElement("span");
- const nameplateField = document.createElement("span");
- const textField = document.createElement("span");
- nameplateField.className = "iclog_name iclog_nameplate";
- nameplateField.appendChild(document.createTextNode(nameplate));
-
- shownameField.className = "iclog_name iclog_showname";
- if (showname === "" || !showname) {
- shownameField.appendChild(document.createTextNode(nameplate));
- } else {
- shownameField.appendChild(document.createTextNode(showname));
- }
-
- textField.className = "iclog_text";
- textField.appendChild(document.createTextNode(msg));
-
- entry.appendChild(shownameField);
- entry.appendChild(nameplateField);
- entry.appendChild(textField);
-
- // Only put a timestamp if the minute has changed.
- if (lastICMessageTime.getMinutes() !== time.getMinutes()) {
- const timeStamp = document.createElement("span");
- timeStamp.className = "iclog_time";
- timeStamp.innerText = time.toLocaleTimeString(undefined, {
- hour: "numeric",
- minute: "2-digit",
- });
- entry.appendChild(timeStamp);
- }
-
- const clientLog = document.getElementById("client_log");
- clientLog.appendChild(entry);
-
- /* This is a little buggy - some troubleshooting might be desirable */
- if (clientLog.scrollTop > clientLog.scrollHeight - 800) {
- clientLog.scrollTop = clientLog.scrollHeight;
- }
-
- lastICMessageTime = new Date();
-}
-
-/**
- * check if the message contains an entry on our callword list
- * @param {string} message
- */
-export function checkCallword(message: string, sfxAudio: HTMLAudioElement) {
- client.callwords.forEach(testCallword);
- function testCallword(item: string) {
- if (item !== "" && message.toLowerCase().includes(item.toLowerCase())) {
- sfxAudio.pause();
- sfxAudio.src = `${AO_HOST}sounds/general/sfx-gallery.opus`;
- sfxAudio.play();
- }
- }
}
export default Client; \ No newline at end of file
diff --git a/webAO/client/addTrack.ts b/webAO/client/addTrack.ts
new file mode 100644
index 0000000..247f07e
--- /dev/null
+++ b/webAO/client/addTrack.ts
@@ -0,0 +1,15 @@
+import { client } from "../client";
+import { unescapeChat } from "../encoding";
+import { getFilenameFromPath } from "../utils/paths";
+
+
+export const addTrack = (trackname: string) => {
+ const newentry = <HTMLOptionElement>document.createElement("OPTION");
+ const songName = getFilenameFromPath(trackname);
+ newentry.text = unescapeChat(songName);
+ newentry.value = trackname;
+ (<HTMLSelectElement>(
+ document.getElementById("client_musiclist")
+ )).options.add(newentry);
+ client.musics.push(trackname);
+} \ No newline at end of file
diff --git a/webAO/client/appendICLog.ts b/webAO/client/appendICLog.ts
new file mode 100644
index 0000000..f8b7852
--- /dev/null
+++ b/webAO/client/appendICLog.ts
@@ -0,0 +1,57 @@
+import { lastICMessageTime, setLastICMessageTime } from "../client";
+
+
+
+/**
+ * Appends a message to the in-character chat log.
+ * @param {string} msg the string to be added
+ * @param {string} name the name of the sender
+ */
+export function appendICLog(
+ msg: string,
+ showname = "",
+ nameplate = "",
+ time = new Date()
+) {
+ const entry = document.createElement("p");
+ const shownameField = document.createElement("span");
+ const nameplateField = document.createElement("span");
+ const textField = document.createElement("span");
+ nameplateField.className = "iclog_name iclog_nameplate";
+ nameplateField.appendChild(document.createTextNode(nameplate));
+
+ shownameField.className = "iclog_name iclog_showname";
+ if (showname === "" || !showname) {
+ shownameField.appendChild(document.createTextNode(nameplate));
+ } else {
+ shownameField.appendChild(document.createTextNode(showname));
+ }
+
+ textField.className = "iclog_text";
+ textField.appendChild(document.createTextNode(msg));
+
+ entry.appendChild(shownameField);
+ entry.appendChild(nameplateField);
+ entry.appendChild(textField);
+
+ // Only put a timestamp if the minute has changed.
+ if (lastICMessageTime.getMinutes() !== time.getMinutes()) {
+ const timeStamp = document.createElement("span");
+ timeStamp.className = "iclog_time";
+ timeStamp.innerText = time.toLocaleTimeString(undefined, {
+ hour: "numeric",
+ minute: "2-digit",
+ });
+ entry.appendChild(timeStamp);
+ }
+
+ const clientLog = document.getElementById("client_log")!;
+ clientLog.appendChild(entry);
+
+ /* This is a little buggy - some troubleshooting might be desirable */
+ if (clientLog.scrollTop > clientLog.scrollHeight - 800) {
+ clientLog.scrollTop = clientLog.scrollHeight;
+ }
+
+ setLastICMessageTime(new Date());
+} \ No newline at end of file
diff --git a/webAO/client/checkCallword.ts b/webAO/client/checkCallword.ts
new file mode 100644
index 0000000..f6cffbc
--- /dev/null
+++ b/webAO/client/checkCallword.ts
@@ -0,0 +1,17 @@
+import { client } from "../client";
+import { AO_HOST } from "./aoHost";
+
+/**
+ * check if the message contains an entry on our callword list
+ * @param {string} message
+ */
+export function checkCallword(message: string, sfxAudio: HTMLAudioElement) {
+ client.callwords.forEach(testCallword);
+ function testCallword(item: string) {
+ if (item !== "" && message.toLowerCase().includes(item.toLowerCase())) {
+ sfxAudio.pause();
+ sfxAudio.src = `${AO_HOST}sounds/general/sfx-gallery.opus`;
+ sfxAudio.play();
+ }
+ }
+} \ No newline at end of file
diff --git a/webAO/client/createArea.ts b/webAO/client/createArea.ts
new file mode 100644
index 0000000..63af644
--- /dev/null
+++ b/webAO/client/createArea.ts
@@ -0,0 +1,30 @@
+import { client } from "../client";
+import { area_click } from "../dom/areaClick";
+
+export const createArea = (id: number, name: string) => {
+ const thisarea = {
+ name,
+ players: 0,
+ status: "IDLE",
+ cm: "",
+ locked: "FREE",
+ };
+
+ client.areas.push(thisarea);
+
+ // Create area button
+ const newarea = document.createElement("SPAN");
+ newarea.className = "area-button area-default";
+ newarea.id = `area${id}`;
+ newarea.innerText = thisarea.name;
+ newarea.title =
+ `Players: ${thisarea.players}\n` +
+ `Status: ${thisarea.status}\n` +
+ `CM: ${thisarea.cm}\n` +
+ `Area lock: ${thisarea.locked}`;
+ newarea.onclick = function () {
+ area_click(newarea);
+ };
+
+ document.getElementById("areas")!.appendChild(newarea);
+} \ No newline at end of file
diff --git a/webAO/client/fetchLists.ts b/webAO/client/fetchLists.ts
new file mode 100644
index 0000000..e9772cb
--- /dev/null
+++ b/webAO/client/fetchLists.ts
@@ -0,0 +1,60 @@
+import { AO_HOST } from "./aoHost";
+import { request } from "../services/request.js";
+
+export const fetchBackgroundList = async () => {
+ try {
+ const bgdata = await request(`${AO_HOST}backgrounds.json`);
+ const bg_array = JSON.parse(bgdata);
+ // the try catch will fail before here when there is no file
+
+ const bg_select = <HTMLSelectElement>document.getElementById("bg_select");
+ bg_select.innerHTML = "";
+
+ bg_select.add(new Option("Custom", "0"));
+ bg_array.forEach((background: string) => {
+ bg_select.add(new Option(background));
+ });
+ } catch (err) {
+ console.warn("there was no backgrounds.json file");
+ }
+}
+
+export const fetchCharacterList = async () => {
+ try {
+ const chardata = await request(`${AO_HOST}characters.json`);
+ const char_array = JSON.parse(chardata);
+ // the try catch will fail before here when there is no file
+
+ const char_select = <HTMLSelectElement>(
+ document.getElementById("client_ininame")
+ );
+ char_select.innerHTML = "";
+
+ char_array.forEach((character: string) => {
+ char_select.add(new Option(character));
+ });
+ } catch (err) {
+ console.warn("there was no characters.json file");
+ }
+}
+
+
+export const fetchEvidenceList = async () => {
+ try {
+ const evidata = await request(`${AO_HOST}evidence.json`);
+ const evi_array = JSON.parse(evidata);
+ // the try catch will fail before here when there is no file
+
+ const evi_select = <HTMLSelectElement>(
+ document.getElementById("evi_select")
+ );
+ evi_select.innerHTML = "";
+
+ evi_array.forEach((evi: string) => {
+ evi_select.add(new Option(evi));
+ });
+ evi_select.add(new Option("Custom", "0"));
+ } catch (err) {
+ console.warn("there was no evidence.json file");
+ }
+} \ No newline at end of file
diff --git a/webAO/client/fixLastArea.ts b/webAO/client/fixLastArea.ts
new file mode 100644
index 0000000..f1aa99f
--- /dev/null
+++ b/webAO/client/fixLastArea.ts
@@ -0,0 +1,15 @@
+import { client } from "../client";
+import { addTrack } from "./addTrack";
+
+
+/**
+ * Area list fuckery
+ */
+export const fix_last_area = () => {
+ if (client.areas.length > 0) {
+ const malplaced = client.areas.pop().name;
+ const areas = document.getElementById("areas")!;
+ areas.removeChild(areas.lastChild);
+ addTrack(malplaced);
+ }
+} \ No newline at end of file
diff --git a/webAO/client/handleBans.ts b/webAO/client/handleBans.ts
new file mode 100644
index 0000000..b977fc8
--- /dev/null
+++ b/webAO/client/handleBans.ts
@@ -0,0 +1,17 @@
+/**
+ * Handles the kicked packet
+ * @param {string} type is it a kick or a ban
+ * @param {string} reason why
+ */
+export const handleBans = (type: string, reason: string) => {
+ document.getElementById("client_error")!.style.display = "flex";
+ document.getElementById(
+ "client_errortext"
+ )!.innerHTML = `${type}:<br>${reason.replace(/\n/g, "<br />")}`;
+ (<HTMLElement>(
+ document.getElementsByClassName("client_reconnect")[0]
+ )).style.display = "none";
+ (<HTMLElement>(
+ document.getElementsByClassName("client_reconnect")[1]
+ )).style.display = "none";
+} \ No newline at end of file
diff --git a/webAO/client/handleCharacterInfo.ts b/webAO/client/handleCharacterInfo.ts
new file mode 100644
index 0000000..9d74a8b
--- /dev/null
+++ b/webAO/client/handleCharacterInfo.ts
@@ -0,0 +1,105 @@
+import { client } from "../client";
+import { safeTags } from "../encoding";
+import iniParse from "../iniParse";
+import request from "../services/request";
+import fileExists from "../utils/fileExists";
+import { AO_HOST } from "./aoHost";
+
+
+/**
+ * Handles the incoming character information, and downloads the sprite + ini for it
+ * @param {Array} chargs packet arguments
+ * @param {Number} charid character ID
+ */
+export const handleCharacterInfo = async (chargs: string[], charid: number) => {
+ const img = <HTMLImageElement>document.getElementById(`demo_${charid}`);
+ if (chargs[0]) {
+ let cini: any = {};
+ const getCharIcon = async () => {
+ const extensions = [".png", ".webp"];
+ img.alt = chargs[0];
+ const charIconBaseUrl = `${AO_HOST}characters/${encodeURI(
+ chargs[0].toLowerCase()
+ )}/char_icon`;
+ for (let i = 0; i < extensions.length; i++) {
+ const fileUrl = charIconBaseUrl + extensions[i];
+ const exists = await fileExists(fileUrl);
+ if (exists) {
+ img.alt = chargs[0];
+ img.title = chargs[0];
+ img.src = fileUrl;
+ return;
+ }
+ }
+ };
+ getCharIcon();
+
+ // If the ini doesn't exist on the server this will throw an error
+ try {
+ const cinidata = await request(
+ `${AO_HOST}characters/${encodeURI(chargs[0].toLowerCase())}/char.ini`
+ );
+ cini = iniParse(cinidata);
+ } catch (err) {
+ cini = {};
+ img.classList.add("noini");
+ console.warn(`character ${chargs[0]} is missing from webAO`);
+ // If it does, give the user a visual indication that the character is unusable
+ }
+
+ const mute_select = <HTMLSelectElement>(
+ document.getElementById("mute_select")
+ );
+ mute_select.add(new Option(safeTags(chargs[0]), String(charid)));
+ const pair_select = <HTMLSelectElement>(
+ document.getElementById("pair_select")
+ );
+ pair_select.add(new Option(safeTags(chargs[0]), String(charid)));
+
+ // sometimes ini files lack important settings
+ const default_options = {
+ name: chargs[0],
+ showname: chargs[0],
+ side: "def",
+ blips: "male",
+ chat: "",
+ category: "",
+ };
+ cini.options = Object.assign(default_options, cini.options);
+
+ // sometimes ini files lack important settings
+ const default_emotions = {
+ number: 0,
+ };
+ cini.emotions = Object.assign(default_emotions, cini.emotions);
+
+ client.chars[charid] = {
+ name: safeTags(chargs[0]),
+ showname: safeTags(cini.options.showname),
+ desc: safeTags(chargs[1]),
+ blips: safeTags(cini.options.blips).toLowerCase(),
+ gender: safeTags(cini.options.gender).toLowerCase(),
+ side: safeTags(cini.options.side).toLowerCase(),
+ chat:
+ cini.options.chat === ""
+ ? safeTags(cini.options.category).toLowerCase()
+ : safeTags(cini.options.chat).toLowerCase(),
+ evidence: chargs[3],
+ icon: img.src,
+ inifile: cini,
+ muted: false,
+ };
+
+ if (
+ client.chars[charid].blips === "male" &&
+ client.chars[charid].gender !== "male" &&
+ client.chars[charid].gender !== ""
+ ) {
+ client.chars[charid].blips = client.chars[charid].gender;
+ }
+
+ } else {
+ console.warn(`missing charid ${charid}`);
+ img.style.display = "none";
+ }
+} \ No newline at end of file
diff --git a/webAO/client/isAudio.ts b/webAO/client/isAudio.ts
new file mode 100644
index 0000000..430f543
--- /dev/null
+++ b/webAO/client/isAudio.ts
@@ -0,0 +1,6 @@
+export const isAudio = (trackname: string) => {
+ const audioEndings = [".wav", ".mp3", ".ogg", ".opus"];
+ return (
+ audioEndings.filter((ending) => trackname.endsWith(ending)).length === 1
+ );
+} \ No newline at end of file
diff --git a/webAO/client/isLowMemory.ts b/webAO/client/isLowMemory.ts
new file mode 100644
index 0000000..caa6784
--- /dev/null
+++ b/webAO/client/isLowMemory.ts
@@ -0,0 +1,10 @@
+import { setOldLoading } from '../client'
+export const isLowMemory = () => {
+ if (
+ /webOS|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|PlayStation|Nintendo|Opera Mini/i.test(
+ navigator.userAgent
+ )
+ ) {
+ setOldLoading(true);
+ }
+}
diff --git a/webAO/client/loadResources.ts b/webAO/client/loadResources.ts
new file mode 100644
index 0000000..7039333
--- /dev/null
+++ b/webAO/client/loadResources.ts
@@ -0,0 +1,79 @@
+import getCookie from "../utils/getCookie";
+import vanilla_evidence_arr from "../constants/evidence.js";
+import vanilla_background_arr from "../constants/backgrounds.js";
+import { client } from "../client";
+import { setChatbox } from "../dom/setChatbox";
+import { changeSFXVolume, changeShoutVolume, changeTestimonyVolume } from "../dom/changeVolume";
+import { showname_click } from "../dom/showNameClick";
+
+const version = process.env.npm_package_version;
+/**
+ * Load game resources and stored settings.
+ */
+export const loadResources = () => {
+ document.getElementById("client_version")!.innerText = `version ${version}`;
+ // Load background array to select
+ const background_select = <HTMLSelectElement>(
+ document.getElementById("bg_select")
+ );
+ background_select.add(new Option("Custom", "0"));
+ vanilla_background_arr.forEach((background) => {
+ background_select.add(new Option(background));
+ });
+
+ // Load evidence array to select
+ const evidence_select = <HTMLSelectElement>(
+ document.getElementById("evi_select")
+ );
+ evidence_select.add(new Option("Custom", "0"));
+ vanilla_evidence_arr.forEach((evidence) => {
+ evidence_select.add(new Option(evidence));
+ });
+
+ // Read cookies and set the UI to its values
+ (<HTMLInputElement>document.getElementById("OOC_name")).value =
+ getCookie("OOC_name") ||
+ `web${String(Math.round(Math.random() * 100 + 10))}`;
+
+ // Read cookies and set the UI to its values
+ const cookietheme = getCookie("theme") || "default";
+
+ (<HTMLOptionElement>(
+ document.querySelector(`#client_themeselect [value="${cookietheme}"]`)
+ )).selected = true;
+ client.viewport.reloadTheme();
+
+ const cookiechatbox = getCookie("chatbox") || "dynamic";
+
+ (<HTMLOptionElement>(
+ document.querySelector(`#client_chatboxselect [value="${cookiechatbox}"]`)
+ )).selected = true;
+ setChatbox(cookiechatbox);
+
+ (<HTMLInputElement>document.getElementById("client_mvolume")).value =
+ getCookie("musicVolume") || "1";
+ client.viewport.changeMusicVolume();
+ (<HTMLAudioElement>document.getElementById("client_sfxaudio")).volume =
+ Number(getCookie("sfxVolume")) || 1;
+ changeSFXVolume();
+ (<HTMLAudioElement>document.getElementById("client_shoutaudio")).volume =
+ Number(getCookie("shoutVolume")) || 1;
+ changeShoutVolume();
+ (<HTMLAudioElement>(
+ document.getElementById("client_testimonyaudio")
+ )).volume = Number(getCookie("testimonyVolume")) || 1;
+ changeTestimonyVolume();
+ (<HTMLInputElement>document.getElementById("client_bvolume")).value =
+ getCookie("blipVolume") || "1";
+ client.viewport.changeBlipVolume();
+
+ (<HTMLInputElement>document.getElementById("ic_chat_name")).value =
+ getCookie("ic_chat_name");
+ (<HTMLInputElement>document.getElementById("showname")).checked = Boolean(
+ getCookie("showname")
+ );
+ showname_click(null);
+
+ (<HTMLInputElement>document.getElementById("client_callwords")).value =
+ getCookie("callwords");
+} \ No newline at end of file
diff --git a/webAO/client/resetICParams.ts b/webAO/client/resetICParams.ts
new file mode 100644
index 0000000..414da27
--- /dev/null
+++ b/webAO/client/resetICParams.ts
@@ -0,0 +1,21 @@
+import { selectedShout, setSelectedShout } from "../client";
+
+/**
+ * Resets the IC parameters for the player to enter a new chat message.
+ * This should only be called when the player's previous chat message
+ * was successfully sent/presented.
+ */
+export function resetICParams() {
+ (<HTMLInputElement>document.getElementById("client_inputbox")).value = "";
+ document.getElementById("button_flash")!.className = "client_button";
+ document.getElementById("button_shake")!.className = "client_button";
+
+ (<HTMLInputElement>document.getElementById("sendpreanim")).checked = false;
+ (<HTMLInputElement>document.getElementById("sendsfx")).checked = false;
+
+ if (selectedShout) {
+ document.getElementById(`button_${selectedShout}`)!.className =
+ "client_button";
+ setSelectedShout(0);
+ }
+} \ No newline at end of file
diff --git a/webAO/client/saveChatLogHandle.ts b/webAO/client/saveChatLogHandle.ts
new file mode 100644
index 0000000..bcc1075
--- /dev/null
+++ b/webAO/client/saveChatLogHandle.ts
@@ -0,0 +1,26 @@
+import downloadFile from "../services/downloadFile";
+
+export const saveChatlogHandle = async () => {
+ const clientLog = document.getElementById("client_log")!;
+ const icMessageLogs = clientLog.getElementsByTagName("p");
+ const messages: string[] = [];
+
+ for (let i = 0; i < icMessageLogs.length; i++) {
+ const SHOWNAME_POSITION = 0;
+ const TEXT_POSITION = 2;
+ const showname = icMessageLogs[i].children[SHOWNAME_POSITION].innerHTML;
+ const text = icMessageLogs[i].children[TEXT_POSITION].innerHTML;
+ const message = `${showname}: ${text}`;
+ messages.push(message);
+ }
+ const d = new Date();
+ let ye = new Intl.DateTimeFormat("en", { year: "numeric" }).format(d);
+ let mo = new Intl.DateTimeFormat("en", { month: "short" }).format(d);
+ let da = new Intl.DateTimeFormat("en", { day: "2-digit" }).format(d);
+
+ const filename = `chatlog-${da}-${mo}-${ye}`.toLowerCase();
+ downloadFile(messages.join("\n"), filename);
+
+ // Reset Chatbox to Empty
+ (<HTMLInputElement>document.getElementById("client_inputbox")).value = "";
+}; \ No newline at end of file
diff --git a/webAO/client/sender/sendOOC.ts b/webAO/client/sender/sendOOC.ts
index a410b5f..9674ad9 100644
--- a/webAO/client/sender/sendOOC.ts
+++ b/webAO/client/sender/sendOOC.ts
@@ -1,7 +1,7 @@
import { client } from '../../client'
import { escapeChat } from '../../encoding';
import setCookie from '../../utils/setCookie';
-
+import { saveChatlogHandle } from '../../client/saveChatLogHandle'
/**
* Sends an out-of-character chat message.
* @param {string} message the message to send
@@ -17,7 +17,7 @@ export const sendOOC = (message: string) => {
const oocMessage = `${escapeChat(message)}`;
const commands = {
- "/save_chatlog": client.saveChatlogHandle,
+ "/save_chatlog": saveChatlogHandle,
};
const commandsMap = new Map(Object.entries(commands));
diff --git a/webAO/dom/iniEdit.ts b/webAO/dom/iniEdit.ts
index 359a226..0710de9 100644
--- a/webAO/dom/iniEdit.ts
+++ b/webAO/dom/iniEdit.ts
@@ -1,4 +1,5 @@
import { client } from "../client";
+import { handleCharacterInfo } from "../client/handleCharacterInfo";
import { packetHandler } from "../packets/packetHandler";
/**
@@ -8,7 +9,7 @@ export async function iniedit() {
const ininame = (<HTMLInputElement>document.getElementById("client_ininame"))
.value;
const inicharID = client.charID;
- await client.handleCharacterInfo(ininame.split("&"), inicharID);
+ await handleCharacterInfo(ininame.split("&"), inicharID);
packetHandler.get("PV")!(`PV#0#CID#${inicharID}`.split("#"));
}
window.iniedit = iniedit;
diff --git a/webAO/dom/showNameClick.ts b/webAO/dom/showNameClick.ts
index 265f6c8..3e48b70 100644
--- a/webAO/dom/showNameClick.ts
+++ b/webAO/dom/showNameClick.ts
@@ -5,7 +5,7 @@ import setCookie from "../utils/setCookie";
* Triggered when the showname checkboc is clicked
* @param {MouseEvent} event
*/
-export function showname_click(_event: Event) {
+export function showname_click(_event: Event | null) {
setCookie(
"showname",
String((<HTMLInputElement>document.getElementById("showname")).checked)
diff --git a/webAO/packets/handlers/handleBD.ts b/webAO/packets/handlers/handleBD.ts
index 4ec291e..dbfb54b 100644
--- a/webAO/packets/handlers/handleBD.ts
+++ b/webAO/packets/handlers/handleBD.ts
@@ -1,5 +1,6 @@
-import { client, setBanned } from "../../client";
+import { setBanned } from "../../client";
import { safeTags } from "../../encoding";
+import { handleBans } from '../../client/handleBans'
/**
@@ -8,6 +9,6 @@ import { safeTags } from "../../encoding";
* @param {Array} args ban reason
*/
export const handleBD = (args: string[]) => {
- client.handleBans("Banned", safeTags(args[1]));
+ handleBans("Banned", safeTags(args[1]));
setBanned(true);
} \ No newline at end of file
diff --git a/webAO/packets/handlers/handleCI.ts b/webAO/packets/handlers/handleCI.ts
index 53e42f7..cb693bc 100644
--- a/webAO/packets/handlers/handleCI.ts
+++ b/webAO/packets/handlers/handleCI.ts
@@ -1,4 +1,5 @@
import { client } from '../../client'
+import { handleCharacterInfo } from '../../client/handleCharacterInfo'
/**
* Handles incoming character information, bundling multiple characters
* per packet.
@@ -18,7 +19,7 @@ export const handleCI = (args: string[]) => {
(<HTMLProgressElement>(
document.getElementById("client_loadingbar")
)).value = charid;
- setTimeout(() => client.handleCharacterInfo(chargs, charid), 500);
+ setTimeout(() => handleCharacterInfo(chargs, charid), 500);
}
}
// Request the next pack
diff --git a/webAO/packets/handlers/handleEM.ts b/webAO/packets/handlers/handleEM.ts
index 9f3cb87..5e49ea4 100644
--- a/webAO/packets/handlers/handleEM.ts
+++ b/webAO/packets/handlers/handleEM.ts
@@ -1,4 +1,8 @@
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';
/**
@@ -23,13 +27,13 @@ export const handleEM = (args: string[]) => {
)).value =
client.char_list_length + client.evidence_list_length + trackindex;
if (client.musics_time) {
- client.addTrack(trackname);
- } else if (client.isAudio(trackname)) {
+ addTrack(trackname);
+ } else if (isAudio(trackname)) {
client.musics_time = true;
- client.fix_last_area();
- client.addTrack(trackname);
+ fix_last_area();
+ addTrack(trackname);
} else {
- client.createArea(trackindex, trackname);
+ createArea(trackindex, trackname);
}
}
}
diff --git a/webAO/packets/handlers/handleFA.ts b/webAO/packets/handlers/handleFA.ts
index ccfe923..7a373e8 100644
--- a/webAO/packets/handlers/handleFA.ts
+++ b/webAO/packets/handlers/handleFA.ts
@@ -1,4 +1,5 @@
import { client } from '../../client'
+import { createArea } from '../../client/createArea';
import { safeTags } from '../../encoding';
/**
@@ -9,6 +10,6 @@ export const handleFA = (args: string[]) => {
client.resetAreaList();
for (let i = 1; i < args.length - 1; i++) {
- client.createArea(i - 1, safeTags(args[i]));
+ createArea(i - 1, safeTags(args[i]));
}
}
diff --git a/webAO/packets/handlers/handleFM.ts b/webAO/packets/handlers/handleFM.ts
index 630477b..fce10e3 100644
--- a/webAO/packets/handlers/handleFM.ts
+++ b/webAO/packets/handlers/handleFM.ts
@@ -1,7 +1,7 @@
import { client } from "../../client";
+import { addTrack } from "../../client/addTrack";
import { safeTags } from "../../encoding";
-
/**
* Handles updated music list
* @param {Array} args packet arguments
@@ -11,6 +11,6 @@ export const handleFM = (args: string[]) => {
for (let i = 1; i < args.length - 1; i++) {
// Check when found the song for the first time
- client.addTrack(safeTags(args[i]));
+ addTrack(safeTags(args[i]));
}
}
diff --git a/webAO/packets/handlers/handleKB.ts b/webAO/packets/handlers/handleKB.ts
index 8705b83..b0aa2b2 100644
--- a/webAO/packets/handlers/handleKB.ts
+++ b/webAO/packets/handlers/handleKB.ts
@@ -1,5 +1,6 @@
-import { client, setBanned } from "../../client";
+import { setBanned } from "../../client";
import { safeTags } from "../../encoding";
+import { handleBans } from '../../client/handleBans'
/**
* Handles the banned packet
@@ -7,6 +8,6 @@ import { safeTags } from "../../encoding";
* @param {Array} args ban reason
*/
export const handleKB = (args: string[]) => {
- client.handleBans("Banned", safeTags(args[1]));
+ handleBans("Banned", safeTags(args[1]));
setBanned(true);
}
diff --git a/webAO/packets/handlers/handleKK.ts b/webAO/packets/handlers/handleKK.ts
index fd9a88c..c8a97b1 100644
--- a/webAO/packets/handlers/handleKK.ts
+++ b/webAO/packets/handlers/handleKK.ts
@@ -1,11 +1,10 @@
-import { client } from "../../client";
import { safeTags } from "../../encoding";
-
+import { handleBans } from '../../client/handleBans'
/**
* Handles the kicked packet
* @param {Array} args kick reason
*/
export const handleKK = (args: string[]) => {
- client.handleBans("Kicked", safeTags(args[1]));
+ handleBans("Kicked", safeTags(args[1]));
}
diff --git a/webAO/packets/handlers/handleMC.ts b/webAO/packets/handlers/handleMC.ts
index bf60eb9..aeb178d 100644
--- a/webAO/packets/handlers/handleMC.ts
+++ b/webAO/packets/handlers/handleMC.ts
@@ -1,6 +1,7 @@
import { prepChat } from "../../encoding";
-import { appendICLog, client } from '../../client'
+import { client } from '../../client'
import { AO_HOST } from "../../client/aoHost";
+import { appendICLog } from '../../client/appendICLog'
/**
* Handles a music change to an arbitrary resource.
diff --git a/webAO/packets/handlers/handleMS.ts b/webAO/packets/handlers/handleMS.ts
index 0aad19a..1256900 100644
--- a/webAO/packets/handlers/handleMS.ts
+++ b/webAO/packets/handlers/handleMS.ts
@@ -1,4 +1,6 @@
-import { client, extrafeatures, resetICParams, UPDATE_INTERVAL } from "../../client";
+import { client, extrafeatures, UPDATE_INTERVAL } from "../../client";
+import { handleCharacterInfo } from "../../client/handleCharacterInfo";
+import { resetICParams } from "../../client/resetICParams";
import { prepChat, safeTags } from "../../encoding";
/**
@@ -6,119 +8,104 @@ import { prepChat, safeTags } from "../../encoding";
* @param {*} args packet arguments
*/
export const handleMS = (args: string[]) => {
- // TODO: this if-statement might be a bug.
- if (args[4] !== client.viewport.chatmsg.content) {
- document.getElementById("client_inner_chat")!.innerHTML = "";
+ // TODO: this if-statement might be a bug.
+ if (args[4] !== client.viewport.chatmsg.content) {
+ document.getElementById("client_inner_chat")!.innerHTML = "";
- const char_id = Number(args[9]);
- const char_name = safeTags(args[3]);
+ 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;
+ 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) {
+ 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("&");
- client.handleCharacterInfo(chargs, char_id);
- }
+ handleCharacterInfo(chargs, char_id);
}
+ }
- try {
- msg_nameplate = client.chars[char_id].showname;
- } catch (e) {
- msg_nameplate = args[3];
- }
+ 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 {
+ msg_blips = client.chars[char_id].blips;
+ } catch (e) { }
- try {
- char_chatbox = client.chars[char_id].chat;
- } catch (e) {
- char_chatbox = "default";
- }
+ 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");
- }
+ 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: 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: safeTags(args[12]),
+ flip: Number(args[13]),
+ flash: Number(args[14]),
+ color: Number(args[15]),
+ speed: UPDATE_INTERVAL,
+ };
- if (char_muted === false) {
- let chatmsg = {
- deskmod: 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: 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("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]),
+ 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_cccc, chatmsg);
+ chatmsg = Object.assign(extra_27, 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]),
+ if (extrafeatures.includes("effects")) {
+ const extra_28 = {
+ additive: Number(args[29]),
+ effects: args[30].split("|"),
};
- 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);
- }
+ 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: ["", "", ""],
@@ -126,17 +113,6 @@ export const handleMS = (args: string[]) => {
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,
@@ -151,12 +127,38 @@ export const handleMS = (args: string[]) => {
};
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();
- }
- client.viewport.handle_ic_speaking(chatmsg); // no await
+ // our own message appeared, reset the buttons
+ if (chatmsg.charid === client.charID) {
+ resetICParams();
}
+ client.viewport.handle_ic_speaking(chatmsg); // no await
}
- } \ No newline at end of file
+ }
+} \ No newline at end of file
diff --git a/webAO/packets/handlers/handleSC.ts b/webAO/packets/handlers/handleSC.ts
index f4953e0..b42a4cd 100644
--- a/webAO/packets/handlers/handleSC.ts
+++ b/webAO/packets/handlers/handleSC.ts
@@ -1,6 +1,7 @@
import queryParser from "../../utils/queryParser";
import { client } from '../../client'
+import { handleCharacterInfo } from "../../client/handleCharacterInfo";
let { mode } = queryParser();
/**
@@ -30,7 +31,7 @@ export const handleSC = async (args: string[]) => {
document.getElementById("client_loadingbar")
)).value = charid;
await sleep(0.1); // TODO: Too many network calls without this. net::ERR_INSUFFICIENT_RESOURCES
- client.handleCharacterInfo(chargs, charid);
+ handleCharacterInfo(chargs, charid);
}
// We're done with the characters, request the music
client.sender.sendServer("RM#%");
diff --git a/webAO/packets/handlers/handleSM.ts b/webAO/packets/handlers/handleSM.ts
index 48f9cd9..08bf7e0 100644
--- a/webAO/packets/handlers/handleSM.ts
+++ b/webAO/packets/handlers/handleSM.ts
@@ -1,4 +1,8 @@
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
@@ -21,14 +25,15 @@ export const handleSM = (args: string[]) => {
document.getElementById("client_loadingbar")
)).value = client.char_list_length + client.evidence_list_length + i;
if (client.musics_time) {
- client.addTrack(trackname);
- } else if (client.isAudio(trackname)) {
+ addTrack(trackname);
+ } else if (isAudio(trackname)) {
client.musics_time = true;
- client.fix_last_area();
- client.addTrack(trackname);
+ fix_last_area();
+ addTrack(trackname);
} else {
- client.createArea(trackindex, trackname);
+ createArea(trackindex, trackname);
}
+
}
// Music done, carry on
diff --git a/webAO/packets/handlers/handleackMS.ts b/webAO/packets/handlers/handleackMS.ts
index 2b971b0..dcca118 100644
--- a/webAO/packets/handlers/handleackMS.ts
+++ b/webAO/packets/handlers/handleackMS.ts
@@ -1,4 +1,4 @@
-import { resetICParams } from "../../client";
+import { resetICParams } from '../../client/resetICParams'
/**
* server got our message
diff --git a/webAO/viewport.ts b/webAO/viewport.ts
index 6c39784..7716409 100644
--- a/webAO/viewport.ts
+++ b/webAO/viewport.ts
@@ -1,19 +1,20 @@
import tryUrls from "./utils/tryUrls";
import fileExists from "./utils/fileExists";
import Client, { delay } from "./client";
-import {opusCheck} from './dom/opusCheck'
+import { opusCheck } from './dom/opusCheck'
import { UPDATE_INTERVAL } from "./client";
import { setChatbox } from "./dom/setChatbox";
import { resizeChatbox } from "./dom/resizeChatbox";
import transparentPng from "./constants/transparentPng";
import mlConfig from "./utils/aoml";
-import { appendICLog } from "./client";
-import { checkCallword } from "./client";
import setEmote from "./client/setEmote";
import getAnimLength from "./utils/getAnimLength";
import { safeTags } from "./encoding";
import setCookie from "./utils/setCookie";
import { AO_HOST } from "./client/aoHost";
+import { appendICLog } from "./client/appendICLog";
+import { checkCallword } from './client/checkCallword'
+
interface ChatMsg {
content: string;
objection: number;
@@ -449,7 +450,7 @@ const viewport = (masterClient: Client): Viewport => {
const displayname =
(<HTMLInputElement>document.getElementById("showname")).checked &&
- chatmsg.showname !== ""
+ chatmsg.showname !== ""
? chatmsg.showname
: chatmsg.nameplate;
@@ -620,9 +621,9 @@ const viewport = (masterClient: Client): Viewport => {
blipChannels.forEach(
(channel: HTMLAudioElement) =>
- (channel.src = `${AO_HOST}sounds/general/sfx-blip${encodeURI(
- chatmsg.blips.toLowerCase()
- )}.opus`)
+ (channel.src = `${AO_HOST}sounds/general/sfx-blip${encodeURI(
+ chatmsg.blips.toLowerCase()
+ )}.opus`)
);
// process markup
@@ -637,15 +638,15 @@ const viewport = (masterClient: Client): Viewport => {
fg.style.animation = "";
const effectName = chatmsg.effects[0].toLowerCase();
const badEffects = ["", "-", "none"];
- if (effectName.startsWith("rain") ) {
+ if (effectName.startsWith("rain")) {
(<HTMLLinkElement>document.getElementById("effect_css")).href = "styles/effects/rain.css";
let intensity = 200;
- if(effectName.endsWith("weak")) {
+ if (effectName.endsWith("weak")) {
intensity = 100;
} else if (effectName.endsWith("strong")) {
intensity = 400;
}
- if ( intensity < fg.childElementCount)
+ if (intensity < fg.childElementCount)
fg.innerHTML = '';
else
intensity = intensity - fg.childElementCount;
@@ -653,9 +654,9 @@ const viewport = (masterClient: Client): Viewport => {
for (let i = 0; i < intensity; i++) {
let drop = document.createElement("p");
drop.style.left = (Math.random() * 100) + "%";
- drop.style.animationDelay = String(Math.random())+"s";
+ drop.style.animationDelay = String(Math.random()) + "s";
fg.appendChild(drop)
- }
+ }
} else if (
chatmsg.effects[0] &&
!badEffects.includes(effectName)