Table of Contents
Current Systems
This document describes the current LanteaCraft rewrite state as implemented in the source tree. It is intentionally descriptive, not aspirational: sections call out what is working, what is prototype-quality, and what still needs testing.
Stargate Multiblock Lifecycle
Implemented
The Stargate frame is implemented as a 7×7 block multiblock centered on a stargate_base at the bottom middle. The base stores horizontal facing; the frame is resolved relative to base.FACING.getClockWise().
The accepted pattern is defined in StargateMultiblock.buildPattern():
x = -3..3,y = 0..6- frame positions are every block on the bottom row, top row, left side, and right side
- bottom center
x=0,y=0must bestargate_base - chevrons are at:
- top:
(-2,6),(0,6),(2,6) - upper sides:
(-3,4),(3,4) - lower sides:
(-3,1),(3,1) - bottom:
(-2,0),(2,0)
- all other frame positions must be
stargate_ring
Placement flow:
- Placing a
stargate_basecallsStargateMultiblock.tryAssembleAtBase. - Placing a
stargate_ringorstargate_chevroncallsStargateMultiblock.tryAssembleFrom, which searches nearby candidate bases. - Successful assembly sets the
assembled=trueblockstate on all frame blocks. - Successful server-side assembly registers a
StargateEntryinStargateNetworkSavedData.
Interaction flow:
- Right-clicking an assembled base/component with no item sends the address chat message.
- The chat address is clickable and copies the gate address to clipboard.
- Right-clicking the assembled bottom row with a valid solid block applies bottom-row camouflage via the base block entity.
Disassembly flow:
- Breaking the assembled base calls
disassembleAtBase. - Breaking an assembled component calls
disassembleFrom, which searches nearby bases. - Disassembly sets
assembled=falseon all existing frame blocks found for the base. - Server-side disassembly removes the gate from saved data and attempts to release chunk tickets for active outgoing/incoming connections.
Prototype Quality
- Assembly/debug logging is very verbose and currently logs every pattern match/mismatch.
- Disassembly depends on finding the existing frame from the base. Partial destruction cases need more testing.
- The assembled visual is currently a BER-driven ring plus simple assembled block models, not final block replacement logic.
- Bottom camouflage is stored as a single block type on the base BE and rendered across all seven bottom-row positions.
Needs Testing
- Breaking each possible frame block while the gate is active.
- Reassembling after partial break/replace.
- Base facing for all four horizontal directions.
- Applying camouflage from each bottom-row block.
- Whether existing worlds with old saved addresses behave acceptably after the new address scheme.
Address Generation And Saved Data
Implemented
Addresses are generated by StargateAddress.
Current format:
6 generated gate glyphs + 1 dimension glyph
The glyph alphabet is the legacy 38-character set:
ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-+
The first six glyphs are generated from the gate chunk coordinates. The dimension is no longer mixed into the six generated glyphs. Instead, the seventh glyph represents the dimension.
Reserved/preferred dimension glyphs:
A:minecraft:overworldN:minecraft:the_netherE:minecraft:the_end
Other dimensions are assigned the first available legacy glyph. These assignments are persisted in StargateNetworkSavedData.dimensionGlyphs.
Saved data is global and stored from the overworld data storage under:
lanteacraft_stargate_network
Persisted data includes:
- registered gates:
- address
- dimension resource location
- base position
- facing
- dimension glyph assignments
- active one-way connections:
- source address
- destination address
- connection start game time
Lookup maps maintained in memory:
gatesByAddressaddressesByLocationactiveConnectionsconnectionStartTimesdimensionGlyphs
Collision handling:
- If the generated address already belongs to another gate,
uniqueAddresssalts the six generated glyphs. - The final dimension glyph is preserved during salting.
Prototype Quality
- Dimension glyph assignment supports 38 dimensions. If all glyphs are exhausted, the code logs a warning and reuses
+. - There is no user-facing dimension glyph registry or display yet.
- Existing saved gates from the previous 7-symbol hash format are loaded as-is; there is no migration pass.
- The first six glyphs are chunk-derived, so multiple gates in the same chunk rely on collision salting.
Needs Testing
- New gate generation in Overworld, Nether, End, and at least one modded dimension.
- Stability of dimension glyphs after save/reload.
- Collision behavior for multiple gates in one chunk.
- Behavior when old saved gates exist from before the dimension-glyph format.
DHD Dialing Flow
Implemented
The DHD block opens a client-side DhdScreen on right-click.
The GUI:
- renders the legacy DHD texture
- accepts typed glyphs from the legacy 38-character set
- supports paste from clipboard
- supports backspace/delete
- caps input to
StargateAddress.ADDRESS_LENGTHcurrently 7 - plays the DHD button sound locally when buttons/backspace/dial are pressed
- sends
DialStargatePayloadto the server when the center button/Enter is pressed
Server payload handling:
- Validates that the DHD block still exists.
- Finds the nearest assembled Stargate within radius 8.
- Blank address means disconnect the local outgoing connection.
- Nonblank address must be exactly 7 valid glyphs.
- Looks up the destination by address.
- Rejects dialing the same local gate.
- Forces source/destination chunks.
- Stores a one-way active connection.
- Starts dialing animation/sound state on both source and destination base block entities.
Prototype Quality
- The DHD is not a menu/container; it is a custom screen opened from client hooks.
- The DHD searches for the nearest assembled gate, not an explicitly linked gate.
- There is no power, crystal, ownership, iris, or address book system.
- Blank address is overloaded as disconnect.
- Receiving gates cannot close incoming connections; this is intentional current behavior.
Needs Testing
- DHD behavior when multiple gates are within radius.
- Paste behavior with lowercase, invalid chars, and overlong strings.
- Cross-dimensional dialing after dimension glyph overhaul.
- DHD disconnect when source/destination chunks are loaded or unloaded.
Connection Model
Implemented
Connections are one-way and stored as:
sourceAddress -> destinationAddress
The source gate is the dialing/outgoing gate. The destination gate is incoming.
Connection state lives in two places:
StargateNetworkSavedData.activeConnectionsfor authoritative server routing.StargateBaseBlockEntity.connectedAddressfor rendering/sound state.
The source and destination BEs both receive:
startDialing(otherAddress)setConnectedAddress(otherAddress)
Disconnect behavior:
- Only the source/outgoing gate can disconnect via DHD.
- Disconnect removes the active connection and clears both BEs if their dimensions are loaded.
- Disassembly removes connections involving the removed gate and releases chunk tickets.
Timeout behavior:
StargateTeleportHandlerenforces a one-minute timeout (20 * 60ticks).- Timeout is checked on the source gate's dimension tick.
- On timeout, chunk tickets are released, saved connection is removed, and both BEs are cleared when accessible.
Prototype Quality
- There is no connection conflict protection beyond overwriting
activeConnections.put(source, destination). - There is no check that the destination is already busy.
- No persistence repair pass validates that active connections still point to valid assembled gates.
- BE visual state and saved network state can potentially drift if a target dimension is unavailable during cleanup.
Needs Testing
- Dialing from a gate that already has an outgoing connection.
- Dialing a gate that is already receiving.
- Save/reload while a connection is active.
- Timeout across dimensions.
- Disassembly during active dialing/open wormhole.
Teleport Behavior
Implemented
StargateTeleportHandler subscribes to server level post-tick events.
For each active source address:
- it only processes the source in the level matching the source gate dimension
- it checks wormhole timeout
- it scans players in that level against the source gate interior
For each active destination address:
- it only processes incoming behavior in the destination gate dimension
- it scans players in that level against the destination gate interior
Interior detection:
- local X is projected onto the gate right vector
- local depth is projected onto the gate facing vector
- valid area is approximately:
- width:
abs(localX) ⇐ 2.35 - height:
0.1..5.9 - depth:
abs(localDepth) ⇐ 0.7
Outgoing source behavior:
- entering the front side teleports to the destination gate's front side
- local X and local Y are preserved
- player yaw/pitch are preserved
- teleport cooldown is applied
Back side of outgoing gate:
- entering from the back does not traverse the wormhole
- player is moved to the front side of the same source gate
- player is pushed outward
Incoming destination behavior:
- entering an incoming wormhole rejects the player
- player is moved to the front side of the destination gate
- player is pushed outward at a speed derived from entry velocity, with a minimum rejection speed
Cross-dimensional safety:
- player iteration uses
List.copyOf(level.players())so cross-dimension teleport does not mutate the list being iterated.
Prototype Quality
- Teleport volume is a simple rectangular slab inside the gate, not a true circular portal test.
- Orientation is mostly “preserve player yaw/pitch”, not “walk out facing relative to entry direction”.
- Entity support is player-only.
- No mount, projectile, item, mob, or vehicle traversal.
- Cooldowns are held in an in-memory map and are not persisted.
Needs Testing
- Nether to Overworld and Overworld to Nether travel after the snapshot iteration fix.
- Walking through at angles and high speed.
- Back-side entry on source gates.
- Incoming-side rejection at different velocities.
- Multiple players traversing the same gate in the same tick.
Chunk Loading Behavior
Implemented
StargateChunkLoading registers a NeoForge TicketController named:
lanteacraft:stargate
When a connection is opened:
- source chunk is force-loaded in the source level
- destination chunk is force-loaded in the destination level if that level exists
- tickets are ticking tickets
- ticket owner is the source base position
When a connection disconnects, times out, or disassembles:
- the same source/destination chunks are force-unloaded using the same owner where possible
Prototype Quality
- Only the base chunk is loaded, not nearby DHD/player arrival chunks.
- Destination chunk loading depends on
server.getLevel(destination.dimension())returning a loaded level. - Ticket ownership always uses source base position, including destination-level tickets.
- There is no startup repair/reassertion for persisted active connections.
Needs Testing
- Whether destination chunks remain ticking for the entire active wormhole.
- Disconnect and timeout release behavior across dimensions.
- World reload with an active connection.
- Breaking source or destination gate while chunk tickets are active.
Known Risks And TODOs
Current Risks
- Existing saved gate addresses may not match the new 6+1 address scheme.
- Active connection state can outlive visual BE state if a dimension or chunk is unavailable during cleanup.
- Destination busy/source busy rules are not implemented.
- The DHD nearest-gate search may pick the wrong gate in dense builds.
- The debug logging volume is high enough to be noisy during normal construction.
- Renderer and gameplay state are tightly coupled to the base block entity.
- Only players teleport.
TODO Candidates
- Add address/data migration for old saved addresses or document world reset requirements during development.
- Add connection validation and busy checks.
- Add explicit DHD-to-gate linking.
- Add non-player entity traversal when safe.
- Add a proper circular portal volume test.
- Add config values for wormhole timeout, DHD search radius, and debug logging.
- Add a command/debug screen for listing registered gates and dimension glyphs.
- Add tests/manual QA checklist for cross-dimensional dialing and chunk ticket lifecycle.
