Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,53 @@ A Velocity proxy only knows its own players. Ask it for `dahendriik` while they

Local first, always — a player on this proxy is already in memory and costs nothing to find.

## Join welcome

A fresh network join receives a single welcome block with the large 26px Grounds
wordmark used by the network HUD, the player's name, and independent Discord,
TikTok and Shop links in one horizontal row. The resource pack supplies sharp
pixel-art brand icons (Discord, TikTok and a shopping bag); both icon and label
open the link. Modern clients receive it after the first backend connection and
one acknowledgement round trip, with no fixed welcome delay. Required packs have
already loaded during configuration. A `grounds:welcome_ready` cookie request is
queued after JoinGame so client join-time mod announcements precede its response.
Clients without a verified HUD font pack see the
Grounds name instead of an unsupported glyph.

Discord defaults to `https://grnds.link/discord`, matching the lobby bossbar.
TikTok (`https://example.com/grounds/tiktok`) and Shop
(`https://example.com/grounds/shop`) are intentional placeholders. Replace these
with `WELCOME_TIKTOK_URL` and `WELCOME_SHOP_URL`; `WELCOME_DISCORD_URL` can override
Discord as well. Keep these values consistent across proxy deployments.

Clients that have not announced Simple Voice Chat receive a short description
and a link to the official installation guide, as a complete localized sentence
followed by the installation action. Client channel registration or a
voice handshake suppresses that section even if voice is disabled or UDP cannot
connect. Handshake messages continue to the backend unchanged. Server switches
do not repeat the welcome. A connection-scoped `grounds:welcome` client cookie
carries whether the block was delivered across proxy/region transfers: an early
redirect still gets its first welcome at the destination. Fresh logins reset
the marker before preferred-region routing. Disconnect and shutdown cancel
pending delivery.

Before rollout, check a fresh join on each proxy, a backend switch, and a proxy
transfer. Check clients with the mod absent, present but disabled, and present
with UDP blocked; only the first should get installation help. Also check a
declined resource pack and a disconnect/reconnect before the ready-cookie reply.
Only legacy protocols before 1.20.5 retain the old five-second negotiation grace.

The installation observers capture only an in-memory bit at maximum synchronous
priority, then explicitly hand off to an asynchronous EventTask. This preserves
packet order before the ready reply without moving other plugins' handlers onto
the packet thread. Before changing the Velocity runtime, verify these dispatcher
semantics against its actual JAR:

```sh
velocity/src/test/scripts/verify-welcome-dispatch.sh \
velocity/build/libs/plugin-proxy-velocity.jar /path/to/deployed-velocity.jar
```

## How the pieces fit

```
Expand Down Expand Up @@ -121,6 +168,20 @@ allowed can still _show_ the MOTD; `/motd set` then reports the refusal instead

## Tab footer and diagnostics

`/whereami` is available to every player and shows their current region, full proxy
ID and current backend ID in one indented Grounds chat block. A short explanation
asks players to use these details when contacting support. Hover and click the
proxy or server ID to copy it. Missing values appear as `—`. The command reads the
current connection on whichever proxy handles it, so backend switches appear
immediately without a presence-service lookup. Region uses `REGION`, falling back
to the existing `CONTINENT`/region code when the datacentre is not configured.
All text is localized in English, German, French and Spanish.
The heading and body follow the Minecraft Mini-CD (warm white, sand and cyan
copy actions). Three first-party pixel icons in `grounds:connection` appear only
with verified HUD readiness and a compatible `WHEREAMI_FONT_PACK_SHA1S` allowlist;
otherwise the indented text labels remain. The icons use an additive platform
pack font and do not replace vanilla fonts or the existing welcome graphics.

The footer is one localized status line, for example `Lobby 2 • 42 players online • 17 ms`.
The server number is its deterministic position among the currently registered servers of the
same kind, not a pod identifier. All proxies with the same discovery inventory show the same
Expand Down Expand Up @@ -215,3 +276,7 @@ maintenance is active. New maintenance drafts default to an empty override.
```

Published on tag as `gg.grounds:plugin-proxy-api` (consume this) and `plugin-proxy-velocity`, and as `ghcr.io/groundsgg/plugin-proxy` — the image carries the shaded JAR at `/jar/plugin.jar` for the `plugin-velocity-jar` Helm chart.

Welcome bitmap icons use `grounds:welcome` U+E400/U+E401/U+E402. Set `WELCOME_FONT_PACK_SHA1S` to the verified platform-pack hashes containing these glyphs and restrict `HUD_FONT_PACK_SHA1S` to that same set. Icons remain disabled unless every HUD-ready hash is covered; unknown packs show plain labels. Existing chat, sidebar and HUD pack allowlists must include a newly activated platform pack as appropriate.

The welcome can use the original full Grounds logo with floating stones. Only enable WELCOME_LOGO_PACK_SHA1S for HUD-approved hashes containing U+E403; otherwise the existing compact wordmark remains. Its40px artwork reserves more rows; with Voice help the block ends in normal-height text and still fits ten closed-chat rows. Voice copy and Install use the same sand-coloured bullet as the bossbar.
41 changes: 41 additions & 0 deletions docs/superpowers/plans/2026-11-04-join-welcome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Join Welcome Implementation Plan

> **For agentic workers:** Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox syntax for tracking.

**Goal:** Deliver the agreed welcome block once per fresh network join with conditional voice installation help.
**Architecture:** A renderer builds translated Adventure components; a Velocity listener handles connection lifecycle and observes mod negotiation. Wire both into plugin-proxy.
**Tech Stack:** Kotlin, Velocity, Adventure, library-i18n, JUnit 6.
**Spec:** `docs/superpowers/specs/2026-11-04-join-welcome-design.md`

## Global Constraints

- Discord is `https://grnds.link/discord`; TikTok and Shop are replaceable placeholders.
- Skip server switches and delivered cross-proxy transfers; preserve a pending first welcome through early region redirects. Clean up on disconnect/shutdown.
- Voice off or disconnected does not mean the mod is absent.
- Draw logo only with verified chat-font readiness; support all four plugin locales.

## Review Focus

- Mod handshake before the first backend connection must suppress the hint.
- Forward client voice handshakes intact and ignore backend-originated messages.
- Late callbacks from a disconnected session must not message a reconnect.
- A transfer onto another proxy must preserve the first welcome if still pending and suppress an already delivered welcome.
- Missing packs and markup-like player names must produce readable, safe text.

### Task 1: Welcome rendering and lifecycle

**Files:** New `welcome/WelcomeMessage.kt`, `welcome/WelcomeListener.kt`, tests under the same package; modify plugin initialization, four resource bundles, README.
**Interfaces:** Renderer `render(playerName, locale, logoReady, voiceInstalled): Component`; listener accepts a delayed scheduler and readiness lookup to test actual event handlers without a running proxy.

- [x] Write rendering tests for clickable URLs, localized voice visibility, safe names and logo fallback; lifecycle tests for switches, transfers, early/disabled voice, backend spoofing, disconnect and reconnect.
- [x] Run `./gradlew :velocity:test --offline --console=plain` and confirm new tests fail because the feature is absent.
- [x] Implement renderer, observer and lifecycle gates; wire a five-second delayed task and register observed voice channels. Add translations and document configurable placeholder links.
- [x] Run `./gradlew test --offline --console=plain` and repository formatting checks. Review the diff for forwarding, cleanup and cross-proxy behavior.

Execution: primary agent, current suitable checkout on a task branch; no separate implementation agents needed.

Review ruling: use a client cookie rather than unconditional transfer suppression, because preferred-region redirects happen at PostLogin before a first backend connection. Cookie state is cosmetic, reset for each LOGIN, queried only for TRANSFER, and tracked by the exact connection.

Validation: `./gradlew spotlessApply test spotlessCheck --offline --console=plain` passed after the transfer fix; 229 tests, zero failures/errors/skips. `git diff --check` passed. Live Minecraft clients and multi-proxy deployment smoke checks were not available in this session.

Visual follow-up: replace the small chat G plus text heading with the verified large HUD wordmark, switch readiness to PlayerHudAppearanceQuery, reserve space for the tall bitmap, and put native icon+label links on separate rows. Updated existing link/layout tests first (three expected failures), then implemented; full Gradle test and formatting checks passed. Stage follow-up is within the existing deployment authorization.
43 changes: 43 additions & 0 deletions docs/superpowers/plans/2026-11-04-whereami.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Whereami Implementation Plan

> **For agentic workers:** Use superpowers:executing-plans for this small change.

**Goal:** Add the approved support-oriented `/whereami` chat block.

**Architecture:** A Velocity SimpleCommand renders a single localized component
through the existing system renderer. The command uses the current invoker's
backend and proxy-specific environment data; no external lookup is needed.

**Tech Stack:** Kotlin, Velocity, Adventure, library-i18n, JUnit, Gradle.

**Spec:** `docs/superpowers/specs/2026-11-04-whereami-design.md`

## Constraints and review focus

No permission grant, no local-proxy assumption about other players, no cached
backend, no duplicate system prefix. Console has no location. Missing data must
not become a copy action. Preserve full IDs and treat all values as literal text.
Use existing colors and pack readiness behavior in all four supported locales.

## Task 1: Command and presentation

- [x] Update `velocity/src/test/kotlin/gg/grounds/proxy/velocity/command/WhereAmICommandTest.kt`
to assert the single indented block, independent proxy identities, backend
switches, unavailable fields, localized console handling, literal IDs and copy
payloads. Run the focused tests and observe failure for the missing command.
- [x] Add `WhereAmICommand.kt` beside the existing proxy commands; add message keys
in `ProxySystemMessage.kt` and all four `messages*.properties` bundles.
- [x] Register `whereami` in `GroundsProxyPlugin.kt` using this proxy's environment
and document player-facing behavior in `README.md`.
- [x] Run focused tests, then `./gradlew test check shadowJar --offline --console=plain`.
Expected: successful checks and packaged Velocity plugin.
- [x] Review the final diff and record actual verification results.

## Verification

The six new command tests failed against the empty command, then passed after
implementation. The final `test check shadowJar --offline --console=plain` run
succeeded, including format checks and packaging. Final review checked one-prefix
rendering, literal values, exact copy payloads, per-proxy identity, current backend
reads and missing data. The command was not exercised on live Minecraft clients.
Unrelated concurrent welcome changes in the checkout were preserved.
35 changes: 35 additions & 0 deletions docs/superpowers/plans/2026-11-05-welcome-mosaic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Welcome Mosaic Implementation Plan

> **For agentic workers:** Use superpowers:executing-plans to implement this plan inline.

**Goal:** A larger, sharper, seamless welcome logo that fits closed chat.
**Architecture:** Two native bitmap cells from existing branded artwork; compact decorated rendering; exact pack hash gates on Stage.
**Tech Stack:** Kotlin, Adventure, Java ImageIO, Minecraft bitmap fonts, Gradle, Argo.
**Spec:** ../specs/2026-11-05-welcome-mosaic-design.md

## Global Constraints

Ten rows, original colors, 14px social icons, separate click targets, conditional voice hint, fallback unchanged, preserve current Stage features.

## Review Focus

Native cell limits; seams from glyph advance; closed-chat cropping; four locales; old-pack fallback.

## Task 1: Native mosaic

- [ ] Add failing font tests for 512x241 source, two 256x241 cells, height56/ascent50 and fractional join spacing.
- [ ] Run focused test, then update WelcomeFont and pinned asset provenance.
- [ ] Verify each cell with native client atlas code and pixel reconstruction.

## Task 2: Compact welcome

- [ ] Add failing tests for both slices, ten rows, icon/logo bounds, all locales and unchanged fallback.
- [ ] Update WelcomeGlyphs, WelcomeLayout, WelcomeMessage and four compact greeting keys.
- [ ] Run focused tests then full Gradle test, spotlessApply and build for both projects.

## Task 3: Stage

- [ ] Review changes, sign isolated source commits and build immutable artifacts.
- [ ] Preserve active content ZIP and current Stage features; publish catalog, pack and proxy image.
- [ ] Update hash gates and pack selection with concurrency checks; activate Stage.
- [ ] Verify both Java proxies, Bedrock fallback and client atlas behavior.
9 changes: 9 additions & 0 deletions docs/superpowers/plans/2026-11-05-welcome-separated-lines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Separate welcome rows

The user approved a slightly smaller logo to keep everything visible in the default ten-row chat.

- Test the 42px logo at ascent41, preserving two 256x241 source cells and exact fractional join spacing.
- Test separate centered greeting/name and social rows, full icon bounds, voice copy and blank footer in ten rows for all four locales.
- Implement using existing welcome fonts and copy; preserve link targets, conditional voice hint and fallback.
- Run test, spotlessApply and build; sign source commits and publish immutable PackSet v1.2.2-stage-welcome.6 plus matching proxy image.
- Preserve current Stage features and content; verify all three proxies after staged rollout.
Loading
Loading