i18n: per-player EN/PT via Adventure GlobalTranslator #1

Merged
masi merged 20 commits from feat/ia-grounding into main 2026-08-12 15:53:28 +00:00
Showing only changes of commit c11085e95e - Show all commits
+80
View File
@@ -26,6 +26,7 @@ All player-facing text is Portuguese (pt-BR).
| `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. |
| `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. |
| `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>`
@@ -156,6 +157,15 @@ Player-facing:
/ranking [categoria] placares do servidor
/canalhandia status mostra toda a configuração
/canalhandia modulos lista os módulos e seu estado
/save salva onde você está (privado)
/save coords o mesmo, escrito por extenso
/save <texto> salva o lugar com um texto
/nota add <texto> anotação privada, só você vê
/nota publica <texto> anotação pública (precisa de permissão)
/nota listar [publicas|privadas] lista o que você pode ver
/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
```
Admin (`canalhandia.admin`):
@@ -199,6 +209,8 @@ survive a restart.
| `canalhandia.forcar` | op | trigger curiosities and guess rounds |
| `canalhandia.admin` | op | change modules and all settings |
| `canalhandia.isento` | nobody | never be the subject |
| `canalhandia.nota` | everyone | `/save` and private notes |
| `canalhandia.nota.publica` | op | write notes everyone can read |
| `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 |
@@ -210,6 +222,73 @@ reacting.
---
## Notes (`/save`, `/nota`)
Somewhere to write things down without leaving the game. Persisted to
`plugins/Canalhandia/notas.yml`.
### Scopes
| Scope | Who reads it | Who may write it |
|---|---|---|
| **private** (default) | only the author | everyone — `canalhandia.nota` |
| **public** | everyone; announced when created | `canalhandia.nota.publica` (op) |
Public notes are gated because a board anyone can write to becomes a graffiti
wall. Grant it per player with LuckPerms:
`lp user <nome> permission set canalhandia.nota.publica true`.
### `/save` — the quick path
`/save` and `/save coords` pin the spot you are standing on. `/save <texto>`
pins it with a note. Always **private**: this is the command someone types
without reading help first, and the safe default for that is the one that
cannot surprise anyone by broadcasting. `/nota publica <texto>` is the explicit
way to share.
### Places, not teleports
Every note stores the world and block coordinates where it was written — on a
Minecraft server a note is nearly always about a *place*. On Java the
coordinates are click-to-copy (the same affordance the death-coords message
uses); Bedrock renders no click event and gets the same text plainly.
There is **no teleport**. Nothing in this module touches gameplay; a note is a
line of text and a set of numbers.
### Privacy
**A private note is never sent to the AI, at any setting.** The AI call leaves
this server for a third-party API, so a private note reaching it would be a
disclosure the author never agreed to. The filter lives inside
`Notes.publicSummary` — the only method the AI path calls — rather than at the
call site, so a future caller cannot get it wrong by accident. A test asserts
it directly.
Public notes *are* sent (`ia.contexto-notas`, default 10, 0 disables), which is
what lets `/ia onde fica a base?` answer from what players actually wrote down.
Two smaller rules follow from the same principle: a note the viewer cannot see
is reported as **missing** rather than as forbidden (saying "that one is
private" would confirm it exists), and `/nota buscar` runs through the same
visibility filter, so search cannot become a way to probe for someone else's
text.
### Details
- Ids are never reused after a deletion — otherwise `/nota ver 2` would point
at a different note than the one someone wrote down a minute ago.
- 100 notes per player, both scopes together.
- 256 characters per note. The section sign and control characters are
stripped: a note is echoed into chat and could otherwise forge a line that
looks like it came from the server.
- Authors delete their own notes; `canalhandia.admin` deletes any, which is the
only way to clear a public note left by someone who has stopped playing.
- Search is case- and accent-insensitive — nobody types "após" into a chat
search, and missing a match over an acute reads as broken.
---
## IA (`/ia`)
Chat Q&A backed by an OpenAI-compatible endpoint (default MiniMax). Gated to
@@ -422,6 +501,7 @@ 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) |
| `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 |
| `ServerState.java` | Main-thread snapshot of the live world for the AI |