Skip to content
This repository was archived by the owner on Aug 31, 2026. It is now read-only.

Knowledge belongs to a place: what this world knows is what a pad here can aim at - #28

Merged
StannisMod merged 7 commits into
1.12from
feature/tier-1-2-knowledge-interop
Aug 20, 2026
Merged

Knowledge belongs to a place: what this world knows is what a pad here can aim at#28
StannisMod merged 7 commits into
1.12from
feature/tier-1-2-knowledge-interop

Conversation

@StannisMod

@StannisMod StannisMod commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Knowing where a place is stops being a property of the game and becomes a property of the ground you are standing on. Until now a planet was either known to everybody or to nobody: a beacon planted anywhere announced it to every launch pad in the world, and a telescope survey - the one thing that actually finds places - wrote into a crystal that a tier-1 rocket could not read at all. Now each world carries what it has learned, the pack's authored list is the floor under all of them, and the two discovery systems finally touch at one deliberate point.

Two things to do, and nothing in the code will do either for you:

  1. First read this if planetsMustBeDiscovered is off in your pack: there is nothing here for you. Everything below is what happens when destinations must be discovered. With the flag off every world stays selectable from every pad exactly as it is today, no gate is added anywhere, and condition 2 does not apply.
  2. Re-plant beacons that were planted before this build - and know what re-planting now gets you. A beacon used to write into the global known-set and re-announce itself there on every load; it now teaches the bodies of its own system, and that knowledge lives in their own saved sets, which a world made before this build does not have. Re-planting therefore restores the place to its NEIGHBOURS, not to your home pad: to make it selectable at home, carry its address home on a memory crystal and deposit it at an observatory there.

Flying to a moon

A moon can be landed on, and a descent aimed at one no longer puts you on its planet. A moon is generated inside its parent's cell so that a planet and its moons travel as one destination - which meant an address named a family while the code that mints worlds treated it as naming an object. The first body of a cell to be approached got the world; every later approach, moon or planet, was answered with that same world, silently.

This touches procedurally generated moons only. A <moon> written into planetDefs is a body with its own identity and has always been landed on correctly. An existing world needs nothing done to it: a planet keeps the world it was already given, and the moons that could not be reached become reachable.

Finding somewhere, and being able to fly there

A survey teaches the world it was made from. Point an observatory at a patch of sky, and what it makes out is written into the crystal AND into the knowledge of the body the machine stands on - so a launch pad on that world can afterwards be aimed at what the telescope found. Where you build the instrument now matters: the world under it learns, its neighbour does not.

Only what the instrument RESOLVED can teach anything. A system that merely registered as a point of light, one that dust obscured, and one the operator set to record positions only all leave the ground exactly as ignorant as it was. How good the instrument is, and what the operator asked it for, therefore bound where a tier-1 rocket may go - not just how detailed a crystal is.

A crystal can be put down. The observatory has a Deposit control: it reads the addresses in the machine into what this world knows, so knowledge somebody carried here becomes knowledge a pad here can use. It costs no power and no data - the finding has already been paid for; this is only writing it down. The machine reports how many of how many addresses landed rather than reporting silent success.

An address only reaches tier-1 once the place is a real world. A procedurally generated body has no world until a tier-2 ship actually descends to it, and an address with no world behind it has nothing for a rocket to fly to, so a deposit skips it. Survey it again after somebody has landed there and the address carries the world it now has. That is the shape of the loop: tier-2 goes first and makes the place real, tier-1 follows.

The crossing is one-way, on purpose. A crystal deposits into a world's set. A world's set never feeds a crystal, a navigation console, or a jump target. The two discovery systems stay separate; this is the single sanctioned bridge between them.

What a beacon means now

A beacon is a local announcement rather than a galactic one. Planting one teaches the bodies of its own system - moons included - and nothing outside it. What it spreads is knowledge among neighbours, which is what a beacon is for; carrying a place's address further is the crystal's job.

On a server

Knowledge is communal per world, not per player. One person building an observatory opens those destinations for everyone who launches from that world - there is no per-player research state to track, and none to lose when somebody leaves.

A discovery is broadcast as that world's properties, the way a beacon always has been. No new packet is introduced. It is a player-driven event - a survey step, a beacon, a deposit - and priced for that frequency; nothing here discovers on a tick.

Fixes

  • SILENT - a procedural moon could never be realized: approaching one returned its planet's dimension, and the descent landed the ship on the planet with no error anywhere.

Internals worth knowing

No addon is known to build against these, so nothing here asks anyone to migrate.

  • DimensionProperties gains locallyKnownPlanets with discoverPlanet / isPlanetKnownHere / getLocallyKnownPlanets, persisted as an int array under locallyKnownPlanets and cleared before a read.
  • EntityRocket.isPlanetKnown asks the world it is standing in after the global set, instead of the global set alone.
  • UniverseRegistry.realizedDimAt and realizeBody take a body's variant; realizableBodiesAt and variantOf are new, and PlanetRealizer.realize takes the SystemBody that was approached rather than its address.
  • TelescopeScan.characterise / resolveLook / resolveBatch accept an optional IntConsumer that reports every body a look actually named.
  • Three lang keys for the deposit control, in both locales.

- DimensionProperties gains locallyKnownPlanets, taught by discoverPlanet
- persist it only when non-empty; loading replaces rather than merges
- a rocket asks the world it stands in, with the global set as the floor
- pin the contract: one body's finds never reach its neighbour
- a moon is built in its parent's cell, so a cell names a family
- address a body by its variant, the rank the derivation already uses
- realize() takes the SystemBody; the probe verb states which one it means
- pin it: a moon gets its own world and never inherits the planet's
- report the bodies a look actually named, for a caller that can act
- the observatory teaches its own dimension and syncs it like a beacon
- only a resolved, unobscured, full-detail look may teach anything
- teach every body of the beacon's system, moons included
- stop re-announcing to the global set on load; the local sets hold it
- return who learned, so the caller owns the syncing
- one-way crossing: a crystal fills a body's set, never the reverse
- skip an address with no world and report landed of total
- no new packet: the deposit syncs the way a beacon always has
- probe the production gate through a real rocket in the standing world
- probe the Deposit path and report which worlds landed, not just how many
- mint the target for the negative case so nothing else can satisfy it
- a client e2e presses Deposit and asks the server what it changed
- the crystal names a minted world, so a survey cannot have taught it
- read a crystal without depositing it, or the probe performs the act
- with research off a world nobody knows is still selectable
@StannisMod StannisMod added the feature New gameplay capability label Aug 20, 2026
@StannisMod
StannisMod marked this pull request as ready for review August 20, 2026 11:47
@StannisMod
StannisMod merged commit 6acdadd into 1.12 Aug 20, 2026
@StannisMod
StannisMod deleted the feature/tier-1-2-knowledge-interop branch August 20, 2026 11:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9bcb9e58b0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +876 to +878
if (candidate.kind() == body.kind()
&& candidate.orbitalDistance() == body.orbitalDistance()
&& candidate.name().sameCell(body.name())) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Distinguish sibling moons when resolving variants

When a generated planet has multiple moons, every sibling has the same cell, MOON kind, and parent-relative orbitalDistance(), so this predicate maps all of them to the first moon's variant. Approaching a later moon will therefore realize the first moon or, once that moon is realized, descend into its dimension instead of the body the ship reached; include the moon's distinct offset/orbital law in the identity.

Useful? React with 👍 / 👎.

Comment on lines +117 to 120
// A moon whose parent is not in its own cell cannot be built: the family is what gives it its
// star, its orbit and its sky, and by construction the parent is always here.
if (parentBody == null && target.kind() == SystemBodyKind.MOON) {
return Constants.INVALID_PLANET;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require a realized parent before materializing a moon

When a ship approaches an unvisited moon before its rocky parent has been realized, parentBody is non-null so this check permits realization even though its dimension is still invalid. materialize() consequently skips setParentPlanet, registers the moon as a standalone planet, and never repairs that relationship when the parent is later realized; either defer the moon until its parent has a dimension or explicitly preserve and establish the parent relationship.

Useful? React with 👍 / 👎.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

feature New gameplay capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant