Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/en/robust-toolbox/transform/lerping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Lerping + Corrections

## Lerping

With ss14 being tick-based we need to render entities in-between ticks. To do this we apply lerping for the following scenarios:
1. Our local entity we need to lerp from tick A -> tick B
2. For remote entities we lerp from tick A -> tick B. Due to the state buffer this will often be 1+ ticks behind. However if tick B does not exist and we receive tick C instead we use that as the target rather than jumping a tick.
3. With z-levels we need to be able to lerp cross-parent and also use z-position — essentially updating the lerp's source position to a new one.

If the correction is large or we otherwise want a snap (e.g. containers, teleports) we need to be able to cancel the lerp entirely.

Something else that makes it a pain is handling multiple transform updates inside one tick, most notably physics substepping, so we need to know what the transform was at the start and end of a tick is.

For the z-level related mechanics to it see z-levels.md

## Correction
If mispredicts happen then the above instantly snaps — this necessitates smoothing errors out.

## CVars

Ideally you don't need to touch these but the net.interp* values handle the interpolation distance and corrections.

## How it works

Transform itself purely keeps simulation state and nothing to do with rendering. All of the rendering values are handle via the client's TransformSystem.

Everything gets handled in 2 spots:
1. ClientGameStateManager handles dropped ticks — if tick B is missing we lerp from tick A -> tick C. This is done via interpolation lookahead.
2. TransformSystem.FrameUpdate handles the remaining data.

In TransformSystem we cache all snapped moves so we know when we need to ignore lerping, but if there are no snaps then we try and figure out if we need to:
- Snap due to interp distance being too far
- Re-parent the entity (grid-traversal and z-levels predominantly — TryCreateEndpoint)
- Handle corrections

Most of the complexity comes from handling prediction, specifically ignoring any rollback / replay transform states and only comparing about the start / end states of a tick.
36 changes: 36 additions & 0 deletions src/en/robust-toolbox/z-levels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Z-levels

## What are they

z-levels are a way to sandwich maps together done via ZMapNetwork. This entails:
- ZLevelMapNetworkComponent, meta component stored in nullspace.
- ZLevelMapComponent, added to component maps.
- ZLevelGridComponent, used to keep grids aligned via soft joints. These are done manually as physics does not currently support cross-map joints.
- ZLevelPositionComponent, used on entities with z-level heights — this is what also hooks into transform-lerping (see lerping.md)

These systems are also used:
- ClientZLevelSystem, this handles gluing lerping with TransformSystem.
- ZLevelGridSyncSystem, this is what runs the soft-joints for ZLevelGridComponent.
- ZLevelSystem handles the map-network + the physics itself.
- ZLevelPhysicsSystem does the meat of the work around entities traversing z-levels.

## CVars

These are under zlevel.* predominantly around controlling the fake "physics" side of it.

## Visuals

If you wish to affect the visuals then use ZLevelVisualsEvent — used for the projection offset if you wish for the z-levels to not be perfectly stacked, and a relevant overlay.
Overlays get the zlevel offset passed in via `OverlayDrawArgs` and know where they are in the stack, relatively speaking.

For world overlays you only want applied once, e.g. damage borders, night-vision, use PostZLevel as the space to avoid them accidentally being applied on every z-level render.

## Physics

This is handled in two main ways:
1. ZLevelGridSync runs soft physics between linked grids, preferring the smaller grid to move more towards the larger grid. Generally you should only need to set the CVars for this under zlevel.*
2. ZLevelPhysics handles the normal entity z-level interactions.

The physics handles 2 parts:
1. Integrating z-level physics velocities in the tick with substepping so high-velocities don't clip.
2. Handling "supports" / "highground" so entities can't drop a z-level where they wouldn't be able to intersect normally.
Loading