aboutsummaryrefslogtreecommitdiff
path: root/webAO/client
diff options
context:
space:
mode:
authorstonedDiscord <Tukz@gmx.de>2026-02-11 12:28:49 +0100
committerGitHub <noreply@github.com>2026-02-11 12:28:49 +0100
commit8e7af5b93009c987a4c0c3fef014cf7b64463e03 (patch)
tree04b0c383ca35962dc3054ec7ace34bb64f019622 /webAO/client
parent726d89ce8605d27be1c14bba59f81cfd6254ccb3 (diff)
parent5bb35a981e2f35df7fbf126faa8655ee3b3ca142 (diff)
Merge pull request #293 from OmniTroid/better-charloading
Better charloading
Diffstat (limited to 'webAO/client')
-rw-r--r--webAO/client/aoHost.ts3
-rw-r--r--webAO/client/checkCallword.ts2
-rw-r--r--webAO/client/handleCharacterInfo.ts176
3 files changed, 108 insertions, 73 deletions
diff --git a/webAO/client/aoHost.ts b/webAO/client/aoHost.ts
index 003e237..0d7cb0f 100644
--- a/webAO/client/aoHost.ts
+++ b/webAO/client/aoHost.ts
@@ -2,7 +2,7 @@ import queryParser from "../utils/queryParser";
const { asset } = queryParser();
export let AO_HOST = asset;
-export const setAOhost = (val: string) => {
+export const setAOhost = (val: string): string => {
const currentProtocol = window.location.protocol;
const assetProtocol = val.split(":")[0] + ":";
@@ -19,4 +19,5 @@ export const setAOhost = (val: string) => {
AO_HOST = val;
}
console.log("Asset URL ist now " + AO_HOST);
+ return AO_HOST;
};
diff --git a/webAO/client/checkCallword.ts b/webAO/client/checkCallword.ts
index b7413f7..795eac9 100644
--- a/webAO/client/checkCallword.ts
+++ b/webAO/client/checkCallword.ts
@@ -11,7 +11,7 @@ export function checkCallword(message: string, sfxAudio: HTMLAudioElement) {
if (item !== "" && message.toLowerCase().includes(item.toLowerCase())) {
sfxAudio.pause();
sfxAudio.src = `${AO_HOST}sounds/general/sfx-gallery.opus`;
- sfxAudio.play();
+ sfxAudio.play().catch(() => {});
}
}
}
diff --git a/webAO/client/handleCharacterInfo.ts b/webAO/client/handleCharacterInfo.ts
index 3764c84..28992e9 100644
--- a/webAO/client/handleCharacterInfo.ts
+++ b/webAO/client/handleCharacterInfo.ts
@@ -2,50 +2,22 @@ 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";
-export const getCharIcon = async (img: HTMLImageElement, charname: string) => {
- img.alt = charname;
- const charIconBaseUrl = `${AO_HOST}characters/${encodeURI(
- charname.toLowerCase(),
- )}/char_icon`;
- for (let i = 0; i < client.charicon_extensions.length; i++) {
- const fileUrl = charIconBaseUrl + client.charicon_extensions[i];
- const exists = await fileExists(fileUrl);
- if (exists) {
- img.alt = charname;
- img.title = charname;
- img.src = fileUrl;
- return;
- }
- }
-};
-
/**
- * Handles the incoming character information, and downloads the sprite + ini for it
- * @param {Array} chargs packet arguments
- * @param {Number} charid character ID
+ * Lightweight character setup that runs on join. Sets the icon src directly
+ * (letting the browser handle loading) and stores default character data.
+ * Does NOT fetch char.ini — that is deferred until needed via ensureCharIni.
*/
-export const handleCharacterInfo = async (chargs: string[], charid: number) => {
+export const setupCharacterBasic = (chargs: string[], charid: number) => {
const img = <HTMLImageElement>document.getElementById(`demo_${charid}`);
if (chargs[0]) {
- let cini: any = {};
-
- getCharIcon(img, chargs[0]);
-
- // 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
- }
+ img.alt = chargs[0];
+ img.title = chargs[0];
+ const iconExt = client.charicon_extensions[0] || ".png";
+ img.src = `${AO_HOST}characters/${encodeURI(
+ chargs[0].toLowerCase(),
+ )}/char_icon${iconExt}`;
const mute_select = <HTMLSelectElement>(
document.getElementById("mute_select")
@@ -56,47 +28,109 @@ export const handleCharacterInfo = async (chargs: string[], charid: number) => {
);
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);
-
+ // Store defaults — these get replaced with actual ini values by ensureCharIni
client.chars[charid] = {
name: safeTags(chargs[0]),
- showname: safeTags(cini.options.showname),
+ showname: safeTags(chargs[0]),
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(),
+ blips: "male",
+ gender: "",
+ side: "def",
+ chat: "",
evidence: chargs[3],
- icon: img.src,
- inifile: cini,
+ icon: "",
muted: false,
};
+ } else {
+ console.warn(`missing charid ${charid}`);
+ img.style.display = "none";
+ }
+};
- if (
- client.chars[charid].blips === "male" &&
- client.chars[charid].gender !== "male" &&
- client.chars[charid].gender !== ""
- ) {
- client.chars[charid].blips = client.chars[charid].gender;
+/**
+ * Fetches and parses char.ini for a character if not already loaded.
+ * Replaces default values in client.chars[charid] with actual ini values.
+ */
+export const ensureCharIni = async (charid: number): Promise<any> => {
+ const char = client.chars[charid];
+ if (!char) return {};
+ if (char.inifile) return char.inifile;
+
+ const img = <HTMLImageElement>document.getElementById(`demo_${charid}`);
+ let cini: any = {};
+
+ try {
+ const cinidata = await request(
+ `${AO_HOST}characters/${encodeURI(char.name.toLowerCase())}/char.ini`,
+ );
+ cini = iniParse(cinidata);
+ } catch (err) {
+ cini = {};
+ if (img) img.classList.add("noini");
+ console.warn(`character ${char.name} is missing from webAO`);
+ }
+
+ const default_options = {
+ name: char.name,
+ showname: char.name,
+ side: "def",
+ blips: "male",
+ chat: "",
+ category: "",
+ };
+ cini.options = Object.assign(default_options, cini.options);
+
+ const default_emotions = {
+ number: 0,
+ };
+ cini.emotions = Object.assign(default_emotions, cini.emotions);
+
+ // Replace defaults with actual ini values
+ char.showname = safeTags(cini.options.showname);
+ char.blips = safeTags(cini.options.blips).toLowerCase();
+ char.gender = safeTags(cini.options.gender).toLowerCase();
+ char.side = safeTags(cini.options.side).toLowerCase();
+ char.chat =
+ cini.options.chat === ""
+ ? safeTags(cini.options.category).toLowerCase()
+ : safeTags(cini.options.chat).toLowerCase();
+ char.icon = img ? img.src : "";
+ char.inifile = cini;
+
+ if (
+ char.blips === "male" &&
+ char.gender !== "male" &&
+ char.gender !== ""
+ ) {
+ char.blips = char.gender;
+ }
+
+ return cini;
+};
+
+/**
+ * Full character info load (used by iniEdit and handleMS ini-edit path).
+ * Fetches icon + ini for a single character, replacing any existing data.
+ */
+export const handleCharacterInfo = async (chargs: string[], charid: number) => {
+ const img = <HTMLImageElement>document.getElementById(`demo_${charid}`);
+ if (chargs[0]) {
+ img.alt = chargs[0];
+ img.title = chargs[0];
+ const iconExt = client.charicon_extensions[0] || ".png";
+ img.src = `${AO_HOST}characters/${encodeURI(
+ chargs[0].toLowerCase(),
+ )}/char_icon${iconExt}`;
+
+ // Reset inifile so ensureCharIni will re-fetch
+ if (client.chars[charid]) {
+ client.chars[charid].name = safeTags(chargs[0]);
+ client.chars[charid].inifile = null;
+ } else {
+ setupCharacterBasic(chargs, charid);
}
+
+ await ensureCharIni(charid);
} else {
console.warn(`missing charid ${charid}`);
img.style.display = "none";