diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java
index c9aa34865..67b1155a2 100644
--- a/src/main/java/net/minecraft/client/Minecraft.java
+++ b/src/main/java/net/minecraft/client/Minecraft.java
@@ -8,7 +8,6 @@ import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.File;
 import java.io.IOException;
-import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Comparator;
@@ -822,7 +821,7 @@ public class Minecraft
         if(screen != null)
         {
             setIngameNotInFocus();
-            screen.init(this, resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
+            screen.opened(this, resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
             skipRenderWorld = false;
         } else
         {
@@ -1306,7 +1305,7 @@ public class Minecraft
     {
         resolution.setScale(gameSettings.guiScale.value);
         if(currentScreen != null) {
-            currentScreen.init(this, resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
+            currentScreen.opened(this, resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/Screen.java b/src/main/java/net/minecraft/client/gui/Screen.java
index e0f15a306..04657620f 100644
--- a/src/main/java/net/minecraft/client/gui/Screen.java
+++ b/src/main/java/net/minecraft/client/gui/Screen.java
@@ -95,7 +95,7 @@ public abstract class Screen extends Gui {
     protected void buttonReleased(ButtonElement button) {
     }
 
-    public void init(Minecraft mc, int width, int height) {
+    public void opened(Minecraft mc, int width, int height) {
         this.mc = mc;
         font = mc.font;
         this.width = width;
diff --git a/src/main/java/net/minecraft/client/gui/SignEditorScreen.java b/src/main/java/net/minecraft/client/gui/SignEditorScreen.java
index dc09c7ac3..4f39d4e71 100644
--- a/src/main/java/net/minecraft/client/gui/SignEditorScreen.java
+++ b/src/main/java/net/minecraft/client/gui/SignEditorScreen.java
@@ -27,7 +27,7 @@ public class SignEditorScreen extends Screen
         buttons.clear();
         Keyboard.enableRepeatEvents(true);
 
-        Block block = entitySign.getBlockType();
+        Block block = entitySign.getBlock();
         if(block == Blocks.SIGN_POST_PLANKS_OAK)
         {
             yOffset = 36;
@@ -123,15 +123,15 @@ public class SignEditorScreen extends Screen
         float scale = 93.75F;
         GL11.glScalef(-scale, -scale, -scale);
         GL11.glRotatef(180F, 0.0F, 1.0F, 0.0F);
-        Block block = entitySign.getBlockType();
+        Block block = entitySign.getBlock();
         if(block == Blocks.SIGN_POST_PLANKS_OAK)
         {
-            float signAngle = (float)(entitySign.getMovedData() * 360) / 16F;
+            float signAngle = (float)(entitySign.getBlockMeta() * 360) / 16F;
             GL11.glRotatef(signAngle, 0.0F, 1.0F, 0.0F);
             GL11.glTranslatef(0.0F, -1.0625F, 0.0F);
         } else
         {
-            int meta = entitySign.getMovedData();
+            int meta = entitySign.getBlockMeta();
             float signAngle = 0.0F;
             if(meta == 2)
             {
diff --git a/src/main/java/net/minecraft/client/gui/container/CraftingScreen.java b/src/main/java/net/minecraft/client/gui/container/CraftingScreen.java
index 520fe1d65..637786438 100644
--- a/src/main/java/net/minecraft/client/gui/container/CraftingScreen.java
+++ b/src/main/java/net/minecraft/client/gui/container/CraftingScreen.java
@@ -7,16 +7,11 @@ import net.minecraft.core.player.inventory.container.Inventory;
 import net.minecraft.core.world.World;
 import org.lwjgl.opengl.GL11;
 
-// Referenced classes of package net.minecraft.src:
-//            GuiContainer, ContainerWorkbench, Container, FontRenderer, 
-//            RenderEngine, InventoryPlayer, World
-
 public class CraftingScreen extends AbstractContainerScreen
 {
-
-    public CraftingScreen(Inventory inventoryplayer, World world, int i, int j, int k)
+    public CraftingScreen(Inventory inventory, World world, int x, int y, int z)
     {
-        super(new CraftingMenu(inventoryplayer, world, i, j, k));
+        super(new CraftingMenu(inventory, world, x, y, z));
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java
index 525817d01..076039760 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java
@@ -21,7 +21,7 @@ public class EntityFallingSandEntry extends EntityEntry<FallingBlockEntity>{
 
     @Override
     public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, FallingBlockEntity sand) {
-        TextCycleElement<Integer> blockIdCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, 0, 120, 20, sand.blockID) {
+        TextCycleElement<Integer> blockIdCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, 0, 120, 20, sand.carriedBlock.blockId) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
                 return ModelViewerScreen.cycleBlockId(current, offset);
@@ -33,7 +33,7 @@ public class EntityFallingSandEntry extends EntityEntry<FallingBlockEntity>{
                     int id = Integer.parseInt(s);
                     if (Block.blocksList[id] != null) return id;
                 } catch (Exception ignored){}
-                return sand.blockID;
+                return sand.carriedBlock.blockId;
             }
 
             @Override
@@ -43,7 +43,7 @@ public class EntityFallingSandEntry extends EntityEntry<FallingBlockEntity>{
         };
         blockIdCycle.textField.setPrefaceText("ID: ");
         blockIdCycle.textField.setPlaceholder("Block ID");
-        blockIdCycle.setOnValueChanged(() -> sand.blockID = blockIdCycle.getCurrentElement());
+        blockIdCycle.setOnValueChanged(() -> sand.carriedBlock.blockId = blockIdCycle.getCurrentElement());
         return new ArrayList<ButtonElement>(){{add(blockIdCycle);}};
     }
 
diff --git a/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java b/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java
index 32de69b52..069b0d57b 100644
--- a/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java
+++ b/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java
@@ -19,6 +19,7 @@ import net.minecraft.core.Global;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.BlastFurnaceBlockEntity;
+import net.minecraft.core.block.entity.BlockEntityDispatcher;
 import net.minecraft.core.block.entity.DispenserBlockEntity;
 import net.minecraft.core.block.entity.FlagBlockEntity;
 import net.minecraft.core.block.entity.MobSpawnerBlockEntity;
@@ -1117,12 +1118,12 @@ public class ClientPacketHandler extends PacketHandler
     @Override
     public void handleTileEntityData(BlockEntityDataPacket packet)
     {
-        Class<?> clazz = BlockEntity.getClassFromID(packet.tag.getString("id"));
+        Class<?> clazz = BlockEntityDispatcher.getClassFromID(packet.tag.getString("id"));
         if (clazz == null) return;
         BlockEntity existingBlockEntity = worldClient.getBlockEntity(packet.tag.getInteger("x"), packet.tag.getInteger("y"), packet.tag.getInteger("z"));
         if (existingBlockEntity == null || existingBlockEntity.getClass() != clazz)
         {
-            BlockEntity blockEntity = BlockEntity.createAndLoadEntity(packet.tag);
+            BlockEntity blockEntity = BlockEntityDispatcher.createAndLoadEntity(packet.tag);
             if (blockEntity != null)
             {
                 mc.theWorld.setBlockTileEntity(blockEntity.x, blockEntity.y, blockEntity.z, blockEntity);
diff --git a/src/main/java/net/minecraft/client/option/GameSettings.java b/src/main/java/net/minecraft/client/option/GameSettings.java
index 9492cf108..277fef93f 100644
--- a/src/main/java/net/minecraft/client/option/GameSettings.java
+++ b/src/main/java/net/minecraft/client/option/GameSettings.java
@@ -437,7 +437,7 @@ public class GameSettings {
 			guiScale.value = (guiScale.value + max) % max;
 			mc.resolution.setScale(guiScale.value);
 			if (mc.currentScreen != null) {
-				mc.currentScreen.init(mc, mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
+				mc.currentScreen.opened(mc, mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
 			}
 		}
 		if(option == mipmapType || option == mipmapLevels) {
@@ -457,7 +457,7 @@ public class GameSettings {
 		}
 		if(option == language) {
 			if (mc.currentScreen != null) {
-				mc.currentScreen.init(mc, mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
+				mc.currentScreen.opened(mc, mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
 			}
 		}
 		if(option == lightmapStyle) {
diff --git a/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java b/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
index 2a5b68615..54e66fac3 100644
--- a/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
+++ b/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
@@ -225,12 +225,12 @@ public class BlockModelDispatcher
         addDispatch(new CrossedSquaresBlockModel<>(Blocks.SPINIFEX).withTextures("minecraft:block/spinifex"));
         addDispatch(new AlgaeBlockModel<>(Blocks.ALGAE).withTextures("minecraft:block/algae").withCustomItemBounds(0.0f, 0.01f, 0.0f, 1.0f, 0.0125f, 1.0f));
 
-        addDispatch(new CrossedSquaresBlockModel<>(Blocks.FLOWER_YELLOW).withTextures("minecraft:block/flower_yellow"));
-        addDispatch(new CrossedSquaresBlockModel<>(Blocks.FLOWER_RED).withTextures("minecraft:block/flower_red"));
-        addDispatch(new CrossedSquaresBlockModel<>(Blocks.FLOWER_PINK).withTextures("minecraft:block/flower_pink"));
-        addDispatch(new CrossedSquaresBlockModel<>(Blocks.FLOWER_PURPLE).withTextures("minecraft:block/flower_purple"));
-        addDispatch(new CrossedSquaresBlockModel<>(Blocks.FLOWER_LIGHT_BLUE).withTextures("minecraft:block/flower_light_blue"));
-        addDispatch(new CrossedSquaresBlockModel<>(Blocks.FLOWER_ORANGE).withTextures("minecraft:block/flower_orange"));
+        addDispatch(new StackedFlowerBlockModel<>(Blocks.FLOWER_YELLOW, "minecraft:block/flower_yellow"));
+        addDispatch(new StackedFlowerBlockModel<>(Blocks.FLOWER_RED, "minecraft:block/flower_red"));
+        addDispatch(new StackedFlowerBlockModel<>(Blocks.FLOWER_PINK, "minecraft:block/flower_pink"));
+        addDispatch(new StackedFlowerBlockModel<>(Blocks.FLOWER_PURPLE, "minecraft:block/flower_purple"));
+        addDispatch(new StackedFlowerBlockModel<>(Blocks.FLOWER_LIGHT_BLUE, "minecraft:block/flower_light_blue"));
+        addDispatch(new StackedFlowerBlockModel<>(Blocks.FLOWER_ORANGE, "minecraft:block/flower_orange"));
 
         addDispatch(new CrossedSquaresBlockModel<>(Blocks.MUSHROOM_BROWN).withTextures("minecraft:block/mushroom_brown"));
         addDispatch(new CrossedSquaresBlockModel<>(Blocks.MUSHROOM_RED).withTextures("minecraft:block/mushroom_red"));
diff --git a/src/main/java/net/minecraft/client/render/block/model/PistonBlockModel.java b/src/main/java/net/minecraft/client/render/block/model/PistonBlockModel.java
index b8973b353..3ca6f7468 100644
--- a/src/main/java/net/minecraft/client/render/block/model/PistonBlockModel.java
+++ b/src/main/java/net/minecraft/client/render/block/model/PistonBlockModel.java
@@ -42,8 +42,8 @@ public class PistonBlockModel<T extends PistonBaseBlock> extends StandardBlockMo
         block.setBlockBoundsBasedOnState(renderBlocks.blockAccess, x, y, z);
         return renderPistonBase(tessellator, x, y, z, false);
     }
-    @Override
-    public boolean renderNoCulling(Tessellator tessellator, int x, int y, int z) {
+
+    public boolean renderHeadless(Tessellator tessellator, int x, int y, int z) {
         renderBlocks.renderAllFaces = true;
         boolean result = renderPistonBase(tessellator, x, y, z, true);
         renderBlocks.renderAllFaces = false;
diff --git a/src/main/java/net/minecraft/client/render/block/model/StackedFlowerBlockModel.java b/src/main/java/net/minecraft/client/render/block/model/StackedFlowerBlockModel.java
new file mode 100644
index 000000000..8112551f7
--- /dev/null
+++ b/src/main/java/net/minecraft/client/render/block/model/StackedFlowerBlockModel.java
@@ -0,0 +1,30 @@
+package net.minecraft.client.render.block.model;
+
+import net.minecraft.client.render.texture.stitcher.IconCoordinate;
+import net.minecraft.client.render.texture.stitcher.TextureRegistry;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.StackedFlowerBlock;
+import net.minecraft.core.util.helper.Side;
+
+public class StackedFlowerBlockModel<T extends StackedFlowerBlock> extends CrossedSquaresBlockModel<T> {
+    private final IconCoordinate[] ICONS;
+
+    public StackedFlowerBlockModel(Block block, String baseTexture) {
+        super(block);
+
+        ICONS = new IconCoordinate[T.MAX_STACK_COUNT + 1];
+        for (int i = 0; i < T.MAX_STACK_COUNT + 1; i++) {
+            ICONS[i] = TextureRegistry.getTexture(baseTexture + i);
+        }
+    }
+
+    @Override
+    public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data) {
+        final int stackCount = T.getStackCount(data);
+        if (stackCount > T.MAX_STACK_COUNT) {
+            return ICONS[0];
+        }
+
+        return ICONS[stackCount];
+    }
+}
diff --git a/src/main/java/net/minecraft/client/render/blockentity/FlowerJarBlockEntityRenderer.java b/src/main/java/net/minecraft/client/render/blockentity/FlowerJarBlockEntityRenderer.java
index 285508ad3..6fa5c9352 100644
--- a/src/main/java/net/minecraft/client/render/blockentity/FlowerJarBlockEntityRenderer.java
+++ b/src/main/java/net/minecraft/client/render/blockentity/FlowerJarBlockEntityRenderer.java
@@ -42,7 +42,7 @@ public class FlowerJarBlockEntityRenderer extends BlockEntityRenderer<FlowerJarB
                     lmc = tileEntity.worldObj.getLightmapCoord(tileEntity.x, tileEntity.y, tileEntity.z, 0);
                 }
             }
-            BlockModelDispatcher.getInstance().getDispatch(block).renderBlockOnInventory(tessellator, 0, lightLevel, lmc);
+            BlockModelDispatcher.getInstance().getDispatch(block).renderBlockOnInventory(tessellator, tileEntity.flowerData, lightLevel, lmc);
         }
         GL11.glPopMatrix();
     }
diff --git a/src/main/java/net/minecraft/client/render/blockentity/PistonBlockEntityRenderer.java b/src/main/java/net/minecraft/client/render/blockentity/PistonBlockEntityRenderer.java
index 4677ed0c6..53f7dba58 100644
--- a/src/main/java/net/minecraft/client/render/blockentity/PistonBlockEntityRenderer.java
+++ b/src/main/java/net/minecraft/client/render/blockentity/PistonBlockEntityRenderer.java
@@ -86,7 +86,7 @@ public class PistonBlockEntityRenderer extends BlockEntityRenderer<MovingPistonB
                     blockModelPistonHead.setFaceTextureOverride(null);
                 }
                 tessellator.setTranslation((float)x - (float)blockEntity.x, (float)y - (float)blockEntity.y, (float)z - (float)blockEntity.z);
-                pistonBase.renderNoCulling(tessellator, blockEntity.x, blockEntity.y, blockEntity.z);
+                pistonBase.renderHeadless(tessellator, blockEntity.x, blockEntity.y, blockEntity.z);
             } else
             {
                 BlockModel.setRenderBlocks(containerRenderBlock);
diff --git a/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java b/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java
index 01785c6bc..134f0f8f7 100644
--- a/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java
+++ b/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java
@@ -32,19 +32,19 @@ public class SignBlockEntityRenderer extends BlockEntityRenderer<SignBlockEntity
     public void renderTileEntitySignAt(SignBlockEntity tileEntity, double d, double d1, double d2,
                                        float f)
     {
-        Block block = tileEntity.getBlockType();
+        Block block = tileEntity.getBlock();
         GL11.glPushMatrix();
         float scale = 0.6666667F;
         if(block == Blocks.SIGN_POST_PLANKS_OAK)
         {
             GL11.glTranslatef((float)d + 0.5F, (float)d1 + 0.75F * scale, (float)d2 + 0.5F);
-            float f2 = (float)(tileEntity.getMovedData() * 360) / 16F;
+            float f2 = (float)(tileEntity.getBlockMeta() * 360) / 16F;
             GL11.glRotatef(-f2, 0.0F, 1.0F, 0.0F);
             signModel.signStick.visible = true;
         }
         else
         {
-            int i = tileEntity.getMovedData();
+            int i = tileEntity.getBlockMeta();
             float f3 = 0.0F;
             if(i == 2)
             {
diff --git a/src/main/java/net/minecraft/client/render/entity/FallingBlockRenderer.java b/src/main/java/net/minecraft/client/render/entity/FallingBlockRenderer.java
index 3d020c599..d0c5fc0f5 100644
--- a/src/main/java/net/minecraft/client/render/entity/FallingBlockRenderer.java
+++ b/src/main/java/net/minecraft/client/render/entity/FallingBlockRenderer.java
@@ -64,8 +64,8 @@ public class FallingBlockRenderer extends EntityRenderer<FallingBlockEntity>
         BlockModel.setRenderBlocks(containerRenderBlock);
 
         container.setLightReferenceEntity(fallingBlock);
-        container.setBlock(blockX, blockY, blockZ, fallingBlock.blockID, fallingBlock.blockMeta, fallingBlock.blockEntity);
-        BlockModelDispatcher.getInstance().getDispatch(Block.getBlock(fallingBlock.blockID)).renderNoCulling(Tessellator.instance, blockX, blockY, blockZ);
+        container.setBlock(blockX, blockY, blockZ, fallingBlock.carriedBlock.blockId, fallingBlock.carriedBlock.metadata, fallingBlock.carriedBlock.entity);
+        BlockModelDispatcher.getInstance().getDispatch(Block.getBlock(fallingBlock.carriedBlock.blockId)).renderNoCulling(Tessellator.instance, blockX, blockY, blockZ);
         container.setLightReferenceEntity(null);
         container.clear();
 
@@ -75,10 +75,10 @@ public class FallingBlockRenderer extends EntityRenderer<FallingBlockEntity>
         Lighting.enableLight();
         GL11.glPopMatrix();
 
-        BlockEntityRenderer<BlockEntity> renderer = BlockEntityRenderDispatcher.instance.getRenderer(fallingBlock.blockEntity);
+        BlockEntityRenderer<BlockEntity> renderer = BlockEntityRenderDispatcher.instance.getRenderer(fallingBlock.carriedBlock.entity);
         if (renderer != null) {
             GL11.glPushMatrix();
-            renderer.doRender(tessellator, fallingBlock.blockEntity, x - 0.5, y - 0.5, z - 0.5, partialTick);
+            renderer.doRender(tessellator, fallingBlock.carriedBlock.entity, x - 0.5, y - 0.5, z - 0.5, partialTick);
             GL11.glPopMatrix();
         }
     }
diff --git a/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java b/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java
index 4348b3fb2..4b184a97a 100644
--- a/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java
+++ b/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java
@@ -19,6 +19,7 @@ import net.minecraft.client.render.model.PlayerSlimModel;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.*;
 import net.minecraft.core.block.Block;
@@ -144,8 +145,8 @@ public class PlayerRenderer extends MobRenderer<Player>
     }
 
     public void drawHeldObject(Player player, float partialTick) {
-        if (player.getHeldObject() instanceof BlockEntity.CarriedBlock) {
-            BlockEntity.CarriedBlock carriedBlock = (BlockEntity.CarriedBlock)player.getHeldObject();
+        if (player.getHeldObject() instanceof CarriedBlock) {
+            CarriedBlock carriedBlock = (CarriedBlock)player.getHeldObject();
             if (container == null || container.world != player.world) {
                 container = new BlocksContainer(player.world);
                 containerRenderBlock = new RenderBlocks(container);
@@ -177,8 +178,8 @@ public class PlayerRenderer extends MobRenderer<Player>
             tessellator.setTranslation(-blockX -0.5, -blockY -0.5, -blockZ -0.5);
 
             container.setLightReferenceEntity(player);
-            container.setBlock(blockX, blockY, blockZ, carriedBlock.block.id, carriedBlock.metadata, carriedBlock.entity);
-            BlockModelDispatcher.getInstance().getDispatch(carriedBlock.block).renderNoCulling(Tessellator.instance, blockX, blockY, blockZ);
+            container.setBlock(blockX, blockY, blockZ, carriedBlock.blockId, carriedBlock.metadata, carriedBlock.entity);
+            BlockModelDispatcher.getInstance().getDispatch(carriedBlock.block()).renderNoCulling(Tessellator.instance, blockX, blockY, blockZ);
             tessellator.draw();
             tessellator.setTranslation(0, 0, 0);
             container.setLightReferenceEntity(null);
diff --git a/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java b/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java
index fdea38f0b..63dbd8c20 100644
--- a/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java
+++ b/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java
@@ -8,6 +8,7 @@ import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
+import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.Global;
@@ -18,6 +19,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.block.BlockItem;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
@@ -35,6 +37,12 @@ public class BlockItemModel extends StandardItemModel {
         this.blockModel = BlockModelDispatcher.getInstance().getDispatch(block);
         icon = blockModel.getBlockTextureFromSideAndMetadata(Side.NORTH, 0);
     }
+
+    @Override
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack) {
+        return this.blockModel.getBlockTextureFromSideAndMetadata(Side.NORTH, itemStack.getMetadata());
+    }
+
     @Override
     public void renderItemFirstPerson(Tessellator tessellator, ItemRenderer renderer, Player player, ItemStack stack, float partialTick) {
         final Minecraft mc = Minecraft.getMinecraft(this);
diff --git a/src/main/java/net/minecraft/core/block/Blocks.java b/src/main/java/net/minecraft/core/block/Blocks.java
index 28ba3374c..3842e3af3 100644
--- a/src/main/java/net/minecraft/core/block/Blocks.java
+++ b/src/main/java/net/minecraft/core/block/Blocks.java
@@ -816,18 +816,18 @@ public final class Blocks {
             .setBlockItem((b) -> new AlgaeBlockItem(b))
             .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH);
 
-        FLOWER_YELLOW = new FlowerBlock("flower.yellow", "minecraft:block/flower_yellow", 330).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedYellow)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
-        FLOWER_RED = new FlowerBlock("flower.red", "minecraft:block/flower_red", 331).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedRed)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
-        FLOWER_PINK = new FlowerBlock("flower.pink", "minecraft:block/flower_pink", 332).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedPink)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
-        FLOWER_PURPLE = new FlowerBlock("flower.purple", "minecraft:block/flower_purple", 333).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedPurple)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
-        FLOWER_LIGHT_BLUE = new FlowerBlock("flower.lightblue", "minecraft:block/flower_light_blue", 334).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedLightblue)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
-        FLOWER_ORANGE = new FlowerBlock("flower.orange", "minecraft:block/flower_orange", 335).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedOrange)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
+        FLOWER_YELLOW = new StackedFlowerBlock("flower.yellow", "minecraft:block/flower_yellow", 330).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedYellow)
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK, BlockTags.SHEARS_DO_SILK_TOUCH);
+        FLOWER_RED = new StackedFlowerBlock("flower.red", "minecraft:block/flower_red", 331).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedRed)
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK, BlockTags.SHEARS_DO_SILK_TOUCH);
+        FLOWER_PINK = new StackedFlowerBlock("flower.pink", "minecraft:block/flower_pink", 332).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedPink)
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK, BlockTags.SHEARS_DO_SILK_TOUCH);
+        FLOWER_PURPLE = new StackedFlowerBlock("flower.purple", "minecraft:block/flower_purple", 333).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedPurple)
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK, BlockTags.SHEARS_DO_SILK_TOUCH);
+        FLOWER_LIGHT_BLUE = new StackedFlowerBlock("flower.lightblue", "minecraft:block/flower_light_blue", 334).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedLightblue)
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK, BlockTags.SHEARS_DO_SILK_TOUCH);
+        FLOWER_ORANGE = new StackedFlowerBlock("flower.orange", "minecraft:block/flower_orange", 335).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedOrange)
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK, BlockTags.SHEARS_DO_SILK_TOUCH);
 
         MUSHROOM_BROWN = new MushroomBlock("mushroom.brown", "minecraft:block/mushroom_brown", 340).withSound(BlockSounds.GRASS).withHardness(0.0F).withLightEmission(0.125F).withOverrideColor(MaterialColor.paintedBrown)
             .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.PIGS_FAVOURITE_BLOCK);
@@ -1148,7 +1148,7 @@ public final class Blocks {
             .withTags(BlockTags.MINEABLE_BY_PICKAXE);
         COBBLE_NETHERRACK_MOSSY = new Block("cobble.netherrack.mossy", "minecraft:block/cobble_netherrack_mossy", 802, Material.netherrack).withSound(BlockSounds.STONE).withHardness(0.4F)
             .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.INFINITE_BURN);
-        NETHERRACK = new Block("netherrack", "minecraft:block/netherrack", 803, Material.netherrack).withSound(BlockSounds.STONE).withHardness(0.32F)
+        NETHERRACK = new StoneBlock("netherrack", "minecraft:block/netherrack", 803, () -> Blocks.COBBLE_NETHERRACK, Material.netherrack).withSound(BlockSounds.STONE).withHardness(0.32F)
             .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.INFINITE_BURN, BlockTags.CAVES_CUT_THROUGH, BlockTags.NETHER_MOBS_SPAWN);
         BRICK_NETHERRACK = new Block("brick.netherrack", "minecraft:block/brick_netherrack", 804, Material.netherrack).withSound(BlockSounds.STONE).withHardness(0.4F)
             .withTags(BlockTags.MINEABLE_BY_PICKAXE);
diff --git a/src/main/java/net/minecraft/core/block/ChainlinkFenceBlock.java b/src/main/java/net/minecraft/core/block/ChainlinkFenceBlock.java
index 4e254cbd9..fb79d2f1e 100644
--- a/src/main/java/net/minecraft/core/block/ChainlinkFenceBlock.java
+++ b/src/main/java/net/minecraft/core/block/ChainlinkFenceBlock.java
@@ -17,7 +17,7 @@ public class ChainlinkFenceBlock extends ThinFenceBlock
     public boolean canConnectTo(WorldSource world, int x, int y, int z)
     {
         int id = world.getBlockId(x, y, z);
-        return Block.hasTag(id, BlockTags.CHAINLINK_FENCES_CONNECT) || (Block.blocksList[id] != null && (Block.blocksList[id].blockMaterial == Material.stone || Block.blocksList[id].blockMaterial == Material.metal));
+        return Block.hasTag(id, BlockTags.CHAINLINK_FENCES_CONNECT) || (Block.blocksList[id] != null && (Block.blocksList[id].blockMaterial.isStone() || Block.blocksList[id].blockMaterial == Material.metal));
     }
     
     @Override
diff --git a/src/main/java/net/minecraft/core/block/CropsPumpkinBlock.java b/src/main/java/net/minecraft/core/block/CropsPumpkinBlock.java
index 2768a0348..025397d92 100644
--- a/src/main/java/net/minecraft/core/block/CropsPumpkinBlock.java
+++ b/src/main/java/net/minecraft/core/block/CropsPumpkinBlock.java
@@ -40,8 +40,8 @@ public class CropsPumpkinBlock
     }
 
     @Override
-    protected boolean canThisPlantGrowOnThisBlockID(int i) {
-        return i == Blocks.FARMLAND_DIRT.id;
+    protected boolean mayPlaceOn(int blockId) {
+        return blockId == Blocks.FARMLAND_DIRT.id;
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/CropsWheatBlock.java b/src/main/java/net/minecraft/core/block/CropsWheatBlock.java
index d6c56892b..e46da3a28 100644
--- a/src/main/java/net/minecraft/core/block/CropsWheatBlock.java
+++ b/src/main/java/net/minecraft/core/block/CropsWheatBlock.java
@@ -27,9 +27,9 @@ public class CropsWheatBlock extends FlowerBlock implements IBonemealable
     }
 
 	@Override
-	public boolean canThisPlantGrowOnThisBlockID(int i)
+	public boolean mayPlaceOn(int blockId)
     {
-        return i == Blocks.FARMLAND_DIRT.id;
+        return blockId == Blocks.FARMLAND_DIRT.id;
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/DeadBushBlock.java b/src/main/java/net/minecraft/core/block/DeadBushBlock.java
index b22db93e1..24bdc04c0 100644
--- a/src/main/java/net/minecraft/core/block/DeadBushBlock.java
+++ b/src/main/java/net/minecraft/core/block/DeadBushBlock.java
@@ -20,9 +20,9 @@ public class DeadBushBlock extends FlowerBlock
     }
 	
     @Override
-	public boolean canThisPlantGrowOnThisBlockID(int i)
+	public boolean mayPlaceOn(int blockId)
     {
-        return i == Blocks.SAND.id || i == Blocks.DIRT_SCORCHED.id;
+        return blockId == Blocks.SAND.id || blockId == Blocks.DIRT_SCORCHED.id;
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/FlowerBlock.java b/src/main/java/net/minecraft/core/block/FlowerBlock.java
index 682a27acf..d6386bddf 100644
--- a/src/main/java/net/minecraft/core/block/FlowerBlock.java
+++ b/src/main/java/net/minecraft/core/block/FlowerBlock.java
@@ -1,10 +1,7 @@
 package net.minecraft.core.block;
 
-import java.util.Random;
-
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.tag.BlockTags;
-import net.minecraft.core.data.gamerule.GameRule;
 import net.minecraft.core.data.gamerule.GameRules;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
@@ -15,136 +12,122 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-// Referenced classes of package net.minecraft.src:
-//            Block, Material, World, GrassBlock,
-//            AxisAlignedBB
+import java.util.Random;
 
-public class FlowerBlock extends Block implements IBonemealable
-{
+public class FlowerBlock extends Block implements IBonemealable {
+    public static final int MASK_PERMANENT = 0b1000_0000;
 
-	public boolean killedByWeather = false;
-	public boolean canBeBonemealed = false;
+    public boolean killedByWeather = false;
+    public boolean canBeBonemealed = false;
 
-	public FlowerBlock(String key, String namespaceId, int id)
-    {
+    public FlowerBlock(String key, String namespaceId, int id) {
         super(key, namespaceId, id, Material.plant);
         setTicking(true);
         float f = 0.2F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 3F, 0.5F + f);
     }
-    
-    public FlowerBlock setKilledByWeather()
-    {
-    	killedByWeather = true;
-    	return this;
+
+    public FlowerBlock setKilledByWeather() {
+        killedByWeather = true;
+        return this;
     }
-    public FlowerBlock setBonemealable()
-    {
+
+    public FlowerBlock setBonemealable() {
         canBeBonemealed = true;
         return this;
     }
 
     @Override
     public int getPlacedBlockMetadata(Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
-    	return LeavesLayerBlock.MASK_PERMANENT;
+        return MASK_PERMANENT;
     }
-    
+
     @Override
-	public boolean canPlaceBlockAt(World world, int x, int y, int z)
-    {
-        return super.canPlaceBlockAt(world, x, y, z) && canThisPlantGrowOnThisBlockID(world.getBlockId(x, y - 1, z));
+    public boolean canPlaceBlockAt(World world, int x, int y, int z) {
+        return super.canPlaceBlockAt(world, x, y, z) && mayPlaceOn(world.getBlockId(x, y - 1, z));
     }
 
-    protected boolean canThisPlantGrowOnThisBlockID(int i)
-    {
-    	if (Block.blocksList[i] == null) return false;
-        return Block.blocksList[i].hasTag(BlockTags.GROWS_FLOWERS);
+    protected boolean mayPlaceOn(int blockId) {
+        if (Block.blocksList[blockId] == null) return false;
+        return Block.blocksList[blockId].hasTag(BlockTags.GROWS_FLOWERS);
     }
 
     @Override
-	public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
-    {
+    public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
         super.onNeighborBlockChange(world, x, y, z, blockId);
-        func_268_h(world, x, y, z);
+        checkAlive(world, x, y, z);
     }
 
     @Override
-	public void updateTick(World world, int x, int y, int z, Random rand)
-    {
-        func_268_h(world, x, y, z);
-        
-        if (world.getGameRuleValue(GameRules.DO_SEASONAL_GROWTH) && world.getSeasonManager().getCurrentSeason() != null && ((world.getBlockMetadata(x, y, z) & 0b1000_000) == 0) && world.getSeasonManager().getCurrentSeason().killFlowers && killedByWeather && rand.nextInt(256) == 0)
-        {
-        	world.setBlockWithNotify(x, y, z, 0);
+    public void updateTick(World world, int x, int y, int z, Random rand) {
+        checkAlive(world, x, y, z);
+
+        if (world.getGameRuleValue(GameRules.DO_SEASONAL_GROWTH) && world.getSeasonManager().getCurrentSeason() != null && (!isPermanent(world.getBlockMetadata(x, y, z))) && world.getSeasonManager().getCurrentSeason().killFlowers && killedByWeather && rand.nextInt(256) == 0) {
+            world.setBlockWithNotify(x, y, z, 0);
         }
     }
 
-    protected final void func_268_h(World world, int i, int j, int k)
-    {
-        if(!canBlockStay(world, i, j, k))
-        {
-            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
-            world.setBlockWithNotify(i, j, k, 0);
+    protected final void checkAlive(World world, int x, int y, int z) {
+        if (!canBlockStay(world, x, y, z)) {
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
+            world.setBlockWithNotify(x, y, z, 0);
         }
     }
 
     @Override
-    public boolean canBlockStay(World world, int x, int y, int z)
-    {
-        return (world.getFullBlockLightValue(x, y, z) >= 8 || world.canBlockSeeTheSky(x, y, z)) && canThisPlantGrowOnThisBlockID(world.getBlockId(x, y - 1, z));
+    public boolean canBlockStay(World world, int x, int y, int z) {
+        return (world.getFullBlockLightValue(x, y, z) >= 8 || world.canBlockSeeTheSky(x, y, z)) && mayPlaceOn(world.getBlockId(x, y - 1, z));
+    }
+
+    public static boolean isPermanent(int metadata) {
+        return (metadata & MASK_PERMANENT) > 0;
+    }
+
+    public static int setPermanent(int metadata, boolean permanent) {
+        return (metadata & ~MASK_PERMANENT) | (permanent ? MASK_PERMANENT : 0b0000_0000);
     }
 
     @Override
-	public AABB getCollisionBoundingBoxFromPool(WorldSource world, int x, int y, int z)
-    {
+    public AABB getCollisionBoundingBoxFromPool(WorldSource world, int x, int y, int z) {
         return null;
     }
 
     @Override
-	public boolean isSolidRender()
-    {
+    public boolean isSolidRender() {
         return false;
     }
 
     @Override
-	public boolean isCubeShaped()
-    {
+    public boolean isCubeShaped() {
         return false;
     }
 
     @Override
     public boolean onBonemealUsed(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
         Random rand = world.rand;
-        if(!world.isClientSide && canBeBonemealed)
-        {
-            if (entityplayer.getGamemode().consumeBlocks())
-            {
+        if (!world.isClientSide && canBeBonemealed) {
+            if (entityplayer.getGamemode().consumeBlocks()) {
                 itemstack.stackSize--;
             }
             label0:
-            for(int j1 = 0; j1 < 128; j1++)
-            {
+            for (int j1 = 0; j1 < 128; j1++) {
                 int k1 = blockX;
                 int l1 = blockY;
                 int i2 = blockZ;
-                for(int j2 = 0; j2 < j1 / 16; j2++)
-                {
+                for (int j2 = 0; j2 < j1 / 16; j2++) {
                     k1 += rand.nextInt(3) - 1;
                     l1 += ((rand.nextInt(3) - 1) * rand.nextInt(3)) / 2;
                     i2 += rand.nextInt(3) - 1;
                     int id1 = world.getBlockId(k1, l1 - 1, i2);
-                    if(Block.blocksList[id1] == null || !Block.blocksList[id1].hasTag(BlockTags.GROWS_FLOWERS))
-                    {
+                    if (Block.blocksList[id1] == null || !Block.blocksList[id1].hasTag(BlockTags.GROWS_FLOWERS)) {
                         continue label0;
                     }
                 }
 
-                if(world.getBlockId(k1, l1, i2) != 0)
-                {
+                if (world.getBlockId(k1, l1, i2) != 0) {
                     continue;
                 }
-                if(rand.nextFloat() > 0.75)
-                {
+                if (rand.nextFloat() > 0.75) {
                     world.setBlockWithNotify(k1, l1, i2, id);
                 }
             }
diff --git a/src/main/java/net/minecraft/core/block/JarBlock.java b/src/main/java/net/minecraft/core/block/JarBlock.java
index 4b66b37a5..63f6e3293 100644
--- a/src/main/java/net/minecraft/core/block/JarBlock.java
+++ b/src/main/java/net/minecraft/core/block/JarBlock.java
@@ -5,6 +5,7 @@ import net.minecraft.core.block.entity.FlowerJarBlockEntity;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
@@ -78,22 +79,40 @@ public class JarBlock extends EntityBlock {
             } else {
                 FlowerJarBlockEntity tileEntity = (FlowerJarBlockEntity) world.getBlockEntity(x, y, z);
                 int flowerInPot = tileEntity.flowerInPot;
+                int flowerData = tileEntity.flowerData;
                 if (flowerInPot > 0 && hasTag(flowerInPot, BlockTags.PLANTABLE_IN_JAR)) {
                     tileEntity.flowerInPot = 0;
                     world.setBlockMetadataWithNotify(x, y, z, 0);
                     world.playSoundAtEntity(player, player, "random.pop", 0.2F, 0.5f);
                     if (!world.isClientSide) {
-                        world.dropItem(x, y, z, new ItemStack(flowerInPot, 1, 0));
+                        world.dropItem(x, y, z, new ItemStack(flowerInPot, 1, flowerData));
                     }
                 }
             }
-        } else if (world.getBlockMetadata(x, y, z) == 0 && player.getHeldItem().getItem() instanceof BlockItem) {
+        } else if (player.getHeldItem().getItem() instanceof BlockItem) {
             Block blockInHand = ((BlockItem) player.getHeldItem().getItem()).getBlock();
-            if(hasTag(blockInHand.id, BlockTags.PLANTABLE_IN_JAR)){
-                player.getHeldItem().consumeItem(player);
+            if (hasTag(blockInHand.id, BlockTags.PLANTABLE_IN_JAR)) {
                 FlowerJarBlockEntity tileEntity = (FlowerJarBlockEntity) world.getBlockEntity(x, y, z);
-                world.setBlockMetadataWithNotify(x, y, z, 1);
-                tileEntity.flowerInPot = blockInHand.id;
+                if(world.getBlockMetadata(x, y, z) == 0) {
+                    player.getHeldItem().consumeItem(player);
+                    world.setBlockMetadataWithNotify(x, y, z, 1);
+                    tileEntity.flowerInPot = blockInHand.id;
+                    tileEntity.flowerData = player.getHeldItem().getMetadata();
+                    world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, this, EnumBlockSoundEffectType.PLACE);
+                    return true;
+                } else if (blockInHand instanceof StackedFlowerBlock && blockInHand == Block.getBlock(tileEntity.flowerInPot)) {
+                    final int metadata = tileEntity.flowerData;
+                    final int currentStackCount = StackedFlowerBlock.getStackCount(metadata);
+                    if (currentStackCount >= StackedFlowerBlock.MAX_STACK_COUNT) {
+                        return false;
+                    }
+
+                    final int newMetadata = StackedFlowerBlock.setPermanent(StackedFlowerBlock.setStackCount(metadata, currentStackCount + 1), true);
+                    tileEntity.flowerData = newMetadata;
+                    world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, this, EnumBlockSoundEffectType.PLACE);
+                    player.getHeldItem().consumeItem(player);
+                    return true;
+                }
             }
         }
         return true;
diff --git a/src/main/java/net/minecraft/core/block/MushroomBlock.java b/src/main/java/net/minecraft/core/block/MushroomBlock.java
index a3a06e182..f14f9b8ad 100644
--- a/src/main/java/net/minecraft/core/block/MushroomBlock.java
+++ b/src/main/java/net/minecraft/core/block/MushroomBlock.java
@@ -39,9 +39,9 @@ public class MushroomBlock extends FlowerBlock
     }
 
     @Override
-	protected boolean canThisPlantGrowOnThisBlockID(int i)
+	protected boolean mayPlaceOn(int blockId)
     {
-        return Block.solid[i];
+        return Block.solid[blockId];
     }
 
     @Override
@@ -52,7 +52,7 @@ public class MushroomBlock extends FlowerBlock
             return false;
         } else
         {
-            return world.getFullBlockLightValue(x, y, z) < 13 && canThisPlantGrowOnThisBlockID(world.getBlockId(x, y - 1, z));
+            return world.getFullBlockLightValue(x, y, z) < 13 && mayPlaceOn(world.getBlockId(x, y - 1, z));
         }
     }
 }
diff --git a/src/main/java/net/minecraft/core/block/SaplingBaseBlock.java b/src/main/java/net/minecraft/core/block/SaplingBaseBlock.java
index a2af4d4e2..13e3af427 100644
--- a/src/main/java/net/minecraft/core/block/SaplingBaseBlock.java
+++ b/src/main/java/net/minecraft/core/block/SaplingBaseBlock.java
@@ -25,9 +25,9 @@ public abstract class SaplingBaseBlock extends FlowerBlock implements IBonemeala
     }
 
 	@Override
-	public boolean canThisPlantGrowOnThisBlockID(int i)
+	public boolean mayPlaceOn(int blockId)
     {
-        return i == Blocks.SAND.id || super.canThisPlantGrowOnThisBlockID(i);
+        return blockId == Blocks.SAND.id || super.mayPlaceOn(blockId);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/SeatBlock.java b/src/main/java/net/minecraft/core/block/SeatBlock.java
index fd1d63380..52dabc50c 100644
--- a/src/main/java/net/minecraft/core/block/SeatBlock.java
+++ b/src/main/java/net/minecraft/core/block/SeatBlock.java
@@ -57,7 +57,7 @@ public class SeatBlock
     
     @Override
     protected BlockEntity getNewBlockEntity() {
-        return new SeatBlockEntity();
+        return new SeatBlockEntity(this);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/StackedFlowerBlock.java b/src/main/java/net/minecraft/core/block/StackedFlowerBlock.java
new file mode 100644
index 000000000..313f005cc
--- /dev/null
+++ b/src/main/java/net/minecraft/core/block/StackedFlowerBlock.java
@@ -0,0 +1,69 @@
+package net.minecraft.core.block;
+
+import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.enums.EnumBlockSoundEffectType;
+import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.helper.Side;
+import net.minecraft.core.world.World;
+
+/**
+ * Represents a flower block that can store multiple flowers within itself, up to a maximum of 4.
+ */
+public class StackedFlowerBlock extends FlowerBlock {
+    public static final int MASK_STACK_COUNT = 0b0110_0000;
+    public static final int OFFSET_STACK_COUNT = 5;
+    public static final int MAX_STACK_COUNT = MASK_STACK_COUNT >> OFFSET_STACK_COUNT;
+
+    public StackedFlowerBlock(String key, String namespaceId, int id) {
+        super(key, namespaceId, id);
+    }
+
+    @Override
+    public int getPlacedBlockMetadata(Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+        final int metadata = stack.getMetadata();
+        return setPermanent(metadata, true);
+    }
+
+    @Override
+    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, BlockEntity blockEntity) {
+        final int stackCount = getStackCount(meta) + 1;
+
+        if (dropCause == EnumDropCause.PICK_BLOCK) {
+            return new ItemStack[] { new ItemStack(this, 1, 0) };
+        } else if (dropCause == EnumDropCause.SILK_TOUCH) {
+            return new ItemStack[] { new ItemStack(this, 1, meta & MASK_STACK_COUNT)};
+        } else {
+            return new ItemStack[] { new ItemStack(this, stackCount, 0) };
+        }
+    }
+
+    @Override
+    public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit) {
+        final int metadata = world.getBlockMetadata(x, y, z);
+        final int currentStackCount = getStackCount(metadata);
+        if (currentStackCount >= MAX_STACK_COUNT) {
+            return false;
+        }
+
+        final ItemStack heldItem = player.getHeldItem();
+        if (heldItem == null || heldItem.stackSize < 1 || heldItem.getItem().id != this.id) {
+            return false;
+        }
+
+        final int newMetadata = setPermanent(setStackCount(metadata, currentStackCount + 1), true);
+        world.setBlockMetadataWithNotify(x, y, z, newMetadata);
+        world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, this, EnumBlockSoundEffectType.PLACE);
+        heldItem.consumeItem(player);
+        return true;
+    }
+
+    public static int getStackCount(int metadata) {
+        return (metadata & MASK_STACK_COUNT) >> OFFSET_STACK_COUNT;
+    }
+
+    public static int setStackCount(int metadata, int stackCount) {
+        return (metadata & ~MASK_STACK_COUNT) | ((stackCount << OFFSET_STACK_COUNT) & MASK_STACK_COUNT);
+    }
+}
diff --git a/src/main/java/net/minecraft/core/block/SteelFenceBlock.java b/src/main/java/net/minecraft/core/block/SteelFenceBlock.java
index 2f554c0a6..3dba8a56f 100644
--- a/src/main/java/net/minecraft/core/block/SteelFenceBlock.java
+++ b/src/main/java/net/minecraft/core/block/SteelFenceBlock.java
@@ -12,6 +12,6 @@ public class SteelFenceBlock extends ThinFenceBlock {
     @Override
     public boolean canConnectTo(WorldSource world, int x, int y, int z) {
         int id = world.getBlockId(x, y, z);
-        return Block.hasTag(id, BlockTags.CHAINLINK_FENCES_CONNECT) || (Block.blocksList[id] != null && (Block.blocksList[id].blockMaterial == Material.stone || Block.blocksList[id].blockMaterial == Material.metal));
+        return Block.hasTag(id, BlockTags.CHAINLINK_FENCES_CONNECT) || (Block.blocksList[id] != null && (Block.blocksList[id].blockMaterial.isStone() || Block.blocksList[id].blockMaterial == Material.metal));
     }
 }
diff --git a/src/main/java/net/minecraft/core/block/TallGrassBlock.java b/src/main/java/net/minecraft/core/block/TallGrassBlock.java
index 860bfff67..be059352c 100644
--- a/src/main/java/net/minecraft/core/block/TallGrassBlock.java
+++ b/src/main/java/net/minecraft/core/block/TallGrassBlock.java
@@ -22,12 +22,12 @@ public class TallGrassBlock extends FlowerBlock
     }
 
     @Override
-    protected boolean canThisPlantGrowOnThisBlockID(int i) {
-    	Block block = Block.getBlock(i);
+    protected boolean mayPlaceOn(int blockId) {
+    	Block block = Block.getBlock(blockId);
     	if(block != null && block instanceof MossBlock) {
     		return true;
     	}
-    	return super.canThisPlantGrowOnThisBlockID(i);
+    	return super.mayPlaceOn(blockId);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/entity/BlastFurnaceBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/BlastFurnaceBlockEntity.java
index 5b6b34e58..f19d28083 100644
--- a/src/main/java/net/minecraft/core/block/entity/BlastFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/BlastFurnaceBlockEntity.java
@@ -146,7 +146,7 @@ public class BlastFurnaceBlockEntity extends FurnaceBlockEntity
         if (worldObj != null) {
             BlastFurnaceBlock.updateFurnaceBlockState(forceLit | (currentBurnTime > 0), worldObj, x, y, z);
         } else if (carriedBlock != null) {
-            carriedBlock.block = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_BLAST_ACTIVE : Blocks.FURNACE_BLAST_IDLE;
+            carriedBlock.blockId = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_BLAST_ACTIVE.id : Blocks.FURNACE_BLAST_IDLE.id;
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/block/entity/BlockEntity.java b/src/main/java/net/minecraft/core/block/entity/BlockEntity.java
index a3e142cc9..22701c5b4 100644
--- a/src/main/java/net/minecraft/core/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/BlockEntity.java
@@ -1,9 +1,8 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.Block;
 import com.mojang.nbt.CompoundTag;
-import net.minecraft.core.block.piston.MovingPistonBlockEntity;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.Mob;
@@ -14,20 +13,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.ICarriable;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.slf4j.Logger;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
 
 public class BlockEntity implements ICarriable
 {
-    private static final Logger LOGGER = LogUtils.getLogger();
-
-    private static final Map<String, Class<? extends BlockEntity>> nameToClassMap = new HashMap<>();
-    private static final Map<Class<? extends BlockEntity>, String> classToNameMap = new HashMap<>();
     public @Nullable World worldObj; // Null when loading data from nbt and null when held by entity
     public @Nullable CarriedBlock carriedBlock;
     public int x;
@@ -39,78 +28,10 @@ public class BlockEntity implements ICarriable
     {
     }
 
-    private static void addMapping(Class<? extends BlockEntity> entityClass, String name)
-    {
-        if(nameToClassMap.containsKey(name))
-        {
-            throw new IllegalArgumentException("Duplicate id: " + name);
-        } else
-        {
-            nameToClassMap.put(name, entityClass);
-            classToNameMap.put(entityClass, name);
-        }
-    }
-
-    public void readFromNBT(CompoundTag nbttagcompound)
-    {
-        x = nbttagcompound.getInteger("x");
-        y = nbttagcompound.getInteger("y");
-        z = nbttagcompound.getInteger("z");
-    }
-
-    public void writeToNBT(CompoundTag nbttagcompound)
-    {
-        String name = classToNameMap.get(getClass());
-        if(name == null)
-        {
-            throw new RuntimeException(getClass() + " is missing a mapping! This is a bug!");
-        } else
-        {
-            nbttagcompound.putString("id", name);
-            nbttagcompound.putInt("x", x);
-            nbttagcompound.putInt("y", y);
-            nbttagcompound.putInt("z", z);
-        }
-    }
-
     public void tick()
     {
     }
 
-    public static BlockEntity createAndLoadEntity(CompoundTag nbttagcompound)
-    {
-        BlockEntity blockEntity = null;
-        Class<? extends BlockEntity> entityClass = nameToClassMap.get(nbttagcompound.getString("id"));
-        try
-        {
-            if(entityClass != null)
-            {
-                blockEntity = entityClass.newInstance();
-            }
-        }
-        catch(Exception exception)
-        {
-            LOGGER.error("Exception when instancing class '{}'!", entityClass.getSimpleName(), exception);
-        }
-        if(blockEntity != null)
-        {
-            blockEntity.readFromNBT(nbttagcompound);
-        } else
-        {
-            LOGGER.warn("Skipping BlockEntity with id {}", nbttagcompound.getString("id"));
-        }
-        return blockEntity;
-    }
-
-    public static Class<? extends BlockEntity> getClassFromID(String id)
-    {
-        return nameToClassMap.get(id);
-    }
-
-    public int getMovedData()
-    {
-        return worldObj.getBlockMetadata(x, y, z);
-    }
 
     public void setChanged()
     {
@@ -125,17 +46,37 @@ public class BlockEntity implements ICarriable
         return null;
     }
 
-    public double getDistanceFrom(double d, double d1, double d2)
-    {
-        double d3 = ((double) x + 0.5D) - d;
-        double d4 = ((double) y + 0.5D) - d1;
-        double d5 = ((double) z + 0.5D) - d2;
-        return d3 * d3 + d4 * d4 + d5 * d5;
+    public int getBlockId() {
+        if (carriedBlock != null) {
+            return carriedBlock.blockId;
+        } else {
+            return worldObj.getBlockId(x, y, z);
+        }
+    }
+
+    public Block getBlock() {
+        if (carriedBlock != null) {
+            return carriedBlock.block();
+        } else {
+            return worldObj.getBlock(x, y, z);
+        }
+    }
+
+    public int getBlockMeta() {
+        if (carriedBlock != null) {
+            return carriedBlock.metadata;
+        } else {
+            return worldObj.getBlockMetadata(x, y, z);
+        }
     }
 
-    public Block getBlockType()
+
+    public double getDistanceFrom(double x, double y, double z)
     {
-        return Block.blocksList[worldObj.getBlockId(x, y, z)];
+        double dx = ((double) this.x + 0.5D) - x;
+        double dy = ((double) this.y + 0.5D) - y;
+        double dz = ((double) this.z + 0.5D) - z;
+        return dx * dx + dy * dy + dz * dz;
     }
 
     public boolean isInvalid()
@@ -153,24 +94,26 @@ public class BlockEntity implements ICarriable
         tileEntityInvalid = false;
     }
 
-    static 
+    public void readFromNBT(CompoundTag nbttagcompound)
     {
-        addMapping(FurnaceBlockEntity.class, "Furnace");
-        addMapping(ChestBlockEntity.class, "Chest");
-        addMapping(JukeboxBlockEntity.class, "RecordPlayer");
-        addMapping(DispenserBlockEntity.class, "Trap");
-        addMapping(SignBlockEntity.class, "Sign");
-        addMapping(MobSpawnerBlockEntity.class, "MobSpawner");
-        addMapping(NoteBlockEntity.class, "Music");
-        addMapping(MovingPistonBlockEntity.class, "Piston");
-        addMapping(BlastFurnaceBlockEntity.class, "BlastFurnace");
-        addMapping(SensorBlockEntity.class, "Sensor");
-        addMapping(TrommelBlockEntity.class, "Trommel");
-        addMapping(BasketBlockEntity.class, "Basket");
-        addMapping(FlagBlockEntity.class, "Flag");
-        addMapping(SeatBlockEntity.class, "Seat");
-        addMapping(FlowerJarBlockEntity.class, "FlowerJar");
-        addMapping(GoldMeshBlockEntity.class, "MeshGold");
+        x = nbttagcompound.getInteger("x");
+        y = nbttagcompound.getInteger("y");
+        z = nbttagcompound.getInteger("z");
+    }
+
+    public void writeToNBT(CompoundTag nbttagcompound)
+    {
+        String name = BlockEntityDispatcher.getIDFromClass(getClass());
+        if(name == null)
+        {
+            throw new RuntimeException(getClass() + " is missing a mapping! This is a bug!");
+        } else
+        {
+            nbttagcompound.putString("id", name);
+            nbttagcompound.putInt("x", x);
+            nbttagcompound.putInt("y", y);
+            nbttagcompound.putInt("z", z);
+        }
     }
 
     @Override
@@ -190,7 +133,7 @@ public class BlockEntity implements ICarriable
 
         Block currentBlock = world.getBlock(x, y, z);
         if (currentBlock != null && !currentBlock.hasTag(BlockTags.PLACE_OVERWRITES)) return false;
-        world.setBlockAndMetadataWithNotify(x, y, z, carriedBlock.block.id, carriedBlock.metadata);
+        world.setBlockAndMetadataWithNotify(x, y, z, carriedBlock.blockId, carriedBlock.metadata);
 
         worldObj = world;
         this.carriedBlock = null;
@@ -221,7 +164,7 @@ public class BlockEntity implements ICarriable
         if (world.isClientSide) return;
         dropContents(world, holderX, holderY, holderZ);
         assert carriedBlock != null;
-        carriedBlock.block.dropBlockWithCause(world, EnumDropCause.WORLD, holderX, holderY, holderZ, carriedBlock.metadata, this, null); // TODO this might be scuffed since the position won't have correlated to a real block
+        carriedBlock.block().dropBlockWithCause(world, EnumDropCause.WORLD, holderX, holderY, holderZ, carriedBlock.metadata, this, null); // TODO this might be scuffed since the position won't have correlated to a real block
     }
 
     @Override
@@ -247,73 +190,4 @@ public class BlockEntity implements ICarriable
         return new CarriedBlock(holder, currentBlock, currentMeta, this);
     }
 
-    public static class CarriedBlock implements ICarriable {
-        // Ignore warnings, nbt read process *should* guarantee these to be non-null
-        public @NotNull Block block;
-        public int metadata;
-        public @NotNull BlockEntity entity;
-        public @NotNull Entity holder;
-        public @NotNull World world;
-        public CarriedBlock(@NotNull Entity holder, @NotNull Block block, int metadata, @NotNull BlockEntity entity) {
-            this.holder = holder;
-            this.block = block;
-            this.metadata = metadata;
-            this.entity = entity;
-            this.world = holder.world;
-        }
-
-        protected CarriedBlock() {
-
-        }
-
-        @Override
-        public void heldTick(World world, Entity holder) {
-            entity.heldTick(world, holder);
-        }
-
-        @Override
-        public boolean tryPlace(World world, Entity holder, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
-            return entity.tryPlace(world, holder, blockX, blockY, blockZ, side, xPlaced, yPlaced);
-        }
-
-        @Override
-        public void drop(World world, Entity holder) {
-            entity.drop(world, holder);
-        }
-
-        @Override
-        public boolean canBeCarried(World world, Entity potentialHolder) {
-            return entity.canBeCarried(world, potentialHolder);
-        }
-
-        @Override
-        public ICarriable pickup(World world, Entity holder) {
-            return entity.pickup(world, holder);
-        }
-
-        @Override
-        public void writeToNBT(CompoundTag tag) {
-            CompoundTag entityTag = new CompoundTag();
-            entity.writeToNBT(entityTag);
-            tag.put("entity", entityTag);
-            tag.putInt("block", block.id);
-            tag.putShort("meta", (short) metadata);
-            tag.putString("type", "blockEntity");
-        }
-
-        @Override
-        public void readFromNBT(CompoundTag tag) {
-            entity = createAndLoadEntity(tag.getCompound("entity"));
-            entity.carriedBlock = this;
-            block = Objects.requireNonNull(Block.getBlock(tag.getInteger("block")));
-            metadata = tag.getShort("meta");
-        }
-
-        public static CarriedBlock createAndLoadCarriedBlock(@NotNull Entity holder, CompoundTag tag) {
-            CarriedBlock carriedBlock = new CarriedBlock();
-            carriedBlock.holder = holder;
-            carriedBlock.readFromNBT(tag);
-            return carriedBlock;
-        }
-    }
 }
diff --git a/src/main/java/net/minecraft/core/block/entity/BlockEntityDispatcher.java b/src/main/java/net/minecraft/core/block/entity/BlockEntityDispatcher.java
new file mode 100644
index 000000000..953a78d42
--- /dev/null
+++ b/src/main/java/net/minecraft/core/block/entity/BlockEntityDispatcher.java
@@ -0,0 +1,83 @@
+package net.minecraft.core.block.entity;
+
+import com.mojang.logging.LogUtils;
+import com.mojang.nbt.CompoundTag;
+import net.minecraft.core.block.piston.MovingPistonBlockEntity;
+import org.slf4j.Logger;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class BlockEntityDispatcher {
+    private static final Logger LOGGER = LogUtils.getLogger();
+
+    private static final Map<String, Class<? extends BlockEntity>> nameToClassMap = new HashMap<>();
+    private static final Map<Class<? extends BlockEntity>, String> classToNameMap = new HashMap<>();
+
+    public static void addMapping(Class<? extends BlockEntity> entityClass, String name)
+    {
+        if(nameToClassMap.containsKey(name))
+        {
+            throw new IllegalArgumentException("Duplicate id: " + name);
+        } else
+        {
+            nameToClassMap.put(name, entityClass);
+            classToNameMap.put(entityClass, name);
+        }
+    }
+
+    public static BlockEntity createAndLoadEntity(CompoundTag nbttagcompound)
+    {
+        BlockEntity blockEntity = null;
+        Class<? extends BlockEntity> entityClass = nameToClassMap.get(nbttagcompound.getString("id"));
+        try
+        {
+            if(entityClass != null)
+            {
+                blockEntity = entityClass.newInstance();
+            }
+        }
+        catch(Exception exception)
+        {
+            LOGGER.error("Exception when instancing class '{}'!", entityClass.getSimpleName(), exception);
+        }
+        if(blockEntity != null)
+        {
+            blockEntity.readFromNBT(nbttagcompound);
+        } else
+        {
+            LOGGER.warn("Skipping BlockEntity with id {}", nbttagcompound.getString("id"));
+        }
+        return blockEntity;
+    }
+
+    public static Class<? extends BlockEntity> getClassFromID(String id)
+    {
+        return nameToClassMap.get(id);
+    }
+
+    public static String getIDFromClass(Class<? extends BlockEntity> clazz)
+    {
+        return classToNameMap.get(clazz);
+    }
+
+    static
+    {
+        addMapping(FurnaceBlockEntity.class, "Furnace");
+        addMapping(ChestBlockEntity.class, "Chest");
+        addMapping(JukeboxBlockEntity.class, "RecordPlayer");
+        addMapping(DispenserBlockEntity.class, "Trap");
+        addMapping(SignBlockEntity.class, "Sign");
+        addMapping(MobSpawnerBlockEntity.class, "MobSpawner");
+        addMapping(NoteBlockEntity.class, "Music");
+        addMapping(MovingPistonBlockEntity.class, "Piston");
+        addMapping(BlastFurnaceBlockEntity.class, "BlastFurnace");
+        addMapping(SensorBlockEntity.class, "Sensor");
+        addMapping(TrommelBlockEntity.class, "Trommel");
+        addMapping(BasketBlockEntity.class, "Basket");
+        addMapping(FlagBlockEntity.class, "Flag");
+        addMapping(SeatBlockEntity.class, "Seat");
+        addMapping(FlowerJarBlockEntity.class, "FlowerJar");
+        addMapping(GoldMeshBlockEntity.class, "MeshGold");
+    }
+}
diff --git a/src/main/java/net/minecraft/core/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/ChestBlockEntity.java
index a9b147df7..2d34a4b72 100644
--- a/src/main/java/net/minecraft/core/block/entity/ChestBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/ChestBlockEntity.java
@@ -8,6 +8,7 @@ package net.minecraft.core.block.entity;
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.ChestBlock;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.ItemEntity;
 import net.minecraft.core.entity.player.Player;
diff --git a/src/main/java/net/minecraft/core/block/entity/DispenserBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/DispenserBlockEntity.java
index 63a328024..4dc9298a7 100644
--- a/src/main/java/net/minecraft/core/block/entity/DispenserBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/DispenserBlockEntity.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.block.entity;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.ItemEntity;
 import net.minecraft.core.entity.player.Player;
diff --git a/src/main/java/net/minecraft/core/block/entity/FlowerJarBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/FlowerJarBlockEntity.java
index c94621a16..ed04eedf6 100644
--- a/src/main/java/net/minecraft/core/block/entity/FlowerJarBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/FlowerJarBlockEntity.java
@@ -2,6 +2,7 @@ package net.minecraft.core.block.entity;
 
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.StackedFlowerBlock;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.item.ItemStack;
@@ -12,11 +13,13 @@ import net.minecraft.core.world.World;
 public class FlowerJarBlockEntity extends BlockEntity {
 
     public int flowerInPot;
+    public int flowerData;
 
     @Override
     public void readFromNBT(CompoundTag tag) {
         super.readFromNBT(tag);
         flowerInPot = tag.getInteger("PlantedId");
+        flowerData = Byte.toUnsignedInt(tag.getByteOrDefault("PlantedData", (byte) 0));
     }
 
     @Override
@@ -24,6 +27,7 @@ public class FlowerJarBlockEntity extends BlockEntity {
         super.writeToNBT(tag);
         if (flowerInPot > 0) {
             tag.putInt("PlantedId", flowerInPot);
+            tag.putByte("PlantedData", (byte) flowerData);
         }
     }
 
@@ -31,10 +35,14 @@ public class FlowerJarBlockEntity extends BlockEntity {
     public void dropContents(World world, int x, int y, int z) {
         super.dropContents(world, x, y, z);
         if (flowerInPot > 0 && Block.hasTag(flowerInPot, BlockTags.PLANTABLE_IN_JAR)) {
-            flowerInPot = 0;
             if (!world.isClientSide) {
-                world.dropItem(x, y, z, new ItemStack(flowerInPot, 1, 0));
+                if (Block.getBlock(flowerInPot) instanceof StackedFlowerBlock) {
+                    world.dropItem(x, y, z, new ItemStack(flowerInPot, StackedFlowerBlock.getStackCount(flowerData) + 1, 0));
+                } else {
+                    world.dropItem(x, y, z, new ItemStack(flowerInPot, 1, flowerData));
+                }
             }
+            flowerInPot = 0;
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/block/entity/FurnaceBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/FurnaceBlockEntity.java
index c88aeb46b..7f42cf2cd 100644
--- a/src/main/java/net/minecraft/core/block/entity/FurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/FurnaceBlockEntity.java
@@ -11,6 +11,7 @@ import com.mojang.nbt.ListTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.FurnaceBlock;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.crafting.LookupFuelFurnace;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.recipe.entry.RecipeEntryFurnace;
@@ -311,7 +312,7 @@ public class FurnaceBlockEntity extends BlockEntity
         if (worldObj != null) {
             FurnaceBlock.updateFurnaceBlockState( forceLit | (currentBurnTime > 0), worldObj, x, y, z);
         } else if (carriedBlock != null) {
-            carriedBlock.block = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_STONE_ACTIVE : Blocks.FURNACE_STONE_IDLE;
+            carriedBlock.blockId = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_STONE_ACTIVE.id : Blocks.FURNACE_STONE_IDLE.id;
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/block/entity/NoteBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/NoteBlockEntity.java
index cbe8141d8..734eafd2b 100644
--- a/src/main/java/net/minecraft/core/block/entity/NoteBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/NoteBlockEntity.java
@@ -54,7 +54,7 @@ public class NoteBlockEntity extends BlockEntity
         }
         Material material = world.getBlockMaterial(x, y - 1, z);
         byte noteIndex = 0;
-        if(material == Material.stone)
+        if(material.isStone())
         {
             noteIndex = 1;
         }
diff --git a/src/main/java/net/minecraft/core/block/entity/SeatBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/SeatBlockEntity.java
index 7d7e15ea0..c2f64de27 100644
--- a/src/main/java/net/minecraft/core/block/entity/SeatBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/SeatBlockEntity.java
@@ -1,7 +1,9 @@
 package net.minecraft.core.block.entity;
 
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.Entity;
+import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.World;
 
@@ -10,18 +12,24 @@ public class SeatBlockEntity
     implements IVehicle {
     private Entity passenger;
 
-    public SeatBlockEntity() {
+    public Block seat;
+    public SeatBlockEntity(Block seat) {
         passenger = null;
+        this.seat = seat;
     }
 
     @Override
     public void tick() {
         if (passenger != null) {
-            worldObj.updateEntity(passenger);
+            if (carriedBlock != null) {
+                carriedBlock.world.updateEntity(passenger);
+            } else {
+                worldObj.updateEntity(passenger);
+            }
         }
 
         // TODO the server really needs a better way of telling the client that a tile entity no longer exists, but this works to fix the client thinking that the seat remains if its broken in multiplayer
-        if (worldObj.getBlock(x, y, z) != Blocks.SEAT){
+        if (worldObj != null && worldObj.getBlock(x, y, z) != seat) {
             ejectRider();
         }
     }
@@ -39,29 +47,56 @@ public class SeatBlockEntity
         this.passenger = null;
         entity.vehicle = null;
 
-        if (isSafe(this.x, this.y + 1, this.z)) {
-            entity.moveTo(this.x + 0.5, this.y + 1, this.z + 0.5, entity.yRot, entity.xRot);
-        } else if (isSafe(this.x - 1, this.y, this.z)) {
-            entity.moveTo(this.x - 0.5, this.y, this.z + 0.5, entity.yRot, entity.xRot);
-        } else if (isSafe(this.x + 1, this.y, this.z)) {
-            entity.moveTo(this.x + 1.5, this.y, this.z + 0.5, entity.yRot, entity.xRot);
-        } else if (isSafe(this.x, this.y, this.z - 1)) {
-            entity.moveTo(this.x + 0.5, this.y, this.z - 0.5, entity.yRot, entity.xRot);
-        } else if (isSafe(this.x, this.y, this.z + 1)) {
-            entity.moveTo(this.x + 0.5, this.y, this.z + 1.5, entity.yRot, entity.xRot);
+        double x, y, z;
+        if (carriedBlock != null) {
+            x = carriedBlock.holder.x;
+            y = carriedBlock.holder.y;
+            z = carriedBlock.holder.z;
         } else {
-            entity.moveTo(this.x + 0.5, this.y + 1, this.z + 0.5, entity.yRot, entity.xRot);
+            x = this.x;
+            y = this.y;
+            z = this.z;
+        }
+
+        if (isSafe(x, y + 1, z)) {
+            entity.moveTo(x + 0.5, y + 1, z + 0.5, entity.yRot, entity.xRot);
+        } else if (isSafe(x - 1, y, z)) {
+            entity.moveTo(x - 0.5, y, z + 0.5, entity.yRot, entity.xRot);
+        } else if (isSafe(x + 1, y, z)) {
+            entity.moveTo(x + 1.5, y, z + 0.5, entity.yRot, entity.xRot);
+        } else if (isSafe(x, y, z - 1)) {
+            entity.moveTo(x + 0.5, y, z - 0.5, entity.yRot, entity.xRot);
+        } else if (isSafe(x, y, z + 1)) {
+            entity.moveTo(x + 0.5, y, z + 1.5, entity.yRot, entity.xRot);
+        } else {
+            entity.moveTo(x + 0.5, y + 1, z + 0.5, entity.yRot, entity.xRot);
         }
 
         return entity;
     }
 
-    private boolean isSafe(int x, int y, int z) {
-        return !worldObj.isBlockNormalCube(x, y, z) && !worldObj.isBlockNormalCube(x, y + 1, z);
+    private boolean isSafe(double x, double y, double z) {
+        int _x = MathHelper.round(x);
+        int _y = MathHelper.round(y);
+        int _z = MathHelper.round(z);
+        if (carriedBlock != null) {
+            return !carriedBlock.world.isBlockNormalCube(_x, _y, _z) && !carriedBlock.world.isBlockNormalCube(_x, _y + 1, _z);
+        } else {
+            return !worldObj.isBlockNormalCube(_x, _y, _z) && !worldObj.isBlockNormalCube(_x, _y + 1, _z);
+        }
     }
     @Override
     public void positionRider() {
-        passenger.setPos(this.x + 0.5, this.y + 0.5 + passenger.getRidingHeight(), z + 0.5);
+        if (carriedBlock != null) {
+            passenger.setPos(carriedBlock.holder.x, carriedBlock.holder.y + passenger.getRidingHeight(), carriedBlock.holder.z);
+        } else {
+            passenger.setPos(this.x + 0.5, this.y + 0.5 + passenger.getRidingHeight(), z + 0.5);
+        }
+    }
+
+    @Override
+    public void dropContents(World world, int x, int y, int z) {
+        ejectRider();
     }
 
     @Override
@@ -76,7 +111,11 @@ public class SeatBlockEntity
 
     @Override
     public void moveExitingEntity(Entity entity) {
-        entity.moveTo(this.x, this.y + 2, this.z, entity.yRot, entity.xRot);
+        if (carriedBlock != null) {
+            entity.moveTo(carriedBlock.holder.x, carriedBlock.holder.y + 2, carriedBlock.holder.z, entity.yRot, entity.xRot);
+        } else {
+            entity.moveTo(this.x, this.y + 2, this.z, entity.yRot, entity.xRot);
+        }
     }
 
     @Override
@@ -89,4 +128,8 @@ public class SeatBlockEntity
         return 0;
     }
 
+    @Override
+    public void heldTick(World world, Entity holder) {
+        tick();
+    }
 }
diff --git a/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java
index ad118d63f..b4b337360 100644
--- a/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java
@@ -8,6 +8,7 @@ import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.ChestBlock;
 import net.minecraft.core.block.TrommelBlock;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.crafting.LookupFuelFurnace;
 import net.minecraft.core.data.DataLoader;
 import net.minecraft.core.data.registry.recipe.entry.RecipeEntryTrommel;
@@ -186,7 +187,7 @@ public class TrommelBlockEntity extends BlockEntity
             			if (worldObj != null) {
                             TrommelBlock.updateTrommelBlockState(true, worldObj, x, y, z);
                         } else if (carriedBlock != null) {
-                            carriedBlock.block = Blocks.TROMMEL_ACTIVE;
+                            carriedBlock.blockId = Blocks.TROMMEL_ACTIVE.id;
                         }
                         flag1 = true;
                     }
@@ -234,7 +235,7 @@ public class TrommelBlockEntity extends BlockEntity
                 if (worldObj != null) {
                     TrommelBlock.updateTrommelBlockState(burnTime > 0, worldObj, x, y, z);
                 } else if (carriedBlock != null) {
-                    carriedBlock.block = burnTime > 0 ? Blocks.TROMMEL_ACTIVE : Blocks.TROMMEL_IDLE;
+                    carriedBlock.blockId = burnTime > 0 ? Blocks.TROMMEL_ACTIVE.id : Blocks.TROMMEL_IDLE.id;
                 }
             }
         }
@@ -344,7 +345,7 @@ public class TrommelBlockEntity extends BlockEntity
                 slimeMob.moveTo(x + (double)f, y + 1D, z + (double)f1, random.nextFloat() * 360F, 0.0F);
                 worldObj.entityJoinedWorld(slimeMob);
             } else if (carriedBlock != null) {
-                slimeMob.moveTo(carriedBlock.holder.x + (double)f, carriedBlock.holder.y + 1D, carriedBlock.holder.z + (double)f1, random.nextFloat() * 360F, 0.0F);
+                slimeMob.moveTo(carriedBlock.holder.x + (double)f, carriedBlock.holder.y + carriedBlock.holder.heightOffset, carriedBlock.holder.z + (double)f1, random.nextFloat() * 360F, 0.0F);
                 carriedBlock.world.entityJoinedWorld(slimeMob);
             }
         }
diff --git a/src/main/java/net/minecraft/core/block/material/Material.java b/src/main/java/net/minecraft/core/block/material/Material.java
index 38333208f..e393e9cda 100644
--- a/src/main/java/net/minecraft/core/block/material/Material.java
+++ b/src/main/java/net/minecraft/core/block/material/Material.java
@@ -16,6 +16,7 @@ public class Material
     private boolean notSolidBlocking;
     public final MaterialColor color;
     private boolean alwaysDestroyable;
+    private boolean isStone;
     private int pushReaction = PISTON_PUSHABLE;
     private int lightningConductivity = LIGHTNING_NEUTRAL;
 
@@ -45,6 +46,13 @@ public class Material
         return true;
     }
 
+    public Material setAsStone() {
+        isStone = true;
+        return this;
+    }
+
+    public boolean isStone() { return isStone; }
+
     public Material notSolidBlocking()
     {
         notSolidBlocking = true;
@@ -126,14 +134,14 @@ public class Material
     public static final Material dirt = new Material(MaterialColor.dirt);
     public static final Material wood = new Material(MaterialColor.wood).flammable();
 
-    public static final Material stone = new Material(MaterialColor.stone).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
-    public static final Material basalt = new Material(MaterialColor.basalt).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
-    public static final Material limestone = new Material(MaterialColor.limestone).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
-    public static final Material granite = new Material(MaterialColor.granite).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
-    public static final Material permafrost = new Material(MaterialColor.permafrost).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
-    public static final Material marble = new Material(MaterialColor.marble).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
-    public static final Material slate = new Material(MaterialColor.slate).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
-    public static final Material netherrack = new Material(MaterialColor.netherrack).setConductivity(LIGHTNING_LIGHT_INSULATOR).notAlwaysDestroyable();
+    public static final Material stone = new Material(MaterialColor.stone).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
+    public static final Material basalt = new Material(MaterialColor.basalt).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
+    public static final Material limestone = new Material(MaterialColor.limestone).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
+    public static final Material granite = new Material(MaterialColor.granite).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
+    public static final Material permafrost = new Material(MaterialColor.permafrost).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
+    public static final Material marble = new Material(MaterialColor.marble).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
+    public static final Material slate = new Material(MaterialColor.slate).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
+    public static final Material netherrack = new Material(MaterialColor.netherrack).setConductivity(LIGHTNING_LIGHT_INSULATOR).setAsStone().notAlwaysDestroyable();
 
     public static final Material metal = new Material(MaterialColor.metal).setConductivity(LIGHTNING_STRONG_CONDUCTOR).notAlwaysDestroyable();
     public static final Material water = new LiquidMaterial(MaterialColor.water).setConductivity(LIGHTNING_LIGHT_CONDUCTOR).destroyOnPush();
diff --git a/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java b/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
new file mode 100644
index 000000000..dd643a210
--- /dev/null
+++ b/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
@@ -0,0 +1,137 @@
+package net.minecraft.core.block.motion;
+
+import com.mojang.nbt.CompoundTag;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.block.entity.BlockEntityDispatcher;
+import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.entity.Entity;
+import net.minecraft.core.entity.Mob;
+import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.util.helper.Side;
+import net.minecraft.core.world.ICarriable;
+import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Objects;
+
+public class CarriedBlock implements ICarriable {
+    public int blockId;
+    public int metadata;
+    public @Nullable BlockEntity entity;
+    // Ignore warnings, nbt read process *should* guarantee these to be non-null
+    public @NotNull Entity holder;
+    public @NotNull World world;
+    public CarriedBlock(@NotNull Entity holder, @NotNull Block block, int metadata, @Nullable BlockEntity entity) {
+        this(holder, block.id, metadata, entity);
+    }
+
+    public CarriedBlock(@NotNull Entity holder, int blockId, int metadata, @Nullable BlockEntity entity) {
+        this.holder = holder;
+        this.blockId = blockId;
+        this.metadata = metadata;
+        this.entity = entity;
+        this.world = holder.world;
+    }
+
+    protected CarriedBlock() {
+
+    }
+
+    public Block block() {
+        return Block.getBlock(blockId);
+    }
+
+    @Override
+    public void heldTick(World world, Entity holder) {
+        if (entity != null) {
+            entity.heldTick(world, holder);
+        }
+    }
+
+    @Override
+    public boolean tryPlace(World world, Entity holder, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+        if (entity != null) {
+            return entity.tryPlace(world, holder, blockX, blockY, blockZ, side, xPlaced, yPlaced);
+        } else {
+            int x = blockX + side.getOffsetX();
+            int y = blockY + side.getOffsetY();
+            int z = blockZ + side.getOffsetZ();
+
+            Block currentBlock = world.getBlock(x, y, z);
+            if (currentBlock != null && !currentBlock.hasTag(BlockTags.PLACE_OVERWRITES)) return false;
+            world.setBlockAndMetadataWithNotify(x, y, z, blockId, metadata);
+
+            Block b = world.getBlock(x, y, z);
+            if (b != null && holder instanceof Mob) {
+                b.onBlockPlacedByMob(world, x, y, z, side, (Mob) holder, yPlaced);
+            }
+            return true;
+        }
+    }
+
+    @Override
+    public void drop(World world, Entity holder) {
+        if (entity != null) {
+            entity.drop(world, holder);
+        } else {
+            final int holderX = MathHelper.floor(holder.x);
+            final int holderY = MathHelper.floor(holder.y);
+            final int holderZ = MathHelper.floor(holder.z);
+            for (int _y = holderY - 1; _y <= holderY + 1; _y++) {
+                for (int _x = holderX - 1; _x <= holderX + 1; _x++) {
+                    for (int _z = holderZ - 1; _z <= holderZ + 1; _z++) {
+                        if (tryPlace(world, holder, _x, _y - 1, _z, Side.TOP, 0, 0)) {
+                            return;
+                        }
+                    }
+                }
+            }
+            if (world.isClientSide) return;
+            block().dropBlockWithCause(world, EnumDropCause.WORLD, holderX, holderY, holderZ, metadata, entity, null); // TODO this might be scuffed since the position won't have correlated to a real block
+        }
+    }
+
+    @Override
+    public boolean canBeCarried(World world, Entity potentialHolder) {
+        return true;
+    }
+
+    @Override
+    public ICarriable pickup(World world, Entity holder) {
+        return this;
+    }
+
+    @Override
+    public void writeToNBT(CompoundTag tag) {
+        if (entity != null) {
+            CompoundTag entityTag = new CompoundTag();
+            entity.writeToNBT(entityTag);
+            tag.put("entity", entityTag);
+        }
+        tag.putInt("block", blockId);
+        tag.putShort("meta", (short) metadata);
+        tag.putString("type", TYPE_BLOCK);
+    }
+
+    @Override
+    public void readFromNBT(CompoundTag tag) {
+        if (tag.containsKey("entity")) {
+            entity = BlockEntityDispatcher.createAndLoadEntity(tag.getCompound("entity"));
+            if (entity != null) {
+                entity.carriedBlock = this;
+            }
+        }
+        blockId = tag.getInteger("block");
+        metadata = tag.getShort("meta");
+    }
+
+    public static CarriedBlock createAndLoadCarriedBlock(@NotNull Entity holder, CompoundTag tag) {
+        CarriedBlock carriedBlock = new CarriedBlock();
+        carriedBlock.holder = holder;
+        carriedBlock.readFromNBT(tag);
+        return carriedBlock;
+    }
+}
diff --git a/src/main/java/net/minecraft/core/block/piston/MovingPistonBlockEntity.java b/src/main/java/net/minecraft/core/block/piston/MovingPistonBlockEntity.java
index 984ff1830..fbe867f72 100644
--- a/src/main/java/net/minecraft/core/block/piston/MovingPistonBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/piston/MovingPistonBlockEntity.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.block.piston;
 
 import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.block.entity.BlockEntityDispatcher;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.helper.Direction;
@@ -46,7 +47,6 @@ public class MovingPistonBlockEntity extends BlockEntity
         return movedId;
     }
 
-    @Override
 	public int getMovedData()
     {
         return movedData;
@@ -188,7 +188,7 @@ public class MovingPistonBlockEntity extends BlockEntity
         movedData = tag.getInteger("blockData");
         if (tag.containsKey("blockEntity")) {
             CompoundTag entityTag = tag.getCompound("blockEntity");
-            movedEntity = BlockEntity.createAndLoadEntity(entityTag);
+            movedEntity = BlockEntityDispatcher.createAndLoadEntity(entityTag);
         }
         direction = Direction.getDirectionById(tag.getInteger("facing"));
         progressO = progress = tag.getFloat("progress");
diff --git a/src/main/java/net/minecraft/core/block/piston/SteelPistonBaseBlock.java b/src/main/java/net/minecraft/core/block/piston/SteelPistonBaseBlock.java
index 6b05635c1..125b9c0be 100644
--- a/src/main/java/net/minecraft/core/block/piston/SteelPistonBaseBlock.java
+++ b/src/main/java/net/minecraft/core/block/piston/SteelPistonBaseBlock.java
@@ -9,6 +9,7 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.FallingBlockEntity;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.AABB;
+import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
@@ -96,13 +97,19 @@ public class SteelPistonBaseBlock extends PistonBaseBlock{
             xo = x + direction.getOffsetX();
             yo = y + direction.getOffsetY();
             zo = z + direction.getOffsetZ();
-            int blockId = world.getBlockId(xo, yo, zo);
+            Block block = world.getBlock(xo, yo, zo);
+            if (block == null) return true;
             int blockMeta = world.getBlockMetadata(xo, yo, zo);
             BlockEntity blockEntity = world.getBlockEntity(xo, yo, zo);
             world.removeBlockTileEntity(xo, yo, zo);
             world.setBlockWithNotify(xo, yo, zo, 0);
-            FallingBlockEntity fallingBlockEntity = new FallingBlockEntity(world, xo + 0.5, yo + 0.5, zo + 0.5, blockId, blockMeta, blockEntity);
+            FallingBlockEntity fallingBlockEntity = new FallingBlockEntity(world, xo + 0.5, yo + 0.5, zo + 0.5, block.id, blockMeta, blockEntity);
             fallingBlockEntity.hasRemovedBlock = true;
+            if (blockEntity instanceof IVehicle) {
+                Entity rider = ((IVehicle) blockEntity).getPassenger();
+                ((IVehicle) blockEntity).ejectRider();
+                if (rider != null) rider.startRiding(fallingBlockEntity);
+            }
             world.entityJoinedWorld(fallingBlockEntity);
         }
         return true;
@@ -113,7 +120,7 @@ public class SteelPistonBaseBlock extends PistonBaseBlock{
         List<Entity> entityList = new ArrayList<>(world.getEntitiesWithinAABBExcludingEntity(null, AABB.getTemporaryBB((double)x + direction.getOffsetX(), (double)y + direction.getOffsetY(), (double)z + direction.getOffsetZ(), (double)x + direction.getOffsetX() + 1, (double)y + direction.getOffsetY() + 1, (double)z + direction.getOffsetZ() + 1)));
         for (Entity entity : entityList){
             if (entity == null || entity.noPhysics) continue;
-            final double speed = 2; // Todo design solution for making each stacked piston push less effective then the previous
+            final double speed = 2;
             entity.fling(direction.getOffsetX() * speed, direction.getOffsetY() * speed, direction.getOffsetZ() * speed, 1f);
         }
         super.extendEvent(world, x, y, z, data, direction);
diff --git a/src/main/java/net/minecraft/core/data/registry/Registries.java b/src/main/java/net/minecraft/core/data/registry/Registries.java
index 9b061abca..98f563649 100644
--- a/src/main/java/net/minecraft/core/data/registry/Registries.java
+++ b/src/main/java/net/minecraft/core/data/registry/Registries.java
@@ -71,7 +71,7 @@ public class Registries extends Registry<Registry<?>>
         ITEM_GROUPS.register("minecraft:planks",stackListOf(Blocks.PLANKS_OAK, new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 0), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 1), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 2), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 3), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 4), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 5), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 6), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 7), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 8), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 9), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 10), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 11), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 12), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 13), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 14), new ItemStack(Blocks.PLANKS_OAK_PAINTED, 1, 15)));
         ITEM_GROUPS.register("minecraft:grasses",stackListOf(Blocks.GRASS, Blocks.GRASS_RETRO));
         ITEM_GROUPS.register("minecraft:dirt",stackListOf(Blocks.DIRT, Blocks.DIRT_SCORCHED));
-        ITEM_GROUPS.register("minecraft:trommel_dirt",stackListOf(Blocks.DIRT, Blocks.DIRT_SCORCHED, Blocks.GRASS, Blocks.GRASS_RETRO, Blocks.GRASS_SCORCHED, Blocks.PATH_DIRT, Blocks.FARMLAND_DIRT));
+        ITEM_GROUPS.register("minecraft:trommel_dirt",stackListOf(Blocks.DIRT, Blocks.DIRT_SCORCHED, Blocks.GRASS, Blocks.GRASS_RETRO, Blocks.GRASS_SCORCHED, Blocks.PATH_DIRT, Blocks.FARMLAND_DIRT, Blocks.MUD));
         ITEM_GROUPS.register("minecraft:moss_stones",stackListOf(Blocks.MOSS_STONE, Blocks.MOSS_BASALT, Blocks.MOSS_LIMESTONE, Blocks.MOSS_GRANITE));
         ITEM_GROUPS.register("minecraft:logs",stackListOf(Blocks.LOG_OAK, Blocks.LOG_PINE, Blocks.LOG_BIRCH, Blocks.LOG_CHERRY, Blocks.LOG_EUCALYPTUS, Blocks.LOG_OAK_MOSSY, Blocks.LOG_THORN, Blocks.LOG_PALM));
         ITEM_GROUPS.register("minecraft:leaves",stackListOf(Blocks.LEAVES_OAK, Blocks.LEAVES_OAK_RETRO, Blocks.LEAVES_PINE, Blocks.LEAVES_BIRCH, Blocks.LEAVES_CHERRY, Blocks.LEAVES_EUCALYPTUS, Blocks.LEAVES_SHRUB));
diff --git a/src/main/java/net/minecraft/core/entity/Entity.java b/src/main/java/net/minecraft/core/entity/Entity.java
index a12ce083f..09a8590b1 100644
--- a/src/main/java/net/minecraft/core/entity/Entity.java
+++ b/src/main/java/net/minecraft/core/entity/Entity.java
@@ -60,6 +60,7 @@ public abstract class Entity
     public float yRotO;
     public float xRotO;
     public float pushTime;
+    public int pushesThisTick;
     public final AABB bb = AABB.getPermanentBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
     public boolean onGround = false;
     public boolean horizontalCollision;
@@ -235,6 +236,7 @@ public abstract class Entity
 
     public void baseTick()
     {
+        pushesThisTick = 0;
         pushTime *= 0.98f;
         if (pushTime < 0.001f){
             pushTime = 0;
@@ -691,10 +693,12 @@ public abstract class Entity
     }
 
     public void fling(double xd, double yd, double zd, float pushTime) {
+        this.pushesThisTick++;
         this.fallDistance = 0;
-        this.xd += xd;
-        this.yd += yd;
-        this.zd += zd;
+        double scalar = Math.sqrt(pushesThisTick) - Math.sqrt(pushesThisTick - 1);
+        this.xd += xd * scalar;
+        this.yd += yd * scalar;
+        this.zd += zd * scalar;
         if (pushTime > this.pushTime) {
             this.pushTime = pushTime;
         }
@@ -1148,10 +1152,10 @@ public abstract class Entity
             float f = ((float)((i >> 0) % 2) - 0.5F) * bbWidth * 0.9F;
             float f1 = ((float)((i >> 1) % 2) - 0.5F) * 0.1F;
             float f2 = ((float)((i >> 2) % 2) - 0.5F) * bbWidth * 0.9F;
-            int j = MathHelper.floor(x + (double)f);
-            int k = MathHelper.floor(y + (double) getHeadHeight() + (double)f1);
-            int l = MathHelper.floor(z + (double)f2);
-            if(world.isBlockNormalCube(j, k, l))
+            int x = MathHelper.floor(this.x + (double)f);
+            int y = MathHelper.floor(this.y + (double) getHeadHeight() + (double)f1);
+            int z = MathHelper.floor(this.z + (double)f2);
+            if(world.isBlockNormalCube(x, y, z))
             {
                 return true;
             }
diff --git a/src/main/java/net/minecraft/core/entity/FallingBlockEntity.java b/src/main/java/net/minecraft/core/entity/FallingBlockEntity.java
index 1374c94d8..e1912e1c6 100644
--- a/src/main/java/net/minecraft/core/entity/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/core/entity/FallingBlockEntity.java
@@ -9,37 +9,40 @@ import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.SandBlock;
 import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.block.entity.BlockEntityDispatcher;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 import com.mojang.nbt.CompoundTag;
+import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
 public class FallingBlockEntity extends Entity
 {
-    public int blockID;
-    public int blockMeta;
-    public @Nullable BlockEntity blockEntity;
+    public CarriedBlock carriedBlock;
     public int fallTime;
     public boolean hasRemovedBlock = false;
 
     public FallingBlockEntity(World world)
     {
         super(world);
-        blockID = Blocks.SAND.id;
+        carriedBlock = new CarriedBlock(this, Blocks.SAND, 0, null);
         fallTime = 0;
     }
 
     public FallingBlockEntity(World world, double x, double y, double z, int blockId, int blockMeta, @Nullable BlockEntity blockEntity) {
         super(world);
         fallTime = 0;
-        this.blockID = blockId;
-        this.blockMeta = blockMeta;
-        this.blockEntity = blockEntity;
+        carriedBlock = new CarriedBlock(this, blockId, blockMeta, blockEntity);
+        if (blockEntity != null) {
+            blockEntity.worldObj = null;
+            blockEntity.carriedBlock = carriedBlock;
+        }
         blocksBuilding = true;
-        setSize(0.98F, 0.98F);
+        setSize(1F, 1F);
         heightOffset = bbHeight / 2.0F;
         setPos(x, y, z);
         xd = 0.0D;
@@ -70,7 +73,7 @@ public class FallingBlockEntity extends Entity
     @Override
 	public void tick()
     {
-        if(blockID == 0)
+        if(carriedBlock.blockId == 0)
         {
             remove();
             return;
@@ -79,7 +82,7 @@ public class FallingBlockEntity extends Entity
         if (pushTime < 0.05f || (pushTime < 0.25 && onGround)){
             pushTime = 0;
         }
-        if (isOnFire() && blockID == Blocks.TNT.id) {
+        if (isOnFire() && carriedBlock.blockId == Blocks.TNT.id) {
             remove();
             TNTPrimedEntity tntPrimedEntity = new TNTPrimedEntity(world, x, y, z);
             tntPrimedEntity.xd = this.xd;
@@ -92,7 +95,7 @@ public class FallingBlockEntity extends Entity
         xo = x;
         yo = y;
         zo = z;
-        if (pushTime < 0.05 && yd <= 0) {
+        if (pushTime < 0.01 && yd <= 0) {
             fallTime++;
         }
         yd -= 0.04D;
@@ -100,83 +103,96 @@ public class FallingBlockEntity extends Entity
         xd *= 0.98D;
         yd *= 0.98D;
         zd *= 0.98D;
-        int x = MathHelper.floor(this.x);
-        int y = MathHelper.floor(this.y);
-        int z = MathHelper.floor(this.z);
-        if(world.getBlockId(x, y, z) == blockID && !hasRemovedBlock)
+        int x = MathHelper.round(this.x - 0.5);
+        int y = MathHelper.round(this.y);
+        int z = MathHelper.round(this.z - 0.5);
+        if(world.getBlockId(x, y, z) == carriedBlock.blockId && !hasRemovedBlock)
         {
             world.setBlockWithNotify(x, y, z, 0);
             hasRemovedBlock = true;
         }
         if (onGround) {
+            Block selfBlock = carriedBlock.block();
             Block blockBelow = world.getBlock(x, y - 1, z);
-            double friction = blockBelow == null ? 0.98 : blockBelow.friction * 0.91F;
+            double friction = selfBlock.friction;
+            friction *= blockBelow == null ? 0.98 : blockBelow.friction * 0.91f;
             xd *= friction;
             zd *= friction;
             yd *= -0.5D;
             pushTime *= (float) friction;
         }
-        if (pushTime < 0.05) {
-            if(onGround)
+
+        double v = Math.hypot(xd, zd);
+        if (v < 0.001 || isInWall()) {
+            if(onGround || isInWall())
             {
+                Entity rider = getPassenger();
+                ejectRider();
                 remove();
-                if((!world.canBlockBePlacedAt(blockID, x, y, z, true, Side.TOP) || SandBlock.canFallBelow(world, x, y - 1, z) || !world.setBlock(x, y, z, blockID)) && !world.isClientSide)
+                if((!world.canBlockBePlacedAt(carriedBlock.blockId, x, y, z, true, Side.TOP) || SandBlock.canFallBelow(world, x, y - 1, z) || !world.setBlock(x, y, z, carriedBlock.blockId)) && !world.isClientSide)
                 {
                     if(hasRemovedBlock) {
                         drop();
                     }
                 } else if (!world.isClientSide) {
-                    world.setBlockMetadata(x, y, z, blockMeta);
-                    world.notifyBlockChange(x, y, z, blockID);
-                    if (blockEntity != null) {
+                    world.setBlockMetadata(x, y, z, carriedBlock.metadata);
+                    if (carriedBlock.entity != null) {
                         BlockEntity oldEnt = world.getBlockEntity(x, y, z);
                         if (oldEnt != null) {
                             oldEnt.invalidate();
                         }
-                        blockEntity.validate();
-                        blockEntity.x = x;
-                        blockEntity.y = y;
-                        blockEntity.z = z;
-                        world.replaceBlockTileEntity(x, y, z, blockEntity);
+                        carriedBlock.entity.validate();
+                        carriedBlock.entity.x = x;
+                        carriedBlock.entity.y = y;
+                        carriedBlock.entity.z = z;
+                        carriedBlock.entity.worldObj = world;
+                        carriedBlock.entity.carriedBlock = null;
+                        world.replaceBlockTileEntity(x, y, z, carriedBlock.entity);
                     }
+                    world.notifyBlockChange(x, y, z, carriedBlock.blockId);
                 }
-            } else
-            if(fallTime > 100 && !world.isClientSide)
-            {
+                if (rider != null) {
+                    BlockEntity te = world.getBlockEntity(x, y, z);
+                    if (te instanceof IVehicle) rider.startRiding((IVehicle) te);
+                }
+            } else if(fallTime > 600 && !world.isClientSide) {
                 if(hasRemovedBlock) {
                     drop();
                 }
+                ejectRider();
                 remove();
             }
+
+            carriedBlock.heldTick(world, this);
         }
     }
 
     public void drop() {
-        Block block = Block.getBlock(blockID);
+        Block block = carriedBlock.block();
         if (block != null) {
-            ItemStack[] drops = block.getBreakResult(world, EnumDropCause.WORLD, blockMeta, blockEntity);
+            ItemStack[] drops = block.getBreakResult(world, EnumDropCause.SILK_TOUCH, carriedBlock.metadata, carriedBlock.entity);
             if (drops != null && drops.length > 0) {
                 for (int i = 0; i < drops.length; i++) {
                     spawnAtLocation(drops[i], 0);
                 }
             }
         }
-        if (blockEntity != null) {
-            int x = MathHelper.floor(this.x);
-            int y = MathHelper.floor(this.y);
-            int z = MathHelper.floor(this.z);
-            blockEntity.dropContents(world, x, y, z);
+        if (carriedBlock.entity != null) {
+            int x = MathHelper.round(this.x - 0.5);
+            int y = MathHelper.round(this.y);
+            int z = MathHelper.round(this.z - 0.5);
+            carriedBlock.entity.dropContents(world, x, y, z);
         }
     }
 
     @Override
     public void addAdditionalSaveData(CompoundTag tag)
     {
-        tag.putShort("Tile", (short)blockID);
-        tag.putShort("TileData", (short) blockMeta);
-        if (blockEntity != null) {
+        tag.putShort("Tile", (short)carriedBlock.blockId);
+        tag.putShort("TileData", (short) carriedBlock.metadata);
+        if (carriedBlock.entity != null) {
             CompoundTag entityTag = new CompoundTag();
-            blockEntity.writeToNBT(entityTag);
+            carriedBlock.entity.writeToNBT(entityTag);
             tag.putCompound("TileEntity", entityTag);
         }
     }
@@ -184,11 +200,10 @@ public class FallingBlockEntity extends Entity
     @Override
 	public void readAdditionalSaveData(CompoundTag tag)
     {
-        blockID = tag.getShort("Tile") & 0x3fff;
-        blockMeta = tag.getShort("TileData") & 0xff;
-        if (tag.containsKey("TileEntity")) {
-            blockEntity = BlockEntity.createAndLoadEntity(tag.getCompound("TileEntity"));
-        }
+        carriedBlock = new CarriedBlock(this,
+            tag.getShort("Tile") & 0x3fff,
+            tag.getShort("TileData") & 0xff,
+            tag.containsKey("TileEntity") ? BlockEntityDispatcher.createAndLoadEntity(tag.getCompound("TileEntity")) : null);
     }
 
     @Override
@@ -203,13 +218,13 @@ public class FallingBlockEntity extends Entity
         return 0.0F;
     }
 
-    public World getWorld()
-    {
-        return world;
-    }
-
     @Override
     public boolean showBoundingBoxOnHover() {
         return true;
     }
+
+    @Override
+    public double getRideHeight() {
+        return 0.0D;
+    }
 }
diff --git a/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java b/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
index 728d6f1c1..2d7f1a860 100644
--- a/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
+++ b/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
@@ -8,6 +8,7 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.ChestBlockEntity;
 import net.minecraft.core.block.logic.RailDirection;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.crafting.LookupFuelFurnace;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.ItemEntity;
@@ -702,12 +703,12 @@ public class MinecartEntity extends Entity implements Container {
 	public boolean interact(Player player) {
         switch (type){
             case PASSENGER_CART:
-                if (!world.isClientSide && passenger == null && player.isSneaking() && player.getHeldObject() instanceof BlockEntity.CarriedBlock) {
-                    BlockEntity.CarriedBlock carriedBlock = (BlockEntity.CarriedBlock) player.getHeldObject();
+                if (!world.isClientSide && passenger == null && player.isSneaking() && player.getHeldObject() instanceof CarriedBlock) {
+                    CarriedBlock carriedBlock = (CarriedBlock) player.getHeldObject();
                     if (carriedBlock.entity instanceof ChestBlockEntity) {
                         ChestBlockEntity chest = (ChestBlockEntity) carriedBlock.entity;
                         this.type = CHEST_CART;
-                        if (carriedBlock.block == Blocks.CHEST_PLANKS_OAK_PAINTED) {
+                        if (carriedBlock.blockId == Blocks.CHEST_PLANKS_OAK_PAINTED.id) {
                             this.typeMeta = carriedBlock.metadata & TYPE_MASK_COLOR | TYPE_MASK_PAINTED_CHEST;
                         } else {
                             this.typeMeta = carriedBlock.metadata & TYPE_MASK_COLOR;
diff --git a/src/main/java/net/minecraft/core/net/entity/entries/FallingSandNetEntry.java b/src/main/java/net/minecraft/core/net/entity/entries/FallingSandNetEntry.java
index 69d474871..907a78e46 100644
--- a/src/main/java/net/minecraft/core/net/entity/entries/FallingSandNetEntry.java
+++ b/src/main/java/net/minecraft/core/net/entity/entries/FallingSandNetEntry.java
@@ -45,6 +45,6 @@ public class FallingSandNetEntry implements IVehicleEntry<FallingBlockEntity>, I
 
     @Override
     public AddEntityPacket getSpawnPacket(EntityTrackerEntry tracker, FallingBlockEntity trackedObject) {
-        return new AddEntityPacket(trackedObject, trackedObject.blockID);
+        return new AddEntityPacket(trackedObject, trackedObject.carriedBlock.blockId);
     }
 }
diff --git a/src/main/java/net/minecraft/core/player/inventory/menu/CraftingMenu.java b/src/main/java/net/minecraft/core/player/inventory/menu/CraftingMenu.java
index 9041c2412..e296a1fae 100644
--- a/src/main/java/net/minecraft/core/player/inventory/menu/CraftingMenu.java
+++ b/src/main/java/net/minecraft/core/player/inventory/menu/CraftingMenu.java
@@ -80,7 +80,9 @@ public class CraftingMenu extends AbstractContainerMenu
 				storeOrDropItem(player, itemstack);
 				insert = true;
 			}
+			craftSlots.setItem(i, null);
 		}
+		resultSlots.setItem(0, null);
 		if(insert) {
 			player.world.playSoundAtEntity(null, player, "random.insert", 0.1F, 1.0f);
 		}
diff --git a/src/main/java/net/minecraft/core/util/helper/MathHelper.java b/src/main/java/net/minecraft/core/util/helper/MathHelper.java
index 99db8f0f1..5dfdac277 100644
--- a/src/main/java/net/minecraft/core/util/helper/MathHelper.java
+++ b/src/main/java/net/minecraft/core/util/helper/MathHelper.java
@@ -40,6 +40,11 @@ public class MathHelper
         return d >= (double)truncated ? truncated : truncated - 1;
     }
 
+    public static int round(double d) {
+        int truncated = (int) d;
+        return d <= truncated + 0.5 ? truncated : truncated + 1;
+    }
+
     public static float abs(float f)
     {
         return f < 0.0F ? -f : f;
diff --git a/src/main/java/net/minecraft/core/world/ICarriable.java b/src/main/java/net/minecraft/core/world/ICarriable.java
index f8d6873ba..44a8f4db6 100644
--- a/src/main/java/net/minecraft/core/world/ICarriable.java
+++ b/src/main/java/net/minecraft/core/world/ICarriable.java
@@ -2,7 +2,7 @@ package net.minecraft.core.world;
 
 import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
-import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.Side;
 import org.slf4j.Logger;
@@ -39,10 +39,12 @@ public interface ICarriable {
 
     void readFromNBT(CompoundTag tag);
 
+    String TYPE_BLOCK = "block";
+
     static ICarriable createAndLoadCarriable(Entity holder, CompoundTag tag) {
         String type = tag.getString("type");
-        if (type.equalsIgnoreCase("blockEntity")) {
-            return BlockEntity.CarriedBlock.createAndLoadCarriedBlock(holder, tag);
+        if (type.equalsIgnoreCase(TYPE_BLOCK)) {
+            return CarriedBlock.createAndLoadCarriedBlock(holder, tag);
         }
         LOGGER.warn("Could not identify carriable for type {}!", type);
         return null;
diff --git a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
index 41b6334c4..ca34189d2 100644
--- a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
+++ b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
@@ -2,6 +2,7 @@ package net.minecraft.core.world.chunk;
 
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
+import net.minecraft.core.block.entity.BlockEntityDispatcher;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
 import com.mojang.nbt.Tag;
@@ -303,7 +304,7 @@ public class ChunkLoaderLegacy
                 if (tileEntityTagBase instanceof CompoundTag)
                 {
                     CompoundTag tileEntityTag = (CompoundTag) tileEntityTagBase;
-                    BlockEntity blockEntity = BlockEntity.createAndLoadEntity(tileEntityTag);
+                    BlockEntity blockEntity = BlockEntityDispatcher.createAndLoadEntity(tileEntityTag);
                     if (blockEntity != null)
                     {
                         chunk.addBlockEntity(blockEntity);
diff --git a/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java b/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
index fbafb6b93..6adbd7322 100644
--- a/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
+++ b/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
@@ -352,7 +352,7 @@ public class ChunkDecoratorOverworld
             int l19 = x + rand.nextInt(16) + 8;
             int k22 = rand.nextInt(world.getHeightBlocks());
             int j24 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureTallGrass(blockId)).place(world, rand, l19, k22, j24);
+            (new WorldFeatureFlowers(blockId, 128, true)).place(world, rand, l19, k22, j24);
         }
 
         byte byteBluebells = 0;
@@ -373,7 +373,7 @@ public class ChunkDecoratorOverworld
             int k14 = x + rand.nextInt(16) + 8;
             int l16 = minY + rand.nextInt(rangeY);
             int k19 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.FLOWER_LIGHT_BLUE.id)).place(world, rand, k14, l16, k19);
+            (new WorldFeatureFlowers(Blocks.FLOWER_LIGHT_BLUE.id, 64, true)).place(world, rand, k14, l16, k19);
         }
 
         byte byteMarigold = 0;
@@ -396,7 +396,7 @@ public class ChunkDecoratorOverworld
             int k14 = x + rand.nextInt(16) + 8;
             int l16 = minY + rand.nextInt(rangeY);
             int k19 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.FLOWER_ORANGE.id)).place(world, rand, k14, l16, k19);
+            (new WorldFeatureFlowers(Blocks.FLOWER_ORANGE.id, 64, true)).place(world, rand, k14, l16, k19);
         }
 
         byte byte0 = 0;
@@ -424,7 +424,7 @@ public class ChunkDecoratorOverworld
             int k14 = x + rand.nextInt(16) + 8;
             int l16 = minY + rand.nextInt(rangeY);
             int k19 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.FLOWER_YELLOW.id)).place(world, rand, k14, l16, k19);
+            (new WorldFeatureFlowers(Blocks.FLOWER_YELLOW.id, 64, true)).place(world, rand, k14, l16, k19);
         }
 
         byte byte1 = 0;
@@ -498,19 +498,19 @@ public class ChunkDecoratorOverworld
             int j15 = x + rand.nextInt(16) + 8;
             int j17 = minY + rand.nextInt(rangeY);
             int j20 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.FLOWER_RED.id)).place(world, rand, j15, j17, j20);
+            (new WorldFeatureFlowers(Blocks.FLOWER_RED.id, 64, true)).place(world, rand, j15, j17, j20);
         }
         if (rand.nextInt(4) == 0) {
             int k15 = x + rand.nextInt(16) + 8;
             int k17 = minY + rand.nextInt(rangeY);
             int k20 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.MUSHROOM_BROWN.id)).place(world, rand, k15, k17, k20);
+            (new WorldFeatureFlowers(Blocks.MUSHROOM_BROWN.id, 64, false)).place(world, rand, k15, k17, k20);
         }
         if (rand.nextInt(8) == 0) {
             int l15 = x + rand.nextInt(16) + 8;
             int l17 = minY + rand.nextInt(rangeY);
             int l20 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.MUSHROOM_RED.id)).place(world, rand, l15, l17, l20);
+            (new WorldFeatureFlowers(Blocks.MUSHROOM_RED.id, 64, false)).place(world, rand, l15, l17, l20);
         }
         if(rand.nextInt(5) == 0) {
             int i18 = x + rand.nextInt(16) + 8;
diff --git a/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java b/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
index 9c0f4cc33..7cca23900 100644
--- a/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
+++ b/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
@@ -154,7 +154,7 @@ public class ChunkDecoratorOverworldRetro
             int k13 = k + rand.nextInt(16) + 8;
             int i16 = minY + rand.nextInt(rangeY);
             int j18 = l + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.FLOWER_YELLOW.id)).place(world, rand, k13, i16, j18);
+            (new WorldFeatureFlowers(Blocks.FLOWER_YELLOW.id, 64, false)).place(world, rand, k13, i16, j18);
         }
 
         if (rand.nextInt(2) == 0)
@@ -162,21 +162,21 @@ public class ChunkDecoratorOverworldRetro
             int i9 = k + rand.nextInt(16) + 8;
             int l13 = minY + rand.nextInt(rangeY);
             int j16 = l + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.FLOWER_RED.id)).place(world, rand, i9, l13, j16);
+            (new WorldFeatureFlowers(Blocks.FLOWER_RED.id, 64, false)).place(world, rand, i9, l13, j16);
         }
         if (rand.nextInt(4) == 0)
         {
             int j9 = k + rand.nextInt(16) + 8;
             int i14 = minY + rand.nextInt(rangeY);
             int k16 = l + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.MUSHROOM_BROWN.id)).place(world, rand, j9, i14, k16);
+            (new WorldFeatureFlowers(Blocks.MUSHROOM_BROWN.id, 64, false)).place(world, rand, j9, i14, k16);
         }
         if (rand.nextInt(8) == 0)
         {
             int k9 = k + rand.nextInt(16) + 8;
             int j14 = minY + rand.nextInt(rangeY);
             int l16 = l + rand.nextInt(16) + 8;
-            (new WorldFeatureFlowers(Blocks.MUSHROOM_RED.id)).place(world, rand, k9, j14, l16);
+            (new WorldFeatureFlowers(Blocks.MUSHROOM_RED.id, 64, false)).place(world, rand, k9, j14, l16);
         }
         for (int l9 = 0; l9 < 10; l9++)
         {
diff --git a/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java b/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java
index e2081c41b..570c494d3 100644
--- a/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java
+++ b/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java
@@ -2,9 +2,11 @@ package net.minecraft.core.world.generate.feature;
 
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.StackedFlowerBlock;
 import net.minecraft.core.world.World;
 
 import java.util.Random;
+import java.util.Stack;
 
 // Referenced classes of package net.minecraft.src:
 //            WorldGenerator, World, Block, FlowerBlock
@@ -12,26 +14,61 @@ import java.util.Random;
 public class WorldFeatureFlowers extends WorldFeature
 {
     private final int plantBlockId;
-    @MethodParametersAnnotation(names = {"plantBlockId"})
-    public WorldFeatureFlowers(int plantBlockId)
+    private final int count;
+    private final boolean varyStackSize;
+
+    @MethodParametersAnnotation(names = {"plantBlockId", "count", "varyStackSize"})
+    public WorldFeatureFlowers(int plantBlockId, int count, boolean varyStackSize)
     {
         this.plantBlockId = plantBlockId;
+        this.count = count;
+        this.varyStackSize = varyStackSize;
     }
 
     @Override
 	public boolean place(World world, Random random, int x, int y, int z)
     {
-        for(int l = 0; l < 64; l++)
+        for(int l = 0; l < count; l++)
         {
             int i1 = (x + random.nextInt(8)) - random.nextInt(8);
             int j1 = (y + random.nextInt(4)) - random.nextInt(4);
             int k1 = (z + random.nextInt(8)) - random.nextInt(8);
             if(world.isAirBlock(i1, j1, k1) && Block.blocksList[plantBlockId].canBlockStay(world, i1, j1, k1))
             {
-                world.setBlock(i1, j1, k1, plantBlockId);
+                final int metadata;
+                if (Block.getBlock(plantBlockId) instanceof StackedFlowerBlock) {
+                    final int stackSize;
+                    if (varyStackSize) {
+                        stackSize = getStackSize(random);
+                    } else {
+                        stackSize = 0;
+                    }
+
+                    metadata = StackedFlowerBlock.setStackCount(0, stackSize);
+                } else {
+                    metadata = 0;
+                }
+                world.setBlockAndMetadata(i1, j1, k1, plantBlockId, metadata);
             }
         }
 
         return true;
     }
+
+    public static int getStackSize(Random random) {
+        // 0 = 0-7 (8 chances)
+        // 1 = 8-11 (4 chances)
+        // 2 = 12-13 (2 chances)
+        // 3 = 14 (1 chance)
+        final int odds = random.nextInt(15);
+        if (odds < 8) {
+            return 0;
+        } else if (odds < 12) {
+            return 1;
+        } else if (odds < 14) {
+            return 2;
+        } else {
+            return 3;
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java b/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java
index e2164ccc7..5d56b987c 100644
--- a/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java
+++ b/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java
@@ -224,13 +224,7 @@ public class WorldFeatureLabyrinth extends WorldFeature
         return BlockTags.CAVES_CUT_THROUGH.appliesTo(world.getBlock(x, y, z)) ||
                 world.getBlockMaterial(x, y, z) == Material.grass ||
                 world.getBlockMaterial(x, y, z) == Material.dirt ||
-                world.getBlockMaterial(x, y, z) == Material.stone ||
-                world.getBlockMaterial(x, y, z) == Material.slate ||
-                world.getBlockMaterial(x, y, z) == Material.marble ||
-                world.getBlockMaterial(x, y, z) == Material.limestone ||
-                world.getBlockMaterial(x, y, z) == Material.basalt ||
-                world.getBlockMaterial(x, y, z) == Material.granite ||
-                world.getBlockMaterial(x, y, z) == Material.permafrost ||
+                world.getBlockMaterial(x, y, z).isStone() ||
                 world.getBlockMaterial(x, y, z) == Material.sand ||
                 world.getBlockMaterial(x, y, z) == Material.moss;
     }
diff --git a/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java b/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java
index 3cff97531..55d70cdef 100644
--- a/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java
+++ b/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java
@@ -2,6 +2,7 @@ package net.minecraft.core.world.generate.feature;
 
 import net.minecraft.core.block.BaseLeavesBlock;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.StackedFlowerBlock;
 import net.minecraft.core.world.World;
 
 import java.util.Random;
@@ -24,14 +25,13 @@ public class WorldFeatureMeadow extends WorldFeature
             int k1 = (y + random.nextInt(4)) - random.nextInt(4);
             int l1 = (z + random.nextInt(8)) - random.nextInt(8);
 
-            int meta = 0;
 
             int index = random.nextInt(blockIds.length);
             int flowerId = blockIds[index];
 
-
             if(world.isAirBlock(j1, k1, l1) && Block.blocksList[flowerId].canBlockStay(world, j1, k1, l1))
             {
+                final int meta = StackedFlowerBlock.setStackCount(0, WorldFeatureFlowers.getStackSize(random));
                 world.setBlockAndMetadata(j1, k1, l1, flowerId, meta);
             }
         }
diff --git a/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java b/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java
index fe0078274..caf11602c 100644
--- a/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java
+++ b/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java
@@ -1156,9 +1156,9 @@ class WorkbenchGenerator {
                 "XXX",
                 "#I#",
                 "#R#")
-            .addInput('X', Items.INGOT_STEEL)
-            .addInput('#', Blocks.BRICK_STONE_POLISHED)
-            .addInput('I', Blocks.PISTON_BASE)
+            .addInput('X', Items.INGOT_STEEL_CRUDE)
+            .addInput('#', "minecraft:stones")
+            .addInput('I', Items.INGOT_STEEL)
             .addInput('R', Items.DUST_REDSTONE)
             .create("steel_piston", Blocks.PISTON_BASE_STEEL.getDefaultStack());
 
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_light_blue.png b/src/main/resources/assets/minecraft/textures/block/flower_light_blue0.png
similarity index 100%
rename from src/main/resources/assets/minecraft/textures/block/flower_light_blue.png
rename to src/main/resources/assets/minecraft/textures/block/flower_light_blue0.png
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_light_blue1.png b/src/main/resources/assets/minecraft/textures/block/flower_light_blue1.png
new file mode 100644
index 000000000..2b9f04e43
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_light_blue1.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_light_blue2.png b/src/main/resources/assets/minecraft/textures/block/flower_light_blue2.png
new file mode 100644
index 000000000..82c14630a
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_light_blue2.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_light_blue3.png b/src/main/resources/assets/minecraft/textures/block/flower_light_blue3.png
new file mode 100644
index 000000000..9c3d39bcc
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_light_blue3.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_orange.png b/src/main/resources/assets/minecraft/textures/block/flower_orange0.png
similarity index 100%
rename from src/main/resources/assets/minecraft/textures/block/flower_orange.png
rename to src/main/resources/assets/minecraft/textures/block/flower_orange0.png
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_orange1.png b/src/main/resources/assets/minecraft/textures/block/flower_orange1.png
new file mode 100644
index 000000000..d3bcc4d43
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_orange1.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_orange2.png b/src/main/resources/assets/minecraft/textures/block/flower_orange2.png
new file mode 100644
index 000000000..1894b192f
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_orange2.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_orange3.png b/src/main/resources/assets/minecraft/textures/block/flower_orange3.png
new file mode 100644
index 000000000..a20b8a93b
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_orange3.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_pink.png b/src/main/resources/assets/minecraft/textures/block/flower_pink0.png
similarity index 100%
rename from src/main/resources/assets/minecraft/textures/block/flower_pink.png
rename to src/main/resources/assets/minecraft/textures/block/flower_pink0.png
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_pink1.png b/src/main/resources/assets/minecraft/textures/block/flower_pink1.png
new file mode 100644
index 000000000..326668ee3
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_pink1.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_pink2.png b/src/main/resources/assets/minecraft/textures/block/flower_pink2.png
new file mode 100644
index 000000000..c56ab98b2
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_pink2.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_pink3.png b/src/main/resources/assets/minecraft/textures/block/flower_pink3.png
new file mode 100644
index 000000000..f48a3b0e1
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_pink3.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_purple.png b/src/main/resources/assets/minecraft/textures/block/flower_purple.png
deleted file mode 100644
index 5a326bc95..000000000
Binary files a/src/main/resources/assets/minecraft/textures/block/flower_purple.png and /dev/null differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_purple0.png b/src/main/resources/assets/minecraft/textures/block/flower_purple0.png
new file mode 100644
index 000000000..fcc4ddea1
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_purple0.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_purple1.png b/src/main/resources/assets/minecraft/textures/block/flower_purple1.png
new file mode 100644
index 000000000..644025445
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_purple1.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_purple2.png b/src/main/resources/assets/minecraft/textures/block/flower_purple2.png
new file mode 100644
index 000000000..5a5af1e59
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_purple2.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_purple3.png b/src/main/resources/assets/minecraft/textures/block/flower_purple3.png
new file mode 100644
index 000000000..e86263c51
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_purple3.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_red.png b/src/main/resources/assets/minecraft/textures/block/flower_red0.png
similarity index 100%
rename from src/main/resources/assets/minecraft/textures/block/flower_red.png
rename to src/main/resources/assets/minecraft/textures/block/flower_red0.png
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_red1.png b/src/main/resources/assets/minecraft/textures/block/flower_red1.png
new file mode 100644
index 000000000..a78271d84
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_red1.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_red2.png b/src/main/resources/assets/minecraft/textures/block/flower_red2.png
new file mode 100644
index 000000000..839567765
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_red2.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_red3.png b/src/main/resources/assets/minecraft/textures/block/flower_red3.png
new file mode 100644
index 000000000..ebf51db32
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_red3.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_yellow.png b/src/main/resources/assets/minecraft/textures/block/flower_yellow0.png
similarity index 100%
rename from src/main/resources/assets/minecraft/textures/block/flower_yellow.png
rename to src/main/resources/assets/minecraft/textures/block/flower_yellow0.png
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_yellow1.png b/src/main/resources/assets/minecraft/textures/block/flower_yellow1.png
new file mode 100644
index 000000000..70ec5c5b9
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_yellow1.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_yellow2.png b/src/main/resources/assets/minecraft/textures/block/flower_yellow2.png
new file mode 100644
index 000000000..a2b7bb2cc
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_yellow2.png differ
diff --git a/src/main/resources/assets/minecraft/textures/block/flower_yellow3.png b/src/main/resources/assets/minecraft/textures/block/flower_yellow3.png
new file mode 100644
index 000000000..bbf55904c
Binary files /dev/null and b/src/main/resources/assets/minecraft/textures/block/flower_yellow3.png differ
