This workshop shows how to get started with Minecraft Modding using Forge.
Download the following software
-
Java Development Kit (JDK): Download and install JDK from https://www.oracle.com/java/technologies/downloads/
-
Eclipse: Download Eclipse from http://www.eclipse.org/downloads/eclipse-packages/, pick “Eclipse IDE for Java Developers” and unzip.
-
Forge: Download Forge 1.19 from https://maven.minecraftforge.net/net/minecraftforge/forge/1.19-41.1.0/forge-1.19-41.1.0-mdk.zip
Follow the instructions as explained below.
Make sure all the software listed in Download and Install is downloaded.
-
Open a Command Prompt as explained at http://windows.microsoft.com/en-us/windows-vista/open-a-command-prompt-window
-
Change directory to “Desktop” using the command
cd Desktop
-
Make a new directory using
mkdir forge
-
Change to the directory using
cd forge
-
In File Explorer, right-click on the Forge 1.19 zip file downloaded earlier, select “Extract All…”, and extract the contents into the newly created
forge
directory. -
In Command Prompt, run the command
gradlew genEclipseRuns
. The output should showBUILD SUCCESSFUL
.
Make sure all the software listed in Download and Install is downloaded.
-
In Finder, go to “Applications”, then “Utilities”, then double click on “Terminal”.
-
Change directory to Desktop using the command
cd Desktop
-
Make a new directory using
mkdir forge
-
Change to the directory using
cd forge
-
Unzip the downloaded Forge 1.19 zip file using the command
unzip ~/Downloads/forge-1.19-41.1.0-mdk.zip
-
Run the command
./gradlew genEclipseRuns
. The output should showBUILD SUCCESSFUL
.
This is a very important step as this will confirm that you can actually start modding.
-
Open up Eclipse.
-
In the “Eclipse IDE Launcher” window, click on “Launch”.
-
In the Eclipse window, chose menu “File”, “Import…”.
-
Click the arrow next to “Gradle”.
-
Select “Existing Gradle Project” and click “Next >” .
-
In the box that says “Project root directory”, choose the location of the
forge
directory. -
Click “Finish”.
-
-
The Eclipse window should look like the following:
-
Click the “Restore” button at the top left:
-
Now, your window should look like the following:
-
On the left is the “Package Explorer”, which is where the game’s source code lives. We’ll come back to it later. For now, in the “Gradle Tasks” window on the right side, double click on the
forge
folder. Then, double click onforgegradle runs
and selectrunClient
. -
Double click on
runClient
to start the Minecraft launcher. It should look like the following:
If you’re able to launch Minecraft in this way, your setup is good to go. Let’s start modding!
Purpose: This mod adds items to player’s inventory when they type a certain word or phrase in chat.
Instructions: Create a new Java class called ChatItems
:
-
Double click on the
forge
folder in the “Package Explorer” on the left side. -
Expand the folder
src/main/java
. -
Right click on the package
com.example.examplemod
and selectNew
>Class
. -
In the “Name” box, fill in
ChatItems
, then click on theFinish
Button. -
Replace the resulting code with Chat Items code.
package com.example.examplemod;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = ExampleMod.MODID)
public class ChatItems {
@SubscribeEvent
public static void giveItems(ServerChatEvent event) {
if (event.getMessage().contains("potato")) {
event.getPlayer().getInventory().add(new ItemStack(Items.POTATO, 64));
}
}
}
At this point, your window should look like the following:
Once you’ve finished editing the files, it’s time to run the game. Click on the green play button at the top-left to run your modded Minecraft:
When Eclipse asks you to save the file, click on the “Save” button. This will save the file and start the Minecraft launcher.
Gameplay:
-
Create a new Creative mode world.
-
Press
T
to open the chat window. -
Type in any message that contains the word
potato
. -
You should receive one stack (64 items) of potatoes.
This variation produces a different item for a different text message. For example change the text from "potato"
to "diamond"
and the item produced from Items.POTATO
to Items.DIAMOND
. To see more possibilities, use Ctrl
+Space
with your cursor just after Items.
to show the list of items.
To see the changes you’ve made, close Minecraft and restart it by clicking on the play button in Eclipse.
This variation produces different items for different chat text. For example, typing potato
will yield potatoes while typing diamond
will yield diamonds.
@SubscribeEvent
public static void giveItems(ServerChatEvent event){
if (event.getMessage().contains("potato")) {
event.getPlayer().getInventory().add(new ItemStack(Items.POTATO, 64));
}
if (event.getMessage().contains("diamond")) {
event.getPlayer().getInventory().add(new ItemStack(Items.DIAMOND, 64));
}
}
This variation yields multiple items for a single message. Instead of producing potatoes and diamonds separately, the player gets both items at once from a single trigger word.
@SubscribeEvent
public void giveItems(ServerChatEvent event){
if (event.getMessage().contains("potato")) {
event.getPlayer().inventory.addItemStackToInventory(new ItemStack(Items.POTATO, 64));
event.getPlayer().inventory.addItemStackToInventory(new ItemStack(Items.DIAMOND, 64));
}
}
Purpose: This mod will spawn an ender dragon every time a player places a dragon egg block.
Instructions: In the package com.example.examplemod
, make a new class called DragonSpawner
and replace its code with the code shown in Ender Dragon Spawner code.
package com.example.examplemod;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = ExampleMod.MODID)
public class DragonSpawner {
@SubscribeEvent
public static void spawnDragon(BlockEvent.EntityPlaceEvent event) {
if (event.getPlacedBlock().getBlock() == Blocks.DRAGON_EGG) {
event.getLevel().removeBlock(event.getPos(), false); // false = no flags
EnderDragon dragon = EntityType.ENDER_DRAGON.create(event.getEntity().getLevel());
dragon.moveTo(event.getPos(), 0, 0);
dragon.getPhaseManager().setPhase(EnderDragonPhase.TAKEOFF);
event.getLevel().addFreshEntity(dragon);
}
}
}
Gameplay:
-
Use the command
/give Dev minecraft:dragon_egg
to give yourself a dragon egg. -
Select the hotbar slot containing the dragon egg.
-
Right click in the world to place down the dragon egg, which will spawn an ender dragon.
Note
|
When running the /give command, you may get the error You don’t have permissions to perform the command . The reason for this is that you don’t have cheats enabled in your world. When you are creating a world, there will be a box that says you are in “Survival”" mode. Click on the box until it says “Creative” mode, which will automatically enable cheats. Then, create the the world normally. You will need to create a new world for this.
|
This variation changes the block that triggers spawning as well as the entity spawned. For example, you can change the block to Blocks.SPONGE
and the entity to EntitySquid
. Like with Chat Items, use Ctrl
+Space
to show the list of possible items or entities.
@SubscribeEvent
public static void spawnSquid(BlockEvent.EntityPlaceEvent event) {
if (event.getPlacedBlock() == Blocks.SPONGE.defaultBlockState()) {
event.getLevel().removeBlock(event.getPos(), false); // false = no flags
Squid squid = EntityType.SQUID.create(event.getEntity().level);
squid.moveTo(event.getPos(), 0, 0);
event.getLevel().addFreshEntity(squid);
}
}
After doing this, press Control
+ Shift
+ O
on a Windows computer or Cmd
+ Shift
+ O
on a Mac computer to update the imports and fix the error. After launching the game, in the Minecraft game window, give yourself a sponge using the command /give Dev minecraft:sponge
, or grab a sponge from the creative inventory. Place the sponge in the world to spawn a squid.
Purpose: This mod will alert all players when a creeper spawns.
Instructions: Make a new Java class called CreeperSpawnAlert
. Replace its contents with Creeper Spawn Alert code.
package com.example.examplemod;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.monster.Creeper;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = ExampleMod.MODID)
public class CreeperSpawnAlert {
@SubscribeEvent
public static void sendAlert(EntityJoinLevelEvent event) {
if (event.getEntity() instanceof Creeper && event.getLevel().isClientSide) {
for (Player player : event.getLevel().players()) {
player.sendSystemMessage(Component.literal(ChatFormatting.GREEN + "A creeper has spawned!"));
}
}
}
}
Gameplay:
-
Make sure you are not on peaceful mode.
-
Set the time to night time using the command
/time set night
You should get a bunch of messages saying “A creeper has spawned!”. One of these messages is sent to you every time a creeper spawns.
This variation changes the message printed.
player.sendSystemMessage(Component.literal(ChatFormatting.RED + "Run away, a creeper has spawned!"));
This variation prints messages for zombies instead of creepers.
if (event.getEntity() instanceof Zombie && event.getLevel().isClientSide) {
for (Player player : event.getLevel().players()) {
player.sendSystemMessage(Component.literal(ChatFormatting.GREEN + "A zombie has spawned!"));
}
}
Purpose: This mod turns all snowballs into arrows so that they can hurt entities.
Instructions: Create a new Java class called SharpSnowballs
. Replace its code with Sharp Snowballs code.
package com.example.examplemod;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.projectile.Arrow;
import net.minecraft.world.entity.projectile.Snowball;
import net.minecraft.world.level.Level;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = ExampleMod.MODID)
public class SharpSnowballs {
@SubscribeEvent
public static void replaceSnowballWithArrow(EntityJoinLevelEvent event) {
Entity snowball = event.getEntity();
Level level = event.getLevel();
if (!(snowball instanceof Snowball)) {
return;
}
if (!level.isClientSide) {
Arrow arrow = EntityType.ARROW.create(level);
arrow.moveTo(snowball.position());
arrow.setDeltaMovement(snowball.getDeltaMovement());
level.addFreshEntity(arrow);
}
event.setCanceled(true);
}
}
Gameplay:
-
Give yourself a snowball using the command
/give Dev minecraft:snowball
, or grab a snowball from the creative inventory. -
Select the snowball in your hotbar and right click to throw it.
-
The snowball should turn into an arrow.
You can also spawn snow golems by placing a pumpkin on top of a tower of two snow blocks. The snow golem will act as a turret, shooting out snowballs that turn into arrows at hostile mobs.
Tip: Spawn a zombie or two for the snow golems to shoot.
This variation converts snowballs into lit TNT.
Replace the line Arrow arrow = EntityType.ARROW.create(level);
with the code shown in Explosive Snowballs code.
PrimedTnt arrow = EntityType.TNT.create(level);
arrow.setFuse(80);
Make sure to fix the imports using Ctrl
+ Shift
+ O
on Windows or Cmd
+ Shift
+ O
on Mac.
Purpose: This mod adds helpful potion effects to iron golems when they are spawned in the world.
Instructions:
Create a new Java class called OverpoweredIronGolems
and replace its contents with Overpowered Iron Golems code.
package com.example.examplemod;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.animal.IronGolem;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = ExampleMod.MODID)
public class OverpoweredIronGolems {
@SubscribeEvent
public static void applyPotionEffectsToGolem(EntityJoinLevelEvent event) {
if (!(event.getEntity() instanceof IronGolem)) {
return;
}
IronGolem golem = (IronGolem) event.getEntity();
golem.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SPEED, 1000000, 5));
golem.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, 1000000, 5));
golem.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 1000000, 5));
golem.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 1000000, 5));
}
}
Gameplay:
-
Spawn an iron golem by using the command
/summon minecraft:iron_golem
-
Spawn some hostile mobs (zombies, skeletons, etc.) near the iron golem. For example, use the command
/summon minecraft:zombie
. -
The golem should move towards the hostile mobs to kill them.
Normally, iron golems move slowly, but with the speed effect from the mod, they should move very fast.
Purpose: Normally, rain does not create water on the terrain. This mod places water at the feet of entities when it is raining.
Instructions: Create a new Java class called RainWater
and replace its contents with Rain Water code.
package com.example.examplemod;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = ExampleMod.MODID)
public class RainWater {
@SubscribeEvent
public static void makeWater(LivingEvent.LivingTickEvent event) {
Entity entity = event.getEntity();
Level level = entity.level;
BlockPos entityPos = entity.blockPosition();
if (level.isClientSide) {
return;
}
if (!level.isRaining() || level.getBiome(entityPos).get().getPrecipitation() != Biome.Precipitation.RAIN) {
return;
}
for (int i = entityPos.getY(); i < 320; i++) {
if (level.getBlockState(entityPos.atY(i)).getBlock() != Blocks.AIR) {
return;
}
}
BlockPos posBelow = entityPos.below(1);
if (!level.getBlockState(posBelow).isCollisionShapeFullBlock(level, posBelow)) {
return;
}
level.setBlockAndUpdate(entityPos, Blocks.WATER.defaultBlockState());
}
}
Gameplay:
-
Go to a biome where it rains, such as plains, forest, swamp, or jungle. Make sure you’re not in a biome where rain doesn’t happen, such as desert, savanna, or taiga.
-
Use the command
/weather rain
to start the rain. -
Start walking on the ground, and water should be placed at the feet of you and all other entities in the rain.
-
If water is not spawning, make sure you’re not standing in a transparent block such as tall grass or a flower.
-
This variation spawns TNT during thunderstorms instead of placing water during rain.
Replace the makeWater()
method in the RainWater
class with the code in TNT Thunder Code.
@SubscribeEvent
public static void spawnTnt(LivingEvent.LivingTickEvent event) {
Entity entity = event.getEntity();
Level level = entity.level;
BlockPos entityPos = entity.blockPosition();
if (level.isClientSide) {
return;
}
if (!level.isThundering() || level.getBiome(entityPos).get().getPrecipitation() != Biome.Precipitation.RAIN) {
return;
}
for (int i = entityPos.getY(); i < 320; i++) {
if (level.getBlockState(entityPos.atY(i)).getBlock() != Blocks.AIR) {
return;
}
}
BlockPos posBelow = entityPos.below(1);
if (!level.getBlockState(posBelow).isCollisionShapeFullBlock(level, posBelow)) {
return;
}
if (level.random.nextInt(40) != 1) {
return;
}
PrimedTnt tnt = EntityType.TNT.create(level);
tnt.setFuse(80);
tnt.moveTo(entityPos, 0, 0);
level.addFreshEntity(tnt);
}
Don’t forget to fix the imports using Ctrl
+ Shift
+ O
on Windows or Cmd
+ Shift
+ O
on Mac.
To test this variation, travel to a rainy biome and use the command /weather thunder
to make the weather stormy. Then, watch for TNT to be placed wherever you walk around. The TNT should explode after 4 seconds.
Purpose: This mod gives armor to all skeletons and makes them attack each other.
Instructions: Create a new Java class called SkeletonWar
and replace its contents with Skeleton War code.
package com.example.examplemod;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
import net.minecraft.world.entity.monster.AbstractSkeleton;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.util.Arrays;
import java.util.List;
@Mod.EventBusSubscriber(modid = ExampleMod.MODID)
public class SkeletonWar {
static List<Item> helmets = Arrays.asList(Items.LEATHER_HELMET,
Items.CHAINMAIL_HELMET, Items.GOLDEN_HELMET, Items.IRON_HELMET,
Items.DIAMOND_HELMET, Items.NETHERITE_HELMET, Items.TURTLE_HELMET);
static List<Item> chestplates = Arrays.asList(Items.LEATHER_CHESTPLATE,
Items.CHAINMAIL_CHESTPLATE, Items.GOLDEN_CHESTPLATE, Items.IRON_CHESTPLATE,
Items.DIAMOND_CHESTPLATE, Items.NETHERITE_CHESTPLATE);
static List<Item> leggings = Arrays.asList(Items.LEATHER_LEGGINGS,
Items.CHAINMAIL_LEGGINGS, Items.GOLDEN_LEGGINGS, Items.IRON_LEGGINGS,
Items.DIAMOND_LEGGINGS, Items.NETHERITE_LEGGINGS);
static List<Item> boots = Arrays.asList(Items.LEATHER_BOOTS,
Items.CHAINMAIL_BOOTS, Items.GOLDEN_BOOTS, Items.IRON_BOOTS,
Items.DIAMOND_BOOTS, Items.NETHERITE_BOOTS);
@SubscribeEvent
public static void makeWarNotPeace(EntityJoinLevelEvent event) {
if (!(event.getEntity() instanceof AbstractSkeleton skeleton)) {
return;
}
skeleton.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(skeleton, AbstractSkeleton.class, true));
RandomSource random = skeleton.level.random;
skeleton.setItemSlot(EquipmentSlot.HEAD, new ItemStack(helmets.get(random.nextInt(6))));
skeleton.setItemSlot(EquipmentSlot.CHEST, new ItemStack(chestplates.get(random.nextInt(5))));
skeleton.setItemSlot(EquipmentSlot.LEGS, new ItemStack(leggings.get(random.nextInt(5))));
skeleton.setItemSlot(EquipmentSlot.FEET, new ItemStack(boots.get(random.nextInt(5))));
}
}
Gameplay:
-
Spawn a skeleton by using the command
/summon minecraft:skeleton
or by using a skeleton spawn egg. -
Spawn more skeletons and watch them fight.
You can also create an enclosed arena to spawn skeletons in. Try adding some traps or lava!
Are you interested in creating a new item, new block, new recipe, new textures, and lots of other fun mods? Then check out Minecraft Modding with Forge from O’Reilly.
Are you interested in following these instructions and learning a bit of Java in the process as well? Then check out Minecraft Modding with Forge Training Video from O’Reilly or scan the QR code from your phone.