Document mail, death history, achievements, weekly rankings, spontaneous AI and BlueMap markers
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016pEyCmrAYHBFgpYjwFxKxh
This commit is contained in:
@@ -24,9 +24,11 @@ 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 on respawn (the death screen swallows chat sent during the event), so they can run back to their dropped items. Respects `keepInventory`. No storage, no command. |
|
||||
| `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 on respawn (the death screen swallows chat sent during the event), so they can run back to their dropped items. Respects `keepInventory`. `/mortes` lists your last 10 deaths with the cause and where each happened (`mortes.yml`) — your own only, since where someone died is where their stuff is. |
|
||||
| `zoacao` | A chat message matching the trigger (a pattern + a match mode) is swapped for a random line from `zoacao.mensagens` — a chat gag. The player's name still prefixes it. Default: a bare `f`/`F` (trimmed) → a random gag line. Match modes: `igual` (equals), `contem` (contains), `comeca` (starts with), `termina` (ends with), `regex`. The mode, the pattern, and the message list are all editable in-game with `/canalhandia zoacao ...`. Pure chat swap; the `luto` tribute is unaffected (paying respects still needs the `[F]` button or `/f`). Affects Bedrock chat too (it's a chat event, not a click). |
|
||||
| `notas` | Notes in chat. `/save` pins where you are; `/nota add <texto>` writes a private one (only you see it, everyone may write); `/nota publica <texto>` writes one everyone reads, and needs `canalhandia.nota.publica` (default op). Every note stores its coordinates — click-to-copy on Java. Persisted to `notas.yml`. **No teleport**: nothing here touches gameplay. |
|
||||
| `recados` | `/recado <jogador> <texto>` — a line for someone who is offline, delivered on their next join. `/recados` shows how many of yours are still unread. Persisted to `recados.yml`. |
|
||||
| `conquistas` | Named achievements beyond the numeric milestones: "Casca Grossa" (50h, under 10 deaths), "Turista" (100h, barely mined), "Imortal às Avessas". `/conquistas` lists them all and marks yours. Persisted to `conquistas.yml`. |
|
||||
| `ia` | `/ia <pergunta>` asks an OpenAI-compatible model in chat. Has a personality (`zoeiro` by default — it will tease you), sees the last few chat lines and the live server state, and grounds answers in the asker's real stats. Optional wiki lookup, per-player memory, operator corrections. |
|
||||
|
||||
Toggle any of them: `/canalhandia modulo <nome> <on|off>`
|
||||
@@ -166,6 +168,11 @@ Player-facing:
|
||||
/nota buscar <texto> procura no texto das anotações
|
||||
/nota ver <n> mostra uma anotação inteira
|
||||
/nota remover <n> apaga uma anotação sua
|
||||
/recado <jogador> <texto> recado entregue quando a pessoa entrar
|
||||
/recados quantos recados seus ainda não foram lidos
|
||||
/mortes suas últimas mortes, com causa e lugar
|
||||
/conquistas conquistas, com as suas marcadas
|
||||
/ranking semanal [métrica] só o que foi ganho nesta semana
|
||||
```
|
||||
|
||||
Admin (`canalhandia.admin`):
|
||||
@@ -182,6 +189,8 @@ Admin (`canalhandia.admin`):
|
||||
/canalhandia zoacao limpar volta para as frases padrão
|
||||
/ia personalidade lista as personalidades da IA
|
||||
/ia personalidade <nome> zoeiro | amigao | seco | aldeao | neutro
|
||||
/ia eventos <on|off> IA comenta mortes seguidas sozinha
|
||||
/ia saudacao <on|off> IA dá as boas-vindas de quem entra
|
||||
/canalhandia reload
|
||||
/curiosidade modo <entrada|intervalo|ambos|manual>
|
||||
/curiosidade intervalo <min> intervalo do modo temporizado
|
||||
@@ -211,6 +220,7 @@ survive a restart.
|
||||
| `canalhandia.isento` | nobody | never be the subject |
|
||||
| `canalhandia.nota` | everyone | `/save` and private notes |
|
||||
| `canalhandia.nota.publica` | op | write notes everyone can read |
|
||||
| `canalhandia.recado` | everyone | leave messages for other players |
|
||||
| `canalhandia.ia` | op | `/ia` (public question, broadcast to chat) |
|
||||
| `canalhandia.ia.privado` | op | `/iap` (private question, answer only to the asker) |
|
||||
| `canalhandia.ia.corrigir` | op | `/ia corrigir <resposta>` — register a correction for the last answer |
|
||||
@@ -289,6 +299,84 @@ text.
|
||||
|
||||
---
|
||||
|
||||
## Weekly rankings
|
||||
|
||||
`/ranking semanal [métrica]` shows only what was **gained since the start of the
|
||||
week**. On a server with three regulars an all-time board is decided by whoever
|
||||
started first and then stops being a contest; subtracting a weekly baseline
|
||||
makes it one again.
|
||||
|
||||
Rotation is time-based and idempotent: the snapshot carries the timestamp it was
|
||||
taken at and is replaced only once a week has actually elapsed. **A restart
|
||||
never rotates it** — a server that restarts nightly would otherwise reset the
|
||||
week every day, which is the failure this design exists to avoid.
|
||||
|
||||
Players who did not move are dropped (the point is who is playing *this* week).
|
||||
Someone missing from the baseline counts their whole value, having joined during
|
||||
the week. A negative difference is dropped rather than shown: statistics only go
|
||||
up, so a negative means a stale baseline or a reset stats file, not a result.
|
||||
|
||||
---
|
||||
|
||||
## Spontaneous AI lines
|
||||
|
||||
Off by default (`ia.comentar-eventos`, `ia.saudacao`). The persona can comment
|
||||
on a run of deaths and greet players as they join, using their own numbers. Both
|
||||
are opt-in because a chatty AI nobody asked for is the fastest way to make
|
||||
players hate the feature.
|
||||
|
||||
`/ia eventos <on|off>` and `/ia saudacao <on|off>` toggle them live.
|
||||
|
||||
### Why the budget is strict
|
||||
|
||||
A player question is self-limiting — someone chose to spend it. A line the AI
|
||||
decides to make on its own is not, and it costs money every time. `Budget`
|
||||
enforces three limits, **all** of which must pass:
|
||||
|
||||
| Limit | Default | Why |
|
||||
|---|---|---|
|
||||
| gap between any two lines | 10 min | stops chat spam |
|
||||
| daily cap, separate from `/ia`'s | 20 | protects the spend |
|
||||
| per-subject cooldown | 30 min | one unlucky player is not narrated all evening |
|
||||
|
||||
`allows()` does not spend, so a caller that decides not to fire (nobody online,
|
||||
the model returned nothing) has burned nothing. `saySomething` spends **up
|
||||
front** rather than on success: two events landing in the same tick would
|
||||
otherwise both pass `allows()` and fire together — the exact double-message the
|
||||
gap exists to prevent.
|
||||
|
||||
A death streak decays after 15 minutes. Three deaths across an evening is not a
|
||||
streak; three in ten minutes is. Spontaneous lines are silent on failure —
|
||||
nobody asked for it, so nobody should see it fail.
|
||||
|
||||
---
|
||||
|
||||
## Notes on the BlueMap web map
|
||||
|
||||
Public notes are drawn as markers on BlueMap (`notas.no-mapa`, default on).
|
||||
Notes already carry a world and coordinates and the server already runs BlueMap,
|
||||
so this joins the two. **Private notes are never drawn, at any setting.**
|
||||
|
||||
BlueMap is an **optional** dependency. `BlueMapBridge` is the only class that
|
||||
touches its API, and every entry point catches `NoClassDefFoundError` as well as
|
||||
`Exception` — the failure mode of a missing optional dependency is a linkage
|
||||
error, not an exception — so a server without BlueMap logs one fine-level line
|
||||
and carries on.
|
||||
|
||||
The dependency is `provided` scope because BlueMap ships those classes itself; a
|
||||
second copy inside this jar would shadow them and break the real plugin.
|
||||
`preflight.sh` fails if that scope is ever dropped.
|
||||
|
||||
Markers are **rebuilt**, not incrementally patched: BlueMap discards everything
|
||||
when it unloads and expects addons to re-create markers on its enable callback,
|
||||
and a full rebuild of a tiny list cannot drift out of sync the way a missed
|
||||
delete would. Notes are matched to the map that renders their world, or a Nether
|
||||
note would be drawn at the same numeric coordinates in the overworld, pointing
|
||||
at nothing. Note text is player-written and lands in a web page, so it is
|
||||
HTML-escaped.
|
||||
|
||||
---
|
||||
|
||||
## IA (`/ia`)
|
||||
|
||||
Chat Q&A backed by an OpenAI-compatible endpoint (default MiniMax). Gated to
|
||||
@@ -501,6 +589,12 @@ here is a crash-on-boot you get to fix while the server is still up.
|
||||
| `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) |
|
||||
| `Mail.java` | Offline messages and their YAML storage |
|
||||
| `DeathLog.java` | Recent deaths per player, for `/mortes` |
|
||||
| `Achievement.java` / `Achievements.java` | The named-achievement catalogue (pure) and its award bookkeeping |
|
||||
| `WeeklyStats.java` | Weekly ranking baseline and the delta arithmetic (pure) |
|
||||
| `Budget.java` | The three-limit gate on spontaneous AI lines (pure) |
|
||||
| `BlueMapBridge.java` | Public notes as markers on the BlueMap web map (optional dependency) |
|
||||
| `Note.java` / `Notes.java` | One note (scope, text, place, visibility rules) and its YAML storage |
|
||||
| `Persona.java` | The AI's five tones, each carrying the safety guard |
|
||||
| `ChatLog.java` | Bounded, thread-safe ring of recent public chat for the AI |
|
||||
|
||||
Reference in New Issue
Block a user