Three features that all answer questions the server could already have
answered but was throwing away.
Mail (/recado <jogador> <texto>, /recados). On a server where people rarely
overlap, "achei diamante em -400 70 200" had to go through Discord or be lost.
Messages are queued for anyone who has joined before — resolved through
usercache.json, case-insensitively, because nobody types a name with the right
capitalisation — and delivered on their next join. If the recipient is online
it is delivered immediately instead of queued, since queueing it would mean
the person standing next to you reads it only after a relog.
Delivery is destructive: a message that stayed queued would be re-read on every
single join, turning a helpful note into a nuisance. It is also delayed a few
seconds and re-checks isOnline, because a player can leave inside the delay and
the mail would otherwise be consumed with nobody there to read it. Its own
join handler, not a branch inside onJoin, which returns early when the
curiosidades module is off — mail must not depend on an unrelated module.
Inbox capped per recipient, counting every sender, so the cap cannot be
bypassed with a second account.
Death history (/mortes). The mortes module already knew where and how someone
died and discarded it once the coords were delivered on respawn. Keeping the
last ten per player answers what people actually ask a day later. Eviction is
per player, not global, or one player's bad night would erase everyone else's
history. Your own deaths only: where someone died is where their stuff is, and
a public list of that is a looting guide.
Named achievements (/conquistas). Milestones covers round numbers; this covers
the combinations that say something about how someone plays — "Casca Grossa"
(50 hours, under 10 deaths), "Turista" (100 hours, barely mined), "Imortal às
Avessas" (dies more than once per hundred blocks mined). Every condition is a
pure function of a stat map, so the catalogue is unit-tested without a server.
The ratio ones carry a floor on absolute mining, so a new player is not handed
a joke achievement on their second death — there is a test for exactly that.
First sight is silent, like Milestones: the first time a player is checked,
whatever they have already earned is recorded without announcing it. Otherwise
enabling the module would dump a dozen announcements for history earned months
ago. Players who qualify for nothing are still marked as seen, or every later
check would treat them as new and stay silent forever.
Achievements share the milestone task rather than adding a second timer: both
sweep every online player's statistics, so one pass does the work of two.
Stats.totalOf sums a material-keyed statistic into a long — the per-material
values are ints and a long-running player's total can pass Integer.MAX_VALUE.
The /conquistas checklist uses "[x]" on Bedrock instead of "✔", which renders
there as a tofu box — the same per-platform rule the reaction labels follow.
Msg.ago renders wall-clock timestamps as "há 2 dias"; a timestamp from the
future clamps to "agora" rather than printing a negative age.
263 tests, up from 218.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pEyCmrAYHBFgpYjwFxKxh