Two-Tier Firework Rocket Propulsion & Vector Convergence — MC 26.2
This page details the mathematical propulsion algorithms, state transitions, and vector difference convergence powering firework rocket boosting in Max Elytra Fly Speed (MC 26.2).
📋 Subsystem Infobox
| Parameter | Technical Details |
|---|---|
| Subsystem Name | Two-Tier Firework Rocket Propulsion & Vector Convergence |
| Java Implementation | net.instantgratification.maxelytraflyspeed.util.RocketBoostHelper |
| Bytecode Mixin | net.instantgratification.maxelytraflyspeed.mixin.FireworkRocketEntityMixin |
| Target Method | FireworkRocketEntity.tick |
| Controlling GameRules | elytra_initial_boost_speed (Default: 30), elytra_high_speed_acceleration (Default: 15) |
| Algorithmic Complexity | $\mathcal{O}(1)$ time complexity, zero memory allocations per tick |
| Convergence Rate | $15%\text{ vector difference per tick}$ ($f_{\text{acc}} = 0.15$) |
🎮 Step-by-Step Player Workflow
In vanilla Minecraft, firework rockets apply a fixed formula designed solely for low-speed flight: $$\vec{b}{\text{vanilla}} = \vec{u}{\text{look}} \times 0.1 + \left(\vec{u}_{\text{look}} \times 1.5 - \vec{v}\right) \times 0.5$$ When flying above $30\text{ BPS}$ ($1.5\text{ blocks/tick}$), the vanilla formula actively decelerates the player!
Max Elytra Fly Speed introduces a Two-Tier Propulsion Engine:
- Tier 1 — Snappy Launch Boost ($v < 30\text{ BPS}$): When launching from a standstill or slow glide, the rocket delivers instant, snappy vanilla acceleration ($50%$ convergence per tick) to quickly reach cruising velocity.
- Tier 2 — High-Speed Vector Convergence ($v \ge 30\text{ BPS}$): Above $30\text{ BPS}$, the rocket transitions to proportional vector difference convergence, pulling the flight vector smoothly towards the camera look angle scaled by the configured maximum speed ceiling.
- Continuous Re-Orientation: As the player turns their camera, the high-speed convergence factor continuously aligns their momentum with the new look direction without jarring angular snapping.
📐 Mathematical Propulsion Models
1. Tier 1: Snappy Initial Acceleration
When the current velocity magnitude $v_{\text{current}} = |\vec{v}{\text{old}}|$ is below the initial boost threshold ($v{\text{initial_ticks}} = \frac{\text{initialBoostSpeedBps}}{20.0}$):
$$\vec{b}{\text{initial}} = \vec{u}{\text{look}} \times 0.1 + \left(\vec{u}{\text{look}} \times v{\text{initial_ticks}} - \vec{v}_{\text{old}}\right) \times 0.5$$
2. Tier 2: Proportional High-Speed Vector Convergence
When $v_{\text{current}} \ge v_{\text{initial_ticks}}$, the boost vector calculates the difference between the target velocity $\vec{v}{\text{target}} = \vec{u}{\text{look}} \times v_{\text{max_ticks}}$ and the current velocity:
$$\vec{b}{\text{high}} = \vec{u}{\text{look}} \times 0.1 + \left(\vec{u}{\text{look}} \times v{\text{max_ticks}} - \vec{v}{\text{old}}\right) \times f{\text{acc}}$$
where $f_{\text{acc}}$ is the high-speed acceleration factor: $$f_{\text{acc}} = \max\left(0.05, \frac{\text{highAccPermille}}{100.0}\right)$$ (Default: $15 \implies f_{\text{acc}} = 0.15$ or $15%\text{ convergence per tick}$).
3. Vector Sum & Velocity Clamping
The final target movement is combined and clamped to ensure it never exceeds the configured ceiling:
$$\vec{v}{\text{target_movement}} = \vec{v}{\text{old}} + \vec{b}$$
$$\vec{v}{\text{final}} = \begin{cases} \vec{v}{\text{target_movement}} \times \left(\frac{v_{\text{max_ticks}}}{|\vec{v}{\text{target_movement}}|}\right) & \text{if } |\vec{v}{\text{target_movement}}| > v_{\text{max_ticks}} \ \vec{v}_{\text{target_movement}} & \text{otherwise} \end{cases}$$
📊 Visual State Machine Flowchart
[ PLAYER USES FIREWORK ROCKET ]
|
v
Is Current Velocity < 30 BPS?
/ \
(YES) / \ (NO)
v v
[ TIER 1: SNAPPY BOOST ] [ TIER 2: HIGH-SPEED CONVERGENCE ]
• 50% convergence • 15% proportional convergence
• Quick launch to 30 BPS • Smooth pull toward look vector * maxSpeed
\ /
v v
[ VECTOR SUM & SPEED CLAMP ]
• Add boost to deltaMovement
• Clamp magnitude <= maxSpeedBps / 20.0📑 Acceleration Time Reference Table
Assuming starting speed of $30\text{ BPS}$ ($1.5\text{ blocks/tick}$) and look angle aligned with flight path:
| Max Speed Setting | Acceleration Setting ($f_{\text{acc}}$) | Ticks to Reach 90% Max Speed | Seconds to Reach 90% Max Speed | Blocks Traveled During Boost |
|---|---|---|---|---|
| 50 BPS | $15%\text{ / tick}$ (Default) | $\approx 14\text{ ticks}$ | $0.70\text{ seconds}$ | $\approx 29\text{ blocks}$ |
| 100 BPS | $15%\text{ / tick}$ (Default) | $\approx 15\text{ ticks}$ | $0.75\text{ seconds}$ | $\approx 52\text{ blocks}$ |
| 100 BPS | $25%\text{ / tick}$ (Fast) | $\approx 9\text{ ticks}$ | $0.45\text{ seconds}$ | $\approx 35\text{ blocks}$ |
| 200 BPS | $15%\text{ / tick}$ (Default) | $\approx 16\text{ ticks}$ | $0.80\text{ seconds}$ | $\approx 98\text{ blocks}$ |
| 200 BPS | $50%\text{ / tick}$ (Supersonic) | $\approx 5\text{ ticks}$ | $0.25\text{ seconds}$ | $\approx 38\text{ blocks}$ |
| 500 BPS | $15%\text{ / tick}$ (Default) | $\approx 17\text{ ticks}$ | $0.85\text{ seconds}$ | $\approx 235\text{ blocks}$ |
💻 Developer & Bytecode Mixin Hooks
1. RocketBoostHelper.java
package net.instantgratification.maxelytraflyspeed.util;
import net.minecraft.world.phys.Vec3;
public final class RocketBoostHelper {
public static Vec3 calculateBoostMovement(
Vec3 oldMovement,
Vec3 lookAngle,
double initialBoostSpeedTicks,
double maxSpeedTicks,
double highAccFactor
) {
if (oldMovement == null) oldMovement = Vec3.ZERO;
if (lookAngle == null) lookAngle = Vec3.ZERO;
double currentSpeed = oldMovement.length();
Vec3 targetBoost;
if (currentSpeed < initialBoostSpeedTicks) {
targetBoost = lookAngle.scale(0.1).add(
lookAngle.scale(initialBoostSpeedTicks).subtract(oldMovement).scale(0.5)
);
} else {
Vec3 targetVelocity = lookAngle.scale(maxSpeedTicks);
targetBoost = lookAngle.scale(0.1).add(
targetVelocity.subtract(oldMovement).scale(highAccFactor)
);
}
Vec3 targetMovement = oldMovement.add(targetBoost);
double targetSpeed = targetMovement.length();
if (targetSpeed > maxSpeedTicks && targetSpeed > 0.0) {
targetMovement = targetMovement.scale(maxSpeedTicks / targetSpeed);
}
return targetMovement;
}
}2. Bytecode Injection in FireworkRocketEntityMixin.java
- Mixin Target:
FireworkRocketEntity.class - Injection (
@Redirect): Redirectsentity.setDeltaMovement()insidetick()to applyRocketBoostHelper.calculateBoostMovement().
