| Age | Commit message (Collapse) | Author |
|
DirectMessageError.reason was a String backed by two constants, so the
receiving side matched one case and let everything else fall through to
"the target is offline". Adding a third reason on the proxy would have
shipped it to Paper servers that silently reported the wrong thing - the
one string-keyed dispatch sitting next to a protocol layer whose messages
are otherwise a sealed hierarchy with exhaustiveness checking.
As an enum, the reader must decide what to show for each case, and
CrossServerDirectMessageManager's when no longer needs an else.
The wire format is unchanged: kotlinx serializes an enum as its name, so
the existing snapshots still decode. What did need care is the reverse
direction - a reason from a newer proxy would now fail to parse, where the
String version degraded. The property has a default and the codec enables
coerceInputValues, so an unknown reason lands on TARGET_OFFLINE, exactly
the old else branch. There is a compatibility test for that case.
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
Every channel message wrote a fully interpolated INFO line, duplicating
what the dedicated async ChannelMessageLogger already persists. Every
cross-server message produced one INFO on the sending Paper server, two on
Velocity, and one on each receiving Paper server - so a single global chat
message cost up to four synchronous console and latest.log writes across
the network, on the message path, with JUL and Logback appenders being
synchronous.
These are now debug, and phrased so the string is not built unless debug
is on: the JUL sites take a supplier, the slf4j sites take a format plus
arguments.
Handshake, registration and delivery-failure lines stay at info - they
fire once per server or once per failed message, and they explain
something an operator needs to see.
Two relay tests asserted on the text of a log line. One of them was
verifying "0 servers" where the same test already verifies zero sends;
the other was really checking that the payload reaches the target, so it
now decodes the relayed bytes and compares them to the original message.
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
The channel Paper and Velocity talk over was declared in seven places, in
two spellings ("lunaticchat:main" and the namespace/name pair), one of
them an inline literal in CrossServerChatManager that bypassed even its
own file's constant. Renaming it meant finding all seven; missing one
leaves both sides compiling and starting, just not talking. It now lives
next to the codec that defines the wire format.
The echo-suppression cache was likewise written twice, and the copies had
already drifted in style - one hand-rolled the expiry sweep, the other used
filter/map - while staying semantically identical. Any future change to
eviction would have had to land in both, and CrossServerChatManager's copy
carried a comment claiming ConcurrentHashMap iterators cannot remove(),
which they can.
MessageDeduplicationCache documents the one property that surprised the
tests written against it: eviction orders by millisecond timestamp, so a
burst inside a single millisecond evicts arbitrarily among its members.
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
These were all scaffolding that drifted out of use, and each one costs
a reader time before they discover it does nothing:
- UUIDASStringSerializer duplicated UUIDSerializer byte for byte; the
differing descriptor name never reaches the JSON/YAML wire format, so
the choice between them was a coin flip for contributors.
- Velocity's BuildInfo was never referenced (the plugin reads its version
from PluginContainer) and read a "commit" property the build never
wrote, so it would have reported "unknown" had anyone called it.
- KanaConverter.TrieNode.Leaf is never constructed: buildTrie starts from
a Branch and insert only ever returns Branch. Six branches guarded
against a state the type system allowed but the code could not produce.
With those gone, isValidRomaji and toHiragana were visibly the same
trie walk, so they now share one longestMatch.
- @Deprecated command handling had no annotated command to act on.
- The settings backup restore looked for *.backup.* files that nothing in
the repository writes, so it always fell through to empty settings.
Also drops CommandContext.replyWithEvent/replyPlain, PluginCoroutineScope's
unused plugin parameter, GitHubRelease fields no caller reads, and four
language keys with no lookup site.
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
Allow /tell and /reply to reach players on other Paper servers behind a
Velocity proxy using the "<player>@<server>" target syntax.
Engine (protocol bumped 1.0.0 -> 1.0.1, optional sub-channels):
- Add DirectMessageRelay, DirectMessageError, PresenceSnapshot/PresenceEntry
and PresenceRequest messages plus codec branches.
Velocity:
- CrossServerDirectMessageRelay routes a DM to the target server (or returns
a delivery error to the source).
- PresenceTracker broadcasts proxy-wide presence snapshots on join/quit/switch
and on request.
Paper:
- RemotePlayerRegistry caches proxy presence for completion and remote target
resolution.
- CrossServerDirectMessageManager handles send/receive/error and dedup.
- DirectMessageHandler reply state generalized to ReplyTarget (Local/Remote)
so /reply works across servers.
- TellCommand parses "name@server", completes local names and remote
name@server targets, and uses exact local name matching.
- New crossServerDirectMessage config flag and i18n keys (en/ja).
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
|
|
|
|
- Add 23 new test files covering exceptions, data classes, permissions,
setting handlers, commands, and cross-server relay
- Change command execute methods from private to internal visibility
to enable unit testing (16 command files)
- Engine coverage: 65.5% → 92.4%
- Platform-paper coverage: 16.8% → 40.0%
- Platform-velocity coverage: 62.4% → 76.8%
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
- Add Jacoco plugin to all subprojects with XML report generation
- Replace post-test-results.sh with Codecov upload in CI workflow
- Add codecov.yml configuration
- Add 140 new tests across engine, platform-paper, and platform-velocity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
|
|
Explain why the plugin parameter uses Any type instead of a generic:
- Velocity's EventManager.register() accepts Object
- Generic type provides little practical benefit given the API design
- Typically receives the main plugin instance
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
|
|
|