diff --git a/src/common/resources/lang/en_US/options.lang b/src/common/resources/lang/en_US/options.lang
index 0eb92ced8..8e933da01 100644
--- a/src/common/resources/lang/en_US/options.lang
+++ b/src/common/resources/lang/en_US/options.lang
@@ -149,7 +149,7 @@ options.turnWithVehicle=Turn with Vehicle
 options.playServerSounds=Play Server Sounds
 options.lightmapStyle=Lightmap Style
 options.lightmapStyle.gray=Grayscale
-options.lightmapStyle.cosy=Cosy
+options.lightmapStyle.colorized=Colorized
 options.lightmapStyle.disabled=Disabled
 options.customLightmap=Custom Lightmap
 
@@ -219,4 +219,5 @@ key.sprint=Sprint (if enabled)
 key.toggleDebug=Toggle Debug
 key.toggleOverlay=Toggle Overlays
 key.sortInventory=Sort Inventory
+key.pickAmmo=Pick Ammo
 key.disabled=Disabled
diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java
index 24b6aacf5..59e147c3b 100644
--- a/src/main/java/net/minecraft/client/Minecraft.java
+++ b/src/main/java/net/minecraft/client/Minecraft.java
@@ -8,6 +8,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Random;
 
+import net.minecraft.client.gui.hud.AmmoPickerComponent;
+import net.minecraft.client.gui.hud.HudComponents;
 import org.lwjgl.LWJGLException;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
@@ -1275,7 +1277,10 @@ public class Minecraft
                         	thePlayer.setFlySpeed(newSpeed);
                         	ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.flightSpeed);
                         }
-                        else if (!gameSettings.keyZoom.isPressed())
+                        else if (gameSettings.keyPickAmmo.isPressed()) {
+                            thePlayer.pickAmmo(scrollDelta);
+                        }
+                        else if (!gameSettings.keyZoom.isPressed() && !gameSettings.keyPickAmmo.isPressed())
                         {
                             thePlayer.inventory.changeCurrentItem(scrollDelta);
                         }
@@ -1483,6 +1488,10 @@ public class Minecraft
                 }
             }
 
+            if (gameSettings.keyPickAmmo.isPressed()) {
+                ((AmmoPickerComponent) HudComponents.AMMO_PICKER).show();
+            }
+
             boolean breakBlockPressed = gameSettings.keyAttack.isPressed() || (controllerInput != null && controllerInput.buttonZR.isPressed());
             boolean placeBlockPressed = gameSettings.keyInteract.isPressed() || (controllerInput != null && controllerInput.buttonZL.isPressed());
 
diff --git a/src/main/java/net/minecraft/client/entity/player/EntityPlayerSP.java b/src/main/java/net/minecraft/client/entity/player/EntityPlayerSP.java
index 669b12bd4..89503edee 100644
--- a/src/main/java/net/minecraft/client/entity/player/EntityPlayerSP.java
+++ b/src/main/java/net/minecraft/client/entity/player/EntityPlayerSP.java
@@ -33,6 +33,8 @@ import net.minecraft.core.block.entity.TileEntityTrommel;
 import net.minecraft.core.data.gamerule.GameRules;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.EntityPlayer;
+import net.minecraft.core.item.IAmmoPickable;
+import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.command.ClientCommandHandler;
 import net.minecraft.core.net.command.ClientPlayerCommandSender;
@@ -207,7 +209,7 @@ public class EntityPlayerSP extends EntityPlayer
         checkInTile(x - (double) bbWidth * 0.35D, bb.minY + 0.5D, z - (double) bbWidth * 0.35D);
         checkInTile(x + (double) bbWidth * 0.35D, bb.minY + 0.5D, z - (double) bbWidth * 0.35D);
         checkInTile(x + (double) bbWidth * 0.35D, bb.minY + 0.5D, z + (double) bbWidth * 0.35D);
-        boolean canSprint = world.getGameRule(GameRules.ALLOW_SPRINTING) && !this.noPhysics;
+        boolean canSprint = world.getGameRuleValue(GameRules.ALLOW_SPRINTING) && !this.noPhysics;
         if (onGround && !forwardInput && input.moveForward >= f && !isSprinting() && canSprint)
         {
             if (sprintTimer == 0)
@@ -396,6 +398,28 @@ public class EntityPlayerSP extends EntityPlayer
         	messageHistory.remove(0);
         }
     }
+
+    public void pickAmmo(int offset) {
+        if (offset == 0) return;
+        if (offset < 0) offset = -1;
+        if (offset > 0) offset = 1;
+
+        ItemStack stack = mc.thePlayer.getHeldItem();
+        if (stack == null) return;
+
+        Item item = stack.getItem();
+        if (!(item instanceof IAmmoPickable)) return;
+
+        IAmmoPickable pickable = (IAmmoPickable) item;
+        List<ItemStack> ammoTypes = pickable.getPresentAmmoTypes(this);
+
+        int pickedIndex = ammoTypes.indexOf(pickable.getPickedAmmoType(stack));
+        int newIndex = pickedIndex + offset;
+        if (newIndex < 0) newIndex = ammoTypes.size() - 1;
+        if (newIndex >= ammoTypes.size()) newIndex = 0;
+
+        pickable.setPickedAmmoType(stack, ammoTypes.get(newIndex));
+    }
     
     @Override
     public boolean isSneaking()
diff --git a/src/main/java/net/minecraft/client/gui/hud/AmmoPickerComponent.java b/src/main/java/net/minecraft/client/gui/hud/AmmoPickerComponent.java
new file mode 100644
index 000000000..86b4cdf25
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/hud/AmmoPickerComponent.java
@@ -0,0 +1,142 @@
+package net.minecraft.client.gui.hud;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.render.Lighting;
+import net.minecraft.client.render.item.model.ItemModel;
+import net.minecraft.client.render.item.model.ItemModelDispatcher;
+import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.core.item.IAmmoPickable;
+import net.minecraft.core.item.Item;
+import net.minecraft.core.item.ItemStack;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AmmoPickerComponent
+    extends MovableHudComponent {
+    private final List<ItemStack> PREVIEW_AMMO_TYPES = new ArrayList<>();
+
+    private long visibleTime = 0L;
+
+    public AmmoPickerComponent(String key, Layout layout) {
+        super(key, 16, 48, layout);
+
+        PREVIEW_AMMO_TYPES.add(new ItemStack(Item.ammoArrow));
+        PREVIEW_AMMO_TYPES.add(new ItemStack(Item.ammoArrowGold));
+        PREVIEW_AMMO_TYPES.add(new ItemStack(Item.armorQuiverGold));
+    }
+
+    public void show() {
+        visibleTime = System.currentTimeMillis() + 1000;
+    }
+
+    private float getOpacity() {
+        long timeRemaining = visibleTime - System.currentTimeMillis();
+        if (timeRemaining <= 0) return 0.0f;
+        if (timeRemaining >= 250) return 1.0f;
+
+        return timeRemaining / 250f;
+    }
+
+    @Override
+    public boolean isVisible(Minecraft mc) {
+        return System.currentTimeMillis() < visibleTime && mc.gameSettings.immersiveMode.drawHotbar();
+    }
+
+    @Override
+    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+        int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
+        int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
+
+        ItemStack stack = mc.thePlayer.getHeldItem();
+        if (stack == null) {
+            visibleTime = 0;
+            return;
+        }
+
+        Item item = stack.getItem();
+        if (!(item instanceof IAmmoPickable)) {
+            visibleTime = 0;
+            return;
+        }
+
+        IAmmoPickable pickable = (IAmmoPickable) item;
+        List<ItemStack> ammoTypes = pickable.getPresentAmmoTypes(mc.thePlayer);
+        if (ammoTypes.isEmpty()) {
+            visibleTime = 0;
+            return;
+        }
+
+        int pickedIndex = ammoTypes.indexOf(pickable.getPickedAmmoType(stack));
+        if (pickedIndex < 0) pickedIndex = 0;
+        int prevIndex = getPrevItemIndex(pickedIndex, ammoTypes.size());
+        int nextIndex = getNextItemIndex(pickedIndex, ammoTypes.size());
+
+        ItemStack pickedAmmo = ammoTypes.get(pickedIndex);
+        ItemStack prevAmmo = ammoTypes.get(prevIndex);
+        ItemStack nextAmmo = ammoTypes.get(nextIndex);
+
+        GL11.glEnable(GL11.GL_DEPTH_TEST);
+        GL11.glDisable(GL11.GL_BLEND);
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+        Lighting.enableInventoryLight();
+
+        float opacity = getOpacity();
+
+        renderItem(mc, prevAmmo, x, y, 0.5f * opacity);
+        renderItem(mc, pickedAmmo, x, y + 16, 1.0f * opacity);
+        renderItem(mc, nextAmmo, x, y + 32, 0.5f * opacity);
+
+        Lighting.disable();
+    }
+
+    @Override
+    public void renderPreview(Minecraft mc, Gui gui, Layout layout, int xSizeScreen, int ySizeScreen) {
+        int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
+        int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
+
+        int pickedIndex = 1;
+        int prevIndex = getPrevItemIndex(pickedIndex, PREVIEW_AMMO_TYPES.size());
+        int nextIndex = getNextItemIndex(pickedIndex, PREVIEW_AMMO_TYPES.size());
+
+        ItemStack pickedAmmo = PREVIEW_AMMO_TYPES.get(pickedIndex);
+        ItemStack prevAmmo = PREVIEW_AMMO_TYPES.get(prevIndex);
+        ItemStack nextAmmo = PREVIEW_AMMO_TYPES.get(nextIndex);
+
+        GL11.glEnable(GL11.GL_DEPTH_TEST);
+        GL11.glDisable(GL11.GL_BLEND);
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+        Lighting.enableInventoryLight();
+
+        GL11.glEnable(GL11.GL_DEPTH_TEST);
+        GL11.glDisable(GL11.GL_BLEND);
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+        Lighting.enableInventoryLight();
+
+        renderItem(mc, prevAmmo, x, y, 0.5f);
+        renderItem(mc, pickedAmmo, x, y + 16, 1.0f);
+        renderItem(mc, nextAmmo, x, y + 32, 0.5f);
+
+        Lighting.disable();
+    }
+
+    private void renderItem(Minecraft mc, ItemStack itemStack, int x, int y, float alpha) {
+        ItemModel itemModel = ItemModelDispatcher.getInstance().getDispatch(itemStack.getItem());
+        itemModel.renderItemIntoGui(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemStack, x, y, alpha);
+    }
+
+    private int getNextItemIndex(int pickedIndex, int listLength) {
+        return (pickedIndex + 1) % listLength;
+    }
+
+    private int getPrevItemIndex(int pickedIndex, int listLength) {
+        if (pickedIndex - 1 < 0) {
+            return listLength - 1;
+        }
+        return (pickedIndex - 1) % listLength;
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/hud/HudComponents.java b/src/main/java/net/minecraft/client/gui/hud/HudComponents.java
index 32bbb9f9b..887514243 100644
--- a/src/main/java/net/minecraft/client/gui/hud/HudComponents.java
+++ b/src/main/java/net/minecraft/client/gui/hud/HudComponents.java
@@ -58,4 +58,5 @@ public class HudComponents {
     public static final HudComponent OXYGEN_BAR = register(new OxygenBarComponent("oxygen_bar", new SnapLayout(HEALTH_BAR, ComponentAnchor.TOP_LEFT, ComponentAnchor.BOTTOM_LEFT)));
     public static final HudComponent FIRE_BAR = register(new FireBarComponent("fire_bar", new SnapLayout(OXYGEN_BAR, ComponentAnchor.TOP_LEFT, ComponentAnchor.BOTTOM_LEFT)));
     public static final HudComponent ROTATION_LOCK = register(new RotationLockComponent("rotation_lock", new SnapLayout(CROSSHAIR, ComponentAnchor.CENTER_RIGHT, ComponentAnchor.CENTER_LEFT)));
+    public static final HudComponent AMMO_PICKER = register(new AmmoPickerComponent("ammo_picker", new SnapLayout(CROSSHAIR, ComponentAnchor.CENTER_LEFT, ComponentAnchor.CENTER_RIGHT)));
 }
diff --git a/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java b/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
index 67b2fcc20..c59d6a95a 100644
--- a/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
+++ b/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
@@ -150,6 +150,7 @@ public abstract class OptionsPages
             .withComponent(new KeyBindingComponent(mc.gameSettings.keyChat))
             .withComponent(new KeyBindingComponent(mc.gameSettings.keyCommand))
             .withComponent(new KeyBindingComponent(mc.gameSettings.keyGuidebook))
+            .withComponent(new KeyBindingComponent(mc.gameSettings.keyPickAmmo))
             .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowRecipe))
             .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowUsage))
             .withComponent(new KeyBindingComponent(mc.gameSettings.keyPlayerList))
diff --git a/src/main/java/net/minecraft/client/option/GameSettings.java b/src/main/java/net/minecraft/client/option/GameSettings.java
index 982b055f1..fdb789847 100644
--- a/src/main/java/net/minecraft/client/option/GameSettings.java
+++ b/src/main/java/net/minecraft/client/option/GameSettings.java
@@ -213,6 +213,7 @@ public class GameSettings {
 	public KeyBinding keySprint = new KeyBinding("key.sprint").bindKeyboard(KEY_NONE);
 	public KeyBinding keyToggleDebug = new KeyBinding("key.toggleDebug").bindKeyboard(KEY_F3);
 	public KeyBinding keyToggleOverlay = new KeyBinding("key.toggleOverlay").bindKeyboard(KEY_F4);
+	public KeyBinding keyPickAmmo = new KeyBinding("key.pickAmmo").bindKeyboard(KEY_LMENU);
 
 	public KeyBinding[] keys = ReflectUtils.getAllObjects(GameSettings.class, KeyBinding.class, this);
 
diff --git a/src/main/java/net/minecraft/client/option/enums/LightmapStyle.java b/src/main/java/net/minecraft/client/option/enums/LightmapStyle.java
index c9bf9f812..2126ba431 100644
--- a/src/main/java/net/minecraft/client/option/enums/LightmapStyle.java
+++ b/src/main/java/net/minecraft/client/option/enums/LightmapStyle.java
@@ -2,7 +2,7 @@ package net.minecraft.client.option.enums;
 
 public enum LightmapStyle {
     GRAY("options.lightmapStyle.gray"),
-    COSY("options.lightmapStyle.cosy"),
+    COLORIZED("options.lightmapStyle.colorized"),
     DISABLED("options.lightmapStyle.disabled");
 
     private final String translationKey;
diff --git a/src/main/java/net/minecraft/client/render/LightmapHelper.java b/src/main/java/net/minecraft/client/render/LightmapHelper.java
index ec161011e..9ec4299b9 100644
--- a/src/main/java/net/minecraft/client/render/LightmapHelper.java
+++ b/src/main/java/net/minecraft/client/render/LightmapHelper.java
@@ -99,8 +99,8 @@ public class LightmapHelper {
 			}else {
 				LightmapStyle lightmapStyle = mc.gameSettings.lightmapStyle.value;
 				
-				if(lightmapStyle == LightmapStyle.COSY) {
-					generateCosyLightmap(world, partialTicks);
+				if(lightmapStyle == LightmapStyle.COLORIZED) {
+					generateColorizedLightmap(world, partialTicks);
 				}else if(lightmapStyle == LightmapStyle.GRAY) {
 					generateGrayLightmap(world, partialTicks);
 				}
@@ -187,7 +187,7 @@ public class LightmapHelper {
 		}
 	}
 	
-	public void generateCosyLightmap(World world, float partialTicks) {
+	public void generateColorizedLightmap(World world, float partialTicks) {
 		float ambientBrightness = world.getAmbientBrightness(partialTicks);
 		float brightness = mc.gameSettings.brightness.value - 0.5f;
 
@@ -282,8 +282,8 @@ public class LightmapHelper {
 		ByteBuffer buffer = Buffer.buffer;
 		buffer.clear();
 
-		for(int i = 0; i < lightmapData.length; i++) {
-			int color = lightmapData[i];
+		for(int i = 0; i < data.length; i++) {
+			int color = data[i];
 
 			int a = color >> 24;
 			int r = (color >> 16) & 0xFF;
diff --git a/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java b/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java
index 5174775ed..0ec8ed312 100644
--- a/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java
+++ b/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java
@@ -21,13 +21,13 @@ public final class BlockColorDispatcher
         addDispatch(Block.fluidWaterStill, new BlockColorCustom(Colorizers.water));
         addDispatch(Block.fluidWaterFlowing, new BlockColorCustom(Colorizers.water));
         addDispatch(Block.grass, new BlockColorCustom(Colorizers.grass));
-        addDispatch(Block.layerLeavesOak, new BlockColorLeavesOak(Colorizers.oak));
+        addDispatch(Block.layerLeavesOak, new BlockColorCustom(Colorizers.oak));
         addDispatch(Block.leavesBirch, new BlockColorCustom(Colorizers.birch));
         addDispatch(Block.leavesCherry, new BlockColorCustom(Colorizers.cherry));
         addDispatch(Block.leavesCherryFlowering, new BlockColorCustom(Colorizers.cherry));
         addDispatch(Block.leavesEucalyptus, new BlockColorCustom(Colorizers.eucalyptus));
         addDispatch(Block.leavesCacao, new BlockColorCustom(Colorizers.cacao));
-        addDispatch(Block.leavesOak, new BlockColorLeavesOak(Colorizers.oak));
+        addDispatch(Block.leavesOak, new BlockColorCustom(Colorizers.oak));
         addDispatch(Block.leavesPine, new BlockColorCustom(Colorizers.pine));
         addDispatch(Block.leavesShrub, new BlockColorCustom(Colorizers.shrub));
         addDispatch(Block.leavesThorn, new BlockColorCustom(Colorizers.thorn));
diff --git a/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java b/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
index 96c130303..bc59af80c 100644
--- a/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
+++ b/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
@@ -79,6 +79,7 @@ public class ItemModelBow extends ItemModelStandard {
         }
         super.renderItemIntoGui(tessellator, fontrenderer, renderengine, itemStack, x, y, brightness, alpha);
     }
+
     public Item getNextArrow(EntityPlayer player){
         if (player instanceof EntityOtherPlayerMP){
             int id = player.getArrowId();
@@ -87,6 +88,7 @@ public class ItemModelBow extends ItemModelStandard {
         }
         return player.getNextArrow();
     }
+
     @Override
     public void heldTransformThirdPerson(ItemRenderer renderer, Entity entity, ItemStack itemStack) {
         GL11.glTranslatef(0.0F, 0.125F, 0.3125F);
diff --git a/src/main/java/net/minecraft/core/block/BlockGrass.java b/src/main/java/net/minecraft/core/block/BlockGrass.java
index fe1d7d72e..95f121127 100644
--- a/src/main/java/net/minecraft/core/block/BlockGrass.java
+++ b/src/main/java/net/minecraft/core/block/BlockGrass.java
@@ -7,9 +7,6 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.data.gamerule.GameRules;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.util.helper.Axis;
-import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.biome.Biomes;
@@ -54,7 +51,7 @@ public class BlockGrass extends Block
             {
                 world.setBlockWithNotify(l, i1, j1, this.id);
             }
-            if (world.getGameRule(GameRules.DO_SEASONAL_GROWTH) && world.getBlockId(x, y + 1, z) == 0 && world.getSeasonManager().getCurrentSeason() != null && world.getSeasonManager().getCurrentSeason().growFlowers && rand.nextInt(256) == 0)
+            if (world.getGameRuleValue(GameRules.DO_SEASONAL_GROWTH) && world.getBlockId(x, y + 1, z) == 0 && world.getSeasonManager().getCurrentSeason() != null && world.getSeasonManager().getCurrentSeason().growFlowers && rand.nextInt(256) == 0)
             {
                 int idToSpawn = 0;
                 int r = rand.nextInt(400);
diff --git a/src/main/java/net/minecraft/core/block/BlockMotionSensor.java b/src/main/java/net/minecraft/core/block/BlockMotionSensor.java
index eccff28f3..632843ee6 100644
--- a/src/main/java/net/minecraft/core/block/BlockMotionSensor.java
+++ b/src/main/java/net/minecraft/core/block/BlockMotionSensor.java
@@ -1,17 +1,18 @@
 
 package net.minecraft.core.block;
 
-import net.minecraft.core.enums.EnumDropCause;
-import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.util.helper.Color;
+import java.util.Random;
+
 import net.minecraft.client.util.helper.Colors;
-import net.minecraft.core.world.WorldSource;
-import net.minecraft.core.world.World;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntitySensor;
 import net.minecraft.core.block.material.Material;
-
-import java.util.Random;
+import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.helper.Color;
+import net.minecraft.core.util.helper.Direction;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.WorldSource;
 
 // Referenced classes of package net.minecraft.src:
 //            Block, Material, World, Item,
@@ -19,6 +20,7 @@ import java.util.Random;
 
 public class BlockMotionSensor extends BlockTileEntityRotatable
 {
+    public final boolean isActive;
 
     public BlockMotionSensor(String key, int id, boolean isActive)
     {
@@ -43,22 +45,15 @@ public class BlockMotionSensor extends BlockTileEntityRotatable
         spawnParticles(world, x, y, z);
     }
 
-    public static void updateSensorBlockState(boolean flag, World world, int x, int y, int z)
-    {
-        int l = world.getBlockMetadata(x, y, z);
-
-        if(flag)
-        {
-            world.setBlockWithNotify(x, y, z, Block.motionsensorActive.id);
-        }
-        if(!flag)
-        {
-            world.setBlockWithNotify(x, y, z, Block.motionsensorIdle.id);
-        }
-        world.setBlockMetadataWithNotify(x, y, z, l);
-
-
-    }
+	public static void updateSensorBlockState(boolean active, World world, int x, int y, int z) {
+		int meta = world.getBlockMetadata(x, y, z);
+		if(active) {
+			world.setBlockWithNotify(x, y, z, Block.motionsensorActive.id);
+		}else {
+			world.setBlockWithNotify(x, y, z, Block.motionsensorIdle.id);
+		}
+		world.setBlockMetadataWithNotify(x, y, z, meta);
+	}
 
 	private void spawnParticles(World world, int x, int y, int z) {
 		Random random = world.rand;
@@ -127,7 +122,13 @@ public class BlockMotionSensor extends BlockTileEntityRotatable
                 return null;
         }
     }
-
-    public final boolean isActive;
+    
+    public static Direction getFacingDirection(int meta) {
+    	if(meta == 2) return Direction.NORTH;
+    	if(meta == 3) return Direction.SOUTH;
+    	if(meta == 4) return Direction.WEST;
+    	if(meta == 5) return Direction.EAST;
+    	return Direction.NONE;
+    }
 
 }
diff --git a/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java b/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
index 8acd2777e..40b63c8ca 100644
--- a/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
+++ b/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
@@ -1,119 +1,95 @@
 package net.minecraft.core.block.entity;
 
+import java.util.List;
+
 import net.minecraft.core.achievement.AchievementList;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockMotionSensor;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.EntityPlayer;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.sound.SoundCategory;
+import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 
-import java.util.List;
-import java.util.Random;
-
-public class TileEntitySensor extends TileEntity
-{
-    public TileEntitySensor() { }
-
-    private int getSightRange(World world, int x, int y, int z, int metadata)
-    {
-        // Determine facing direction for sensor
-        int dx = 0;
-        int dz = 0;
-        switch (metadata)
-        {
-            case 2: // 0b00000010
-                dz = -1;
-                break;
-            case 3: // 0b00000011
-                dz = 1;
-                break;
-            case 4: // 0b00000100
-                dx = -1;
-                break;
-            case 5: // 0b00000101
-                dx = 1;
-                break;
-            default: // Error
-                return 0;
-        }
-
-        // Determine range
-        int range = 2;
-        Block blockInFront = world.getBlock(x + dx, y, z + dz);
-        if (blockInFront != null && blockInFront.hasTag(BlockTags.EXTENDS_MOTION_SENSOR_RANGE))
-        {
-            range = 5;
-        }
-
-        // Determine effective range
-        for (int i = 0; i < range; i++)
-        {
-            if (world.isBlockOpaqueCube(x + dx + (i * dx), y, z + dz + (i * dz)))
-            {
-                return i;
-            }
-        }
+public class TileEntitySensor extends TileEntity {
 
-        return range;
-    }
+	private int getSightRange(World world, int x, int y, int z, Direction facing) {
+		if(facing == Direction.NONE) {
+			return 0;
+		}
+		
+		int range = 2;
+		int blockInFront = world.getBlockId(x + facing.getOffsetX(), y + facing.getOffsetY(), z + facing.getOffsetZ());
+		if(Block.hasTag(blockInFront, BlockTags.EXTENDS_MOTION_SENSOR_RANGE)) {
+			range = 5;
+		}
+		
+		for(int i = 1; i <= range; i++) {
+			int x1 = x + facing.getOffsetX() * i;
+			int y1 = y + facing.getOffsetY() * i;
+			int z1 = z + facing.getOffsetZ() * i;
+			int id = world.getBlockId(x1, y1, z1);
+			if(Block.solid[id] && !Block.hasTag(id, BlockTags.EXTENDS_MOTION_SENSOR_RANGE)) {
+				return i - 1;
+			}
+		}
+		
+		return range;
+	}
 
-    private AABB getDetectionBox(int x, int y, int z, int metadata, int effectiveRange)
-    {
-        if (metadata == 2)
-        {
-            return AABB.getBoundingBoxFromPool(x, y, z - effectiveRange, x + 1, (float) y + 1, z + 1);
-        }
-        else if (metadata == 3)
-        {
-            return AABB.getBoundingBoxFromPool(x, y, z, x + 1, (float) y + 1, z + 1 + effectiveRange);
-        }
-        else if (metadata == 4)
-        {
-            return AABB.getBoundingBoxFromPool(x - effectiveRange, y, z, x + 1, (float) y + 1, z + 1);
-        }
-        else
-        {
-            return AABB.getBoundingBoxFromPool(x, y, z, x + 1 + effectiveRange, (float) y + 1, z + 1);
-        }
-    }
+	private AABB getDetectionBox(int x, int y, int z, Direction facing, int range) {
+		int x1 = x + facing.getOffsetX();
+		int y1 = y + facing.getOffsetY();
+		int z1 = z + facing.getOffsetZ();
+		
+		int x2 = x + facing.getOffsetX() * range;
+		int y2 = y + facing.getOffsetY() * range;
+		int z2 = z + facing.getOffsetZ() * range;
+		
+		int minX = Math.min(x1, x2);
+		int minY = Math.min(y1, y2);
+		int minZ = Math.min(z1, z2);
+		
+		int maxX = Math.max(x1, x2) + 1;
+		int maxY = Math.max(y1, y2) + 1;
+		int maxZ = Math.max(z1, z2) + 1;
+		
+		return AABB.getBoundingBoxFromPool(minX, minY, minZ, maxX, maxY, maxZ);
+	}
 
-    @Override
-	public void tick()
-    {
-        if (worldObj != null && !worldObj.isClientSide)
-        {
-            boolean shouldBeActive = false;
-            int metadata = worldObj.getBlockMetadata(x, y, z);
-            int effectiveRange = getSightRange(worldObj, x, y, z, metadata);
-            if (effectiveRange > 0)
-            {
-                AABB detectionBox = getDetectionBox(x, y, z, metadata, effectiveRange);
-                List<Entity> list = worldObj.getEntitiesWithinAABB(Entity.class, detectionBox);
-                if (!list.isEmpty())
-                {
-                    // Trigger achievements
-                    for (Entity e : list)
-                    {
-                        if (e instanceof EntityPlayer)
-                        {
-                            ((EntityPlayer) e).triggerAchievement(AchievementList.GET_SENSED);
-                        }
-                    }
-                    shouldBeActive = true;
-                }
-            }
-            if (shouldBeActive && worldObj.getBlockId(x, y, z) != Block.motionsensorActive.id)
-            {
-                worldObj.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "random.breath", 0.5F, worldObj.rand.nextFloat());
-                BlockMotionSensor.updateSensorBlockState(true, worldObj, x, y, z);
-            }
-            if (!shouldBeActive && worldObj.getBlockId(x, y, z) != Block.motionsensorIdle.id)
-            {
-                BlockMotionSensor.updateSensorBlockState(false, worldObj, x, y, z);
-            }
-        }
-    }
+	@Override
+	public void tick() {
+		if(worldObj == null || worldObj.isClientSide) {
+			return;
+		}
+		
+		int id = worldObj.getBlockId(x, y, z);
+		int meta = worldObj.getBlockMetadata(x, y, z);
+		
+		boolean shouldBeActive = false;
+		Direction facing = BlockMotionSensor.getFacingDirection(meta);
+		int effectiveRange = getSightRange(worldObj, x, y, z, facing);
+		if(effectiveRange > 0) {
+			AABB detectionBox = getDetectionBox(x, y, z, facing, effectiveRange);
+			List<Entity> list = worldObj.getEntitiesWithinAABBExcludingEntity(null, detectionBox);
+			for(int i=0; i < list.size(); i++) {
+				Entity entity = list.get(i);
+				if(entity instanceof EntityPlayer) {
+					EntityPlayer player = (EntityPlayer) entity;
+					player.triggerAchievement(AchievementList.GET_SENSED);
+				}
+				shouldBeActive = true;
+			}
+		}
+		
+		if(shouldBeActive && id == Block.motionsensorIdle.id) {
+			worldObj.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, x + 0.5, y + 0.5, z + 0.5, "random.breath", 0.5f, worldObj.rand.nextFloat());
+			BlockMotionSensor.updateSensorBlockState(true, worldObj, x, y, z);
+		}
+		if(!shouldBeActive && id == Block.motionsensorActive.id) {
+			BlockMotionSensor.updateSensorBlockState(false, worldObj, x, y, z);
+		}
+	}
 }
diff --git a/src/main/java/net/minecraft/core/data/gamerule/GameRules.java b/src/main/java/net/minecraft/core/data/gamerule/GameRules.java
index 5099773f6..2c19c2f27 100644
--- a/src/main/java/net/minecraft/core/data/gamerule/GameRules.java
+++ b/src/main/java/net/minecraft/core/data/gamerule/GameRules.java
@@ -13,6 +13,7 @@ public abstract class GameRules
     public static GameRuleBoolean DWARF_MODE = register(new GameRuleBoolean("dwarfMode", false));
     public static GameRuleBoolean MOB_GRIEFING = register(new GameRuleBoolean("mobGriefing", true));
     public static GameRuleBoolean DO_DAY_CYCLE = register(new GameRuleBoolean("doDaylightCycle", true));
+    public static GameRuleBoolean INSTANT_HEALING = register(new GameRuleBoolean("instantHealing", false));
 
     public static <T extends GameRule<?>> T register(T gameRule)
     {
diff --git a/src/main/java/net/minecraft/core/entity/EntityLiving.java b/src/main/java/net/minecraft/core/entity/EntityLiving.java
index 128369d58..eb89adc33 100644
--- a/src/main/java/net/minecraft/core/entity/EntityLiving.java
+++ b/src/main/java/net/minecraft/core/entity/EntityLiving.java
@@ -8,6 +8,7 @@ import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.data.gamerule.GameRules;
 import net.minecraft.core.entity.player.EntityPlayer;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.enums.PlacementMode;
@@ -404,7 +405,7 @@ public abstract class EntityLiving extends Entity
 
     public void eatFood(ItemFood food) {
         if (food == null) return;
-        if (food.getTicksPerHeal() == 0) {
+        if (food.getTicksPerHeal() == 0 || world.getGameRuleValue(GameRules.INSTANT_HEALING)) {
             heal(food.getHealAmount());
         } else {
             if (consumedFood.containsKey(food)) {
diff --git a/src/main/java/net/minecraft/core/entity/player/EntityPlayer.java b/src/main/java/net/minecraft/core/entity/player/EntityPlayer.java
index f9366a192..fbfd338d2 100644
--- a/src/main/java/net/minecraft/core/entity/player/EntityPlayer.java
+++ b/src/main/java/net/minecraft/core/entity/player/EntityPlayer.java
@@ -32,6 +32,7 @@ import net.minecraft.core.entity.vehicle.EntityMinecart;
 import net.minecraft.core.enums.ArtType;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.enums.EnumSleepStatus;
+import net.minecraft.core.item.IAmmoPickable;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.tool.ItemToolSword;
@@ -97,7 +98,7 @@ public abstract class EntityPlayer extends EntityLiving
     }
 
     private void setupDwarfMode() {
-        boolean dwarfModeEnabled = world.getGameRule(GameRules.DWARF_MODE);
+        boolean dwarfModeEnabled = world.getGameRuleValue(GameRules.DWARF_MODE);
         if (dwarfModeEnabled && !isDwarf) {
             setSize(0.6f, 1.0f - 0.2f);
             heightOffset = 1.0F - 0.38F;
@@ -293,7 +294,7 @@ public abstract class EntityPlayer extends EntityLiving
     @Override
     public void playHurtSound() {
     	float pitch = 1.0f;
-    	if(world.getGameRule(GameRules.DWARF_MODE)) {
+    	if(world.getGameRuleValue(GameRules.DWARF_MODE)) {
     		pitch = 2.0f;
     	}
         world.playSoundAtEntity(null, this, getHurtSound(), getSoundVolume(), (random.nextFloat() - random.nextFloat()) * 0.2F + pitch);
@@ -302,7 +303,7 @@ public abstract class EntityPlayer extends EntityLiving
     @Override
     public void playDeathSound() {
     	float pitch = 1.0f;
-    	if(world.getGameRule(GameRules.DWARF_MODE)) {
+    	if(world.getGameRuleValue(GameRules.DWARF_MODE)) {
     		pitch = 2.0f;
     	}
         world.playSoundAtEntity(null, this, getDeathSound(), getSoundVolume(), (random.nextFloat() - random.nextFloat()) * 0.2F + pitch);
@@ -343,7 +344,7 @@ public abstract class EntityPlayer extends EntityLiving
         {
             dropPlayerItemWithRandomChoice(new ItemStack(Item.sign, 1), true);
         }
-        if (!world.getGameRule(GameRules.KEEP_INVENTORY))
+        if (!world.getGameRuleValue(GameRules.KEEP_INVENTORY))
         {
             craftingInventory.onCraftGuiClosed(this);
             inventory.dropAllItems();
@@ -860,7 +861,7 @@ public abstract class EntityPlayer extends EntityLiving
                     setPlayerSpawnCoordinate(new ChunkCoordinates(x, y, z));
                 }
             }
-            if (!world.getGameRule(GameRules.ALLOW_SLEEPING))
+            if (!world.getGameRuleValue(GameRules.ALLOW_SLEEPING))
             {
 				sendStatusMessage(I18n.getInstance().translateKey("bed.noAllowSleeping"));
                 return EnumSleepStatus.DISABLED_BY_GAMERULE;
@@ -1347,23 +1348,20 @@ public abstract class EntityPlayer extends EntityLiving
         inventory.setInventorySlotContents(slot1, stack2);
     }
     public Item getNextArrow(){
-        Item nextArrow = null;
-        ItemStack quiverSlot = inventory.armorItemInSlot(2);
-        if(quiverSlot != null && quiverSlot.itemID == Item.armorQuiver.id && quiverSlot.getMetadata() < quiverSlot.getMaxDamage()){
-            nextArrow = Item.ammoArrow;
-        }
-        else if(quiverSlot != null && quiverSlot.itemID == Item.armorQuiverGold.id){
-            nextArrow = Item.ammoArrowPurple;
-        }
-        else if (hasItem(Item.ammoArrowGold))
-        {
-            nextArrow = Item.ammoArrowGold;
+        ItemStack heldItem = getHeldItem();
+        if (heldItem.itemID != Item.toolBow.id) return null;
+
+        IAmmoPickable pickable = ((IAmmoPickable) Item.toolBow);
+        ItemStack ammoType = pickable.getPickedAmmoType(heldItem);
+
+        if (ammoType.itemID == Item.armorQuiver.id) {
+            return Item.ammoArrow;
         }
-        else if(hasItem(Item.ammoArrow))
-        {
-            nextArrow = Item.ammoArrow;
+        if (ammoType.itemID == Item.armorQuiverGold.id) {
+            return Item.ammoArrowPurple;
         }
-        return nextArrow;
+
+        return ammoType.getItem();
     }
     public int getArrowId(){
         return entityData.getInt(18);
diff --git a/src/main/java/net/minecraft/core/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/core/entity/projectile/EntityFireball.java
index 251f33b33..f93236416 100644
--- a/src/main/java/net/minecraft/core/entity/projectile/EntityFireball.java
+++ b/src/main/java/net/minecraft/core/entity/projectile/EntityFireball.java
@@ -21,6 +21,12 @@ public class EntityFireball extends EntityProjectile
         super(world);
         setSize(1.0F, 1.0F);
     }
+
+    public EntityFireball(World world, EntityLiving owner) {
+        super(world, owner);
+        setSize(1.0F, 1.0F);
+    }
+
     public EntityFireball(World world, double x, double y, double z,
             double vX, double vY, double vZ)
     {
diff --git a/src/main/java/net/minecraft/core/item/IAmmoPickable.java b/src/main/java/net/minecraft/core/item/IAmmoPickable.java
new file mode 100644
index 000000000..55bea82c4
--- /dev/null
+++ b/src/main/java/net/minecraft/core/item/IAmmoPickable.java
@@ -0,0 +1,46 @@
+package net.minecraft.core.item;
+
+import net.minecraft.core.entity.player.EntityPlayer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface IAmmoPickable {
+    List<ItemStack> getAmmoTypes();
+
+    default List<ItemStack> getPresentAmmoTypes(EntityPlayer player) {
+        List<ItemStack> filteredList = new ArrayList<>();
+        List<ItemStack> ammoTypes = getAmmoTypes();
+
+        for (ItemStack ammoType : ammoTypes) {
+            if (hasAmmoType(player, ammoType)) {
+                filteredList.add(ammoType);
+            }
+        }
+
+        return filteredList;
+    }
+
+    default boolean isAmmoType(ItemStack stack) {
+        List<ItemStack> ammoTypes = this.getAmmoTypes();
+        for (ItemStack ammoType : ammoTypes) {
+            if (ammoType.isItemEqual(stack)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    default boolean hasAmmoType(EntityPlayer player, ItemStack ammoType) {
+        return player.inventory.containsItem(ammoType);
+    }
+
+    void setPickedAmmoType(ItemStack itemStack, ItemStack ammoType);
+
+    ItemStack getPickedAmmoType(ItemStack itemStack);
+
+    default ItemStack getDefaultAmmoType() {
+        return getAmmoTypes().get(0);
+    }
+}
diff --git a/src/main/java/net/minecraft/core/item/Item.java b/src/main/java/net/minecraft/core/item/Item.java
index c2b1306ca..e29a0eaf4 100644
--- a/src/main/java/net/minecraft/core/item/Item.java
+++ b/src/main/java/net/minecraft/core/item/Item.java
@@ -441,6 +441,13 @@ public class Item
     static 
     {
         StatList.onItemInit();
+
+        ((ItemBow) toolBow).addAmmoType(new ItemStack(ammoArrow));
+        ((ItemBow) toolBow).addAmmoType(new ItemStack(ammoArrowGold));
+        ((ItemBow) toolBow).addAmmoType(new ItemStack(armorQuiver));
+        ((ItemBow) toolBow).addAmmoType(new ItemStack(armorQuiverGold));
+
+        ((ItemHandCannonUnloaded) handcannonUnloaded).addAmmoType(new ItemStack(ammoChargeExplosive));
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/item/ItemBow.java b/src/main/java/net/minecraft/core/item/ItemBow.java
index 6df182e85..e41bf25e9 100644
--- a/src/main/java/net/minecraft/core/item/ItemBow.java
+++ b/src/main/java/net/minecraft/core/item/ItemBow.java
@@ -1,18 +1,22 @@
 
 package net.minecraft.core.item;
 
-// Referenced classes of package net.minecraft.src:
-//            Item, EntityPlayer, InventoryPlayer, World, 
-//            EntityArrow, ItemStack
-
+import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.entity.projectile.EntityArrow;
 import net.minecraft.core.entity.projectile.EntityArrowGolden;
 import net.minecraft.core.entity.projectile.EntityArrowPurple;
 import net.minecraft.core.entity.player.EntityPlayer;
 import net.minecraft.core.world.World;
 
-public class ItemBow extends Item
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ItemBow
+    extends Item
+    implements IAmmoPickable
 {
+    protected final List<ItemStack> AMMO_TYPES = new ArrayList<>();
 
     public ItemBow(String name, int id)
     {
@@ -21,43 +25,112 @@ public class ItemBow extends Item
         setMaxDamage(384);
     }
 
+    public void addAmmoType(ItemStack stack) {
+        stack.stackSize = 1;
+        for (ItemStack ammoType : AMMO_TYPES) {
+            if (ammoType.isItemEqual(stack)) {
+                return;
+            }
+        }
+        AMMO_TYPES.add(stack);
+    }
+
     @Override
     public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
     {
-        ItemStack quiverSlot = entityplayer.inventory.armorItemInSlot(2);
-        if(quiverSlot != null && quiverSlot.itemID == Item.armorQuiver.id && quiverSlot.getMetadata() < quiverSlot.getMaxDamage()){
-            entityplayer.inventory.armorItemInSlot(2).damageItem(1, entityplayer);
-            itemstack.damageItem(1, entityplayer);
-            world.playSoundAtEntity(entityplayer, entityplayer, "random.bow", 0.3f, 1.0F / (itemRand.nextFloat() * 0.4F + 0.8F));
-            if (!world.isClientSide) {
-                world.entityJoinedWorld(new EntityArrow(world, entityplayer, true, 0));
-            }
+        ItemStack ammoType = getPickedAmmoType(itemstack);
+        if (!hasAmmoType(entityplayer, ammoType)) {
+            List<ItemStack> filteredList = getPresentAmmoTypes(entityplayer);
+            if (filteredList.isEmpty()) return itemstack;
+            ammoType = filteredList.get(0);
+            setPickedAmmoType(itemstack, ammoType);
         }
-        else if(quiverSlot != null && quiverSlot.itemID == Item.armorQuiverGold.id){
-            itemstack.damageItem(1, entityplayer);
-            world.playSoundAtEntity(entityplayer, entityplayer, "random.bow", 0.3f, 1.0F / (itemRand.nextFloat() * 0.4F + 0.8F));
-            if (!world.isClientSide) {
-                world.entityJoinedWorld(new EntityArrowPurple(world, entityplayer, false));
+
+        if (ammoType.itemID != Item.armorQuiver.id && ammoType.itemID != Item.armorQuiverGold.id) {
+            if (!entityplayer.inventory.consumeInventoryItem(ammoType.itemID)) {
+                return itemstack;
             }
         }
-        else if (entityplayer.inventory.consumeInventoryItem(Item.ammoArrowGold.id))
-        {
-            itemstack.damageItem(1, entityplayer);
-            world.playSoundAtEntity(entityplayer, entityplayer, "random.bow", 0.3f, 1.0F / (itemRand.nextFloat() * 0.4F + 0.8F));
-            if(!world.isClientSide)
-            {
-                world.entityJoinedWorld(new EntityArrowGolden(world, entityplayer, true));
-            }
+
+        itemstack.damageItem(1, entityplayer);
+        world.playSoundAtEntity(entityplayer, entityplayer, "random.bow", 0.3f, 1.0F / (itemRand.nextFloat() * 0.4F + 0.8F));
+        if (!world.isClientSide) {
+            handleAmmoFired(ammoType, world, entityplayer);
         }
-        else if(entityplayer.inventory.consumeInventoryItem(Item.ammoArrow.id))
-        {
-            itemstack.damageItem(1, entityplayer);
-            world.playSoundAtEntity(entityplayer, entityplayer, "random.bow", 0.3f, 1.0F / (itemRand.nextFloat() * 0.4F + 0.8F));
-            if(!world.isClientSide)
-            {
-                world.entityJoinedWorld(new EntityArrow(world, entityplayer, true, 0));
-            }
+
+        if (ammoType.itemID == Item.armorQuiver.id) {
+            entityplayer.inventory.armorItemInSlot(2).damageItem(1, entityplayer);
         }
+
         return itemstack;
     }
+
+    private void handleAmmoFired(ItemStack ammoType, World world, EntityPlayer player) {
+        if (ammoType.itemID == Item.ammoArrow.id) {
+            world.entityJoinedWorld(new EntityArrow(world, player, true, 0));
+        } else if (ammoType.itemID == Item.ammoArrowGold.id) {
+            world.entityJoinedWorld(new EntityArrowGolden(world, player, true));
+        } else if (ammoType.itemID == Item.armorQuiver.id) {
+            world.entityJoinedWorld(new EntityArrow(world, player, true, 0));
+        } else if (ammoType.itemID == Item.armorQuiverGold.id) {
+            world.entityJoinedWorld(new EntityArrowPurple(world, player, false));
+        }
+    }
+
+    @Override
+    public boolean hasAmmoType(EntityPlayer player, ItemStack ammoType) {
+        ItemStack quiverSlot = player.inventory.armorItemInSlot(2);
+
+        if (ammoType.itemID == Item.armorQuiver.id) {
+            return quiverSlot != null && quiverSlot.itemID == ammoType.itemID && quiverSlot.getMetadata() < quiverSlot.getMaxDamage();
+        }
+        if (ammoType.itemID == Item.armorQuiverGold.id) {
+            return quiverSlot != null && quiverSlot.itemID == ammoType.itemID;
+        }
+
+        return player.inventory.containsItem(ammoType);
+    }
+
+    @Override
+    public List<ItemStack> getAmmoTypes() {
+        return Collections.unmodifiableList(AMMO_TYPES);
+    }
+
+    @Override
+    public void setPickedAmmoType(ItemStack itemStack, ItemStack ammoType) {
+        CompoundTag tag = itemStack.getData();
+        CompoundTag ammoTag = tag.getCompoundOrDefault("ammo", null);
+        if (ammoTag == null) {
+            ammoTag = new CompoundTag();
+            tag.putCompound("ammo", ammoTag);
+        }
+
+        writeAmmoTypeToTag(ammoType, ammoTag);
+    }
+
+    @Override
+    public ItemStack getPickedAmmoType(ItemStack itemStack) {
+        CompoundTag tag = itemStack.getData();
+        CompoundTag ammoTag = tag.getCompoundOrDefault("ammo", null);
+        if (ammoTag == null) {
+            ammoTag = new CompoundTag();
+            writeAmmoTypeToTag(getDefaultAmmoType(), ammoTag);
+            tag.putCompound("ammo", ammoTag);
+        }
+
+        short id = ammoTag.getShortOrDefault("id", (short) getDefaultAmmoType().itemID);
+
+        for (ItemStack stack : AMMO_TYPES) {
+            if (stack.itemID == id) {
+                return stack;
+            }
+        }
+
+        return getDefaultAmmoType();
+    }
+
+    private void writeAmmoTypeToTag(ItemStack ammoType, CompoundTag ammoTag) {
+        ammoTag.putShort("id", (short) ammoType.itemID);
+    }
+
 }
diff --git a/src/main/java/net/minecraft/core/item/ItemHandCannonLoaded.java b/src/main/java/net/minecraft/core/item/ItemHandCannonLoaded.java
index 13f6cb549..f39cd6cc1 100644
--- a/src/main/java/net/minecraft/core/item/ItemHandCannonLoaded.java
+++ b/src/main/java/net/minecraft/core/item/ItemHandCannonLoaded.java
@@ -1,11 +1,8 @@
 package net.minecraft.core.item;
 
-// Referenced classes of package net.minecraft.src:
-//            Item, EntityPlayer, InventoryPlayer, World,
-//            EntityArrow, ItemStack
-
 import net.minecraft.core.entity.player.EntityPlayer;
 import net.minecraft.core.entity.projectile.EntityCannonball;
+import net.minecraft.core.entity.projectile.EntityFireball;
 import net.minecraft.core.world.World;
 
 public class ItemHandCannonLoaded extends Item
@@ -26,7 +23,7 @@ public class ItemHandCannonLoaded extends Item
 		if(!world.isClientSide)
 		{
 			itemstack.damageItem(1, entityplayer);
-			world.entityJoinedWorld(new EntityCannonball(world, entityplayer));
+			handleAmmoFired(getAmmoType(itemstack), world, entityplayer);
 			if(itemstack.stackSize <= 0) {
 				return null;
 			}
@@ -34,4 +31,14 @@ public class ItemHandCannonLoaded extends Item
 		}
         return itemstack;
     }
+
+	private ItemStack getAmmoType(ItemStack itemStack) {
+		return ((IAmmoPickable) Item.handcannonUnloaded).getPickedAmmoType(itemStack);
+	}
+
+	private void handleAmmoFired(ItemStack ammoType, World world, EntityPlayer player) {
+		if (ammoType.itemID == Item.ammoChargeExplosive.id) {
+			world.entityJoinedWorld(new EntityCannonball(world, player));
+		}
+	}
 }
diff --git a/src/main/java/net/minecraft/core/item/ItemHandCannonUnloaded.java b/src/main/java/net/minecraft/core/item/ItemHandCannonUnloaded.java
index 9319f67e6..dcdb46749 100644
--- a/src/main/java/net/minecraft/core/item/ItemHandCannonUnloaded.java
+++ b/src/main/java/net/minecraft/core/item/ItemHandCannonUnloaded.java
@@ -1,14 +1,18 @@
 package net.minecraft.core.item;
 
-// Referenced classes of package net.minecraft.src:
-//            Item, EntityPlayer, InventoryPlayer, World,
-//            EntityArrow, ItemStack
-
+import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.entity.player.EntityPlayer;
 import net.minecraft.core.world.World;
 
-public class ItemHandCannonUnloaded extends Item
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ItemHandCannonUnloaded
+    extends Item
+    implements IAmmoPickable
 {
+    private final List<ItemStack> AMMO_TYPES = new ArrayList<>();
 
     public ItemHandCannonUnloaded(String name, int id)
     {
@@ -17,14 +21,79 @@ public class ItemHandCannonUnloaded extends Item
         maxStackSize = 1;
     }
 
+    public void addAmmoType(ItemStack stack) {
+        stack.stackSize = 1;
+        for (ItemStack ammoType : AMMO_TYPES) {
+            if (ammoType.isItemEqual(stack)) {
+                return;
+            }
+        }
+        AMMO_TYPES.add(stack);
+    }
+
+    @Override
+    public CompoundTag getDefaultTag() {
+        CompoundTag tag = super.getDefaultTag();
+        CompoundTag ammoTag = new CompoundTag();
+        writeAmmoTypeToTag(getDefaultAmmoType(), ammoTag);
+        tag.putCompound("ammo", ammoTag);
+
+        return tag;
+    }
+
     @Override
     public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
     {
-        if (entityplayer.inventory.consumeInventoryItem(Item.ammoChargeExplosive.id))
+        ItemStack ammoType = getPickedAmmoType(itemstack);
+        if (entityplayer.inventory.consumeInventoryItem(ammoType.itemID))
         {
             world.playSoundAtEntity(entityplayer, entityplayer, "random.click", 1.0F, 1.9F / (itemRand.nextFloat() * 0.2F + 0.4F));
             return new ItemStack(Item.handcannonLoaded, 1, itemstack.getMetadata(), itemstack.getData());
         }
         return itemstack;
     }
+
+    @Override
+    public List<ItemStack> getAmmoTypes() {
+        return Collections.unmodifiableList(AMMO_TYPES);
+    }
+
+    @Override
+    public void setPickedAmmoType(ItemStack itemStack, ItemStack ammoType) {
+        CompoundTag tag = itemStack.getData();
+        CompoundTag ammoTag = tag.getCompoundOrDefault("ammo", null);
+        if (ammoTag == null) {
+            ammoTag = new CompoundTag();
+            tag.putCompound("ammo", ammoTag);
+        }
+
+        writeAmmoTypeToTag(ammoType, ammoTag);
+    }
+
+    @Override
+    public ItemStack getPickedAmmoType(ItemStack itemStack) {
+        CompoundTag tag = itemStack.getData();
+        CompoundTag ammoTag = tag.getCompoundOrDefault("ammo", null);
+        if (ammoTag == null) {
+            ammoTag = new CompoundTag();
+            writeAmmoTypeToTag(getDefaultAmmoType(), ammoTag);
+            tag.putCompound("ammo", ammoTag);
+        }
+
+        short id = ammoTag.getShortOrDefault("id", (short) getDefaultAmmoType().itemID);
+        short damage = ammoTag.getShortOrDefault("Damage", (short) getDefaultAmmoType().getMetadata());
+
+        for (ItemStack stack : AMMO_TYPES) {
+            if (stack.itemID == id && stack.getMetadata() == damage) {
+                return stack;
+            }
+        }
+
+        return getDefaultAmmoType();
+    }
+
+    private void writeAmmoTypeToTag(ItemStack ammoType, CompoundTag ammoTag) {
+        ammoTag.putShort("id", (short) ammoType.itemID);
+        ammoTag.putShort("Damage", (short) ammoType.getMetadata());
+    }
 }
diff --git a/src/main/java/net/minecraft/core/item/ItemStack.java b/src/main/java/net/minecraft/core/item/ItemStack.java
index fb13326c6..ef0d986b6 100644
--- a/src/main/java/net/minecraft/core/item/ItemStack.java
+++ b/src/main/java/net/minecraft/core/item/ItemStack.java
@@ -367,7 +367,12 @@ public final class ItemStack
 
     public boolean isItemEqual(ItemStack itemstack)
     {
-        return itemID == itemstack.itemID && metadata == itemstack.metadata;
+        if (itemstack == null) return false;
+        boolean idMatches = itemID == itemstack.itemID;
+        if (idMatches && getItem().getHasSubtypes()) {
+            return metadata == itemstack.metadata;
+        }
+        return idMatches;
     }
 
     public String getItemName()
diff --git a/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java b/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java
index b4c763c7d..d1291d729 100644
--- a/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java
+++ b/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java
@@ -27,7 +27,7 @@ public class ItemToolAxe extends ItemTool
     @Override
     public boolean beforeDestroyBlock(World world, ItemStack itemStack, int x, int y, int z, EntityPlayer player)
     {
-    	if(!world.isClientSide && world.getGameRule(GameRules.TREECAPITATOR) && !player.isSneaking()) {
+    	if(!world.isClientSide && world.getGameRuleValue(GameRules.TREECAPITATOR) && !player.isSneaking()) {
     		int id = world.getBlockId(x, y, z);
     		if(Block.getBlock(id) instanceof BlockLog) {
             	return !new TreecapitatorHelper(world, x, y, z, player).chopTree();
diff --git a/src/main/java/net/minecraft/core/player/inventory/InventoryPlayer.java b/src/main/java/net/minecraft/core/player/inventory/InventoryPlayer.java
index 4e4b50b8b..d59597d4b 100644
--- a/src/main/java/net/minecraft/core/player/inventory/InventoryPlayer.java
+++ b/src/main/java/net/minecraft/core/player/inventory/InventoryPlayer.java
@@ -64,6 +64,22 @@ public class InventoryPlayer
         return -1;
     }
 
+    public boolean containsItem(ItemStack itemStack) {
+        for (ItemStack stack : mainInventory) {
+            if (itemStack.isItemEqual(stack)) {
+                return true;
+            }
+        }
+
+        for (ItemStack stack : armorInventory) {
+            if (itemStack.isItemEqual(stack)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     private int storeItemStack(ItemStack itemstack)
     {
         for(int i = 0; i < mainInventory.length; i++)
diff --git a/src/main/java/net/minecraft/core/world/Explosion.java b/src/main/java/net/minecraft/core/world/Explosion.java
index 8efb8d859..f79b4941e 100644
--- a/src/main/java/net/minecraft/core/world/Explosion.java
+++ b/src/main/java/net/minecraft/core/world/Explosion.java
@@ -39,7 +39,7 @@ public class Explosion {
 		explosionY = y;
 		explosionZ = z;
 		destroyBlocks = true;
-		if(!world.getGameRule(GameRules.MOB_GRIEFING)) {
+		if(!world.getGameRuleValue(GameRules.MOB_GRIEFING)) {
 		    destroyBlocks = entity == null || entity instanceof EntityPlayer;
 		}
 	}
diff --git a/src/main/java/net/minecraft/core/world/SpawnerMobs.java b/src/main/java/net/minecraft/core/world/SpawnerMobs.java
index d2f9197e9..386746d05 100644
--- a/src/main/java/net/minecraft/core/world/SpawnerMobs.java
+++ b/src/main/java/net/minecraft/core/world/SpawnerMobs.java
@@ -201,7 +201,7 @@ public final class SpawnerMobs
 
 	public static boolean performSleepSpawning(World world, List<EntityPlayer> list)
     {
-        if (!world.getGameRule(GameRules.DO_NIGHTMARES))
+        if (!world.getGameRuleValue(GameRules.DO_NIGHTMARES))
         {
             return false;
         }
diff --git a/src/main/java/net/minecraft/core/world/World.java b/src/main/java/net/minecraft/core/world/World.java
index 73f856909..28423c816 100644
--- a/src/main/java/net/minecraft/core/world/World.java
+++ b/src/main/java/net/minecraft/core/world/World.java
@@ -292,7 +292,7 @@ public class World implements WorldSource {
         biomeProvider = this.worldType.createBiomeProvider(this);
     }
 
-    public <T> T getGameRule(GameRule<T> gameRule)
+    public <T> T getGameRuleValue(GameRule<T> gameRule)
     {
         return levelData.getGameRules().getValue(gameRule);
     }
@@ -1643,7 +1643,7 @@ public class World implements WorldSource {
 
     public float getCelestialAngle(float partialTick)
     {
-    	if(!getGameRule(GameRules.DO_DAY_CYCLE)) {
+    	if(!getGameRuleValue(GameRules.DO_DAY_CYCLE)) {
     		partialTick = 1.0f;
     	}
         return worldType.getCelestialAngle(this, levelData.getWorldTime(), partialTick);
@@ -2519,7 +2519,7 @@ public class World implements WorldSource {
 			saveWorld(false, null, true);
 		}
 
-		if(getGameRule(GameRules.DO_DAY_CYCLE)) {
+		if(getGameRuleValue(GameRules.DO_DAY_CYCLE)) {
 			levelData.setWorldTime(levelData.getWorldTime() + 1L);
 		}
 
diff --git a/src/main/resources/assets/minecraft/textures/block/leaves_caatinga_fancy.png b/src/main/resources/assets/minecraft/textures/block/leaves_caatinga_fancy.png
index a04c7fda3..f8889b2bf 100644
Binary files a/src/main/resources/assets/minecraft/textures/block/leaves_caatinga_fancy.png and b/src/main/resources/assets/minecraft/textures/block/leaves_caatinga_fancy.png differ
diff --git a/src/main/resources/assets/minecraft/textures/colormap/oak/overworld_fall.png b/src/main/resources/assets/minecraft/textures/colormap/oak/overworld_fall.png
index 9a8c224ae..7a61dd673 100644
Binary files a/src/main/resources/assets/minecraft/textures/colormap/oak/overworld_fall.png and b/src/main/resources/assets/minecraft/textures/colormap/oak/overworld_fall.png differ
