Minecraft as a Game Engine

Minecraft has become a widely used tool in a lot of environments such as education, but what people don't tend to think is that this game is capable of much more animation wise. In this post I will try to show you how to use Minecraft as a game engine with little code involved. Let's begin!

How does it work?

The first step on learning how to use a rendering engine is learning the data structures it uses, the tick loop, etc.

Minecraft processes changes in the world every 50 milliseconds, which is 1/20 of a second. Minecraft as a game uses the LWJGL library which uses OpenGL, a common rendering engine used in a lot of games nowadays.

The game also renders in regions of 16x16 blocks called chunks with some distance limits that we will have to take into account.

By the end of this post, you will be able to create your own engine, and although it can be run in a server, some methods in this post are latency sensitive such as the block gravity and the cinematics.

What should our game engine contain?

According to the Wikipedia page for game engine, most of the include:

  • A rendering engine (We already have this)
  • A physics engine
  • A Sound engine (playable custom sounds)
  • Animation creator
  • Artificial intelligence
  • Tons of things Minecraft already implements for us

We will start with the easier concepts, and as we progress, we will start to add more code.

Mods vs Plugins

We could develop the engine as a mod (a client side modification) or as a plugin for the Spigot platform (a fork of the original Minecraft server that focuses on performance). I think Minecraft has overcomplicated how mods are made, forcing us the developers to use the Forge library, MCP, unreadable obfuscated function names...

Another point for not using a mod in this case is that I have little (or none) experience with Forge coding for the reasons stated above.

World rendering

Hypixel Server map using Shaders

The first thing a player sees in a game is the terrain that is surrounding him. Minecraft has extensive settings to modify this experience such as FOV (field of view), rendering distance, quality of animations...

Visual modifications to the game can only be created client side by heavily modifying the dark rendering engine used in the client (the previous photo shows the Shaders mod creating custom shades), and as so, we won't focus on this.

The game has some clashing settings for our engine; for example, the FOV modification affects the character speed feeling, and as so, we will have to stick with block-based rendered objects. Other compromises/problems you will face while using Minecraft related code will be transparency and biome dynamic coloring for textures.

Resource Packs

Since 1.6.1, Minecraft allows content creators to modify all the textures available in the game and sounds, even giving us the option to add new assets.

If you want to create a shooter kind of game, we will need to have gun (pixelated) textures, and you can see lots of examples in famous multiplayer servers of the game:

Custom guns in CvC, a Hypixel game

But this doesn't end here! Since 1.8, Mojang has given texture creators the ability to give depth and custom dimensions to their models through a complex JSON based engine. As always, there's someone that makes this process easier, and that's @Sphax84 with his program Cubik Studio, a voxel based editor that can export your models into Minecraft JSON, with advanced functions such as in-game relative hand placing, rotations and imports and exports from real models in .STL (3D printings), .OBJ (Mesh) and many more.

This allows us to give more detail to our engine by not limiting our textures to predefined voxels and go above the normal possibilities the old texture pack system gave us. Here are some examples:

3D modelled karts

Medieval weapon

Cinematics

Okay, enough talking. Let's start with code. Minecraft doesn't have cinematics support, but the Spectator gamemode makes the player experience during a cinematic more inversive.

We will create an API that will accept a list of locations and will make a smooth transition for spectators. The method that is usually used to create the smooth teleports is a lerp function, which uses Linear interpolation. The important code is in the lerp() function, the rest is just classes to make it easier for the developers to add dynamic locations:

{% gist hugmanrique/e79916c79140b4601c9d638d43651da6 %}

As you can see, the actual code is in the CinematicTask class, where it loads the current and the next locations and, every tick, calculates the next position using the lerp() function in line 110. You could even make this more powerful by adding text to each position, but that's up to you.

You can now create your own Cinematic class, and initialize the cinematic for a Player using:

{% highlight java %} new CinematicTask(plugin, player, this).start(); {% endhighlight %}

Sound

The resource pack system isn't limited to textures! Sounds are also implemented with this system, and they don't have many limitations. The only sound format Minecraft supports is .ogg (Wiki page), but there are plenty of converters online.

Again, this is a client side modification, and as so, we can't do anything about it. Although one thing that should receive a mention is that you can add custom .ogg files and then play them from the server specifying the folder structure as so:

{% highlight java %} player.playSound("folder.structure.file"); {% endhighlight %}

Animation

Creating animations is hard, especially because there aren't many tools available to automate things. There are two kind of animations we will focus in:

  • Item animations
  • Entity animations

The first uses the resource pack system explained above. It simply uses frame based animations and Cubik Creator is also compatible with this kind of assets.

The second is the most difficult one to achieve. Whether you are trying to move a wheel or sit down, you will need to use Armor stands, a powerful entity added in 1.8 that allow us to push the limits of the "voxelness" of Minecraft. Here are some examples:

Target minigame in Epicube

The Bukkit API provides powerful methods and allow us to create cool animations using Euler angles. Let's try to spawn some swords and a delivery man opening a special chest:

{% gist hugmanrique/1bd273e3b20b419f625c437db61b7ff9 %}

And here's the result after adding rotation, hidding the armor stands and creating the delivery man: (This was created 5 months ago)

{% include video.html url="nVyq2blnS3U" %}

Artificial Intelligence

The internal Minecraft server contains a powerful AI library used with Creatures (an internal class that represent mobs) that allows you to add custom Pathfinder goals that define how the mob will behave. Let's try to create a mob that will follow the nearest player.

We will need to use NMS in this case, and I recommend you to create the classes in this Spigot tutorial before proceding, as I will assume you already have them.

The type of goal we will need is the PathfinderGoalFollow. We can now proceed:

{% highlight java %} public class Follower extends EntityZombie { public Follower(World world) { super(((CraftWorld) world).getHandle());

    // Get the fields as in the tutorial
    
    // Follow entities at 1.2 speed
    goalSelector.a(0, new PathfinderGoalFollow(this, 1.2, false));
    
    // Look at player from 8 blocks
    this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
}

} {% endhighlight %}

Ocelots are creatures that implement this goal

As you have noticed, this isn't even a quarter of the required code to create a custom entity (that's why I included the Spigot tutorial). But that's why we are here, to create an API over the overcomplicated NMS code required for this to work. Minecraft gives us lots of premade pathfinder goals, but you can always create your own. This gives us infinite possibilities to control the movement of entities.

Physics

We all love Minecraft generation, don't we?

This one is the last, and probably the funniest. Every game engine has gravity, hitboxes and movement properties. Since Minecraft 1.9, hitboxes are actually phisical, so they prevent two players from sticking together. That's some job already done for us, but let's see how to implement gravity components such as -9.81m/s^2 (Gravitational acceleration in Earth) and 4m/s^2 (negative gravity, also known as Anti-gravity) which is impossible in our current model of the Universe; but who cares, this is Minecraft.

We all know that Minecraft doesn't respect gravity rules for placed blocks (it does for entities), so we will have to override the block placing and create a falling block entity with the placed block texture:

{% gist hugmanrique/7d5d9824f648b652a4d5d66abbc1a5ea %}

That one was easy! We just prevent the BlockPlaceEvent (this can cause issues if we aren't under localhost), and create a FallingBlock with the same data as the placed block. You should also remove the block from the player's hand.

Final notes

Woah! You made it to the end. I hope you all learned what things game engines should implement to make the life of game developers easier and how to implement some of these techniques in Minecraft. I know you were waiting for this word the entire post, so here you go: Gameception :video_game:

As you have seen, not all the things can be implemented server side, but being able to create a custom physics engine under 20 lines is awesome! I implemented all of this ideas in a Game API months ago when I was trying to make a Battlefield realistic server based game in Minecraft, but I lost the motivation on this project, not because it didn't work, but simply because this game was becoming boring for me (it still is).

You can find all the (complete) code used in this tutorial in one of my GitHub repos.

Special thanks to @SantiTR_ for the original idea, make sure to check him out!

Hugo :wink:

© Hugmanrique. Made with