<feed xmlns='http://www.w3.org/2005/Atom'>
<title>LunaticChat.git/platform-paper/src/main/resources, branch main</title>
<subtitle>A next-generation chat plugin for Paper, Folia and Velocity.
</subtitle>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/'/>
<entry>
<title>refactor: read config.yml into the config classes directly</title>
<updated>2026-08-04T16:16:03+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-08-03T06:16:39+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=576c057bb98dab27c2b97931fc5635603fe1bf57'/>
<id>576c057bb98dab27c2b97931fc5635603fe1bf57</id>
<content type='text'>
Every setting's default was written three times - in config.yml, in the
ConfigManager getter call, and on the data class - and copying the file
key by key is what made that necessary. They had already drifted:
checkForUpdates defaulted to false in ConfigManager while both config.yml
and the data class said true.

Worse, features.channelChat.messageLogging was documented in config.yml
with three settings and never parsed at all. ConfigManager did not build
it, so ChannelMessageLoggingConfig() always won and an operator editing
retentionDays or maxFileSizeMB changed nothing. Those settings now take
effect - the documented behaviour, but a real change for anyone whose file
disagrees with the defaults.

KAML deserializes the file straight into the tree, the same way player
settings and channel data are already read, so a default now lives only on
the data class. Two consequences worth stating:

- japaneseConversion.cache and .api are nested classes now, because the
  data has to match the file rather than the file being flattened by hand
  on the way in. The YAML is unchanged.
- api.retryAttempts is gone from config.yml. It was parsed and stored, but
  never reached GoogleIMEClient or RomanjiConverter, so it documented a
  knob that did nothing.

Unknown keys are ignored and a malformed file falls back to defaults with
a log line, so neither an old config nor a typo stops the server booting.

The tests parse real YAML instead of a mocked FileConfiguration, which
lets them cover what the mock could not: a partial file, a retired key, a
malformed document, and - the one that would have caught the drift above -
that the bundled config.yml equals the declared defaults.

Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Every setting's default was written three times - in config.yml, in the
ConfigManager getter call, and on the data class - and copying the file
key by key is what made that necessary. They had already drifted:
checkForUpdates defaulted to false in ConfigManager while both config.yml
and the data class said true.

Worse, features.channelChat.messageLogging was documented in config.yml
with three settings and never parsed at all. ConfigManager did not build
it, so ChannelMessageLoggingConfig() always won and an operator editing
retentionDays or maxFileSizeMB changed nothing. Those settings now take
effect - the documented behaviour, but a real change for anyone whose file
disagrees with the defaults.

KAML deserializes the file straight into the tree, the same way player
settings and channel data are already read, so a default now lives only on
the data class. Two consequences worth stating:

- japaneseConversion.cache and .api are nested classes now, because the
  data has to match the file rather than the file being flattened by hand
  on the way in. The YAML is unchanged.
- api.retryAttempts is gone from config.yml. It was parsed and stored, but
  never reached GoogleIMEClient or RomanjiConverter, so it documented a
  knob that did nothing.

Unknown keys are ignored and a malformed file falls back to defaults with
a log line, so neither an old config nor a typo stops the server booting.

The tests parse real YAML instead of a mocked FileConfiguration, which
lets them cover what the mock could not: a partial file, a retired key, a
malformed document, and - the one that would have caught the drift above -
that the bundled config.yml equals the declared defaults.

Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>refactor: remove code that no production path reaches</title>
<updated>2026-08-02T10:10:56+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-08-02T10:10:46+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=bc0d7d522e169f3eeb8d5b632ee673392060694b'/>
<id>bc0d7d522e169f3eeb8d5b632ee673392060694b</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>feat: support Paper 26.2 (Minecraft 26.2)</title>
<updated>2026-08-02T08:43:50+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-08-02T08:43:50+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=45c29405be5169e088023aa01cde50467f3eabed'/>
<id>45c29405be5169e088023aa01cde50467f3eabed</id>
<content type='text'>
Paper 26.2 bundles Adventure 5.2.0, a major bump from the 4.26.1 shipped by 26.1.
Adventure 5 makes ClickEvent generic, so the raw type in
CommandContext.replyWithEvent no longer compiled. Auditing the rest of the
Adventure 5 removals found no other affected usage.

api-version is raised to 26.2, dropping 26.1 support: the two Adventure majors
are not binary compatible, so claiming 26.1 compatibility would be a lie.

Also fixes two problems found while verifying on a real server: the Velocity
healthcheck invoked mc-health, which does not exist in the mc-proxy image, so the
container had never once passed its check; and the debug environments pinned no
build at all, which meant the proxy came up as 4.1.0-SNAPSHOT while the plugin is
compiled against velocity-api 3.5.1. Server versions are now derived by x from
the Gradle coordinates so they cannot drift from what the plugin targets.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Paper 26.2 bundles Adventure 5.2.0, a major bump from the 4.26.1 shipped by 26.1.
Adventure 5 makes ClickEvent generic, so the raw type in
CommandContext.replyWithEvent no longer compiled. Auditing the rest of the
Adventure 5 removals found no other affected usage.

api-version is raised to 26.2, dropping 26.1 support: the two Adventure majors
are not binary compatible, so claiming 26.1 compatibility would be a lie.

Also fixes two problems found while verifying on a real server: the Velocity
healthcheck invoked mc-health, which does not exist in the mc-proxy image, so the
container had never once passed its check; and the debug environments pinned no
build at all, which meant the proxy came up as 4.1.0-SNAPSHOT while the plugin is
compiled against velocity-api 3.5.1. Server versions are now derived by x from
the Gradle coordinates so they cannot drift from what the plugin targets.</pre>
</div>
</content>
</entry>
<entry>
<title>feat: add cross-server direct messaging via Velocity</title>
<updated>2026-06-17T07:15:40+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-06-17T07:15:40+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=c678bd15324dad0519cb1d9a4c58202a981ee8e2'/>
<id>c678bd15324dad0519cb1d9a4c58202a981ee8e2</id>
<content type='text'>
Allow /tell and /reply to reach players on other Paper servers behind a
Velocity proxy using the "&lt;player&gt;@&lt;server&gt;" target syntax.

Engine (protocol bumped 1.0.0 -&gt; 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 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Allow /tell and /reply to reach players on other Paper servers behind a
Velocity proxy using the "&lt;player&gt;@&lt;server&gt;" target syntax.

Engine (protocol bumped 1.0.0 -&gt; 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 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>feat: Support Minecraft 26.1</title>
<updated>2026-04-04T07:12:42+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-04-04T07:12:42+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=c7aff8fbd0b04624b8291cf0362bed70471f46ae'/>
<id>c7aff8fbd0b04624b8291cf0362bed70471f46ae</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>chore: Remove unused language data</title>
<updated>2026-03-25T23:36:12+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-03-25T23:36:12+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=b4ad3086eaaa5280855816a5dd6ed37b939a4659'/>
<id>b4ad3086eaaa5280855816a5dd6ed37b939a4659</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>feat: Add Night warning to Status Command</title>
<updated>2026-03-25T22:27:51+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-03-25T21:21:37+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=e0d1f7a9bc9122d02de829a28a51b9aec8611fa5'/>
<id>e0d1f7a9bc9122d02de829a28a51b9aec8611fa5</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>feat: Improved notification messages when logging in to the server</title>
<updated>2026-03-17T13:11:21+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-03-17T13:11:21+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=2bc07010e32a2c1313d44d7d313d2317531971ff'/>
<id>2bc07010e32a2c1313d44d7d313d2317531971ff</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>feat: Remove permission</title>
<updated>2026-03-17T12:54:05+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-03-17T12:54:05+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=1812e3558db357ddd21d3d2fd40df63b2a7f000a'/>
<id>1812e3558db357ddd21d3d2fd40df63b2a7f000a</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>feat!: Remove ChatMode feature, followback channel chat mode</title>
<updated>2026-03-17T11:34:18+00:00</updated>
<author>
<name>Sho Sakuma</name>
<email>me@m1sk9.dev</email>
</author>
<published>2026-03-17T11:34:18+00:00</published>
<link rel='alternate' type='text/html' href='https://www.dangofactory.net/cgit/cgit.cgi/LunaticChat.git/commit/?id=634dd975038bb5b845c28ca6c96aa285ef94e965'/>
<id>634dd975038bb5b845c28ca6c96aa285ef94e965</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
</feed>
