Compare commits
2 commits
10694c69bc
...
657ead4c5a
| Author | SHA1 | Date | |
|---|---|---|---|
| 657ead4c5a | |||
| b579941964 |
5 changed files with 52 additions and 6 deletions
|
|
@ -82,6 +82,14 @@ SimpleAdmin groups have no display name or colour, so those come from a site con
|
||||||
`"supporter": true` are listed apart from staff and can't sign in unless they hold
|
`"supporter": true` are listed apart from staff and can't sign in unless they hold
|
||||||
`@css/generic`.
|
`@css/generic`.
|
||||||
|
|
||||||
|
### Name history (optional)
|
||||||
|
|
||||||
|
SimpleAdmin keeps one row per SteamID + IP in `sa_players_ips` and overwrites its name on each
|
||||||
|
connect, so a rename on the same IP loses the old name. `sql/players-ips-name-history.sql` adds
|
||||||
|
`name` to that table's primary key, so every name a SteamID has joined with is kept and shows up
|
||||||
|
on its player page and in name search. SimpleAdmin needs no changes. Run it once against the
|
||||||
|
SimpleAdmin database; the file has the revert. Names are still only recorded at connect.
|
||||||
|
|
||||||
## Limitations and caveats
|
## Limitations and caveats
|
||||||
|
|
||||||
- **Tested against a real MySQL 8.4** with SimpleAdmin 1.8.2b's migrations applied, and a fake game
|
- **Tested against a real MySQL 8.4** with SimpleAdmin 1.8.2b's migrations applied, and a fake game
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ function liveHeader(s) {
|
||||||
</div>
|
</div>
|
||||||
<div class="live-stats">
|
<div class="live-stats">
|
||||||
<div><b>${s.count}<span class="faint">/${s.maxPlayers}</span></b><small>Players</small></div>
|
<div><b>${s.count}<span class="faint">/${s.maxPlayers}</span></b><small>Players</small></div>
|
||||||
<div><b><span class="team t score">${s.scoreT}</span> <span class="faint">:</span> <span class="team ct score">${s.scoreCt}</span></b><small>T vs CT</small></div>
|
<div><b><span class="team t score">${s.scoreT}</span> <span class="faint">:</span> <span class="team ct score">${s.scoreCt}</span></b><small>${s.warmup ? "Warmup, no rounds yet" : "Rounds won, T vs CT"}</small></div>
|
||||||
<div><b>${s.staffOnline}</b><small>Staff online</small></div>
|
<div><b>${s.staffOnline}</b><small>Staff online</small></div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,12 @@ async function server() {
|
||||||
}
|
}
|
||||||
const side = (team, name, score) => {
|
const side = (team, name, score) => {
|
||||||
const list = s.players.filter((p) => p.team === team).sort((a, b) => b.kills - a.kills);
|
const list = s.players.filter((p) => p.team === team).sort((a, b) => b.kills - a.kills);
|
||||||
|
const humans = list.filter((p) => !p.bot).length;
|
||||||
return `<section class="panel side ${team === 3 ? "ct" : "t"}">
|
return `<section class="panel side ${team === 3 ? "ct" : "t"}">
|
||||||
<div class="panel-head"><h2>${name}</h2><b class="side-score">${score}</b></div>
|
<div class="panel-head">
|
||||||
|
<div><h2>${name}</h2><p>${humans} ${humans === 1 ? "player" : "players"}${list.length > humans ? `, ${list.length - humans} ${list.length - humans === 1 ? "bot" : "bots"}` : ""}</p></div>
|
||||||
|
${s.warmup ? '<span class="side-warmup">Warmup</span>' : `<div class="side-score"><b>${score}</b><small>${score === 1 ? "round" : "rounds"} won</small></div>`}
|
||||||
|
</div>
|
||||||
${list.length ? `<table>
|
${list.length ? `<table>
|
||||||
<thead><tr><th>Player</th><th class="num">Kills</th><th class="num">Deaths</th><th class="num hide-sm">Ping</th></tr></thead>
|
<thead><tr><th>Player</th><th class="num">Kills</th><th class="num">Deaths</th><th class="num hide-sm">Ping</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -52,7 +56,7 @@ async function server() {
|
||||||
</div>
|
</div>
|
||||||
<div class="live-stats">
|
<div class="live-stats">
|
||||||
<div><b>${s.count}<span class="faint">/${s.maxPlayers}</span></b><small>Players</small></div>
|
<div><b>${s.count}<span class="faint">/${s.maxPlayers}</span></b><small>Players</small></div>
|
||||||
<div><b><span class="team t score">${s.scoreT}</span> <span class="faint">:</span> <span class="team ct score">${s.scoreCt}</span></b><small>T vs CT</small></div>
|
<div><b><span class="team t score">${s.scoreT}</span> <span class="faint">:</span> <span class="team ct score">${s.scoreCt}</span></b><small>${s.warmup ? "Warmup, no rounds yet" : "Rounds won, T vs CT"}</small></div>
|
||||||
<div><b>${s.staffOnline}</b><small>Staff online</small></div>
|
<div><b>${s.staffOnline}</b><small>Staff online</small></div>
|
||||||
</div>
|
</div>
|
||||||
${s.address ? `<div class="live-join">
|
${s.address ? `<div class="live-join">
|
||||||
|
|
|
||||||
|
|
@ -950,9 +950,12 @@ dialog::backdrop { background: rgba(5, 6, 9, 0.65); }
|
||||||
.side { overflow: hidden; }
|
.side { overflow: hidden; }
|
||||||
.side.ct { box-shadow: inset 0 3px 0 #6fa3e8; }
|
.side.ct { box-shadow: inset 0 3px 0 #6fa3e8; }
|
||||||
.side.t { box-shadow: inset 0 3px 0 #e3b353; }
|
.side.t { box-shadow: inset 0 3px 0 #e3b353; }
|
||||||
.side-score { font: 700 32px/1 var(--display); }
|
.side-score { display: grid; justify-items: end; gap: 2px; }
|
||||||
.side.ct .side-score { color: #6fa3e8; }
|
.side-score b { font: 700 32px/1 var(--display); }
|
||||||
.side.t .side-score { color: #e3b353; }
|
.side-score small { color: var(--muted); font-size: 13px; }
|
||||||
|
.side.ct .side-score b { color: #6fa3e8; }
|
||||||
|
.side.t .side-score b { color: #e3b353; }
|
||||||
|
.side-warmup { color: var(--muted); font: 600 17px/1 var(--display); letter-spacing: 0.01em; }
|
||||||
.side .who .rank { display: flex; margin-top: 2px; font-size: 13px; }
|
.side .who .rank { display: flex; margin-top: 2px; font-size: 13px; }
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
|
|
@ -966,6 +969,7 @@ dialog::backdrop { background: rgba(5, 6, 9, 0.65); }
|
||||||
.topbar-inner { gap: 8px; padding: 0 12px; }
|
.topbar-inner { gap: 8px; padding: 0 12px; }
|
||||||
.tabs { gap: 0; }
|
.tabs { gap: 0; }
|
||||||
.tabs a { padding: 0 6px; font-size: 15px; }
|
.tabs a { padding: 0 6px; font-size: 15px; }
|
||||||
|
.topbar nav { min-width: 0; overflow-x: auto; scrollbar-width: none; }
|
||||||
.signin { padding: 0 8px; }
|
.signin { padding: 0 8px; }
|
||||||
.hide-xs { display: none; }
|
.hide-xs { display: none; }
|
||||||
.show-xs { display: inline; }
|
.show-xs { display: inline; }
|
||||||
|
|
|
||||||
30
sql/players-ips-name-history.sql
Normal file
30
sql/players-ips-name-history.sql
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
-- Keep every name a SteamID has used, instead of overwriting it.
|
||||||
|
--
|
||||||
|
-- CS2-SimpleAdmin records each connect with an upsert keyed on sa_players_ips' primary key,
|
||||||
|
-- (steamid, address), so a player who rejoins from the same IP under a new name overwrites the old
|
||||||
|
-- name. With name in the key, a new name on the same SteamID+IP is a new row; the same name again
|
||||||
|
-- still just bumps used_at. SimpleAdmin's own code is unchanged: its IP cache already keeps only
|
||||||
|
-- the newest row per IP, so multi-account and IP-ban checks behave as before.
|
||||||
|
--
|
||||||
|
-- name becomes binary-collated so a case-only rename ("astra" -> "Astra") is also kept, and NOT
|
||||||
|
-- NULL because primary key columns can't be NULL (SimpleAdmin always writes a name).
|
||||||
|
--
|
||||||
|
-- Only records names at connect, like before: a rename mid-session shows up on the next join.
|
||||||
|
-- Re-check after upgrading SimpleAdmin, in case a later migration rebuilds this table's key.
|
||||||
|
|
||||||
|
UPDATE sa_players_ips SET name = '' WHERE name IS NULL;
|
||||||
|
|
||||||
|
ALTER TABLE sa_players_ips
|
||||||
|
MODIFY name VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
ADD PRIMARY KEY (steamid, address, name);
|
||||||
|
|
||||||
|
-- Revert (drops the older names, keeping the newest row per SteamID+IP):
|
||||||
|
--
|
||||||
|
-- DELETE a FROM sa_players_ips a JOIN sa_players_ips b
|
||||||
|
-- ON a.steamid = b.steamid AND a.address = b.address
|
||||||
|
-- AND (a.used_at < b.used_at OR (a.used_at = b.used_at AND a.name < b.name));
|
||||||
|
-- ALTER TABLE sa_players_ips
|
||||||
|
-- DROP PRIMARY KEY,
|
||||||
|
-- ADD PRIMARY KEY (steamid, address),
|
||||||
|
-- MODIFY name VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue