2024-04-11 10:18:52 +02:00
|
|
|
|
|
|
|
## On-rail Minecart Movement
|
|
|
|
|
|
|
|
Minecart movement is handled in two distinct regimes: on a rail and off. The
|
|
|
|
off-rail movement is handled with minetest's builtin entity movement handling.
|
|
|
|
The on-rail movement is handled with a custom algorithm. This section details
|
|
|
|
the latter.
|
|
|
|
|
|
|
|
The data for on-rail minecart movement is stored entirely inside mod storage
|
2024-04-11 10:33:36 +02:00
|
|
|
and indexed by a hex-encoded 128-bit universally-unique identifier (uuid). Minecart
|
|
|
|
entities store this uuid and a sequence identifier. The code for handling this
|
|
|
|
storage is in [storage.lua](./storage.lua). This was done so that minecarts can
|
|
|
|
still move while no players are connected or when out of range of players. Inspiration
|
|
|
|
for this was the [Advanced Trains mod](http://advtrains.de/). This is a behavior difference
|
|
|
|
when compared to minecraft, as carts there will stop movement when out of range of
|
|
|
|
players.
|
2024-04-11 10:18:52 +02:00
|
|
|
|
|
|
|
Processing for minecart movement is as follows:
|
2024-04-11 10:33:36 +02:00
|
|
|
1. In a globalstep handler in [carts.lua](./carts.lua), determine which carts are
|
|
|
|
moving.
|
2024-04-11 10:18:52 +02:00
|
|
|
2. Call `do_movement` in [movement.lua](./movement.lua) to update
|
2024-04-11 10:33:36 +02:00
|
|
|
each cart's location and handle interactions with the environment.
|
2024-04-11 10:18:52 +02:00
|
|
|
1. Each movement is broken up into one or more steps that are completely
|
|
|
|
contained inside a block. This prevents carts from ever jumping from
|
|
|
|
one rail to another over a gap or thru solid blocks because of server
|
2024-04-11 10:33:36 +02:00
|
|
|
lag. Each step is processed with `do_movement_step`
|
2024-04-11 10:18:52 +02:00
|
|
|
2. Each step uses physically accurate, timestep-independent physics
|
2024-04-11 10:33:36 +02:00
|
|
|
to move the cart. Calculating the acceleration to apply to a cart
|
|
|
|
is broken out into its own function (`calculate_acceperation`).
|
2024-04-11 10:18:52 +02:00
|
|
|
3. As the cart enters and leaves blocks, handlers in nearby blocks are called
|
2024-04-11 10:33:36 +02:00
|
|
|
to allow the cart to efficiently interact with the environment. Handled by
|
|
|
|
the functions `handle_cart_enter` and `handle_cart_leave`
|
|
|
|
4. The cart checks for nearby carts and collides elastically with these. The
|
|
|
|
calculations for these collisions are in the function `handle_cart_collision`
|
|
|
|
5. If the cart enters a new block, determine the new direction the cart will
|
2024-04-11 11:17:06 +02:00
|
|
|
move with `mcl_minecarts:get_rail_direction` in [functions.lua](./functions.lua).
|
2024-04-11 10:33:36 +02:00
|
|
|
The rail nodes provide a hook `_mcl_minecarts.get_next_direction` that
|
|
|
|
provides this information based on the previous movement direction.
|
2024-04-11 10:18:52 +02:00
|
|
|
3. If an entity exists for a given cart, the entity will update its position
|
|
|
|
while loaded in.
|
|
|
|
|
|
|
|
Cart movement when on a rail occurs regarless of whether an entity for that
|
|
|
|
cart exists or is loaded into memory. As a consequence of this movement, it
|
|
|
|
is possible for carts with unloaded entities to enter range of a player.
|
|
|
|
To handle this, periodic checks are performed around players and carts that
|
|
|
|
are within range but don't have a cart have a new entity spawned.
|
|
|
|
|
|
|
|
Every time a cart has a new entity spawned, it increases a sequence number in
|
|
|
|
the cart data to allow removing old entities from the minetest engine. Any cart
|
|
|
|
entity that does not have the current sequence number for a minecart gets removed
|
|
|
|
once processing for that entity resumes.
|
2024-04-11 10:33:36 +02:00
|
|
|
|