# 1.12 End gateway finder

[Gateway Portal Search Tool and Updates (0x53ee71ebe11e)](https://www.youtube.com/watch?v=gZiHaUDi-Mk)

[Reference demo by 0x53ee71ebe11e](https://www.youtube.com/watch?v=MnofuX_1ibE)

The source code is based off of `0x53ee71ebe11e`'s original code, previously hosted at
https://end.of.pony.wtf/portal-finder.html but no longer available.

## Decompilation

Decompiled from wasm and minified js by AI in
`<Readable decompilation and verification preserving original behavior (ai)>`,
and (hopefully) preserving the original behavior.

This browser implementation only uses HTML, CSS, and JS, and no longer depends on
the original Emscripten modules, packed worker protocol, or WebGL renderer.

## Usage

This 1.12 end gateway map shows the locations of outer island end gateways (`end_gateway_return`),
and has a calculator for scheduling flying machines for manipulating them
(now superseded by chunk savestating).

```text
-24 72 SW
Gateway: -373 +10 1175
/tp @s -384 ~ 1152
```

This means that chunk -24 72, when generated+populated without any chunks in between being
generated/populated, will place an end gateway at x -373 z 1175, 10 blocks above the **highest opaque**
block in that column (slime block is transparent, column shouldn't be void). The end gateway is in
the **southwest** corner of the 16x16 offset population area (-24 72 is the northwest).

You will want to savestate chunk -24 72 as **ungenerated**, keep it loaded, and then build redstone
wiring to load the other 3 chunks in its population area, before having a **sticky piston**
**load -24 72 while pulling the end gateway location**.

The sticky piston will list the block positions its pulling, then load -24 72, which populates and
places the end gateway in the sticky piston's position list, which it then pulls and turns into a
unlinked gateway. (You can pull bedrock as well). If the northwest chunk can't be reached within
pull limit pick another location.

See [Myren's video](https://www.youtube.com/watch?v=-4UhrzA-F2g&t=706s) for a video guide.

The `show gateways requiring blocked chorus flowers` gives more candidates for gateways, you will
need to ensure the highest block in every chorus plant generation location is **not endstone** for
a gateway to be placed by the block.

More candidates can be found with RNG manipulation, but that's too much work for this.

### Gateway Calculations

Based off of `TheEndChunkGenerator.java`.
- `TheEndChunkGenerator` only advances random in `getChunk` (chunk generation) and `populateChunk`.
  This calculation assumes that a chunk is **generated and then immediately populated, with no
  other chunks generated or populated in-between** for consistency. (RNG manipulation is possible).
- By default, the map only checks chunks with `chorusFlowerCount == 0`, so chorus fruit placement RNG
  does not affect the calculation. There is an option to model blocking chorus attempts.
- The **seed-specific** yellow areas represent chunks *population areas* (offset +8 +8) with
  `islandNoise > 40.0F`, and they are the only areas where end gateways can be placed.
  - Original C used `>= 40.0F`, this is slightly wrong.

### Options
- `show only gateways that can generate on this seed`: disabling ignores the seed-specific
  `chunkDistanceSquared > 4096L && islandNoise > 40.0F` filter that gateways require to spawn.
- `show chunk-relative placement coordinates`: off by default. When off, show absolute block X/Z
  coordinates for gateway placement and blocked chorus attempts. Enabling it shows gateway coordinates
  and chorus placements relative to the chunk it is **placed in**.
- `show gateways that place in the populating chunk (NW)`: off by default. Enable it to show gateways
  that place within the populating chunk (NW), which needs to be savestated (no redstone can go there).
  Blocked chorus candidates are also hidden when any attempted flower is in that NW chunk.
  You cannot pull these.
- `show gateways requiring blocked chorus flowers`: includes candidates with a nonzero `chorusFlowerCount`
  when the attempted flower positions are blocked with non-endstone at the highest block. Only the
  flower X/Z placement advancements are used, and those attempted positions are shown in detailed labels.
- `show distance to closest gateway`: draws lines from center to closest gateways in Euclidean (L2 norm)
  and Manhattan (L1 norm) distances.

Click a chunk without dragging to inspect chorus growth. The analysis enumerates
blocking positions for each reachable vertical or horizontal growth check and
reports only setups whose next gateway roll is `0/700`, along with the exact
chorus blocks required. Set `show gateways that place in the populating chunk
(NW)` when you also want to inspect setups that require touching the northwest
chunk; those setups are hidden by default. When several blocks can stop the
same plant during the same growth phase, they are shown as numbered
alternative setups:
choose one numbered setup, rather than placing every listed block.
If multiple growth phases lead to the same gateway and RNG state, they are
shown under one gateway heading with separate phase subsections.
Each setup also lists every initial flower root and whether that flower is
blocked or allowed to grow. Later roots are listed per setup because blocking
an earlier flower changes the Java `Random` stream.
Growth coordinates use `rootY+N` because this source-only map does not
reconstruct the End heightmap; X/Z and RNG consumption are exact for the
modeled empty surrounding space.

The options menu also has an explicit `analyze visible chunks` action. It runs
the same analysis over every chunk currently on-screen and highlights chunks
with at least one blocking setup that produces a gateway. This is intentionally
very expensive, especially at the widest zoom levels. It uses a bounded pool of
Web Workers (up to eight, based on available logical CPUs). The `stop analysis`
button cancels outstanding simulations; afterward it becomes `clear analysis`,
which removes the retained results. Panning and zooming do not clear completed
or partial results. With seed filtering enabled, only chunks whose population
area passes the seed-specific gateway terrain check are highlighted.

### Commands

The UI supports the original console commands and the default flying-machine schedule behavior:

```text
seed <numerical-seed>
tp [block/chunk] [~]{x} [~]{z}
start <chunk-x|~> <chunk-z|~> <hashset-size>
target <chunk-x> <chunk-z> [gametick-offset ['details']]
timings [TRIGGER]...
boop
clear
```

`start` sets the flying-machine origin and hashmap size used by the map;
`target` then reports whether the configured route can reach a target portal
seed chunk. The hashmap size controls which priority zero chunks are shown and
how far the route can reach.

The timing grammar is:

```text
trigger <name> <linear-offset> [delay <duration> | protect <duration> |
  fm <linear-offset> <duration>]...
```

`target x z` prints the repeating 900-gametick good/bad windows. Supplying a
start tick prints the events at that offset; appending `details` adds protection
and flying-machine lifecycle lines, matching the original command adapter.

Mouse dragging pans the map. Scrollwheel zoom has 8 levels, with 128 through 1 pixels per chunk.

## Run it

```sh
make site
python3 -m http.server --directory dist 8000 # or any other static web server
```

Then open <http://localhost:8000/>. The worker and core must be served over
HTTP; opening `index.html` directly will not work because browsers restrict
worker loading from `file:` URLs.

The Nix flake provides Node.js for tests and Emscripten/WABT/Binaryen for the decompilation checks:

```sh
nix build
python3 -m http.server --directory result 8000

nix develop
make site
```

### Tests

```sh
make verify-observable
make emscripten
```

`make verify-observable` is the normal pre-commit check. It exercises the C
and JavaScript implementations, the worker protocol, command transcripts,
and renderer geometry before rebuilding `dist/`. See
`OBSERVABLE_BEHAVIOR_AUDIT.md` for the oracle provenance and known limits.

`make emscripten` is an independent native ABI check; it is not required to
run the browser site.

Generated Emscripten and wasm2c artifacts are intentionally not part of the
source tree. The site is rebuilt from the readable JavaScript sources above.

## Source layout

- `portal-gateway.js` — Java `Random`, 1.12 simplex/island noise, gateway
  placement, area scanning, and End island masks.
- `portal-chorus.js` — exact 1.12 `ChorusFlowerBlock.generate()` RNG model
  used by selected-chunk chorus blocking analysis.
- `portal-chorus-worker.js` — worker entry point for parallel visible-chunk
  chorus analysis.
- `portal-core.js` — terrain-view generation, worker's RGBA reachability overlay.
  Red overlay chunks are priority zero chunks.
- `portal-route.js` — exact high-level reconstruction of the native
  hash-aligned flying-machine traversal and 900-gametick availability bitmap.
- `portal-scheduler.js` — readable timing grammar and the recovered
  schedule/trace formatter for trigger, protection, and flying-machine events.
- `portal-worker.js` — structured worker API for gateway searches and complete
  terrain/reachability tiles.
- `portal-finder-ui.js` — editable Canvas 2D tiled renderer, pan/zoom controls,
  markers, and console commands.

- `native/end-terrain.c` and `.h` — decompiled C implementation of the Java gateway and terrain calculations.
- `native/EndGatewayReference.java` — relevant Java code for end gateway generation.
- `tests/test_end_terrain.c` — C fixtures recovered from the original WASM.
