ed53e25e57
CI / changes (pull_request) Successful in 5s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 20s
CI / ui (pull_request) Has been skipped
CI / conformance (pull_request) Successful in 11s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 2m41s
Cap a player's simultaneous unfinished games per kind (vs_ai, random, friends) with independent guest and durable-account tiers, held in a new single-row backend.config table (-1 = unlimited) behind an in-memory cache and editable live in the admin console (/_gm/limits). Each game is tagged with games.game_kind on creation. This replaces the earlier flat MaxActiveQuickGames=10 combined cap: the per-tier/kind config is the single mechanism, enforced at the same handler gate (ensureUnderGameLimit by kind on lobby/enqueue) plus the durable friends cap in CreateInvitation. game.Service.AtGameLimit only resolves the tier and counts; the limit policy stays at the request edge. Guests are now refused friend requests, friend-code redemption, befriend-in-game and invitation creation outright (403 guest_forbidden) -- previously only the UI hid these. Admin: a kind column in both game lists and the config editor. Defaults: guest 1 vs_ai / 1 random / 0 friends; durable 10 / 10 / 10.
25 lines
1.2 KiB
Go Template
25 lines
1.2 KiB
Go Template
{{define "content" -}}
|
|
<h1>Games</h1>
|
|
{{with .Data}}
|
|
<nav class="subnav">
|
|
<a href="/_gm/games"{{if eq .Status ""}} class="active"{{end}}>all</a> ·
|
|
<a href="/_gm/games?status=open"{{if eq .Status "open"}} class="active"{{end}}>open</a> ·
|
|
<a href="/_gm/games?status=active"{{if eq .Status "active"}} class="active"{{end}}>active</a> ·
|
|
<a href="/_gm/games?status=finished"{{if eq .Status "finished"}} class="active"{{end}}>finished</a>
|
|
</nav>
|
|
<table class="list">
|
|
<thead><tr><th>Game</th><th>Variant</th><th>Kind</th><th>Status</th><th>🤖</th><th class="num">Players</th><th>Updated</th></tr></thead>
|
|
<tbody>
|
|
{{range .Items}}
|
|
<tr><td><a href="/_gm/games/{{.ID}}">{{.ID}}</a></td><td>{{.Variant}}</td><td>{{.Kind}}</td><td>{{.Status}}</td><td>{{if .VsAI}}🤖{{end}}</td><td class="num">{{.Players}}</td><td>{{.UpdatedAt}}</td></tr>
|
|
{{else}}<tr><td colspan="7"><span class="note">no games</span></td></tr>{{end}}
|
|
</tbody>
|
|
</table>
|
|
<nav class="pager">
|
|
{{if .Pager.HasPrev}}<a href="/_gm/games?status={{.Status}}&page={{.Pager.PrevPage}}">« prev</a>{{end}}
|
|
<span>page {{.Pager.Page}} · {{.Pager.Total}} total</span>
|
|
{{if .Pager.HasNext}}<a href="/_gm/games?status={{.Status}}&page={{.Pager.NextPage}}">next »</a>{{end}}
|
|
</nav>
|
|
{{end}}
|
|
{{- end}}
|