
Guided Missiles in Minecraft
Friday, 6th June, 2025
[video removed from print]
Cue Soothing Minecraft — Relaxing Farm Morning. I'm tending the fields, watching the river flow. My brother walks by, saying hi. What's missing?
A brother-seeking missile with an explosive warhead enough to crack his cute Netherite armor, of course! This is my journey of developing such a thing with the mc_missile Minecraft mod. Follow this article and you too will have a fire-and-forget, top-attack, Infrared-homing missile at your disposal.
The Starting Point
The server we're playing on runs the mc_missile Minecraft mod. It allows all players to program guided missiles and fire them from a crossbow or dispenser.
A missile is built from components, each with a price tag and effects on the missile. For us only the rocket motor, air frame and seeker head matter.
Like the player (including my brother) the missile is an entity in Minecraft. The missile has
-
a position (with the elevation ),
-
velocity ,
-
pitch and
-
yaw .
These angles are in degrees and there's no roll. Additionally, they are the negated angles displayed in the Mincraft F3 Menu. That's because projectiles have flipped headings for some reason: is up, down and is north, east, south and west.
Minecraft updates the missile's state every tick (20 times a second). The update in tick is separated into three stages:
-
Receive the control input: The missile's only input method is an unrealisticly beefy control moment gyroscope. So the player's guidance code produces a requested change in pitch and yaw . It has no direct control over the missiles position, velocity, or thrust — only the rotation.
-
Update the missile's state: The gyroscope is powerful but not overly powerful. When the control input is too large (larger than defined by the airframe), it is scaled down linearly:
With this, Minecraft applies the adjusted control input plus some random noise.
Each is normally distributed noise dependent on the air frame used by the missile. So you don't have perfect control over the missiles rotation, there is always some variance.
Now the acceleration can be calculated from the rotation vector , the current thrust and gravity .
is normally distributed noise and like the thrust function defined by the rocket motor.
Lastly, the velocity and position are updated with the airframe defined drag .
-
Now that the missile's state has been updated Minecraft sends that state to the player's guidance code. All these values contain some variance, too — depending on the missile's inertial measurement unit. The guidance server has a little less than 50ms to send the rotation change for the next tick.
In the first tick (), the missile doesn't have guidance input yet and thus flies straight ahead with the velocity and rotation of the shooter. No variance is applied here.
Disclaimer: As you can see the flight dynamics of Minecraft missiles don't have anything to do with real missiles. There are no aerodynamic aspects simulated at all, for example. All we do is magically rotate a rock in vacuum. Thus the guidance code explained in this article can only be applied to the toy world that is Minecraft and nothing else. Still, it'll be fun!
[video removed from print]
So what happens when we write the simplest guidance code we can think of: doing nothing. We all like oxidized weapons so let's use Rust for this:
let mut control_input = ControlInput {
pitch_turn: 0.0,
yaw_turn: 0.0,
// --snip--
};
We're probably more likely to blow ourselves up than my brother like this. (A cheaper airframe would take an even less predictable path.)
Flying a Straight Line
[video removed from print]
Let's start with compensating the rotation noise . We can simply record the missile's heading in the first tick
self.target_pitch = missile_state.pitch;
self.target_yaw = missile_state.yaw;
and in all following ticks measure the missile's heading deviation and correct for it.
let mut control_input = ControlInput {
pitch_turn: self.target_pitch - missile_state.pitch,
yaw_turn: self.target_yaw - missile_state.yaw,
// --snip--
};
Now the missile flies in a consistently straight line. It just isn't flying where we're pointing our crosshair (at my brother).
Compensating for Gravity

As we can see we only have to adjust our pitch: There's no gravity messing with our yaw. Given the pitch of a desired acceleration (towards my brother) what pitch should the rocket point in?
Assume, without loss of generality, and ignore thrust variance. Also, assume (otherwise we'd have to calculate a parabola when our initial velocity suffices). Then and we can write:
and with some trigonometry:
There's no closed-form solution for . The best we can do is rewrite it like this and use a numerical root-finding approach like Newton's method:

How do we do that with Rust? We use Python, calculate a lookup-table resolving and use that in Rust.
import numpy as np
from scipy import optimize
def f(x, thrust, target_pitch_rad, g):
return ((g/thrust) + np.tan(target_pitch_rad)*np.cos(x) - np.sin(x))
def fprime(x, thrust, target_pitch_rad, g):
return (-np.tan(target_pitch_rad)*np.sin(x) - np.cos(x))
# Set the gravity to 1 so that we can easily scale the effective thrust in rust.
# effective_thrust = thrust/g
g = 1
thrusts = np.linspace(1, 5, 30)
target_pitches_deg = np.linspace(-90, 90, 30)
target_pitches_rad = np.deg2rad(target_pitches_deg)
thrusts_grid, target_pitches_rad_grid = np.meshgrid(thrusts, target_pitches_rad)
target_pitches_deg_grid = np.rad2deg(target_pitches_rad_grid)
heading_pitches_rad = optimize.newton(
f,
target_pitches_rad_grid,
fprime=fprime,
args=(thrusts_grid, target_pitches_rad_grid, g)
)
heading_pitches_deg = np.rad2deg(heading_pitches_rad)
[video removed from print]
As you can see in the colourful plot, when the missile has high thrust we don't really have to correct for gravity at all and our yellow line is basically straight. When the thrust is almost as strong as the gravity, we have to adjust our heading a lot more aggressively.
Pretty nice!
IrSeeker and Top Attack
One problem with the above design is that errors along the way are added up and make the missile miss sometimes.
We can fix this with the IrSeekerM missile component, which provides my brother's position every tick (when there's a line-of-sight).
Then the missile can update it's target heading and fix it's past inaccuracies.
With the missile's position and some target coordinates you can calculate the desired pitch and yaw with the below trigonometry.
pub async fn calc_alpha_psi(target_direction: Vec3) -> (f64, f64) {
// projected onto the horizontal plane
let vec_horizontal = Vec3::new(target_direction.x, 0.0, target_direction.z);
let mut alpha = vec_horizontal
.normalize()
.dot(&target_direction.normalize())
.acos()
.to_degrees();
if target_direction.y < 0.0 {
alpha *= -1.0;
}
let psi = target_direction.x.atan2(target_direction.z).to_degrees();
(alpha, psi)
}
And then the gravity corrected pitch , and to make the missile accelerate towards the target.
[video removed from print]
I had some fun with this and implemented top-attacks, where the missile rises into the air before striking the ground at high speed. At some point the missile switches from flying to some block in the sky to flying towards my brother.
Oh, no, our missile isn't hitting any more! Why is that?
Velocity-Awareness

The issue is that accelerating towards my brother isn't actually what we want: We want to align our velocity so that it moves us closer towards the target. Our previous calculation simply points our acceleration vector towards the target. When or is already pointing in the right direction that is correct. But at the apogee of a top-attack our missile's velocity is pointing towards the sky, not the target; so we miss.
Say our target is at and we are at . Then we're asking for our new velocity to fulfil
with and .
Because of gravity the exact length of is unfortunately not known at this point. A good approximation is to ignore gravity for now and use
You might already notice that defines a line in direction (from the missile towards my brother) and a sphere around with radius . So we're asking for a line-sphere intersection. You could either do the math yourself or use Wikipedia and come up with
I use the larger because then we're also accelerating towards the target while keeping our velocity correctly pointed. (You could also use the smaller one and accelerate away from the target in case you want to break.) With this I know where to accelerate:
We again need to compensate for gravity to calculate the right missile rotation.

One last problem: When the above radical is negative we can't calculate the square-root. This is the case when the sphere and line don't intersect at all. For us that means our current velocity is so far off and our thrust so weak there's no way we could reach the requested velocity this tick. In this case the best we can do is take the point of our circle closest to our line. That's equivalent to projecting orthographically onto :
Again we need to compensate for gravity just like before. Doing this for a few ticks should hopefully be enough to at some point have a positive radical and use the line-sphere intersection then. Fun fact: In this situation we aren't accelerating towards the target at all. We're completely focused on getting us on course, first.
[video removed from print]
Now our top attack works all the time. (Minus that one time the proximity fuse triggered too early, whoops.)
[video removed from print]
And direct attacks work, too.
[video removed from print]
Even aerial brothers can be engaged! This only works with this design because the rocket motor is so crazily powerful. It costs something like five diamonds per rocket alone! Anything cheaper wouldn't work like this.
Other Ideas
[video removed from print]
There's a lot you could improve upon. A few of my ideas:
- Use a different war head, the mc_missile mod offers many options.
- Implement a boost phase where the missile clears the trees and buildings the shooter stands under before rising into the sky.
- Guess the target's position based on the current direction (works without top-attack). Then you can save on the expensive seeker.
- Do some parabola calculation and use a cheaper rocket motor that only has a short burn duration in the beginning.
- Implement Proportional navigation to shoot down moving and aerial targets.
- Use lock-on after launch to fire at targets without visual contact.
- Generally use cheaper components and deal with the implications.
- much, much more...
I encourage you to give the mc_missile Minecraft mod a go — it's real fun!
PS
[video removed from print]
Psst, my entire guidance code is open-source; just don't tell my brother.
PPS
My brother is actually really cool. Thanks for testing my missiles!
Other Articles

grub-install --removable for buggy UEFI
Friday, 8th November, 2024
Install Debian on a device with a broken NVRAM.

Maki, Atoms and Time Travel
Sunday, 6th February, 2022
Maki showcases how a program for interactive and programmatic animation development can be implemented. Its programmatic approach provides the precision technical concepts require, while its interactivity and real-time updates avoid a disconnect between input and output.

LunarVim in Distrobox
Tuesday, 25th October, 2022
You're missing that one program that isn't available in your Linux distro? With Distrobox, the 'Linux Subsystem for Linux,' you can install it anyways. This article explains how to do that with the example of installing LunarVim on Red Hat.

Installing Gentoo To My Liking
Tuesday, 26th April, 2022
Gentoo is a Linux distribution that offers as many options as possible. This article leads you through the decisions I took to end up with a system that best suits my needs.