Chapter 4. Entities
Now that you have a good understanding of how to make mods with event handlers, we can move on to other types of mods. The theme of Chapter 3 was explosions, which are fun, but this chapter’s theme will be entities. First, you will make pigs drop diamonds in addition to their normal drop of porkchops. Next, you will make all zombies receive diamond armor and a diamond axe when they spawn. Finally, you will allow creepers to spawn five reinforcements when they die.
Pigs Dropping Diamonds
Pigs are passive entities. They will follow you if you hold a carrot. You can also breed them with a carrot. You can even ride on them with a saddle and a carrot on a stick. When pigs die, they drop porkchops. Wouldn’t it be fun to make them drop diamonds or some other material instead? Let’s do that!
First, create an event handler class called PigsDroppingDiamonds
. The method code you need to add is shown in Example 4-1.
Example 4-1. Pigs dropping diamonds method code
@SubscribeEvent
public
void
dropDiamonds
(
LivingDeathEvent
event
)
{
if
(
!
(
event
.
entity
instanceof
EntityPig
)
)
{
return
;
}
Random
random
=
new
Random
(
)
;
if
(
!
event
.
entity
.
worldObj
.
isRemote
)
{
event
.
entity
.
dropItem
(
Items
.
diamond
,
random
.
nextInt
(
3
)
)
;
}
}
This method runs on a
LivingDeathEvent
, which happens when an entity dies.If the entity is not a pig, the method returns.
This line creates a new variable of the name
random
and typeRandom
. This is a Java class that generates random numbers.If the world is not a client world, tested by the
isRemote
field, then the method continues. If this statement was not here, the pig would drop twice the number of items, but half of the items would be ghost items, and would be impossible to pick up.dropItem
is a method on theentity
class that drops an item at the position of the entity. It takes two parameters: the first is the item to be dropped, and the second is the number of items to be dropped.In this case,
event.entity
refers to the pig.Items
is a Forge class that has the complete list of items in Minecraft.Items.diamond
refers to the diamond item, as the name says. ThenextInt()
method gets a random number between 0 and the number before the parameter given, 2 in this case. This line then drops 0 to 2 diamond items when the pig dies.
The final code should look like Example 4-2.
Example 4-2. Pigs dropping diamonds final code
package
org
.
devoxx4kids
.
forge
.
mods
;
import
java.util.Random
;
import
net.minecraft.entity.passive.EntityPig
;
import
net.minecraft.init.Items
;
import
net.minecraftforge.event.entity.living.LivingDeathEvent
;
import
net.minecraftforge.fml.common.eventhandler.SubscribeEvent
;
public
class
PigsDroppingDiamonds
{
@SubscribeEvent
public
void
dropDiamonds
(
LivingDeathEvent
event
){
if
(!(
event
.
entity
instanceof
EntityPig
))
{
return
;
}
Random
random
=
new
Random
();
if
(!
event
.
entity
.
worldObj
.
isRemote
)
{
event
.
entity
.
dropItem
(
Items
.
diamond
,
random
.
nextInt
(
3
));
}
}
}
Make sure to import everything, and import java.util.Random
when you are importing the Random
class.
Now, you are ready to try out your mod.
Run Minecraft by clicking the green arrow at the top and log in to your world. Spawn a pig by using a Spawn Pig item, and kill it by using a sword. You should see something like Figure 4-1.
There are a variety of items in Minecraft. Instead of dropping diamonds, you can experiment with dropping some other items as well. You are limited, however, to items known to Forge. So delete diamond
from the code, place your cursor right after Items.
and press Ctrl-Space. This will show the list of Minecraft items that are known to Forge, as shown in Figure 4-2.
You can select any item that you wish, click the green arrow to run Minecraft, and your dead pig will then drop that particular item. For example, a pig dropping a potato is shown in Figure 4-3.
The brown splotch under the pig is the potato that it dropped.
Another twist to this mod involves dropping a block, instead of an item, when the pigs die. For example, change Items.diamond
to Item.getItemFromBlock(Blocks.cobblestone)
to drop a cobblestone instead of a diamond. You need the Item.getItemFromBlock()
method because Blocks.cobblestone
is a block, not an item, so it can’t be used in the method dropItem()
. Item.getItemFromBlock()
turns it into an ItemBlock
, which is the item version of the block. A pig dropping a cobblestone is shown in Figure 4-4.
Just as the complete list of items can be seen by placing the cursor after Items.
and pressing Ctrl-Space, the complete list of blocks can be seen by placing the cursor right after Blocks.
and using the same key sequence. This is shown in Figure 4-5.
Try dropping different items and blocks when the pig dies.
Any living entity such as a cow, iron golem, or skeleton fires a LivingDeathEvent
as well. Change the first line in the dropDiamonds()
method to check for that particular entity instead of EntityPig
. For example, replace EntityPig
with EntityIronGolem
to change the items dropped on iron golem death. This will allow you to drop any item or block on the death of that entity.
Zombie Knights
Zombies are the most common hostile mobs in the game. They also drop many things (e.g., iron ingots and carrots), and they can pick up armor. This next mod will make zombies spawn with armor whenever they enter the world. They will also be given an axe. This way, zombies will be much stronger and harder to kill.
First, make an event handler class called ZombieKnights
. Then, add the code shown in Example 4-3.
Example 4-3. Zombie knights method code
@SubscribeEvent
public
void
giveArmor
(
EntityJoinWorldEvent
event
)
{
if
(
!
(
event
.
entity
instanceof
EntityZombie
)
)
{
return
;
}
EntityZombie
zombie
=
(
EntityZombie
)
event
.
entity
;
zombie
.
setCurrentItemOrArmor
(
0
,
new
ItemStack
(
Items
.
diamond_axe
)
)
;
zombie
.
setCurrentItemOrArmor
(
1
,
new
ItemStack
(
Items
.
diamond_chestplate
)
)
;
zombie
.
setCurrentItemOrArmor
(
2
,
new
ItemStack
(
Items
.
diamond_leggings
)
)
;
zombie
.
setCurrentItemOrArmor
(
3
,
new
ItemStack
(
Items
.
diamond_boots
)
)
;
zombie
.
setCurrentItemOrArmor
(
4
,
new
ItemStack
(
Items
.
diamond_helmet
)
)
;
}
This method runs on an
EntityJoinWorldEvent
, which happens when an entity is created.If the entity is not a zombie, the method returns.
This line shows a good example of casting in Java. Before we understand the concept of casting, let’s first discuss inheritance.
Java allows a class to be derived from another class. A class that is derived from another class is called a subclass or a child class. The class from which the subclass is derived is called a superclass or a parent class. A child class inherits a parent class by using the
extends
Java keyword. So a child class is also known to extend the parent class.For example,
Animal
could be a parent class, andCat
,Fish
, andBat
could be child classes. Each animal knows how to eat, and that ability can be defined in theAnimal
class. However, each animal also has special abilities that separate them from the others (e.g., in our sample of animals, only cats can walk, only fish can swim, and only bats can fly). Those specific abilities can then be defined in their respective child classes.A class can be derived from a class that is derived from another class, and so on, and ultimately derived from the topmost class,
java.lang.Object
. All the classes up tojava.lang.Object
are said to be in the parent hierarchy of the child class. This concept is commonly known as inheritance. A subclass inherits fields and methods of all the classes in the parent hierarchy.Casting is taking an object and “turning it into” an object of a different type. Specifically, you can take an object from the parent hierarchy and cast it into an object of a more specific type.
In our case,
Entity
is in the parent hierarchy ofEntityZombie
. So after we’ve confirmed that the given entity is of the typeEntityZombie
, as done in , we can castevent.entity
toEntityZombie
. This will allow us to call all the methods fromEntityZombie
, of course, after casting. We are particularly looking for methods that give armor/items to the zombie.Casting is done by specifying the more specific type in parentheses,
(
and)
, before the more generic type.The
setCurrentItemOrArmor
method assigns an item or armor at a particular slot for the given entity. There are five available slots, starting with slot 0. The first slot is meant for an item that the entity will hold. This line gives the zombie a diamond axe in this slot.The next four slots are meant for armor. This line and the three lines after it give the zombie full diamond armor in the armor slots: 1–4. Slot 1 is chestplate, slot 2 is leggings, slot 3 is boots, and slot 4 is helmet. You can put any kind of these armor in the appropriate slot, and in this mod, all the armor is diamond armor.
Import everything, and you should then be good to go.
The final code should look like Example 4-4.
Example 4-4. Zombie knights final code
package
org
.
devoxx4kids
.
forge
.
mods
;
import
net.minecraft.entity.monster.EntityZombie
;
import
net.minecraft.entity.passive.EntityHorse
;
import
net.minecraft.init.Items
;
import
net.minecraft.item.ItemStack
;
import
net.minecraftforge.event.ServerChatEvent
;
import
net.minecraftforge.event.entity.EntityJoinWorldEvent
;
import
net.minecraftforge.event.entity.living.LivingHurtEvent
;
import
net.minecraftforge.fml.common.eventhandler.SubscribeEvent
;
public
class
ZombieKnights
{
@SubscribeEvent
public
void
giveArmor
(
EntityJoinWorldEvent
event
){
if
(!(
event
.
entity
instanceof
EntityZombie
))
{
return
;
}
EntityZombie
zombie
=
(
EntityZombie
)
event
.
entity
;
zombie
.
setCurrentItemOrArmor
(
0
,
new
ItemStack
(
Items
.
diamond_axe
));
zombie
.
setCurrentItemOrArmor
(
1
,
new
ItemStack
(
Items
.
diamond_chestplate
));
zombie
.
setCurrentItemOrArmor
(
2
,
new
ItemStack
(
Items
.
diamond_leggings
));
zombie
.
setCurrentItemOrArmor
(
3
,
new
ItemStack
(
Items
.
diamond_boots
));
zombie
.
setCurrentItemOrArmor
(
4
,
new
ItemStack
(
Items
.
diamond_helmet
));
}
}
Run Minecraft by clicking the green arrow. Spawn a zombie, and it should have a diamond armor.
In Chapter 3, in the bouncing zombie tower picture, all the zombies had full diamond armor. This is because the player who took the screenshot was using the zombie knights and the exploding minecarts mods at the same time. An example of a zombie knight by itself is shown in Figure 4-6.
Creeper Reinforcements
The final mod in this chapter will be about creepers. Creepers are probably the most famous hostile mob in Minecraft, even if they aren’t the most common one. A bit of interesting history about the creeper: its entity model (shape) was made when Notch accidentally inverted the model of a pig.
This mod will spawn five creepers when a creeper dies, making the game much harder. You won’t be able to just kill the creepers, but will instead have to trap them. If you make the mistake of killing them, five more will attack you.
Create an event handler class called CreeperReinforcements
. The method code for it is shown in Example 4-5.
Example 4-5. Creeper reinforcements method code
@SubscribeEvent
public
void
spawnReinforcements
(
LivingDeathEvent
event
)
{
if
(
!
(
event
.
entity
instanceof
EntityCreeper
)
)
{
return
;
}
for
(
int
i
=
0
;
i
<
5
;
i
+
+
)
{
EntityCreeper
creeper
=
new
EntityCreeper
(
event
.
entity
.
worldObj
)
;
creeper
.
setLocationAndAngles
(
event
.
entity
.
posX
,
event
.
entity
.
posY
,
event
.
entity
.
posZ
,
0
,
0
)
;
if
(
!
event
.
entity
.
worldObj
.
isRemote
)
{
event
.
entity
.
worldObj
.
spawnEntityInWorld
(
creeper
)
;
}
}
}
This method runs on a
LivingDeathEvent
, which happens when an entity dies.If the entity is not a creeper, the method returns.
This line is the start of a
for
loop, another Java concept. Afor
loop is a way to repeat code until a certain condition is met. The general form of thefor
loop requires three values between the parentheses: the initialization, termination, and increment. These values are separated by semicolons. The initialization is run once, as the loop begins. The termination tells the loop when to stop; when the statement in this section becomesfalse
, the loop stops. This statement is checked after each repetition of the code. The increment happens after each time a loop is completed. The code that is repeated every time is within the opening bracket afterfor (int i = 0 ; i < 5 ; i++)
and the corresponding closing bracket two lines afterevent.entity.worldObj.spawnEntityInWorld(creeper);
.In this case, a new integer variable called
i
is made in the initialization and set to0
. The termination says to keep going untili
is not less than 5.++
is a new Java operator called an increment. This operator can be placed after an integer variable, and increments the value of the variable by 1. In our case, the increment says to increasei
by 1 each time.So when the loop starts out,
i
is set to0
and the code inside thefor
loop is run once. After the completion of the first run, it is incremented by 1, so it is now equal to 1. Before the next run of the loop, the termination condition is checked. If it isfalse
, then the loop is stopped and the next Java statement after the loop is executed. If it istrue
, then the loop is run once again, the value incremented, the termination checked, and so on.This keeps going on until
i
is incremented to 5, at which point it is not less than 5, because it is equal to 5. The loop has run five times by now. Because the termination statement isfalse
, the loop stops.A new variable called
creeper
is created. This variable will store the creeper that should be spawned. Because it is inside thefor
loop, it will run five times.This moves the creeper to the position of the dead creeper. It is also inside the
for
loop.The
LivingDeathEvent
will actually be called twice for each death. The first time, in whichisRemote
is false, the creeper needs to be spawned. The second time, whenisRemote
is true, the creeper should not be spawned. This is because whenisRemote
is false, everything is happening on the client side. We want to spawn the creeper on the client, because if we spawn it on the server, it will have no AI and will not move or take damage.This spawns the creeper. Because this line and the surrounding
if
statement are in thefor
loop, they will run twice.
You have now finished your mod and can test it out in Minecraft. Spawn a creeper by using a Spawn Creeper item, and kill it with a diamond sword. Five more creepers should spawn. Figure 4-7 shows what happens if you spawn one creeper and constantly kill its offspring. You can also spawn an iron golem inside the area, and it will start killing creepers and making more for you. When one creeper explodes, a lot of creepers will die and make tons of creepers. The only way to get rid of them is by setting your game difficulty to peaceful.
Notice the gray items in the picture; those are the gunpowder items dropped upon creeper death. There are also a few experience orbs, which are dropped upon a mob’s death. All these creepers came from one creeper, which eventually multiplied on death.
Summary
In this chapter, you learned about entities and how you can mod them to make them more interesting. First, you made pigs drop diamonds. You also learned how different items and blocks can be dropped and how the same technique can be applied to other living entities. Armored zombies were created, and finally, you made creepers spawn reinforcements on death. Now that you know how to modify entities’ behavior, you can make cool mods like faster creepers, skeletons with swords, and flying pigs.
We discussed Java concepts like generating random numbers, using a for
loop for repeating code until a condition was met, and using the increment operator. We also looked at inheritance and casting, two fundamental concepts that were applied in multiple places.
In the next chapter, you will learn about movement and how to mod the player’s movement.
Get Minecraft Modding with Forge now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.