Tutorial - anon-noob/mothball GitHub Wiki

So you wanna learn how to use mothball? You've come to the right place! It doesn't take long to start stratfinding linear jumps proficiently (curved jumps are much harder but you'll eventually get there).

Getting Started

To get started, find a discord server which has mothball access. The Minecraft Parkour Central discord server is one that provides access to mothball and is also a server for Minecraft parkour in general.

Running Mothball

As mentioned in the main page, type ;s or any of the valid commands at the start of your message so the bot knows to begin a mothball simulation. Whatever is typed afterward will be calculated accordingly.

After running a simulation with a message, you can edit that message to re-run mothball calculations so there is no need to spam messages for every calculation. It's also proper etiquette to not clog them with pointless simulations. It only confuses you even further than necessary.

You can continue on a simulation by replying to your message and starting the simulation with ;then. This will continue the simulation where you left off. If you edited a message which has follow-up simulations, it will also re-run those simulations.

Comments

Anything between two # or after an unpaired # will be treated as a comment and Mothball will ignore it. Typing ;s # hello # sprint # world is equivalent to ;s sprint

Basic Movement

Mothball calculates movement in the following order:

  1. Add current velocity to position (Move the player)
  2. Calculate acceleration
  3. Add acceleration to velocity

Note that this is different from in game ticks, where position is calculated at the end of each tick. However, calculating position first makes it easier to conceptualize simulations.

Before we start simulating in mothball, we recommend taking a look at Mothball Movement Functions which will help with syntax, arguments, and what functions are available to you.


Example Simulation - Walking

To start off, let's simulate walking with mothball. In game, this is simply pressing the w key (or whatever key you have binded to walking forward). Looking at the Mothball Movement Functions, we see that walk is the function that can simulate... well... walking in game!

The result should look like this.

simulating walking

FYI for all you nerdy programmers out there, walk is the same as walk(), which is a simple walk simulation with no arguments passed.

But now you want to simulate walking for more than just one game tick. Looking at the documentation Mothball Movement Functions, we can tell Mothball how long to walk for using the syntax walk(duration) where duration is a nonnegative integer. So if we wanted to walk for 5 ticks, then we would type walk(5).

The result should look like this.

simulating walking 5 ticks

Now if typing walk is too hard for you, why not just type w? Some functions in Mothball have aliases, which means you can do the same stuff using different names. For example, w is an alias of walk, and so w(5) should give us the same results as before.

simulating walking 5 ticks using w alias

Looking at the documentation Mothball Movement Functions, we can see that the walk function has one alias w. I mean it does literally say

# Other Aliases: w

But why use aliases? Some functions have quite long names and aliases are meant to be faster ways to type, but the choice is yours. Would you rather type sprintstrafejump or just stfj?


Example Simulation - Sprint Jumping

Now let's try simulating a jump. Looking at the documentation again, we find the following about the sprintjump function.

# Other Aliases: sj
sprintjump(
  duration: int = 1,
  rotation: float = None,
  *,
  slip: float = None
  speed: int = None,
  slow: int = None
)

After jump, the player is airborn. Equivalent to sj(1) sa(duration - 1).

Here, sa is an alias of sprintair, which is when you hold sprint and press w while airborn.

A normal jump lasts 12 ticks, so let's simulate that in Mothball.

simulating sprintjump

We can also check that sj(12) is equivalent to sj(1) sa(11). In other words, you spend 1 tick jumping, and the remaining ticks midair.

simulating sprintjump with sa

Do remember that unlike the walk (or w) function, sj(4) is NOT equivalent to sj sj sj sj. That is absurd and is only possible using an in-game glitch. You'll get different results.

wrong way to simulate jumps

With Rotation Argument

Now how would you simulate a normal sprint jump while facing 3 degrees? We see that sprintjump or sj has rotation as an argument, so we can use sj(12,3) to simulate this. The 3 in this case tells Mothball the angle while the 12 tells the duration.

simulate with rotation argument

With Keyword Arguments

But what if I want to simulate a normal sprint jump with speed 2? We see that sprintjump or sj has speed as an argument. Since speed comes after the asterisk *, it is strictly a keyword argument, which means you must type speed = 2 instead of just 2. The simulation would be sj(12, speed=2).

simulate with keyword argument speed

Appending Inputs

By default, every movement function assumes you are going forward with the w key. To change that, we can append inputs after the function name. Inputs can be any combination of the four default in-game movement keys wasd. The syntax for appending inputs is function.inputs

The function s sprints one tick going forward, but s.wa will sprint with w and a, going forward and left. Likewise, s.wd(3) will sprint 3 ticks with w and d, going forward and right.

appending inputs

And of course, doing just s is equivalent to s.w.

Mothball does not prevent you from doing absurd movement that are impossible in game, such as sj.s(12), sprint jumping backward using the s key. Doing this can be helpful for calculating certain scenarios but it would be better to just use sj(12,180), sprint jumping forward facing 180 degrees.

Negating Inputs with -

You can use - to reverse the inputs of a function. For example, -sn is equivalent to sn.s and -wa.wd is equivalent to wa.sa. It is recommended that you only use - if it is equivalent to function.s for readability reasons.

45 Strafes

A 45 strafe is when you face 45 degrees and counterstrafe in order to move slightly faster, hence gaining additional distance. For example, if you face 45 degrees to the right while moving forward and left, you are 45 strafing. The angle that you're travelling at is still effectively 0, but you gain extra speed!

All the Mothball Movement Functions listed has a corresponding 45 strafe equivalent. Just add 45 after the function name. For example, wa (alias of walkair) becomes wa45 (alias of walkair45).

On the left, with 45; on the right, without.

image image

Sprint Jump 45s Are Weird

The documentation provides a warning.

Be careful!
Unless otherwise stated, function45 is equivalent to function.wa(1,45). For example, walk45 is equivalent to walk.wa(1,45)

Appending 45 to a function will tell Mothball to maximize as much distance as possible, which may or may not mean facing 45 degrees. For the majority of movement functions, function45 is equivalent to function.wa(1,45). Only sprint jumps have this problem.

Sprint jump 45s

sj45(duration) is equivalent to sj sa45(duration - 1). In game this means facing 0 while jumping, and 45 strafing while midair. sj45 is NOT equivalent to sj.wa(1,45) as this is actually weaker, and you don't even go perfectly straight! In fact, sprint jumping without strafe is stronger than sprint jumping with strafe. Bonus fact, sj45(1) = sj(1) but sj45(t) != sj(t) for any $t > 1$.

sj sj45 sj.wa(1,45)

Sprint strafe jump 45s

sprintstrafejump or stfj will jump with strafe and maximize distance by finding the best angle to jump at. The rest of the airborn ticks will either face 0 or 45 depending on whether you use stfj or stfj45.

Similar to sj and sj45, stfj(duration) is equivalent to stfj sa45(duration - 1). It is also true that stfj45(1) = stfj(1) and stfj(t) != stfj(t) for any $t > 1$.

Sneak sprint jump 45s

snsj45(duration) is equivalent to snsj45 sa45(duration - 1) However, you might notice that it is not equivalent to snsj sa45(duration - 1) and that's because snsj45 != snsj. It turns out that sneak sprint jumping with strafe is stronger than without strafe, hence snsj45 will find the best angle to jump at, with the remaining airborn ticks facing 45.

In this case, facing about $9.11$ degrees is optimal. Keep in mind that this optimal angle is only true for this specific circumstance. Even if the player has speed 1, the optimal angle will be different!

snsj snsj.wa snsj45

Recommended Practices

While Mothball doesn't prevent you from doing absurd things such as stop45.wd (how do you 45 with wd and not move!?), you should probably follow these practices to avoid confusion and unintended behaviors. If you do try any of these sacrilegious pracitces, consequences will never be the same.

Please, DO NOT:

  • Append inputs to a 45ed function, such as w45.wd, or to the stfj function
  • Negate any function that already has inputs explicitly appended, such as -sj.wd
  • Append inputs or 45-ify any of the stop function

Using Setter Functions

They way every simulation works is by moving a Player object. This player object has attributes that affect how it is moved. Below are a list of the relevant attributes.

Player Attributes Purpose
z the player's z position
x the player's x position
vz the player's z velocity
vx the player's x velocity
rotation the player's default rotation (or "the angle the player faces")
slip the player's default ground slipperiness
inertia the player's inertia threshold
speed the player's speed potion amplifier
slow the player's slow potion amplifier
air sprint delay whether the player's sprint activation is delayed while midair
precision the precision, or decimal places, the output displays

Whenever a function is omitted, it will use the default value that was set. For example, all movement functions have the duration argument default to 1. However, the rotation argument does not need to be explicitly stated, which tells mothball to use the player's default rotation.

Mothball has Setter Functions which literally "set" default attributes for the rest of the simulation, unless otherwise overridden.


Dealing with Angles

Recall that almost all movement functions has a rotation arguemnt. If we wanted to simulate walking with w for 5 ticks facing -69 degrees, we simply do w(5, -69)

However, doing this does not set our default rotation to -69. In other words, the rest of the simulation will be calculated while facing 0. In mothball syntax, ;s w(5,-69) wa(3,-69) is NOT equivalent of ;s w(5,-69) wa(3) because the wa(3) will not be facing -69.

Face and Anglequeue

We can change the default rotation using the setter function face (its alias is f). Doing ;s f(1.5) sj sa(1,3) sa.wd is equivalent to ;s sj(1,1.5) sa(1,3) sa.wd(1,1.5). Note that the sa(1,3) overrides the default facing just for that function.

Of course, we can change the default rotation any time we wish.

But now let's say you have multiple angles that you want to turn to each tick. Sure, you can do

sj(1,1) sa(1,2) sa(1,3) sa(1,4) ... sa(1, 12) # you get the point

but that is quite a lot of leg work. Instead, ew use anglequeue, or its alias aq. The aq function takes as many comma-separated numbers and queues up those numbers which will be used as the default facing for subsequent ticks. This means we could rewrite the above simulation as

aq(1,2,3,4,5,6,7,8,9,10,11,12) sj(12)

and as a bonus, it changes the default rotation, so

aq(1,2,3,4,5,6,7,8,9,10,11,12) sj(12) sn(2)

the sn(2) function is executed while facing 12.

Turn and Turnqueue

The other way to change the default rotation is by using the turn function. Whereas face(angle) sets the default rotation to angle, turn(angle) will add to the default rotation and set it as default. And of course, turnqueue is the anglequeue version of turn. Hence,

aq(1,2,3,5,8,13,21) sj(10)

# is equivalent to #

tq(1,1,1,2,3,5,8) sj(10)

Recommendation: For the sake of your sanity, please try to NOT combine anglequeue and turnqueue together. What will happen is that both anglequeue and turnqueue will be applied with anglequeue taking priority over turnqueue.

Set Position and Velocity

Probably one of the most common things you'll do in your simulations is setting your position whenever and whereever.

To set your x or z position, use the functions setposx and setposz (aliases x and z respectively). For example, sj(12) z(0) sj(13)

You can also use the vertical line | which resets the player's position, that is, | is equivalent to x(0) z(0)

Likewise, you can set your velocity to any value, anywhere, and anytime you want using vx and vz. For example, s(2) vz(0.2) sj(12)

Set Output Precision

Use precision or pre to set the number of decimal places that will be displayed, defaults to 6.

Other Setter Functions

Well you don't need much explanation, its essentially the same idea. The setter functions set the default attribute for the rest of the simulation unless otherwise stated. For example,

;s slip(0.98) sj(12) sj(12) slip(0.6) sj(12)
# is equivalent to #
;s slip(0.98) sj(12) sj(12) sj(12, slip=0.6)

Using Output Functions

What's the point in running simulations when you don't utilize output functions? These functions display important information, and you can use as many as you need at any point in the simulation.

Preamble - Converting between blocks, displacement, and momentum

Before we introduce the output functions, it is helpful to learn the different ways we measure distance in Minecraft.

The simplest unit is displacement, which is simply how far the player is from the starting point. When you open the f3 menu and look at your coords, you can calculate your displacement by simple subtraction. For example, if your z coordinate read $3.253$ at the start and your final z coordinate was $5.187$, then your displacement was $1.934$ units.

To describe "block to block" jumps, we typically use the blocks unit. To convert from displacement $d$ to blocks $b$, we use the formula

$$b = \begin{cases}d + 0.6 &d \geq 0 \ d - 0.6 &d < 0\end{cases}$$

Realistically, this only works when $|d| \geq 0.6$

Okay but what does this $4$ blocks = $3.4$ units of displacement represent in Minecraft?

image

To describe momentum, we typically use the uniut "blocks of momentum" or "mm" for short. To convert from displacement $d$ to momentum $m$, we use the formula

$$m = \begin{cases}d - 0.6 &d \geq 0 \ d + 0.6 &d < 0\end{cases}$$

Realistically, this only works when $|d| \geq 0.6$

Okay but what does this $1$ block of mm = $1.6$ units of displacement represent in Minecraft?

image