feat: feed asker stats to the IA + comic death messages
Two features requested after the IA grounding deploy.
IA player-stats grounding: the IA could not answer "quantos blocos eu
minerei?" because its context carried only generic server facts, never the
asker's own numbers. OfflineStats now reads one player's headline stats
(blocks mined, time played, distance, deaths, mob kills) from their vanilla
stats JSON and Ai.compose() injects them as a system turn, gated by
ia.estatisticas-jogador (default true). ~30 tokens per question; always on
so it never misses a stat question. Pure formatSummary extracted for tests.
Comic deaths (mortes module): replaces the vanilla death message with a
cause-based pt-BR comic line plus a death counter ("Fulano foi achatado
como panqueca (47ª morte)") and sends the death coordinates privately to
the dead player (Java click-to-copy, Bedrock plain text) so they can run
back to their dropped items. No storage, no command — a PlayerDeathEvent
side effect gated by modulos.mortes. DeathFlavor is a pure cause->phrase
map, unit-tested. Coexists with the luto [F] handler.
DEATHS stat timing: assumes Paper fires PlayerDeathEvent before awarding
minecraft:deaths, so the counter shows +1 to include the current death; a
log line confirms the raw stat on the first real death so the +1 can be
dropped if the server increments first.
117 tests green (101 + 13 DeathFlavor + 3 OfflineStatsSummary).
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ All player-facing text is Portuguese (pt-BR).
|
||||
| `enquete` | `/enquete Pergunta \| A \| B` — clickable voting with a live tally on the boss bar. |
|
||||
| `ranking` | `/ranking mineracao` and friends. Covers **offline players too**. |
|
||||
| `marcos` | Announces round milestones — 100 km walked, 24 hours played — the first time someone crosses one. |
|
||||
| `mortes` | Replaces each death message with a comic pt-BR line (cause-based flavor + a death counter) and sends the death coordinates **privately** to the dead player, so they can run back to their dropped items. No storage, no command. |
|
||||
| `ia` | `/ia <pergunta>` asks an OpenAI-compatible model in chat. Optional wiki grounding, per-player memory, operator corrections. |
|
||||
|
||||
Toggle any of them: `/canalhandia modulo <nome> <on|off>`
|
||||
@@ -246,6 +247,12 @@ no model round trip.
|
||||
- **Server context**: the `contexto:` list in `config.yml` is facts the model
|
||||
would never know (server name, Bedrock prefix, installed mods). Sent on every
|
||||
question.
|
||||
- **Asker's stats**: when `estatisticas-jogador` is on (default), the asking
|
||||
player's headline numbers (blocks mined, time played, distance walked, deaths,
|
||||
mob kills) are read from their vanilla stats JSON and injected as context, so
|
||||
"quantos blocos eu minerei?" gets a real answer instead of "não tenho
|
||||
acesso". The stats file lags by under a minute. Gated off with
|
||||
`/canalhandia` settings or `ia.estatisticas-jogador: false`.
|
||||
- **Recipes**: `RecipeBook` snapshots `Bukkit.recipeIterator()` at enable (main
|
||||
thread) and answers recipe questions from that snapshot — `explaintext` drops
|
||||
tables, so the wiki cannot supply them.
|
||||
@@ -313,8 +320,9 @@ microk8s kubectl cp target/Canalhandia-1.0.0.jar minecraft/${POD#pod/}:$SRV/plug
|
||||
| `GuessRound.java` | "Adivinhe de quem é" round state |
|
||||
| `Poll.java` | Poll state, voting, results |
|
||||
| `Milestones.java` | Threshold tracking, persisted to `marcos.yml` |
|
||||
| `OfflineStats.java` | Reads stats JSON for offline players |
|
||||
| `OfflineStats.java` | Reads stats JSON for offline players (rankings + the asker's stat summary for the IA) |
|
||||
| `RankingMetric.java` | Leaderboard columns and their formatting |
|
||||
| `DeathFlavor.java` | Comic pt-BR verb phrases for each death cause (used by the `mortes` module) |
|
||||
| `Msg.java` | Shared chat formatting and pt-BR number/duration formatting |
|
||||
|
||||
### Adding a curiosity
|
||||
|
||||
Reference in New Issue
Block a user