Permalink
Switch branches/tags
Nothing to show
Find file Copy path
6b628c2 Feb 6, 2018
@arun-gupta @AdityaGupta1
1143 lines (875 sloc) 33.5 KB

Minecraft Modding using Forge

Requirements

  • A Mac or Windows computer

  • A Minecraft account is not required

Download and Install

Download

Download the following software

Mac or Windows

Follow the instructions for Mac or Windows as explained below.

Mac

Make sure all the software lised in Download and Install is downloaded.

  1. In Finder, go to Applications, Utilities, double click on Terminal

  2. Change directory to Desktop as cd Desktop

  3. Make a new directory by giving the command mkdir forge

  4. Change to the directory cd forge

  5. Unzip the downloaded Forge 1.12 zip file as unzip ~/Downloads/forge-1.12.2-14.23.1.2555-mdk.zip

  6. Give the command ./gradlew setupDecompWorkspace eclipse. The output should show BUILD SUCCESSFUL.

Windows

Make sure all the software lised in Download and Install is downloaded.

  1. Open a Command Prompt as explained at http://windows.microsoft.com/en-us/windows-vista/open-a-command-prompt-window

  2. Change directory to Desktop as cd Desktop

  3. Make a new directory by giving the command mkdir forge

  4. Change to the directory cd forge

  5. In File Explorer, double click on the Forge 1.12 zip file downloaded earlier and extract all the contents in this newly created directory.

  6. In Command Prompt, give the command gradlew setupDecompWorkspace eclipse. The output should show BUILD SUCCESSFUL.

A detailed video with complete installation steps on Mac is given below:

forge install video pic

Verify

This is a very important step as this will confirm that you can actually start modding.

  1. Open up Eclipse

  2. In the “Eclipse Launcer” window, click on Browse…​, choose the location of eclipse directory in the unzipped forge directory

  3. Click on “OK”

  4. In the Eclipse window, you should see a “MDKExample” folder and be able to expand it. There should be no red exclamation marks next to it.

Troubleshooting

  1. If you either selected “Cancel”" or selected a different directory in Eclipse Launcher, click on “File”, “Switch Workspace”, “Other…​”, and select the correct directory.

  2. If you don’t see the MDKExample folder, the gradlew command might have shown some errors. Try running it again.

The Main File

To start modding, we need a main file. This file will register all of our mods so that they actually function in the game. To make this main file, first you need to make a new package. Click on the arrow next to the “MDKExample” folder in the left side of your window. Then, right click on “src/main/java” and select New > Package. Name it org.devoxx4kids.forge.mods.

We need to create a new class in this package. To do this, right click on the new package you created and select New > Class. Name it MainMod. The middle of your screen will show its code. Replace all of the code with the code in Set up the main file.

Example 1. Set up the main file
package org.devoxx4kids.forge.mods;

import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;

@Mod(modid = MainMod.MODID, version = MainMod.VERSION)
public class MainMod {
	public static final String MODID = "mymods";
	public static final String VERSION = "1.0";

	@EventHandler
	public void init(FMLInitializationEvent event) {

	}
}

Your main file is now ready to go.

Chat Items

Purpose: To make the player receive items when he/she says a certain word or phrase in a chat message.

Instructions: In your new package, org.devoxx4kids.forge.mods, make a new file called ChatItems. Replace its code with Chat Items code.

Example 2. Chat Items code
package org.devoxx4kids.forge.mods;

import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class ChatItems {

	@SubscribeEvent
	public void giveItems(ServerChatEvent event) {
		if (event.getMessage().contains("potato")) {
			event.getPlayer().inventory.addItemStackToInventory(new ItemStack(
					Items.POTATO, 64));
		}
	}
}

Register your mod in the main file by using the line shown in Chat Items registering. The line should go between the two brackets after the line that says init().

Example 3. Chat Items registering
MinecraftForge.EVENT_BUS.register(new ChatItems());

Your main file should now look like Main file after registering Chat Items.

Example 4. Main file after registering Chat Items
package org.devoxx4kids.forge.mods;

import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;

@Mod(modid = MainMod.MODID, version = MainMod.VERSION)
public class MainMod {
	public static final String MODID = "mymods";
	public static final String VERSION = "1.0";

	@EventHandler
	public void init(FMLInitializationEvent event) {
		MinecraftForge.EVENT_BUS.register(new ChatItems());
	}
}

Once you’ve finished editing the files, click the green “Run Client” button on the Eclipse menu bar to build and run your modded Minecraft.

Gameplay:

  1. Create a new “Creative” world

  2. Press “T” to open up the chat window

  3. Type in any message that contains the word “potato”

  4. You should receive one stack (one stack = 64 items) of potatoes

Change text/item

Change text message and produce a different item. For example change the text to diamond and item produced to Diamond. Use Ctrl+Space to show the list of items.

Close Minecraft window and restart it by clicking on the “Run Client” button on the Eclipse menu bar.

Different Items

Produce different items for different chat text

Example 5. Different Chat Items code
@SubscribeEvent
public void giveItems(ServerChatEvent event){
	if (event.getMessage().contains("potato")) {
		event.getPlayer().inventory.addItemStackToInventory(new ItemStack(Items.POTATO, 64));
	}

	if (event.getMessage().contains("diamond")) {
		event.getPlayer().inventory.addItemStackToInventory(new ItemStack(Items.DIAMOND, 64));
	}
}

Multiple Items

Produce multiple items for chat text

Example 6. Multiple Chat Items code
@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));
	}
}

Ender Dragon Spawner

Purpose: To spawn an Ender Dragon every time a player places a Dragon Egg block.

Instructions: In the package org.devoxx4kids.forge.mods, make a new class called DragonSpawner and replace its code with the code shown in Dragon Spawner code.

Example 7. Dragon Spawner code
package org.devoxx4kids.forge.mods;

import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.dragon.phase.PhaseList;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.event.world.BlockEvent.PlaceEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class DragonSpawner {

	@SubscribeEvent
	public void spawnDragon(PlaceEvent event) {
		if (event.getPlacedBlock() == Blocks.DRAGON_EGG.getBlockState().getBaseState()) {
			event.getWorld().setBlockToAir(new BlockPos(event.getPos().getX(), event.getPos().getY(),event.getPos().getZ()));
			EntityDragon dragon = new EntityDragon(event.getWorld());
			dragon.setLocationAndAngles(event.getPos().getX(), event.getPos().getY(), event.getPos().getZ(), 0, 0);
			dragon.getPhaseManager().setPhase(PhaseList.TAKEOFF);
			event.getWorld().spawnEntity(dragon);
		}
	}
}

Then, register it like you did with Chat Items, but use the line of code shown in Dragon Spawner registering.

Example 8. Dragon Spawner registering
MinecraftForge.EVENT_BUS.register(new DragonSpawner());

Gameplay:

  1. Use the command “/give <your player name> dragon_egg” to give yourself a dragon egg

  2. Select the slot in which the dragon egg is placed

  3. Double click in the world to place down the dragon egg, and an Ender Dragon should spawn

The player name will not be your normal player name, it will be a Forge-generated player name. Check your chat window to see what your player name is.

Note
You may get the error “You don’t have permissions to perform the command”. The reason it says that you don’t have permission to run the command is because 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 rest of the world normally. You will need to create a new world for this.

Change block/entity

Change block that triggers spawning and spawn a different item. For example change the block to sponge and entity to EntitySquid. Use Ctrl+Space to show the list of items.

Example 9. Spawn squid
if (event.getPlacedBlock() == Blocks.SPONGE.getBlockState().getBaseState()) {
	event.getWorld().setBlockToAir(new BlockPos(event.getPos().getX(), event.getPos().getY(),event.getPos().getZ()));
	EntitySquid squid = new EntitySquid(event.getWorld());
	squid.setLocationAndAngles(event.getPos().getX(), event.getPos().getY(), event.getPos().getZ(), 0, 0);
	event.getWorld().spawnEntity(squid);
}

After doing this, press Control + Shift + O on a Windows computer or Cmd + Shift + O on a Mac computer to import one class and fix the error. When you test out this mod, place down a Wet Sponge, not a Sponge.

Change offset of entities

Change event.pos.getX(), event.pos.getY(), event.pos.getZ() and add or subtract 5 to spawn entities at an offset.

Example 10. Spawn offset
dragon.setLocationAndAngles(event.getPos().getX() + 5, event.getPos().getY(), event.getPos().getZ(), 0, 0);

Creeper Spawn Alert

Purpose: To alert all players when a creeper spawns.

Instructions: In your package, make a new class called CreeperSpawnAlert. Replace its contents with Creeper Spawn Alert code.

Example 11. Creeper Spawn Alert code
package org.devoxx4kids.forge.mods;

import java.util.List;

import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class CreeperSpawnAlert {

	@SubscribeEvent
	public void sendAlert(EntityJoinWorldEvent event) {
		if (!(event.getEntity() instanceof EntityCreeper)) {
			return;
		}

		List players = event.getEntity().world.playerEntities;

		for (int i = 0; i < players.size(); i++) {
			EntityPlayer player = (EntityPlayer) players.get(i);
			if (event.getWorld().isRemote) {
				player.sendStatusMessage(new TextComponentString(TextFormatting.GREEN + "A creeper has spawned!"), false);
			}
		}
	}
}

Register it using the line in Creeper Spawn Alert registering.

Example 12. Creeper Spawn Alert registering
MinecraftForge.EVENT_BUS.register(new CreeperSpawnAlert());

Gameplay:

  1. Make sure you are not on peaceful mode.

  2. Set the time to night time /time set night

You should get a bunch of messages saying “A creeper has spawned!” in light green letters. One of these messages is sent to you every time a creeper spawns.

Change color/format of message

Change color to red

Example 13. Color of message
player.sendStatusMessage(new TextComponentString(TextFormatting.RED + "A creeper has spawned!"), false);

Try different colors by code completion after EnumChatFormatting.

Change style to italics

Example 14. Style of message
player.sendStatusMessage(new TextComponentString(TextFormatting.ITALIC + "A creeper has spawned!"));

Try different styles by code completion after EnumChatFormatting.

Change text of message

Example 15. Style of message
player.sendStatusMessage(new TextComponentString(TextFormatting.GREEN + "Run away, a creeper has spawned!"));

Talk about text within quotes.

Print same message for different mobs

Example 16. Same message for differet mobs using AND
if (!(event.getEntity() instanceof EntityCreeper && event.getEntity() instanceof EntityZombie)) {
	return;
}

OR

Example 17. Same message for differet mobs using OR
if (!(event.getEntity() instanceof EntityCreeper) || !(event.getEntity() instanceof EntityZombie)) {
	return;
}

Explain AND and OR

Print different message for different mobs

Example 18. Different message for different mobs
@SubscribeEvent
public void sendAlert(EntityJoinWorldEvent event) {
	if (!(event.getEntity() instanceof EntityCreeper || event.getEntity() instanceof EntityZombie)) {
		return;
	}

	String message;

	if (event.getEntity() instanceof EntityCreeper) {
		message = "A creeper has spawned";
	} else {
		message = "A zombie has spawned";
	}

	List players = event.getEntity().worldObj.playerEntities;

	for (int i = 0; i < players.size(); i++) {
		EntityPlayer player = (EntityPlayer) players.get(i);
		if (event.getWorld().isRemote) {
			player.sendStatusMessage(new TextComponentString(TextFormatting.GREEN + message), false);
		}
	}
}

Print message for all mobs

Example 19. Message for all mobs
if (!(event.getEntity() instanceof EntityMob)) {
	return;
}

Explain how to reach EntityMob.

Sharp Snowballs

Purpose: To turn all snowballs into arrows so that they can hurt entities.

Instructions: In your package, create a new class called SharpSnowballs. Replace its code with Sharp Snowballs code.

Example 20. Sharp Snowballs code
package org.devoxx4kids.forge.mods;

import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class SharpSnowballs {

	@SubscribeEvent
	public void replaceSnowballWithArrow(EntityJoinWorldEvent event) {
		Entity snowball = event.getEntity();
		World world = snowball.world;

		if (!(snowball instanceof EntitySnowball)) {
			return;
		}

		if (!world.isRemote) {
			EntityTippedArrow arrow = new EntityTippedArrow(world);
			arrow.setLocationAndAngles(snowball.posX, snowball.posY, snowball.posZ,
					0, 0);
			arrow.motionX = snowball.motionX;
			arrow.motionY = snowball.motionY;
			arrow.motionZ = snowball.motionZ;

			// gets arrow out of player's head
			// gets the angle of arrow right, in the direction of motion
			arrow.posX += arrow.motionX;
			arrow.posY += arrow.motionY;
			arrow.posZ += arrow.motionZ;

			world.spawnEntity(arrow);
			snowball.setDead();
		}
	}
}

Register the new class using the line in Sharp Snowballs registering.

Example 21. Sharp Snowballs registering
MinecraftForge.EVENT_BUS.register(new SharpSnowballs());

Gameplay:

  1. Get a Snowball item from your inventory

  2. Right click with it to throw it

  3. It 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.

Tip: spawn a Zombie or two for the Snow Golems to shoot.

Explosive snowballs

Replace EntityTippedArrow arrow = new EntityTippedArrow(world); line with the code shown in Explosive Snowballs code.

Example 22. Explosive Snowballs code
EntityTNTPrimed arrow = new EntityTNTPrimed(world);
arrow.setFuse(80);

Make sure to fix the imports using Cmd + Shift + 0 on Mac and Ctrl + Shift + O on Windows.

Overpowered Iron Golems

Purpose: To add helpful potion effects to Iron Golems when they spawn in the world.

Instructions:

In your package, make a new class called OverpoweredIronGolems and replace its contents with Overpowered Iron Golems code.

Example 23. Overpowered Iron Golems code
package org.devoxx4kids.forge.mods;

import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class OverpoweredIronGolems {

	@SubscribeEvent
	public void golemMagic(EntityJoinWorldEvent event) {
		if (!(event.getEntity() instanceof EntityIronGolem)) {
			return;
		}

		EntityLiving entity = (EntityLiving) event.getEntity();
		entity.addPotionEffect(new PotionEffect(Potion.getPotionById(1), 1000000, 5));
		entity.addPotionEffect(new PotionEffect(Potion.getPotionById(5), 1000000, 5));
		entity.addPotionEffect(new PotionEffect(Potion.getPotionById(10), 1000000, 5));
		entity.addPotionEffect(new PotionEffect(Potion.getPotionById(11), 1000000, 5));
	}
}

Then, register the class using the line shown in [Iron_Golems_Register].

MinecraftForge.EVENT_BUS.register(new OverpoweredIronGolems());

Gameplay:

  1. Spawn an Iron Golem by using the command /summon villager_golem.

  2. Spawn some hostile mobs near the Iron Golem

The golem should move towards them to kill them. Normally, Iron Golems move slowly, but with the speed effect from the mod, they should move very fast.

Rain Water

Purpose: To place water at the feet of entities when it is raining.

Instructions: In your package, create a new class called RainWater and replace its contents with Rain Water code.

Example 24. Rain Water code
package org.devoxx4kids.forge.mods;

import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class RainWater {

	@SubscribeEvent
	public void makeWater(LivingUpdateEvent event) {
		Entity entity = event.getEntity();
		World world = entity.world;
		int x = (int) Math.floor(entity.posX);
		int y = (int) Math.floor(entity.posY);
		int z = (int) Math.floor(entity.posZ);

		if (!world.isRaining()) {
			return;
		}

		for (int i = y; i < 256; i++) {
			if (world.getBlockState(new BlockPos(x, i, z)) != Blocks.AIR.getBlockState().getBaseState()) {
				return;
			}
		}

		if (world.isRemote || !world.getBlockState(new BlockPos(x, y - 1, z)).isFullCube()) {
			return;
		}

		world.setBlockState(new BlockPos(x, y, z), Blocks.WATER.getBlockState().getBaseState());
	}
}

Then, register it using the line shown in Rain Water registering.

Example 25. Rain Water registering
MinecraftForge.EVENT_BUS.register(new RainWater());

Gameplay:

  1. Use the command /weather rain to make the weather rainy

  2. Start moving, and water should be placed wherever you or any other entity go, but it will disappear quickly

TNT Thunder

Purpose: Spawn a TNT with fuse at a random duration wherever an entity is walking

Instructions: Replace the makeWater method in RainWater class:

Example 26. TNT Thunder Code
@SubscribeEvent
public void makeWater(LivingUpdateEvent event) {
	Entity entity = event.getEntity();
	World world = entity.world;
	int x = (int) Math.floor(entity.posX);
	int y = (int) Math.floor(entity.posY);
	int z = (int) Math.floor(entity.posZ);

	if (!entity.world.isThundering()) {
		return;
	}

	for (int i = y; i < 256; i++) {
		if (world.getBlockState(new BlockPos(x, i, z)) != Blocks.AIR.getBlockState().getBaseState()) {
			return;
		}
	}

	if (world.isRemote || !world.getBlockState(new BlockPos(x, y - 1, z)).isFullCube()) {
		return;
	}

	Random random = new Random();

	if (random.nextInt(40) != 1) {
		return;
	}

	EntityTNTPrimed tnt = new EntityTNTPrimed(world);
	tnt.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, 0, 0);
	tnt.setFuse(80);
	world.spawnEntity(tnt);
}

Fix the imports.

Gameplay:

  1. Use the command /weather thunder to make the weather stormy

  2. Watch for TNT to be placed wherever you walk around. The TNT will blow up after 1-4 seconds.

Wall Climber (NOT WORKING)

Purpose: To allow players to climb up straight walls without any blocks or other help.

Instructions: In your package, create a new class called WallClimber and replace its contents with Wall Climber code.

Example 27. Wall Climber code
package org.devoxx4kids.forge.mods;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.event.entity.living.LivingFallEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent;

public class WallClimber {

	@SubscribeEvent
	public void climbWall(PlayerTickEvent event) {

		EntityPlayer player = event.player;

		if (!player.isCollidedHorizontally) {
			return;
		}

		if (player.isActiveItemStackBlocking()) {
			player.motionY = -0.5;
		} else if (player.isSneaking()) {
			player.motionY = 0;
		} else {
			player.motionY = 0.5;
		}

	}

	@SubscribeEvent
	public void negateFallDamage(LivingFallEvent event) {
		if (!(event.getEntity() instanceof EntityPlayer)) {
			return;
		}

		event.setCanceled(true);
	}
}

Then, register it using the line shown in Wall Climber registering.

Example 28. Wall Climber registering
FMLCommonHandler.instance().bus().register(new WallClimber());
MinecraftForge.EVENT_BUS.register(new WallClimber());

You’ll find that Eclipse flags a missing import for FMLCommonHandler so make sure to add it as we did earlier.

Gameplay:

  1. Build a wall straight up with any solid block you want

  2. Run into that wall and you should start going up

  3. Block with a sword to go down instead of up

  4. Hold Shift to stop moving up or down

Arrow Shotgun (NOT WORKING)

Purpose: To make all bows fire 20 flaming arrows instead of one arrow.

Instructions: In your package, create a new class called ArrowShotgun and replace its contents with Arrow Shotgun code.

Example 29. Arrow Shotgun code
package org.devoxx4kids.forge.mods;

import java.util.Random;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.item.ItemBow;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.player.ArrowLooseEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class ArrowShotgun {

	private final int arrows = 20;

	@SubscribeEvent
	public void shootArrows(ArrowLooseEvent event) {
		EntityPlayer player = event.getEntityPlayer();
		World world = event.getWorld();

		Random random = new Random();

		float velocity = 2.0F;

		for (int i = 0; i < arrows; i++) {
			EntityArrow arrow = new EntityTippedArrow(world, player);
			arrow.setLocationAndAngles(0.0F, ItemBow.getArrowVelocity(event.getCharge()) * 3.0F, 12.0F, player.rotationYaw, player.rotationPitch);
			arrow.pickupStatus = EntityArrow.PickupStatus.DISALLOWED;
			arrow.setFire(10000);
			if (!world.isRemote) {
				world.spawnEntity(arrow);
			}
		}

		event.setCanceled(true);
	}
}

Then, register it using the line shown in Arrow Shotgun registering.

Example 30. Arrow Shotgun registering
MinecraftForge.EVENT_BUS.register(new ArrowShotgun());

Gameplay:

  1. Get a Bow item from your inventory

  2. Hold right click to charge it

  3. Release right click when the bow begins shaking

  4. 20 flaming arrows should be fired out

Skeleton War

Purpose: To make all skeletons try to kill each other and also receive armor on spawning.

Instructions: In your package, create a new class called SkeletonWar and replace its contents with Skeleton War code.

Example 31. Skeleton War code
package org.devoxx4kids.forge.mods;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.init.Items;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class SkeletonWar {

	@SubscribeEvent
	public void makeWarNotPeace(EntityJoinWorldEvent event) {
		if (!(event.getEntity() instanceof EntitySkeleton)) {
			return;
		}
		EntitySkeleton skeleton = (EntitySkeleton) event.getEntity();

		List<ItemArmor> helmets = Arrays.asList(Items.LEATHER_HELMET,
				Items.CHAINMAIL_HELMET, Items.GOLDEN_HELMET, Items.IRON_HELMET,
				Items.DIAMOND_HELMET);
		List<ItemArmor> chestplates = Arrays.asList(Items.LEATHER_CHESTPLATE,
				Items.CHAINMAIL_CHESTPLATE, Items.GOLDEN_CHESTPLATE,
				Items.IRON_CHESTPLATE, Items.DIAMOND_CHESTPLATE);
		List<ItemArmor> leggings = Arrays.asList(Items.LEATHER_LEGGINGS,
				Items.CHAINMAIL_LEGGINGS, Items.GOLDEN_LEGGINGS,
				Items.IRON_LEGGINGS, Items.DIAMOND_LEGGINGS);
		List<ItemArmor> boots = Arrays.asList(Items.LEATHER_BOOTS,
				Items.CHAINMAIL_BOOTS, Items.GOLDEN_BOOTS, Items.IRON_BOOTS,
				Items.DIAMOND_BOOTS);

		skeleton.targetTasks.addTask(3, new EntityAINearestAttackableTarget(
				skeleton, EntitySkeleton.class, true));
		skeleton.canPickUpLoot();

		Random random = new Random();
		skeleton.setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(
				helmets.get(random.nextInt(5))));
		skeleton.setItemStackToSlot(EntityEquipmentSlot.CHEST, new ItemStack(
				chestplates.get(random.nextInt(5))));
		skeleton.setItemStackToSlot(EntityEquipmentSlot.LEGS, new ItemStack(
				leggings.get(random.nextInt(5))));
		skeleton.setItemStackToSlot(EntityEquipmentSlot.FEET,
				new ItemStack(boots.get(random.nextInt(5))));
	}

}

Then, register it using the line shown in Skeleton War registering.

Example 32. Skeleton War registering
MinecraftForge.EVENT_BUS.register(new SkeletonWar());

Gameplay:

  1. Get a Spawn Skeleton item from your inventory

  2. Right click on the ground two times to spawn two skeletons

  3. The skeletons should have assorted pieces of armor; they should also be shooting each other

Fast Bows (NOT WORKING)

Purpose: To add an enchantment which reduces the time needed to nock an arrow on a bow and pull it back all the way.

Instructions: In your package, create a new class called EnchantmentArrowFast and replace its contents with Fast Bows code. The name EnchantmentArrowFast is modeled after other bow enchantments' names in the code. For example, the enchantment Flame, which sets arrows on fire after they are launched, is called EnchantmentArrowFire.

Example 33. Fast Bows code
package org.devoxx4kids.forge.mods;

import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.init.Items;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraftforge.event.entity.living.LivingEntityUseItemEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class EnchantmentArrowFast extends Enchantment {
	public EnchantmentArrowFast() {
		super(Enchantment.Rarity.UNCOMMON, EnumEnchantmentType.BOW,
				new EntityEquipmentSlot[] { EntityEquipmentSlot.MAINHAND,
						EntityEquipmentSlot.OFFHAND });
		this.setName("arrowFast");
	}

	/**
	 * Returns the minimal value of enchantability needed on the enchantment
	 * level passed.
	 */
	public int getMinEnchantability(int enchantmentLevel) {
		return 12 + (enchantmentLevel - 1) * 20;
	}

	/**
	 * Returns the maximum value of enchantability nedded on the enchantment
	 * level passed.
	 */
	public int getMaxEnchantability(int enchantmentLevel) {
		return this.getMinEnchantability(enchantmentLevel) + 25;
	}

	/**
	 * Returns the maximum level that the enchantment can have.
	 */
	public int getMaxLevel() {
		return 2;
	}

	@SubscribeEvent
	public void decreaseBowUseDuration(LivingEntityUseItemEvent.Tick event) {
		if (event.getItem() == null) {
			return;
		}

		if (event.getItem().getItem() != Items.BOW) {
			return;
		}

		int level = EnchantmentHelper.getEnchantmentLevel(MainMod.haste, event.getItem());

		switch (level) {
		case 1:
			event.setDuration(event.getDuration() - 1);
			break;
		case 2:
			event.setDuration(event.getDuration() - 2);
			break;
		default:
			break;
		}
	}
}

Then, you will need to add some extra lines of code besides just the registering line. Right after the line in your main file that says public static final String VERSION = "1.0";, add the line of code from Fast Bows enchantment constant

Example 34. Fast Bows enchantment constant
public static final Enchantment haste = new EnchantmentArrowFast();

After that, put the code from Fast Bows registering in your init() method to register the mod.

Example 35. Fast Bows registering
MinecraftForge.EVENT_BUS.register(haste);
Enchantment.REGISTRY.register(100, new ResourceLocation("arrowFast"), haste);

Don’t forget to fix the imports using Cmd + Shift + O on Mac and Ctrl + Shift + O on Windows.

Lastly, you will have to make a new file to make sure the name of the enchantment shows up correctly (“Haste” instead of “enchantment.arrowFast”). There is a folder with the name "src/main/resources" directly underneath the "src/main/java" folder. Right click on that folder, and select New > Package. Name your new package assets.mymods.lang. Then, right click on your new package and select New > File. When you are asked for the name of the new file, enter the name en_US.lang. In the new file, add in the text shown in Fast Bows .lang file.

Example 36. Fast Bows .lang file
enchantment.arrowFast=Haste

Gameplay:

  1. Get a Bow from your inventory

  2. Get an Enchanted Book that has the enchantment "Haste I" or "Haste II" on it from your inventory

  3. Use an anvil to combine the two items you got

  4. Get out another bow from your inventory, but don’t enchant it

  5. Compare the shooting speeds of the two bows - the ones with Haste should be significantly faster than the one without any enchantmeents

Sharing Your Mods

Open up your computer’s command prompt. Navigate to your Forge folder. Then, type the command gradlew build. On a Mac it may be ./gradlew build. After the process completes, navigate to the "build" folder, then the "libs" folder inside that. In that folder, there should be a .jar file called modid-1.0.jar. This .jar file is all of your mods.

To install your mod on your Minecraft launcher, follow the instructions at http://www.minecraftforge.net/wiki/Installation/Universal.

Minecraft Modding Book from O’Reilly

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.

minecraft modding book cover

Minecraft Modding Video Tutorial 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.

minecraft modding oreilly video course

Tips

  • When changing an item or block, delete the current item/block and press Ctrl + Space to pull up a list of items and blocks that are availible.