diff options
| author | David Skoland <davidskoland@gmail.com> | 2026-02-10 23:38:17 +0100 |
|---|---|---|
| committer | David Skoland <davidskoland@gmail.com> | 2026-02-10 23:38:17 +0100 |
| commit | 020dfcda00ca06b9a06e7076eaf8a0164ae1327e (patch) | |
| tree | 9fe2a8d9fdf81823e48d9a3795e47d0c59964f69 | |
| parent | 9c68a1afcf178a86063f094b96471fa73531bd9a (diff) | |
Refactor playerlist to state-driven rendering with renderPlayerList
handlePR and handlePU now only update client.playerlist state,
and renderPlayerList handles all DOM rendering from that state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| -rw-r--r-- | webAO/client.ts | 5 | ||||
| -rw-r--r-- | webAO/dom/areaClick.ts | 10 | ||||
| -rw-r--r-- | webAO/dom/renderPlayerList.ts | 50 | ||||
| -rw-r--r-- | webAO/dom/updatePlayerAreas.ts | 24 | ||||
| -rw-r--r-- | webAO/packets/handlers/handleASS.ts | 21 | ||||
| -rw-r--r-- | webAO/packets/handlers/handlePR.ts | 55 | ||||
| -rw-r--r-- | webAO/packets/handlers/handlePU.ts | 47 |
7 files changed, 75 insertions, 137 deletions
diff --git a/webAO/client.ts b/webAO/client.ts index 95df67a..05a40c9 100644 --- a/webAO/client.ts +++ b/webAO/client.ts @@ -150,7 +150,8 @@ class Client extends EventEmitter { connect: () => void; loadResources: () => void; isLowMemory: () => void; - players: Map<number, { charId: number; area: number }>; + /** Maps player ID to player data */ + playerlist: Map<number, { charId: number; charName: string; showName: string; name: string; area: number }>; charicon_extensions: string[]; emote_extensions: string[]; emotions_extensions: string[]; @@ -212,7 +213,7 @@ class Client extends EventEmitter { this.temp_packet = ""; loadResources; isLowMemory; - this.players = new Map(); + this.playerlist = new Map(); this.charicon_extensions = [".png", ".webp"]; this.emote_extensions = [".gif", ".png", ".apng", ".webp", ".webp.static"]; this.emotions_extensions = [".png", ".webp"]; diff --git a/webAO/dom/areaClick.ts b/webAO/dom/areaClick.ts index 19953a5..f7b177e 100644 --- a/webAO/dom/areaClick.ts +++ b/webAO/dom/areaClick.ts @@ -1,6 +1,4 @@ import { client } from "../client"; -import { updatePlayerAreas } from "./updatePlayerAreas"; -import { ensureCharIni } from "../client/handleCharacterInfo"; /** * Triggered when an item on the area list is clicked. * @param {HTMLElement} el @@ -14,13 +12,5 @@ export function area_click(el: HTMLElement) { areaHr.textContent = `switched to ${el.textContent}`; document.getElementById("client_log")!.appendChild(areaHr); client.area = Number(el.id.substring(4)); - updatePlayerAreas(client.area); - - // Prefetch char.ini for all characters present in the new area - for (const player of client.players.values()) { - if (player.area === client.area && player.charId >= 0) { - ensureCharIni(player.charId); - } - } } window.area_click = area_click; diff --git a/webAO/dom/renderPlayerList.ts b/webAO/dom/renderPlayerList.ts new file mode 100644 index 0000000..43dab64 --- /dev/null +++ b/webAO/dom/renderPlayerList.ts @@ -0,0 +1,50 @@ +import { client } from "../client"; +import { AO_HOST } from "../client/aoHost"; + +export function renderPlayerList() { + const list = document.getElementById("client_playerlist") as HTMLTableElement; + list.innerHTML = ""; + + for (const [playerID, player] of client.playerlist) { + const playerRow = list.insertRow(); + playerRow.id = `client_playerlist_entry${playerID}`; + + const imgCell = playerRow.insertCell(0); + imgCell.style.width = "64px"; + const img = document.createElement("img"); + if (player.charId >= 0) { + const char = client.chars[player.charId]; + if (char) { + const iconExt = client.charicon_extensions[0] || ".png"; + img.src = `${AO_HOST}characters/${encodeURI(char.name.toLowerCase())}/char_icon${iconExt}`; + img.alt = char.name; + img.title = char.name; + } + } + imgCell.appendChild(img); + + const charNameCell = playerRow.insertCell(1); + charNameCell.textContent = + player.charId >= 0 ? `[${playerID}] ${player.charName}` : ""; + + const showNameCell = playerRow.insertCell(2); + showNameCell.textContent = player.showName; + + const oocNameCell = playerRow.insertCell(3); + oocNameCell.textContent = player.name; + + const kickCell = playerRow.insertCell(4); + kickCell.style.width = "64px"; + const kick = document.createElement("button"); + kick.innerText = "Kick"; + kick.onclick = () => window.kickPlayer(playerID); + kickCell.appendChild(kick); + + const banCell = playerRow.insertCell(5); + banCell.style.width = "64px"; + const ban = document.createElement("button"); + ban.innerText = "Ban"; + ban.onclick = () => window.banPlayer(playerID); + banCell.appendChild(ban); + } +} diff --git a/webAO/dom/updatePlayerAreas.ts b/webAO/dom/updatePlayerAreas.ts deleted file mode 100644 index 99eccf1..0000000 --- a/webAO/dom/updatePlayerAreas.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { client } from "../client"; -import { area_click } from "./areaClick"; -/** - * Triggered when someone switches areas - * @param {Number} ownarea - */ -export function updatePlayerAreas(ownarea: number) { - for (let i = 0; i < client.areas.length; i++) { - if (i === ownarea) - for (let classelement of Array.from( - document.getElementsByClassName( - `area${i}`, - ) as HTMLCollectionOf<HTMLElement>, - )) - classelement.style.display = ""; - else - for (let classelement of Array.from( - document.getElementsByClassName( - `area${i}`, - ) as HTMLCollectionOf<HTMLElement>, - )) - classelement.style.display = "none"; - } -} diff --git a/webAO/packets/handlers/handleASS.ts b/webAO/packets/handlers/handleASS.ts index 092e4f9..c50443a 100644 --- a/webAO/packets/handlers/handleASS.ts +++ b/webAO/packets/handlers/handleASS.ts @@ -1,26 +1,11 @@ import { setAOhost } from "../../client/aoHost"; -import { client } from "../../client"; +import { renderPlayerList } from "../../dom/renderPlayerList"; /** * new asset url!! * @param {Array} args packet arguments */ export const handleASS = (args: string[]) => { - const host = args[1] !== "None" ? setAOhost(args[1]) : args[1]; - - // Re-apply playerlist icon srcs that were set before AO_HOST was known - const iconExt = client.charicon_extensions[0] || ".png"; - for (const [playerID, player] of client.players) { - if (player.charId >= 0) { - const char = client.chars[player.charId]; - if (char) { - const img = document.querySelector<HTMLImageElement>( - `#client_playerlist_entry${playerID} img` - ); - if (img) { - img.src = `${host}characters/${encodeURI(char.name.toLowerCase())}/char_icon${iconExt}`; - } - } - } - } + if (args[1] !== "None") setAOhost(args[1]); + renderPlayerList(); }; diff --git a/webAO/packets/handlers/handlePR.ts b/webAO/packets/handlers/handlePR.ts index e39103d..f81d8dc 100644 --- a/webAO/packets/handlers/handlePR.ts +++ b/webAO/packets/handlers/handlePR.ts @@ -1,51 +1,5 @@ import { client } from "../../client"; -import { kickPlayer, banPlayer } from "../../dom/banPlayer"; - -function addPlayer(playerID: number) { - const list = <HTMLTableElement>document.getElementById("client_playerlist"); - const playerRow = list.insertRow(); - playerRow.id = `client_playerlist_entry${playerID}`; - playerRow.className = `area0`; - - const imgCell = playerRow.insertCell(0); - imgCell.style.width = "64px"; - const img = document.createElement("img"); - imgCell.appendChild(img); - - const name = document.createTextNode("No Data"); - - const charNameCell = playerRow.insertCell(1); - charNameCell.appendChild(name); - const showNameCell = playerRow.insertCell(2); - showNameCell.appendChild(name); - const oocNameCell = playerRow.insertCell(3); - oocNameCell.appendChild(name); - - const kickCell = playerRow.insertCell(4); - kickCell.style.width = "64px"; - const kick = <HTMLButtonElement>document.createElement("button"); - kick.innerText = "Kick"; - kick.onclick = () => { - window.kickPlayer(playerID); - }; - kickCell.appendChild(kick); - - const banCell = playerRow.insertCell(5); - banCell.style.width = "64px"; - const ban = <HTMLButtonElement>document.createElement("button"); - ban.innerText = "Ban"; - ban.onclick = () => { - window.banPlayer(playerID); - }; - banCell.appendChild(ban); -} - -function removePlayer(playerID: number) { - const playerRow = <HTMLTableElement>( - document.getElementById(`client_playerlist_entry${playerID}`) - ); - playerRow.remove(); -} +import { renderPlayerList } from "../../dom/renderPlayerList"; /** * Handles a player joining or leaving @@ -54,10 +8,9 @@ function removePlayer(playerID: number) { export const handlePR = (args: string[]) => { const playerID = Number(args[1]); if (Number(args[2]) === 0) { - addPlayer(playerID); - client.players.set(playerID, { charId: -1, area: 0 }); + client.playerlist.set(playerID, { charId: -1, charName: "", showName: "", name: "", area: 0 }); } else if (Number(args[2]) === 1) { - removePlayer(playerID); - client.players.delete(playerID); + client.playerlist.delete(playerID); } + renderPlayerList(); }; diff --git a/webAO/packets/handlers/handlePU.ts b/webAO/packets/handlers/handlePU.ts index d8d9b44..3b70ad3 100644 --- a/webAO/packets/handlers/handlePU.ts +++ b/webAO/packets/handlers/handlePU.ts @@ -1,59 +1,42 @@ import { client } from "../../client"; -import { updatePlayerAreas } from "../../dom/updatePlayerAreas"; -import { AO_HOST } from "../../client/aoHost"; import { ensureCharIni } from "../../client/handleCharacterInfo"; +import { renderPlayerList } from "../../dom/renderPlayerList"; /** * Handles a playerlist update * @param {Array} args packet arguments */ export const handlePU = (args: string[]) => { - const playerRow = <HTMLTableElement>( - document.getElementById(`client_playerlist_entry${Number(args[1])}`) - ); + const playerID = Number(args[1]); + const player = client.playerlist.get(playerID); + if (!player) return; + const type = Number(args[2]); const data = args[3]; + switch (type) { case 0: - const oocName = <HTMLElement>playerRow.childNodes[3]; - oocName.innerText = data; + player.name = data; break; case 1: - const playerImg = <HTMLImageElement>playerRow.childNodes[0].firstChild; - playerImg.alt = data; - playerImg.title = data; - const iconExt = client.charicon_extensions[0] || ".png"; - playerImg.src = `${AO_HOST}characters/${encodeURI(data.toLowerCase())}/char_icon${iconExt}`; - const charName = <HTMLElement>playerRow.childNodes[1]; - charName.innerText = `[${args[1]}] ${data}`; + player.charName = data; const charId = client.chars.findIndex( (c: any) => c && c.name.toLowerCase() === data.toLowerCase() ); if (charId >= 0) { - const player = client.players.get(Number(args[1])); - if (player) { - player.charId = charId; - if (player.area === client.area) { - ensureCharIni(charId); - } - } + player.charId = charId; + ensureCharIni(charId); } break; case 2: - const showName = <HTMLElement>playerRow.childNodes[2]; - showName.innerText = data; + player.showName = data; break; case 3: - playerRow.className = `area${data}`; - updatePlayerAreas(client.area); - const puPlayer = client.players.get(Number(args[1])); - if (puPlayer) { - puPlayer.area = Number(data); - if (puPlayer.area === client.area && puPlayer.charId >= 0) { - ensureCharIni(puPlayer.charId); - } - } + player.area = Number(data); + break; default: break; } + + renderPlayerList(); }; |
