Skip to content

About

Velocity plugin for Left4Craft Chat

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Left4Chat — Velocity port

Velocity 4 rewrite of the BungeeCord left4chat-bungee-1.0-jar-with-dependencies.jar that ran on the old proxy. No source was available, so the original was decompiled from the shipped jar and reimplemented against the Velocity API.

What it does

Unchanged from the Bungee version:

  • Broadcasts [+] <player> joined / [-] <player> left network-wide.
  • Tells the old server [<] <player> switched to <server> and the new one [>] <player> switched from <server>.
  • Publishes {"type":"join|leave","name":"<player>"} on the minecraft.chat Redis channel for the Discord bot.
  • Keeps the minecraft.players Redis key holding a JSON array of {username, uuid, server} for everyone online.
  • Sends the welcome MOTD on first connect.
  • Suppresses all of the above for players LiteBans is about to kick.

Added since the port:

  • Server alias commands (/hub, /survival, ...) — the old proxy's BungeeAliases plugin, folded in.
  • Reconnects players to the server they were last on, via a Redis hash.
  • Vote rewards: when NuVotifier (running on this proxy) receives a vote, a configurable message is broadcast network-wide and configurable console commands are published to minecraft.console.<server>.in, where the Paper-side Left4Chat's console relay runs them. By default the survival server runs eco give <player> 100. Requires NuVotifier on the proxy; without it the feature logs a warning and stays off.

Building

Needs JDK 25 — Velocity 4.0.0's class files are major version 69, so an older compiler cannot read them.

./gradlew shadowJar
# -> build/libs/left4chat-velocity-2.0.0.jar

Drop the jar in the proxy's plugins/ directory. On first start it writes plugins/left4chat/config.yml; the deployment copy for the OVH proxy is kept at ../ovh-server/velocity/plugins/left4chat/config.yml.

libs/litebans-api-2.19.0.jar is the litebans.api package lifted out of LiteBans.jar, because LiteBans publishes no public Maven artifact. Regenerate it when LiteBans is upgraded:

unzip -q LiteBans.jar 'litebans/api/*' -d /tmp/lb
(cd /tmp/lb && jar cf litebans-api-<version>.jar litebans)

libs/nuvotifier-api-2.7.3.jar is the Vote model and Velocity VotifierEvent lifted out of the NuVotifier release jar, because NuVotifier's JitPack builds are broken for every 2.7.x tag. Regenerate it when NuVotifier is upgraded:

curl -LO https://github.com/NuVotifier/NuVotifier/releases/download/v<version>/nuvotifier.jar
unzip -q nuvotifier.jar 'com/vexsoftware/votifier/velocity/event/*' \
    'com/vexsoftware/votifier/model/Vote.class' -d /tmp/nv
(cd /tmp/nv && jar cf nuvotifier-api-<version>.jar com)

Decompiled original

decompiled/me/sisko/left4chat/ holds the CFR output for Main, PlayerListUpdater and MOTDSender — the entire original plugin, about 120 lines. Kept for reference when diffing behaviour.

API mapping

BungeeCord Velocity 4
Plugin subclass + plugin.yml @Plugin-annotated class, descriptor generated by the API's annotation processor
onEnable() @Subscribe ProxyInitializeEvent
PostLoginEvent PostLoginEvent (com.velocitypowered.api.event.connection)
PlayerDisconnectEvent DisconnectEvent
ServerSwitchEvent, getFrom() null on first join ServerConnectedEvent, getPreviousServer() empty on first join
ProxyServer.broadcast(BaseComponent[]) ProxyServer.sendMessage(Component) — ProxyServer is an Audience
ServerInfo.getPlayers() RegisteredServer.getPlayersConnected()
ProxiedPlayer.getServer().getInfo().getName() Player.getCurrentServer() → Optional<ServerConnection>
ProxiedPlayer.getDisplayName() Player.getUsername() — Velocity has no proxy-side display name
ChatColor.translateAlternateColorCodes('&', s) LegacyComponentSerializer.legacyAmpersand().deserialize(s)
getProxy().getScheduler().schedule(plugin, task, 1, SECONDS) proxy.getScheduler().buildTask(plugin, task).delay(...).schedule()
litebans.api.Database unchanged — the LiteBans API is platform-neutral

Behavioural changes

Everything here is a deliberate departure from the decompiled original. Each one can be reverted through config except where noted.

  1. Redis host, password, MOTD and the four message prefixes are now configuration. They were compiled into the old jar, pointing at the dead 10.8.0.2 VPN address. That also means the old Redis password was shipped inside a distributed jar and should be treated as compromised.

  2. Connections are pooled. The original constructed a new Jedis(...), re-authenticated, issued one command and closed the socket — on every join, every leave and every player-list refresh. Now a single pooled RedisClient is held for the plugin's lifetime.

  3. Redis and LiteBans work happens off the event thread. The original ran Database.get().isPlayerBanned(...) — a SQL round trip — inline in the Bungee login sequence. That was survivable against a LAN database; against PlanetScale it would add its latency to every login.

  4. Redis failures no longer propagate. They are logged and swallowed, so a Redis outage costs announcements rather than breaking joins.

  5. The MOTD is sent on first ServerPostConnectEvent instead of on a one-second timer after login. The original's delay was working around the player not being on a backend server yet; this waits for the actual event. motd.delay-millis adds a delay on top if something else clears chat on join.

  6. Player-list writes are coalesced. Ten simultaneous joins scheduled ten identical Redis writes before; now overlapping requests collapse into one.

  7. A player with no current server no longer breaks the player list. Bungee's getServer() returned null mid-handshake and the resulting NPE aborted the whole update, leaving the key stale. Their server field is now null.

  8. refresh-interval-seconds optionally republishes the player list on a timer as a safety net. Off by default in the bundled config, set to 60 in the OVH deployment config. Set to 0 for the old behaviour.

  9. The player list key is cleared on proxy shutdown, instead of leaving the Discord bot showing a full server until the proxy comes back.

  10. The switching player no longer receives their own "switched from" message. The original excluded them from the old server's broadcast but not the new server's — asymmetric, and almost certainly unintended. Not configurable; revert in Left4Chat#onServerConnected if the old behaviour is wanted.

Not carried over

Nothing. The original had no commands, no permissions and no other listeners.

About

Velocity plugin for Left4Craft Chat

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages