fix team names in replay viewer
This commit is contained in:
@@ -132,6 +132,7 @@ class ReplayCanvasEngine {
|
||||
|
||||
_buildDOM() {
|
||||
this.container.innerHTML = ''
|
||||
this._panelRows = []
|
||||
const layout = document.createElement('div')
|
||||
layout.className = 'rc-layout'
|
||||
|
||||
@@ -222,32 +223,28 @@ class ReplayCanvasEngine {
|
||||
|
||||
_buildTeamPanel(panel, isWinner) {
|
||||
const teamEntities = this.entities.filter((e) => e.playerId > 0 && e.isWinner === isWinner)
|
||||
const seen = new Set()
|
||||
const unique = []
|
||||
// One row per player; a player may have several entities (one per spawn).
|
||||
const byPlayer = new Map()
|
||||
for (const e of teamEntities) {
|
||||
if (e.type === 'ground' && !seen.has(e.playerId)) {
|
||||
seen.add(e.playerId)
|
||||
unique.push(e)
|
||||
}
|
||||
}
|
||||
for (const e of teamEntities) {
|
||||
if (!seen.has(e.playerId)) {
|
||||
seen.add(e.playerId)
|
||||
unique.push(e)
|
||||
}
|
||||
if (!byPlayer.has(e.playerId)) byPlayer.set(e.playerId, [])
|
||||
byPlayer.get(e.playerId).push(e)
|
||||
}
|
||||
for (const list of byPlayer.values()) list.sort((a, b) => a.times[0] - b.times[0])
|
||||
|
||||
const color = isWinner ? RC.WIN : RC.LOSE
|
||||
const firstPlayer = unique.length ? this.players[unique[0].playerId] : null
|
||||
const clanTag = firstPlayer?.clan || ''
|
||||
const label = clanTag ? `<span class="rc-clan-tag">${esc(clanTag)}</span>` : (isWinner ? 'Winners' : 'Losers')
|
||||
const firstId = byPlayer.size ? byPlayer.keys().next().value : null
|
||||
const firstPlayer = firstId ? this.players[firstId] : null
|
||||
const teamSlot = firstPlayer ? firstPlayer.team : (isWinner ? this.data.teamWon : null)
|
||||
const teamName = teamSlot != null ? this.data.teamNames?.[String(teamSlot)] : ''
|
||||
const label = teamName ? esc(teamName) : (isWinner ? 'Winners' : 'Losers')
|
||||
let html = `<div class="rc-panel-head"><span class="rc-panel-label" style="color:${color}">${label}</span></div><div class="rc-panel-list">`
|
||||
for (const ent of unique) {
|
||||
const p = this.players[ent.playerId]
|
||||
for (const [pid, list] of byPlayer) {
|
||||
const p = this.players[pid]
|
||||
const name = p ? esc(p.name) : '?'
|
||||
const ent = list[0]
|
||||
const veh = esc(ent.vehicleName)
|
||||
const panelIcon = ent.miniIcon ? ent.miniIcon.replace('mini:', '') : (ent.iconKey || 'medium')
|
||||
html += `<div class="rc-row" data-player-id="${ent.playerId}" data-entity-index="${ent.entityIndex}">
|
||||
html += `<div class="rc-row" data-player-id="${pid}">
|
||||
<img class="rc-type-icon" src="/api/icons/type/${panelIcon}" alt="" loading="lazy" onerror="this.style.display='none'">
|
||||
<div class="rc-row-info">
|
||||
<span class="rc-row-name">${name}</span>
|
||||
@@ -258,13 +255,51 @@ class ReplayCanvasEngine {
|
||||
}
|
||||
html += '</div>'
|
||||
panel.innerHTML = html
|
||||
panel.querySelectorAll('.rc-row').forEach((row) => {
|
||||
|
||||
const rows = panel.querySelectorAll('.rc-row')
|
||||
let i = 0
|
||||
for (const [pid, list] of byPlayer) {
|
||||
const row = rows[i++]
|
||||
if (!row) continue
|
||||
const pr = {
|
||||
row,
|
||||
playerId: pid,
|
||||
entities: list,
|
||||
vehEl: row.querySelector('.rc-row-veh'),
|
||||
iconEl: row.querySelector('.rc-type-icon'),
|
||||
statusEl: row.querySelector('.rc-row-status'),
|
||||
shownEntityIndex: list[0].entityIndex,
|
||||
currentEntityIndex: list[0].entityIndex,
|
||||
}
|
||||
this._panelRows.push(pr)
|
||||
row.addEventListener('mouseenter', () => {
|
||||
const ent = this.entities.find((e) => e.entityIndex === Number(row.dataset.entityIndex))
|
||||
if (ent && !this._isEntityGone(ent, this.currentTime)) this._setHighlight(Number(row.dataset.playerId))
|
||||
const ent = pr.currentEntityIndex != null
|
||||
? this.entities.find((e) => e.entityIndex === pr.currentEntityIndex)
|
||||
: null
|
||||
if (ent && !this._isEntityGone(ent, this.currentTime)) this._setHighlight(pid)
|
||||
})
|
||||
row.addEventListener('mouseleave', () => this._setHighlight(null))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve which of a player's spawned vehicles is relevant at time t, and
|
||||
// whether the player is currently alive, down (awaiting respawn), or gone.
|
||||
_playerStateAtTime(entities, t) {
|
||||
for (const e of entities) {
|
||||
const first = e.times[0]
|
||||
const last = e.times[e.times.length - 1]
|
||||
if (t >= first && t <= last && !this._isEntityDead(e, t)) {
|
||||
return { entity: e, dead: false, gone: false }
|
||||
}
|
||||
}
|
||||
let recent = null
|
||||
for (const e of entities) {
|
||||
if (e.times[0] <= t && (!recent || e.times[0] >= recent.times[0])) recent = e
|
||||
}
|
||||
if (!recent) return { entity: entities[0] || null, dead: false, gone: false }
|
||||
const hasFutureSpawn = entities.some((e) => e.times[0] > t)
|
||||
const gone = !hasFutureSpawn && this._isEntityGone(recent, t)
|
||||
return { entity: recent, dead: true, gone }
|
||||
}
|
||||
|
||||
_buildEventList() {
|
||||
@@ -402,16 +437,25 @@ class ReplayCanvasEngine {
|
||||
|
||||
_updatePanelDeathStates() {
|
||||
const t = this.currentTime
|
||||
this.container.querySelectorAll('.rc-row').forEach((row) => {
|
||||
const ent = this.entities.find((e) => e.entityIndex === Number(row.dataset.entityIndex))
|
||||
if (!ent) return
|
||||
const dead = this._isEntityDead(ent, t)
|
||||
const gone = this._isEntityGone(ent, t)
|
||||
row.classList.toggle('rc-dead', dead)
|
||||
row.classList.toggle('rc-gone', gone)
|
||||
const status = row.querySelector('.rc-row-status')
|
||||
status.textContent = dead || gone ? 'x' : ''
|
||||
})
|
||||
if (!this._panelRows) return
|
||||
for (const pr of this._panelRows) {
|
||||
const st = this._playerStateAtTime(pr.entities, t)
|
||||
pr.currentEntityIndex = st.entity ? st.entity.entityIndex : null
|
||||
if (st.entity && st.entity.entityIndex !== pr.shownEntityIndex) {
|
||||
pr.shownEntityIndex = st.entity.entityIndex
|
||||
if (pr.vehEl) pr.vehEl.textContent = st.entity.vehicleName || ''
|
||||
if (pr.iconEl) {
|
||||
const panelIcon = st.entity.miniIcon
|
||||
? st.entity.miniIcon.replace('mini:', '')
|
||||
: (st.entity.iconKey || 'medium')
|
||||
pr.iconEl.src = `/api/icons/type/${panelIcon}`
|
||||
pr.iconEl.style.display = ''
|
||||
}
|
||||
}
|
||||
pr.row.classList.toggle('rc-dead', st.dead)
|
||||
pr.row.classList.toggle('rc-gone', st.gone)
|
||||
if (pr.statusEl) pr.statusEl.textContent = st.dead || st.gone ? 'x' : ''
|
||||
}
|
||||
}
|
||||
|
||||
_updateBattleLog() {
|
||||
|
||||
@@ -524,8 +524,7 @@ h3 {
|
||||
|
||||
.rc-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(190px, 230px) minmax(560px, 720px) minmax(190px, 230px);
|
||||
width: min(100%, 1210px);
|
||||
grid-template-columns: minmax(160px, 200px) min(720px, 60vh, 92vw) minmax(160px, 200px);
|
||||
gap: 0.5rem;
|
||||
align-items: start;
|
||||
justify-content: center;
|
||||
|
||||
Reference in New Issue
Block a user