# Neoriris Portal Door Mod Overview

## Summary

Neoriris Portal Door is a Minecraft Forge 1.12.2 companion mod for the Neoriris upgrade lab. It adds redstone-sensitive wall-mounted portal frame controllers that create and remove real PortalGun portal pairs, allowing a build to use PortalGun traversal without requiring players to manually fire portal shots.

- Mod ID: `neoririsportaldoor`
- Version: `0.1.5`
- Minecraft: `1.12.2`
- Forge: `14.23.5.2860`
- Required dependencies: `portalgun`, `ichunutil`
- Main custom objects: `portal_door_a`, `portal_door_b`, `entangled_portal_door_pair`

## Custom Blocks And Items

### Neoriris Portal Door A

- Registry ID: `neoririsportaldoor:portal_door_a`
- Display name: `Neoriris Portal Door A`
- Creative tab: Redstone
- Visual model: thin iron-edged wall panel with a lapis-blue face
- Portal role: endpoint A, using PortalGun's A/blue-side portal state

### Neoriris Portal Door B

- Registry ID: `neoririsportaldoor:portal_door_b`
- Display name: `Neoriris Portal Door B`
- Creative tab: Redstone
- Visual model: thin iron-edged wall panel with a redstone-red face
- Portal role: endpoint B, using PortalGun's B/red-side portal state

### Neoriris Entangled Door Pair

- Registry ID: `neoririsportaldoor:entangled_portal_door_pair`
- Display name: `Neoriris Entangled Door Pair`
- Max stack size: `1`
- Creative tab: Redstone
- Purpose: survival-friendly kit that unpacks into one Door A frame controller and one Door B frame controller sharing the same hidden entanglement UUID.

Right-clicking the kit server-side initializes a UUID if needed, creates one A controller item and one B controller item, copies the same `PairId` and `PairLabel` into both, then consumes the kit. If inventory space is limited, overflow controller items are dropped at the player.

Commands still work for legacy/unbound controller items:

```mcfunction
/give @p neoririsportaldoor:portal_door_a
/give @p neoririsportaldoor:portal_door_b
/give @p neoririsportaldoor:entangled_portal_door_pair
```

## PairId Vs PairLabel

`PairId` is the real bond for entangled doors. `PairLabel` is display metadata for signs, route names, anvil names, and status output.

Item and tile NBT use a nested compound:

```text
NeoririsPortalDoor: {
  PairId: "uuid-string",
  PairLabel: "Clock Tower Route",
  PairRole: "A" or "B",
  Schema: 1
}
```

Entangled pair kits omit `PairRole` because they contain both roles. If a kit is renamed in an anvil before unpacking, both output doors receive that visible label and the same hidden `PairId`.

## Pairing Model

The current pairing order is:

- If both candidate doors have non-empty `PairId`, they only pair when the IDs are exactly equal and the roles are opposite A/B.
- If both doors have no `PairId`, the legacy label-based fallback is used.
- If exactly one endpoint has a `PairId`, it does not pair by label. Status output reports the entangled/legacy mismatch.
- If duplicate same-role endpoints with the same `PairId` are loaded, the mod does not crash. It chooses the nearest mutually valid opposite endpoint and adds a warning status.

This preserves old worlds and schematics while preventing same-label multiplayer pairs from cross-linking.

Example status for an entangled door:

```text
Portal Door A label='Clock Tower Route', bound=true, pairId=4a4c7d47..., facing=NORTH, paired with BlockPos{x=..., y=..., z=...}, active=true
```

Example status for a legacy door:

```text
Portal Door A label='Clock Tower Route', bound=false, legacy label pairing enabled, active=false
```

## Multiplayer Safety

Pair IDs are generated server-side with `UUID.randomUUID()` when a kit is crafted/updated/used on the server. Pair identity does not depend on player names, coordinates, timestamps, item names, labels, or recipe grid contents.

This means multiple players can craft or rename kits to the same visible route label without cross-connecting:

```text
Player 1: "Clock Tower Route" -> UUID A
Player 2: "Clock Tower Route" -> UUID B
Player 3: unnamed/default -> UUID C
```

Each A/B pair follows its own hidden UUID.

## Placement Rules

Portal doors are wall-mounted portal frame controller panels, not full cubes and not the traversable portal surface themselves.

- A controller can only be placed against a horizontally solid support face.
- The controller should be placed on the empty wall block immediately above the intended 1x2 portal surface.
- In player terms: choose the two vertical wall blocks that should become the PortalGun portal, then place Door A or Door B on the third wall block directly above them.
- The controller faces outward from the support block it is mounted on.
- If the supporting block is removed, the door drops as an item and removes any portal pair it managed.
- Entangled drops preserve `PairId`, `PairLabel`, `PairRole`, and `Schema`.
- The collision/selection shape is a thin panel inset inside the block space.
- The block material is iron, with metal sound, hardness `1.5`, and resistance `8.0`.

Portal placement is tied to the controller position:

- The lower portal cell is two blocks below the controller.
- The upper portal cell is one block below the controller.
- PortalGun must accept those exact two cells as a valid 1x2 portal placement.
- If PortalGun rejects the exact placement, the pair does not open and the door reports a failure status.

## Moving Placed Doors

Placed Neoriris portal frame controllers can be safely removed with a Portal Gun:

```text
Sneak-right-click a placed Door A or Door B while holding a Portal Gun.
```

This pops the wall controller off, closes any managed portal pair, and returns the controller item while preserving:

- `PairId`
- `PairLabel`
- `PairRole`
- `Schema`

This is the preferred survival-safe way to move an entangled endpoint without breaking its hidden bond.

## Redstone Interaction

Either endpoint can power the pair. The mod checks the controller, support block, adjacent blocks, the expected lower portal cell, and nearby trigger positions in front/below the portal target.

When power is detected:

- Door A acts as the pair manager.
- Existing managed portals for that pair are removed first.
- A new PortalGun A endpoint is spawned on Door A's two wall cells below the controller.
- A new PortalGun B endpoint is spawned on Door B's two wall cells below the controller.
- PortalGun open sounds play at both endpoints.
- The pair remains active while either endpoint stays powered.

When power is lost:

- The mod waits `20` ticks, roughly one second.
- This gives the player a short walk-through grace period after stepping off a plate.
- After the grace period, both managed PortalGun endpoints are removed.

## PortalGun Integration

The mod does not implement its own teleportation system. It delegates traversal to PortalGun.

- It requires `PortalGun.blockPortal` and `PortalGun.eventHandlerServer`.
- It uses `PortalGunHelper.canPlacePortal(...)` to verify exact placement.
- It uses `PortalGunHelper.spawnPortal(...)` to create endpoints.
- It uses PortalGun world save data to remove managed endpoints.
- It uses the synthetic owner UUID string `NeoririsPortalDoor`.
- Managed channels use the prefix `neoriris-door:` and remain dimension/position scoped.

Because the endpoints are real PortalGun portals, traversal behavior, rendering, collision, and portal colors come from the PortalGun mod.

## Lifecycle And Persistence

Each door tile entity stores:

- `pairId`
- `pairLabel`
- `role`
- Active PortalGun channel
- Active state
- Power-loss tick for grace-period closing
- Last user-facing status message

Old tile entities with no `PairId` still load as legacy/unbound doors. Managed portals are cleaned up when a door breaks, support disappears, chunks unload, tile entities invalidate, labels change, or redstone power is lost past the grace period.

## Survival Crafting Recipes

The current build includes Forge JSON recipes under `assets/neoririsportaldoor/recipes/`.

### Door A

```text
I O I
I L I
I P I
```

- `I` = `minecraft:iron_ingot`
- `O` = `minecraft:obsidian`
- `L` = lapis lazuli, `minecraft:dye` data `4`
- `P` = `portalgun:item_dust_ender_pearl`
- Output = `neoririsportaldoor:portal_door_a`

### Door B

```text
I O I
I R I
I P I
```

- `I` = `minecraft:iron_ingot`
- `O` = `minecraft:obsidian`
- `R` = `minecraft:redstone`
- `P` = `portalgun:item_dust_ender_pearl`
- Output = `neoririsportaldoor:portal_door_b`

### Entangled Door Pair

```text
I O I
L M R
I O I
```

- `I` = `minecraft:iron_ingot`
- `O` = `minecraft:obsidian`
- `L` = lapis lazuli, `minecraft:dye` data `4`
- `M` = `portalgun:item_miniature_black_hole`
- `R` = `minecraft:redstone`
- Output = `neoririsportaldoor:entangled_portal_door_pair`

The PortalGun ingredient registry names were verified from the installed `PortalGun-1.12.2-7.1.0.jar` recipes.

## Legacy Label Fallback

Legacy fallback remains enabled by default. Plain `/give` controller items and old placed controllers with no `PairId` still pair by matching label and opposite A/B role.

Entangled and legacy endpoints intentionally do not mix, even when labels match. This protects survival-crafted pairs from accidentally binding to old schematic doors with the same visible text.

## Route Tuner

`route_tuner` is not implemented in `0.1.5`. If added later, it should only copy/apply `PairLabel` and item display labels. It must never copy, overwrite, or generate `PairId`.

## Client-Side Presentation

The mod customizes the client main menu for the Neoriris lab pack:

- Replaces the vanilla panorama resources with Neoriris screenshots.
- Draws a `NEORIRIS` title overlay.
- Shows `Clock Tower Route`.
- Shows the multiplayer tunnel hint:

```text
Multiplayer -> Neoriris Cloudflare Tunnel
Forge 1.12.2 | PortalGun | cloudflared://minecraft.system42.one
```

This presentation layer is client-only and does not affect server gameplay.

## Typical Entangled Setup

1. Craft `Neoriris Entangled Door Pair`.
2. Optionally rename the kit in an anvil, for example `Clock Tower Route`.
3. Right-click the kit to unpack it into linked Door A and Door B controller items.
4. For each endpoint, choose the two vertical wall blocks that should act as the portal surface.
5. Place Door A and Door B on the third wall block directly above those two portal-surface blocks.
6. Wire a pressure plate, lever, button, or redstone circuit so either endpoint receives power.
7. The mod opens a real PortalGun portal pair between the two UUID-bound endpoints.
8. When power is removed, the pair closes after the short grace period.

## Known Constraints

- Both endpoints must be loaded; an unloaded counterpart cannot be selected.
- Pairing only happens between opposite types, so A pairs with B and B pairs with A.
- PortalGun must accept the exact two portal-surface wall cells below each controller.
- Portal behavior remains dimension-specific.
- The optional Route Tuner is a TODO, not part of `0.1.5`.
