Files
wireless-docs/content/core.typ
2026-06-20 20:51:44 -04:00

134 lines
4.7 KiB
Typst

#import "/lib.typ": callout, example, note, solution, tip, todo
= Core Mechanics <core>
== Entity IDs
Entities are the dynamic movable objects in the game. Minecraft tracks every entity with a unique ID
number. Whenever an entity is added to the game world, a global counter is incremented and the new
entity is assigned the current value.
A large number of game objects are tracked in this way, and so creating any one of them will
increment that global counter. To reiterate, *this is a global counter, shared for all entities in
the game*.
== Stationary Item Optimization
Typically, item entities fall to the floor and sit stationary soon after being created. Processing
movement for these stationary entities would be wasteful, so an optimization was added in 1.14: if
an item is sitting stationary on a block, then only process movement every 4th tick.
However, it would also be wasteful if every 4th tick processed _every_ item, so instead the items
are divided into four groups. Each tick stationary items from only one of the four groups check for
movement.
#callout(kind: "tip", label: "Key Point:")[
Stationary items can only begin to fall when their $"age" + "id"$ is a multiple of $4$.
]
Here is the relevant code path for the optimization:
```java
public class ItemEntity extends Entity {
public void tick() {
...
if (this.onGround() && !(this.getDeltaMovement().horizontalDistanceSqr() > (double)1.0E-5F) && (this.tickCount + this.getId()) % 4 != 0) {
...
} else {
this.move(MoverType.SELF, this.getDeltaMovement());
...
}
...
}
}
public class Entity {
public void move(final MoverType moverType, Vec3 delta) {
...
this.setOnGroundWithMovement(this.verticalCollisionBelow, this.horizontalCollision, movement);
...
}
public void setOnGroundWithMovement(final boolean onGround, final boolean horizontalCollision, final Vec3 movement) {
this.onGround = onGround;
...
}
}
```
#note[ `onGround` is only ever updated via `move`, and this branch is the *only* place that
`ItemEntity.move` is called. ]
== Observable Drop Delay
The effect is that if the item is on a block and has negligible horizontal momentum, it *cannot
fall* until the condition is satisfied, even if it's no longer on the ground. It can only fall early
if it gains horizontal momentum or is pushed.
This means if we know the remainder of $"id" slash 4$, we can predict which ages allow it to fall.
And the inverse: if we know which age allowed an item to fall, we can deduce the remainder of
$"id" / 4$.
#table(
columns: (auto, auto),
$"age"$, $"id"$,
[0], [0],
[1], [3],
[2], [2],
[3], [1],
)
This means if we know the remainder of $"age" / 4$, we can
#todo[Falling item animation][Spawn a few items, note their ID and age. Let them settle on a block, then
remove that supporting block. There will be a few ticks where the item hovers in place before it
falls.]
#example[
Consider this timeline. We spawn a few items, give them time to settle on the ground, then remove
their support. We observe when item $O$ begins to fall, and infer when we should expect the other
items to fall.
- `t+0`, spawn item $O$
- `t+1`, spawn item $A$
- `t+4`, spawn item $B$
- `t+4`, spawn item $C$
- `t+20`, remove support
- `t+22`, item $O$ begins to fall
Assuming no other entities spawn in this time period; these are the only things which increment
the counter.
At what ticks should we expect items $A$, $B$, and $C$ to begin to fall?
#solution[
Item $O$ falls when its age is $22 = 2 (mod 4)$, so its id must be $-2 (mod 4)$
Item $A$ spawns next, so its id must be $-1 (mod 4)$.
It can only fall when its age is $1 (mod 4)$.
It checks on ticks `t+2`, `t+6`, `t+10`, `t+14`, `t+18`, but is supported for all these.
On tick `t+22`, it will no longer be supported and will begin to fall.
Item $B$ spawns next, so its id must be $0 (mod 4)$.
It can only fall when its age is $0 (mod 4)$.
These are ticks `t+4`, `t+8`, `t+12`, `t+16`, `t+20`. So it falls immediately when the support
is removed.
Item $C$ spawns next, so its id must be $1 (mod 4)$.
It can only fall when its age is $-1 = 3 (mod 4)$.
These are ticks `t+7`, `t+11`, `t+15`, `t+19`, `t+23`.
- `t+20` remove support, item $B$ falls
- `t+22` items $O$ and $A$ fall
- `t+23` item $C$ falls
]
]
For simplicity, suppose we spawn all our items on the same tick. Then `this.tickCount` will be the
same for all of them, and we only need to consider the ID.
The result of this is that if you spawn several item entities, allow them to settle on a block, then
remove that block