All pages

Contributing

Sending a change back to Vantage itself - where issues go, how branches and commits are written in this repository, what "verified" means before a merge request, what the pipeline checks, and the house rules the code keeps.

Vantage is MIT-licensed and its source is public on GitLab. Most people who change it should fork it and ship their own; Fork it says why, and Forking says how. This page is for the other case: you have fixed something or built something, and you would like it in Vantage itself. It describes how this repository already does things, read from its history, its pipeline file and ARCHITECTURE.md, so that your merge request reads like the rest of the log and passes the same checks.

Before you start

Vantage has one maintainer. A small fix can go straight to a merge request. For anything larger, such as a new feature, a new dependency or a change to how something is stored, open an issue first and describe what you want to do. Finding out that a change does not fit costs one message that way, rather than an evening.

Issues live on the project's GitLab page, at gitlab.com/Ekoss/vantage/-/issues. You need a GitLab account to open one, as with any GitLab project.

Getting the code

The default branch is main. Fork the project on GitLab, clone your fork, and work on a branch of your own:

git clone https://gitlab.com/<you>/vantage.git
cd vantage
git checkout -b fix/short-description-of-the-fix
./gradlew compileJava test

You need JDK 25 to run Gradle; Building has the details, and the one flag to remember when you build a jar.

Branches

A branch is named <type>/<short-kebab-description>. The type is drawn from the same vocabulary as commit prefixes, so a reviewer scanning open merge requests knows the shape of the change before opening it. These are real branches from the history:

BranchWhat it carried
feat/waypoints-anywhereWaypoints scoped by the world you are in, not by island
fix/chat-click-actionsChat lines that kept their click after a feature rewrote them
feat/pathfinding-revampA new pathfinding engine
polish/obsidian-glassThe Obsidian Glass interface
fix/stats-2.0.1The Vantage Stats fixes of a patch release

Branch from main and target main. A large piece of work may have a branch of its own that smaller branches merge into first, as fix/stats-2.0.1 did, but you will rarely need that.

Commits

The subject

A subject is a lower-case area prefix, a colon, and a short lower-case line saying what the change does:

chat: keep the click when a feature rewrites a line
stats: one refused row no longer stops every upload, and the mod's own words pass its own filter
pathfinding: a new engine - real block shapes, searched off the client thread
features/mining: gemstone grinding efficiency and drill fuel burn rate
release: 2.0.1 for both targets

The prefix names where the change lives or what kind of work it is:

Kind of prefixExamples from the log
A feature area, as its package pathfeatures/mining, features/qol, features/combat
A subsystemstats, ui, hud, chat, pathfinding, api
A kind of workdocs, build, tools, ci, refactor, chore, fix
The release routinerelease, announce

Some subjects are imperative ("keep the click…"); many name the result instead ("a new engine…", "2.0.1 for both targets"). Either reads well in a log. What they avoid is vagueness: "fixes" or "update" says nothing a reviewer can check.

The body

The body says why: what was broken, what you tried and rejected, and what you deliberately left alone. It is fine for it to run to several paragraphs when the decision was not obvious. It ends with a paragraph that starts Verified: and names the commands you ran and what they said, not "tested and works". Shortened, from the commit that fixed chat clicks:

chat: keep the click when a feature rewrites a line

On Hypixel the click is the interaction. A party invite, a warp, the stash
pickup line and a duel accept are all a click on a chat line, so a rewrite
that drops the ClickEvent does not cost formatting - it turns a working
prompt into dead text, with nothing in the log to say why.
…
Verified: ./gradlew compileJava test clean on both targets (26.2, and
-Pminecraft_version=26.1.2), … ChatActionsTest builds the
component shape Hypixel actually sends - plain text with one clickable run
inside it - and pins that the legacy round trip loses the click, that
keepActions puts it back without touching the rewrite's text, …

Merges

History keeps a branch's own commits and joins them to main with a merge commit. A merge made locally is written merge: <branch> into <target>, for example merge: fix/stats-2.0.1 into main; one made on GitLab keeps GitLab's own Merge branch '<branch>' into 'main'. Keep your branch's commits meaningful on their own, since they stay in the log.

What "verified" means

Before you open a merge request, run these and keep their output:

./gradlew compileJava test                                # the default Minecraft version
./gradlew compileJava test -Pminecraft_version=26.1.2     # the other one
./gradlew runUiSmokeTest                                  # then read run/screenshots/smoke-report.txt
python tools/tracker.py --check

The pipeline compiles only the default Minecraft version, so the second line is yours to run. The smoke test's report, not its exit code, is the verdict, and as of 2.0.1 a healthy report lists exactly one expected line; Testing shows it.

Some changes owe one more check:

If you changedAlso run
A feature's annotation, its options, a command or a keypython tools/tracker.py, python tools/tracker.py --catalog and python tools/sitedocs.py, then commit what they regenerate
A mixinpython tools/mixin_targets.py, after building each version once
Vantage Statspython tools/stats_catalogue.py --check and python tools/stats_golden.py --check
Anything you can seeOpen the screenshots; the menu-lit, gallery-lit and menu-ember frames show the light and a second preset
A feature id or an option's field nameAdd a migration, because both are persistence keys; Options and config shows how

Merge requests

The description

Write it in three parts, in the same voice as a commit body:

PartWhat goes in it
WhyThe problem, not the patch: what was wrong that made the change necessary
What was verifiedThe commands you ran and what each said, the smoke-test report included
RiskWhat could break, and what you deliberately left out of scope

Mark an unfinished merge request as a draft by starting its title with Draft:. GitLab will not merge it until the prefix is gone.

Linking issues

Write Closes #12 in the description to close issue 12 when the merge request is merged.

What the pipeline runs

A pipeline starts once the merge request exists. A branch with no merge request open runs nothing, so pushing early is quiet until you open one. On a merge request these jobs run:

JobWhat it checksFails the pipeline?
compile./gradlew compileJava test on the default Minecraft version, with the test report shown on the merge requestYes
build-jar./gradlew build -PnoVersionBump; the jar and its checksum stay downloadable for 30 days, so a reviewer can try itYes
tracker-currentThe tracker check, then the regenerated docs/catalog.json diffed against yoursYes
sast, secret_detectionGitLab's scanners; findings show on the merge request as reportsNo
ui-smoke-testThe UI smoke test under a virtual display, only when someone starts it by handNo

The release jobs run only for version tags, and the Discord announcement job only on main. Testing lists every job, and Releasing the ones that ship a build.

House rules

ARCHITECTURE.md opens with the ground rules every change is written against. Restated for someone new to the code:

  1. Never guess a Minecraft or Fabric signature. Read the sources. Minecraft 26.x ships unobfuscated, so the names you read are the real ones; there are no mappings.
  2. Read other mods for facts, never for code. Skyblocker and SkyHanni are LGPL. Reading them to learn a chat message's format, an item's NBT keys or a room's data is fine; copying their code is not, because Vantage is MIT.
  3. Compile often, and leave no stub that throws. A change is not done until it compiles cleanly.
  4. Write Java 25. Records, sealed interfaces, pattern-matching switch, var where the type is obvious, text blocks, virtual threads for blocking I/O, java.net.http.HttpClient. No Kotlin.
  5. Keep a change inside its package. Every subsystem has a package of its own under dev.cherishev.vantage. A diff that wanders into an unrelated one should say why.
  6. Write player-facing text as plain English literals, not translation keys, unless it is a vanilla component.
  7. Mixins go in mixin.<area>, listed in the matching vantage.<area>.mixins.json. Prefer a Fabric API event where one exists. A widened member goes in both versions' access wideners; Multi-version explains why.
  8. Touch Minecraft's state only on the client thread. Network and file I/O run on virtual threads and post their results back.
  9. The Minecraft access token has exactly one call site, in core/stats/sync/IdentityProof.java, where it goes straight to Mojang. grep -rn "getAccessToken\|getSessionId" src/main/java must print one line. This is a release gate.

A few more come up in review often enough to know in advance:

  • A feature is one file. The @FeatureInfo annotation registers it; never add a hand-written register(new X()) line to an area's XFeatures.register(), which is only for that area's shared setup. Writing a feature covers the annotation.
  • Use core.util.Timer for cooldowns and debounces, not System.currentTimeMillis(). The wall clock is right only for a timestamp that is saved, compared with Hypixel's, shown as a date or time, or read across threads.
  • A chat line the mod rewrites keeps its click. On Hypixel the click is the interaction; TextUtils.keepActions and a unit test guard it.
  • Visual work follows the glass contract, docs/design/liquid-glass.md. The UI toolkit is the guided tour.

Your contribution's licence

Vantage is released under the MIT licence, with the copyright line Copyright (c) 2026 CherishEv. The repository has no contributor agreement and no separate terms for contributions, and this page does not add any. If the terms under which your change is merged matter to you, say so in the merge request before it is merged.

Whatever you send has to be yours to give: code you wrote, or code under a licence that allows it. That is the same reason rule 2 exists.

  • Forking: taking the code and making it yours, which is usually the better road.
  • Testing: every check behind "verified", and what CI runs.
  • Architecture: where things live before you change them.
  • Writing a feature: the annotation, the lifecycle and the build's checks.