diff --git a/game/client/src/main/java/net/betterthanadventure/utils/DataDumper.java b/game/client/src/main/java/net/betterthanadventure/utils/DataDumper.java
index af57e1a85..e93c93b84 100644
--- a/game/client/src/main/java/net/betterthanadventure/utils/DataDumper.java
+++ b/game/client/src/main/java/net/betterthanadventure/utils/DataDumper.java
@@ -76,7 +76,7 @@ public class DataDumper implements MinecraftAccessor {
         writer = new BufferedWriter(new FileWriter(new File(wikiDumpFile, "blocks.csv")));
         writer.write("ID,Translation Key,Hardness,Blast Resistance,Mining Level,Stacksize,Name,Description,Tags\n");
         for (int i = 0; i < Blocks.blocksList.length; i++) {
-            Block block = Blocks.blocksList[i];
+            Block<?> block = Blocks.blocksList[i];
             String string = blockToCSV(block);
             if (string.isEmpty() && !hideUnused){
                 string = i + "\n";
@@ -124,11 +124,11 @@ public class DataDumper implements MinecraftAccessor {
         builder.append("\n");
         return builder.toString();
     }
-    public static String blockToCSV(Block block){
+    public static String blockToCSV(Block<?> block){
         if (block == null) return "";
         StringBuilder builder = new StringBuilder();
         builder
-                .append(block.id).append(",")
+                .append(block.id()).append(",")
                 .append(block.getKey()).append(",")
                 .append(block.getHardness()).append(",")
                 .append(block.getBlastResistance(null)).append(",")
diff --git a/game/client/src/main/java/net/minecraft/client/Minecraft.java b/game/client/src/main/java/net/minecraft/client/Minecraft.java
index dbe652239..550c8cf1f 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -26,7 +26,7 @@ import net.minecraft.client.net.handler.PacketHandlerClient;
 import net.minecraft.client.world.WorldClient;
 import net.minecraft.client.world.chunk.provider.ChunkProviderStatic;
 import net.minecraft.core.achievement.Achievements;
-import net.minecraft.core.block.BlockLeavesBase;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.entity.TileEntityDispatcher;
 import net.minecraft.core.entity.EntityDispatcher;
 import net.minecraft.core.net.command.CommandManager;
@@ -986,7 +986,7 @@ public class Minecraft
                     OpenGLHelper.checkError("pre render");
                     RenderBlocks.fancyGrass = gameSettings.fancyGraphics.value == 1;
                     EntityItem.enableItemClumping = gameSettings.enableItemClumping.value;
-                    BlockLeavesBase.enableTreeShadowing = gameSettings.treeShadows.value;
+                    BlockLogicLeavesBase.enableTreeShadowing = gameSettings.treeShadows.value;
                     sndManager.updateListener(thePlayer, timer.partialTicks);
                     glEnable(GL_TEXTURE_2D);
                     if(currentWorld != null)
diff --git a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleBlockBreaking.java b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleBlockBreaking.java
index f7e7f5869..4b6db2647 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleBlockBreaking.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleBlockBreaking.java
@@ -11,10 +11,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
 public class ParticleBlockBreaking extends Particle {
-    private final Block block;
+    private final Block<?> block;
     private final Side side;
 
-    public ParticleBlockBreaking(World world, double x, double y, double z, double xa, double ya, double za, Block block, Side side, int meta) {
+    public ParticleBlockBreaking(World world, double x, double y, double z, double xa, double ya, double za, Block<?> block, Side side, int meta) {
         super(world, x, y, z, xa, ya, za);
         this.side = side;
         this.block = block;
diff --git a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java
index 5693ba24d..d87d72efc 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java
@@ -5,7 +5,6 @@ import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.util.dispatch.Dispatcher;
 import net.minecraft.core.Global;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.animal.MobFireflyCluster;
 import net.minecraft.core.item.Item;
diff --git a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleLeaf.java b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleLeaf.java
index 02499f5af..ed41e9f14 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleLeaf.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleLeaf.java
@@ -6,7 +6,7 @@ import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLeavesBase;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -23,13 +23,13 @@ public class ParticleLeaf extends Particle {
     }
 
     @Override
-    public boolean collidesWithBlock(Block block, int metadata) {
-        return !(block instanceof BlockLeavesBase);
+    public boolean collidesWithBlock(Block<?> block, int metadata) {
+        return !Block.hasLogicClass(block, BlockLogicLeavesBase.class);
     }
 
     public ParticleLeaf init(int x, int y, int z) {
-        Block block = Blocks.blocksList[this.world.getBlockId(x, y, z)];
-        if (!(block instanceof BlockLeavesBase)) this.remove();
+        Block<?> block = Blocks.blocksList[this.world.getBlockId(x, y, z)];
+        if (!Block.hasLogicClass(block, BlockLogicLeavesBase.class)) this.remove();
         int col = BlockColorDispatcher.getInstance().getDispatch(block).getWorldColor(world, x, y, z);
         this.rCol *= (float) (col >> 16 & 0xff) / 255F;
         this.gCol *= (float) (col >> 8 & 0xff) / 255F;
diff --git a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleWaterDrop.java b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleWaterDrop.java
index 03369f5f0..336a13bec 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleWaterDrop.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleWaterDrop.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.entity.particle;
 
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
-import net.minecraft.core.block.BlockFluid;
+import net.minecraft.core.block.BlockLogicFluid;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
@@ -43,7 +43,7 @@ public class ParticleWaterDrop extends Particle {
         }
         Material m = this.world.getBlockMaterial(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z));
         if (m.isLiquid() || m.isSolid()) {
-            double y0 = (MathHelper.floor(this.y) + 1) - BlockFluid.getWaterVolume(this.world.getBlockMetadata(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z)));
+            double y0 = (MathHelper.floor(this.y) + 1) - BlockLogicFluid.getWaterVolume(this.world.getBlockMetadata(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z)));
             if (this.y < y0) {
                 remove();
             }
diff --git a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java
index 40642c06a..06ef3e025 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java
@@ -25,8 +25,7 @@ import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.achievement.stat.Stat;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.client.gui.toasts.AchievementToast;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockPortal;
+import net.minecraft.core.block.BlockLogicPortal;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.entity.TileEntityDispenser;
@@ -50,6 +49,7 @@ import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.GetSkinUrlThread;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
+import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.World;
 import org.slf4j.Logger;
 
@@ -163,14 +163,14 @@ public class PlayerLocal extends Player
                 {
                     timeUntilPortal = 10;
                     mc.sndManager.playSound("portal.travel", SoundCategory.WORLD_SOUNDS, 1.0F, random.nextFloat() * 0.4F + 0.8F);
-                    int targetDim = ((BlockPortal) Blocks.blocksList[portalID]).targetDimension;
-                    if (dimension == targetDim)
+                    Dimension targetDim = ((BlockLogicPortal) Blocks.blocksList[portalID].getLogic()).targetDimension;
+                    if (dimension == targetDim.id)
                     {
                         mc.usePortal(0, portalColor);
                     }
                     else
                     {
-                        mc.usePortal(targetDim, portalColor);
+                        mc.usePortal(targetDim.id, portalColor);
                     }
                 }
             }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
index fff1eafad..19e56e934 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
@@ -22,7 +22,6 @@ import net.minecraft.client.holiday.Holidays;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.Global;
 import net.minecraft.core.Version;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.GL11;
@@ -43,7 +42,7 @@ public class ScreenMainMenu extends Screen
 {
     private static final Logger LOGGER = LogUtils.getLogger();
 
-    private static final Block[] BLOCKS_TO_DRAW = {
+    private static final Block<?>[] BLOCKS_TO_DRAW = {
     		Blocks.STONE, Blocks.DIRT, Blocks.PLANKS_OAK, Blocks.COBBLE_STONE, Blocks.COBBLE_STONE_MOSSY, Blocks.BASALT, Blocks.LIMESTONE,
     		Blocks.GRANITE, Blocks.BRICK_CLAY, Blocks.ICE, Blocks.WOOL, Blocks.BLOCK_SNOW, Blocks.OBSIDIAN, Blocks.COBBLE_NETHERRACK
     };
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenSignEditor.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenSignEditor.java
index 78734166e..18c377a5e 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenSignEditor.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenSignEditor.java
@@ -27,7 +27,7 @@ public class ScreenSignEditor extends Screen
         buttons.clear();
         Keyboard.enableRepeatEvents(true);
 
-        Block block = entitySign.getBlock();
+        Block<?> block = entitySign.getBlock();
         if(block == Blocks.SIGN_POST_PLANKS_OAK)
         {
             yOffset = 36;
@@ -123,7 +123,7 @@ public class ScreenSignEditor extends Screen
         float scale = 93.75F;
         GL11.glScalef(-scale, -scale, -scale);
         GL11.glRotatef(180F, 0.0F, 1.0F, 0.0F);
-        Block block = entitySign.getBlock();
+        Block<?> block = entitySign.getBlock();
         if(block == Blocks.SIGN_POST_PLANKS_OAK)
         {
             float signAngle = (float)(entitySign.getBlockMeta() * 360) / 16F;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java b/game/client/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java
index 70521a8a7..e2170d571 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java
@@ -74,7 +74,7 @@ public abstract class AchievementPage {
 
     public abstract int lineColorCanUnlock(boolean isHovered);
 
-    public static IconCoordinate getTextureFromBlock(Block block) {
+    public static IconCoordinate getTextureFromBlock(Block<?> block) {
         return BlockModelDispatcher.getInstance().getDispatch(block).getBlockTextureFromSideAndMetadata(Side.TOP, 0);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/achievements/pages/AchievementPageOverworld.java b/game/client/src/main/java/net/minecraft/client/gui/achievements/pages/AchievementPageOverworld.java
index 90e000a5f..d258e97d0 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/achievements/pages/AchievementPageOverworld.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/achievements/pages/AchievementPageOverworld.java
@@ -52,10 +52,10 @@ public class AchievementPageOverworld extends AchievementPage {
     protected static final int ORE_DIAMOND = 3;
     protected static final int ORE_REDSTONE = 4;
     protected static final int ORE_LAPIS = 5;
-    protected static final Block[] STONE_ORES = new Block[]     { Blocks.ORE_COAL_STONE,    Blocks.ORE_IRON_STONE,      Blocks.ORE_GOLD_STONE,      Blocks.ORE_DIAMOND_STONE,       Blocks.ORE_REDSTONE_STONE,      Blocks.ORE_LAPIS_STONE};
-    protected static final Block[] GRANITE_ORES = new Block[]   { Blocks.ORE_COAL_GRANITE,  Blocks.ORE_IRON_GRANITE,    Blocks.ORE_GOLD_GRANITE,    Blocks.ORE_DIAMOND_GRANITE,     Blocks.ORE_REDSTONE_GRANITE,    Blocks.ORE_LAPIS_GRANITE};
-    protected static final Block[] LIMESTONE_ORES = new Block[] { Blocks.ORE_COAL_LIMESTONE,Blocks.ORE_IRON_LIMESTONE,  Blocks.ORE_GOLD_LIMESTONE,  Blocks.ORE_DIAMOND_LIMESTONE,   Blocks.ORE_REDSTONE_LIMESTONE,  Blocks.ORE_LAPIS_LIMESTONE};
-    protected static final Block[] BASALT_ORES = new Block[]    { Blocks.ORE_COAL_BASALT,   Blocks.ORE_IRON_BASALT,     Blocks.ORE_GOLD_BASALT,     Blocks.ORE_DIAMOND_BASALT,      Blocks.ORE_REDSTONE_BASALT,     Blocks.ORE_LAPIS_BASALT};
+    protected static final Block<?>[] STONE_ORES = new Block[]     { Blocks.ORE_COAL_STONE,    Blocks.ORE_IRON_STONE,      Blocks.ORE_GOLD_STONE,      Blocks.ORE_DIAMOND_STONE,       Blocks.ORE_REDSTONE_STONE,      Blocks.ORE_LAPIS_STONE};
+    protected static final Block<?>[] GRANITE_ORES = new Block[]   { Blocks.ORE_COAL_GRANITE,  Blocks.ORE_IRON_GRANITE,    Blocks.ORE_GOLD_GRANITE,    Blocks.ORE_DIAMOND_GRANITE,     Blocks.ORE_REDSTONE_GRANITE,    Blocks.ORE_LAPIS_GRANITE};
+    protected static final Block<?>[] LIMESTONE_ORES = new Block[] { Blocks.ORE_COAL_LIMESTONE,Blocks.ORE_IRON_LIMESTONE,  Blocks.ORE_GOLD_LIMESTONE,  Blocks.ORE_DIAMOND_LIMESTONE,   Blocks.ORE_REDSTONE_LIMESTONE,  Blocks.ORE_LAPIS_LIMESTONE};
+    protected static final Block<?>[] BASALT_ORES = new Block[]    { Blocks.ORE_COAL_BASALT,   Blocks.ORE_IRON_BASALT,     Blocks.ORE_GOLD_BASALT,     Blocks.ORE_DIAMOND_BASALT,      Blocks.ORE_REDSTONE_BASALT,     Blocks.ORE_LAPIS_BASALT};
 
     @Override
     public IconCoordinate getBackgroundTile(ScreenAchievements screen, int layer, Random random, int tileX, int tileY) {
@@ -226,7 +226,7 @@ public class AchievementPageOverworld extends AchievementPage {
 
     private static final WeightedRandomBag<Integer> oreBag = new WeightedRandomBag<>();
 
-    private IconCoordinate getOreFromStone(Block stoneBlock, Random random, int tileX, int tileY){
+    private IconCoordinate getOreFromStone(Block<?> stoneBlock, Random random, int tileX, int tileY){
         oreBag.clear();
 
         random.setSeed(random.nextLong());
@@ -385,7 +385,7 @@ public class AchievementPageOverworld extends AchievementPage {
                         Object o = structure[l][y][x];
                         IconCoordinate c = null;
                         if (o instanceof Block) {
-                            c = getTextureFromBlock((Block) o);
+                            c = getTextureFromBlock((Block<?>) o);
                         } else if (o instanceof IconCoordinate) {
                             c = (IconCoordinate) o;
                         }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
index eb1054174..74ce586b0 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
@@ -13,7 +13,7 @@ import net.minecraft.client.gui.guidebook.search.GuidebookPageSearch;
 import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.client.util.helper.ItemDragHandler;
 import net.minecraft.core.InventoryAction;
-import net.minecraft.core.block.entity.TileEntityFurnaceBlastFurnace;
+import net.minecraft.core.block.entity.TileEntityFurnaceBlast;
 import net.minecraft.core.crafting.LookupFuelFurnace;
 import net.minecraft.core.crafting.LookupFuelFurnaceBlast;
 import net.minecraft.core.data.registry.Registries;
@@ -403,7 +403,7 @@ public abstract class ScreenContainerAbstract extends Screen
 			// Furnace behavior
 			MenuFurnace furnace = (MenuFurnace) inventorySlots;
 			
-			boolean isBlastFurnace = furnace.furnace instanceof TileEntityFurnaceBlastFurnace;
+			boolean isBlastFurnace = furnace.furnace instanceof TileEntityFurnaceBlast;
 			boolean isFuel, isIngredient = false;
 			
 			if(isBlastFurnace) {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFurnace.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFurnace.java
index 5759fd05e..3963a4d40 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFurnace.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFurnace.java
@@ -2,7 +2,7 @@ package net.minecraft.client.gui.container;
 
 import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.core.block.entity.TileEntityFurnace;
-import net.minecraft.core.block.entity.TileEntityFurnaceBlastFurnace;
+import net.minecraft.core.block.entity.TileEntityFurnaceBlast;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.player.inventory.menu.MenuFurnace;
 import net.minecraft.core.player.inventory.container.ContainerInventory;
@@ -21,7 +21,7 @@ public class ScreenFurnace extends ScreenContainerAbstract
 	protected void drawGuiContainerForegroundLayer()
     {
         I18n i18n = I18n.getInstance();
-        if(furnaceInventory instanceof TileEntityFurnaceBlastFurnace) {
+        if(furnaceInventory instanceof TileEntityFurnaceBlast) {
             font.drawString(i18n.translateKey("gui.furnace.blast.label.blast_furnace"), 60, 6, 0x404040);
         } else {
             font.drawString(i18n.translateKey("gui.furnace.label.furnace"), 60, 6, 0x404040);
@@ -32,7 +32,7 @@ public class ScreenFurnace extends ScreenContainerAbstract
     @Override
 	protected void drawGuiContainerBackgroundLayer(float f)
     {
-        if(furnaceInventory instanceof TileEntityFurnaceBlastFurnace) {
+        if(furnaceInventory instanceof TileEntityFurnaceBlast) {
             mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/blastfurnace.png").bind();
         } else {
             mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/furnace.png").bind();
@@ -43,7 +43,7 @@ public class ScreenFurnace extends ScreenContainerAbstract
         drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
         if(furnaceInventory.isBurning())
         {
-            if (furnaceInventory instanceof TileEntityFurnaceBlastFurnace) {
+            if (furnaceInventory instanceof TileEntityFurnaceBlast) {
                 int fireHeight = furnaceInventory.getBurnTimeRemainingScaled(14);
                 drawTexturedModalRect(x + 56, y + 35 + 14 - fireHeight, 176, 14 - fireHeight, 14, fireHeight + 2);
                 int arrowWidth = furnaceInventory.getCookProgressScaled(24);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java
index c1357e118..fd6f3d365 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java
@@ -4,7 +4,6 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.ItemElement;
 import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.guidebook.ScreenGuidebook;
-import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.GuidebookPageManager;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/displays/DisplayAdapterLabel.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/displays/DisplayAdapterLabel.java
index 2d101d333..ebb1fb683 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/displays/DisplayAdapterLabel.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/displays/DisplayAdapterLabel.java
@@ -24,12 +24,12 @@ public class DisplayAdapterLabel implements RecipeDisplayAdapter<RecipeEntryLabe
             int lastId = 0;
             int offset = 1;
             while (blocksAdded < 50) {
-                Block b = null;
+                Block<?> b = null;
                 while (b == null) {
                     b = Blocks.getBlock(lastId + offset++);
                 }
                 randomOptions[blocksAdded++] = b;
-                lastId = b.id;
+                lastId = b.id();
                 offset = 1;
             }
         }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
index df93189e5..8cbb7736f 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
@@ -14,7 +14,6 @@ import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
 import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.animal.MobFireflyCluster;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.player.gamemode.Gamemode;
 import net.minecraft.core.player.inventory.slot.Slot;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java
index 68b6cea6a..7977210aa 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java
@@ -5,7 +5,6 @@ import net.minecraft.client.gui.ItemElement;
 import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.guidebook.GuidebookPageManager;
 import net.minecraft.client.gui.guidebook.ScreenGuidebook;
-import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.RecipePage;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java
index 7121386f4..763d2cb1f 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java
@@ -5,7 +5,6 @@ import net.minecraft.client.gui.ItemElement;
 import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.guidebook.GuidebookPageManager;
 import net.minecraft.client.gui.guidebook.ScreenGuidebook;
-import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.RecipePage;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java
index c71bd646a..e5548159b 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java
@@ -5,7 +5,6 @@ import net.minecraft.client.gui.ItemElement;
 import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.guidebook.GuidebookPageManager;
 import net.minecraft.client.gui.guidebook.ScreenGuidebook;
-import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.RecipePage;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
index 0aeba6b6f..b65691767 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
@@ -16,7 +16,7 @@ import net.minecraft.client.gui.Gui;
 import net.minecraft.client.gui.HeldItemTooltipElement;
 import net.minecraft.client.gui.ScreenPhotoMode;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
-import net.minecraft.core.block.BlockPortal;
+import net.minecraft.core.block.BlockLogicPortal;
 import net.minecraft.core.enums.ChatVisibility;
 import net.minecraft.core.item.IArmorItem;
 import net.minecraft.core.util.helper.Direction;
@@ -106,7 +106,7 @@ public class HudIngame extends Gui
 
         // Render pumpkin overlay
         ItemStack headSlotItem = mc.thePlayer.inventory.armorItemInSlot(IArmorItem.PIECE_HEAD);
-        if (mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && (headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id || headSlotItem.itemID == Blocks.PUMPKIN_REDSTONE.id))
+        if (mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && (headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id() || headSlotItem.itemID == Blocks.PUMPKIN_REDSTONE.id()))
         {
             renderPumpkinBlur(width, height);
         }
@@ -367,8 +367,8 @@ public class HudIngame extends Gui
                 {
                     debugOffset += space;
 
-                    Block block = Blocks.blocksList[mc.currentWorld.getBlockId(mc.objectMouseOver.x, mc.objectMouseOver.y, mc.objectMouseOver.z)];
-                    if (block.id > 0 && block.id < Blocks.blocksList.length)
+                    Block<?> block = Blocks.blocksList[mc.currentWorld.getBlockId(mc.objectMouseOver.x, mc.objectMouseOver.y, mc.objectMouseOver.z)];
+                    if (block.id() > 0 && block.id() < Blocks.blocksList.length)
                     {
                         drawDebugScreenLineRight("Looking at:");
 
@@ -383,7 +383,7 @@ public class HudIngame extends Gui
                             name = "<ERROR>";
                         }
 
-                        String id = block.namespaceID + " [" + block.id + ":" + meta + "]";
+                        String id = block.namespaceId() + " [" + block.id() + ":" + meta + "]";
 
                         drawDebugScreenLineRight(name);
                         drawDebugScreenLineRight(block.getLanguageKey(meta));
@@ -413,7 +413,7 @@ public class HudIngame extends Gui
                         drawDebugScreenLineRight("Signal: " + mc.currentWorld.getSignal(mc.objectMouseOver.x, mc.objectMouseOver.y, mc.objectMouseOver.z, mc.objectMouseOver.side));
                         drawDebugScreenLineRight("Direct signal: " + mc.currentWorld.getDirectSignal(mc.objectMouseOver.x, mc.objectMouseOver.y, mc.objectMouseOver.z, mc.objectMouseOver.side));
 
-                        for (Tag<Block> tag : BlockTags.TAG_LIST)
+                        for (Tag<Block<?>> tag : BlockTags.TAG_LIST)
                         {
                             if (tag.appliesTo(block))
                             {
@@ -945,7 +945,7 @@ public class HudIngame extends Gui
         GL11.glDepthMask(false);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
         GL11.glColor4f(1.0F, 1.0F, 1.0F, intensity);
-        IconCoordinate portal = BlockModelDispatcher.getInstance().getDispatch(Blocks.getBlock(mc.thePlayer.portalID)).getBlockTextureFromSideAndMetadata(Side.NORTH, mc.thePlayer.portalColor.blockMeta << 4 | BlockPortal.MASK_COLOR_SET);
+        IconCoordinate portal = BlockModelDispatcher.getInstance().getDispatch(Blocks.getBlock(mc.thePlayer.portalID)).getBlockTextureFromSideAndMetadata(Side.NORTH, mc.thePlayer.portalColor.blockMeta << 4 | BlockLogicPortal.MASK_COLOR_SET);
         portal.parentAtlas.bind();
         float f1 = (float) portal.getIconUMin();
         float f2 = (float) portal.getIconVMin();
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngameDoom.java b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngameDoom.java
index 933ebb698..f4c306854 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngameDoom.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngameDoom.java
@@ -47,7 +47,7 @@ public class HudIngameDoom
 
         // Render pumpkin overlay
         ItemStack headSlotItem = mc.thePlayer.inventory.armorItemInSlot(IArmorItem.PIECE_HEAD);
-        if (mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && (headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id || headSlotItem.itemID == Blocks.PUMPKIN_REDSTONE.id))
+        if (mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && (headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id() || headSlotItem.itemID == Blocks.PUMPKIN_REDSTONE.id()))
         {
             renderPumpkinBlur(width, height);
         }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
index 3ccb32e60..352fa0f17 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
@@ -22,7 +22,6 @@ import net.minecraft.client.render.shader.ShadersRenderer;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.Texture;
 import net.minecraft.client.util.helper.Textures;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.item.Item;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/ViewerCategoryBlock.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/ViewerCategoryBlock.java
index 60084e433..7c7554931 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/ViewerCategoryBlock.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/ViewerCategoryBlock.java
@@ -21,7 +21,7 @@ import java.util.HashMap;
 import java.util.List;
 
 public class ViewerCategoryBlock extends ModelViewerCategory {
-    public HashMap<Block, BlockEntry> entryHashMap = new HashMap<>();
+    public HashMap<Block<?>, BlockEntry> entryHashMap = new HashMap<>();
     public TextCycleElement<Integer> blockIdTextField;
     public TextCycleElement<Integer> blockMetaTextField;
     public ViewerCategoryBlock(ScreenModelViewer modelViewer) {
@@ -29,7 +29,7 @@ public class ViewerCategoryBlock extends ModelViewerCategory {
         createEntries();
     }
     public void createEntries(){
-        for (Block block : Blocks.blocksList){
+        for (Block<?> block : Blocks.blocksList){
             if (block == null) continue;
             entryHashMap.put(block, new BlockEntryBasic(block));
         }
@@ -46,7 +46,7 @@ public class ViewerCategoryBlock extends ModelViewerCategory {
 
     @Override
     public String getCurrentDisplayInfo(I18n translator) {
-        Block displayBlock = Blocks.getBlock(DisplayChunk.displayBlockId);
+        Block<?> displayBlock = Blocks.getBlock(DisplayChunk.displayBlockId);
         String name = "None";
         if (displayBlock != null){
             name = I18n.getInstance().translateNameKey(displayBlock.getKey());
@@ -170,7 +170,7 @@ public class ViewerCategoryBlock extends ModelViewerCategory {
         mc.currentWorld.loadedEntityList.removeIf(entity -> entity instanceof EntityItem);
     }
     public void setDisplayBlock(int id, int meta){
-        Block displayBlock = Blocks.blocksList[DisplayChunk.displayBlockId];
+        Block<?> displayBlock = Blocks.blocksList[DisplayChunk.displayBlockId];
         BlockEntry entry = entryHashMap.get(Blocks.getBlock(DisplayChunk.displayBlockId));
         int _id = DisplayChunk.displayBlockId;
         int _meta = DisplayChunk.displayBlockMeta;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java
index cce7e9a8c..588d6022b 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java
@@ -9,8 +9,8 @@ import net.minecraft.core.world.World;
 import java.util.List;
 
 public abstract class BlockEntry {
-    public Block block;
-    public BlockEntry(Block block){
+    public Block<?> block;
+    public BlockEntry(Block<?> block){
         this.block = block;
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryBasic.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryBasic.java
index e55c7746b..131aba683 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryBasic.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryBasic.java
@@ -9,7 +9,7 @@ import net.minecraft.core.world.World;
 import java.util.List;
 
 public class BlockEntryBasic extends BlockEntry{
-    public BlockEntryBasic(Block block) {
+    public BlockEntryBasic(Block<?> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryJar.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryJar.java
index 90c02ceb8..ebadac288 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryJar.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntryJar.java
@@ -5,7 +5,6 @@ import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.modelviewer.ScreenModelViewer;
 import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityFlowerJar;
 import net.minecraft.core.util.helper.MathHelper;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntrySign.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntrySign.java
index a5f5394d1..671f79483 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntrySign.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntrySign.java
@@ -13,7 +13,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 public class BlockEntrySign extends BlockEntry{
-    public BlockEntrySign(Block block) {
+    public BlockEntrySign(Block<?> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntryFallingBlock.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntryFallingBlock.java
index 435785984..ef4036727 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntryFallingBlock.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntryFallingBlock.java
@@ -5,7 +5,6 @@ import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.modelviewer.ScreenModelViewer;
 import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
-import net.minecraft.core.block.Block;
 
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.EntityFallingBlock;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryBlock.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryBlock.java
index 6ba13b55c..6c5accb5b 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryBlock.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryBlock.java
@@ -7,7 +7,6 @@ import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.modelviewer.ScreenModelViewer;
 import net.minecraft.client.gui.modelviewer.elements.ListSelectorButtonElement;
 import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.lang.I18n;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryItem.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryItem.java
index 44390d55f..7184241e0 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryItem.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntryItem.java
@@ -5,7 +5,6 @@ import net.minecraft.client.entity.particle.ParticleItemBreaking;
 import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.lang.I18n;
diff --git a/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java b/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java
index b047b70bb..bf0635aa5 100644
--- a/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java
+++ b/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java
@@ -19,10 +19,10 @@ import net.minecraft.core.Global;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.block.entity.TileEntityFurnaceBlastFurnace;
 import net.minecraft.core.block.entity.TileEntityDispatcher;
 import net.minecraft.core.block.entity.TileEntityDispenser;
 import net.minecraft.core.block.entity.TileEntityFlag;
+import net.minecraft.core.block.entity.TileEntityFurnaceBlast;
 import net.minecraft.core.block.entity.TileEntityMobSpawner;
 import net.minecraft.core.block.entity.TileEntityFurnace;
 import net.minecraft.core.block.entity.TileEntityTrommel;
@@ -870,7 +870,7 @@ public class PacketHandlerClient extends PacketHandler
                 break;
             }
             case PacketContainerOpen.TYPE_BLAST_FURNACE: {
-                TileEntityFurnaceBlastFurnace tileEntityFurnaceBlast = new TileEntityFurnaceBlastFurnace();
+                TileEntityFurnaceBlast tileEntityFurnaceBlast = new TileEntityFurnaceBlast();
                 mc.thePlayer.displayFurnaceScreen(tileEntityFurnaceBlast);
                 mc.thePlayer.craftingInventory.containerId = containerOpenPacket.windowId;
                 break;
diff --git a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java
index 52ea1add8..3441840c7 100644
--- a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java
+++ b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java
@@ -51,7 +51,7 @@ public abstract class PlayerController {
 			return;
 		}
 
-		Block mineBlock = Blocks.getBlock(mc.currentWorld.getBlockId(x, y, z));
+		Block<?> mineBlock = Blocks.getBlock(mc.currentWorld.getBlockId(x, y, z));
 		if(mineBlock != null) {
 			float mineStrength = mineBlock.blockStrength(mc.currentWorld, x, y, z, side, mc.thePlayer);
 			
@@ -77,7 +77,7 @@ public abstract class PlayerController {
 			return;
 		}
 		
-		Block mineBlock = Blocks.getBlock(mc.currentWorld.getBlockId(x, y, z));
+		Block<?> mineBlock = Blocks.getBlock(mc.currentWorld.getBlockId(x, y, z));
 		if(mineBlock != null) {	
 			syncCurrentPlayItem();
 			
@@ -150,19 +150,19 @@ public abstract class PlayerController {
 		if (!player.getGamemode().canInteract() || mc.thePlayer.getHeldObject() != null) return false;
 		setMineBlock(null, null, null);
 		World world = mc.currentWorld;
-		Block block = Blocks.getBlock(world.getBlockId(x, y, z));
+		Block<?> block = Blocks.getBlock(world.getBlockId(x, y, z));
 		if(block == null) return false;
 		
 		Item heldItem = null;
 		ItemStack heldItemStack = player.getCurrentEquippedItem();
 		if(heldItemStack != null) {
-			if(!heldItemStack.beforeDestroyBlock(world, block.id, x, y, z, side, player)) {
+			if(!heldItemStack.beforeDestroyBlock(world, block.id(), x, y, z, side, player)) {
 				return false;
 			}
 			heldItem = heldItemStack.getItem();
 		}
 		
-		world.playBlockEvent(EVENT_BLOCK_BREAK, x, y, z, block.id);
+		world.playBlockEvent(EVENT_BLOCK_BREAK, x, y, z, block.id());
 		int meta = world.getBlockMetadata(x, y, z);
 		boolean removed = world.setBlockWithNotify(x, y, z, 0);
 		if(removed) {
@@ -185,7 +185,7 @@ public abstract class PlayerController {
 		if (!mc.thePlayer.getGamemode().canInteract() || mc.thePlayer.getHeldObject() != null) return;
 		mc.currentWorld.onBlockHit(mc.thePlayer, x, y, z, side);
 		
-		Block block = Blocks.getBlock(mc.currentWorld.getBlockId(x, y, z));
+		Block<?> block = Blocks.getBlock(mc.currentWorld.getBlockId(x, y, z));
 		if(block != null) {
 			block.onBlockLeftClicked(mc.currentWorld, x, y, z, mc.thePlayer, side, xHit, yHit);
 		}
@@ -313,7 +313,7 @@ public abstract class PlayerController {
 		player.craftingInventory = player.inventorySlots;
 	}
 	
-	public void playDigSound(Block block, int x, int y, int z) {
+	public void playDigSound(Block<?> block, int x, int y, int z) {
 		if(soundDelay <= 0) {
 			mc.currentWorld.playBlockSoundEffect(null, x + 0.5f, y + 0.5f, z + 0.5f, block, EnumBlockSoundEffectType.DIG);
 			soundDelay = 3;
diff --git a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerSP.java b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerSP.java
index 7f2bab88e..ea84e2740 100644
--- a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerSP.java
+++ b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerSP.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.player.controller;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.player.Player;
diff --git a/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java b/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
index 64af7299f..8044d2c89 100644
--- a/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
@@ -51,7 +51,7 @@ public class ItemRenderer
 
     public int getItemColorFromMetadata(Item item, int metadata) {
         if (item instanceof ItemBlock) {
-            Block block = ((ItemBlock)item).getBlock();
+            Block<?> block = ((ItemBlock<?>)item).getBlock();
             return BlockColorDispatcher.getInstance().getDispatch(block).getFallbackColor(metadata);
         }
         return 0xFFFFFF;
@@ -139,8 +139,8 @@ public class ItemRenderer
 			
 			int id = mc.currentWorld.getBlockId(blockX, blockY, blockZ);
             int meta = mc.currentWorld.getBlockMetadata(blockX, blockY, blockZ);
-            Block block = Blocks.blocksList[id];
-            BlockModel<Block> model = BlockModelDispatcher.getInstance().getDispatch(block);
+            Block<?> block = Blocks.blocksList[id];
+            BlockModel<?> model = BlockModelDispatcher.getInstance().getDispatch(block);
 			if(mc.currentWorld.isBlockNormalCube(blockX, blockY, blockZ)) {
 				renderInsideOfBlock(partialTicks, model.getBlockTextureFromSideAndMetadata(Side.NORTH, meta));
 			} else {
diff --git a/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java b/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java
index 8ebdb9258..69eadfcc9 100644
--- a/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java
+++ b/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java
@@ -153,7 +153,7 @@ public final class ParticleEngine {
      * @param data The metadata value of the destroyed block.
      */
     public void destroy(int x, int y, int z, int id, int data) {
-        Block block = Blocks.blocksList[id];
+        Block<?> block = Blocks.blocksList[id];
         if (block == null) return;
         int amount = 4;
         if (block == Blocks.FIRE) {
@@ -184,7 +184,7 @@ public final class ParticleEngine {
         if (id == 0) {
             return;
         }
-        Block block = Blocks.blocksList[id];
+        Block<?> block = Blocks.blocksList[id];
         AABB bounds = block.getBounds();
         float r = 0.1F;
         double xp = x + rand.nextDouble() * (bounds.maxX - bounds.minX - (r * 2.0F)) + r + bounds.minX;
diff --git a/game/client/src/main/java/net/minecraft/client/render/RenderBlockCache.java b/game/client/src/main/java/net/minecraft/client/render/RenderBlockCache.java
index 339d989ba..188f03851 100644
--- a/game/client/src/main/java/net/minecraft/client/render/RenderBlockCache.java
+++ b/game/client/src/main/java/net/minecraft/client/render/RenderBlockCache.java
@@ -26,10 +26,10 @@ final public class RenderBlockCache {
     private int offsetY = Integer.MAX_VALUE;
     private int offsetZ = Integer.MAX_VALUE;
     
-    private Block block;
+    private Block<?> block;
     private WorldSource access;
 
-    public void setupCache(Block block, WorldSource access, int x, int y, int z){
+    public void setupCache(Block<?> block, WorldSource access, int x, int y, int z){
         if(x != offsetX || y != offsetY || z != offsetZ || this.block != block || this.access != access) {
             this.block = block;
             this.access = access;
@@ -46,14 +46,14 @@ final public class RenderBlockCache {
 		float brightness = block.getBlockBrightness(access, x, y, z);
 
 		if(LightmapHelper.isLightmapEnabled() || mc.fullbright) {
-			int lightEmission = Blocks.lightEmission[block.id];
+			int lightEmission = block.emission;
 			if(lightEmission >= 15) {
 				return 1.0f;
 			}
 			if(!mc.isAmbientOcclusionEnabled()) {
 				return 1.0f;
 			}
-			Block block = access.getBlock(x, y, z);
+            Block<?> block = access.getBlock(x, y, z);
 			if(block == null) {
 				return 1.0f;
 			}
@@ -90,7 +90,7 @@ final public class RenderBlockCache {
     public int getLightmapCoord(int relX, int relY, int relZ) {
     	int index = (relX + CACHE_RANGE) * CACHE_SIZE * CACHE_SIZE + (relY + CACHE_RANGE) * CACHE_SIZE + (relZ + CACHE_RANGE);
     	if(!lightmapCoordCached[index]) {
-    		int lightEmission = Blocks.lightEmission[block.id];
+    		int lightEmission = block.emission;
     		lightmapCoordValue[index] = access.getLightmapCoord(relX + offsetX, relY + offsetY, relZ + offsetZ, lightEmission);
     		lightmapCoordCached[index] = true;
     	}
diff --git a/game/client/src/main/java/net/minecraft/client/render/RenderBlocks.java b/game/client/src/main/java/net/minecraft/client/render/RenderBlocks.java
index 642e161c2..a38c8bea9 100644
--- a/game/client/src/main/java/net/minecraft/client/render/RenderBlocks.java
+++ b/game/client/src/main/java/net/minecraft/client/render/RenderBlocks.java
@@ -56,7 +56,7 @@ public class RenderBlocks
     {
         if (mc.fullbright) return 1.0f;
         int id = blockAccess.getBlockId(x, y, z);
-        Block block = blockAccess.getBlock(x, y, z);
+        Block<?> block = blockAccess.getBlock(x, y, z);
         if (block != null)
         {
 
@@ -66,7 +66,7 @@ public class RenderBlocks
         return blockAccess.getBrightness(x, y, z, Blocks.lightEmission[id]);
     }
 
-	public void renderBlockFallingSand(Tessellator tessellator, BlockModel<Block> blockModel, Block block, WorldSource world, int x, int y, int z) {
+	public void renderBlockFallingSand(Tessellator tessellator, BlockModel<?> blockModel, Block<?> block, WorldSource world, int x, int y, int z) {
 		final boolean lightmap = LightmapHelper.isLightmapEnabled();
 		
 		float sideBottom = 1.0f;
@@ -148,7 +148,7 @@ public class RenderBlocks
 		tessellator.draw();
 	}
 
-    public boolean renderStandardBlock(Tessellator tessellator, BlockModel<Block> blockModel, AABB bounds, int x, int y, int z)
+    public boolean renderStandardBlock(Tessellator tessellator, BlockModel<?> blockModel, AABB bounds, int x, int y, int z)
     {
         int color = BlockColorDispatcher.getInstance().getDispatch(blockModel.block).getWorldColor(blockAccess, x, y, z);
         float r = (float)(color >> 16 & 0xff) / 255F;
@@ -161,7 +161,7 @@ public class RenderBlocks
      * @author CyborgCabbage
      * Thanks! :D
      */
-    public boolean renderStandardBlock(Tessellator tessellator, BlockModel<Block> blockModel, AABB bounds, int x, int y, int z, float r, float g, float b) {
+    public boolean renderStandardBlock(Tessellator tessellator, BlockModel<?> blockModel, AABB bounds, int x, int y, int z, float r, float g, float b) {
         this.enableAO = true;
         int meta = blockAccess.getBlockMetadata(x, y, z);
         cache.setupCache(blockModel.block, blockAccess, x, y, z);
@@ -172,7 +172,7 @@ public class RenderBlocks
         this.enableAO = false;
         return somethingRendered;
     }
-    public final boolean renderSide(Tessellator tessellator, BlockModel<Block> blockModel, AABB bounds, int x, int y, int z, float r, float g, float b, Side side, int meta){
+    public final boolean renderSide(Tessellator tessellator, BlockModel<?> blockModel, AABB bounds, int x, int y, int z, float r, float g, float b, Side side, int meta){
         boolean useColor;
         switch (side){
             case BOTTOM:
@@ -226,7 +226,7 @@ public class RenderBlocks
      * @author CyborgCabbage
      * Thanks! :D
      */
-    public final boolean renderSide(Tessellator tessellator, BlockModel<Block> blockModel, AABB bounds, int x, int y, int z, float r, float g, float b, int side, int meta,
+    public final boolean renderSide(Tessellator tessellator, BlockModel<?> blockModel, AABB bounds, int x, int y, int z, float r, float g, float b, int side, int meta,
                                     int dirX, int dirY, int dirZ, float depth,
                                     int topX, int topY, int topZ, float topP, float botP,
                                     int lefX, int lefY, int lefZ, float lefP, float rigP
@@ -264,11 +264,11 @@ public class RenderBlocks
         }
         return rendered;
     }
-    public final void setupLighting(Block block, int x, int y, int z, float r, float g, float b, int side, int meta,
+    public final void setupLighting(Block<?> block, int x, int y, int z, float r, float g, float b, int side, int meta,
                                     int dirX, int dirY, int dirZ, float depth,
                                     int topX, int topY, int topZ, float topP, float botP,
                                     int lefX, int lefY, int lefZ, float lefP, float rigP){
-    	boolean ao = mc.isAmbientOcclusionEnabled() && Blocks.lightEmission[block.id] == 0;
+    	boolean ao = mc.isAmbientOcclusionEnabled() && block.emission == 0;
         boolean isFullCube = depth <= FULL_CUBE_THRESHOLD;
 
     	if(LightmapHelper.isLightmapEnabled()) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
index b54465e5e..84e6d65ad 100644
--- a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
+++ b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
@@ -1300,7 +1300,7 @@ public class RenderGlobal
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.5F);
             GL11.glPushMatrix();
             int k = worldObj.getBlockId(hitResult.x, hitResult.y, hitResult.z);
-            Block block = k <= 0 ? null : Blocks.blocksList[k];
+            Block<?> block = k <= 0 ? null : Blocks.blocksList[k];
             GL11.glDisable(GL11.GL_ALPHA_TEST);
             GL11.glPolygonOffset(-3F, -3F);
             GL11.glEnable(32823 /*GL_POLYGON_OFFSET_FILL*/);
@@ -1734,7 +1734,7 @@ public class RenderGlobal
 
             case EVENT_BLOCK_BREAK: // Block break effect
                 if(data > 0) {
-                    Block block = Blocks.blocksList[data];
+                    Block<?> block = Blocks.blocksList[data];
 
                     worldObj.playBlockSoundEffect(null, (float)x + 0.5F, (float)y + 0.5F, (float)z + 0.5F, block, EnumBlockSoundEffectType.MINE);
                 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
index b69e8554a..7908c72c5 100644
--- a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
@@ -36,7 +36,6 @@ import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.util.debug.Debug;
 import net.minecraft.core.util.phys.HitResult;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.Player;
@@ -807,7 +806,7 @@ public class WorldRenderer
             {
                 continue;
             }
-            if(Blocks.blocksList[i2].blockMaterial == Material.lava)
+            if(Blocks.blocksList[i2].getMaterial() == Material.lava)
             {
                 mc.particleEngine.add(new ParticleSmoke(world, (float)randX + f1, (double)((float)y + 0.1F) - Blocks.blocksList[i2].getBounds().minY, (float)randZ + f2, 0.0D, 0.0D, 0.0D));
                 continue;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java
index 5a9c764dc..40deaa376 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/color/BlockColorDispatcher.java
@@ -6,7 +6,7 @@ import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 
 public final class BlockColorDispatcher
-    extends Dispatcher<Block, BlockColor>
+    extends Dispatcher<Block<?>, BlockColor>
 {
     private static final BlockColorDispatcher instance = new BlockColorDispatcher();
     private static final BlockColor defaultColor = new BlockColorDefault();
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
index 8ba0c6fb7..e21074ca7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
@@ -4,18 +4,19 @@ import net.minecraft.client.render.RenderBlocks;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 
-public abstract class BlockModel<T extends Block>
+public abstract class BlockModel<T extends BlockLogic>
 {
     public static RenderBlocks renderBlocks;
-    public final T block;
+    public final Block<T> block;
     protected boolean hasOverbright = false;
-    public BlockModel(Block block){
-        this.block = (T) block;
+    public BlockModel(Block<T> block){
+        this.block = block;
     }
     public abstract boolean render(Tessellator tessellator, int x, int y, int z);
     public boolean renderNoCulling(Tessellator tessellator, int x, int y, int z) {
@@ -88,23 +89,23 @@ public abstract class BlockModel<T extends Block>
     }
 
     public final boolean renderStandardBlock(Tessellator tessellator, AABB bounds, int x, int y, int z){
-        return renderBlocks.renderStandardBlock(tessellator, (BlockModel<Block>) this, bounds, x, y, z);
+        return renderBlocks.renderStandardBlock(tessellator, this, bounds, x, y, z);
     }
     public final boolean renderStandardBlock(Tessellator tessellator, AABB bounds, int x, int y, int z, float r, float g, float b){
-        return renderBlocks.renderStandardBlock(tessellator, (BlockModel<Block>) this, bounds, x, y, z, r, g, b);
+        return renderBlocks.renderStandardBlock(tessellator, this, bounds, x, y, z, r, g, b);
     }
     public final boolean renderSide(Tessellator tessellator,  AABB bounds, int x, int y, int z, Side side, int meta){
-        return renderBlocks.renderSide(tessellator, (BlockModel<Block>) this, bounds, x, y, z, 1, 1, 1, side, meta);
+        return renderBlocks.renderSide(tessellator, this, bounds, x, y, z, 1, 1, 1, side, meta);
     }
     public final boolean renderSide(Tessellator tessellator,  AABB bounds, int x, int y, int z, float r, float g, float b, Side side, int meta){
-        return renderBlocks.renderSide(tessellator, (BlockModel<Block>) this, bounds, x, y, z, r, g, b, side, meta);
+        return renderBlocks.renderSide(tessellator, this, bounds, x, y, z, r, g, b, side, meta);
     }
     public final boolean renderSide(Tessellator tessellator,  AABB bounds, int x, int y, int z, float r, float g, float b, int side, int meta,
                                     int dirX, int dirY, int dirZ, float depth,
                                     int topX, int topY, int topZ, float topP, float botP,
                                     int lefX, int lefY, int lefZ, float lefP, float rigP
     ){
-        return renderBlocks.renderSide(tessellator, (BlockModel<Block>) this, bounds, x, y, z, r, g, b, side, meta,
+        return renderBlocks.renderSide(tessellator, this, bounds, x, y, z, r, g, b, side, meta,
                 dirX, dirY, dirZ, depth,
                 topX, topY, topZ, topP, botP,
                 lefX, lefY, lefZ, lefP, rigP);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java
index c4b41b2e2..a7b9dfd7b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java
@@ -2,11 +2,12 @@ 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.BlockActivator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicActivator;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelActivator extends BlockModelVeryRotatable<BlockActivator> {
+public class BlockModelActivator<T extends BlockLogic> extends BlockModelVeryRotatable<T> {
     public final IconCoordinate[] poweredTextures = {
         TextureRegistry.getTexture("minecraft:block/activator/bottom_active"),
         TextureRegistry.getTexture("minecraft:block/activator/top_active"),
@@ -23,7 +24,7 @@ public class BlockModelActivator extends BlockModelVeryRotatable<BlockActivator>
         TextureRegistry.getTexture("minecraft:block/activator/side_active_overlay"),
         TextureRegistry.getTexture("minecraft:block/activator/side_active_overlay")
     };
-    public BlockModelActivator(Block block) {
+    public BlockModelActivator(Block<T> block) {
         super(block);
     }
 
@@ -35,7 +36,7 @@ public class BlockModelActivator extends BlockModelVeryRotatable<BlockActivator>
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        if ((data & BlockActivator.MASK_POWERED) != 0) {
+        if ((data & BlockLogicActivator.MASK_POWERED) != 0) {
             return poweredTextures[getTextureIndex(side, data)];
         } else {
             return super.getBlockTextureFromSideAndMetadata(side, data);
@@ -45,7 +46,7 @@ public class BlockModelActivator extends BlockModelVeryRotatable<BlockActivator>
     @Override
     public IconCoordinate getBlockOverbrightTextureFromSideAndMeta(Side side, int data)
     {
-        boolean isPowered = (data & BlockActivator.MASK_POWERED) != 0;
+        boolean isPowered = (data & BlockLogicActivator.MASK_POWERED) != 0;
         if (!isPowered) return null;
         return overbrightTextures[getTextureIndex(side, data)];
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java
index 96f9e0069..a7f25cb71 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java
@@ -5,12 +5,13 @@ import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelAlgae<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelAlgae(Block block) {
+public class BlockModelAlgae<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelAlgae(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java
index e2d25efd2..94842cfef 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java
@@ -3,21 +3,22 @@ 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.client.render.tessellator.Tessellator;
-import net.minecraft.core.block.BlockAxisAligned;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicAxisAligned;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.helper.Sides;
 
-public class BlockModelAxisAligned<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelAxisAligned(Block block) {
+public class BlockModelAxisAligned<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelAxisAligned(Block<T> block) {
         super(block);
     }
 
     @Override
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        Axis axis = BlockAxisAligned.metaToAxis(meta);
+        Axis axis = BlockLogicAxisAligned.metaToAxis(meta);
         switch(axis)
         {
             case Y:
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java
index 59bf3ca95..b95b4ed92 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java
@@ -4,13 +4,13 @@ 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.block.Block;
-import net.minecraft.core.block.BlockBasket;
+import net.minecraft.core.block.BlockLogicBasket;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 
-public class BlockModelBasket<T extends BlockBasket> extends BlockModelStandard<T> {
+public class BlockModelBasket<T extends BlockLogicBasket> extends BlockModelStandard<T> {
     protected IconCoordinate fillTexture = TextureRegistry.getTexture("minecraft:block/basket/fill");
-    public BlockModelBasket(Block block) {
+    public BlockModelBasket(Block<T> block) {
         super(block);
     }
 
@@ -44,7 +44,7 @@ public class BlockModelBasket<T extends BlockBasket> extends BlockModelStandard<
         bounds.set(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
         renderBlocks.renderBitMask = 0;
 
-        final int height = block.getFillLevel(renderBlocks.blockAccess, x, y, z);
+        final int height = block.getLogic().getFillLevel(renderBlocks.blockAccess, x, y, z);
         // Interior
         if (height > 0)
         {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java
index dbf36818b..7cccfe222 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java
@@ -3,14 +3,15 @@ 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.client.render.tessellator.Tessellator;
-import net.minecraft.core.block.BlockBed;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicBed;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 
-public class BlockModelBed<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelBed<T extends BlockLogic> extends BlockModelStandard<T> {
     protected IconCoordinate underTexture = TextureRegistry.getTexture("minecraft:block/bed/bottom");
-    public BlockModelBed(Block block) {
+    public BlockModelBed(Block<T> block) {
         super(block);
         atlasIndices[0] = TextureRegistry.getTexture("minecraft:block/bed/foot_front");
         atlasIndices[1] = TextureRegistry.getTexture("minecraft:block/bed/foot_side");
@@ -27,8 +28,8 @@ public class BlockModelBed<T extends Block> extends BlockModelStandard<T> {
         renderBlocks.cache.setupCache(block, renderBlocks.blockAccess, x, y, z);
 
         final int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        final int direction = BlockBed.getDirection(meta);
-        final boolean isFootOfBed = BlockBed.isBlockFootOfBed(meta);
+        final int direction = BlockLogicBed.getDirection(meta);
+        final boolean isFootOfBed = BlockLogicBed.isBlockFootOfBed(meta);
 
         final double minY = bounds.minY;
         bounds.minY += 0.1875D;
@@ -50,7 +51,7 @@ public class BlockModelBed<T extends Block> extends BlockModelStandard<T> {
         renderSide(tessellator, bounds, x, y, z, Side.TOP, meta);
 
         renderBlocks.uvRotateTop = 0;
-        final int f17 = isFootOfBed ? BlockBed.headOfBedMap[BlockBed.footToHeadMap[direction]] : BlockBed.headOfBedMap[direction];
+        final int f17 = isFootOfBed ? BlockLogicBed.headOfBedMap[BlockLogicBed.footToHeadMap[direction]] : BlockLogicBed.headOfBedMap[direction];
 
         if(f17 != 2 && (renderBlocks.renderAllFaces || shouldSideBeRendered(renderBlocks.blockAccess, bounds, x, y, z - 1, 2)))
         {
@@ -88,9 +89,9 @@ public class BlockModelBed<T extends Block> extends BlockModelStandard<T> {
         if(side == Side.BOTTOM) {
             return underTexture;
         }
-        int k = BlockBed.getDirection(data);
-        int l = BlockBed.bedDirection[k][side.getId()];
-        if(BlockBed.isBlockFootOfBed(data)) {
+        int k = BlockLogicBed.getDirection(data);
+        int l = BlockLogicBed.bedDirection[k][side.getId()];
+        if(BlockLogicBed.isBlockFootOfBed(data)) {
             if(l == 2) {
                 return atlasIndices[3];
             }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java
index 85baf689f..e19c412a0 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java
@@ -4,21 +4,21 @@ 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.block.Block;
+import net.minecraft.core.block.BlockLogicBrazier;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockBrazier;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelBrazier<T extends BlockBrazier>
+public class BlockModelBrazier<T extends BlockLogicBrazier>
     extends BlockModelStandard<T> {
     protected IconCoordinate sideTexture = TextureRegistry.getTexture("minecraft:block/brazier/side");
     protected IconCoordinate baseTexture = TextureRegistry.getTexture("minecraft:block/brazier/base");
-    protected BlockModelStandard<Block> fireModel = new BlockModelFire<>(Blocks.FIRE, true).withTextures("minecraft:block/fire");
+    protected BlockModelStandard<?> fireModel = new BlockModelFire<>(Blocks.FIRE, true).withTextures("minecraft:block/fire");
 
-    public BlockModelBrazier(Block block) {
+    public BlockModelBrazier(Block<T> block) {
         super(block);
     }
 
@@ -44,7 +44,7 @@ public class BlockModelBrazier<T extends BlockBrazier>
         renderSide(tessellator, bounds, x, y - 1, z, Side.TOP, 0);
         renderBlocks.enableAO = false;
 
-        if (block.isBurning()) {
+        if (block.getLogic().isBurning()) {
             fireModel.render(tessellator, x, y, z);
         }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java
index 0cdb12c72..44b362410 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java
@@ -3,13 +3,14 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelCactus<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelCactus(Block block) {
+public class BlockModelCactus<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelCactus(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCake.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCake.java
index 8f3e9b25a..aab08a3ed 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCake.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCake.java
@@ -3,11 +3,12 @@ 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.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelCake<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelCake<T extends BlockLogic> extends BlockModelStandard<T> {
     protected IconCoordinate cakeInner = TextureRegistry.getTexture("minecraft:block/cake/inner");
-    public BlockModelCake(Block block) {
+    public BlockModelCake(Block<T> block) {
         super(block);
         float f = 0.0625F;
         float f1 = 0.5F;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java
index 1ee54fd96..074da2f85 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java
@@ -3,10 +3,11 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelCandle<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelCandle(Block block) {
+public class BlockModelCandle<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelCandle(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java
index 07958e0e4..6833192a8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java
@@ -3,12 +3,13 @@ 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.BlockChest;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicChest;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelChest<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelChest<T extends BlockLogic> extends BlockModelStandard<T> {
     protected IconCoordinate chestFrontSingle;
     protected IconCoordinate chestFrontLeft;
     protected IconCoordinate chestFrontRight;
@@ -16,7 +17,7 @@ public class BlockModelChest<T extends Block> extends BlockModelStandard<T> {
     protected IconCoordinate chestBackRight;
     protected IconCoordinate chestSide;
     protected IconCoordinate chestTop;
-    public BlockModelChest(Block block, String rootKey) {
+    public BlockModelChest(Block<T> block, String rootKey) {
         super(block);
         chestFrontSingle = TextureRegistry.getTexture(rootKey + "front");
         chestFrontLeft = TextureRegistry.getTexture(rootKey + "left_front");
@@ -35,15 +36,15 @@ public class BlockModelChest<T extends Block> extends BlockModelStandard<T> {
             return chestTop;
         }
 
-        Side facing = BlockChest.getDirectionFromMeta(meta).getSide();
-        BlockChest.Type type = BlockChest.getTypeFromMeta(meta);
+        Side facing = BlockLogicChest.getDirectionFromMeta(meta).getSide();
+        BlockLogicChest.Type type = BlockLogicChest.getTypeFromMeta(meta);
 
-        if(type == BlockChest.Type.SINGLE) {
+        if(type == BlockLogicChest.Type.SINGLE) {
             if(side == facing) {
                 return chestFrontSingle;
             }
         }
-        if(type == BlockChest.Type.LEFT) {
+        if(type == BlockLogicChest.Type.LEFT) {
             if(side == facing) {
                 return chestFrontLeft;
             }
@@ -51,7 +52,7 @@ public class BlockModelChest<T extends Block> extends BlockModelStandard<T> {
                 return chestBackRight;
             }
         }
-        if(type == BlockChest.Type.RIGHT) {
+        if(type == BlockLogicChest.Type.RIGHT) {
             if(side == facing) {
                 return chestFrontRight;
             }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChestPainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChestPainted.java
index 3404a4fcc..fb8b6435e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChestPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChestPainted.java
@@ -3,13 +3,14 @@ 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.BlockChest;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicChest;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelChestPainted<T extends Block> extends BlockModelChest<T> {
+public class BlockModelChestPainted<T extends BlockLogic> extends BlockModelChest<T> {
     public static final IconCoordinate[][] texCoords = new IconCoordinate[DyeColor.COLOR_AMOUNT][];
     public static final int TEX_SINGLE_FRONT = 0;
     public static final int TEX_LEFT_FRONT = 1;
@@ -32,7 +33,7 @@ public class BlockModelChestPainted<T extends Block> extends BlockModelChest<T>
             texCoords[c.blockMeta][TEX_TOP] = TextureRegistry.getTexture(rootKey + "top");
         }
     }
-    public BlockModelChestPainted(Block block) {
+    public BlockModelChestPainted(Block<T> block) {
         super(block, "minecraft:block/chest/planks/");
     }
 
@@ -45,15 +46,15 @@ public class BlockModelChestPainted<T extends Block> extends BlockModelChest<T>
             return texCoords[color][6];
         }
 
-        Side facing = BlockChest.getDirectionFromMeta(meta).getSide();
-        BlockChest.Type type = BlockChest.getTypeFromMeta(meta);
+        Side facing = BlockLogicChest.getDirectionFromMeta(meta).getSide();
+        BlockLogicChest.Type type = BlockLogicChest.getTypeFromMeta(meta);
 
-        if(type == BlockChest.Type.SINGLE) {
+        if(type == BlockLogicChest.Type.SINGLE) {
             if(side == facing) {
                 return texCoords[color][TEX_SINGLE_FRONT];
             }
         }
-        if(type == BlockChest.Type.LEFT) {
+        if(type == BlockLogicChest.Type.LEFT) {
             if(side == facing) {
                 return texCoords[color][TEX_LEFT_FRONT];
             }
@@ -61,7 +62,7 @@ public class BlockModelChestPainted<T extends Block> extends BlockModelChest<T>
                 return texCoords[color][TEX_RIGHT_BACK];
             }
         }
-        if(type == BlockChest.Type.RIGHT) {
+        if(type == BlockLogicChest.Type.RIGHT) {
             if(side == facing) {
                 return texCoords[color][TEX_RIGHT_FRONT];
             }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java
index 9112fc166..3a332973e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java
@@ -5,9 +5,10 @@ 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.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelCropsPumpkin<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelCropsPumpkin<T extends BlockLogic> extends BlockModelStandard<T> {
     public static final IconCoordinate[] GROWTH_STAGE_TEXTURES_TOP = {
             TextureRegistry.getTexture("minecraft:block/crops_pumpkin/stage1_top"),
             TextureRegistry.getTexture("minecraft:block/crops_pumpkin/stage2_top"),
@@ -23,7 +24,7 @@ public class BlockModelCropsPumpkin<T extends Block> extends BlockModelStandard<
 
     public static final IconCoordinate LEAF_TEXTURE = TextureRegistry.getTexture("minecraft:block/crops_pumpkin/stage0");
 
-    public BlockModelCropsPumpkin(Block block) {
+    public BlockModelCropsPumpkin(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java
index 812b707f6..0b50edcf6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java
@@ -5,11 +5,12 @@ 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.block.Block;
-import net.minecraft.core.block.BlockCropsWheat;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicCropsWheat;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelCropsWheat<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelCropsWheat<T extends BlockLogic> extends BlockModelStandard<T> {
     public final IconCoordinate[] growthStageTextures = {
             TextureRegistry.getTexture("minecraft:block/crops_wheat/stage0"),
             TextureRegistry.getTexture("minecraft:block/crops_wheat/stage1"),
@@ -21,9 +22,9 @@ public class BlockModelCropsWheat<T extends Block> extends BlockModelStandard<T>
             TextureRegistry.getTexture("minecraft:block/crops_wheat/stage7")
     };
 
-    public BlockModelCropsWheat(Block block) {
+    public BlockModelCropsWheat(Block<T> block) {
         super(block);
-        assert growthStageTextures.length == BlockCropsWheat.MAX_GROWTH_STATE + 1 : "There must be a texture for each wheat growth stage!";
+        assert growthStageTextures.length == BlockLogicCropsWheat.MAX_GROWTH_STATE + 1 : "There must be a texture for each wheat growth stage!";
     }
 
     @Override
@@ -98,6 +99,6 @@ public class BlockModelCropsWheat<T extends Block> extends BlockModelStandard<T>
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        return growthStageTextures[MathHelper.clamp(data, 0, 7)];
+        return growthStageTextures[MathHelper.clamp(data, 0, BlockLogicCropsWheat.MAX_GROWTH_STATE)];
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java
index 6a7e29510..fbabfa513 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java
@@ -5,13 +5,14 @@ import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.helper.Side;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelCrossedSquares<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelCrossedSquares(Block block) {
+public class BlockModelCrossedSquares<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelCrossedSquares(Block<T> block) {
         super(block);
     }
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
index 70d73ae05..35f13b428 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
@@ -6,20 +6,20 @@ import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 
 public class BlockModelDispatcher
-    extends Dispatcher<Block, BlockModel>
+    extends Dispatcher<Block<?>, BlockModel<?>>
 {
     private static BlockModelDispatcher instance = new BlockModelDispatcher();
     public static BlockModelDispatcher getInstance()
     {
         return instance;
     }
-    public static BlockModelEmpty modelEmpty = new BlockModelEmpty(null);
-    public void addDispatch(BlockModel dispatchable)
+    public static BlockModelEmpty<?> modelEmpty = new BlockModelEmpty<>(null);
+    public void addDispatch(BlockModel<?> model)
     {
-        addDispatch(dispatchable.block, dispatchable);
+        addDispatch(model.block, model);
     }
     @Override
-    public void addDispatch(Block key, BlockModel value)
+    public void addDispatch(Block<?> key, BlockModel<?> value)
     {
         if (dispatches.containsValue(key)){
             throw new IllegalArgumentException("Block '" + key.toString() + "' already assigned a model!");
@@ -27,7 +27,7 @@ public class BlockModelDispatcher
         dispatches.put(key, value);
     }
     @Override
-    protected BlockModel getDefault()
+    protected BlockModel<?> getDefault()
     {
         return modelEmpty;
     }
@@ -293,8 +293,8 @@ public class BlockModelDispatcher
 
         addDispatch(new BlockModelWireRedstone<>(Blocks.WIRE_REDSTONE));
 
-        addDispatch(new BlockModelTorchRedstone(Blocks.TORCH_REDSTONE_IDLE).withTextures("minecraft:block/torch_redstone_idle"));
-        addDispatch(new BlockModelTorchRedstone(Blocks.TORCH_REDSTONE_ACTIVE).withTextures("minecraft:block/torch_redstone_active"));
+        addDispatch(new BlockModelTorchRedstone<>(Blocks.TORCH_REDSTONE_IDLE).withTextures("minecraft:block/torch_redstone_idle"));
+        addDispatch(new BlockModelTorchRedstone<>(Blocks.TORCH_REDSTONE_ACTIVE).withTextures("minecraft:block/torch_redstone_active"));
 
         final float width = 0.1875F;
         final float height = 0.125F;
@@ -333,7 +333,7 @@ public class BlockModelDispatcher
             .withCustomItemBounds(0,0,0,1,1,1));
 
         addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD, TextureRegistry.getTexture("minecraft:block/piston/side")).withTextures("minecraft:block/piston/face"));
-        addDispatch(new BlockModelEmpty(Blocks.PISTON_MOVING));
+        addDispatch(new BlockModelEmpty<>(Blocks.PISTON_MOVING));
         addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD_STEEL, TextureRegistry.getTexture("minecraft:block/piston_steel/side"), 6/16d).withTextures("minecraft:block/piston_steel/face"));
 
         addDispatch(new BlockModelStandard<>(Blocks.NOTEBLOCK).withTextures("minecraft:block/noteblock"));
@@ -345,7 +345,7 @@ public class BlockModelDispatcher
         addDispatch(new BlockModelSpikes<>(Blocks.SPIKES).withTextures("minecraft:block/spikes/top", "minecraft:block/spikes/bottom", "minecraft:block/spikes/side"));
 
         addDispatch(new BlockModelVeryRotatable<>(Blocks.DISPENSER_COBBLE_STONE).withTextures("minecraft:block/dispenser/top", "minecraft:block/dispenser/bottom", "minecraft:block/dispenser/side", "minecraft:block/dispenser/side", "minecraft:block/dispenser/front", "minecraft:block/dispenser/side"));
-        addDispatch(new BlockModelActivator(Blocks.ACTIVATOR_COBBLE_NETHERRACK).withTextures("minecraft:block/activator/top", "minecraft:block/activator/bottom", "minecraft:block/activator/side", "minecraft:block/activator/side", "minecraft:block/activator/front", "minecraft:block/activator/side"));
+        addDispatch(new BlockModelActivator<>(Blocks.ACTIVATOR_COBBLE_NETHERRACK).withTextures("minecraft:block/activator/top", "minecraft:block/activator/bottom", "minecraft:block/activator/side", "minecraft:block/activator/side", "minecraft:block/activator/front", "minecraft:block/activator/side"));
 
         addDispatch(new BlockModelTrapDoor<>(Blocks.TRAPDOOR_PLANKS_OAK).withTextures("minecraft:block/trapdoor/planks/top", "minecraft:block/trapdoor/planks/side"));
         addDispatch(new BlockModelTrapDoor<>(Blocks.TRAPDOOR_IRON).withTextures("minecraft:block/trapdoor/iron/top", "minecraft:block/trapdoor/iron/side"));
@@ -400,9 +400,9 @@ public class BlockModelDispatcher
 
         addDispatch(new BlockModelFarmland<>(Blocks.FARMLAND_DIRT).withTextures("minecraft:block/farmland/dry"));
 
-        addDispatch(new BlockModelEmpty(Blocks.SIGN_POST_PLANKS_OAK).withTextures("minecraft:block/planks/oak"));
-        addDispatch(new BlockModelEmpty(Blocks.SIGN_WALL_PLANKS_OAK).withTextures("minecraft:block/planks/oak"));
-        addDispatch(new BlockModelEmpty(Blocks.FLAG).withTextures("minecraft:block/planks/oak"));
+        addDispatch(new BlockModelEmpty<>(Blocks.SIGN_POST_PLANKS_OAK).withTextures("minecraft:block/planks/oak"));
+        addDispatch(new BlockModelEmpty<>(Blocks.SIGN_WALL_PLANKS_OAK).withTextures("minecraft:block/planks/oak"));
+        addDispatch(new BlockModelEmpty<>(Blocks.FLAG).withTextures("minecraft:block/planks/oak"));
 
         addDispatch(new BlockModelLayer<>(Blocks.LAYER_SNOW).withTextures("minecraft:block/block_snow"));
         addDispatch(new BlockModelLayer<>(Blocks.LAYER_LEAVES_OAK).withTextures("minecraft:block/leaves/oak_fancy"));
@@ -427,7 +427,7 @@ public class BlockModelDispatcher
         addDispatch(new BlockModelHorizontalRotation<>(Blocks.PUMPKIN).withTextures("minecraft:block/pumpkin/top", "minecraft:block/pumpkin/bottom", "minecraft:block/pumpkin/side"));
         addDispatch(new BlockModelHorizontalRotation<>(Blocks.PUMPKIN_CARVED_IDLE).withTextures("minecraft:block/pumpkin_carved/top", "minecraft:block/pumpkin_carved/bottom", "minecraft:block/pumpkin_carved/front", "minecraft:block/pumpkin_carved/side", "minecraft:block/pumpkin_carved/side", "minecraft:block/pumpkin_carved/side"));
         addDispatch(new BlockModelHorizontalRotation<>(Blocks.PUMPKIN_CARVED_ACTIVE).withTextures("minecraft:block/pumpkin_carved_lit/top", "minecraft:block/pumpkin_carved_lit/bottom", "minecraft:block/pumpkin_carved_lit/front", "minecraft:block/pumpkin_carved_lit/side", "minecraft:block/pumpkin_carved_lit/side", "minecraft:block/pumpkin_carved_lit/side"));
-        addDispatch(new BlockModelPumpkinRedstone(Blocks.PUMPKIN_REDSTONE).withTextures("minecraft:block/pumpkin_redstone/top", "minecraft:block/pumpkin_redstone/bottom", "minecraft:block/pumpkin_redstone/front", "minecraft:block/pumpkin_redstone/side", "minecraft:block/pumpkin_redstone/side", "minecraft:block/pumpkin_redstone/side"));
+        addDispatch(new BlockModelPumpkinRedstone<>(Blocks.PUMPKIN_REDSTONE).withTextures("minecraft:block/pumpkin_redstone/top", "minecraft:block/pumpkin_redstone/bottom", "minecraft:block/pumpkin_redstone/front", "minecraft:block/pumpkin_redstone/side", "minecraft:block/pumpkin_redstone/side", "minecraft:block/pumpkin_redstone/side"));
 
 
         addDispatch(new BlockModelStandard<>(Blocks.COBBLE_NETHERRACK).withTextures("minecraft:block/cobbled_netherrack"));
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java
index 714072c78..e56bd181f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java
@@ -5,12 +5,12 @@ import net.minecraft.client.render.RenderBlocks;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockDoor;
+import net.minecraft.core.block.BlockLogicDoor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 
-public class BlockModelDoor<T extends BlockDoor> extends BlockModelStandard<T> {
-    public BlockModelDoor(Block block) {
+public class BlockModelDoor<T extends BlockLogicDoor> extends BlockModelStandard<T> {
+    public BlockModelDoor(Block<T> block) {
         super(block);
     }
     
@@ -44,8 +44,8 @@ public class BlockModelDoor<T extends BlockDoor> extends BlockModelStandard<T> {
 			sideEastWest = 0.6f;
 		}
 		
-		boolean aboveIsDoor = renderBlocks.blockAccess.getBlock(x, y + 1, z) instanceof BlockDoor;
-		boolean belowIsDoor = renderBlocks.blockAccess.getBlock(x, y - 1, z) instanceof BlockDoor;
+		boolean aboveIsDoor = Block.hasLogicClass(renderBlocks.blockAccess.getBlock(x, y + 1, z), BlockLogicDoor.class);
+		boolean belowIsDoor = Block.hasLogicClass(renderBlocks.blockAccess.getBlock(x, y - 1, z), BlockLogicDoor.class);
 
 		int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
 		
@@ -120,7 +120,7 @@ public class BlockModelDoor<T extends BlockDoor> extends BlockModelStandard<T> {
     }
     protected boolean shouldFlipTexture(Side side, int meta){
         if(side == Side.TOP || side == Side.BOTTOM) return false;
-        int state = block.getRotation(meta);
+        int state = block.getLogic().getRotation(meta);
         int l = state / 2 + (side.getId() & 1 ^ state);
         if((state == 0 || state == 2) ^ (side.getId() <= 3))
         {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorGlass.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorGlass.java
index a2c5ba964..cecdafc59 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorGlass.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorGlass.java
@@ -1,11 +1,11 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockDoor;
+import net.minecraft.core.block.BlockLogicDoor;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelDoorGlass<T extends BlockDoor> extends BlockModelDoor<T> {
-    public BlockModelDoorGlass(Block block) {
+public class BlockModelDoorGlass<T extends BlockLogicDoor> extends BlockModelDoor<T> {
+    public BlockModelDoorGlass(Block<T> block) {
         super(block);
     }
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorPainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorPainted.java
index 61dd40e60..8eca872ad 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoorPainted.java
@@ -3,12 +3,12 @@ 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.BlockDoor;
+import net.minecraft.core.block.BlockLogicDoor;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelDoorPainted<T extends BlockDoor> extends BlockModelDoor<T> {
+public class BlockModelDoorPainted<T extends BlockLogicDoor> extends BlockModelDoor<T> {
     public static final IconCoordinate[] doorBottomTextures = new IconCoordinate[DyeColor.COLOR_AMOUNT];
     public static final IconCoordinate[] doorTopTextures = new IconCoordinate[DyeColor.COLOR_AMOUNT];
     public static final IconCoordinate[] frameTopTextures = new IconCoordinate[DyeColor.COLOR_AMOUNT];
@@ -21,7 +21,7 @@ public class BlockModelDoorPainted<T extends BlockDoor> extends BlockModelDoor<T
         }
     }
     private final boolean isTop;
-    public BlockModelDoorPainted(Block block, boolean isTop) {
+    public BlockModelDoorPainted(Block<T> block, boolean isTop) {
         super(block);
         this.isTop = isTop;
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
index 4364c2b58..8c01dacce 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
@@ -3,11 +3,12 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockModelEmpty extends BlockModelStandard<Block> {
-    public BlockModelEmpty(Block block) {
+public class BlockModelEmpty<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelEmpty(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFarmland.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFarmland.java
index d5455d4dd..a99cc6e5c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFarmland.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFarmland.java
@@ -3,28 +3,28 @@ 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.Blocks;
-import net.minecraft.core.block.BlockFarmland;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicFarmland;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelFarmland<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelFarmland<T extends BlockLogic> extends BlockModelStandard<T> {
     protected IconCoordinate topWet = TextureRegistry.getTexture("minecraft:block/farmland/wet_top");
     protected IconCoordinate topWetFertilized = TextureRegistry.getTexture("minecraft:block/farmland/wet_fertilized_top");
     protected IconCoordinate topDry = TextureRegistry.getTexture("minecraft:block/farmland/dry_top");
     protected IconCoordinate topDryFertilized = TextureRegistry.getTexture("minecraft:block/farmland/dry_fertilized_top");
     protected IconCoordinate mud = TextureRegistry.getTexture("minecraft:block/farmland/wet");
 
-    public BlockModelFarmland(Block block) {
+    public BlockModelFarmland(Block<T> block) {
         super(block);
     }
 
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, final int data)
     {
-        boolean isWet = BlockFarmland.isWet(data);
-        boolean isFertilized = BlockFarmland.isFertilized(data);
+        boolean isWet = BlockLogicFarmland.isWet(data);
+        boolean isFertilized = BlockLogicFarmland.isFertilized(data);
 
         if (side == Side.TOP) {
             if (isWet && isFertilized) {
@@ -46,7 +46,7 @@ public class BlockModelFarmland<T extends Block> extends BlockModelStandard<T> {
 
     @Override
     public boolean shouldSideBeRendered(WorldSource blockAccess, AABB bounds, int x, int y, int z, int side) {
-        if (side >= 2 && blockAccess.getBlockId(x, y, z) == Blocks.FARMLAND_DIRT.id) return false;
+        if (side >= 2 && blockAccess.getBlockId(x, y, z) == block.id()) return false;
         return super.shouldSideBeRendered(blockAccess, bounds, x, y, z, side);
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java
index 3b21d2d7c..28346c6b2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java
@@ -3,14 +3,14 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFence;
+import net.minecraft.core.block.BlockLogicFence;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelFence<T  extends BlockFence> extends BlockModelStandard<T> {
-    public BlockModelFence(Block block) {
+public class BlockModelFence<T  extends BlockLogicFence> extends BlockModelStandard<T> {
+    public BlockModelFence(Block<T> block) {
         super(block);
     }
 
@@ -22,18 +22,19 @@ public class BlockModelFence<T  extends BlockFence> extends BlockModelStandard<T
         renderStandardBlock(tessellator, bounds, x, y, z);
         boolean flag1 = false;
         boolean flag2 = false;
-        if(block.canConnectTo(renderBlocks.blockAccess, x - 1, y, z) || block.canConnectTo(renderBlocks.blockAccess, x + 1, y, z))
+        BlockLogicFence fence = block.getLogic();
+        if(fence.canConnectTo(renderBlocks.blockAccess, x - 1, y, z) || fence.canConnectTo(renderBlocks.blockAccess, x + 1, y, z))
         {
             flag1 = true;
         }
-        if(block.canConnectTo(renderBlocks.blockAccess, x, y, z - 1) || block.canConnectTo(renderBlocks.blockAccess, x, y, z + 1))
+        if(fence.canConnectTo(renderBlocks.blockAccess, x, y, z - 1) || fence.canConnectTo(renderBlocks.blockAccess, x, y, z + 1))
         {
             flag2 = true;
         }
-        boolean flag3 = block.canConnectTo(renderBlocks.blockAccess, x - 1, y, z);
-        boolean flag4 = block.canConnectTo(renderBlocks.blockAccess, x + 1, y, z);
-        boolean flag5 = block.canConnectTo(renderBlocks.blockAccess, x, y, z - 1);
-        boolean flag6 = block.canConnectTo(renderBlocks.blockAccess, x, y, z + 1);
+        boolean flag3 = fence.canConnectTo(renderBlocks.blockAccess, x - 1, y, z);
+        boolean flag4 = fence.canConnectTo(renderBlocks.blockAccess, x + 1, y, z);
+        boolean flag5 = fence.canConnectTo(renderBlocks.blockAccess, x, y, z - 1);
+        boolean flag6 = fence.canConnectTo(renderBlocks.blockAccess, x, y, z + 1);
         if(!flag1 && !flag2)
         {
             flag1 = true;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java
index 617c77436..7adc7272d 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java
@@ -3,14 +3,14 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFenceGate;
+import net.minecraft.core.block.BlockLogicFenceGate;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelFenceGate<T extends BlockFenceGate> extends BlockModelStandard<T> {
-    public BlockModelFenceGate(Block block) {
+public class BlockModelFenceGate<T extends BlockLogicFenceGate> extends BlockModelStandard<T> {
+    public BlockModelFenceGate(Block<T> block) {
         super(block);
     }
 
@@ -19,8 +19,8 @@ public class BlockModelFenceGate<T extends BlockFenceGate> extends BlockModelSta
         AABB bounds = block.getBounds();
         boolean flag = true;
         int l = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        boolean flag1 = BlockFenceGate.isOpen(l);
-        int i1 = BlockFenceGate.getDirection(l);
+        boolean flag1 = BlockLogicFenceGate.isOpen(l);
+        int i1 = BlockLogicFenceGate.getDirection(l);
         if(i1 == 3 || i1 == 1)
         {
             float f = 0.4375F;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGatePainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGatePainted.java
index d9603f8fc..ab9ed48ad 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGatePainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGatePainted.java
@@ -2,11 +2,11 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFenceGate;
+import net.minecraft.core.block.BlockLogicFenceGate;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelFenceGatePainted<T extends BlockFenceGate> extends BlockModelFenceGate<T> {
-    public BlockModelFenceGatePainted(Block block) {
+public class BlockModelFenceGatePainted<T extends BlockLogicFenceGate> extends BlockModelFenceGate<T> {
+    public BlockModelFenceGatePainted(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFencePainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFencePainted.java
index 10ef9687a..ed0480db3 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFencePainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFencePainted.java
@@ -2,13 +2,13 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFence;
+import net.minecraft.core.block.BlockLogicFence;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelFencePainted<T extends BlockFence> extends BlockModelFence<T> {
+public class BlockModelFencePainted<T extends BlockLogicFence> extends BlockModelFence<T> {
 
 
-    public BlockModelFencePainted(Block block) {
+    public BlockModelFencePainted(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java
index b3111e2ed..416c521bc 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java
@@ -6,19 +6,19 @@ import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFenceThin;
+import net.minecraft.core.block.BlockLogicFenceThin;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelFenceThin<T extends BlockFenceThin> extends BlockModelStandard<T> {
+public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockModelStandard<T> {
     private final IconCoordinate texIndex;
     private final IconCoordinate bottomTexIndex;
     private final IconCoordinate topTexIndex;
     private final IconCoordinate columnTexIndex;
 
-    public BlockModelFenceThin(Block block, IconCoordinate texIndex, IconCoordinate bottomTexIndex, IconCoordinate topTexIndex, IconCoordinate columnTexIndex){
+    public BlockModelFenceThin(Block<T> block, IconCoordinate texIndex, IconCoordinate bottomTexIndex, IconCoordinate topTexIndex, IconCoordinate columnTexIndex){
         super(block);
         this.texIndex = texIndex;
         this.bottomTexIndex = bottomTexIndex;
@@ -45,11 +45,11 @@ public class BlockModelFenceThin<T extends BlockFenceThin> extends BlockModelSta
 			cNorthSouth = 0.8f;
 			cEastWest = 0.6f;
 		}
-
-        boolean connectNorth = block.canConnectTo(renderBlocks.blockAccess, x + Direction.NORTH.getOffsetX(), y + Direction.NORTH.getOffsetY(), z + Direction.NORTH.getOffsetZ());
-        boolean connectSouth = block.canConnectTo(renderBlocks.blockAccess, x + Direction.SOUTH.getOffsetX(), y + Direction.SOUTH.getOffsetY(), z + Direction.SOUTH.getOffsetZ());
-        boolean connectEast = block.canConnectTo(renderBlocks.blockAccess, x + Direction.EAST.getOffsetX(), y + Direction.EAST.getOffsetY(), z + Direction.EAST.getOffsetZ());
-        boolean connectWest = block.canConnectTo(renderBlocks.blockAccess, x + Direction.WEST.getOffsetX(), y + Direction.WEST.getOffsetY(), z + Direction.WEST.getOffsetZ());
+        BlockLogicFenceThin thin = block.getLogic();
+        boolean connectNorth = thin.canConnectTo(renderBlocks.blockAccess, x + Direction.NORTH.getOffsetX(), y + Direction.NORTH.getOffsetY(), z + Direction.NORTH.getOffsetZ());
+        boolean connectSouth = thin.canConnectTo(renderBlocks.blockAccess, x + Direction.SOUTH.getOffsetX(), y + Direction.SOUTH.getOffsetY(), z + Direction.SOUTH.getOffsetZ());
+        boolean connectEast = thin.canConnectTo(renderBlocks.blockAccess, x + Direction.EAST.getOffsetX(), y + Direction.EAST.getOffsetY(), z + Direction.EAST.getOffsetZ());
+        boolean connectWest = thin.canConnectTo(renderBlocks.blockAccess, x + Direction.WEST.getOffsetX(), y + Direction.WEST.getOffsetY(), z + Direction.WEST.getOffsetZ());
 
         boolean lineNorthSouth = connectNorth && connectSouth;
         boolean lineEastWest = connectEast && connectWest;
@@ -85,19 +85,19 @@ public class BlockModelFenceThin<T extends BlockFenceThin> extends BlockModelSta
         double fenceBottommostMaxU = fenceBottommostTex.getSubIconU(onePix * 16);
         double fenceBottommostMaxV = fenceBottommostTex.getSubIconV(onePix * 16);
 
-        Block blockAbove = renderBlocks.blockAccess.getBlock(x, y + 1, z);
-        boolean connectUpNorth = blockAbove == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.NORTH.getOffsetX(), y + Direction.NORTH.getOffsetY() + 1, z + Direction.NORTH.getOffsetZ());
-        boolean connectUpSouth = blockAbove == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.SOUTH.getOffsetX(), y + Direction.SOUTH.getOffsetY() + 1, z + Direction.SOUTH.getOffsetZ());
-        boolean connectUpEast = blockAbove == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.EAST.getOffsetX(), y + Direction.EAST.getOffsetY() + 1, z + Direction.EAST.getOffsetZ());
-        boolean connectUpWest = blockAbove == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.WEST.getOffsetX(), y + Direction.WEST.getOffsetY() + 1, z + Direction.WEST.getOffsetZ());
+        Block<?> blockAbove = renderBlocks.blockAccess.getBlock(x, y + 1, z);
+        boolean connectUpNorth = blockAbove == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.NORTH.getOffsetX(), y + Direction.NORTH.getOffsetY() + 1, z + Direction.NORTH.getOffsetZ());
+        boolean connectUpSouth = blockAbove == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.SOUTH.getOffsetX(), y + Direction.SOUTH.getOffsetY() + 1, z + Direction.SOUTH.getOffsetZ());
+        boolean connectUpEast = blockAbove == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.EAST.getOffsetX(), y + Direction.EAST.getOffsetY() + 1, z + Direction.EAST.getOffsetZ());
+        boolean connectUpWest = blockAbove == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.WEST.getOffsetX(), y + Direction.WEST.getOffsetY() + 1, z + Direction.WEST.getOffsetZ());
 
-        Block blockBelow = renderBlocks.blockAccess.getBlock(x, y - 1, z);
-        boolean connectDownNorth = blockBelow == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.NORTH.getOffsetX(), y + Direction.NORTH.getOffsetY() - 1, z + Direction.NORTH.getOffsetZ());
-        boolean connectDownSouth = blockBelow == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.SOUTH.getOffsetX(), y + Direction.SOUTH.getOffsetY() - 1, z + Direction.SOUTH.getOffsetZ());
-        boolean connectDownEast = blockBelow == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.EAST.getOffsetX(), y + Direction.EAST.getOffsetY() - 1, z + Direction.EAST.getOffsetZ());
-        boolean connectDownWest = blockBelow == block && block.canConnectTo(renderBlocks.blockAccess, x + Direction.WEST.getOffsetX(), y + Direction.WEST.getOffsetY() - 1, z + Direction.WEST.getOffsetZ());
+        Block<?> blockBelow = renderBlocks.blockAccess.getBlock(x, y - 1, z);
+        boolean connectDownNorth = blockBelow == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.NORTH.getOffsetX(), y + Direction.NORTH.getOffsetY() - 1, z + Direction.NORTH.getOffsetZ());
+        boolean connectDownSouth = blockBelow == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.SOUTH.getOffsetX(), y + Direction.SOUTH.getOffsetY() - 1, z + Direction.SOUTH.getOffsetZ());
+        boolean connectDownEast = blockBelow == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.EAST.getOffsetX(), y + Direction.EAST.getOffsetY() - 1, z + Direction.EAST.getOffsetZ());
+        boolean connectDownWest = blockBelow == block && thin.canConnectTo(renderBlocks.blockAccess, x + Direction.WEST.getOffsetX(), y + Direction.WEST.getOffsetY() - 1, z + Direction.WEST.getOffsetZ());
 
-        if (block.shouldDrawColumn(renderBlocks.blockAccess, x, y, z))
+        if (thin.shouldDrawColumn(renderBlocks.blockAccess, x, y, z))
         {
             double sidesMinU = columnTexIndex.getIconUMin();
             double sidesMinV = columnTexIndex.getIconVMin();
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java
index 5ada4a739..92c7ab6e3 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java
@@ -4,18 +4,18 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockFire;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicFire;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelFire<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelFire<T extends BlockLogic> extends BlockModelStandard<T> {
     private final boolean overrideRender;
-    public BlockModelFire(Block block) {
+    public BlockModelFire(Block<T> block) {
         this(block, false);
     }
 
-    public BlockModelFire(Block block, boolean overrideRender) {
+    public BlockModelFire(Block<T> block, boolean overrideRender) {
         super(block);
         this.overrideRender = overrideRender;
     }
@@ -39,7 +39,7 @@ public class BlockModelFire<T extends Block> extends BlockModelStandard<T> {
         double vMin = tex.getIconVMin();
         double vMax = tex.getIconVMax();
         final float yOffset = 1.4F;
-        if(overrideRender || renderBlocks.blockAccess.isBlockNormalCube(x, y - 1, z) || ((BlockFire)Blocks.FIRE).canBurn(renderBlocks.blockAccess, x, y - 1, z))
+        if(overrideRender || renderBlocks.blockAccess.isBlockNormalCube(x, y - 1, z) || BlockLogicFire.canBurn(renderBlocks.blockAccess, x, y - 1, z))
         {
             double d8 = (double)x + 0.5D + 0.2D;
             double d9 = ((double)x + 0.5D) - 0.2D;
@@ -114,7 +114,7 @@ public class BlockModelFire<T extends Block> extends BlockModelStandard<T> {
                 uMax = uMin;
                 uMin = d10;
             }
-            if(((BlockFire)Blocks.FIRE).canBurn(renderBlocks.blockAccess, x - 1, y, z))
+            if(BlockLogicFire.canBurn(renderBlocks.blockAccess, x - 1, y, z))
             {
                 tessellator.addVertexWithUV((float)x + f3, (float)y + yOffset + f4, z + 1, uMax, vMin);
                 tessellator.addVertexWithUV(x, (float)(y) + f4, z + 1, uMax, vMax);
@@ -125,7 +125,7 @@ public class BlockModelFire<T extends Block> extends BlockModelStandard<T> {
                 tessellator.addVertexWithUV(x, (float)(y) + f4, z + 1, uMax, vMax);
                 tessellator.addVertexWithUV((float)x + f3, (float)y + yOffset + f4, z + 1, uMax, vMin);
             }
-            if(((BlockFire)Blocks.FIRE).canBurn(renderBlocks.blockAccess, x + 1, y, z))
+            if(BlockLogicFire.canBurn(renderBlocks.blockAccess, x + 1, y, z))
             {
                 tessellator.addVertexWithUV((float)(x + 1) - f3, (float)y + yOffset + f4, z, uMin, vMin);
                 tessellator.addVertexWithUV((x + 1), (float)(y) + f4, z, uMin, vMax);
@@ -136,7 +136,7 @@ public class BlockModelFire<T extends Block> extends BlockModelStandard<T> {
                 tessellator.addVertexWithUV((x + 1), (float)(y) + f4, z, uMin, vMax);
                 tessellator.addVertexWithUV((float)(x + 1) - f3, (float)y + yOffset + f4, z, uMin, vMin);
             }
-            if(((BlockFire)Blocks.FIRE).canBurn(renderBlocks.blockAccess, x, y, z - 1))
+            if(BlockLogicFire.canBurn(renderBlocks.blockAccess, x, y, z - 1))
             {
                 tessellator.addVertexWithUV(x, (float)y + yOffset + f4, (float)z + f3, uMax, vMin);
                 tessellator.addVertexWithUV(x, (float)(y) + f4, z, uMax, vMax);
@@ -147,7 +147,7 @@ public class BlockModelFire<T extends Block> extends BlockModelStandard<T> {
                 tessellator.addVertexWithUV(x, (float)(y) + f4, z, uMax, vMax);
                 tessellator.addVertexWithUV(x, (float)y + yOffset + f4, (float)z + f3, uMax, vMin);
             }
-            if(((BlockFire)Blocks.FIRE).canBurn(renderBlocks.blockAccess, x, y, z + 1))
+            if(BlockLogicFire.canBurn(renderBlocks.blockAccess, x, y, z + 1))
             {
                 tessellator.addVertexWithUV(x + 1, (float)y + yOffset + f4, (float)(z + 1) - f3, uMin, vMin);
                 tessellator.addVertexWithUV(x + 1, (float)(y) + f4, (z + 1), uMin, vMax);
@@ -158,7 +158,7 @@ public class BlockModelFire<T extends Block> extends BlockModelStandard<T> {
                 tessellator.addVertexWithUV(x + 1, (float)(y) + f4, (z + 1), uMin, vMax);
                 tessellator.addVertexWithUV(x + 1, (float)y + yOffset + f4, (float)(z + 1) - f3, uMin, vMin);
             }
-            if(((BlockFire)Blocks.FIRE).canBurn(renderBlocks.blockAccess, x, y + 1, z))
+            if(BlockLogicFire.canBurn(renderBlocks.blockAccess, x, y + 1, z))
             {
                 double d11 = (double)x + 0.5D + 0.5D;
                 double d13 = ((double)x + 0.5D) - 0.5D;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFlowerStackable.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFlowerStackable.java
index 41b48e2f2..2c600d299 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFlowerStackable.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFlowerStackable.java
@@ -3,13 +3,13 @@ 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.BlockFlowerStackable;
+import net.minecraft.core.block.BlockLogicFlowerStackable;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelFlowerStackable<T extends BlockFlowerStackable> extends BlockModelCrossedSquares<T> {
+public class BlockModelFlowerStackable<T extends BlockLogicFlowerStackable> extends BlockModelCrossedSquares<T> {
     private final IconCoordinate[] ICONS;
 
-    public BlockModelFlowerStackable(Block block, String baseTexture) {
+    public BlockModelFlowerStackable(Block<T> block, String baseTexture) {
         super(block);
 
         ICONS = new IconCoordinate[T.MAX_STACK_COUNT + 1];
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java
index 74be6157c..783fe0b99 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java
@@ -5,15 +5,16 @@ import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFluid;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicFluid;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelFluid<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelFluid(Block block) {
+public class BlockModelFluid<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelFluid(Block<T> block) {
         super(block);
     }
 
@@ -45,17 +46,17 @@ public class BlockModelFluid<T extends Block> extends BlockModelStandard<T> {
         final float sideEastWest = 0.6f;
 
         final float yOff = 0.001f;
-        Material material = block.blockMaterial;
+        Material material = block.getMaterial();
         int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        float f7 = BlockFluid.getFluidHeight(renderBlocks.blockAccess, x, y, z, material);
-        float f8 = BlockFluid.getFluidHeight(renderBlocks.blockAccess, x, y, z + 1, material);
-        float f9 = BlockFluid.getFluidHeight(renderBlocks.blockAccess, x + 1, y, z + 1, material);
-        float f10 = BlockFluid.getFluidHeight(renderBlocks.blockAccess, x + 1, y, z, material);
+        float f7 = BlockLogicFluid.getFluidHeight(renderBlocks.blockAccess, x, y, z, material);
+        float f8 = BlockLogicFluid.getFluidHeight(renderBlocks.blockAccess, x, y, z + 1, material);
+        float f9 = BlockLogicFluid.getFluidHeight(renderBlocks.blockAccess, x + 1, y, z + 1, material);
+        float f10 = BlockLogicFluid.getFluidHeight(renderBlocks.blockAccess, x + 1, y, z, material);
         if(renderBlocks.renderAllFaces || renderTop)
         {
             didRender = true;
             IconCoordinate texture = getBlockTextureFromSideAndMetadata(Side.TOP, meta);
-            float rotation = (float) BlockFluid.getSlopeAngle(renderBlocks.blockAccess, x, y, z, material);
+            float rotation = (float) BlockLogicFluid.getSlopeAngle(renderBlocks.blockAccess, x, y, z, material);
             if(rotation > -999F)
             {
                 texture = getBlockTextureFromSideAndMetadata(Side.NORTH, meta);
@@ -218,7 +219,7 @@ public class BlockModelFluid<T extends Block> extends BlockModelStandard<T> {
     public boolean shouldSideBeRendered(WorldSource blockAccess, AABB bounds, int x, int y, int z, int side)
     {
         Material material = blockAccess.getBlockMaterial(x, y, z);
-        if(material == block.blockMaterial)
+        if(material == block.getMaterial())
         {
             return false;
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java
index 50be90892..e47a6c138 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java
@@ -3,20 +3,21 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFullyRotatable;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicFullyRotatable;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockModelFullyRotatable<T extends BlockFullyRotatable> extends BlockModelStandard<T> {
-    public BlockModelFullyRotatable(Block block) {
+public class BlockModelFullyRotatable<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelFullyRotatable(Block<T> block) {
         super(block);
     }
 
     @Override
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         final int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        final Direction dir = BlockFullyRotatable.metaToDirection(meta);
+        final Direction dir = BlockLogicFullyRotatable.metaToDirection(meta);
 
         switch (dir) {
             case DOWN:
@@ -58,6 +59,7 @@ public class BlockModelFullyRotatable<T extends BlockFullyRotatable> extends Blo
         return result;
     }
 
+
     @Override
     public void renderBlockOnInventory(Tessellator tessellator, int metadata, float brightness, float alpha, @Nullable Integer lightmapCoordinate) {
         super.renderBlockOnInventory(tessellator, 1, brightness, alpha, lightmapCoordinate);
@@ -65,10 +67,10 @@ public class BlockModelFullyRotatable<T extends BlockFullyRotatable> extends Blo
 
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data) {
-        final Direction dir = BlockFullyRotatable.metaToDirection(data);
+        final Direction dir = BlockLogicFullyRotatable.metaToDirection(data);
         if (side == dir.getSide()) {
             return atlasIndices[Side.TOP.getId()];
         }
         return side.getDirection() != dir.getOpposite() ? atlasIndices[Side.NORTH.getId()] : atlasIndices[Side.BOTTOM.getId()];
     }
-}
+}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFurnace.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFurnace.java
index bbb864709..d512b8726 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFurnace.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFurnace.java
@@ -3,15 +3,16 @@ 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.BlockLogic;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.helper.Sides;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelFurnace<T extends Block>
+public class BlockModelFurnace<T extends BlockLogic>
     extends BlockModelHorizontalRotation<T> {
 
-    public BlockModelFurnace(Block block) {
+    public BlockModelFurnace(Block<T> block) {
         super(block);
     }
 
@@ -26,8 +27,7 @@ public class BlockModelFurnace<T extends Block>
             if (container != null) {
                 boolean hasOutput = container.getItem(2) != null;
                 if (hasOutput) {
-                    IconCoordinate newFront = TextureRegistry.getTexture(originalFront.namespaceId.namespace + ":block/" + originalFront.namespaceId.value + "_filled");
-                    return newFront;
+                    return TextureRegistry.getTexture(originalFront.namespaceId.namespace + ":block/" + originalFront.namespaceId.value + "_filled");
                 }
             }
             return originalFront;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java
index efb4fe85d..862c7b768 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java
@@ -6,6 +6,7 @@ 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.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.Side;
@@ -14,7 +15,7 @@ import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelGrass<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelGrass<T extends BlockLogic> extends BlockModelStandard<T> {
     public static boolean useOverlay = false;
     private static final IconCoordinate[] overlayIndices = new IconCoordinate[]{
             null,
@@ -24,7 +25,7 @@ public class BlockModelGrass<T extends Block> extends BlockModelStandard<T> {
             TextureRegistry.getTexture("minecraft:block/grass/side_overlay"),
             TextureRegistry.getTexture("minecraft:block/grass/side_overlay")};
     protected IconCoordinate snowSide = TextureRegistry.getTexture("minecraft:block/grass/snowy_side");
-    public BlockModelGrass(Block block) {
+    public BlockModelGrass(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java
index faaf02d26..fe338966d 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java
@@ -2,19 +2,20 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockRotatable;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicRotatable;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.helper.Sides;
 
-public class BlockModelHorizontalRotation<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelHorizontalRotation(Block block) {
+public class BlockModelHorizontalRotation<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelHorizontalRotation(Block<T> block) {
         super(block);
     }
 
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        int index = Sides.orientationLookUpHorizontal[6 * Math.min(data & BlockRotatable.MASK_DIRECTION, 5) + side.getId()];
+        int index = Sides.orientationLookUpHorizontal[6 * Math.min(data & BlockLogicRotatable.MASK_DIRECTION, 5) + side.getId()];
         if (index >= Sides.orientationLookUpHorizontal.length) return atlasIndices[0];
         return atlasIndices[index];
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelIce.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelIce.java
index 4f39d4fc9..0c6221b2e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelIce.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelIce.java
@@ -1,11 +1,12 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelIce<T extends Block> extends BlockModelTransparent<T> {
-    public BlockModelIce(Block block) {
+public class BlockModelIce<T extends BlockLogic> extends BlockModelTransparent<T> {
+    public BlockModelIce(Block<T> block) {
         super(block, false);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java
index ad05a9539..e644dd943 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java
@@ -5,12 +5,13 @@ 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.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelJar<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelJar<T extends BlockLogic> extends BlockModelStandard<T> {
     protected IconCoordinate jarEmpty = TextureRegistry.getTexture("minecraft:block/jar");
     protected IconCoordinate jarFull = TextureRegistry.getTexture("minecraft:block/jar_dirt");
-    public BlockModelJar(Block block) {
+    public BlockModelJar(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java
index 677785f41..eeb5ea75f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java
@@ -4,10 +4,11 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelLadder<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelLadder(Block block) {
+public class BlockModelLadder<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelLadder(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLamp.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLamp.java
index c4fde0924..44b125a73 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLamp.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLamp.java
@@ -3,12 +3,12 @@ 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.BlockLamp;
+import net.minecraft.core.block.BlockLogicLamp;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelLamp<T extends BlockLamp> extends BlockModelStandard<T> {
+public class BlockModelLamp<T extends BlockLogicLamp> extends BlockModelStandard<T> {
     private static final IconCoordinate[] texCoordsInactive = new IconCoordinate[DyeColor.COLOR_AMOUNT];
     private static final IconCoordinate[] texCoordsActive = new IconCoordinate[DyeColor.COLOR_AMOUNT];
 
@@ -19,7 +19,7 @@ public class BlockModelLamp<T extends BlockLamp> extends BlockModelStandard<T> {
         }
     }
 
-    public BlockModelLamp(Block block) {
+    public BlockModelLamp(Block<T> block) {
         super(block);
     }
 
@@ -27,7 +27,7 @@ public class BlockModelLamp<T extends BlockLamp> extends BlockModelStandard<T> {
     public IconCoordinate getBlockTexture(WorldSource worldSource, int x, int y, int z, Side side)
     {
         int color = worldSource.getBlockMetadata(x, y, z) & DyeColor.MASK_COLOR;
-        if (block.isActive) {
+        if (block.getLogic().isActive) {
             return texCoordsActive[color];
         } else {
             return texCoordsInactive[color];
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java
index f3cc255b0..ea2ba175e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java
@@ -4,19 +4,20 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLanternFirefly;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicLanternFirefly;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelLantern<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelLantern(Block block) {
+public class BlockModelLantern<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelLantern(Block<T> block) {
         super(block);
     }
 
     @Override
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        boolean isHanging = (meta & BlockLanternFirefly.MASK_HANGING) == 0;
-        boolean isAngled = (meta & BlockLanternFirefly.MASK_ANGLED) != 0;
+        boolean isHanging = (meta & BlockLogicLanternFirefly.MASK_HANGING) == 0;
+//        boolean isAngled = (meta & BlockLogicLanternFirefly.MASK_ANGLED) != 0;
 
         float brightness = 1.0f;
         if(LightmapHelper.isLightmapEnabled()) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLayer.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLayer.java
index c19c8b090..eb749ae44 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLayer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLayer.java
@@ -2,13 +2,14 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelLayer<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelLayer(Block block) {
+public class BlockModelLayer<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelLayer(Block<T> block) {
         super(block);
         withCustomItemBounds(0.0f, 0.0f, 0.0f, 1.0f, 2 / 16F, 1.0f);
     }
@@ -21,7 +22,7 @@ public class BlockModelLayer<T extends Block> extends BlockModelStandard<T> {
     @Override
     public boolean shouldSideBeRendered(WorldSource blockAccess, AABB bounds, int x, int y, int z, int side, int meta)
     {
-        if(side > 1 && blockAccess.getBlockId(x, y, z) == block.id && blockAccess.getBlockMetadata(x, y, z) == meta){
+        if(side > 1 && blockAccess.getBlockId(x, y, z) == block.id() && blockAccess.getBlockMetadata(x, y, z) == meta){
             return false;
         }
         return super.shouldSideBeRendered(blockAccess, bounds, x, y, z, side);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java
index cdbedc79d..f5f5a7ed9 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java
@@ -3,15 +3,16 @@ 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.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelLeaves<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelLeaves<T extends BlockLogic> extends BlockModelStandard<T> {
     protected static boolean fancyGraphics;
     protected final IconCoordinate fancyLeavesTexture;
 
-    public BlockModelLeaves(Block block, String leavesTex) {
+    public BlockModelLeaves(Block<T> block, String leavesTex) {
         super(block);
         withTextures(leavesTex);
         fancyLeavesTexture = TextureRegistry.getTexture(leavesTex + "_fancy");
@@ -30,7 +31,7 @@ public class BlockModelLeaves<T extends Block> extends BlockModelStandard<T> {
     public boolean shouldSideBeRendered(WorldSource blockAccess, AABB bounds, int x, int y, int z, int side)
     {
         int i1 = blockAccess.getBlockId(x, y, z);
-        if(!fancyGraphics && i1 == block.id)
+        if(!fancyGraphics && i1 == block.id())
         {
             return false;
         } else
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java
index 632036c09..69e9a846d 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java
@@ -5,21 +5,21 @@ 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.block.Block;
-import net.minecraft.core.block.BlockLeavesCacao;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicLeavesCacao;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelLeavesCacao<T extends Block> extends BlockModelLeaves<T> {
+public class BlockModelLeavesCacao<T extends BlockLogic> extends BlockModelLeaves<T> {
     protected IconCoordinate[] growthStages = new IconCoordinate[]{
             TextureRegistry.getTexture("minecraft:block/leaves/cacao_bean_stage0"),
             TextureRegistry.getTexture("minecraft:block/leaves/cacao_bean_stage1"),
             TextureRegistry.getTexture("minecraft:block/leaves/cacao_bean_stage2"),
             TextureRegistry.getTexture("minecraft:block/leaves/cacao_bean_stage3")};
-    public BlockModelLeavesCacao(Block block) {
+    public BlockModelLeavesCacao(Block<T> block) {
         super(block, "minecraft:block/leaves/cacao");
-        assert growthStages.length == BlockLeavesCacao.MAX_GROWTH_STATE : "There must be a texture associated with every cacao bean stage!";
+        assert growthStages.length == BlockLogicLeavesCacao.MAX_GROWTH_STATE : "There must be a texture associated with every cacao bean stage!";
     }
 
     @Override
@@ -28,17 +28,17 @@ public class BlockModelLeavesCacao<T extends Block> extends BlockModelLeaves<T>
 
         AABB bounds = block.getBounds();
 
-        final int growthRate = BlockLeavesCacao.getGrowthRate(renderBlocks.blockAccess.getBlockMetadata(x, y, z));
+        final int growthRate = BlockLogicLeavesCacao.getGrowthRate(renderBlocks.blockAccess.getBlockMetadata(x, y, z));
         float brightness = 1.0f;
         if(LightmapHelper.isLightmapEnabled()) {
             int lmc = block.getLightmapCoord(renderBlocks.blockAccess, x, y, z);
-            if(Blocks.lightEmission[block.id] > 0) {
+            if(block.emission > 0) {
                 lmc = LightmapHelper.setBlocklightValue(lmc, 15);
             }
             tessellator.setLightmapCoord(lmc);
         }else {
             brightness = getBlockBrightness(renderBlocks.blockAccess, x, y, z);
-            if(Blocks.lightEmission[block.id] > 0) {
+            if(block.emission > 0) {
                 brightness = 1.0f;
             }
         }
@@ -46,7 +46,7 @@ public class BlockModelLeavesCacao<T extends Block> extends BlockModelLeaves<T>
         final float cNorthSouth = 0.8F;
         final float cEastWest = 0.6F;
         if (growthRate > 0) {
-            renderBlocks.overrideBlockTexture = growthStages[Math.min(growthRate - 1, BlockLeavesCacao.MAX_GROWTH_STATE - 1)];
+            renderBlocks.overrideBlockTexture = growthStages[Math.min(growthRate - 1, BlockLogicLeavesCacao.MAX_GROWTH_STATE - 1)];
             tessellator.setColorOpaque_F(cNorthSouth * brightness, cNorthSouth * brightness, cNorthSouth * brightness);
             renderNorthFace(tessellator, bounds, x, y, z, renderBlocks.overrideBlockTexture);
             renderSouthFace(tessellator, bounds, x, y, z, renderBlocks.overrideBlockTexture);
@@ -65,7 +65,7 @@ public class BlockModelLeavesCacao<T extends Block> extends BlockModelLeaves<T>
 
         AABB bounds = block.getBounds();
 
-        final IconCoordinate cacaoCoord = growthStages[BlockLeavesCacao.MAX_GROWTH_STATE - 1];
+        final IconCoordinate cacaoCoord = growthStages[BlockLogicLeavesCacao.MAX_GROWTH_STATE - 1];
         GL11.glColor4f(brightness, brightness, brightness, alpha);
 
         tessellator.startDrawingQuads();
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java
index ecfd2f639..fbd3b8034 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java
@@ -4,15 +4,16 @@ 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.block.Block;
-import net.minecraft.core.block.BlockLeavesCherryFlowering;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicLeavesCherryFlowering;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelLeavesCherryFlowering<T extends Block> extends BlockModelLeaves<T> {
+public class BlockModelLeavesCherryFlowering<T extends BlockLogic> extends BlockModelLeaves<T> {
     private final IconCoordinate grownCherryOverlay = TextureRegistry.getTexture("minecraft:block/leaves/cherry_overlay");
     private final IconCoordinate floweringCherryOverlay = TextureRegistry.getTexture("minecraft:block/leaves/cherry_flowering_overlay");
-    public BlockModelLeavesCherryFlowering(Block block) {
+    public BlockModelLeavesCherryFlowering(Block<T> block) {
         super(block, "minecraft:block/leaves/cherry");
     }
 
@@ -20,7 +21,7 @@ public class BlockModelLeavesCherryFlowering<T extends Block> extends BlockModel
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         super.render(tessellator, x, y, z);
 
-        int growthRate = BlockLeavesCherryFlowering.getGrowthRate(renderBlocks.blockAccess.getBlockMetadata(x, y, z));
+        int growthRate = BlockLogicLeavesCherryFlowering.getGrowthRate(renderBlocks.blockAccess.getBlockMetadata(x, y, z));
         if(growthRate > 0) {
             renderBlocks.overrideBlockTexture = grownCherryOverlay;
         } else {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java
index 9c6035792..4d8f54e4f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java
@@ -4,15 +4,16 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLever;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicLever;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.util.phys.Vec3;
 
-public class BlockModelLever<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelLever(Block block) {
+public class BlockModelLever<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelLever(Block<T> block) {
         super(block);
     }
 
@@ -31,28 +32,28 @@ public class BlockModelLever<T extends Block> extends BlockModelStandard<T> {
         float f2 = 0.1875F;
         AABB bounds = block.getBounds();
         switch (i1) {
-            case BlockLever.ROTATION_BOTTOM_NS:
+            case BlockLogicLever.ROTATION_BOTTOM_NS:
                 bounds.set(0.5F - f1, 1f - f2, 0.5F - f, 0.5F + f1, 1f, 0.5F + f);
                 break;
-            case BlockLever.ROTATION_BOTTOM_WE:
+            case BlockLogicLever.ROTATION_BOTTOM_WE:
                 bounds.set(0.5F - f, 1f - f2, 0.5F - f1, 0.5F + f, 1f, 0.5F + f1);
                 break;
-            case BlockLever.ROTATION_TOP_NS:
+            case BlockLogicLever.ROTATION_TOP_NS:
                 bounds.set(0.5F - f1, 0.0F, 0.5F - f, 0.5F + f1, f2, 0.5F + f);
                 break;
-            case BlockLever.ROTATION_TOP_WE:
+            case BlockLogicLever.ROTATION_TOP_WE:
                 bounds.set(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, f2, 0.5F + f1);
                 break;
-            case BlockLever.ROTATION_NORTH:
+            case BlockLogicLever.ROTATION_NORTH:
                 bounds.set(0.5F - f1, 0.5F - f, 1.0F - f2, 0.5F + f1, 0.5F + f, 1.0F);
                 break;
-            case BlockLever.ROTATION_SOUTH:
+            case BlockLogicLever.ROTATION_SOUTH:
                 bounds.set(0.5F - f1, 0.5F - f, 0.0F, 0.5F + f1, 0.5F + f, f2);
                 break;
-            case BlockLever.ROTATION_WEST:
+            case BlockLogicLever.ROTATION_WEST:
                 bounds.set(1.0F - f2, 0.5F - f, 0.5F - f1, 1.0F, 0.5F + f, 0.5F + f1);
                 break;
-            case BlockLever.ROTATION_EAST:
+            case BlockLogicLever.ROTATION_EAST:
                 bounds.set(0.0F, 0.5F - f, 0.5F - f1, f2, 0.5F + f, 0.5F + f1);
                 break;
         }
@@ -65,7 +66,7 @@ public class BlockModelLever<T extends Block> extends BlockModelStandard<T> {
         if(LightmapHelper.isLightmapEnabled()) {
         	tessellator.setLightmapCoord(block.getLightmapCoord(renderBlocks.blockAccess, x, y, z));
         }else {
-			if(Blocks.lightEmission[block.id] > 0) {
+			if(block.emission > 0) {
 				brightness = 1.0f;
 			}else {
 				brightness = getBlockBrightness(renderBlocks.blockAccess, x, y, z);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMotionSensor.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMotionSensor.java
index 377ca0d5a..47ac3ca0f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMotionSensor.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMotionSensor.java
@@ -3,22 +3,22 @@ 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.BlockFullyRotatable;
-import net.minecraft.core.block.BlockMotionSensor;
+import net.minecraft.core.block.BlockLogicVeryRotatable;
+import net.minecraft.core.block.BlockLogicMotionSensor;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelMotionSensor extends BlockModelVeryRotatable<BlockMotionSensor> {
+public class BlockModelMotionSensor extends BlockModelVeryRotatable<BlockLogicMotionSensor> {
     protected IconCoordinate overlay = TextureRegistry.getTexture("minecraft:block/motion_sensor/active_front_overlay");
-    public BlockModelMotionSensor(Block block) {
+    public BlockModelMotionSensor(Block<BlockLogicMotionSensor> block) {
         super(block);
     }
 
     @Override
     public IconCoordinate getBlockOverbrightTextureFromSideAndMeta(Side side, int data)
     {
-        if (!block.isActive) return null;
+        if (!block.getLogic().isActive) return null;
 
-        if(side.getId() == BlockFullyRotatable.metaToDirection(data).getSide().getId())
+        if(side.getId() == BlockLogicVeryRotatable.metaToDirection(data).getSide().getId())
         {
             return overlay;
         }
@@ -26,6 +26,6 @@ public class BlockModelMotionSensor extends BlockModelVeryRotatable<BlockMotionS
     }
     @Override
     public boolean hasOverbright(){
-        return block.isActive;
+        return block.getLogic().isActive;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java
index fffb510a0..ab891b458 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java
@@ -4,13 +4,14 @@ 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.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelOverlayLeaves<T extends Block> extends BlockModelLeaves<T> {
+public class BlockModelOverlayLeaves<T extends BlockLogic> extends BlockModelLeaves<T> {
     protected final IconCoordinate overlayTexture;
-    public BlockModelOverlayLeaves(Block block, String leavesTex, String overlayTex) {
+    public BlockModelOverlayLeaves(Block<T> block, String leavesTex, String overlayTex) {
         super(block, leavesTex);
         overlayTexture = TextureRegistry.getTexture(overlayTex);
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java
index a8468b87d..1181804e2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java
@@ -5,16 +5,17 @@ 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.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelPebbles<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelPebbles<T extends BlockLogic> extends BlockModelStandard<T> {
     protected IconCoordinate[] pebbles = {
             TextureRegistry.getTexture("minecraft:block/pebbles/0"),
             TextureRegistry.getTexture("minecraft:block/pebbles/1"),
             TextureRegistry.getTexture("minecraft:block/pebbles/2")
     };
-    public BlockModelPebbles(Block block) {
+    public BlockModelPebbles(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java
index ec7abc70d..88fa02e4c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java
@@ -4,16 +4,16 @@ 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.block.Block;
-import net.minecraft.core.block.BlockEdible;
+import net.minecraft.core.block.BlockLogicEdible;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 
-public class BlockModelPiePumpkin<T extends BlockEdible> extends BlockModelStandard<T> {
+public class BlockModelPiePumpkin<T extends BlockLogicEdible> extends BlockModelStandard<T> {
     protected IconCoordinate sideTexture = TextureRegistry.getTexture("minecraft:block/pumpkin_pie/side");
     protected IconCoordinate insideTexture = TextureRegistry.getTexture("minecraft:block/pumpkin_pie/inner");
     protected IconCoordinate topTexture = TextureRegistry.getTexture("minecraft:block/pumpkin_pie/top");
 
-    public BlockModelPiePumpkin(Block block) {
+    public BlockModelPiePumpkin(Block<T> block) {
         super(block);
         float f = 0.0625F;
         float f1 = 0.375F;
@@ -48,7 +48,7 @@ public class BlockModelPiePumpkin<T extends BlockEdible> extends BlockModelStand
         boolean insideEast = sliceX == 0 ;
         boolean insideWest = sliceX == 1;
 
-        maxSlices = block.maxBites;
+        maxSlices = block.getLogic().maxBites;
         bounds.set(xMin + offsetXMin, 0.0F, zMin + offsetZMin, xMax - offsetXMax, 0.375F, zMax - offsetZMax);
         renderSide(tessellator, bounds, x, y, z, Side.TOP, 0);
         renderSide(tessellator, bounds, x, y, z, Side.BOTTOM, 0);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java
index ceb16c3ee..0ae4bffe9 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java
@@ -4,24 +4,24 @@ 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.block.Block;
-import net.minecraft.core.block.piston.BlockPistonBase;
+import net.minecraft.core.block.piston.BlockLogicPistonBase;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockModelPiston<T extends BlockPistonBase> extends BlockModelStandard<T> {
+public class BlockModelPiston<T extends BlockLogicPistonBase> extends BlockModelStandard<T> {
     private final IconCoordinate faceTexture;
     protected IconCoordinate sideTexture = TextureRegistry.getTexture("minecraft:block/piston/side");
     protected IconCoordinate topTexture = TextureRegistry.getTexture("minecraft:block/piston/top");
     protected IconCoordinate bottomTexture = TextureRegistry.getTexture("minecraft:block/piston/bottom");
 
     protected final double headThickness;
-    public BlockModelPiston(Block block, IconCoordinate faceTexture){
+    public BlockModelPiston(Block<T> block, IconCoordinate faceTexture){
         this(block, faceTexture, 4/16d);
     }
 
-    public BlockModelPiston(Block block, IconCoordinate faceTexture, double headThickness){
+    public BlockModelPiston(Block<T> block, IconCoordinate faceTexture, double headThickness){
         super(block);
         this.headThickness = headThickness;
         this.faceTexture = faceTexture;
@@ -43,16 +43,19 @@ public class BlockModelPiston<T extends BlockPistonBase> extends BlockModelStand
         return renderPistonBase(tessellator, x, y, z, false);
     }
 
+    private boolean headless = false;
     public boolean renderHeadless(Tessellator tessellator, int x, int y, int z) {
         renderBlocks.renderAllFaces = true;
+        headless = true;
         boolean result = renderPistonBase(tessellator, x, y, z, true);
+        headless = false;
         renderBlocks.renderAllFaces = false;
         return result;
     }
     protected boolean renderPistonBase(Tessellator tessellator, int x, int y, int z, boolean noCulling) {
         int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
         boolean extended = noCulling || (meta & 8) != 0;
-        Direction direction = BlockPistonBase.getDirection(meta);
+        Direction direction = BlockLogicPistonBase.getDirection(meta);
         AABB bounds;
         if(extended)
         {
@@ -159,15 +162,14 @@ public class BlockModelPiston<T extends BlockPistonBase> extends BlockModelStand
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        AABB bounds = block.getBounds();
-        Direction direction = BlockPistonBase.getDirection(data);
+        Direction direction = BlockLogicPistonBase.getDirection(data);
         if (direction == Direction.NONE)
         {
             return atlasIndices[0];
         }
         if (side.getDirection() == direction)
         {
-            if (BlockPistonBase.isPowered(data) || bounds.minX > 0.0D || bounds.minY > 0.0D || bounds.minZ > 0.0D || bounds.maxX < 1.0D || bounds.maxY < 1.0D || bounds.maxZ < 1.0D)
+            if (BlockLogicPistonBase.isPowered(data) || headless)
             {
                 return topTexture;
             }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
index 8544629b5..7a18fc5e2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
@@ -6,13 +6,13 @@ import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.piston.BlockPistonHead;
+import net.minecraft.core.block.piston.BlockLogicPistonHead;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockModelPistonHead extends BlockModelStandard<BlockPistonHead> {
+public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHead> {
     protected IconCoordinate pistonSide;
     protected IconCoordinate pistonDry = TextureRegistry.getTexture("minecraft:block/piston/face");
     protected IconCoordinate pistonSticky = TextureRegistry.getTexture("minecraft:block/piston_sticky/face");
@@ -21,11 +21,11 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockPistonHead> {
     public IconCoordinate faceTextureOverride;
 
     protected final double headThickness;
-    public BlockModelPistonHead(Block block, IconCoordinate pistonSide) {
+    public BlockModelPistonHead(Block<BlockLogicPistonHead> block, IconCoordinate pistonSide) {
         this(block, pistonSide, 4/16d);
     }
 
-    public BlockModelPistonHead(Block block, IconCoordinate pistonSide, double headThickness) {
+    public BlockModelPistonHead(Block<BlockLogicPistonHead> block, IconCoordinate pistonSide, double headThickness) {
         super(block);
         this.pistonSide = pistonSide;
         this.headThickness = headThickness;
@@ -35,7 +35,7 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockPistonHead> {
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         return renderPistonHead(tessellator, block, x, y, z, true);
     }
-    public void renderPistonHeadNoCulling(Tessellator tessellator, BlockPistonHead block, int x, int y, int z, boolean flag) {
+    public void renderPistonHeadNoCulling(Tessellator tessellator, Block<BlockLogicPistonHead> block, int x, int y, int z, boolean flag) {
         renderBlocks.renderAllFaces = true;
         renderPistonHead(tessellator, block, x, y, z, flag);
         renderBlocks.renderAllFaces = false;
@@ -43,9 +43,9 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockPistonHead> {
     public void setFaceTextureOverride(@Nullable IconCoordinate faceTexture){
         faceTextureOverride = faceTexture;
     }
-    protected boolean renderPistonHead(Tessellator tessellator, BlockPistonHead block, int x, int y, int z, boolean flag) {
+    protected boolean renderPistonHead(Tessellator tessellator, Block<BlockLogicPistonHead> block, int x, int y, int z, boolean flag) {
         int metadata = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        Direction direction = BlockPistonHead.getDirectionFromMeta(metadata);
+        Direction direction = BlockLogicPistonHead.getDirectionFromMeta(metadata);
         float brightness = 1.0f;
         if(LightmapHelper.isLightmapEnabled()) {
         	tessellator.setLightmapCoord(block.getLightmapCoord(renderBlocks.blockAccess, x, y, z));
@@ -185,19 +185,19 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockPistonHead> {
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        Direction direction = BlockPistonHead.getDirectionFromMeta(data);
+        Direction direction = BlockLogicPistonHead.getDirectionFromMeta(data);
         if(side.getDirection() == direction)
         {
             if(faceTextureOverride != null)
             {
                 return faceTextureOverride;
             }
-            switch (BlockPistonHead.getPistonType(data)) {
-                case BlockPistonHead.TYPE_NORMAL:
+            switch (BlockLogicPistonHead.getPistonType(data)) {
+                case BlockLogicPistonHead.TYPE_NORMAL:
                     return pistonDry;
-                case BlockPistonHead.TYPE_STICKY:
+                case BlockLogicPistonHead.TYPE_STICKY:
                     return pistonSticky;
-                case BlockPistonHead.TYPE_STEEL:
+                case BlockLogicPistonHead.TYPE_STEEL:
                     return pistonSteel;
             }
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPlanksPainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPlanksPainted.java
index c8669f53f..51d5e8862 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPlanksPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPlanksPainted.java
@@ -3,10 +3,11 @@ 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.BlockLogic;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelPlanksPainted<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelPlanksPainted<T extends BlockLogic> extends BlockModelStandard<T> {
     public static final IconCoordinate[] texCoords = new IconCoordinate[DyeColor.COLOR_AMOUNT];
 
     static {
@@ -15,7 +16,7 @@ public class BlockModelPlanksPainted<T extends Block> extends BlockModelStandard
         }
     }
 
-    public BlockModelPlanksPainted(Block block) {
+    public BlockModelPlanksPainted(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPortal.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPortal.java
index 867522d09..7d14b6bd2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPortal.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPortal.java
@@ -3,15 +3,15 @@ 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.BlockPortal;
+import net.minecraft.core.block.BlockLogicPortal;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelPortal<T extends BlockPortal> extends BlockModelTransparent<T> {
+public class BlockModelPortal<T extends BlockLogicPortal> extends BlockModelTransparent<T> {
     protected IconCoordinate[] colors = new IconCoordinate[16];
-    public BlockModelPortal(Block block, String rootTexKey) {
+    public BlockModelPortal(Block<T> block, String rootTexKey) {
         super(block, false);
         for (DyeColor color : DyeColor.values()) {
             colors[color.blockMeta] = TextureRegistry.getTexture(rootTexKey + color.colorID);
@@ -21,7 +21,7 @@ public class BlockModelPortal<T extends BlockPortal> extends BlockModelTranspare
     @Override
     public boolean shouldSideBeRendered(WorldSource blockAccess, AABB bounds, int x, int y, int z, int side)
     {
-        if(blockAccess.getBlockId(x, y, z) == block.id)
+        if(blockAccess.getBlockId(x, y, z) == block.id())
         {
             return false;
         }
@@ -30,7 +30,7 @@ public class BlockModelPortal<T extends BlockPortal> extends BlockModelTranspare
 
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data) {
-        return colors[block.fromMetadata(data).blockMeta];
+        return colors[block.getLogic().fromMetadata(data).blockMeta];
     }
 
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
index b0aa68bcc..254d2dc36 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
@@ -6,13 +6,14 @@ import net.minecraft.client.render.tessellator.Tessellator;
 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.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockModelPumice<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelPumice<T extends BlockLogic> extends BlockModelStandard<T> {
     private boolean lavaFlag = false;
-    public BlockModelPumice(Block block) {
+    public BlockModelPumice(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumpkinRedstone.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumpkinRedstone.java
index 575e75c8d..fb63afe6b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumpkinRedstone.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumpkinRedstone.java
@@ -3,12 +3,12 @@ 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.BlockPumpkinRedstone;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelPumpkinRedstone extends BlockModelHorizontalRotation<BlockPumpkinRedstone> {
+public class BlockModelPumpkinRedstone<T extends BlockLogic> extends BlockModelHorizontalRotation<T> {
     protected IconCoordinate overlay = TextureRegistry.getTexture("minecraft:block/pumpkin_redstone/front_overlay");
-    public BlockModelPumpkinRedstone(Block block) {
+    public BlockModelPumpkinRedstone(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java
index a04df889e..ffb05a58e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java
@@ -5,19 +5,19 @@ 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.block.Block;
-import net.minecraft.core.block.BlockRail;
+import net.minecraft.core.block.BlockLogicRail;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelRail<T extends BlockRail> extends BlockModelStandard<T> {
+public class BlockModelRail<T extends BlockLogicRail> extends BlockModelStandard<T> {
     protected IconCoordinate railCurve = TextureRegistry.getTexture("minecraft:block/rail/turn");
     protected IconCoordinate powerActive = TextureRegistry.getTexture("minecraft:block/rail_powered/active");
     protected IconCoordinate powerActiveOverlay = TextureRegistry.getTexture("minecraft:block/rail_powered/active_overlay");
     protected IconCoordinate detectorActiveOverlay = TextureRegistry.getTexture("minecraft:block/rail_detector/active_overlay");
 
-    public BlockModelRail(Block block) {
+    public BlockModelRail(Block<T> block) {
         super(block);
         this.hasOverbright = true;
     }
@@ -30,7 +30,7 @@ public class BlockModelRail<T extends BlockRail> extends BlockModelStandard<T> {
         {
             i1 = renderBlocks.overrideBlockTexture;
         }
-        if(block.getIsPowered())
+        if(block.getLogic().getIsPowered())
         {
             l &= 7;
         }
@@ -118,7 +118,7 @@ public class BlockModelRail<T extends BlockRail> extends BlockModelStandard<T> {
     @Override
     public IconCoordinate getBlockOverbrightTexture(WorldSource blockAccess, int x, int y, int z, int side)
     {
-        if (!block.isPowered || (blockAccess.getBlockMetadata(x, y, z) & 8) == 0) return null;
+        if (!block.getLogic().isPowered || (blockAccess.getBlockMetadata(x, y, z) & 8) == 0) return null;
 
         return block == Blocks.RAIL_POWERED ? powerActiveOverlay : detectorActiveOverlay;
     }
@@ -129,7 +129,7 @@ public class BlockModelRail<T extends BlockRail> extends BlockModelStandard<T> {
         if(block == Blocks.RAIL_POWERED && (data & 8) != 0)
         {
             return powerActive;
-        } else if(!block.isPowered && data >= 6)
+        } else if(!block.getLogic().isPowered && data >= 6)
         {
             return railCurve;
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java
index 68e9b1fc2..debb189ba 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java
@@ -4,17 +4,16 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockRepeater;
+import net.minecraft.core.block.BlockLogicRepeater;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-@SuppressWarnings("unchecked")
-public class BlockModelRepeater extends BlockModelStandard<BlockRepeater> {
-	private static final BlockModelTorch<Block> modelTorchActive = (BlockModelTorch<Block>) BlockModelDispatcher.getInstance().getDispatch(Blocks.TORCH_REDSTONE_ACTIVE);
-    private static final BlockModelTorch<Block> modelTorchIdle = (BlockModelTorch<Block>) BlockModelDispatcher.getInstance().getDispatch(Blocks.TORCH_REDSTONE_IDLE);
+public class BlockModelRepeater extends BlockModelStandard<BlockLogicRepeater> {
+	private static final BlockModelTorch<?> modelTorchActive = (BlockModelTorch<?>) BlockModelDispatcher.getInstance().getDispatch(Blocks.TORCH_REDSTONE_ACTIVE);
+    private static final BlockModelTorch<?> modelTorchIdle = (BlockModelTorch<?>) BlockModelDispatcher.getInstance().getDispatch(Blocks.TORCH_REDSTONE_IDLE);
 
-    public BlockModelRepeater(Block block) {
+    public BlockModelRepeater(Block<BlockLogicRepeater> block) {
         super(block);
     }
 
@@ -47,13 +46,13 @@ public class BlockModelRepeater extends BlockModelStandard<BlockRepeater> {
         float brightness = 1.0f;
         if(LightmapHelper.isLightmapEnabled()) {
         	int lmc = block.getLightmapCoord(renderBlocks.blockAccess, x, y, z);
-        	if(Blocks.lightEmission[block.id] > 0) {
+        	if(block.emission > 0) {
         		lmc = LightmapHelper.setBlocklightValue(lmc, 15);
         	}
         	tessellator.setLightmapCoord(lmc);
         }else {
     		brightness = getBlockBrightness(renderBlocks.blockAccess, x, y, z);
-    		if(Blocks.lightEmission[block.id] > 0 || Global.accessor.isFullbrightEnabled()) {
+    		if(block.emission > 0 || Global.accessor.isFullbrightEnabled()) {
     			brightness = 1.0f;
     		}
         }
@@ -67,26 +66,26 @@ public class BlockModelRepeater extends BlockModelStandard<BlockRepeater> {
         {
             case 0: // '\0'
                 d4 = -0.3125D;
-                d2 = BlockRepeater.torchPosOffset[j1];
+                d2 = BlockLogicRepeater.torchPosOffset[j1];
                 break;
 
             case 2: // '\002'
                 d4 = 0.3125D;
-                d2 = -BlockRepeater.torchPosOffset[j1];
+                d2 = -BlockLogicRepeater.torchPosOffset[j1];
                 break;
 
             case 3: // '\003'
                 d3 = -0.3125D;
-                d1 = BlockRepeater.torchPosOffset[j1];
+                d1 = BlockLogicRepeater.torchPosOffset[j1];
                 break;
 
             case 1: // '\001'
                 d3 = 0.3125D;
-                d1 = -BlockRepeater.torchPosOffset[j1];
+                d1 = -BlockLogicRepeater.torchPosOffset[j1];
                 break;
         }
-        BlockModelTorch<Block> modelTorch = block.isRepeaterPowered ? modelTorchActive : modelTorchIdle;
-        if (renderBlocks.overbright && block.isRepeaterPowered) {
+        BlockModelTorch<?> modelTorch = block.getLogic().isRepeaterPowered ? modelTorchActive : modelTorchIdle;
+        if (renderBlocks.overbright && block.getLogic().isRepeaterPowered) {
             modelTorch.renderTorchAtAngle(tessellator, (double)x + d1, (double)y + d, (double)z + d2, 0.0D, 0.0D);
             modelTorch.renderTorchAtAngle(tessellator, (double)x + d3, (double)y + d, (double)z + d4, 0.0D, 0.0D);
         } else if (!renderBlocks.overbright) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java
index b25050257..5317450e0 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java
@@ -2,23 +2,24 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLanternFirefly;
-import net.minecraft.core.block.BlockRope;
+import net.minecraft.core.block.BlockLogicLanternFirefly;
+import net.minecraft.core.block.BlockLogicRope;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelRope<T extends BlockRope>
+public class BlockModelRope<T extends BlockLogicRope>
 extends BlockModelStandard<T> {
-    public BlockModelRope(Block block) {
+    public BlockModelRope(Block<T> block) {
         super(block);
     }
 
     @Override
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         WorldSource world = renderBlocks.blockAccess;
-        boolean hasFloor = world.getBlock(x, y - 1, z) != null && world.getBlock(x, y - 1, z).canPlaceOnSurface();
+        Block<?> below;
+        boolean hasFloor = (below = world.getBlock(x, y - 1, z)) != null && below.canPlaceOnSurface();
         boolean hasBlockNegX = canConnect(world, x, y, z, Side.WEST);
         boolean hasBlockPosX = canConnect(world, x, y, z, Side.EAST);
         boolean hasBlockNegY = canConnect(world, x, y, z, Side.BOTTOM) || hasFloor;
@@ -86,9 +87,9 @@ extends BlockModelStandard<T> {
         int blockX = x + side.getOffsetX();
         int blockY = y + side.getOffsetY();
         int blockZ = z + side.getOffsetZ();
-        Block _block = worldSource.getBlock(blockX, blockY, blockZ);
+        Block<?> _block = worldSource.getBlock(blockX, blockY, blockZ);
         if (side == Side.BOTTOM){
-            if (_block instanceof BlockLanternFirefly && (worldSource.getBlockMetadata(blockX, blockY, blockZ) & 0b1) != 0){
+            if (Block.hasLogicClass(_block, BlockLogicLanternFirefly.class) && (worldSource.getBlockMetadata(blockX, blockY, blockZ) & 0b1) != 0){
                 return true;
             }
         } else if (side == Side.TOP) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRotatable.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRotatable.java
index 67296701c..53d1eb180 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRotatable.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRotatable.java
@@ -2,11 +2,12 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.helper.Sides;
 
-public class BlockModelRotatable<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelRotatable(Block block) {
+public class BlockModelRotatable<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelRotatable(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java
index 90b615dcb..de48d025c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java
@@ -2,11 +2,12 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 
-public class BlockModelSeat<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelSeat(Block block) {
+public class BlockModelSeat<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelSeat(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java
index f46d77c54..6ec38e54c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java
@@ -2,30 +2,30 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockSlab;
+import net.minecraft.core.block.BlockLogicSlab;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelSlab<T extends BlockSlab> extends BlockModelStandard<T> {
-    public BlockModelSlab(Block block){
+public class BlockModelSlab<T extends BlockLogicSlab> extends BlockModelStandard<T> {
+    public BlockModelSlab(Block<T> block){
         super(block);
-        this.atlasIndices = ((BlockModelStandard<?>)BlockModelDispatcher.getInstance().getDispatch(this.block.modelBlock)).atlasIndices;
+        this.atlasIndices = ((BlockModelStandard<?>)BlockModelDispatcher.getInstance().getDispatch(this.block.getLogic().modelBlock)).atlasIndices;
         withCustomItemBounds(0, 0, 0, 1, 0.5d, 1);
     }
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        return BlockModelDispatcher.getInstance().getDispatch(block.modelBlock).getBlockTextureFromSideAndMetadata(side, block.modelBlockMetadata);
+        return BlockModelDispatcher.getInstance().getDispatch(block.getLogic().modelBlock).getBlockTextureFromSideAndMetadata(side, block.getLogic().modelBlockMetadata);
     }
 
     @Override
     public IconCoordinate getBlockTexture(WorldSource blockAccess, int x, int y, int z, Side side)
     {
-        return BlockModelDispatcher.getInstance().getDispatch(block.modelBlock).getBlockTextureFromSideAndMetadata(side, block.modelBlockMetadata);
+        return BlockModelDispatcher.getInstance().getDispatch(block.getLogic().modelBlock).getBlockTextureFromSideAndMetadata(side, block.getLogic().modelBlockMetadata);
     }
 
     @Override
     public int renderLayer() {
-        return BlockModelDispatcher.getInstance().getDispatch(block.modelBlock).renderLayer();
+        return BlockModelDispatcher.getInstance().getDispatch(block.getLogic().modelBlock).renderLayer();
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabMarble.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabMarble.java
index 5246af227..84aca82a7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabMarble.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabMarble.java
@@ -3,14 +3,14 @@ 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.BlockSlab;
+import net.minecraft.core.block.BlockLogicSlab;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelSlabMarble<T extends BlockSlab> extends BlockModelSlab<T> {
+public class BlockModelSlabMarble<T extends BlockLogicSlab> extends BlockModelSlab<T> {
     protected IconCoordinate slabSide = TextureRegistry.getTexture("minecraft:block/carved_marble");
-    public BlockModelSlabMarble(Block block) {
+    public BlockModelSlabMarble(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabPainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabPainted.java
index bd3130f6a..8d3bd72f1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlabPainted.java
@@ -2,12 +2,12 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockSlab;
+import net.minecraft.core.block.BlockLogicSlab;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelSlabPainted<T extends BlockSlab> extends BlockModelSlab<T> {
-    public BlockModelSlabPainted(Block block) {
+public class BlockModelSlabPainted<T extends BlockLogicSlab> extends BlockModelSlab<T> {
+    public BlockModelSlabPainted(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java
index 4306355f8..44397d205 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java
@@ -4,12 +4,13 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockSpikes;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicSpikes;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 
-public class BlockModelSpikes<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelSpikes(Block block) {
+public class BlockModelSpikes<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelSpikes(Block<T> block) {
         super(block);
     }
 
@@ -24,7 +25,7 @@ public class BlockModelSpikes<T extends Block> extends BlockModelStandard<T> {
 
         renderStandardBlock(tessellator, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, 0.1875F, 1.0F), x, y, z);
 
-        if(BlockSpikes.isSpikesUp(metaData)) {
+        if(BlockLogicSpikes.isSpikesUp(metaData)) {
             float brightness = 1.0f;
             if(LightmapHelper.isLightmapEnabled()) {
             	tessellator.setLightmapCoord(block.getLightmapCoord(renderBlocks.blockAccess, x, y, z));
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java
index 568febe01..1ba715e77 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java
@@ -4,17 +4,17 @@ import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockStairs;
+import net.minecraft.core.block.BlockLogicStairs;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelStairs<T extends BlockStairs> extends BlockModelStandard<T> {
-    public BlockModelStairs(Block block) {
+public class BlockModelStairs<T extends BlockLogicStairs> extends BlockModelStandard<T> {
+    public BlockModelStairs(Block<T> block) {
         super(block);
-        this.atlasIndices = ((BlockModelStandard<?>)BlockModelDispatcher.getInstance().getDispatch(this.block.modelBlock)).atlasIndices;
+        this.atlasIndices = ((BlockModelStandard<?>)BlockModelDispatcher.getInstance().getDispatch(this.block.getLogic().modelBlock)).atlasIndices;
     }
 
     @Override
@@ -112,17 +112,17 @@ public class BlockModelStairs<T extends BlockStairs> extends BlockModelStandard<
     @Override
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        return BlockModelDispatcher.getInstance().getDispatch(block.modelBlock).getBlockTextureFromSideAndMetadata(side, data);
+        return BlockModelDispatcher.getInstance().getDispatch(block.getLogic().modelBlock).getBlockTextureFromSideAndMetadata(side, data);
     }
 
     @Override
     public IconCoordinate getBlockTexture(WorldSource blockAccess, int x, int y, int z, Side side)
     {
-        return BlockModelDispatcher.getInstance().getDispatch(block.modelBlock).getBlockTexture(blockAccess, x, y, z, side);
+        return BlockModelDispatcher.getInstance().getDispatch(block.getLogic().modelBlock).getBlockTexture(blockAccess, x, y, z, side);
     }
 
     @Override
     public int renderLayer() {
-        return BlockModelDispatcher.getInstance().getDispatch(block.modelBlock).renderLayer();
+        return BlockModelDispatcher.getInstance().getDispatch(block.getLogic().modelBlock).renderLayer();
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairsPainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairsPainted.java
index df02328aa..c60850ab1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairsPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairsPainted.java
@@ -2,12 +2,12 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockStairs;
+import net.minecraft.core.block.BlockLogicStairs;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelStairsPainted<T extends BlockStairs> extends BlockModelStairs<T> {
-    public BlockModelStairsPainted(Block block) {
+public class BlockModelStairsPainted<T extends BlockLogicStairs> extends BlockModelStairs<T> {
+    public BlockModelStairsPainted(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java
index 8443494dd..cefbbe29b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java
@@ -6,13 +6,14 @@ import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelStandard<T extends Block> extends BlockModel<T>{
+public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T>{
     public static final IconCoordinate BLOCK_TEXTURE_MISSING = TextureRegistry.getTexture("minecraft:block/texture_missing");
     public static final IconCoordinate BLOCK_TEXTURE_UNASSIGNED = TextureRegistry.getTexture("minecraft:block/texture_unassigned");
     public IconCoordinate[] atlasIndices = new IconCoordinate[]{BLOCK_TEXTURE_UNASSIGNED, BLOCK_TEXTURE_UNASSIGNED, BLOCK_TEXTURE_UNASSIGNED, BLOCK_TEXTURE_UNASSIGNED, BLOCK_TEXTURE_UNASSIGNED, BLOCK_TEXTURE_UNASSIGNED};
@@ -20,7 +21,7 @@ public class BlockModelStandard<T extends Block> extends BlockModel<T>{
     public IconCoordinate overbrightTexture = null;
     public int renderlayer = 0;
 
-    public BlockModelStandard(Block block) {
+    public BlockModelStandard(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java
index 8da732220..a32e26629 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java
@@ -5,13 +5,14 @@ import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelStoneMossy<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelStoneMossy<T extends BlockLogic> extends BlockModelStandard<T> {
     protected IconCoordinate mossOverlay;
-    public BlockModelStoneMossy(Block block) {
+    public BlockModelStoneMossy(Block<T> block) {
         super(block);
         mossOverlay = TextureRegistry.getTexture("minecraft:block/moss_overlay");
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java
index 94063164c..bb8fae801 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java
@@ -4,12 +4,12 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockTorch;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicTorch;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelTorch<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelTorch(Block block) {
+public class BlockModelTorch<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelTorch(Block<T> block) {
         super(block);
     }
 
@@ -20,7 +20,7 @@ public class BlockModelTorch<T extends Block> extends BlockModelStandard<T> {
             tessellator.setLightmapCoord(block.getLightmapCoord(renderBlocks.blockAccess, x, y, z));
         }else {
             brightness = getBlockBrightness(renderBlocks.blockAccess, x, y, z);
-            if(Blocks.lightEmission[block.id] > 0) {
+            if(block.emission > 0) {
                 brightness = 1.0F;
             }
         }
@@ -28,18 +28,18 @@ public class BlockModelTorch<T extends Block> extends BlockModelStandard<T> {
         double d = 0.4;
         double d1 = 0.5D - d;
         double d2 = 0.2;
-        int direction = renderBlocks.blockAccess.getBlockMetadata(x, y, z) & BlockTorch.MASK_DIRECTION;
+        int direction = renderBlocks.blockAccess.getBlockMetadata(x, y, z) & BlockLogicTorch.MASK_DIRECTION;
         switch (direction) {
-            case BlockTorch.SIDE_WEST:
+            case BlockLogicTorch.SIDE_WEST:
                 renderTorchAtAngle(tessellator, (double) x - d1, (double) y + d2, z, -d, 0.0D);
                 break;
-            case BlockTorch.SIDE_EAST:
+            case BlockLogicTorch.SIDE_EAST:
                 renderTorchAtAngle(tessellator, (double) x + d1, (double) y + d2, z, d, 0.0D);
                 break;
-            case BlockTorch.SIDE_NORTH:
+            case BlockLogicTorch.SIDE_NORTH:
                 renderTorchAtAngle(tessellator, x, (double) y + d2, (double) z - d1, 0.0D, -d);
                 break;
-            case BlockTorch.SIDE_SOUTH:
+            case BlockLogicTorch.SIDE_SOUTH:
                 renderTorchAtAngle(tessellator, x, (double) y + d2, (double) z + d1, 0.0D, d);
                 break;
             default:
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorchRedstone.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorchRedstone.java
index cae4c94ba..c79309466 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorchRedstone.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorchRedstone.java
@@ -2,14 +2,14 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockTorchRedstone;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelTorchRedstone extends BlockModelTorch<BlockTorchRedstone> {
-    private static final BlockModel<Block> redstoneWire = BlockModelDispatcher.getInstance().getDispatch(Blocks.WIRE_REDSTONE);
+public class BlockModelTorchRedstone<T extends BlockLogic> extends BlockModelTorch<T> {
+    private static final BlockModel<?> redstoneWire = BlockModelDispatcher.getInstance().getDispatch(Blocks.WIRE_REDSTONE);
 
-    public BlockModelTorchRedstone(Block block) {
+    public BlockModelTorchRedstone(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTransparent.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTransparent.java
index d3bb1c846..887066417 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTransparent.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTransparent.java
@@ -1,19 +1,20 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockModelTransparent<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelTransparent<T extends BlockLogic> extends BlockModelStandard<T> {
     private final boolean renderInside;
-    public BlockModelTransparent(Block block, boolean renderInside){
+    public BlockModelTransparent(Block<T> block, boolean renderInside){
         super(block);
         this.renderInside = renderInside;
     }
     @Override
     public boolean shouldSideBeRendered(WorldSource blockAccess, AABB bounds, int x, int y, int z, int side)
     {
-        if(!renderInside && blockAccess.getBlockId(x, y, z) == block.id)
+        if(!renderInside && blockAccess.getBlockId(x, y, z) == block.id())
         {
             return false;
         } else
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java
index 12db78c3e..1b3b32487 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java
@@ -3,15 +3,16 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockTrapDoor;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicTrapDoor;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.helper.Sides;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class BlockModelTrapDoor<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelTrapDoor(Block block) {
+public class BlockModelTrapDoor<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelTrapDoor(Block<T> block) {
         super(block);
         float offset = 0.1875F;
         withCustomItemBounds(0.0F, 0.0F, 0.0F, 1.0F, offset, 1.0F);
@@ -20,7 +21,7 @@ public class BlockModelTrapDoor<T extends Block> extends BlockModelStandard<T> {
     @Override
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         int metadata = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        boolean isUp = BlockTrapDoor.isTrapdoorOpen(metadata);
+        boolean isUp = BlockLogicTrapDoor.isTrapdoorOpen(metadata);
 
         if(isUp) {
             switch (metadata & 3) {
@@ -54,7 +55,7 @@ public class BlockModelTrapDoor<T extends Block> extends BlockModelStandard<T> {
             }
         }
         else{
-            if(BlockTrapDoor.isUpperHalf(metadata)){
+            if(BlockLogicTrapDoor.isUpperHalf(metadata)){
                 renderBlocks.uvRotateSouth = 3;
                 renderBlocks.uvRotateNorth = 3;
                 renderBlocks.uvRotateEast = 3;
@@ -74,7 +75,7 @@ public class BlockModelTrapDoor<T extends Block> extends BlockModelStandard<T> {
     public IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
         int orientation = data & 3;
-        if(BlockTrapDoor.isTrapdoorOpen(data)) {
+        if(BlockLogicTrapDoor.isTrapdoorOpen(data)) {
             int index = Sides.orientationLookUpTrapdoorOpen[6 * orientation + side.getId()];
             return atlasIndices[index];
         } else {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoorPainted.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoorPainted.java
index 04b151c36..0a38a0ca6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoorPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoorPainted.java
@@ -3,13 +3,14 @@ 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.BlockTrapDoor;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicTrapDoor;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.helper.Sides;
 
-public class BlockModelTrapDoorPainted<T extends Block> extends BlockModelTrapDoor<T> {
+public class BlockModelTrapDoorPainted<T extends BlockLogic> extends BlockModelTrapDoor<T> {
     public static final IconCoordinate[] topTextures = new IconCoordinate[DyeColor.COLOR_AMOUNT];
     public static final IconCoordinate[] sideTextures = new IconCoordinate[DyeColor.COLOR_AMOUNT];
 
@@ -19,7 +20,7 @@ public class BlockModelTrapDoorPainted<T extends Block> extends BlockModelTrapDo
             sideTextures[c.blockMeta] = TextureRegistry.getTexture("minecraft:block/trapdoor/planks_" + c.colorID + "/side");
         }
     }
-    public BlockModelTrapDoorPainted(Block block) {
+    public BlockModelTrapDoorPainted(Block<T> block) {
         super(block);
     }
     @Override
@@ -27,7 +28,7 @@ public class BlockModelTrapDoorPainted<T extends Block> extends BlockModelTrapDo
     {
         int color = (data >> 4) & DyeColor.MASK_COLOR;
         int orientation = data & 3;
-        if(BlockTrapDoor.isTrapdoorOpen(data)) {
+        if(BlockLogicTrapDoor.isTrapdoorOpen(data)) {
             int index = Sides.orientationLookUpTrapdoorOpen[6 * orientation + side.getId()];
             if (index < 2) return topTextures[color];
             return sideTextures[color];
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java
index 58c696a32..a5877d724 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java
@@ -3,20 +3,21 @@ package net.minecraft.client.render.block.model;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockTileEntityVeryRotatable;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicVeryRotatable;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockModelVeryRotatable<T extends Block> extends BlockModelStandard<T> {
-    public BlockModelVeryRotatable(Block block) {
+public class BlockModelVeryRotatable<T extends BlockLogic> extends BlockModelStandard<T> {
+    public BlockModelVeryRotatable(Block<T> block) {
         super(block);
     }
 
     @Override
     public boolean render(Tessellator tessellator, int x, int y, int z) {
         final int meta = renderBlocks.blockAccess.getBlockMetadata(x, y, z);
-        final Direction dir = BlockTileEntityVeryRotatable.metaToDirection(meta);
+        final Direction dir = BlockLogicVeryRotatable.metaToDirection(meta);
 
         if (dir == Direction.DOWN || dir == Direction.UP) {
             renderBlocks.uvRotateSouth = 1;
@@ -41,7 +42,7 @@ public class BlockModelVeryRotatable<T extends Block> extends BlockModelStandard
     }
 
     public int getTextureIndex(Side side, int data) {
-        final Direction dir = BlockTileEntityVeryRotatable.metaToDirection(data);
+        final Direction dir = BlockLogicVeryRotatable.metaToDirection(data);
         switch (dir) { // I love brute forcing fixes so much :3
             case SOUTH:
                 return side.getId();
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java
index e00523025..66d69aedf 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java
@@ -6,15 +6,15 @@ import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.util.helper.Colors;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockWireRedstone;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicWireRedstone;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.helper.Color;
 
-public class BlockModelWireRedstone<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelWireRedstone<T extends BlockLogic> extends BlockModelStandard<T> {
     protected final IconCoordinate wireStraight = TextureRegistry.getTexture("minecraft:block/wire_redstone_straight");
     protected final IconCoordinate wireCross = TextureRegistry.getTexture("minecraft:block/wire_redstone_cross");
-    public BlockModelWireRedstone(Block block) {
+    public BlockModelWireRedstone(Block<T> block) {
         super(block);
         withTextures("minecraft:block/wire_redstone_cross");
     }
@@ -38,7 +38,7 @@ public class BlockModelWireRedstone<T extends Block> extends BlockModelStandard<
             tessellator.setLightmapCoord(lmc);
         }else {
             brightness = getBlockBrightness(renderBlocks.blockAccess, x, y, z);
-            if(Blocks.lightEmission[block.id] > 0) {
+            if(block.emission > 0) {
                 brightness = 1.0f;
             }
             brightness = Math.max(brightness, (meta & 0xF)/16f);
@@ -51,32 +51,32 @@ public class BlockModelWireRedstone<T extends Block> extends BlockModelStandard<
         float blue = color.getBlue() / 255.0f;
 
         tessellator.setColorOpaque_F(brightness * red, brightness * green, brightness * blue);
-        boolean west = BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x - 1, y, z, 1) || !renderBlocks.blockAccess.isBlockNormalCube(x - 1, y, z) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x - 1, y - 1, z, -1);
-        boolean east = BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x + 1, y, z, 3) || !renderBlocks.blockAccess.isBlockNormalCube(x + 1, y, z) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x + 1, y - 1, z, -1);
-        boolean north = BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y, z - 1, 2) || !renderBlocks.blockAccess.isBlockNormalCube(x, y, z - 1) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y - 1, z - 1, -1);
-        boolean south = BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y, z + 1, 0) || !renderBlocks.blockAccess.isBlockNormalCube(x, y, z + 1) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y - 1, z + 1, -1);
+        boolean west = BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x - 1, y, z, 1) || !renderBlocks.blockAccess.isBlockNormalCube(x - 1, y, z) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x - 1, y - 1, z, -1);
+        boolean east = BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x + 1, y, z, 3) || !renderBlocks.blockAccess.isBlockNormalCube(x + 1, y, z) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x + 1, y - 1, z, -1);
+        boolean north = BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y, z - 1, 2) || !renderBlocks.blockAccess.isBlockNormalCube(x, y, z - 1) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y - 1, z - 1, -1);
+        boolean south = BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y, z + 1, 0) || !renderBlocks.blockAccess.isBlockNormalCube(x, y, z + 1) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y - 1, z + 1, -1);
         boolean westUp = false;
         boolean eastUp = false;
         boolean northUp = false;
         boolean southUp = false;
         if(!renderBlocks.blockAccess.isBlockOpaqueCube(x, y + 1, z))
         {
-            if(renderBlocks.blockAccess.isBlockNormalCube(x - 1, y, z) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x - 1, y + 1, z, -1))
+            if(renderBlocks.blockAccess.isBlockNormalCube(x - 1, y, z) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x - 1, y + 1, z, -1))
             {
                 west = true;
                 westUp = true;
             }
-            if(renderBlocks.blockAccess.isBlockNormalCube(x + 1, y, z) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x + 1, y + 1, z, -1))
+            if(renderBlocks.blockAccess.isBlockNormalCube(x + 1, y, z) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x + 1, y + 1, z, -1))
             {
                 east = true;
                 eastUp = true;
             }
-            if(renderBlocks.blockAccess.isBlockNormalCube(x, y, z - 1) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y + 1, z - 1, -1))
+            if(renderBlocks.blockAccess.isBlockNormalCube(x, y, z - 1) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y + 1, z - 1, -1))
             {
                 north = true;
                 northUp = true;
             }
-            if(renderBlocks.blockAccess.isBlockNormalCube(x, y, z + 1) && BlockWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y + 1, z + 1, -1))
+            if(renderBlocks.blockAccess.isBlockNormalCube(x, y, z + 1) && BlockLogicWireRedstone.shouldConnectTo(renderBlocks.blockAccess, x, y + 1, z + 1, -1))
             {
                 south = true;
                 southUp = true;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWool.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWool.java
index f450baf72..6059031e9 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWool.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWool.java
@@ -3,10 +3,11 @@ 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.BlockLogic;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 
-public class BlockModelWool<T extends Block> extends BlockModelStandard<T> {
+public class BlockModelWool<T extends BlockLogic> extends BlockModelStandard<T> {
     public static final IconCoordinate[] texCoords = new IconCoordinate[DyeColor.COLOR_AMOUNT];
 
     static {
@@ -14,7 +15,7 @@ public class BlockModelWool<T extends Block> extends BlockModelStandard<T> {
             texCoords[c.blockMeta] = TextureRegistry.getTexture("minecraft:block/wool/" + c.colorID);
         }
     }
-    public BlockModelWool(Block block) {
+    public BlockModelWool(Block<T> block) {
         super(block);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlag.java b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlag.java
index fc3918ab9..e157aa28c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlag.java
+++ b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlag.java
@@ -29,7 +29,7 @@ public class TileEntityRendererFlag extends TileEntityRenderer<TileEntityFlag>
     public void doRender(Tessellator tessellator, TileEntityFlag tileEntity, double x, double y, double z, float partialTick) {
         World theWorld = Minecraft.getMinecraft().currentWorld;
         int blockUnder = theWorld.getBlockId(tileEntity.x, tileEntity.y - 1, tileEntity.z);
-        boolean shortPole = blockUnder == Blocks.FLAG.id;
+        boolean shortPole = blockUnder == Blocks.FLAG.id();
 
         WindProvider theWind = mc.currentWorld.getWorldType().getWindManager();
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlowerJar.java b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlowerJar.java
index 08127f80e..e14d148ce 100644
--- a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlowerJar.java
+++ b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererFlowerJar.java
@@ -29,7 +29,7 @@ public class TileEntityRendererFlowerJar extends TileEntityRenderer<TileEntityFl
     @Override
     public void doRender(Tessellator tessellator, TileEntityFlowerJar tileEntity, double x, double y, double z, float renderPartialTicks) {
         GL11.glPushMatrix();
-        Block block = Blocks.getBlock(tileEntity.flowerInPot);
+        Block<?> block = Blocks.getBlock(tileEntity.flowerInPot);
         if(block != null){
             GL11.glTranslatef((float)x, (float)y, (float)z);
             TextureRegistry.blockAtlas.bind();
diff --git a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererMovingPiston.java b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererMovingPiston.java
index bd31230a2..12cbe6d64 100644
--- a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererMovingPiston.java
+++ b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererMovingPiston.java
@@ -13,10 +13,9 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.block.piston.BlockPistonBase;
+import net.minecraft.core.block.piston.BlockLogicPistonBaseSteel;
+import net.minecraft.core.block.piston.BlockLogicPistonHead;
 import net.minecraft.core.block.piston.TileEntityMovingPistonBlock;
-import net.minecraft.core.block.piston.BlockPistonHead;
-import net.minecraft.core.block.piston.BlockPistonBaseSteel;
 import net.minecraft.core.world.BlocksContainer;
 import net.minecraft.core.world.World;
 import org.lwjgl.opengl.GL11;
@@ -44,7 +43,7 @@ public class TileEntityRendererMovingPiston extends TileEntityRenderer<TileEntit
 	public void doRender(Tessellator tessellator, TileEntityMovingPistonBlock blockEntity, double x, double y, double z,
                          float partialTick)
     {
-        Block block = Blocks.blocksList[blockEntity.getMovedId()];
+        Block<?> block = Blocks.getBlock(blockEntity.getMovedId());
         if(block != null && blockEntity.getProgress(partialTick) < 1.0F)
         {
             if (container == null || container.world != blockEntity.worldObj) {
@@ -65,24 +64,24 @@ public class TileEntityRendererMovingPiston extends TileEntityRenderer<TileEntit
             }
             tessellator.startDrawingQuads();
             tessellator.setTranslation(((float)x - (float)blockEntity.x) + blockEntity.getXOff(partialTick), ((float)y - (float)blockEntity.y) + blockEntity.getYOff(partialTick), ((float)z - (float)blockEntity.z) + blockEntity.getZOff(partialTick));
-            if(block instanceof BlockPistonHead && blockEntity.getProgress(partialTick) < 0.5F)
+            if(Block.hasLogicClass(block, BlockLogicPistonHead.class) && blockEntity.getProgress(partialTick) < 0.5F)
             {
                 BlockModel.setRenderBlocks(renderBlocks);
-                ((BlockModelPistonHead)BlockModelDispatcher.getInstance().getDispatch(block)).renderPistonHeadNoCulling(tessellator, (BlockPistonHead) block, blockEntity.x, blockEntity.y, blockEntity.z, false);
+                ((BlockModelPistonHead)BlockModelDispatcher.getInstance().getDispatch(block)).renderPistonHeadNoCulling(tessellator, (Block<BlockLogicPistonHead>) block, blockEntity.x, blockEntity.y, blockEntity.z, false);
             } else
             if(blockEntity.isSourcePiston() && !blockEntity.isExtending())
             {
-                BlockModelPiston<BlockPistonBase> pistonBase = (BlockModelPiston) BlockModelDispatcher.getInstance().getDispatch(block);
+                BlockModelPiston<?> pistonBase = (BlockModelPiston<?>) BlockModelDispatcher.getInstance().getDispatch(block);
                 BlockModel.setRenderBlocks(renderBlocks);
-                if (block instanceof BlockPistonBaseSteel) { // Todo remove this terrible hardcoded render code
+                if (Block.hasLogicClass(block, BlockLogicPistonBaseSteel.class)) { // Todo remove this terrible hardcoded render code
                     BlockModelPistonHead blockModelPistonHead = ((BlockModelPistonHead) BlockModelDispatcher.getInstance().getDispatch(Blocks.PISTON_HEAD_STEEL));
                     blockModelPistonHead.setFaceTextureOverride(pistonBase.getFaceTexture());
-                    blockModelPistonHead.renderPistonHeadNoCulling(tessellator, (BlockPistonHead) Blocks.PISTON_HEAD_STEEL, blockEntity.x, blockEntity.y, blockEntity.z, blockEntity.getProgress(partialTick) < 0.5F);
+                    blockModelPistonHead.renderPistonHeadNoCulling(tessellator, Blocks.PISTON_HEAD_STEEL, blockEntity.x, blockEntity.y, blockEntity.z, blockEntity.getProgress(partialTick) < 0.5F);
                     blockModelPistonHead.setFaceTextureOverride(null);
                 } else {
                     BlockModelPistonHead blockModelPistonHead = ((BlockModelPistonHead) BlockModelDispatcher.getInstance().getDispatch(Blocks.PISTON_HEAD));
                     blockModelPistonHead.setFaceTextureOverride(pistonBase.getFaceTexture());
-                    blockModelPistonHead.renderPistonHeadNoCulling(tessellator, (BlockPistonHead) Blocks.PISTON_HEAD, blockEntity.x, blockEntity.y, blockEntity.z, blockEntity.getProgress(partialTick) < 0.5F);
+                    blockModelPistonHead.renderPistonHeadNoCulling(tessellator, Blocks.PISTON_HEAD, blockEntity.x, blockEntity.y, blockEntity.z, blockEntity.getProgress(partialTick) < 0.5F);
                     blockModelPistonHead.setFaceTextureOverride(null);
                 }
                 tessellator.setTranslation((float)x - (float)blockEntity.x, (float)y - (float)blockEntity.y, (float)z - (float)blockEntity.z);
@@ -90,8 +89,8 @@ public class TileEntityRendererMovingPiston extends TileEntityRenderer<TileEntit
             } else
             {
                 BlockModel.setRenderBlocks(containerRenderBlock);
-                container.setBlock(blockEntity.x, blockEntity.y, blockEntity.z, block.id, blockEntity.getMovedData(), blockEntity.getMovedEntity());
-                BlockModelDispatcher.getInstance().getDispatch(block).renderNoCulling(Tessellator.instance, blockEntity.x, blockEntity.y, blockEntity.z);
+                container.setBlock(blockEntity.x, blockEntity.y, blockEntity.z, block.id(), blockEntity.getMovedData(), blockEntity.getMovedEntity());
+                BlockModelDispatcher.getInstance().getDispatch(block).renderNoCulling(tessellator, blockEntity.x, blockEntity.y, blockEntity.z);
                 container.setLightReferenceEntity(null);
                 container.clear();
             }
diff --git a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererSign.java b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererSign.java
index ba93ed529..519558e45 100644
--- a/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererSign.java
+++ b/game/client/src/main/java/net/minecraft/client/render/blockentity/TileEntityRendererSign.java
@@ -28,7 +28,7 @@ public class TileEntityRendererSign extends TileEntityRenderer<TileEntitySign>
     public void renderTileEntitySignAt(TileEntitySign tileEntity, double d, double d1, double d2,
                                        float f)
     {
-        Block block = tileEntity.getBlock();
+        Block<?> block = tileEntity.getBlock();
         GL11.glPushMatrix();
         float scale = 0.6666667F;
         if(block == Blocks.SIGN_POST_PLANKS_OAK)
diff --git a/game/client/src/main/java/net/minecraft/client/render/camera/CameraUtil.java b/game/client/src/main/java/net/minecraft/client/render/camera/CameraUtil.java
index 276710b8c..2fd36b3db 100644
--- a/game/client/src/main/java/net/minecraft/client/render/camera/CameraUtil.java
+++ b/game/client/src/main/java/net/minecraft/client/render/camera/CameraUtil.java
@@ -1,9 +1,8 @@
 package net.minecraft.client.render.camera;
 
-import net.minecraft.core.block.BlockFluid;
+import net.minecraft.core.block.BlockLogicFluid;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.phys.HitResult;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.Vec3;
@@ -26,9 +25,9 @@ public abstract class CameraUtil
         int y = MathHelper.floor_float(MathHelper.floor(cameraY));
         int z = MathHelper.floor(camera.getZ(partialTick));
         int id = world.getBlockId(x, y, z);
-        if(id != 0 && Blocks.blocksList[id].blockMaterial == material)
+        if(id != 0 && Blocks.blocksList[id].getMaterial() == material)
         {
-            float f = BlockFluid.getWaterVolume(world.getBlockMetadata(x, y, z)) - 0.2F;
+            float f = BlockLogicFluid.getWaterVolume(world.getBlockMetadata(x, y, z)) - 0.2F;
             float f1 = (float)(y + 1) - f;
             return cameraY < (double)f1;
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
index 64d21cf63..5a4dd0935 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
@@ -147,7 +147,7 @@ public abstract class EntityRenderer<T extends Entity>
         return renderDispatcher.world;
     }
 
-    private void renderShadowOnBlock(Tessellator tessellator, T entity, Block block, double d, double d1, double d2,
+    private void renderShadowOnBlock(Tessellator tessellator, T entity, Block<?> block, double d, double d1, double d2,
                                      int x, int y, int z, float opacity, float size, double xo,
                                      double yo, double zo)
     {
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java
index c25847e04..589409b52 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java
@@ -13,7 +13,6 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.EntityFallingBlock;
 import net.minecraft.core.world.BlocksContainer;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.util.helper.MathHelper;
 import org.lwjgl.opengl.GL11;
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java
index 5ed089652..c1e070110 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java
@@ -36,7 +36,7 @@ public class EntityRendererItem extends EntityRenderer<EntityItem>
 
 	public int getItemColorFromMetadata(Item item, int metadata) {
 		if (item instanceof ItemBlock) {
-			Block block = ((ItemBlock)item).getBlock();
+			Block<?> block = ((ItemBlock<?>)item).getBlock();
 			return BlockColorDispatcher.getInstance().getDispatch(block).getFallbackColor(metadata);
 		}
 		return 0xFFFFFF;
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java
index ad83e5d58..91b94b718 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java
@@ -97,7 +97,7 @@ public class EntityRendererMinecart extends EntityRenderer<MinecartEntity> {
             }
             switch (minecart.type){
                 case MinecartEntity.CHEST_CART:
-                    Block block;
+                    Block<?> block;
                     if ((minecart.typeMeta & 0b0000_0001) != 0) {
                         block = Blocks.CHEST_PLANKS_OAK_PAINTED;
                     } else {
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java
index 49a9c7666..a97975654 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java
@@ -23,11 +23,11 @@ public class EntityRendererSprite<T extends Entity> extends EntityRenderer<T>
         itemIconIndex = i;
     }
 
-    public EntityRendererSprite setFullBright(){
+    public EntityRendererSprite<T> setFullBright(){
         fullBright = true;
         return this;
     }
-    public EntityRendererSprite setScale(float scale){
+    public EntityRendererSprite<T> setScale(float scale){
         this.scale = scale;
         return this;
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java
index d52cefa96..05c78e1eb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java
@@ -7,12 +7,12 @@ import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.EntityPrimedTNT;
 import net.minecraft.core.Global;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import org.lwjgl.opengl.GL11;
 
 public class EntityRendererTNT extends EntityRenderer<EntityPrimedTNT>
 {
+    private final RenderBlocks blockRenderer;
 
     public EntityRendererTNT()
     {
@@ -20,15 +20,14 @@ public class EntityRendererTNT extends EntityRenderer<EntityPrimedTNT>
         shadowSize = 0.5F;
     }
 
-    public void renderTNT(EntityPrimedTNT tnt, double d, double d1, double d2,
-                          float f, float f1)
+    @Override
+    public void render(Tessellator tessellator, EntityPrimedTNT tnt, double x, double y, double z, float yaw, float partialTick)
     {
-        Tessellator tessellator = Tessellator.instance;
         GL11.glPushMatrix();
-        GL11.glTranslatef((float)d, (float)d1, (float)d2);
-        if(((float)tnt.fuse - f1) + 1.0F < 10F)
+        GL11.glTranslatef((float)x, (float)y, (float)z);
+        if(((float)tnt.fuse - partialTick) + 1.0F < 10F)
         {
-            float f2 = 1.0F - (((float)tnt.fuse - f1) + 1.0F) / 10F;
+            float f2 = 1.0F - (((float)tnt.fuse - partialTick) + 1.0F) / 10F;
             if(f2 < 0.0F)
             {
                 f2 = 0.0F;
@@ -42,11 +41,12 @@ public class EntityRendererTNT extends EntityRenderer<EntityPrimedTNT>
             float f4 = 1.0F + f2 * 0.3F;
             GL11.glScalef(f4, f4, f4);
         }
-        float f3 = (1.0F - (((float)tnt.fuse - f1) + 1.0F) / 100F) * 0.8F;
+        float f3 = (1.0F - (((float)tnt.fuse - partialTick) + 1.0F) / 100F) * 0.8F;
         TextureRegistry.blockAtlas.bind();
-        float brightness = tnt.getBrightness(f1);
+        float brightness = tnt.getBrightness(partialTick);
         if (Global.accessor.isFullbrightEnabled()) brightness = 1.0f;
-        BlockModel<Block> model = BlockModelDispatcher.getInstance().getDispatch(Blocks.TNT);
+        BlockModel.setRenderBlocks(blockRenderer);
+        BlockModel<?> model = BlockModelDispatcher.getInstance().getDispatch(Blocks.TNT);
         model.renderBlockOnInventory(tessellator, 0, brightness, null);
         if((tnt.fuse / 5) % 2 == 0)
         {
@@ -63,13 +63,4 @@ public class EntityRendererTNT extends EntityRenderer<EntityPrimedTNT>
         }
         GL11.glPopMatrix();
     }
-
-    @Override
-    public void render(Tessellator tessellator, EntityPrimedTNT entity, double x, double y, double z,
-                       float yaw, float partialTick)
-    {
-        renderTNT(entity, x, y, z, yaw, partialTick);
-    }
-
-    private final RenderBlocks blockRenderer;
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
index 62f74377c..097660555 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
@@ -23,7 +23,6 @@ import net.minecraft.core.block.entity.TileEntity;
 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;
 import net.minecraft.core.player.gamemode.Gamemode;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.BlocksContainer;
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java
index 676d11172..cedcbb1d5 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java
@@ -4,7 +4,6 @@ import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.render.model.ModelWolf;
 import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.animal.MobWolf;
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java
index b9c141f32..1c28468c1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java
@@ -30,9 +30,9 @@ import java.util.Random;
 import static org.lwjgl.opengl.GL11.*;
 
 public class ItemModelBlock extends ItemModelStandard {
-    private Block block;
-    private BlockModel<Block> blockModel;
-    public ItemModelBlock(ItemBlock itemBlock){
+    private Block<?> block;
+    private BlockModel<?> blockModel;
+    public ItemModelBlock(ItemBlock<?> itemBlock){
         super(itemBlock, null);
         this.block = itemBlock.getBlock();
         this.blockModel = BlockModelDispatcher.getInstance().getDispatch(block);
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java
index 815954ff4..fdc7a9ff0 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.item.model;
 
 import net.minecraft.client.util.dispatch.Dispatcher;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.Items;
@@ -222,20 +221,20 @@ public class ItemModelDispatcher extends Dispatcher<Item, ItemModel> {
         addDispatch(new ItemModelStandard(Items.RECORD_WAIT, "minecraft"));
         addDispatch(new ItemModelStandard(Items.RECORD_DOG, "minecraft"));
 
-        addDispatch(new ItemModelBlock((ItemBlock) Blocks.TORCH_COAL.asItem()).setFullBright());
-        addDispatch(new ItemModelBlock((ItemBlock) Blocks.TORCH_REDSTONE_ACTIVE.asItem()).setFullBright());
-        addDispatch(new ItemModelBlock((ItemBlock) Blocks.GLOWSTONE.asItem()).setFullBright());
-        addDispatch(new ItemModelBlock((ItemBlock) Blocks.PUMPKIN_CARVED_ACTIVE.asItem()).setFullBright());
-        addDispatch(new ItemModelBlock((ItemBlock) Blocks.LAMP_ACTIVE.asItem()).setFullBright());
-        addDispatch(new ItemModelBlock((ItemBlock) Blocks.PORTAL_PARADISE.asItem()).setFullBright());
-        addDispatch(new ItemModelBlock((ItemBlock) Blocks.PORTAL_NETHER.asItem()).setFullBright());
+        addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.TORCH_COAL.asItem()).setFullBright());
+        addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.TORCH_REDSTONE_ACTIVE.asItem()).setFullBright());
+        addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.GLOWSTONE.asItem()).setFullBright());
+        addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.PUMPKIN_CARVED_ACTIVE.asItem()).setFullBright());
+        addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.LAMP_ACTIVE.asItem()).setFullBright());
+        addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.PORTAL_PARADISE.asItem()).setFullBright());
+        addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.PORTAL_NETHER.asItem()).setFullBright());
 
         for (int i = 0; i < Blocks.blocksList.length; i++) {
             if (Blocks.blocksList[i] == null) continue;
             Item item = Blocks.blocksList[i].asItem();
             if (dispatches.containsKey(item)) continue;
             if (!(item instanceof ItemBlock)) continue;
-            addDispatch(new ItemModelBlock((ItemBlock) item));
+            addDispatch(new ItemModelBlock((ItemBlock<?>) item));
         }
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/shader/Shaders.java b/game/client/src/main/java/net/minecraft/client/render/shader/Shaders.java
index fd05ffae4..f70129a94 100644
--- a/game/client/src/main/java/net/minecraft/client/render/shader/Shaders.java
+++ b/game/client/src/main/java/net/minecraft/client/render/shader/Shaders.java
@@ -77,7 +77,7 @@ public abstract class Shaders {
 		shader.uniformInt("cbCorrectionMode", minecraft.gameSettings.colorblindnessFix.value.ordinal());
 
 		ItemStack helmet = minecraft.thePlayer == null ? null : minecraft.thePlayer.inventory.armorItemInSlot(IArmorItem.PIECE_HEAD);
-		shader.uniformInt("shaderEffect", helmet != null && helmet.itemID == Blocks.PUMPKIN_REDSTONE.id ? 1 : 0);
+		shader.uniformInt("shaderEffect", helmet != null && helmet.itemID == Blocks.PUMPKIN_REDSTONE.id() ? 1 : 0);
 
 		int isEyeInLiquid = 0;
 		float celestialAngle = 0.0f;
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
index ef4d0cb97..e7d7fdca4 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
@@ -8,12 +8,10 @@ import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.render.RenderBlocks;
 import net.minecraft.client.render.block.model.BlockModel;
-import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.camera.ICamera;
 import net.minecraft.client.render.culling.CameraFrustum;
 import net.minecraft.client.render.entity.EntityRendererItem;
 import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererLegacy.java b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererLegacy.java
index 2bb384149..b203a5574 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererLegacy.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererLegacy.java
@@ -14,7 +14,6 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.RenderBlocks;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.chunk.ChunkCache;
diff --git a/game/client/src/main/java/org/useless/seedviewer/bta/BTAComplexChunk.java b/game/client/src/main/java/org/useless/seedviewer/bta/BTAComplexChunk.java
index 2793bc73a..1ae877411 100644
--- a/game/client/src/main/java/org/useless/seedviewer/bta/BTAComplexChunk.java
+++ b/game/client/src/main/java/org/useless/seedviewer/bta/BTAComplexChunk.java
@@ -22,7 +22,7 @@ public class BTAComplexChunk implements Chunk {
 
     @Override
     public int getBlockColor(ChunkPos3D pos) {
-        Block b = Blocks.getBlock(chunk.getBlockID(pos.x, pos.y, pos.z));
+        Block<?> b = Blocks.getBlock(chunk.getBlockID(pos.x, pos.y, pos.z));
         if (b == null) return 0;
         int meta = chunk.getBlockMetadata(pos.x, pos.y, pos.z);
         return MaterialColor.getColorFromIndex(MaterialColor.getColorIndexFromBlock(b, meta)) | 0xFF_00_00_00;
@@ -40,9 +40,9 @@ public class BTAComplexChunk implements Chunk {
         while (true) {
             int y = start - depth;
             if (y < 0) break;
-            Block b = Blocks.getBlock(chunk.getBlockID(pos.x, y, pos.z));
+            Block<?> b = Blocks.getBlock(chunk.getBlockID(pos.x, y, pos.z));
             if (b == null) break;
-            if (b.blockMaterial != Material.water) break;
+            if (b.getMaterial() != Material.water) break;
             depth++;
         }
         return depth;
diff --git a/game/core/src/main/java/net/minecraft/core/block/Block.java b/game/core/src/main/java/net/minecraft/core/block/Block.java
index 5976a3e3a..04ba1e808 100644
--- a/game/core/src/main/java/net/minecraft/core/block/Block.java
+++ b/game/core/src/main/java/net/minecraft/core/block/Block.java
@@ -1,41 +1,26 @@
 package net.minecraft.core.block;
 
-
-import java.util.ArrayList;
-import java.util.Random;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-import net.minecraft.core.block.entity.TileEntityActivator;
-import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.block.support.FullSupport;
-import net.minecraft.core.block.support.ISupport;
-import net.minecraft.core.entity.EntityFallingBlock;
-import net.minecraft.core.util.helper.Direction;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
 import net.minecraft.core.achievement.stat.Stat;
-import net.minecraft.core.achievement.stat.StatList;
+import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.material.MaterialColor;
-import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.block.support.ISupport;
 import net.minecraft.core.data.tag.ITaggable;
 import net.minecraft.core.data.tag.Tag;
 import net.minecraft.core.entity.Entity;
-import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.IItemConvertible;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.item.tool.ItemToolShears;
 import net.minecraft.core.item.block.ItemBlock;
 import net.minecraft.core.sound.BlockSound;
 import net.minecraft.core.sound.BlockSounds;
 import net.minecraft.core.util.HardIllegalArgumentException;
 import net.minecraft.core.util.collection.NamespaceID;
+import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.util.phys.BoundingVolume;
@@ -43,141 +28,148 @@ import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.util.phys.Vec3;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
-public class Block
-    implements ITaggable<Block>, IItemConvertible
-{
-    public final int id;
-    public final NamespaceID namespaceID;
-    protected float blockHardness;
-    protected float blastResistance;
-    protected boolean blockConstructorCalled;
-    protected boolean enableStats;
-    protected boolean isLitInteriorSurface;
-    protected final AABB bounds = AABB.getPermanentBB(0, 0, 0, 1, 1, 1);
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Random;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public final class Block<T extends BlockLogic>
+    implements ITaggable<Block<?>>, IItemConvertible, BlockInterface {
+    public static boolean disableNormalEntityLogic = false;
+
+    private final int id;
+    private final @NotNull String key;
+    private final @NotNull NamespaceID namespaceID;
+    private final @NotNull BlockLogicSupplier<T> logicSupplier;
+    private T logic;
+
+    public float blockHardness;
+    public float blastResistance;
+    public boolean enableStats;
+    public boolean isLitInteriorSurface;
     public float blockParticleGravity;
-    public final Material blockMaterial;
     public float friction;
-    protected String key;
+    public int emission;
+    public int lightBlock;
     public boolean immovable = false;
+    public boolean isEntityTile = false;
+    public boolean disabledNeighborMetaNotify = false;
+    public boolean shouldTick = false;
+    public @Nullable Supplier<TileEntity> entitySupplier;
     public MaterialColor overrideColor;
     private BlockSound blockSound = BlockSounds.DEFAULT;
-
+    @NotNull public Supplier<Item> blockItemSupplier = () -> new ItemBlock<>(this);
     @Nullable
     Supplier<@NotNull IItemConvertible> statParent = null;
 
+    Block(int id, @NotNull String translationKey, @NotNull String namespaceId, @NotNull BlockLogicSupplier<T> logicSupplier) {
+        this.namespaceID = setupNamespaceId(namespaceId);
+        this.key = setupTranslationKey(translationKey);
+        this.id = setupNumericId(id);
+
+        this.logicSupplier = Objects.requireNonNull(logicSupplier);
 
-	public Block(String translationKey, String namespaceId, int id, Material material)
-    {
-        blockConstructorCalled = true;
         enableStats = true;
         blockParticleGravity = 1.0F;
         friction = 0.6F;
         immovable = false;
-        this.id = id;
-        try {
-            this.namespaceID = new NamespaceID(namespaceId);
-        } catch (HardIllegalArgumentException e){
-            throw new IllegalArgumentException(e);
+    }
+
+    private int setupNumericId(int id) {
+        if (id < 0) {
+            throw new IllegalArgumentException("Numeric id of block '" + namespaceID + "' must not be negative!");
+        }
+        if (id >= Blocks.blocksList.length) {
+            throw new IllegalArgumentException("Numeric id of block '" + namespaceID + "' must not be greater than '" + (Blocks.blocksList.length - 1) + "'!");
         }
+        return id;
+    }
 
-        if(Blocks.blocksList[id] != null) {
-            throw new IllegalArgumentException("Block slot '" + id + "' is already occupied by '" + Blocks.blocksList[id] + "' when adding " + this);
+    private @NotNull String setupTranslationKey(String translationKey) {
+        if (translationKey == null) {
+            throw new NullPointerException("Translation key of block '" + namespaceID + "' must not be null!");
         }
-        if (Blocks.blockMap.containsKey(this.namespaceID)){
-            throw new IllegalArgumentException("Block id '" + namespaceID + "' is already used by '" + Blocks.blockMap.get(this.namespaceID) + "' when adding " + this);
+        if (!translationKey.startsWith("tile.")) {
+            translationKey = "tile." + translationKey;
         }
+        return translationKey;
+    }
 
-        blockMaterial = material;
-        Blocks.blocksList[id] = this;
-        Blocks.blockMap.put(this.namespaceID, this);
-        setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
-        Blocks.solid[id] = isSolidRender();
-        Blocks.lightBlock[id] = (isSolidRender() || blocksLight()) ? 255 : 0;
-        Blocks.translucent[id] = !material.blocksLight();
-        Blocks.isEntityTile[id] = false;
-        this.key = "tile." + translationKey;
-        Blocks.keyToIdMap.put(this.key, this.id);
+    private @NotNull NamespaceID setupNamespaceId(String namespaceId) {
+        if (namespaceId == null) {
+            throw new NullPointerException("NamespaceId must not be null!");
+        }
+        if (!namespaceId.contains(":")) {
+            namespaceId = "minecraft:" + namespaceId;
+        }
+//        String[] parts = namespaceId.split(":");
+//        if (parts.length != 2) throw new IllegalArgumentException("NamespaceId '" + namespaceId + "' contains more then 1 ':' character!");
+//        if (!parts[1].startsWith("block/")) {
+//            namespaceId = parts[0] + ":" + "block/" + parts[1];
+//        }
+        try {
+            return new NamespaceID(namespaceId);
+        } catch (HardIllegalArgumentException e) {
+            throw new RuntimeException(e);
+        }
+    }
 
-        if (Blocks.highestBlockId < id) Blocks.highestBlockId = id;
+    public T getLogic() {
+        return logic;
     }
 
-	public Block withDisabledNeighborNotifyOnMetadataChange()
-    {
-        Blocks.neighborNotifyOnMetadataChangeDisabled[id] = true;
+    public Block<T> withEntity(@Nullable Supplier<TileEntity> entitySupplier) {
+        this.isEntityTile = true;
+        this.entitySupplier = entitySupplier;
         return this;
     }
 
-    protected void initializeBlock()
+    public Block<T> withDisabledNeighborNotifyOnMetadataChange()
     {
+        disabledNeighborMetaNotify = true;
+        return this;
     }
 
-    public Block withLightBlock(int blockAmount)
+    public Block<T> withLightBlock(int blockAmount)
     {
-        Blocks.lightBlock[id] = blockAmount;
+        lightBlock = blockAmount;
         return this;
     }
-    public Block withLightEmission(float lightEmission)
+    public Block<T> withLightEmission(float lightEmission)
     {
-        Blocks.lightEmission[id] = (int)(15F * lightEmission);
+        this.emission = (int)(15F * lightEmission);
         return this;
     }
 
-    public Block withLightEmission(int lightEmission)
+    public Block<T> withLightEmission(int lightEmission)
     {
-        Blocks.lightEmission[id] = lightEmission & 0x0F;
+        this.emission = lightEmission & 0x0F;
         return this;
     }
 
-    public Block withImmovableFlagSet()
+    public Block<T> withImmovableFlagSet()
     {
         this.immovable = true;
         return this;
     }
 
-    public Block withBlastResistance(float blastResistance)
+    public Block<T> withBlastResistance(float blastResistance)
     {
         this.blastResistance = blastResistance * 3F;
         return this;
     }
 
-    public Block withSound(BlockSound sound)
+    public Block<T> withSound(BlockSound sound)
     {
         this.blockSound = sound;
         return this;
     }
 
-    public BlockSound getSound()
-    {
-        return blockSound;
-    }
-
-    public boolean isCubeShaped()
-    {
-        return true;
-    }
-
-    public boolean canPlaceOnSurface()
-    {
-        return this.isCubeShaped();
-    }
-
-    public boolean canPlaceOnSurfaceOnCondition(World world, int x, int y, int z)
-    {
-        return this.canPlaceOnSurface();
-    }
-
-    public boolean renderAsNormalBlockOnCondition(WorldSource world, int x, int y, int z)
-    {
-        return isCubeShaped();
-    }
-
-    public boolean canPlaceOnSurfaceOfBlock(World world, int x, int y, int z)
-    {
-        return canPlaceOnSurface();
-    }
-
-    public Block withHardness(float blockHardness)
+    public Block<T> withHardness(float blockHardness)
     {
         this.blockHardness = blockHardness;
         if(blastResistance < blockHardness * 5F)
@@ -187,530 +179,447 @@ public class Block
         return this;
     }
 
-    public Block withLitInteriorSurface(boolean isLit)
+    public Block<T> withLitInteriorSurface(boolean isLit)
     {
         isLitInteriorSurface = isLit;
         return this;
     }
-    public Block withSetUnbreakable()
+    public Block<T> withSetUnbreakable()
     {
         withHardness(-1F);
         return this;
     }
-    public Block setBlockItem(@NotNull Supplier<Item> itemSupplier){
+    public Block<T> setBlockItem(@NotNull Supplier<Item> itemSupplier){
         this.blockItemSupplier = itemSupplier;
         return this;
     }
 
-    public Block setBlockItem(@NotNull Function<Block, Item> itemSupplier){
+    public Block<T> setBlockItem(@NotNull Function<Block<T>, Item> itemSupplier){
         this.blockItemSupplier = () -> itemSupplier.apply(this);
         return this;
     }
-    public Block withOverrideColor(MaterialColor color){
+    public Block<T> withOverrideColor(MaterialColor color){
         this.overrideColor = color;
         return this;
     }
 
-    public Block setStatParent(@NotNull Supplier<@NotNull IItemConvertible> icon){
+    public Block<T> setStatParent(@NotNull Supplier<@NotNull IItemConvertible> icon){
         this.statParent = icon;
         return this;
     }
 
-    public float getHardness()
+    public Block<T> withDisabledStats()
     {
-        return blockHardness;
+        enableStats = false;
+        return this;
     }
 
-    /**
-     * Make sure if this gets overridden in a block that {@link Block#getBreakResult(World, EnumDropCause, int, TileEntity)} also has a valid method since {@link EntityFallingBlock EntityFallingBlock} uses it!
-     */
-    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, TileEntity tileEntity)
+    public Block<T> setTicking(boolean tick)
     {
-        return getBreakResult(world, dropCause, meta, tileEntity);
+        this.shouldTick = tick;
+        return this;
     }
 
-    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity)
+    public BlockSound getSound()
     {
-        if (dropCause != EnumDropCause.IMPROPER_TOOL)
-        {
-            return new ItemStack[] { new ItemStack(this) };
-        }
-        else return null;
+        return blockSound;
     }
 
-    public Block setTicking(boolean tick)
-    {
-        Blocks.shouldTick[id] = tick;
-        return this;
+    public Material getMaterial() {
+        return logic.getMaterial();
     }
 
-    protected void setBlockBounds(double minX, double minY, double minZ, double maxX, double maxY, double maxZ)
+    public float getHardness()
     {
-        bounds.set(minX, minY, minZ, maxX, maxY, maxZ);
+        return blockHardness;
     }
 
-    public AABB getBounds() {
-        return bounds.copy();
+    public boolean getEnableStats()
+    {
+        return enableStats && getHardness() >= 0F;
     }
 
-    public AABB getBoundsRaw() {
-        return bounds;
+    @Nullable
+    public Stat getStat(String statID) {
+        return asItem().getStat(statID);
     }
 
-	public float getBlockBrightness(WorldSource blockAccess, int x, int y, int z) {
-		return blockAccess.getBrightness(x, y, z, Blocks.lightEmission[id]);
-	}
-
-	public int getLightmapCoord(WorldSource blockAccess, int x, int y, int z) {
-		return blockAccess.getLightmapCoord(x, y, z, Blocks.lightEmission[id]);
-	}
-
-	/**
-	 * Used when fullbright or lightmap is active
-	 */
-	public float getAmbientOcclusionStrength(WorldSource blockAccess, int x, int y, int z) {
-		return isSolidRender() ? 1.0f : 0.0f;
-	}
-
-    public boolean getIsBlockSolid(WorldSource blockAccess, int x, int y, int z, Side side)
-    {
-        return blockAccess.getBlockMaterial(x, y, z).isSolid();
+    public MaterialColor getMaterialColor(){
+        if (overrideColor != null) return overrideColor;
+        return getMaterialColor();
     }
 
-    public AABB getSelectedBoundingBoxFromPool(WorldSource world, int x, int y, int z)
-    {
-        return getBlockBoundsFromState(world, x, y, z).move(x, y, z);
+    @Override
+    public int id() {
+        return id;
     }
 
-    public BoundingVolume getBoundingVolume(World world, int x, int y, int z)
-    {
-        return null;
+    public @NotNull String getKey() {
+        return key;
     }
 
-    public void getCollidingBoundingBoxes(World world, int x, int y, int z, AABB aabb, ArrayList<AABB> aabbList)
-    {
-        addIntersectingBoundingBox(aabb, getCollisionBoundingBoxFromPool(world, x, y, z), aabbList);
+    public @NotNull NamespaceID namespaceId() {
+        return namespaceID;
     }
 
-    protected void addIntersectingBoundingBox(AABB sourceAABB, AABB aabbToAdd, ArrayList<AABB> aabbList) {
-        if(aabbToAdd != null && sourceAABB.intersects(aabbToAdd))
-        {
-            aabbList.add(aabbToAdd);
-        }
+    public void init() {
+        this.logic = logicSupplier.get(this);
     }
 
-    public boolean collidesWithEntity(Entity entity, World world, int x, int y, int z)
-    {
-        return true;
-    }
 
-    public AABB getCollisionBoundingBoxFromPool(WorldSource world, int x, int y, int z)
-    {
-        return getBlockBoundsFromState(world, x, y, z).move(x, y, z);
-    }
-    public MaterialColor getMaterialColor(){
-        if (overrideColor != null) return overrideColor;
-        return blockMaterial.color;
+    @Override
+    public boolean isIn(Tag<Block<?>> tag) {
+        return tag.appliesTo(this);
     }
 
-    public boolean isSolidRender()
-    {
-        return true;
+    @Override
+    public Item asItem() {
+        return Item.itemsList[id];
     }
 
-    public boolean blocksLight()
-    {
-        return false;
+    @Override
+    public ItemStack getDefaultStack() {
+        return new ItemStack(this);
     }
 
-    public boolean canCollideCheck(int meta, boolean shouldCollideWithFluids)
+    public static boolean isBuried (World world, int x, int y, int z)
     {
-        return isCollidable();
+        boolean buried = true;
+        if(Blocks.lightBlock[world.getBlockId(x + 1, y, z)] <= 2)
+            buried = false;
+        if(Blocks.lightBlock[world.getBlockId(x - 1, y, z)] <= 2)
+            buried = false;
+        if(Blocks.lightBlock[world.getBlockId(x, y, z + 1)] <= 2)
+            buried = false;
+        if(Blocks.lightBlock[world.getBlockId(x, y, z - 1)] <= 2)
+            buried = false;
+        if(Blocks.lightBlock[world.getBlockId(x, y + 1, z)] <= 2)
+            buried = false;
+        if(Blocks.lightBlock[world.getBlockId(x, y - 1, z)] <= 2)
+            buried = false;
+        return buried;
     }
 
-    public boolean isCollidable()
+    public static boolean getIsLitInteriorSurface (World world, int x, int y, int z)
     {
-        return true;
+        int l = world.getBlockId(x, y, z);
+        return l != 0 && Blocks.blocksList[l] != null && Blocks.blocksList[l].isLitInteriorSurface;
     }
 
-    public void updateTick(World world, int x, int y, int z, Random rand)
+    @SafeVarargs
+    public final Block<T> withTags(Tag<Block<?>>... tags)
     {
-    }
+        for (Tag<Block<?>> tag : tags)
+        {
+            tag.tag(this);
+        }
 
-    public void animationTick(World world, int x, int y, int z, Random rand)
-    {
+        return this;
     }
 
-    public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
+    public boolean hasTag(Tag<Block<?>> tag)
     {
+        return tag.appliesTo(this);
     }
 
-    public int tickDelay()
-    {
-        return 10;
+    @Override
+    public boolean isCubeShaped() {
+        return logic.isCubeShaped();
     }
 
-    public void onBlockPlacedByWorld(World world, int x, int y, int z)
-    {
+    @Override
+    public boolean canPlaceOnSurface() {
+        return logic.canPlaceOnSurface();
     }
 
-
-    /**
-     * Always called when a block is removed by setBlock
-     */
-    public void onBlockRemoved(World world, int x, int y, int z, int data)
-    {
+    @Override
+    public boolean canPlaceOnSurfaceOnCondition(World world, int x, int y, int z) {
+        return logic.canPlaceOnSurfaceOnCondition(world, x, y, z);
     }
 
-    /**
-     * Called when a block has been broken by a player, after {@link Block#onBlockRemoved(World, int, int, int, int)}
-     */
-    public void onBlockDestroyedByPlayer(World world, int x, int y, int z, Side side, int meta, Player player, Item item) {
+    @Override
+    public boolean renderAsNormalBlockOnCondition(WorldSource world, int x, int y, int z) {
+        return logic.renderAsNormalBlockOnCondition(world, x, y, z);
+    }
 
+    @Override
+    public boolean canPlaceOnSurfaceOfBlock(World world, int x, int y, int z) {
+        return logic.canPlaceOnSurfaceOfBlock(world, x, y, z);
     }
 
-    public float blockStrength(World world, int x, int y, int z, Side side, Player player)
-    {
-        if(blockHardness < 0.0F)
-        {
-            return 0.0F;
-        }
+    @Override
+    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, TileEntity tileEntity) {
+        return logic.getBreakResult(world, dropCause, x, y, z, meta, tileEntity);
+    }
 
-        if (!player.canHarvestBlock(this))
-        {
-            return 1.0F / blockHardness / 100F;
-        }
-        else
-        {
-            return player.getCurrentPlayerStrVsBlock(this) / blockHardness / 30F;
-        }
+    @Override
+    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity) {
+        return logic.getBreakResult(world, dropCause, meta, tileEntity);
     }
 
-    public boolean getImmovable()
-    {
-        return this.immovable;
+    @Override
+    public AABB getBounds() {
+        return logic.getBounds();
     }
 
-    public float getBlastResistance(Entity entity)
-    {
-        return blastResistance / 5F;
+    @Override
+    public AABB getBoundsRaw() {
+        return logic.getBoundsRaw();
     }
 
-    public HitResult collisionRayTrace(World world, int x, int y, int z, Vec3 start, Vec3 end, boolean useSelectorBoxes)
-    {
-        AABB bounds = useSelectorBoxes ? getSelectedBoundingBoxFromPool(world, x, y, z).move(-x, -y, -z) : getBlockBoundsFromState(world, x, y, z);
-        start = start.add(-x, -y, -z);
-        end = end.add(-x, -y, -z);
-		Vec3 minVX = start.clipX(end, bounds.minX);
-		Vec3 maxVX = start.clipX(end, bounds.maxX);
-		Vec3 minVY = start.clipY(end, bounds.minY);
-		Vec3 maxVY = start.clipY(end, bounds.maxY);
-		Vec3 minVZ = start.clipZ(end, bounds.minZ);
-		Vec3 maxVZ = start.clipZ(end, bounds.maxZ);
-
-		if(!isVecInsideYZBounds(bounds,minVX)) minVX = null;
-		if(!isVecInsideYZBounds(bounds,maxVX)) maxVX = null;
-		if(!isVecInsideXZBounds(bounds,minVY)) minVY = null;
-		if(!isVecInsideXZBounds(bounds,maxVY)) maxVY = null;
-		if(!isVecInsideXYBounds(bounds,minVZ)) minVZ = null;
-		if(!isVecInsideXYBounds(bounds,maxVZ)) maxVZ = null;
-
-		Vec3 vec38 = null;
-		if(minVX != null && (vec38 == null || start.distanceToSquared(minVX) < start.distanceToSquared(vec38))) vec38 = minVX;
-		if(maxVX != null && (vec38 == null || start.distanceToSquared(maxVX) < start.distanceToSquared(vec38))) vec38 = maxVX;
-		if(minVY != null && (vec38 == null || start.distanceToSquared(minVY) < start.distanceToSquared(vec38))) vec38 = minVY;
-		if(maxVY != null && (vec38 == null || start.distanceToSquared(maxVY) < start.distanceToSquared(vec38))) vec38 = maxVY;
-		if(minVZ != null && (vec38 == null || start.distanceToSquared(minVZ) < start.distanceToSquared(vec38))) vec38 = minVZ;
-		if(maxVZ != null && (vec38 == null || start.distanceToSquared(maxVZ) < start.distanceToSquared(vec38))) vec38 = maxVZ;
-
-		if(vec38 == null) return null;
-		Side side = Side.NONE;
-		if(vec38 == minVX) side = Side.WEST;
-		if(vec38 == maxVX) side = Side.EAST;
-		if(vec38 == minVY) side = Side.BOTTOM;
-		if(vec38 == maxVY) side = Side.TOP;
-		if(vec38 == minVZ) side = Side.NORTH;
-		if(vec38 == maxVZ) side = Side.SOUTH;
-
-        return new HitResult(x, y, z, side, vec38.add(x, y, z));
-    }
-
-    private boolean isVecInsideYZBounds(AABB bounds, @Nullable Vec3 vec3)
-    {
-        if(vec3 == null) {
-            return false;
-        }
-        return vec3.y >= bounds.minY && vec3.y <= bounds.maxY && vec3.z >= bounds.minZ && vec3.z <= bounds.maxZ;
+    @Override
+    public float getBlockBrightness(WorldSource blockAccess, int x, int y, int z) {
+        return logic.getBlockBrightness(blockAccess, x, y, z);
     }
 
-    private boolean isVecInsideXZBounds(AABB bounds, @Nullable Vec3 vec3)
-    {
-        if(vec3 == null) {
-            return false;
-        }
-        return vec3.x >= bounds.minX && vec3.x <= bounds.maxX && vec3.z >= bounds.minZ && vec3.z <= bounds.maxZ;
+    @Override
+    public int getLightmapCoord(WorldSource blockAccess, int x, int y, int z) {
+        return logic.getLightmapCoord(blockAccess, x, y, z);
     }
 
-    private boolean isVecInsideXYBounds(AABB bounds, @Nullable Vec3 vec3)
-    {
-        if(vec3 == null) {
-            return false;
-        }
-        return vec3.x >= bounds.minX && vec3.x <= bounds.maxX && vec3.y >= bounds.minY && vec3.y <= bounds.maxY;
+    @Override
+    public float getAmbientOcclusionStrength(WorldSource blockAccess, int x, int y, int z) {
+        return logic.getAmbientOcclusionStrength(blockAccess, x, y, z);
     }
 
-    public void onBlockDestroyedByExplosion(World world, int x, int y, int z)
-    {
+    @Override
+    public boolean getIsBlockSolid(WorldSource blockAccess, int x, int y, int z, Side side) {
+        return logic.getIsBlockSolid(blockAccess, x, y, z, side);
     }
 
-    public boolean canPlaceBlockOnSide(World world, int x, int y, int z, Side side)
-    {
-        return canPlaceBlockAt(world, x, y, z);
+    @Override
+    public AABB getSelectedBoundingBoxFromPool(WorldSource world, int x, int y, int z) {
+        return logic.getSelectedBoundingBoxFromPool(world, x, y, z);
     }
 
-    public boolean canPlaceBlockAt(World world, int x, int y, int z)
-    {
-    	return world.canPlaceInsideBlock(x, y, z);
+    @Override
+    public BoundingVolume getBoundingVolume(World world, int x, int y, int z) {
+        return logic.getBoundingVolume(world, x, y, z);
     }
 
-    public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit)
-    {
-        return false;
+    @Override
+    public void getCollidingBoundingBoxes(World world, int x, int y, int z, AABB aabb, ArrayList<AABB> aabbList) {
+        logic.getCollidingBoundingBoxes(world, x, y, z, aabb, aabbList);
     }
 
-    public void onActivatorInteract(World world, int x, int y, int z, TileEntityActivator activator, Direction direction) {
+    @Override
+    public boolean collidesWithEntity(Entity entity, World world, int x, int y, int z) {
+        return logic.collidesWithEntity(entity, world, x, y, z);
     }
 
-    public void onEntityWalking(World world, int x, int y, int z, Entity entity)
-    {
+    @Override
+    public AABB getCollisionBoundingBoxFromPool(WorldSource world, int x, int y, int z) {
+        return logic.getCollisionBoundingBoxFromPool(world, x, y, z);
     }
 
-    public void onBlockLeftClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit)
-    {
+    @Override
+    public boolean isSolidRender() {
+        return logic.isSolidRender();
     }
 
-    public void handleEntityInside(World world, int x, int y, int z, Entity entity, Vec3 entityVelocity)
-    {
+    @Override
+    public boolean blocksLight() {
+        return logic.blocksLight();
     }
-    public AABB getBlockBoundsFromState(WorldSource world, int x, int y, int z)
-    {
-        return getBounds();
+
+    @Override
+    public boolean canCollideCheck(int meta, boolean shouldCollideWithFluids) {
+        return logic.canCollideCheck(meta, shouldCollideWithFluids);
     }
 
-    /**
-     * Gets the redstone signal output by the block itself, i.e. the power it will provide to any immediately adjacent redstone components.
-     */
-    public boolean getSignal(WorldSource worldSource, int x, int y, int z, Side side)
-    {
-        return false;
+    @Override
+    public boolean isCollidable() {
+        return logic.isCollidable();
     }
 
-    public boolean isSignalSource()
-    {
-        return false;
+    @Override
+    public void updateTick(World world, int x, int y, int z, Random rand) {
+        logic.updateTick(world, x, y, z, rand);
     }
 
-    public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity)
-    {
+    @Override
+    public void animationTick(World world, int x, int y, int z, Random rand) {
+        logic.animationTick(world, x, y, z, rand);
     }
 
-    /**
-     * Gets the redstone signal pushed into adjacent solid blocks. Any block experiencing *direct* signal will power itself and all adjacent blocks.
-     */
-    public boolean getDirectSignal(World world, int x, int y, int z, Side side)
-    {
-        return false;
+    @Override
+    public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
+        logic.onNeighborBlockChange(world, x, y, z, blockId);
     }
 
-    public void harvestBlock(World world, Player player, int x, int y, int z, int meta, TileEntity tileEntity)
-    {
-    	player.addStat(getStat(StatList.STAT_MINED), 1);
+    @Override
+    public int tickDelay() {
+        return logic.tickDelay();
+    }
 
-		ItemStack heldItemStack = player.inventory.getCurrentItem();
-		Item heldItem = heldItemStack != null ? Item.itemsList[heldItemStack.itemID] : null;
+    @Override
+    public void onBlockPlacedByWorld(World world, int x, int y, int z) {
+        if (isEntityTile && !disableNormalEntityLogic && entitySupplier != null) {
+            world.setBlockTileEntity(x, y, z, entitySupplier.get());
+        }
+        logic.onBlockPlacedByWorld(world, x, y, z);
+    }
 
-        if (heldItem != null)
-        {
-            if (heldItem.isSilkTouch() && player.canHarvestBlock(this))
-            {
-                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, tileEntity, player);
-                return;
-            }
-            else if (heldItem instanceof ItemToolShears && (this.hasTag(BlockTags.SHEARS_DO_SILK_TOUCH) || this.hasTag(BlockTags.MINEABLE_BY_SHEARS)))
-            {
-                ItemToolShears heldShears = (ItemToolShears) heldItem;
-                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, tileEntity, player);
-                heldShears.onBlockSheared(player, heldItemStack);
-                return;
+    @Override
+    public void onBlockRemoved(World world, int x, int y, int z, int data) {
+        logic.onBlockRemoved(world, x, y, z, data);
+        if (isEntityTile && !disableNormalEntityLogic) {
+            if (!world.isClientSide) {
+                TileEntity tileEntity = world.getBlockEntity(x, y, z);
+                if(tileEntity != null) {
+                    tileEntity.dropContents(world, x, y, z);
+                }
             }
+            world.removeBlockTileEntity(x, y, z);
         }
+    }
 
-        if (player.canHarvestBlock(this))
-        {
-            dropBlockWithCause(world, EnumDropCause.PROPER_TOOL, x, y, z, meta, tileEntity, player);
-        }
-        else
-        {
-            dropBlockWithCause(world, EnumDropCause.IMPROPER_TOOL, x, y, z, meta, tileEntity, player);
-        }
-	}
+    @Override
+    public void onBlockDestroyedByPlayer(World world, int x, int y, int z, Side side, int meta, Player player, Item item) {
+        logic.onBlockDestroyedByPlayer(world, x, y, z, side, meta, player, item);
+    }
 
-    @Nullable
-    public Stat getStat(String statID) {
-        return asItem().getStat(statID);
+    @Override
+    public float blockStrength(World world, int x, int y, int z, Side side, Player player) {
+        return logic.blockStrength(world, x, y, z, side, player);
     }
 
-	public void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, TileEntity tileEntity, Player player) {
-		if(world.isClientSide)
-			return;
+    @Override
+    public boolean getImmovable() {
+        return logic.getImmovable();
+    }
 
-		ItemStack[] drops = getBreakResult(world, cause, x, y, z, meta, tileEntity);
-        if (drops == null) {
-            return;
-        }
-        for (int j = 0, dropsLength = drops.length; j < dropsLength; j++) {
-            ItemStack drop = drops[j];
-            if (drop == null) {
-                continue;
-            }
-            if (hasTag(BlockTags.INSTANT_PICKUP) && player != null) {
-                player.inventory.insertItem(drop, true);
-                if (drop.stackSize <= 0) {
-                    continue;
-                }
-            }
-            if (EntityItem.enableItemClumping) {
-                world.dropItem(x, y, z, drop.copy());
-            } else {
-                for (int i = 0; i < drop.stackSize; i++) {
-                    ItemStack drop1 = drop.copy();
-                    drop1.stackSize = 1;
-                    world.dropItem(x, y, z, drop1);
-                }
-            }
-        }
+    @Override
+    public float getBlastResistance(Entity entity) {
+        return logic.getBlastResistance(entity);
     }
 
-    public ISupport getSupport(World world, int x, int y, int z, Side side) {
-        return FullSupport.INSTANCE;
+    @Override
+    public HitResult collisionRayTrace(World world, int x, int y, int z, Vec3 start, Vec3 end, boolean useSelectorBoxes) {
+        return logic.collisionRayTrace(world, x, y, z, start, end, useSelectorBoxes);
     }
 
-    public boolean canBlockStay(World world, int x, int y, int z)
-    {
-        return true;
+    @Override
+    public void onBlockDestroyedByExplosion(World world, int x, int y, int z) {
+        logic.onBlockDestroyedByExplosion(world, x, y, z);
     }
 
-    public void onBlockPlacedByMob(World world, int x, int y, int z, @NotNull Side side, Mob mob, double xPlaced, double yPlaced) {
-        onBlockPlacedOnSide(world, x, y, z, side, xPlaced, yPlaced);
+    @Override
+    public boolean canPlaceBlockOnSide(World world, int x, int y, int z, Side side) {
+        return logic.canPlaceBlockOnSide(world, x, y, z, side);
     }
 
-    public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
+    @Override
+    public boolean canPlaceBlockAt(World world, int x, int y, int z) {
+        return logic.canPlaceBlockAt(world, x, y, z);
+    }
 
+    @Override
+    public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit) {
+        return logic.onBlockRightClicked(world, x, y, z, player, side, xHit, yHit);
     }
 
-    public String getKey()
-    {
-        return key;
+    @Override
+    public void onActivatorInteract(World world, int x, int y, int z, TileEntityActivator activator, Direction direction) {
+        logic.onActivatorInteract(world, x, y, z, activator, direction);
     }
 
-    public String getLanguageKey(int meta)
-    {
-        return getKey();
+    @Override
+    public void onEntityWalking(World world, int x, int y, int z, Entity entity) {
+        logic.onEntityWalking(world, x, y, z, entity);
     }
 
-    public void triggerEvent(World world, int x, int y, int z, int index, int data)
-    {
+    @Override
+    public void onBlockLeftClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit) {
+        logic.onBlockLeftClicked(world, x, y, z, player, side, xHit, yHit);
+    }
 
+    @Override
+    public void handleEntityInside(World world, int x, int y, int z, Entity entity, Vec3 entityVelocity) {
+        logic.handleEntityInside(world, x, y, z, entity, entityVelocity);
     }
 
-    public boolean getEnableStats()
-    {
-        return enableStats && getHardness() >= 0F;
+    @Override
+    public AABB getBlockBoundsFromState(WorldSource world, int x, int y, int z) {
+        return logic.getBlockBoundsFromState(world, x, y, z);
     }
 
-    public Block withDisabledStats()
-    {
-        enableStats = false;
-        return this;
+    @Override
+    public boolean getSignal(WorldSource worldSource, int x, int y, int z, Side side) {
+        return logic.getSignal(worldSource, x, y, z, side);
     }
 
-    public int getPistonPushReaction(World world, int x, int y, int z)
-    {
-        return blockMaterial.getPushReaction();
+    @Override
+    public boolean isSignalSource() {
+        return logic.isSignalSource();
     }
-    
-    public int getPlacedBlockMetadata(@Nullable Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced)
-    {
-    	return 0;
+
+    @Override
+    public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) {
+        logic.onEntityCollidedWithBlock(world, x, y, z, entity);
     }
 
-    public static boolean isBuried (World world, int x, int y, int z)
-    {
-        boolean buried = true;
-        if(Blocks.lightBlock[world.getBlockId(x + 1, y, z)] <= 2)
-            buried = false;
-        if(Blocks.lightBlock[world.getBlockId(x - 1, y, z)] <= 2)
-            buried = false;
-        if(Blocks.lightBlock[world.getBlockId(x, y, z + 1)] <= 2)
-            buried = false;
-        if(Blocks.lightBlock[world.getBlockId(x, y, z - 1)] <= 2)
-            buried = false;
-        if(Blocks.lightBlock[world.getBlockId(x, y + 1, z)] <= 2)
-            buried = false;
-        if(Blocks.lightBlock[world.getBlockId(x, y - 1, z)] <= 2)
-            buried = false;
-        return buried;
+    @Override
+    public boolean getDirectSignal(World world, int x, int y, int z, Side side) {
+        return logic.getDirectSignal(world, x, y, z, side);
     }
 
-    public static boolean getIsLitInteriorSurface (World world, int x, int y, int z)
-    {
-        int l = world.getBlockId(x, y, z);
-        return l != 0 && Blocks.blocksList[l] != null && Blocks.blocksList[l].isLitInteriorSurface;
+    @Override
+    public void harvestBlock(World world, Player player, int x, int y, int z, int meta, TileEntity tileEntity) {
+        logic.harvestBlock(world, player, x, y, z, meta, tileEntity);
     }
 
-    @SafeVarargs
-    public final Block withTags(Tag<Block>... tags)
-    {
-        for (Tag<Block> tag : tags)
-        {
-            tag.tag(this);
-        }
+    @Override
+    public void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, TileEntity tileEntity, Player player) {
+        logic.dropBlockWithCause(world, cause, x, y, z, meta, tileEntity, player);
+    }
 
-        return this;
+    @Override
+    public ISupport getSupport(World world, int x, int y, int z, Side side) {
+        return logic.getSupport(world, x, y, z, side);
     }
 
-    public boolean hasTag(Tag<Block> tag)
-    {
-        return tag.appliesTo(this);
+    @Override
+    public boolean canBlockStay(World world, int x, int y, int z) {
+        return logic.canBlockStay(world, x, y, z);
     }
 
-    public static boolean hasTag(int id, Tag<Block> tag)
-    {
-        if (id < 0) return false;
-        Block block = Blocks.blocksList[id];
-        if (block == null) return false;
-        return block.hasTag(tag);
+    @Override
+    public void onBlockPlacedByMob(World world, int x, int y, int z, @NotNull Side side, Mob mob, double xPlaced, double yPlaced) {
+        logic.onBlockPlacedByMob(world, x, y, z, side, mob, xPlaced, yPlaced);
     }
 
-    public boolean isClimbable(World world, int x, int y, int z) {
-    	return false;
+    @Override
+    public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
+        logic.onBlockPlacedOnSide(world, x, y, z, side, xPlaced, yPlaced);
     }
 
-    @NotNull
-    public Supplier<Item> blockItemSupplier = () -> new ItemBlock(this);
+    @Override
+    public String getLanguageKey(int meta) {
+        return logic.getLanguageKey(meta);
+    }
 
     @Override
-	public boolean isIn(Tag<Block> tag) {
-        return tag.appliesTo(this);
+    public void triggerEvent(World world, int x, int y, int z, int index, int data) {
+        logic.triggerEvent(world, x, y, z, index, data);
     }
 
     @Override
-    public Item asItem() {
-        return Item.itemsList[id];
+    public int getPistonPushReaction(World world, int x, int y, int z) {
+        return logic.getPistonPushReaction(world, x, y, z);
     }
 
     @Override
-    public ItemStack getDefaultStack() {
-        return new ItemStack(this);
+    public int getPlacedBlockMetadata(@Nullable Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+        return logic.getPlacedBlockMetadata(player, stack, world, x, y, z, side, xPlaced, yPlaced);
+    }
+
+    @Override
+    public boolean isClimbable(World world, int x, int y, int z) {
+        return logic.isClimbable(world, x, y, z);
+    }
+
+    public static boolean hasLogicClass(@Nullable Block<?> block, Class<?> logicClass) {
+        return block != null && block.getLogic().getClass().isAssignableFrom(logicClass);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFenceSteel.java b/game/core/src/main/java/net/minecraft/core/block/BlockFenceSteel.java
deleted file mode 100644
index 7bcb11097..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFenceSteel.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-import net.minecraft.core.block.tag.BlockTags;
-import net.minecraft.core.world.WorldSource;
-
-public class BlockFenceSteel extends BlockFenceThin {
-    public BlockFenceSteel(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
-    }
-
-    @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) || (Blocks.blocksList[id] != null && (Blocks.blocksList[id].blockMaterial.isStone() || Blocks.blocksList[id].blockMaterial.isMetal()));
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockGrassScorched.java b/game/core/src/main/java/net/minecraft/core/block/BlockGrassScorched.java
deleted file mode 100644
index 9c7cf707a..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockGrassScorched.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.block.material.Material;
-import net.minecraft.core.enums.EnumDropCause;
-import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.world.World;
-
-public class BlockGrassScorched extends Block
-{
-    public BlockGrassScorched(String key, String namespaceId, int id, Material material)
-    {
-        super(key, namespaceId, id, material);
-    }
-
-    @Override
-    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity)
-    {
-        switch (dropCause)
-        {
-            case PICK_BLOCK:
-            case SILK_TOUCH:
-                return new ItemStack[] { new ItemStack(this) };
-            default:
-                return new ItemStack[] { new ItemStack(Blocks.DIRT_SCORCHED) };
-        }
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java
new file mode 100644
index 000000000..570450958
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java
@@ -0,0 +1,109 @@
+package net.minecraft.core.block;
+
+import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.entity.TileEntityActivator;
+import net.minecraft.core.block.support.ISupport;
+import net.minecraft.core.entity.Entity;
+import net.minecraft.core.entity.EntityFallingBlock;
+import net.minecraft.core.entity.Mob;
+import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.item.Item;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.collection.NamespaceID;
+import net.minecraft.core.util.helper.Direction;
+import net.minecraft.core.util.helper.Side;
+import net.minecraft.core.util.phys.AABB;
+import net.minecraft.core.util.phys.BoundingVolume;
+import net.minecraft.core.util.phys.HitResult;
+import net.minecraft.core.util.phys.Vec3;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.WorldSource;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+interface BlockInterface {
+
+    int id();
+    @NotNull String getKey();
+    @NotNull NamespaceID namespaceId();
+
+    boolean isCubeShaped();
+    boolean canPlaceOnSurface();
+    boolean canPlaceOnSurfaceOnCondition(World world, int x, int y, int z);
+    boolean renderAsNormalBlockOnCondition(WorldSource world, int x, int y, int z);
+    boolean canPlaceOnSurfaceOfBlock(World world, int x, int y, int z);
+    /**
+     * Make sure if this gets overridden in a block that {@link net.minecraft.core.block.Block#getBreakResult(World, EnumDropCause, int, TileEntity)} also has a valid method since {@link EntityFallingBlock EntityFallingBlock} uses it!
+     */
+    ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, TileEntity tileEntity);
+    ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity);
+    AABB getBounds();
+    AABB getBoundsRaw();
+    float getBlockBrightness(WorldSource blockAccess, int x, int y, int z);
+    int getLightmapCoord(WorldSource blockAccess, int x, int y, int z);
+    /**
+     * Used when fullbright or lightmap is active
+     */
+    float getAmbientOcclusionStrength(WorldSource blockAccess, int x, int y, int z);
+    boolean getIsBlockSolid(WorldSource blockAccess, int x, int y, int z, Side side);
+    AABB getSelectedBoundingBoxFromPool(WorldSource world, int x, int y, int z);
+    BoundingVolume getBoundingVolume(World world, int x, int y, int z);
+    void getCollidingBoundingBoxes(World world, int x, int y, int z, AABB aabb, ArrayList<AABB> aabbList);
+    boolean collidesWithEntity(Entity entity, World world, int x, int y, int z);
+    AABB getCollisionBoundingBoxFromPool(WorldSource world, int x, int y, int z);
+    boolean isSolidRender();
+    boolean blocksLight();
+    boolean canCollideCheck(int meta, boolean shouldCollideWithFluids);
+    boolean isCollidable();
+    void updateTick(World world, int x, int y, int z, Random rand);
+    void animationTick(World world, int x, int y, int z, Random rand);
+    void onNeighborBlockChange(World world, int x, int y, int z, int blockId);
+    int tickDelay();
+    void onBlockPlacedByWorld(World world, int x, int y, int z);
+    /**
+     * Always called when a block is removed by setBlock
+     */
+    void onBlockRemoved(World world, int x, int y, int z, int data);
+    /**
+     * Called when a block has been broken by a player, after {@link net.minecraft.core.block.Block#onBlockRemoved(World, int, int, int, int)}
+     */
+    void onBlockDestroyedByPlayer(World world, int x, int y, int z, Side side, int meta, Player player, Item item);
+    float blockStrength(World world, int x, int y, int z, Side side, Player player);
+    boolean getImmovable();
+    float getBlastResistance(Entity entity);
+    HitResult collisionRayTrace(World world, int x, int y, int z, Vec3 start, Vec3 end, boolean useSelectorBoxes);
+    void onBlockDestroyedByExplosion(World world, int x, int y, int z);
+    boolean canPlaceBlockOnSide(World world, int x, int y, int z, Side side);
+    boolean canPlaceBlockAt(World world, int x, int y, int z);
+    boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit);
+    void onActivatorInteract(World world, int x, int y, int z, TileEntityActivator activator, Direction direction);
+    void onEntityWalking(World world, int x, int y, int z, Entity entity);
+    void onBlockLeftClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit);
+    void handleEntityInside(World world, int x, int y, int z, Entity entity, Vec3 entityVelocity);
+    AABB getBlockBoundsFromState(WorldSource world, int x, int y, int z);
+    /**
+     * Gets the redstone signal output by the block itself, i.e. the power it will provide to any immediately adjacent redstone components.
+     */
+    boolean getSignal(WorldSource worldSource, int x, int y, int z, Side side);
+    boolean isSignalSource();
+    void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity);
+    /**
+     * Gets the redstone signal pushed into adjacent solid blocks. Any block experiencing *direct* signal will power itself and all adjacent blocks.
+     */
+    boolean getDirectSignal(World world, int x, int y, int z, Side side);
+    void harvestBlock(World world, Player player, int x, int y, int z, int meta, TileEntity tileEntity);
+    void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, TileEntity tileEntity, Player player);
+    ISupport getSupport(World world, int x, int y, int z, Side side);
+    boolean canBlockStay(World world, int x, int y, int z);
+    void onBlockPlacedByMob(World world, int x, int y, int z, @NotNull Side side, Mob mob, double xPlaced, double yPlaced);
+    void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced);
+    String getLanguageKey(int meta);
+    void triggerEvent(World world, int x, int y, int z, int index, int data);
+    int getPistonPushReaction(World world, int x, int y, int z);
+    int getPlacedBlockMetadata(@Nullable Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced);
+    boolean isClimbable(World world, int x, int y, int z);
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesBirch.java b/game/core/src/main/java/net/minecraft/core/block/BlockLeavesBirch.java
deleted file mode 100644
index e7ea149ff..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesBirch.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-
-public class BlockLeavesBirch extends BlockLeavesBase
-{
-
-	public BlockLeavesBirch(String key, String namespaceId, int id)
-    {
-        super(key, namespaceId, id, Material.leaves);
-    }
-
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_BIRCH;
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesPalm.java b/game/core/src/main/java/net/minecraft/core/block/BlockLeavesPalm.java
deleted file mode 100644
index 713032a33..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesPalm.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-
-public class BlockLeavesPalm extends BlockLeavesBase {
-
-	public BlockLeavesPalm(String key, String namespaceId, int id) {
-		super(key, namespaceId, id, Material.leaves);
-	}
-
-	@Override
-	protected Block getSapling() {
-		return Blocks.SAPLING_PALM;
-	}
-
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesRetro.java b/game/core/src/main/java/net/minecraft/core/block/BlockLeavesRetro.java
deleted file mode 100644
index 87649b35a..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesRetro.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-
-public class BlockLeavesRetro extends BlockLeavesBase
-{
-	public BlockLeavesRetro(String key, String namespaceId, int id)
-	{
-        super(key, namespaceId, id, Material.leaves);
-	}
-
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_OAK_RETRO;
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesThorn.java b/game/core/src/main/java/net/minecraft/core/block/BlockLeavesThorn.java
deleted file mode 100644
index 992442b61..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesThorn.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-
-public class BlockLeavesThorn extends BlockLeavesBase
-{
-    public BlockLeavesThorn(String key, String namespaceId, int id)
-    {
-        super(key, namespaceId, id, Material.leaves);
-    }
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_THORN;
-    }
-
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java
new file mode 100644
index 000000000..b617efc66
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java
@@ -0,0 +1,507 @@
+package net.minecraft.core.block;
+
+import net.minecraft.core.achievement.stat.StatList;
+import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.entity.TileEntityActivator;
+import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.material.MaterialColor;
+import net.minecraft.core.block.support.FullSupport;
+import net.minecraft.core.block.support.ISupport;
+import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.entity.Entity;
+import net.minecraft.core.entity.EntityItem;
+import net.minecraft.core.entity.Mob;
+import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.item.IItemConvertible;
+import net.minecraft.core.item.Item;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.item.tool.ItemToolShears;
+import net.minecraft.core.util.collection.NamespaceID;
+import net.minecraft.core.util.helper.Direction;
+import net.minecraft.core.util.helper.Side;
+import net.minecraft.core.util.phys.AABB;
+import net.minecraft.core.util.phys.BoundingVolume;
+import net.minecraft.core.util.phys.HitResult;
+import net.minecraft.core.util.phys.Vec3;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.WorldSource;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Random;
+
+public class BlockLogic implements BlockInterface, IItemConvertible {
+    protected final AABB bounds = AABB.getPermanentBB(0, 0, 0, 1, 1, 1);
+    public final @NotNull Block<?> block;
+    protected @NotNull Material material;
+    public BlockLogic(Block<?> block, Material material) {
+        this.block = Objects.requireNonNull(block);
+        this.material = Objects.requireNonNull(material);
+    }
+
+    public void initializeBlock() {
+
+    }
+
+    @Override
+    public final int id() {
+        return block.id();
+    }
+
+    @Override
+    public final @NotNull String getKey() {
+        return block.getKey();
+    }
+
+    @Override
+    public final @NotNull NamespaceID namespaceId() {
+        return block.namespaceId();
+    }
+
+    public @NotNull Material getMaterial() {
+        return material;
+    }
+
+    public @NotNull MaterialColor getMaterialColor() {
+        return material.color;
+    }
+
+    @Override
+    public boolean isCubeShaped() {
+        return true;
+    }
+
+    @Override
+    public boolean canPlaceOnSurface() {
+        return this.isCubeShaped();
+    }
+
+    @Override
+    public boolean canPlaceOnSurfaceOnCondition(World world, int x, int y, int z) {
+        return this.canPlaceOnSurface();
+    }
+
+    @Override
+    public boolean renderAsNormalBlockOnCondition(WorldSource world, int x, int y, int z) {
+        return this.isCubeShaped();
+    }
+
+    @Override
+    public boolean canPlaceOnSurfaceOfBlock(World world, int x, int y, int z) {
+        return canPlaceOnSurface();
+    }
+
+    @Override
+    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, TileEntity tileEntity) {
+        return getBreakResult(world, dropCause, meta, tileEntity);
+    }
+
+    @Override
+    public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity) {
+        if (dropCause != EnumDropCause.IMPROPER_TOOL) {
+            return new ItemStack[] { new ItemStack(block) };
+        }
+        return null;
+    }
+
+    public void setBlockBounds(double minX, double minY, double minZ, double maxX, double maxY, double maxZ)
+    {
+        bounds.set(minX, minY, minZ, maxX, maxY, maxZ);
+    }
+
+    @Override
+    public AABB getBounds() {
+        return bounds.copy();
+    }
+
+    @Override
+    public AABB getBoundsRaw() {
+        return bounds;
+    }
+
+    @Override
+    public float getBlockBrightness(WorldSource blockAccess, int x, int y, int z) {
+        return blockAccess.getBrightness(x, y, z, block.emission);
+    }
+
+    @Override
+    public int getLightmapCoord(WorldSource blockAccess, int x, int y, int z) {
+        return blockAccess.getLightmapCoord(x, y, z, block.emission);
+    }
+
+    @Override
+    public float getAmbientOcclusionStrength(WorldSource blockAccess, int x, int y, int z) {
+        return isSolidRender() ? 1.0f : 0.0f;
+    }
+
+    @Override
+    public boolean getIsBlockSolid(WorldSource blockAccess, int x, int y, int z, Side side) {
+        return blockAccess.getBlockMaterial(x, y, z).isSolid();
+    }
+
+    @Override
+    public AABB getSelectedBoundingBoxFromPool(WorldSource world, int x, int y, int z) {
+        return getBlockBoundsFromState(world, x, y, z).move(x, y, z);
+    }
+
+    @Override
+    public BoundingVolume getBoundingVolume(World world, int x, int y, int z) {
+        return null;
+    }
+
+    @Override
+    public void getCollidingBoundingBoxes(World world, int x, int y, int z, AABB aabb, ArrayList<AABB> aabbList)
+    {
+        addIntersectingBoundingBox(aabb, getCollisionBoundingBoxFromPool(world, x, y, z), aabbList);
+    }
+
+    protected void addIntersectingBoundingBox(AABB sourceAABB, AABB aabbToAdd, ArrayList<AABB> aabbList) {
+        if(aabbToAdd != null && sourceAABB.intersects(aabbToAdd))
+        {
+            aabbList.add(aabbToAdd);
+        }
+    }
+
+    @Override
+    public boolean collidesWithEntity(Entity entity, World world, int x, int y, int z) {
+        return true;
+    }
+
+    @Override
+    public AABB getCollisionBoundingBoxFromPool(WorldSource world, int x, int y, int z) {
+        return getBlockBoundsFromState(world, x, y, z).move(x, y, z);
+    }
+
+    @Override
+    public boolean isSolidRender() {
+        return true;
+    }
+
+    @Override
+    public boolean blocksLight() {
+        return false;
+    }
+
+    @Override
+    public boolean canCollideCheck(int meta, boolean shouldCollideWithFluids) {
+        return isCollidable();
+    }
+
+    @Override
+    public boolean isCollidable() {
+        return true;
+    }
+
+    @Override
+    public void updateTick(World world, int x, int y, int z, Random rand) {
+
+    }
+
+    @Override
+    public void animationTick(World world, int x, int y, int z, Random rand) {
+
+    }
+
+    @Override
+    public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
+
+    }
+
+    @Override
+    public int tickDelay() {
+        return 10;
+    }
+
+    @Override
+    public void onBlockPlacedByWorld(World world, int x, int y, int z) {
+
+    }
+
+    @Override
+    public void onBlockRemoved(World world, int x, int y, int z, int data) {
+
+    }
+
+    @Override
+    public void onBlockDestroyedByPlayer(World world, int x, int y, int z, Side side, int meta, Player player, Item item) {
+
+    }
+
+    @Override
+    public float blockStrength(World world, int x, int y, int z, Side side, Player player) {
+        if(block.blockHardness < 0.0F)
+        {
+            return 0.0F;
+        }
+
+        if (!player.canHarvestBlock(block))
+        {
+            return 1.0F / block.blockHardness / 100F;
+        }
+        else
+        {
+            return player.getCurrentPlayerStrVsBlock(block) / block.blockHardness / 30F;
+        }
+    }
+
+    @Override
+    public boolean getImmovable() {
+        return block.immovable;
+    }
+
+    @Override
+    public float getBlastResistance(Entity entity) {
+        return block.blastResistance / 5f;
+    }
+
+    @Override
+    public HitResult collisionRayTrace(World world, int x, int y, int z, Vec3 start, Vec3 end, boolean useSelectorBoxes) {
+        AABB bounds = useSelectorBoxes ? getSelectedBoundingBoxFromPool(world, x, y, z).move(-x, -y, -z) : getBlockBoundsFromState(world, x, y, z);
+        start = start.add(-x, -y, -z);
+        end = end.add(-x, -y, -z);
+        Vec3 minVX = start.clipX(end, bounds.minX);
+        Vec3 maxVX = start.clipX(end, bounds.maxX);
+        Vec3 minVY = start.clipY(end, bounds.minY);
+        Vec3 maxVY = start.clipY(end, bounds.maxY);
+        Vec3 minVZ = start.clipZ(end, bounds.minZ);
+        Vec3 maxVZ = start.clipZ(end, bounds.maxZ);
+
+        if(!isVecInsideYZBounds(bounds,minVX)) minVX = null;
+        if(!isVecInsideYZBounds(bounds,maxVX)) maxVX = null;
+        if(!isVecInsideXZBounds(bounds,minVY)) minVY = null;
+        if(!isVecInsideXZBounds(bounds,maxVY)) maxVY = null;
+        if(!isVecInsideXYBounds(bounds,minVZ)) minVZ = null;
+        if(!isVecInsideXYBounds(bounds,maxVZ)) maxVZ = null;
+
+        Vec3 vec38 = null;
+        if(minVX != null && (vec38 == null || start.distanceToSquared(minVX) < start.distanceToSquared(vec38))) vec38 = minVX;
+        if(maxVX != null && (vec38 == null || start.distanceToSquared(maxVX) < start.distanceToSquared(vec38))) vec38 = maxVX;
+        if(minVY != null && (vec38 == null || start.distanceToSquared(minVY) < start.distanceToSquared(vec38))) vec38 = minVY;
+        if(maxVY != null && (vec38 == null || start.distanceToSquared(maxVY) < start.distanceToSquared(vec38))) vec38 = maxVY;
+        if(minVZ != null && (vec38 == null || start.distanceToSquared(minVZ) < start.distanceToSquared(vec38))) vec38 = minVZ;
+        if(maxVZ != null && (vec38 == null || start.distanceToSquared(maxVZ) < start.distanceToSquared(vec38))) vec38 = maxVZ;
+
+        if(vec38 == null) return null;
+        Side side = Side.NONE;
+        if(vec38 == minVX) side = Side.WEST;
+        if(vec38 == maxVX) side = Side.EAST;
+        if(vec38 == minVY) side = Side.BOTTOM;
+        if(vec38 == maxVY) side = Side.TOP;
+        if(vec38 == minVZ) side = Side.NORTH;
+        if(vec38 == maxVZ) side = Side.SOUTH;
+
+        return new HitResult(x, y, z, side, vec38.add(x, y, z));
+    }
+
+    private boolean isVecInsideYZBounds(AABB bounds, @Nullable Vec3 vec3)
+    {
+        if(vec3 == null) {
+            return false;
+        }
+        return vec3.y >= bounds.minY && vec3.y <= bounds.maxY && vec3.z >= bounds.minZ && vec3.z <= bounds.maxZ;
+    }
+
+    private boolean isVecInsideXZBounds(AABB bounds, @Nullable Vec3 vec3)
+    {
+        if(vec3 == null) {
+            return false;
+        }
+        return vec3.x >= bounds.minX && vec3.x <= bounds.maxX && vec3.z >= bounds.minZ && vec3.z <= bounds.maxZ;
+    }
+
+    private boolean isVecInsideXYBounds(AABB bounds, @Nullable Vec3 vec3)
+    {
+        if(vec3 == null) {
+            return false;
+        }
+        return vec3.x >= bounds.minX && vec3.x <= bounds.maxX && vec3.y >= bounds.minY && vec3.y <= bounds.maxY;
+    }
+
+    @Override
+    public void onBlockDestroyedByExplosion(World world, int x, int y, int z) {
+
+    }
+
+    @Override
+    public boolean canPlaceBlockOnSide(World world, int x, int y, int z, Side side) {
+        return canPlaceBlockAt(world, x, y, z);
+    }
+
+    @Override
+    public boolean canPlaceBlockAt(World world, int x, int y, int z) {
+        return world.canPlaceInsideBlock(x, y, z);
+    }
+
+    @Override
+    public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit) {
+        return false;
+    }
+
+    @Override
+    public void onActivatorInteract(World world, int x, int y, int z, TileEntityActivator activator, Direction direction) {
+
+    }
+
+    @Override
+    public void onEntityWalking(World world, int x, int y, int z, Entity entity) {
+
+    }
+
+    @Override
+    public void onBlockLeftClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit) {
+
+    }
+
+    @Override
+    public void handleEntityInside(World world, int x, int y, int z, Entity entity, Vec3 entityVelocity) {
+
+    }
+
+    @Override
+    public AABB getBlockBoundsFromState(WorldSource world, int x, int y, int z) {
+        return getBounds();
+    }
+
+    @Override
+    public boolean getSignal(WorldSource worldSource, int x, int y, int z, Side side) {
+        return false;
+    }
+
+    @Override
+    public boolean isSignalSource() {
+        return false;
+    }
+
+    @Override
+    public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) {
+
+    }
+
+    @Override
+    public boolean getDirectSignal(World world, int x, int y, int z, Side side) {
+        return false;
+    }
+
+    @Override
+    public void harvestBlock(World world, Player player, int x, int y, int z, int meta, TileEntity tileEntity) {
+        player.addStat(block.getStat(StatList.STAT_MINED), 1);
+
+        ItemStack heldItemStack = player.inventory.getCurrentItem();
+        Item heldItem = heldItemStack != null ? Item.itemsList[heldItemStack.itemID] : null;
+
+        if (heldItem != null)
+        {
+            if (heldItem.isSilkTouch() && player.canHarvestBlock(block))
+            {
+                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, tileEntity, player);
+                return;
+            }
+            else if (heldItem instanceof ItemToolShears && (block.hasTag(BlockTags.SHEARS_DO_SILK_TOUCH) || block.hasTag(BlockTags.MINEABLE_BY_SHEARS)))
+            {
+                ItemToolShears heldShears = (ItemToolShears) heldItem;
+                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, tileEntity, player);
+                heldShears.onBlockSheared(player, heldItemStack);
+                return;
+            }
+        }
+
+        if (player.canHarvestBlock(block))
+        {
+            dropBlockWithCause(world, EnumDropCause.PROPER_TOOL, x, y, z, meta, tileEntity, player);
+        }
+        else
+        {
+            dropBlockWithCause(world, EnumDropCause.IMPROPER_TOOL, x, y, z, meta, tileEntity, player);
+        }
+    }
+
+    @Override
+    public void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, TileEntity tileEntity, Player player) {
+        if(world.isClientSide)
+            return;
+
+        ItemStack[] drops = getBreakResult(world, cause, x, y, z, meta, tileEntity);
+        if (drops == null) {
+            return;
+        }
+        for (int j = 0, dropsLength = drops.length; j < dropsLength; j++) {
+            ItemStack drop = drops[j];
+            if (drop == null) {
+                continue;
+            }
+            if (block.hasTag(BlockTags.INSTANT_PICKUP) && player != null) {
+                player.inventory.insertItem(drop, true);
+                if (drop.stackSize <= 0) {
+                    continue;
+                }
+            }
+            if (EntityItem.enableItemClumping) {
+                world.dropItem(x, y, z, drop.copy());
+            } else {
+                for (int i = 0; i < drop.stackSize; i++) {
+                    ItemStack drop1 = drop.copy();
+                    drop1.stackSize = 1;
+                    world.dropItem(x, y, z, drop1);
+                }
+            }
+        }
+    }
+
+    @Override
+    public ISupport getSupport(World world, int x, int y, int z, Side side) {
+        return FullSupport.INSTANCE;
+    }
+
+    @Override
+    public boolean canBlockStay(World world, int x, int y, int z) {
+        return true;
+    }
+
+    @Override
+    public void onBlockPlacedByMob(World world, int x, int y, int z, @NotNull Side side, Mob mob, double xPlaced, double yPlaced) {
+        onBlockPlacedOnSide(world, x, y, z, side, xPlaced, yPlaced);
+    }
+
+    @Override
+    public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
+
+    }
+
+    @Override
+    public String getLanguageKey(int meta) {
+        return block.getKey();
+    }
+
+    @Override
+    public void triggerEvent(World world, int x, int y, int z, int index, int data) {
+
+    }
+
+    @Override
+    public int getPistonPushReaction(World world, int x, int y, int z) {
+        return material.getPushReaction();
+    }
+
+    @Override
+    public int getPlacedBlockMetadata(@Nullable Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+        return 0;
+    }
+
+    @Override
+    public boolean isClimbable(World world, int x, int y, int z) {
+        return false;
+    }
+
+    @Override
+    public Item asItem() {
+        return block.asItem();
+    }
+
+    @Override
+    public ItemStack getDefaultStack() {
+        return block.getDefaultStack();
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockActivator.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockActivator.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
index 703d8f102..1a7108d55 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockActivator.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
@@ -1,7 +1,6 @@
 package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.TileEntityActivator;
-import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Item;
@@ -14,12 +13,12 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockActivator extends BlockTileEntityVeryRotatable
+public class BlockLogicActivator extends BlockLogicVeryRotatable
 {
     public static final int MASK_POWERED = 0b0000_1000;
-    public BlockActivator(String key, String namespaceId, int id)
-    {
-        super(key, namespaceId, id, Material.netherrack);
+    public BlockLogicActivator(Block<?> block) {
+        super(block, Material.netherrack);
+        block.withEntity(TileEntityActivator::new);
     }
 
     @Override
@@ -40,7 +39,7 @@ public class BlockActivator extends BlockTileEntityVeryRotatable
 
     private void useItem(World world, int x, int y, int z, Random random)
     {
-        Direction direction = BlockRotatable.getDirectionFromMeta(world.getBlockMetadata(x, y, z));
+        Direction direction = BlockLogicRotatable.getDirectionFromMeta(world.getBlockMetadata(x, y, z));
         int xOffset = direction.getOffsetX();
         int yOffset = direction.getOffsetY();
         int zOffset = direction.getOffsetZ();
@@ -54,7 +53,7 @@ public class BlockActivator extends BlockTileEntityVeryRotatable
             double pz = (double)zOffset * 0.6D + 0.5D;
             if(itemStack == null)
             {
-                Block block = world.getBlock(x + xOffset, y + yOffset, z + zOffset);
+                Block<?> block = world.getBlock(x + xOffset, y + yOffset, z + zOffset);
                 if (block != null) {
                     block.onActivatorInteract(world, x + xOffset, y + yOffset, z + zOffset, activator, direction);
                 } else {
@@ -78,10 +77,10 @@ public class BlockActivator extends BlockTileEntityVeryRotatable
     public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
     {
         int meta = world.getBlockMetadata(x, y, z);
-        boolean flag = getNeighborSignal(world, x, y, z, BlockRotatable.getDirectionFromMeta(meta));
+        boolean flag = getNeighborSignal(world, x, y, z, BlockLogicRotatable.getDirectionFromMeta(meta));
         if(flag && (meta & MASK_POWERED) == 0)
         {
-            world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
             world.setBlockMetadata(x, y, z, meta | MASK_POWERED);
         } else if (!flag){
             world.setBlockMetadata(x, y, z, meta & ~MASK_POWERED);
@@ -118,11 +117,4 @@ public class BlockActivator extends BlockTileEntityVeryRotatable
         }
         return false;
     }
-
-    @Override
-    protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityActivator();
-    }
-
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockAlgae.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicAlgae.java
similarity index 78%
rename from game/core/src/main/java/net/minecraft/core/block/BlockAlgae.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicAlgae.java
index 9fdd7944e..529407867 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockAlgae.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicAlgae.java
@@ -12,12 +12,12 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.phys.AABB;
 
-public class BlockAlgae extends Block
+public class BlockLogicAlgae extends BlockLogic
 {
 
-    protected BlockAlgae(String key, String namespaceId, int id, Material material)
+    protected BlockLogicAlgae(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         setBlockBounds(0.0F, -0.125F, 0.0F, 1.0F, 0.00625f, 1.0F);
     }
 
@@ -26,7 +26,7 @@ public class BlockAlgae extends Block
     {
         if(entity instanceof EntityBoat) {
             int data = world.getBlockMetadata(x, y, z);
-            world.playBlockEvent(null, LevelListener.EVENT_BLOCK_BREAK, x, y, z, id);
+            world.playBlockEvent(null, LevelListener.EVENT_BLOCK_BREAK, x, y, z, block.id());
             world.setBlockWithNotify(x, y, z, 0);
             this.onBlockRemoved(world, x, y, z, data);
         }
@@ -36,13 +36,13 @@ public class BlockAlgae extends Block
     public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
         int blockId = world.getBlockId(x, y, z);
-        return blockId == 0 && Block.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER) && world.getBlockMetadata(x, y -1, z) == 0;
+        return blockId == 0 && Blocks.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER) && world.getBlockMetadata(x, y -1, z) == 0;
     }
 
     @Override
     public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
     {
-        if(!Block.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER) || world.getBlockMetadata(x, y -1, z) != 0){
+        if(!Blocks.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER) || world.getBlockMetadata(x, y -1, z) != 0){
             world.setBlock(x, y, z,0);
         }
     }
@@ -72,7 +72,7 @@ public class BlockAlgae extends Block
         {
             case SILK_TOUCH:
             case PICK_BLOCK:
-                return new ItemStack[] { new ItemStack(this) };
+                return new ItemStack[] { new ItemStack(block) };
             default:
                 return null;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockAxisAligned.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicAxisAligned.java
similarity index 86%
rename from game/core/src/main/java/net/minecraft/core/block/BlockAxisAligned.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicAxisAligned.java
index b18d96ae7..34fd38e5b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockAxisAligned.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicAxisAligned.java
@@ -8,10 +8,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 
-public class BlockAxisAligned extends Block {
+public class BlockLogicAxisAligned extends BlockLogic {
 
-	public BlockAxisAligned(String key, String namespaceId, int id, Material material) {
-		super(key, namespaceId, id, material);
+	public BlockLogicAxisAligned(Block<?> block, Material material) {
+		super(block, material);
 	}
 
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockBasket.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBasket.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/BlockBasket.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicBasket.java
index 30043a126..5fe216bcb 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockBasket.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBasket.java
@@ -12,11 +12,12 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.World;
 
-public class BlockBasket extends BlockTileEntity
+public class BlockLogicBasket extends BlockLogic
 {
-    protected BlockBasket(final String blockName, String namespaceId, int id, final Material material)
+    protected BlockLogicBasket(Block<?> block, final Material material)
     {
-        super(blockName, namespaceId, id, material);
+        super(block, material);
+        block.withEntity(TileEntityBasket::new);
     }
 
     @Override
@@ -49,12 +50,6 @@ public class BlockBasket extends BlockTileEntity
         return false;
     }
 
-    @Override
-    protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityBasket();
-    }
-
     public int getFillLevel(final WorldSource world, final int x, final int y, final int z)
     {
         final TileEntityBasket te = (TileEntityBasket) world.getBlockEntity(x, y, z);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockBed.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
similarity index 93%
rename from game/core/src/main/java/net/minecraft/core/block/BlockBed.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
index 7d3054006..6033321de 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockBed.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
@@ -9,15 +9,13 @@ import net.minecraft.core.enums.EnumSleepStatus;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
-import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.chunk.ChunkCoordinates;
 
-public class BlockBed extends Block {
+public class BlockLogicBed extends BlockLogic {
 
-	public BlockBed(String key, String namespaceId, int id) {
-		super(key, namespaceId, id, Material.wood);
+	public BlockLogicBed(Block<?> block) {
+		super(block, Material.wood);
 		setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5625F, 1.0F);
 	}
 
@@ -33,7 +31,7 @@ public class BlockBed extends Block {
 			int dir = getDirection(meta);
 			x += headBlockToFootBlockMap[dir].getOffsetX();
 			z += headBlockToFootBlockMap[dir].getOffsetZ();
-			if(world.getBlockId(x, y, z) != id) {
+			if(world.getBlockId(x, y, z) != block.id()) {
 				return true;
 			}
 			meta = world.getBlockMetadata(x, y, z);
@@ -45,7 +43,7 @@ public class BlockBed extends Block {
 			int dir = getDirection(meta);
 			x += headBlockToFootBlockMap[dir].getOffsetX();
 			z += headBlockToFootBlockMap[dir].getOffsetZ();
-			if(world.getBlockId(x, y, z) == id) {
+			if(world.getBlockId(x, y, z) == block.id()) {
 				world.setBlockWithNotify(x, y, z, 0);
             }
 			player.addStat(Achievements.SLEEP_NETHER, 1);
@@ -96,10 +94,10 @@ public class BlockBed extends Block {
 		int metadata = world.getBlockMetadata(x, y, z);
 		int direction = getDirection(metadata);
 		if(isBlockFootOfBed(metadata)) {
-			if(world.getBlockId(x - headBlockToFootBlockMap[direction].getOffsetX(), y, z - headBlockToFootBlockMap[direction].getOffsetZ()) != id) {
+			if(world.getBlockId(x - headBlockToFootBlockMap[direction].getOffsetX(), y, z - headBlockToFootBlockMap[direction].getOffsetZ()) != block.id()) {
 				world.setBlockWithNotify(x, y, z, 0);
 			}
-		} else if(world.getBlockId(x + headBlockToFootBlockMap[direction].getOffsetX(), y, z + headBlockToFootBlockMap[direction].getOffsetZ()) != id) {
+		} else if(world.getBlockId(x + headBlockToFootBlockMap[direction].getOffsetX(), y, z + headBlockToFootBlockMap[direction].getOffsetZ()) != block.id()) {
 			world.setBlockWithNotify(x, y, z, 0);
 		}
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockBedrock.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java
similarity index 56%
rename from game/core/src/main/java/net/minecraft/core/block/BlockBedrock.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java
index 68477c5b2..f2df63cd7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockBedrock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java
@@ -4,19 +4,19 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.world.World;
 
-public class BlockBedrock
-	extends Block
+public class BlockLogicBedrock
+	extends BlockLogic
 {
-	public BlockBedrock(String key, String namespaceId, int id, Material material)
+	public BlockLogicBedrock(Block<?> block, Material material)
     {
-		super(key, namespaceId, id, material);
+		super(block, material);
 	}
 
 	@Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
-        if (world.getBlockId(x, y - 1, z) == Blocks.GLOWSTONE.id) {
-            ((BlockPortal) Blocks.PORTAL_PARADISE).tryToCreatePortal(world, x, y, z, DyeColor.SILVER);
+        if (world.getBlockId(x, y - 1, z) == Blocks.GLOWSTONE.id()) {
+            Blocks.PORTAL_PARADISE.getLogic().tryToCreatePortal(world, x, y, z, DyeColor.SILVER);
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockBoneShale.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoneShale.java
similarity index 57%
rename from game/core/src/main/java/net/minecraft/core/block/BlockBoneShale.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicBoneShale.java
index 931f5124d..84ea53511 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockBoneShale.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoneShale.java
@@ -6,27 +6,27 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
-public class BlockBoneShale extends BlockFullyRotatable {
-    public BlockBoneShale(String translationKey, String namespaceId, int id, Material material) {
-        super(translationKey, namespaceId, id, material);
+public class BlockLogicBoneShale extends BlockLogicFullyRotatable {
+    public BlockLogicBoneShale(Block<?> block, Material material) {
+        super(block, material);
     }
 
     @Override
     public float blockStrength(World world, int x, int y, int z, Side side, Player player) {
-        float blockHardness = this.blockHardness;
+        float blockHardness = block.getHardness();
         final int meta = world.getBlockMetadata(x, y, z);
-        final Direction direction = BlockFullyRotatable.metaToDirection(meta);
+        final Direction direction = BlockLogicFullyRotatable.metaToDirection(meta);
         if (side != direction.getSide()) {
             blockHardness *= 66.6f;
         }
 
-        if (!player.canHarvestBlock(this))
+        if (!player.canHarvestBlock(block))
         {
             return 1.0F / blockHardness / 30F;
         }
         else
         {
-            return player.getCurrentPlayerStrVsBlock(this) / blockHardness / 30F;
+            return player.getCurrentPlayerStrVsBlock(block) / blockHardness / 30F;
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockBrazier.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBrazier.java
similarity index 76%
rename from game/core/src/main/java/net/minecraft/core/block/BlockBrazier.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicBrazier.java
index 24040cd72..1c85641e3 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockBrazier.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBrazier.java
@@ -14,12 +14,12 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockBrazier
-    extends Block {
+public class BlockLogicBrazier
+    extends BlockLogic {
     private final boolean burning;
 
-    public BlockBrazier(String key, String namespaceId, int id, boolean burning) {
-        super(key, namespaceId, id, Material.metal);
+    public BlockLogicBrazier(Block<?> block, boolean burning) {
+        super(block, Material.metal);
         this.burning = burning;
     }
 
@@ -46,19 +46,20 @@ public class BlockBrazier
     public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xPlaced, double yPlaced) {
         ItemStack heldItem = player.getHeldItem();
         if (heldItem != null && heldItem.getItem() instanceof ItemFireStriker && !burning) {
-            if (world.getBlock(x + 1, y, z) instanceof BlockFluid ||
-                world.getBlock(x - 1, y, z) instanceof BlockFluid ||
-                world.getBlock(x, y, z + 1) instanceof BlockFluid ||
-                world.getBlock(x, y, z - 1) instanceof BlockFluid) {
+            Block<?> b;
+            if ((b = world.getBlock(x + 1, y, z)) != null && b.getLogic() instanceof BlockLogicFluid ||
+                (b = world.getBlock(x - 1, y, z)) != null && b.getLogic() instanceof BlockLogicFluid ||
+                (b = world.getBlock(x, y, z + 1)) != null && b.getLogic() instanceof BlockLogicFluid ||
+                (b = world.getBlock(x, y, z - 1)) != null && b.getLogic() instanceof BlockLogicFluid) {
                 return false;
             }
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_ACTIVE.id, 0);
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_ACTIVE.id(), 0);
             heldItem.damageItem(1, player);
             world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "fire.ignite", 1.0F, world.rand.nextFloat() * 0.4F + 0.8F);
             return true;
         }
         if (heldItem == null && burning) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_INACTIVE.id, 0);
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_INACTIVE.id(), 0);
             return true;
         }
 
@@ -68,7 +69,7 @@ public class BlockBrazier
     @Override
     public void onActivatorInteract(World world, int x, int y, int z, TileEntityActivator activator, Direction direction) {
         if (burning) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_INACTIVE.id, 0);
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_INACTIVE.id(), 0);
         }
     }
 
@@ -82,9 +83,9 @@ public class BlockBrazier
     @Override
     public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
         if (!burning) return;
-        Block block = Blocks.blocksList[blockId];
-        if (block instanceof BlockFluid) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_INACTIVE.id, 0);
+        Block<?> block = Blocks.blocksList[blockId];
+        if (block != null && block.getLogic() instanceof BlockLogicFluid) {
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.BRAZIER_INACTIVE.id(), 0);
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockButton.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButton.java
similarity index 95%
rename from game/core/src/main/java/net/minecraft/core/block/BlockButton.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicButton.java
index 5477ba41b..ee8c08f96 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockButton.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButton.java
@@ -18,7 +18,7 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockButton extends Block
+public class BlockLogicButton extends BlockLogic
 {
     public static final int MASK_POWERED = 0b0000_1000;
     public static final int MASK_DIRECTION = 0b0000_0111;
@@ -29,10 +29,10 @@ public class BlockButton extends Block
     public static final int SIDE_TOP = 5;
     public static final int SIDE_BOTTOM = 6;
 
-	public BlockButton(String key, String namespaceId, int id)
+	public BlockLogicButton(Block<?> block)
     {
-        super(key, namespaceId, id, Material.decoration);
-        setTicking(true);
+        super(block, Material.decoration);
+        block.setTicking(true);
     }
 
     @Override
@@ -293,28 +293,28 @@ public class BlockButton extends Block
         world.setBlockMetadataWithNotify(x, y, z, direction | MASK_POWERED);
         world.markBlocksDirty(x, y, z, x, y, z);
         world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, (double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "random.click", 0.3F, 0.6F);
-        world.notifyBlocksOfNeighborChange(x, y, z, id);
+        world.notifyBlocksOfNeighborChange(x, y, z, block.id());
         switch (direction) {
             case SIDE_WEST:
-                world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
+                world.notifyBlocksOfNeighborChange(x - 1, y, z, block.id());
                 break;
             case SIDE_EAST:
-                world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
+                world.notifyBlocksOfNeighborChange(x + 1, y, z, block.id());
                 break;
             case SIDE_NORTH:
-                world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
+                world.notifyBlocksOfNeighborChange(x, y, z - 1, block.id());
                 break;
             case SIDE_SOUTH:
-                world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
+                world.notifyBlocksOfNeighborChange(x, y, z + 1, block.id());
                 break;
             case SIDE_TOP:
-                world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+                world.notifyBlocksOfNeighborChange(x, y + 1, z, block.id());
                 break;
             case SIDE_BOTTOM:
-                world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+                world.notifyBlocksOfNeighborChange(x, y - 1, z, block.id());
                 break;
         }
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+        world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
         return true;
     }
 
@@ -328,26 +328,26 @@ public class BlockButton extends Block
     {
         if((data & MASK_POWERED) != 0)
         {
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
+            world.notifyBlocksOfNeighborChange(x, y, z, block.id());
             int direction = data & MASK_DIRECTION;
             switch (direction) {
                 case SIDE_WEST:
-                    world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
+                    world.notifyBlocksOfNeighborChange(x - 1, y, z, block.id());
                     break;
                 case SIDE_EAST:
-                    world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
+                    world.notifyBlocksOfNeighborChange(x + 1, y, z, block.id());
                     break;
                 case SIDE_NORTH:
-                    world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
+                    world.notifyBlocksOfNeighborChange(x, y, z - 1, block.id());
                     break;
                 case SIDE_SOUTH:
-                    world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
+                    world.notifyBlocksOfNeighborChange(x, y, z + 1, block.id());
                     break;
                 case SIDE_TOP:
-                    world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+                    world.notifyBlocksOfNeighborChange(x, y + 1, z, block.id());
                     break;
                 case SIDE_BOTTOM:
-                    world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+                    world.notifyBlocksOfNeighborChange(x, y - 1, z, block.id());
                     break;
             }
         }
@@ -404,26 +404,26 @@ public class BlockButton extends Block
             return;
         }
         world.setBlockMetadataWithNotify(x, y, z, meta & ~MASK_POWERED);
-        world.notifyBlocksOfNeighborChange(x, y, z, id);
+        world.notifyBlocksOfNeighborChange(x, y, z, block.id());
         int direction = meta & MASK_DIRECTION;
         switch (direction) {
             case SIDE_WEST:
-                world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
+                world.notifyBlocksOfNeighborChange(x - 1, y, z, block.id());
                 break;
             case SIDE_EAST:
-                world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
+                world.notifyBlocksOfNeighborChange(x + 1, y, z, block.id());
                 break;
             case SIDE_NORTH:
-                world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
+                world.notifyBlocksOfNeighborChange(x, y, z - 1, block.id());
                 break;
             case SIDE_SOUTH:
-                world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
+                world.notifyBlocksOfNeighborChange(x, y, z + 1, block.id());
                 break;
             case SIDE_TOP:
-                world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+                world.notifyBlocksOfNeighborChange(x, y + 1, z, block.id());
                 break;
             case SIDE_BOTTOM:
-                world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+                world.notifyBlocksOfNeighborChange(x, y - 1, z, block.id());
                 break;
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockCactus.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCactus.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockCactus.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicCactus.java
index a37b22b81..c62c3d4c6 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockCactus.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCactus.java
@@ -12,20 +12,18 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
-import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.util.helper.DamageType;
-import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockCactus extends Block implements IBonemealable
+public class BlockLogicCactus extends BlockLogic implements IBonemealable
 {
 
-	public BlockCactus(String key, String namespaceId, int id)
+	public BlockLogicCactus(Block<?> block)
     {
-        super(key, namespaceId, id, Material.cactus);
-        setTicking(true);
+        super(block, Material.cactus);
+        block.setTicking(true);
         float f = 0.0625F;
         setBlockBounds(f, 0, f, 1 - f, 1, 1 - f);
     }
@@ -41,7 +39,7 @@ public class BlockCactus extends Block implements IBonemealable
         {
             int cactusHeight;
             cactusHeight = 1;
-            while (world.getBlockId(x, y - cactusHeight, z) == id) {
+            while (world.getBlockId(x, y - cactusHeight, z) == block.id()) {
                 cactusHeight++;
             }
             if(cactusHeight < 3)
@@ -49,7 +47,7 @@ public class BlockCactus extends Block implements IBonemealable
                 int i1 = world.getBlockMetadata(x, y, z);
                 if(i1 == 15)
                 {
-                    world.setBlockWithNotify(x, y + 1, z, id);
+                    world.setBlockWithNotify(x, y + 1, z, block.id());
                     world.setBlockMetadataWithNotify(x, y, z, 0);
                 } else
                 {
@@ -61,9 +59,9 @@ public class BlockCactus extends Block implements IBonemealable
 
     public void growCactusOnTop(World world, int x, int y, int z){
         int l;
-        for(l = 1; world.getBlockId(x, y + l, z) == id; l++) { }
+        for(l = 1; world.getBlockId(x, y + l, z) == block.id(); l++) { }
         if(world.isAirBlock(x, y+l, z)){
-            world.setBlockWithNotify(x, y + l, z, id);
+            world.setBlockWithNotify(x, y + l, z, block.id());
         }
     }
 
@@ -122,7 +120,7 @@ public class BlockCactus extends Block implements IBonemealable
         } else
         {
             int l = world.getBlockId(x, y - 1, z);
-            return Block.hasTag(l, BlockTags.GROWS_CACTI);
+            return Blocks.hasTag(l, BlockTags.GROWS_CACTI);
         }
     }
     @Override
@@ -137,7 +135,7 @@ public class BlockCactus extends Block implements IBonemealable
     public boolean onBonemealUsed(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
         if(!world.isClientSide)
         {
-            ((BlockCactus)Blocks.blocksList[id]).growCactusOnTop(world, blockX, blockY, blockZ);
+            growCactusOnTop(world, blockX, blockY, blockZ);
             if (player == null || player.getGamemode().consumeBlocks())
             {
                 itemstack.stackSize--;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockCake.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCake.java
similarity index 75%
rename from game/core/src/main/java/net/minecraft/core/block/BlockCake.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicCake.java
index 485f4dc00..190a3da83 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockCake.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCake.java
@@ -4,12 +4,12 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockCake extends BlockEdible
+public class BlockLogicCake extends BlockLogicEdible
 {
 
-	public BlockCake(String key, String namespaceId, int id)
+	public BlockLogicCake(Block<?> block)
     {
-        super(key, namespaceId, id, 6, 3, () -> Items.FOOD_CAKE);
+        super(block, 6, 3, () -> Items.FOOD_CAKE);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockCandle.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCandle.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/BlockCandle.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicCandle.java
index 0d94b5329..1670188c4 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockCandle.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCandle.java
@@ -10,13 +10,11 @@ import net.minecraft.core.world.WorldSource;
 
 import java.util.Random;
 
-public class BlockCandle extends Block
+public class BlockLogicCandle extends BlockLogic
 {
-    public BlockCandle(String key, String namespaceId, int id, Material material)
+    public BlockLogicCandle(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
-        setTicking(true);
-
+        super(block, material);
         setBlockBounds(0.5f - 1.5f/16f, 0f, 0.5f - 1.5f/16f,
                        0.5f + 1.5f/16f, 0.5f, 0.5f + 1.5f/16f);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockChest.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicChest.java
similarity index 96%
rename from game/core/src/main/java/net/minecraft/core/block/BlockChest.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicChest.java
index 4dc99174e..c5ce4404e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockChest.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicChest.java
@@ -1,7 +1,6 @@
 package net.minecraft.core.block;
 
 import com.mojang.logging.LogUtils;
-import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityChest;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.Mob;
@@ -15,10 +14,11 @@ import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 
-public class BlockChest extends BlockTileEntity implements IPaintable {
+public class BlockLogicChest extends BlockLogic implements IPaintable {
 	private static final Logger LOGGER = LogUtils.getLogger();
-	public BlockChest(String key, String namespaceId, int id, Material material) {
-		super(key, namespaceId, id, material);
+	public BlockLogicChest(Block<?> block, Material material) {
+		super(block, material);
+		block.withEntity(TileEntityChest::new);
 	}
 	
 	@Override
@@ -270,7 +270,8 @@ public class BlockChest extends BlockTileEntity implements IPaintable {
 	}
 
 	public static boolean isChest(World world, int x, int y, int z) {
-		return Blocks.blocksList[world.getBlockId(x, y, z)] instanceof BlockChest;
+		Block<?> b;
+		return (b = Blocks.blocksList[world.getBlockId(x, y, z)]) != null && b.getLogic() instanceof BlockLogicChest;
 	}
 	
 	public static boolean isSingleChest(World world, int x, int y, int z) {
@@ -281,12 +282,7 @@ public class BlockChest extends BlockTileEntity implements IPaintable {
 		int meta = world.getBlockMetadata(x, y, z);
 		return isChest(world, x, y, z) && getTypeFromMeta(meta) == Type.SINGLE && getDirectionFromMeta(meta) == direction;
 	}
-	
-	@Override
-	protected TileEntity getNewBlockEntity() {
-		return new TileEntityChest();
-	}
-	
+
 	public void setDirection(World world, int x, int y, int z, Direction direction) {
 		if(isChest(world, x, y, z)) {
 			world.setBlockMetadataWithNotify(x, y, z, getMetaWithDirection(world.getBlockMetadata(x, y, z), direction));
@@ -412,12 +408,10 @@ public class BlockChest extends BlockTileEntity implements IPaintable {
 	@Override
 	public void setColor(World world, int x, int y, int z, DyeColor color) {
 		final int meta = world.getBlockMetadata(x, y, z);
-		world.setBlockAndMetadata(x, y, z, Blocks.CHEST_PLANKS_OAK_PAINTED.id, meta);
-		((IPaintable) Blocks.CHEST_PLANKS_OAK_PAINTED).setColor(world, x, y, z, color);
+		world.setBlockAndMetadata(x, y, z, Blocks.CHEST_PLANKS_OAK_PAINTED.id(), meta);
+		Blocks.CHEST_PLANKS_OAK_PAINTED.getLogic().setColor(world, x, y, z, color);
 	}
 
-	// Enum
-	
 	public enum Type{
 		
 		SINGLE, LEFT, RIGHT;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockChestLegacy.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicChestLegacy.java
similarity index 88%
rename from game/core/src/main/java/net/minecraft/core/block/BlockChestLegacy.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicChestLegacy.java
index e836d3f1f..6824d42a4 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockChestLegacy.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicChestLegacy.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.block;
 
 import net.minecraft.core.Global;
-import net.minecraft.core.block.BlockChest.Type;
+import net.minecraft.core.block.BlockLogicChest.Type;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityChest;
 import net.minecraft.core.block.material.Material;
@@ -13,10 +13,11 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
 @Deprecated
-public class BlockChestLegacy extends BlockTileEntity {
+public class BlockLogicChestLegacy extends BlockLogic {
 	
-	public BlockChestLegacy(String key, String namespaceId, int id) {
-		super(key, namespaceId, id, Material.wood);
+	public BlockLogicChestLegacy(Block<?> block) {
+		super(block, Material.wood);
+		block.withEntity(TileEntityChest::new);
 	}
 	
 	@Override
@@ -28,14 +29,9 @@ public class BlockChestLegacy extends BlockTileEntity {
 		else return null;
 	}
 
-	@Override
-	protected TileEntity getNewBlockEntity() {
-		return new TileEntityChest();
-	}
-	
 	public static boolean isLegacyChest(World world, int x, int y, int z) {
 		int id = world.getBlockId(x, y, z);
-		return id == Blocks.CHEST_LEGACY.id || id == Blocks.CHEST_LEGACY_PAINTED.id;
+		return id == Blocks.CHEST_LEGACY.id() || id == Blocks.CHEST_LEGACY_PAINTED.id();
 	}
 	
 	@Override
@@ -92,8 +88,8 @@ public class BlockChestLegacy extends BlockTileEntity {
 				facingDirection = Direction.SOUTH;
 			}
 			
-			meta = BlockChest.getMetaWithDirection(meta, facingDirection);
-			meta = BlockChest.getMetaWithType(meta, Type.SINGLE);
+			meta = BlockLogicChest.getMetaWithDirection(meta, facingDirection);
+			meta = BlockLogicChest.getMetaWithType(meta, Type.SINGLE);
 			
 			ItemStack[] items = getAndClearChestInventory(world, x, y, z);
 			
@@ -155,11 +151,11 @@ public class BlockChestLegacy extends BlockTileEntity {
 			if(type == Type.LEFT) otherType = Type.RIGHT;
 			if(type == Type.RIGHT) otherType = Type.LEFT;
 			
-			meta = BlockChest.getMetaWithDirection(meta, facingDirection);
-			meta = BlockChest.getMetaWithType(meta, type);
+			meta = BlockLogicChest.getMetaWithDirection(meta, facingDirection);
+			meta = BlockLogicChest.getMetaWithType(meta, type);
 			
-			otherMeta = BlockChest.getMetaWithDirection(otherMeta, facingDirection);
-			otherMeta = BlockChest.getMetaWithType(otherMeta, otherType);
+			otherMeta = BlockLogicChest.getMetaWithDirection(otherMeta, facingDirection);
+			otherMeta = BlockLogicChest.getMetaWithType(otherMeta, otherType);
 			
 			ItemStack[] items1 = getAndClearChestInventory(world, x, y, z);
 			ItemStack[] items2 = getAndClearChestInventory(world, otherChestX, y, otherChestZ);
@@ -206,15 +202,15 @@ public class BlockChestLegacy extends BlockTileEntity {
 		}
 		int legacyChestMeta = world.getBlockMetadata(x, y, z);
 		
-		Block oldBlock = world.getBlock(x, y, z);
-		Block newBlock = Blocks.CHEST_PLANKS_OAK;
+		Block<?> oldBlock = world.getBlock(x, y, z);
+		Block<?> newBlock = Blocks.CHEST_PLANKS_OAK;
 		
 		if(oldBlock == Blocks.CHEST_LEGACY_PAINTED) {
 			newBlock = Blocks.CHEST_PLANKS_OAK_PAINTED;
 			newMeta = newMeta | (legacyChestMeta << 4);
 		}
 		
-		world.setBlockAndMetadata(x, y, z, newBlock.id, newMeta);
+		world.setBlockAndMetadata(x, y, z, newBlock.id(), newMeta);
 		world.markBlockNeedsUpdate(x, y, z);
 	}
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockChestPainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicChestPainted.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockChestPainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicChestPainted.java
index af52439bc..208df8912 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockChestPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicChestPainted.java
@@ -10,10 +10,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockChestPainted extends BlockChest implements IPainted {
+public class BlockLogicChestPainted extends BlockLogicChest implements IPainted {
 
-	protected BlockChestPainted(String key, String namespaceId, int id, Material material) {
-		super(key, namespaceId, id, material);
+	protected BlockLogicChestPainted(Block<?> block, Material material) {
+		super(block, material);
 	}
 	
 	@Override
@@ -24,7 +24,7 @@ public class BlockChestPainted extends BlockChest implements IPainted {
 	@Override
 	public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity)
 	{
-		return new ItemStack[] { new ItemStack(this, 1, meta & colorBits) };
+		return new ItemStack[] { new ItemStack(block, 1, meta & colorBits) };
 	}
 
 	public static int getMetaForDyeColor(int i) {
@@ -52,7 +52,7 @@ public class BlockChestPainted extends BlockChest implements IPainted {
 	@Override
 	public void removeDye(World world, int x, int y, int z) {
 		final int meta = stripColorFromMetadata(world.getBlockMetadata(x, y, z));
-		world.setBlockAndMetadataWithNotify(x, y, z, Blocks.CHEST_PLANKS_OAK.id, meta);
+		world.setBlockAndMetadataWithNotify(x, y, z, Blocks.CHEST_PLANKS_OAK.id(), meta);
 	}
 
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockClay.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicClay.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockClay.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicClay.java
index 08450fcd8..80fdf5a54 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockClay.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicClay.java
@@ -7,11 +7,11 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 
-public class BlockClay extends Block
+public class BlockLogicClay extends BlockLogic
 {
-    public BlockClay(String key, String namespaceId, int id)
+    public BlockLogicClay(Block<?> block)
     {
-        super(key, namespaceId, id, Material.clay);
+        super(block, Material.clay);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockCobble.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCobble.java
similarity index 71%
rename from game/core/src/main/java/net/minecraft/core/block/BlockCobble.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicCobble.java
index 1120b9f60..11fed0797 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockCobble.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCobble.java
@@ -6,13 +6,14 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.IItemConvertible;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.function.Supplier;
 
-public class BlockCobble extends Block{
-    private final Supplier<IItemConvertible> crushDrop;
-    public BlockCobble(String translationKey, String namespaceId, int id, Material material, Supplier<IItemConvertible> crushResult) {
-        super(translationKey, namespaceId, id, material);
+public class BlockLogicCobble extends BlockLogic {
+    private final @Nullable Supplier<IItemConvertible> crushDrop;
+    public BlockLogicCobble(Block<?> block, Material material, @Nullable Supplier<IItemConvertible> crushResult) {
+        super(block, material);
         this.crushDrop = crushResult;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockCobweb.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCobweb.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/BlockCobweb.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicCobweb.java
index 011cb9eb7..d005361f8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockCobweb.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCobweb.java
@@ -10,12 +10,12 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockCobweb extends Block
+public class BlockLogicCobweb extends BlockLogic
 {
 
-    public BlockCobweb(String key, String namespaceId, int id, Material mat)
+    public BlockLogicCobweb(Block<?> block, Material mat)
     {
-        super(key, namespaceId, id, mat);
+        super(block, mat);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockCropsPumpkin.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCropsPumpkin.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/BlockCropsPumpkin.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicCropsPumpkin.java
index ce9e4d09d..78efd1aad 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockCropsPumpkin.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCropsPumpkin.java
@@ -14,10 +14,10 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockCropsPumpkin
-    extends BlockFlower implements IBonemealable {
-    public BlockCropsPumpkin(String key, String namespaceId, int id) {
-        super(key, namespaceId, id);
+public class BlockLogicCropsPumpkin
+    extends BlockLogicFlower implements IBonemealable {
+    public BlockLogicCropsPumpkin(Block<?> block) {
+        super(block);
     }
 
     @Override
@@ -42,7 +42,7 @@ public class BlockCropsPumpkin
 
     @Override
     protected boolean mayPlaceOn(int blockId) {
-        return blockId == Blocks.FARMLAND_DIRT.id;
+        return blockId == Blocks.FARMLAND_DIRT.id();
     }
 
     @Override
@@ -55,7 +55,7 @@ public class BlockCropsPumpkin
                 if (rand.nextInt((int) (100F / f)) == 0) {
                     meta++;
                     if (meta == 5) {
-                        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.PUMPKIN.id, 0);
+                        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.PUMPKIN.id(), 0);
                     } else {
                         world.setBlockMetadataWithNotify(x, y, z, meta);
                     }
@@ -65,7 +65,7 @@ public class BlockCropsPumpkin
     }
 
     public void fertilize(World world, int x, int y, int z) {
-        world.setBlockWithNotify(x, y, z, Blocks.PUMPKIN.id);
+        world.setBlockWithNotify(x, y, z, Blocks.PUMPKIN.id());
     }
 
     private float getGrowthRate(World world, int x, int y, int z) {
@@ -85,7 +85,7 @@ public class BlockCropsPumpkin
             for(int dz = z - 1; dz <= z + 1; dz++) {
                 int id = world.getBlockId(dx, y - 1, dz);
                 float growthRateMod = 0.0F;
-                if(id == Blocks.FARMLAND_DIRT.id) {
+                if(id == Blocks.FARMLAND_DIRT.id()) {
                     growthRateMod = 1.0F;
                     if(world.getBlockMetadata(dx, y - 1, dz) > 0) {
                         growthRateMod = 3F;
@@ -99,7 +99,7 @@ public class BlockCropsPumpkin
 
         }
 
-        boolean isFertilized = BlockFarmland.isFertilized(world.getBlockMetadata(x, y - 1, z));
+        boolean isFertilized = BlockLogicFarmland.isFertilized(world.getBlockMetadata(x, y - 1, z));
         if (!isFertilized) {
             if (world.getSeasonManager().getCurrentSeason() != null)
             {
@@ -130,7 +130,7 @@ public class BlockCropsPumpkin
         {
             if (!world.isClientSide)
             {
-                ((BlockCropsPumpkin)Blocks.CROPS_PUMPKIN).fertilize(world, blockX, blockY, blockZ);
+                fertilize(world, blockX, blockY, blockZ);
                 if (player == null || player.getGamemode().consumeBlocks())
                 {
                     itemstack.stackSize--;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockCropsWheat.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCropsWheat.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockCropsWheat.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicCropsWheat.java
index f0672224f..da7516505 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockCropsWheat.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicCropsWheat.java
@@ -13,14 +13,14 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockCropsWheat extends BlockFlower implements IBonemealable
+public class BlockLogicCropsWheat extends BlockLogicFlower implements IBonemealable
 {
     public static final int MASK_GROWTH = 0b0000_0111;
     public static final int MAX_GROWTH_STATE = 7;
-	public BlockCropsWheat(String key, String namespaceId, int id)
+	public BlockLogicCropsWheat(Block<?> block)
     {
-        super(key, namespaceId, id);
-        setTicking(true);
+        super(block);
+        block.setTicking(true);
         float f = 0.5F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.25F, 0.5F + f);
     }
@@ -28,7 +28,7 @@ public class BlockCropsWheat extends BlockFlower implements IBonemealable
 	@Override
 	public boolean mayPlaceOn(int blockId)
     {
-        return blockId == Blocks.FARMLAND_DIRT.id;
+        return blockId == Blocks.FARMLAND_DIRT.id();
     }
 
     @Override
@@ -66,16 +66,16 @@ public class BlockCropsWheat extends BlockFlower implements IBonemealable
         int idPosXNegZ = world.getBlockId(x + 1, y, z - 1);
         int idPosXPosZ = world.getBlockId(x + 1, y, z + 1);
         int idNegXPosZ = world.getBlockId(x - 1, y, z + 1);
-        boolean xNeighbor = idNegX == id || idPosX == id;
-        boolean zNeighbor = idNegZ == id || idPosZ == id;
-        boolean diagNeighbor = idNegXNegZ == id || idPosXNegZ == id || idPosXPosZ == id || idNegXPosZ == id;
+        boolean xNeighbor = idNegX == block.id() || idPosX == block.id();
+        boolean zNeighbor = idNegZ == block.id() || idPosZ == block.id();
+        boolean diagNeighbor = idNegXNegZ == block.id() || idPosXNegZ == block.id() || idPosXPosZ == block.id() || idNegXPosZ == block.id();
         for(int dx = x - 1; dx <= x + 1; dx++)
         {
             for(int dz = z - 1; dz <= z + 1; dz++)
             {
                 int id = world.getBlockId(dx, y - 1, dz);
                 float growthRateMod = 0.0F;
-                if(id == Blocks.FARMLAND_DIRT.id)
+                if(id == Blocks.FARMLAND_DIRT.id())
                 {
                     growthRateMod = 1.0F;
                     if(world.getBlockMetadata(dx, y - 1, dz) > 0)
@@ -96,7 +96,7 @@ public class BlockCropsWheat extends BlockFlower implements IBonemealable
             growthRate /= 2.0F;
         }
 
-        boolean isFertilized = BlockFarmland.isFertilized(world.getBlockMetadata(x, y - 1, z));
+        boolean isFertilized = BlockLogicFarmland.isFertilized(world.getBlockMetadata(x, y - 1, z));
         if (!isFertilized) {
             if (world.getSeasonManager().getCurrentSeason() != null)
             {
@@ -110,11 +110,11 @@ public class BlockCropsWheat extends BlockFlower implements IBonemealable
 
     @Override
     public void onBlockDestroyedByPlayer(World world, int x, int y, int z, Side side, int meta, Player player, Item item) {
-        boolean isFertilized = BlockFarmland.isFertilized(world.getBlockMetadata(x, y - 1, z));
+        boolean isFertilized = BlockLogicFarmland.isFertilized(world.getBlockMetadata(x, y - 1, z));
         if (isFertilized && !world.isClientSide) {
             boolean shouldDefertilize = world.rand.nextInt(3) == 2;
             if (shouldDefertilize) {
-                world.setBlockMetadata(x, y - 1, z, BlockFarmland.setFertilized(world.getBlockMetadata(x, y - 1, z), false));
+                world.setBlockMetadata(x, y - 1, z, BlockLogicFarmland.setFertilized(world.getBlockMetadata(x, y - 1, z), false));
             }
         }
     }
@@ -138,7 +138,7 @@ public class BlockCropsWheat extends BlockFlower implements IBonemealable
         {
             if(!world.isClientSide)
             {
-                ((BlockCropsWheat)Blocks.CROPS_WHEAT).fertilize(world, blockX, blockY, blockZ);
+                fertilize(world, blockX, blockY, blockZ);
                 if (player == null || player.getGamemode().consumeBlocks())
                 {
                     itemstack.stackSize--;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockDeadBush.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDeadBush.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockDeadBush.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicDeadBush.java
index acc5e698b..885ac09e7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockDeadBush.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDeadBush.java
@@ -6,12 +6,12 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 
-public class BlockDeadBush extends BlockFlower
+public class BlockLogicDeadBush extends BlockLogicFlower
 {
 
-	public BlockDeadBush(String key, String namespaceId, int id)
+	public BlockLogicDeadBush(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
         float f = 0.4F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.8F, 0.5F + f);
     }
@@ -19,7 +19,7 @@ public class BlockDeadBush extends BlockFlower
     @Override
 	public boolean mayPlaceOn(int blockId)
     {
-        return blockId == Blocks.SAND.id || blockId == Blocks.DIRT_SCORCHED.id;
+        return blockId == Blocks.SAND.id() || blockId == Blocks.DIRT_SCORCHED.id();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockDispenser.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDispenser.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockDispenser.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicDispenser.java
index cbac228c2..da7d5665b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockDispenser.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDispenser.java
@@ -2,7 +2,6 @@ package net.minecraft.core.block;
 
 import java.util.Random;
 
-import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityDispenser;
 import net.minecraft.core.entity.*;
 import net.minecraft.core.entity.player.Player;
@@ -16,12 +15,13 @@ import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 
-public class BlockDispenser extends BlockTileEntityVeryRotatable
+public class BlockLogicDispenser extends BlockLogicVeryRotatable
 {
     public static final int MASK_POWERED = 0b0000_1000;
-	public BlockDispenser(String key, String namespaceId, int id)
+	public BlockLogicDispenser(Block<?> block)
     {
-        super(key, namespaceId, id, Material.stone);
+        super(block, Material.stone);
+        block.withEntity(TileEntityDispenser::new);
     }
 
     @Override
@@ -46,7 +46,7 @@ public class BlockDispenser extends BlockTileEntityVeryRotatable
 
     private void dispenseItem(World world, int x, int y, int z, Random random)
     {
-        Direction direction = BlockTileEntityVeryRotatable.metaToDirection(world.getBlockMetadata(x, y, z));
+        Direction direction = BlockLogicVeryRotatable.metaToDirection(world.getBlockMetadata(x, y, z));
         int xOffset = direction.getOffsetX();
         int yOffset = direction.getOffsetY();
         int zOffset = direction.getOffsetZ();
@@ -108,7 +108,7 @@ public class BlockDispenser extends BlockTileEntityVeryRotatable
         int meta = world.getBlockMetadata(x, y, z);
         if(flag && (meta & MASK_POWERED) == 0)
         {
-            world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
             world.setBlockMetadata(x, y, z, meta | MASK_POWERED);
         } else if (!flag){
             world.setBlockMetadata(x, y, z, meta & ~MASK_POWERED);
@@ -121,10 +121,4 @@ public class BlockDispenser extends BlockTileEntityVeryRotatable
         dispenseItem(world, x, y, z, rand);
     }
 
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityDispenser();
-    }
-
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockDoor.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoor.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockDoor.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicDoor.java
index 2721ec5a1..2615e2e83 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockDoor.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoor.java
@@ -8,7 +8,6 @@ import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.DyeColor;
-import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.Item;
@@ -16,14 +15,13 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.tag.ItemTags;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
-import net.minecraft.core.util.phys.Vec3;
 import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockDoor extends Block implements IPaintable
+public class BlockLogicDoor extends BlockLogic implements IPaintable
 {
     public static final int MASK_ROTATION = 0b0000_0011;
     public static final int MASK_OPENED = 0b0000_0100;
@@ -34,9 +32,9 @@ public class BlockDoor extends Block implements IPaintable
     @Nullable
     public final Supplier<Item> droppedItem;
 	
-	public BlockDoor(String key, String namespaceId, int id, Material material, boolean isTop, boolean requireTool, @Nullable Supplier<Item> droppedItem)
+	public BlockLogicDoor(Block<?> block, Material material, boolean isTop, boolean requireTool, @Nullable Supplier<Item> droppedItem)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         this.isTop = isTop;
         this.requireTool = requireTool;
         this.droppedItem = droppedItem;
@@ -122,20 +120,22 @@ public class BlockDoor extends Block implements IPaintable
     @Override
     public boolean onBlockRightClicked(World world, int x, int y, int z, @Nullable Player player, Side side, double xPlaced, double yPlaced)
     {
-        if(blockMaterial == Material.metal || blockMaterial == Material.steel)
+        if(material == Material.metal || material == Material.steel)
         {
             return false;
         }
         int l = world.getBlockMetadata(x, y, z);
         if(isTop)
         {
-            if(Blocks.blocksList[world.getBlockId(x, y - 1, z)] instanceof BlockDoor)
+            Block<?> b;
+            if((b = Blocks.blocksList[world.getBlockId(x, y - 1, z)]) != null && b.getLogic() instanceof BlockLogicDoor)
             {
             	Blocks.blocksList[world.getBlockId(x, y - 1, z)].onBlockRightClicked(world, x, y - 1, z, player, side, xPlaced, yPlaced);
             }
             return true;
         }
-        if(Blocks.blocksList[world.getBlockId(x, y + 1, z)] instanceof BlockDoor)
+        Block<?> b;
+        if((b = Blocks.blocksList[world.getBlockId(x, y + 1, z)]) != null && b.getLogic() instanceof BlockLogicDoor)
         {
             world.setBlockMetadataWithNotify(x, y + 1, z, l ^ MASK_OPENED);
         }
@@ -158,9 +158,10 @@ public class BlockDoor extends Block implements IPaintable
         
         if(isTop)
         {
-            if(Blocks.blocksList[world.getBlockId(x, y - 1, z)] instanceof BlockDoor)
+            Block<?> b;
+            if((b = Blocks.blocksList[world.getBlockId(x, y - 1, z)]) != null && b.getLogic() instanceof BlockLogicDoor)
             {
-            	((BlockDoor)Blocks.blocksList[world.getBlockId(x, y - 1, z)]).onPoweredBlockChange(world, x, y - 1, z, isPowered);
+            	((BlockLogicDoor)b.getLogic()).onPoweredBlockChange(world, x, y - 1, z, isPowered);
             }
             return;
         }
@@ -169,7 +170,8 @@ public class BlockDoor extends Block implements IPaintable
         {
             return;
         }
-        if(Blocks.blocksList[world.getBlockId(x, y + 1, z)] instanceof BlockDoor)
+        Block<?> b;
+        if((b = Blocks.blocksList[world.getBlockId(x, y + 1, z)]) != null && b.getLogic() instanceof BlockLogicDoor)
         {
             world.setBlockMetadataWithNotify(x, y + 1, z, meta ^ MASK_OPENED);
         }
@@ -184,20 +186,20 @@ public class BlockDoor extends Block implements IPaintable
 //        int i1 = world.getBlockMetadata(x, y, z);
         if(isTop)
         {
-        	Block otherBlock = Blocks.blocksList[world.getBlockId(x, y - 1, z)];
-            if(!(otherBlock instanceof BlockDoor))
+        	Block<?> otherBlock = Blocks.blocksList[world.getBlockId(x, y - 1, z)];
+            if(!(otherBlock != null && otherBlock.getLogic() instanceof BlockLogicDoor))
             {
                 world.setBlockWithNotify(x, y, z, 0);
             }
-            if(blockId > 0 && Blocks.blocksList[blockId].isSignalSource())
+            if(otherBlock != null && blockId > 0 && Blocks.blocksList[blockId].isSignalSource())
             {
                 otherBlock.onNeighborBlockChange(world, x, y - 1, z, blockId);
             }
         } else
         {
             boolean flag = false;
-        	Block otherBlock = Blocks.blocksList[world.getBlockId(x, y + 1, z)];
-            if(!(otherBlock instanceof BlockDoor))
+        	Block<?> otherBlock = Blocks.blocksList[world.getBlockId(x, y + 1, z)];
+            if(!(otherBlock != null && otherBlock.getLogic() instanceof BlockLogicDoor))
             {
                 world.setBlockWithNotify(x, y, z, 0);
                 //dropBlockAsItem(world, i, j, k, i1);
@@ -208,7 +210,7 @@ public class BlockDoor extends Block implements IPaintable
                 dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
                 world.setBlockWithNotify(x, y, z, 0);
                 flag = true;
-                if(otherBlock instanceof BlockDoor)
+                if(otherBlock != null && otherBlock.getLogic() instanceof BlockLogicDoor)
                 {
                     world.setBlockWithNotify(x, y + 1, z, 0);
                 }
@@ -235,13 +237,13 @@ public class BlockDoor extends Block implements IPaintable
     	int myMetadata = world.getBlockMetadata(x, y, z);
     	int upId = world.getBlockId(x, y + 1, z);
     	
-    	if (myId == Blocks.DOOR_PLANKS_OAK_BOTTOM.id && upId == Blocks.DOOR_PLANKS_OAK_BOTTOM.id)
+    	if (myId == Blocks.DOOR_PLANKS_OAK_BOTTOM.id() && upId == Blocks.DOOR_PLANKS_OAK_BOTTOM.id())
     	{
-    		world.setBlockAndMetadata(x, y + 1, z, Blocks.DOOR_PLANKS_OAK_TOP.id, myMetadata);
+    		world.setBlockAndMetadata(x, y + 1, z, Blocks.DOOR_PLANKS_OAK_TOP.id(), myMetadata);
     	}
-    	else if (myId == Blocks.DOOR_IRON_BOTTOM.id && upId == Blocks.DOOR_IRON_BOTTOM.id)
+    	else if (myId == Blocks.DOOR_IRON_BOTTOM.id() && upId == Blocks.DOOR_IRON_BOTTOM.id())
     	{
-    		world.setBlockAndMetadata(x, y + 1, z, Blocks.DOOR_IRON_TOP.id, myMetadata);
+    		world.setBlockAndMetadata(x, y + 1, z, Blocks.DOOR_IRON_TOP.id(), myMetadata);
     	}
     }
 
@@ -299,22 +301,22 @@ public class BlockDoor extends Block implements IPaintable
 
     @Override
     public boolean canBePainted() {
-        return blockMaterial == Material.wood;
+        return material == Material.wood;
     }
 
     @Override
     public void setColor(World world, int x, int y, int z, DyeColor color) {
         final int meta = world.getBlockMetadata(x, y, z);
         if (isTop) {
-            world.setBlockAndMetadata(x, y, z, Blocks.DOOR_PLANKS_PAINTED_TOP.id, meta);
-            ((IPaintable) Blocks.DOOR_PLANKS_PAINTED_TOP).setColor(world, x, y, z, color);
-            world.setBlockAndMetadata(x, y - 1, z, Blocks.DOOR_PLANKS_PAINTED_BOTTOM.id, meta);
-            ((IPaintable) Blocks.DOOR_PLANKS_PAINTED_BOTTOM).setColor(world, x, y - 1, z, color);
+            world.setBlockAndMetadata(x, y, z, Blocks.DOOR_PLANKS_PAINTED_TOP.id(), meta);
+            Blocks.DOOR_PLANKS_PAINTED_TOP.getLogic().setColor(world, x, y, z, color);
+            world.setBlockAndMetadata(x, y - 1, z, Blocks.DOOR_PLANKS_PAINTED_BOTTOM.id(), meta);
+            Blocks.DOOR_PLANKS_PAINTED_BOTTOM.getLogic().setColor(world, x, y - 1, z, color);
         } else {
-            world.setBlockAndMetadata(x, y, z, Blocks.DOOR_PLANKS_PAINTED_BOTTOM.id, meta);
-            ((IPaintable) Blocks.DOOR_PLANKS_PAINTED_BOTTOM).setColor(world, x, y, z, color);
-            world.setBlockAndMetadata(x, y + 1, z, Blocks.DOOR_PLANKS_PAINTED_TOP.id, meta);
-            ((IPaintable) Blocks.DOOR_PLANKS_PAINTED_TOP).setColor(world, x, y + 1, z, color);
+            world.setBlockAndMetadata(x, y, z, Blocks.DOOR_PLANKS_PAINTED_BOTTOM.id(), meta);
+            Blocks.DOOR_PLANKS_PAINTED_BOTTOM.getLogic().setColor(world, x, y, z, color);
+            world.setBlockAndMetadata(x, y + 1, z, Blocks.DOOR_PLANKS_PAINTED_TOP.id(), meta);
+            Blocks.DOOR_PLANKS_PAINTED_TOP.getLogic().setColor(world, x, y + 1, z, color);
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockDoorPainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoorPainted.java
similarity index 81%
rename from game/core/src/main/java/net/minecraft/core/block/BlockDoorPainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicDoorPainted.java
index 08e27fca4..83cd8e844 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockDoorPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoorPainted.java
@@ -8,9 +8,9 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.world.World;
 
-public class BlockDoorPainted extends BlockDoor implements IPainted {
-    public BlockDoorPainted(String key, String namespaceId, int id, Material material, boolean isTop) {
-        super(key, namespaceId, id, material, isTop, false, null);
+public class BlockLogicDoorPainted extends BlockLogicDoor implements IPainted {
+    public BlockLogicDoorPainted(Block<?> block, Material material, boolean isTop) {
+        super(block, material, isTop, false, null);
     }
     @Override
     public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity)
@@ -36,11 +36,11 @@ public class BlockDoorPainted extends BlockDoor implements IPainted {
     @Override
     public void removeDye(World world, int x, int y, int z) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadataWithNotify(x, y, z, this.isTop ? Blocks.DOOR_PLANKS_OAK_TOP.id : Blocks.DOOR_PLANKS_OAK_BOTTOM.id, meta & 0xF);
+        world.setBlockAndMetadataWithNotify(x, y, z, this.isTop ? Blocks.DOOR_PLANKS_OAK_TOP.id() : Blocks.DOOR_PLANKS_OAK_BOTTOM.id(), meta & 0xF);
         if (this.isTop) {
-            world.setBlockAndMetadataWithNotify(x, y - 1, z, Blocks.DOOR_PLANKS_OAK_BOTTOM.id, meta & 0xF);
+            world.setBlockAndMetadataWithNotify(x, y - 1, z, Blocks.DOOR_PLANKS_OAK_BOTTOM.id(), meta & 0xF);
         } else {
-            world.setBlockAndMetadataWithNotify(x, y + 1, z, Blocks.DOOR_PLANKS_OAK_TOP.id, meta & 0xF);
+            world.setBlockAndMetadataWithNotify(x, y + 1, z, Blocks.DOOR_PLANKS_OAK_TOP.id(), meta & 0xF);
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockEdible.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicEdible.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockEdible.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicEdible.java
index b9eb9c8bf..bbea38fa9 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockEdible.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicEdible.java
@@ -12,19 +12,18 @@ import org.jetbrains.annotations.NotNull;
 
 import java.util.function.Supplier;
 
-public abstract class BlockEdible extends Block {
+public abstract class BlockLogicEdible extends BlockLogic {
     @NotNull
     private final Supplier<Item> itemSupplier;
     public int maxBites;
     public int healAmount;
 
-    public BlockEdible(String key, String namespaceId, int id, int maxBites, int healAmount, @NotNull Supplier<Item> dropItemSupplier)
+    public BlockLogicEdible(Block<?> block, int maxBites, int healAmount, @NotNull Supplier<Item> dropItemSupplier)
     {
-        super(key, namespaceId, id, Material.cake);
+        super(block, Material.cake);
         this.maxBites = maxBites;
         this.healAmount = healAmount;
         this.itemSupplier = dropItemSupplier;
-        setTicking(true);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFarmland.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFarmland.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFarmland.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFarmland.java
index baf6712e1..c7e699f21 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFarmland.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFarmland.java
@@ -18,16 +18,16 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockFarmland extends Block implements IBonemealable
+public class BlockLogicFarmland extends BlockLogic implements IBonemealable
 {
 	public static final int MASK_FERTILIZED = 0b0001_0000;
 	public static final int MASK_WET = 0b0000_1111;
-	public BlockFarmland(String key, String namespaceId, int id)
+	public BlockLogicFarmland(Block<?> block)
 	{
-		super(key, namespaceId, id, Material.dirt);
+		super(block, Material.dirt);
 		setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.9375F, 1.0F);
-		withLightBlock(255);
-		setTicking(true);
+		block.withLightBlock(255);
+		block.setTicking(true);
 	}
 
 	public static boolean isWet(int data) {
@@ -101,7 +101,7 @@ public class BlockFarmland extends Block implements IBonemealable
 		{
 			for (int iz = z - radius; iz <= z + radius; iz++)
 			{
-				if (world.getBlockId(ix, y + 1, iz) == Blocks.CROPS_WHEAT.id)
+				if (world.getBlockId(ix, y + 1, iz) == Blocks.CROPS_WHEAT.id())
 				{
 					return true;
 				}
@@ -126,7 +126,7 @@ public class BlockFarmland extends Block implements IBonemealable
 			{
 				for (int z1 = z - range; z1 <= z + range; z1++)
 				{
-					if (Block.hasTag(world.getBlockId(x1, y1, z1), BlockTags.IS_WATER))
+					if (Blocks.hasTag(world.getBlockId(x1, y1, z1), BlockTags.IS_WATER))
 					{
 						return true;
 					}
@@ -149,9 +149,9 @@ public class BlockFarmland extends Block implements IBonemealable
 					return;
 				}
 				if(isWet(world.getBlockMetadata(x, y, z)))
-					world.setBlockWithNotify(x, y, z, Blocks.MUD.id);
+					world.setBlockWithNotify(x, y, z, Blocks.MUD.id());
 				else
-					world.setBlockWithNotify(x, y, z, Blocks.DIRT.id);
+					world.setBlockWithNotify(x, y, z, Blocks.DIRT.id());
 
 			}
 		}
@@ -160,7 +160,7 @@ public class BlockFarmland extends Block implements IBonemealable
 	@Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
 	{
-		world.scheduleBlockUpdate(x, y, z, id, tickDelay() - world.rand.nextInt(10) + world.rand.nextInt(10));
+		world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay() - world.rand.nextInt(10) + world.rand.nextInt(10));
 	}
 
 	@Override
@@ -171,12 +171,12 @@ public class BlockFarmland extends Block implements IBonemealable
 		if (material.isSolid() && material != Material.vegetable)
 		{
 			if(isWet(world.getBlockMetadata(x, y, z)))
-				world.setBlockWithNotify(x, y, z, Blocks.MUD.id);
+				world.setBlockWithNotify(x, y, z, Blocks.MUD.id());
 			else
-				world.setBlockWithNotify(x, y, z, Blocks.DIRT.id);
+				world.setBlockWithNotify(x, y, z, Blocks.DIRT.id());
 
 		} else {
-			world.scheduleBlockUpdate(x, y, z, id, tickDelay() - world.rand.nextInt(10) + world.rand.nextInt(10));
+			world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay() - world.rand.nextInt(10) + world.rand.nextInt(10));
 		}
 	}
 
@@ -196,7 +196,7 @@ public class BlockFarmland extends Block implements IBonemealable
 					{
 						//...And the block is next to another wet mud block, it can become wet
 						int bID = world.getBlockId(x1, y1, z1);
-						if (bID == Blocks.MUD.id || (bID == Blocks.FARMLAND_DIRT.id && BlockFarmland.isWet(world.getBlockMetadata(x1, y1, z1))))
+						if (bID == Blocks.MUD.id() || (bID == Blocks.FARMLAND_DIRT.id() && BlockLogicFarmland.isWet(world.getBlockMetadata(x1, y1, z1))))
 						{
 							return true;
 						}
@@ -217,7 +217,7 @@ public class BlockFarmland extends Block implements IBonemealable
 	@Override
 	public void updateTick(final World world, final int x, final int y, final int z, final Random rand) {
 		if (rand.nextInt(2) != 0) {
-			world.scheduleBlockUpdate(x, y, z, id, tickDelay() - rand.nextInt(10) + rand.nextInt(10));
+			world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay() - rand.nextInt(10) + rand.nextInt(10));
 			return;
 		}
 		int data = world.getBlockMetadata(x, y, z);
@@ -225,14 +225,14 @@ public class BlockFarmland extends Block implements IBonemealable
 		if (isWaterNearby(world, x, y, z, 4) || world.canBlockBeRainedOn(x, y + 1, z)) {
 			if (hydration < 15 && canBecomeWet(world, x, y, z)) {
 				world.setBlockMetadataWithNotify(x, y, z, setWet(data, hydration + 1));
-				world.scheduleBlockUpdate(x, y, z, id, tickDelay() - rand.nextInt(10) + rand.nextInt(10));
+				world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay() - rand.nextInt(10) + rand.nextInt(10));
 			}
 		} else {
 			if (hydration > 0) {
 				world.setBlockMetadataWithNotify(x, y, z, setWet(data, hydration - 1));
-				world.scheduleBlockUpdate(x, y, z, id, tickDelay() - rand.nextInt(10) + rand.nextInt(10));
+				world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay() - rand.nextInt(10) + rand.nextInt(10));
 			} else if (!isCropsNearby(world, x, y, z)) {
-				world.setBlockWithNotify(x, y, z, Blocks.DIRT.id);
+				world.setBlockWithNotify(x, y, z, Blocks.DIRT.id());
 			}
 		}
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFence.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFence.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFence.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFence.java
index a57893b55..b7423fbfc 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFence.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFence.java
@@ -7,7 +7,7 @@ import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockFence extends Block implements IPaintable
+public class BlockLogicFence extends BlockLogic implements IPaintable
 {
 //    private static final List<BoundingVolume> selectionVolumes = new ArrayList<>();
 //
@@ -53,9 +53,9 @@ public class BlockFence extends Block implements IPaintable
 //        selectionVolumes.add(newVolume);
 //    }
 
-    public BlockFence(String key, String namespaceId, int id)
+    public BlockLogicFence(Block<?> block)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
     }
 
     @Override
@@ -110,15 +110,15 @@ public class BlockFence extends Block implements IPaintable
         return false;
     }
 
-    public boolean canConnectTo(WorldSource iblockaccess, int x, int y, int z)
+    public boolean canConnectTo(WorldSource worldSource, int x, int y, int z)
     {
-        int l = iblockaccess.getBlockId(x, y, z);
-        return Block.hasTag(l, BlockTags.FENCES_CONNECT);
+        int l = worldSource.getBlockId(x, y, z);
+        return Blocks.hasTag(l, BlockTags.FENCES_CONNECT);
     }
 
     @Override
     public void setColor(World world, int x, int y, int z, DyeColor color) {
-        world.setBlock(x, y, z, Blocks.FENCE_PLANKS_OAK_PAINTED.id);
-        ((IPaintable) Blocks.FENCE_PLANKS_OAK_PAINTED).setColor(world, x, y, z, color);
+        world.setBlock(x, y, z, Blocks.FENCE_PLANKS_OAK_PAINTED.id());
+        Blocks.FENCE_PLANKS_OAK_PAINTED.getLogic().setColor(world, x, y, z, color);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFenceChainlink.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceChainlink.java
similarity index 50%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFenceChainlink.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceChainlink.java
index 82ccb045a..49f58ab89 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFenceChainlink.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceChainlink.java
@@ -5,18 +5,18 @@ import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockFenceChainlink extends BlockFenceThin
+public class BlockLogicFenceChainlink extends BlockLogicFenceThin
 {
-    public BlockFenceChainlink(String key, String namespaceId, int id, Material material)
+    public BlockLogicFenceChainlink(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
     }
 
     @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) || (Blocks.blocksList[id] != null && (Blocks.blocksList[id].blockMaterial.isStone() || Blocks.blocksList[id].blockMaterial.isMetal()));
+        Block<?> b = world.getBlock(x, y, z);
+        return BlockTags.CHAINLINK_FENCES_CONNECT.appliesTo(b) || (b != null && (b.getMaterial().isStone() || b.getMaterial().isMetal()));
     }
     
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFenceGate.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceGate.java
similarity index 93%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFenceGate.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceGate.java
index 75b791a04..4812453c2 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFenceGate.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceGate.java
@@ -17,14 +17,14 @@ import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockFenceGate extends Block implements IPaintable
+public class BlockLogicFenceGate extends BlockLogic implements IPaintable
 {
     public static final int MASK_DIRECTION = 0b0000_0011;
     public static final int MASK_OPEN = 0b0000_0100;
 
-    public BlockFenceGate(String key, String namespaceId, int id)
+    public BlockLogicFenceGate(Block<?> block)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
     }
 
     @Override
@@ -142,7 +142,7 @@ public class BlockFenceGate extends Block implements IPaintable
     @Override
     public void setColor(World world, int x, int y, int z, DyeColor color) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadata(x, y, z, Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id, meta);
-        ((IPaintable) Blocks.FENCE_GATE_PLANKS_OAK_PAINTED).setColor(world, x, y, z, color);
+        world.setBlockAndMetadata(x, y, z, Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id(), meta);
+        Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.getLogic().setColor(world, x, y, z, color);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFenceGatePainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceGatePainted.java
similarity index 87%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFenceGatePainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceGatePainted.java
index ec37c65b9..90bd3a410 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFenceGatePainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceGatePainted.java
@@ -9,12 +9,12 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockFenceGatePainted extends BlockFenceGate implements IPainted
+public class BlockLogicFenceGatePainted extends BlockLogicFenceGate implements IPainted
 {
 	public static final int MASK_COLOR = 0b1111_0000;
-	public BlockFenceGatePainted(String key, String namespaceId, int id)
+	public BlockLogicFenceGatePainted(Block<?> block)
 	{
-		super(key, namespaceId, id);
+		super(block);
 	}
 	
 	@Override
@@ -46,7 +46,7 @@ public class BlockFenceGatePainted extends BlockFenceGate implements IPainted
 	@Override
 	public void removeDye(World world, int x, int y, int z) {
 		final int meta = world.getBlockMetadata(x, y, z);
-		world.setBlockAndMetadataWithNotify(x, y, z, Blocks.FENCE_GATE_PLANKS_OAK.id, meta & ~MASK_COLOR);
+		world.setBlockAndMetadataWithNotify(x, y, z, Blocks.FENCE_GATE_PLANKS_OAK.id(), meta & ~MASK_COLOR);
 	}
 
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFencePainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFencePainted.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFencePainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFencePainted.java
index 8bb402d15..929bc64b8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFencePainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFencePainted.java
@@ -9,11 +9,11 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockFencePainted extends BlockFence implements IPainted
+public class BlockLogicFencePainted extends BlockLogicFence implements IPainted
 {
-	public BlockFencePainted(String key, String namespaceId, int id)
+	public BlockLogicFencePainted(Block<?> block)
 	{
-		super(key, namespaceId, id);
+		super(block);
 	}
 	
 	@Override
@@ -44,7 +44,7 @@ public class BlockFencePainted extends BlockFence implements IPainted
 
 	@Override
 	public void removeDye(World world, int x, int y, int z) {
-		world.setBlockWithNotify(x, y, z, Blocks.FENCE_PLANKS_OAK.id);
+		world.setBlockWithNotify(x, y, z, Blocks.FENCE_PLANKS_OAK.id());
 	}
 
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceSteel.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceSteel.java
new file mode 100644
index 000000000..1b3f4f2fd
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceSteel.java
@@ -0,0 +1,17 @@
+package net.minecraft.core.block;
+
+import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.world.WorldSource;
+
+public class BlockLogicFenceSteel extends BlockLogicFenceThin {
+    public BlockLogicFenceSteel(Block<?> block, Material material) {
+        super(block, material);
+    }
+
+    @Override
+    public boolean canConnectTo(WorldSource world, int x, int y, int z) {
+        Block<?> block = world.getBlock(x, y, z);
+        return BlockTags.CHAINLINK_FENCES_CONNECT.appliesTo(block) || (block != null && (block.getMaterial().isStone() || block.getMaterial().isMetal()));
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFenceThin.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceThin.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFenceThin.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceThin.java
index 3cb49d597..7306274d1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFenceThin.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceThin.java
@@ -5,11 +5,11 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public abstract class BlockFenceThin extends Block
+public abstract class BlockLogicFenceThin extends BlockLogic
 {
-    public BlockFenceThin(String key, String namespaceId, int id, Material material)
+    public BlockLogicFenceThin(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
     }
 
     @Override
@@ -47,14 +47,14 @@ public abstract class BlockFenceThin extends Block
         if (drawColumn) return true;
 
         int oy = 1;
-        while (world.getBlockId(x, y + oy, z) == this.id)
+        while (world.getBlockId(x, y + oy, z) == block.id())
         {
             oy++;
         }
         oy--;
 
         boolean drawColumnFromOther = false;
-        while (world.getBlockId(x, y + oy, z) == this.id)
+        while (world.getBlockId(x, y + oy, z) == block.id())
         {
             if (shouldDrawColumn_do(world, x, y + oy, z))
             {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFenceWallPaper.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceWallPaper.java
similarity index 57%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFenceWallPaper.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceWallPaper.java
index d8b13eab3..a8fa39226 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFenceWallPaper.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFenceWallPaper.java
@@ -4,17 +4,17 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockFenceWallPaper extends BlockFenceThin
+public class BlockLogicFenceWallPaper extends BlockLogicFenceThin
 {
-    public BlockFenceWallPaper(String key, String namespaceId, int id, Material material)
+    public BlockLogicFenceWallPaper(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
     }
 
     @Override
     public boolean canConnectTo(WorldSource world, int x, int y, int z)
     {
         int l = world.getBlockId(x, y, z);
-        return Block.hasTag(l, BlockTags.FENCES_CONNECT);
+        return Blocks.hasTag(l, BlockTags.FENCES_CONNECT);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFire.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java
similarity index 78%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFire.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java
index 9158324f7..03e988a02 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFire.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java
@@ -13,7 +13,7 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockFire extends Block {
+public class BlockLogicFire extends BlockLogic {
 	public static final int FLAME_INSTANT = 60;
 	public static final int FLAME_EASY = 30;
 	public static final int FLAME_MEDIUM = 15;
@@ -26,9 +26,9 @@ public class BlockFire extends Block {
 	private static final int[] flameChance = new int[Blocks.blocksList.length];
 	private static final int[] burnChance = new int[Blocks.blocksList.length];
 
-	public BlockFire(String key, String namespaceId, int id) {
-		super(key, namespaceId, id, Material.fire);
-		setTicking(true);
+	public BlockLogicFire(Block<?> block) {
+		super(block, Material.fire);
+		block.setTicking(true);
 		setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
 	}
 
@@ -40,40 +40,40 @@ public class BlockFire extends Block {
 
 	@Override
 	public void initializeBlock() {
-		setFlammable(Blocks.PLANKS_OAK.id, FLAME_HARD, BURN_MEDIUM);
-		setFlammable(Blocks.PLANKS_OAK_PAINTED.id, FLAME_HARD, BURN_MEDIUM);
-		setFlammable(Blocks.FENCE_PLANKS_OAK.id, FLAME_HARD, BURN_MEDIUM);
-		setFlammable(Blocks.FENCE_PLANKS_OAK_PAINTED.id, FLAME_HARD, BURN_MEDIUM);
-		setFlammable(Blocks.SLAB_PLANKS_OAK.id, FLAME_HARD, BURN_MEDIUM);
-		setFlammable(Blocks.SLAB_PLANKS_PAINTED.id, FLAME_HARD, BURN_MEDIUM);
-		setFlammable(Blocks.STAIRS_PLANKS_OAK.id, FLAME_HARD, BURN_MEDIUM);
-		setFlammable(Blocks.LOG_OAK.id, FLAME_HARD, BURN_HARD);
-		setFlammable(Blocks.LOG_PINE.id, FLAME_HARD, BURN_HARD);
-		setFlammable(Blocks.LOG_BIRCH.id, FLAME_HARD, BURN_HARD);
-		setFlammable(Blocks.LOG_CHERRY.id, FLAME_HARD, BURN_HARD);
-		setFlammable(Blocks.LOG_OAK_MOSSY.id, FLAME_HARD, BURN_HARD);
-		setFlammable(Blocks.LOG_EUCALYPTUS.id, FLAME_HARD, BURN_HARD);
-		setFlammable(Blocks.LEAVES_OAK.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_PINE.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_BIRCH.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_CHERRY.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_CHERRY_FLOWERING.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_OAK_RETRO.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_SHRUB.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_EUCALYPTUS.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.LEAVES_CACAO.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.BOOKSHELF_PLANKS_OAK.id, FLAME_EASY, BURN_MEDIUM);
-		setFlammable(Blocks.TNT.id, FLAME_MEDIUM, BURN_INSTANT);
-		setFlammable(Blocks.WOOL.id, FLAME_EASY, BURN_EASY);
-		setFlammable(Blocks.MOSS_STONE.id, 100, 30);
-		setFlammable(Blocks.MOSS_BASALT.id, 100, 30);
-		setFlammable(Blocks.MOSS_LIMESTONE.id, 100, 30);
-		setFlammable(Blocks.MOSS_GRANITE.id, 100, 30);
+		setFlammable(Blocks.PLANKS_OAK, FLAME_HARD, BURN_MEDIUM);
+		setFlammable(Blocks.PLANKS_OAK_PAINTED, FLAME_HARD, BURN_MEDIUM);
+		setFlammable(Blocks.FENCE_PLANKS_OAK, FLAME_HARD, BURN_MEDIUM);
+		setFlammable(Blocks.FENCE_PLANKS_OAK_PAINTED, FLAME_HARD, BURN_MEDIUM);
+		setFlammable(Blocks.SLAB_PLANKS_OAK, FLAME_HARD, BURN_MEDIUM);
+		setFlammable(Blocks.SLAB_PLANKS_PAINTED, FLAME_HARD, BURN_MEDIUM);
+		setFlammable(Blocks.STAIRS_PLANKS_OAK, FLAME_HARD, BURN_MEDIUM);
+		setFlammable(Blocks.LOG_OAK, FLAME_HARD, BURN_HARD);
+		setFlammable(Blocks.LOG_PINE, FLAME_HARD, BURN_HARD);
+		setFlammable(Blocks.LOG_BIRCH, FLAME_HARD, BURN_HARD);
+		setFlammable(Blocks.LOG_CHERRY, FLAME_HARD, BURN_HARD);
+		setFlammable(Blocks.LOG_OAK_MOSSY, FLAME_HARD, BURN_HARD);
+		setFlammable(Blocks.LOG_EUCALYPTUS, FLAME_HARD, BURN_HARD);
+		setFlammable(Blocks.LEAVES_OAK, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_PINE, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_BIRCH, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_CHERRY, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_CHERRY_FLOWERING, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_OAK_RETRO, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_SHRUB, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_EUCALYPTUS, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.LEAVES_CACAO, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.BOOKSHELF_PLANKS_OAK, FLAME_EASY, BURN_MEDIUM);
+		setFlammable(Blocks.TNT, FLAME_MEDIUM, BURN_INSTANT);
+		setFlammable(Blocks.WOOL, FLAME_EASY, BURN_EASY);
+		setFlammable(Blocks.MOSS_STONE, 100, 30);
+		setFlammable(Blocks.MOSS_BASALT, 100, 30);
+		setFlammable(Blocks.MOSS_LIMESTONE, 100, 30);
+		setFlammable(Blocks.MOSS_GRANITE, 100, 30);
 	}
 
-	public static void setFlammable(int id, int flameChance, int burnChance) {
-		BlockFire.flameChance[id] = flameChance;
-		BlockFire.burnChance[id] = burnChance;
+	public static void setFlammable(Block<?> block, int flameChance, int burnChance) {
+		BlockLogicFire.flameChance[block.id()] = flameChance;
+		BlockLogicFire.burnChance[block.id()] = burnChance;
 	}
 
 	@Override
@@ -111,7 +111,7 @@ public class BlockFire extends Block {
 
 	@Override
 	public void updateTick(World world, int x, int y, int z, Random rand) {
-		Block blockUnder = world.getBlock(x, y - 1, z);
+		Block<?> blockUnder = world.getBlock(x, y - 1, z);
 		boolean infiniBurn = blockUnder != null && blockUnder.hasTag(BlockTags.INFINITE_BURN) || !world.getGameRuleValue(GameRules.DO_FIRE_SPREAD);
 
 		//Extinguish fire
@@ -134,7 +134,7 @@ public class BlockFire extends Block {
 		if (meta < 15) {
 			world.setBlockMetadata(x, y, z, meta + rand.nextInt(3) / 2);
 		}
-		world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+		world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
 		
 		
 		if (!infiniBurn && !canNeighborCatchFire(world, x, y, z)) {
@@ -185,7 +185,7 @@ public class BlockFire extends Block {
 					
 					if(world.getGameRuleValue(GameRules.DO_FIRE_SPREAD) && getBurnResultId(world, x1, y1, z1) == 0 /* Fix for fire destroying moss blocks */) {
 						//Spread Fire with higher meta
-						world.setBlockAndMetadataWithNotify(x1, y1, z1, id, Math.min(meta + rand.nextInt(5) / 4, 15));
+						world.setBlockAndMetadataWithNotify(x1, y1, z1, block.id(), Math.min(meta + rand.nextInt(5) / 4, 15));
 					}
 				}
 
@@ -198,20 +198,19 @@ public class BlockFire extends Block {
 	private void checkBurn(World world, int x, int y, int z, int chance, Random random, int meta) {
 		if (!world.getGameRuleValue(GameRules.DO_FIRE_SPREAD)) return;
 		if (random.nextInt(chance) < burnChance[world.getBlockId(x, y, z)]) {
-			boolean isTNT = world.getBlockId(x, y, z) == Blocks.TNT.id;
+			boolean isTNT = world.getBlockId(x, y, z) == Blocks.TNT.id();
 			
 			if (random.nextInt(meta + 10) < 5 && !world.canBlockBeRainedOn(x, y, z)) {
 				if(getBurnResultId(world, x, y, z) == 0 /* Fix for fire destroying moss blocks */) {
 					//Spread Fire with higher meta
-					world.setBlockAndMetadataWithNotify(x, y, z, id, Math.min(meta + random.nextInt(5) / 4, 15));
+					world.setBlockAndMetadataWithNotify(x, y, z, block.id(), Math.min(meta + random.nextInt(5) / 4, 15));
 				}
 			} else {
 				setBurnResult(world, x, y, z);
 			}
 			
 			if (isTNT) {
-				BlockTNT TNTBlock = (BlockTNT) Blocks.TNT;
-				TNTBlock.ignite(world, x, y, z, true);
+				Blocks.TNT.getLogic().ignite(world, x, y, z, true);
 			}
 		}
 	}
@@ -271,23 +270,22 @@ public class BlockFire extends Block {
 
 	protected int getBurnResultId(World world, int x, int y, int z) {
 		int id = world.getBlockId(x, y, z);
-		Block stoneBlock = BlockMoss.getStoneBlock(id);
+		Block<?> stoneBlock = BlockLogicMoss.getStoneBlock(id);
 		if (stoneBlock != null) {
-			return stoneBlock.id;
+			return stoneBlock.id();
 		}
 		return 0;
 	}
 
 	@Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z) {
-		if (world.getBlockId(x, y - 1, z) == Blocks.OBSIDIAN.id
-				&& ((BlockPortal) Blocks.PORTAL_NETHER).tryToCreatePortal(world, x, y, z, null)) {
+		if (world.getBlockId(x, y - 1, z) == Blocks.OBSIDIAN.id() && Blocks.PORTAL_NETHER.getLogic().tryToCreatePortal(world, x, y, z, null)) {
 			return;
 		}
 		if (!world.isBlockNormalCube(x, y - 1, z) && !canNeighborCatchFire(world, x, y, z)) {
 			world.setBlockWithNotify(x, y, z, getBurnResultId(world, x, y, z));
 		} else {
-			world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+			world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
 		}
 	}
 	public void ignite(final World world, final int x, final int y, final int z) {
@@ -311,16 +309,16 @@ public class BlockFire extends Block {
 			hasCreatedFire = this.tryIgnite(world, x, y - 1, z);
 		}
 		if (!hasCreatedFire) {
-			world.setBlock(x, y, z, Blocks.FIRE.id);
+			world.setBlock(x, y, z, Blocks.FIRE.id());
 		}
 	}
 	private boolean tryIgnite(final World world, final int x, final int y, final int z) {
 		final int tile = world.getBlockId(x, y, z);
-		if (tile == Blocks.FIRE.id) {
+		if (tile == Blocks.FIRE.id()) {
 			return true;
 		}
 		if (tile == 0) {
-			world.setBlock(x, y, z, Blocks.FIRE.id);
+			world.setBlock(x, y, z, Blocks.FIRE.id());
 			return true;
 		}
 		return false;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFlag.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlag.java
similarity index 83%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFlag.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFlag.java
index 92c2be5e1..a6c5498cd 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFlag.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlag.java
@@ -14,13 +14,14 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockFlag extends BlockTileEntity {
+public class BlockLogicFlag extends BlockLogic {
 
-    public BlockFlag(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
+    public BlockLogicFlag(Block<?> block, Material material) {
+        super(block, material);
         float f = 2 / 16f;
         float f1 = 1.0F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f1, 0.5F + f);
+        block.withEntity(TileEntityFlag::new);
     }
 
     @Override
@@ -74,16 +75,4 @@ public class BlockFlag extends BlockTileEntity {
     public int getPistonPushReaction(World world, int x, int y, int z) {
         return Material.PISTON_DESTROY_ON_PUSH;
     }
-
-    @Override
-    protected TileEntity getNewBlockEntity() {
-        try
-        {
-            return new TileEntityFlag();
-        }
-        catch(Exception exception)
-        {
-            throw new RuntimeException(exception);
-        }
-    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFlower.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlower.java
similarity index 92%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFlower.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFlower.java
index 8aff9ab5d..b50711c11 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFlower.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlower.java
@@ -15,25 +15,25 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockFlower extends Block implements IBonemealable {
+public class BlockLogicFlower extends BlockLogic implements IBonemealable {
     public static final int MASK_PERMANENT = 0b1000_0000;
 
     public boolean killedByWeather = false;
     public boolean canBeBonemealed = false;
 
-    public BlockFlower(String key, String namespaceId, int id) {
-        super(key, namespaceId, id, Material.plant);
-        setTicking(true);
+    public BlockLogicFlower(Block<?> block) {
+        super(block, Material.plant);
+        block.setTicking(true);
         float f = 0.2F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 3F, 0.5F + f);
     }
 
-    public BlockFlower setKilledByWeather() {
+    public BlockLogicFlower setKilledByWeather() {
         killedByWeather = true;
         return this;
     }
 
-    public BlockFlower setBonemealable() {
+    public BlockLogicFlower setBonemealable() {
         canBeBonemealed = true;
         return this;
     }
@@ -129,7 +129,7 @@ public class BlockFlower extends Block implements IBonemealable {
                     continue;
                 }
                 if (rand.nextFloat() > 0.75) {
-                    world.setBlockWithNotify(k1, l1, i2, id);
+                    world.setBlockWithNotify(k1, l1, i2, block.id());
                 }
             }
             return true;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFlowerStackable.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlowerStackable.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFlowerStackable.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFlowerStackable.java
index a5f24c6f8..7dd71a5a9 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFlowerStackable.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlowerStackable.java
@@ -12,13 +12,13 @@ import org.jetbrains.annotations.Nullable;
 /**
  * Represents a flower block that can store multiple flowers within itself, up to a maximum of 4.
  */
-public class BlockFlowerStackable extends BlockFlower {
+public class BlockLogicFlowerStackable extends BlockLogicFlower {
     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 BlockFlowerStackable(String key, String namespaceId, int id) {
-        super(key, namespaceId, id);
+    public BlockLogicFlowerStackable(Block<?> block) {
+        super(block);
     }
 
     @Override
@@ -49,13 +49,13 @@ public class BlockFlowerStackable extends BlockFlower {
         }
 
         final ItemStack heldItem = player.getHeldItem();
-        if (heldItem == null || heldItem.stackSize < 1 || heldItem.getItem().id != this.id) {
+        if (heldItem == null || heldItem.stackSize < 1 || heldItem.getItem().id != block.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);
+        world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, block, EnumBlockSoundEffectType.PLACE);
         heldItem.consumeItem(player);
         return true;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFluid.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java
similarity index 86%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFluid.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java
index 86a1cf1a6..5d61e5660 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFluid.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java
@@ -15,14 +15,14 @@ import net.minecraft.core.world.WorldSource;
 
 import java.util.Random;
 
-public abstract class BlockFluid extends Block
+public abstract class BlockLogicFluid extends BlockLogic
 {
 
-	public BlockFluid(String key, String namespaceId, int id, Material material)
+	public BlockLogicFluid(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
-        setTicking(true);
+        block.setTicking(true);
     }
 
     public static float getWaterVolume(int data)
@@ -37,7 +37,7 @@ public abstract class BlockFluid extends Block
 
     protected int getDepth(WorldSource world, int x, int y, int z)
     {
-        if(world.getBlockMaterial(x, y, z) != blockMaterial)
+        if(world.getBlockMaterial(x, y, z) != material)
         {
             return -1;
         }
@@ -49,7 +49,7 @@ public abstract class BlockFluid extends Block
 
     protected int getRenderedDepth(WorldSource blockAccess, int x, int y, int z)
     {
-        if (blockAccess.getBlockMaterial(x, y, z) != blockMaterial)
+        if (blockAccess.getBlockMaterial(x, y, z) != material)
         {
             return -1;
         }
@@ -83,7 +83,7 @@ public abstract class BlockFluid extends Block
     public boolean getIsBlockSolid(WorldSource blockAccess, int x, int y, int z, Side side)
     {
         Material material = blockAccess.getBlockMaterial(x, y, z);
-        if(material == blockMaterial)
+        if(material == this.material)
         {
             return false;
         }
@@ -170,11 +170,11 @@ public abstract class BlockFluid extends Block
     @Override
     public int tickDelay()
     {
-        if(blockMaterial == Material.water)
+        if(material == Material.water)
         {
             return 5;
         }
-        return blockMaterial != Material.lava ? 0 : 30;
+        return material != Material.lava ? 0 : 30;
     }
 
     @Override
@@ -194,7 +194,7 @@ public abstract class BlockFluid extends Block
     @Override
     public void animationTick(World world, int x, int y, int z, Random rand)
     {
-        if(blockMaterial == Material.water && rand.nextInt(64) == 0)
+        if(material == Material.water && rand.nextInt(64) == 0)
         {
             int data = world.getBlockMetadata(x, y, z) & 0x0F;
             if(data > 0 && data < 8)
@@ -202,7 +202,7 @@ public abstract class BlockFluid extends Block
                 world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F, "liquid.water", rand.nextFloat() * 0.25F + 0.75F, rand.nextFloat() * 1.0F + 0.5F);
             }
         }
-        if(blockMaterial == Material.lava && world.getBlockMaterial(x, y + 1, z) == Material.air && !world.isBlockOpaqueCube(x, y + 1, z) && rand.nextInt(100) == 0)
+        if(material == Material.lava && world.getBlockMaterial(x, y + 1, z) == Material.air && !world.isBlockOpaqueCube(x, y + 1, z) && rand.nextInt(100) == 0)
         {
             double xOff = (double) x + rand.nextFloat();
             double yOff = (double) y + getBounds().maxY;
@@ -216,11 +216,11 @@ public abstract class BlockFluid extends Block
         Vec3 vec3 = null;
         if(material == Material.water)
         {
-            vec3 = ((BlockFluid)Blocks.FLUID_WATER_FLOWING).getFlow(blockAccess, x, y, z);
+            vec3 = Blocks.FLUID_WATER_FLOWING.getLogic().getFlow(blockAccess, x, y, z);
         }
         if(material == Material.lava)
         {
-            vec3 = ((BlockFluid)Blocks.FLUID_LAVA_FLOWING).getFlow(blockAccess, x, y, z);
+            vec3 = Blocks.FLUID_LAVA_FLOWING.getLogic().getFlow(blockAccess, x, y, z);
         }
         if(vec3 == null ||(vec3.x == 0.0D && vec3.z == 0.0D))
         {
@@ -245,11 +245,11 @@ public abstract class BlockFluid extends Block
 
     private void checkForHarden(World world, int x, int y, int z)
     {
-        if(world.getBlockId(x, y, z) != id)
+        if(world.getBlockId(x, y, z) != block.id())
         {
             return;
         }
-        if(blockMaterial == Material.lava)
+        if(material == Material.lava)
         {
             if(world.getBlockMaterial(x, y, z - 1) == Material.water ||
                 world.getBlockMaterial(x, y, z + 1) == Material.water ||
@@ -261,28 +261,28 @@ public abstract class BlockFluid extends Block
                 if(data == 0)
                 {
                     if (world.dimension == Dimension.NETHER) {
-                        world.setBlockWithNotify(x, y, z, Blocks.COBBLE_NETHERRACK_IGNEOUS.id);
+                        world.setBlockWithNotify(x, y, z, Blocks.COBBLE_NETHERRACK_IGNEOUS.id());
                     } else {
-                        world.setBlockWithNotify(x, y, z, Blocks.OBSIDIAN.id);
+                        world.setBlockWithNotify(x, y, z, Blocks.OBSIDIAN.id());
                     }
                 }
                 else if(data <= 2)
                 {
-                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_GRANITE.id);
+                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_GRANITE.id());
                 }
                 else if(data <= 4)
                 {
-                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_STONE.id);
+                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_STONE.id());
                 }
                 else
                 {
-                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_BASALT.id);
+                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_BASALT.id());
                 }
                 fizz(world, x, y, z);
             }
         }
 
-        if(blockMaterial == Material.water)
+        if(material == Material.water)
         {
             if(world.getBlockMaterial(x, y, z - 1) == Material.lava ||
                 world.getBlockMaterial(x, y, z + 1) == Material.lava ||
@@ -293,7 +293,7 @@ public abstract class BlockFluid extends Block
                 int data = world.getBlockMetadata(x, y, z) & 0x0F;
                 if(data == 0)
                 {
-                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_LIMESTONE.id);
+                    world.setBlockWithNotify(x, y, z, Blocks.COBBLE_LIMESTONE.id());
                     fizz(world, x, y, z);
                 }
             }
@@ -317,10 +317,10 @@ public abstract class BlockFluid extends Block
     @Override
     public AABB getBlockBoundsFromState(WorldSource world, int x, int y, int z)
     {
-        float f7 = BlockFluid.getFluidHeight(world, x, y, z, blockMaterial);
-        float f8 = BlockFluid.getFluidHeight(world, x, y, z + 1, blockMaterial);
-        float f9 = BlockFluid.getFluidHeight(world, x + 1, y, z + 1, blockMaterial);
-        float f10 = BlockFluid.getFluidHeight(world, x + 1, y, z, blockMaterial);
+        float f7 = BlockLogicFluid.getFluidHeight(world, x, y, z, material);
+        float f8 = BlockLogicFluid.getFluidHeight(world, x, y, z + 1, material);
+        float f9 = BlockLogicFluid.getFluidHeight(world, x + 1, y, z + 1, material);
+        float f10 = BlockLogicFluid.getFluidHeight(world, x + 1, y, z, material);
         return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, Math.max((f7 + f8 + f9 + f10)/4f, 0.2), 1.0F);
     }
 
@@ -342,10 +342,10 @@ public abstract class BlockFluid extends Block
                 int i2 = worldSource.getBlockMetadata(j1, y, l1);
                 if(i2 >= 8 || i2 == 0)
                 {
-                    f += BlockFluid.getWaterVolume(i2) * 10F;
+                    f += BlockLogicFluid.getWaterVolume(i2) * 10F;
                     l += 10;
                 }
-                f += BlockFluid.getWaterVolume(i2);
+                f += BlockLogicFluid.getWaterVolume(i2);
                 l++;
                 continue;
             }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFluidFlowing.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFluidFlowing.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
index 05ee752f9..9643fe9f3 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFluidFlowing.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
@@ -8,25 +8,26 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockFluidFlowing extends BlockFluid
+public class BlockLogicFluidFlowing extends BlockLogicFluid
 {
     int maxCount;
     boolean[] result;
     int[] distance;
+    public final Block<?> blockStill;
 
-
-	public BlockFluidFlowing(String key, String namespaceId, int id, Material material)
+	public BlockLogicFluidFlowing(Block<?> block, Material material, Block<?> blockStill)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         maxCount = 0;
         result = new boolean[4];
         distance = new int[4];
+        this.blockStill = blockStill;
     }
 
     private void setFluidStill(World world, int x, int y, int z)
     {
         int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadata(x, y, z, id + 1, meta);
+        world.setBlockAndMetadata(x, y, z, blockStill.id(), meta);
         world.markBlocksDirty(x, y, z, x, y, z);
         world.markBlockNeedsUpdate(x, y, z);
     }
@@ -36,7 +37,7 @@ public class BlockFluidFlowing extends BlockFluid
     {
         int localFlowDecay = getDepth(world, x, y, z);
         byte flowDecayMod = 1;
-        if(blockMaterial == Material.lava && world.dimension != Dimension.NETHER)
+        if(material == Material.lava && world.dimension != Dimension.NETHER)
         {
             flowDecayMod = 2;
         }
@@ -64,13 +65,13 @@ public class BlockFluidFlowing extends BlockFluid
                     newFlowDecay = flowDecayAbove + 8;
                 }
             }
-            if(maxCount >= 2 && blockMaterial == Material.water)
+            if(maxCount >= 2 && material == Material.water)
             {
                 if(world.getBlockMaterial(x, y - 1, z).isSolid())
                 {
                     newFlowDecay = 0;
                 }
-                else if(world.getBlockMaterial(x, y - 1, z) == blockMaterial && world.getBlockMetadata(x, y - 1, z) == 0)
+                else if(world.getBlockMaterial(x, y - 1, z) == material && world.getBlockMetadata(x, y - 1, z) == 0)
                 {
                     newFlowDecay = 0;
                 }
@@ -85,8 +86,8 @@ public class BlockFluidFlowing extends BlockFluid
                 else
                 {
                     world.setBlockMetadataWithNotify(x, y, z, localFlowDecay);
-                    world.scheduleBlockUpdate(x, y, z, id, tickDelay());
-                    world.notifyBlocksOfNeighborChange(x, y, z, id);
+                    world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
+                    world.notifyBlocksOfNeighborChange(x, y, z, block.id());
                 }
             }
             else
@@ -107,9 +108,9 @@ public class BlockFluidFlowing extends BlockFluid
                 Blocks.blocksList[id].dropBlockWithCause(world, EnumDropCause.WORLD, x, y - 1, z, meta, null, null);
         	}
             if(localFlowDecay >= 8) {
-                world.setBlockAndMetadataWithNotify(x, y - 1, z, this.id, localFlowDecay);
+                world.setBlockAndMetadataWithNotify(x, y - 1, z, block.id(), localFlowDecay);
             } else {
-                world.setBlockAndMetadataWithNotify(x, y - 1, z, this.id, localFlowDecay + 8);
+                world.setBlockAndMetadataWithNotify(x, y - 1, z, block.id(), localFlowDecay + 8);
             }
         } else
         if(localFlowDecay >= 0 && (localFlowDecay == 0 || isFluidBlocking(world, x, y - 1, z)))
@@ -150,7 +151,7 @@ public class BlockFluidFlowing extends BlockFluid
             int i1 = world.getBlockId(x, y, z);
             if(i1 > 0)
             {
-                if(blockMaterial == Material.lava)
+                if(material == Material.lava)
                 {
                     fizz(world, x, y, z);
                 } else
@@ -158,7 +159,7 @@ public class BlockFluidFlowing extends BlockFluid
                     Blocks.blocksList[i1].dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
                 }
             }
-            world.setBlockAndMetadataWithNotify(x, y, z, id, meta);
+            world.setBlockAndMetadataWithNotify(x, y, z, block.id(), meta);
         }
     }
 
@@ -190,7 +191,7 @@ public class BlockFluidFlowing extends BlockFluid
             {
                 z2++;
             }
-            if(isFluidBlocking(world, x2, y2, z2) || world.getBlockMaterial(x2, y2, z2) == blockMaterial && world.getBlockMetadata(x2, y2, z2) == 0)
+            if(isFluidBlocking(world, x2, y2, z2) || world.getBlockMaterial(x2, y2, z2) == material && world.getBlockMetadata(x2, y2, z2) == 0)
             {
                 continue;
             }
@@ -236,7 +237,7 @@ public class BlockFluidFlowing extends BlockFluid
             {
                 z2++;
             }
-            if(isFluidBlocking(world, x2, y2, z2) || world.getBlockMaterial(x2, y2, z2) == blockMaterial && world.getBlockMetadata(x2, y2, z2) == 0)
+            if(isFluidBlocking(world, x2, y2, z2) || world.getBlockMaterial(x2, y2, z2) == material && world.getBlockMetadata(x2, y2, z2) == 0)
             {
                 continue;
             }
@@ -268,9 +269,8 @@ public class BlockFluidFlowing extends BlockFluid
 
     private boolean isFluidBlocking(World world, int x, int y, int z)
     {
-        int id = world.getBlockId(x, y, z);
-        if (Blocks.blocksList[id] == null || Blocks.blocksList[id] instanceof BlockFluid || Blocks.blocksList[id].hasTag(BlockTags.BROKEN_BY_FLUIDS)) return false;
-        return true;
+        Block<?> b = world.getBlock(x, y, z);
+        return b != null && !(b.getLogic() instanceof BlockLogicFluid) && !b.hasTag(BlockTags.BROKEN_BY_FLUIDS);
     }
 
     protected int getHighest(World world, int x, int y, int z, int currentFlowDecay)
@@ -294,7 +294,7 @@ public class BlockFluidFlowing extends BlockFluid
     private boolean canSpreadTo(World world, int x, int y, int z)
     {
         Material material = world.getBlockMaterial(x, y, z);
-        if(material == blockMaterial)
+        if(material == this.material)
         {
             return false;
         }
@@ -312,9 +312,9 @@ public class BlockFluidFlowing extends BlockFluid
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
         super.onBlockPlacedByWorld(world, x, y, z);
-        if(world.getBlockId(x, y, z) == id)
+        if(world.getBlockId(x, y, z) == block.id())
         {
-            world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFluidStill.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidStill.java
similarity index 73%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFluidStill.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidStill.java
index 08d24723c..3bc15bae9 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFluidStill.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidStill.java
@@ -5,17 +5,16 @@ import java.util.Random;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
-public class BlockFluidStill extends BlockFluid
+
+public class BlockLogicFluidStill extends BlockLogicFluid
 {
+    public final Block<?> blockFlowing;
 
-	public BlockFluidStill(String key, String namespaceId, int id, Material material)
+	public BlockLogicFluidStill(Block<?> block, Material material, Block<?> blockFlowing)
     {
-        super(key, namespaceId, id, material);
-        setTicking(false);
-        if(material == Material.lava)
-        {
-            setTicking(true);
-        }
+        super(block, material);
+        block.setTicking(material == Material.lava);
+        this.blockFlowing = blockFlowing;
     }
 
     @Override
@@ -23,7 +22,7 @@ public class BlockFluidStill extends BlockFluid
     {
         super.onNeighborBlockChange(world, x, y, z, blockId);
         if (blockId == Side.TOP.getId()) return;
-        if(world.getBlockId(x, y, z) == id)
+        if(world.getBlockId(x, y, z) == block.id())
         {
             setFlowing(world, x, y, z);
         }
@@ -33,16 +32,16 @@ public class BlockFluidStill extends BlockFluid
     {
         int meta = world.getBlockMetadata(x, y, z);
         world.noNeighborUpdate = true;
-        world.setBlockAndMetadata(x, y, z, id - 1, meta);
+        world.setBlockAndMetadata(x, y, z, blockFlowing.id(), meta);
         world.markBlocksDirty(x, y, z, x, y, z);
-        world.scheduleBlockUpdate(x, y, z, id - 1, tickDelay());
+        world.scheduleBlockUpdate(x, y, z, blockFlowing.id(), tickDelay());
         world.noNeighborUpdate = false;
     }
 
     @Override
 	public void updateTick(World world, int x, int y, int z, Random rand)
     {
-        if(blockMaterial == Material.lava)
+        if(material == Material.lava)
         {
             int l = rand.nextInt(3);
             for(int i1 = 0; i1 < l; i1++)
@@ -55,12 +54,12 @@ public class BlockFluidStill extends BlockFluid
                 {
                     if(isFlammable(world, x - 1, y, z) || isFlammable(world, x + 1, y, z) || isFlammable(world, x, y, z - 1) || isFlammable(world, x, y, z + 1) || isFlammable(world, x, y - 1, z) || isFlammable(world, x, y + 1, z))
                     {
-                        world.setBlockWithNotify(x, y, z, Blocks.FIRE.id);
+                        world.setBlockWithNotify(x, y, z, Blocks.FIRE.id());
                         return;
                     }
                     continue;
                 }
-                if(Blocks.blocksList[blockId].blockMaterial.blocksMotion())
+                if(Blocks.blocksList[blockId].getMaterial().blocksMotion())
                 {
                     return;
                 }
@@ -71,6 +70,6 @@ public class BlockFluidStill extends BlockFluid
 
     private boolean isFlammable(World world, int x, int y, int z)
     {
-        return BlockFire.canBurn(world, x, y, z);
+        return BlockLogicFire.canBurn(world, x, y, z);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFullyRotatable.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFullyRotatable.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFullyRotatable.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFullyRotatable.java
index 16a5ec55e..6c11d72ce 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFullyRotatable.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFullyRotatable.java
@@ -7,10 +7,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 
-public abstract class BlockFullyRotatable extends Block {
+public class BlockLogicFullyRotatable extends BlockLogic {
     public static final int MASK_DIRECTION = 0b0000_0111;
-    public BlockFullyRotatable(String translationKey, String namespaceId, int id, Material material) {
-        super(translationKey, namespaceId, id, material);
+    public BlockLogicFullyRotatable(Block<?> block, Material material) {
+        super(block, material);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFurnace.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFurnace.java
similarity index 92%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFurnace.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFurnace.java
index f063c0e83..bd351d32a 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFurnace.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFurnace.java
@@ -15,13 +15,14 @@ import org.slf4j.Logger;
 
 import java.util.Random;
 
-public class BlockFurnace extends BlockTileEntityRotatable
+public class BlockLogicFurnace extends BlockLogicRotatable
 {
     private static final Logger LOGGER = LogUtils.getLogger();
-	public BlockFurnace(String key, String namespaceId, int id, boolean flag)
+	public BlockLogicFurnace(Block<?> block, boolean active)
     {
-        super(key, namespaceId, id, Material.stone);
-        isActive = flag;
+        super(block, Material.stone);
+        isActive = active;
+        block.withEntity(TileEntityFurnace::new);
     }
 
     @Override
@@ -99,9 +100,9 @@ public class BlockFurnace extends BlockTileEntityRotatable
 		}
 		keepFurnaceInventory = true;
 		if(lit) {
-			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_STONE_ACTIVE.id);
+			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_STONE_ACTIVE.id());
 		} else {
-			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_STONE_IDLE.id);
+			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_STONE_IDLE.id());
 		}
 		keepFurnaceInventory = false;
 		world.setBlockMetadataWithNotify(x, y, z, meta);
@@ -109,12 +110,6 @@ public class BlockFurnace extends BlockTileEntityRotatable
 		world.setBlockTileEntity(x, y, z, tileEntity);
 	}
 
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityFurnace();
-    }
-
     protected Random furnaceRand;
     protected final boolean isActive;
     public static boolean keepFurnaceInventory = false;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockFurnaceBlast.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFurnaceBlast.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockFurnaceBlast.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicFurnaceBlast.java
index 9cccd3117..643132270 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockFurnaceBlast.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFurnaceBlast.java
@@ -3,7 +3,7 @@ package net.minecraft.core.block;
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.block.entity.TileEntityFurnaceBlastFurnace;
+import net.minecraft.core.block.entity.TileEntityFurnaceBlast;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
@@ -13,13 +13,14 @@ import org.slf4j.Logger;
 
 import java.util.Random;
 
-public class BlockFurnaceBlast extends BlockFurnace
+public class BlockLogicFurnaceBlast extends BlockLogicFurnace
 {
     private static final Logger LOGGER = LogUtils.getLogger();
 
-	public BlockFurnaceBlast(String key, String namespaceId, int id, boolean flag)
+	public BlockLogicFurnaceBlast(Block<?> block, boolean flag)
     {
-        super(key, namespaceId, id, flag);
+        super(block, flag);
+        block.withEntity(TileEntityFurnaceBlast::new);
     }
 
     @Override
@@ -41,8 +42,8 @@ public class BlockFurnaceBlast extends BlockFurnace
     public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xPlaced, double yPlaced)
     {
         if (!world.isClientSide) {
-            TileEntityFurnaceBlastFurnace tileentityblastfurnace = (TileEntityFurnaceBlastFurnace) world.getBlockEntity(x, y, z);
-            player.displayFurnaceScreen(tileentityblastfurnace);
+            TileEntityFurnaceBlast furnaceBlast = (TileEntityFurnaceBlast) world.getBlockEntity(x, y, z);
+            player.displayFurnaceScreen(furnaceBlast);
         }
         return true;
     }
@@ -96,9 +97,9 @@ public class BlockFurnaceBlast extends BlockFurnace
 		}
 		keepFurnaceInventory = true;
 		if(lit) {
-			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_BLAST_ACTIVE.id);
+			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_BLAST_ACTIVE.id());
 		} else {
-			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_BLAST_IDLE.id);
+			world.setBlockWithNotify(x, y, z, Blocks.FURNACE_BLAST_IDLE.id());
 		}
 		keepFurnaceInventory = false;
 		world.setBlockMetadataWithNotify(x, y, z, meta);
@@ -106,10 +107,4 @@ public class BlockFurnaceBlast extends BlockFurnace
 		world.setBlockTileEntity(x, y, z, tileEntity);
 	}
 
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityFurnaceBlastFurnace();
-    }
-
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockGlass.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGlass.java
similarity index 78%
rename from game/core/src/main/java/net/minecraft/core/block/BlockGlass.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicGlass.java
index 5b90ae5c6..cd77979c4 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockGlass.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGlass.java
@@ -6,12 +6,12 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 
-public class BlockGlass extends BlockTransparent
+public class BlockLogicGlass extends BlockLogicTransparent
 {
 
-    public BlockGlass(String key, String namespaceId, int id, Material material)
+    public BlockLogicGlass(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockGlassTinted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGlassTinted.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockGlassTinted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicGlassTinted.java
index e9139b829..686f63bc8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockGlassTinted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGlassTinted.java
@@ -6,12 +6,12 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 
-public class BlockGlassTinted extends BlockGlass
+public class BlockLogicGlassTinted extends BlockLogicGlass
 {
 
-    public BlockGlassTinted(String key, String namespaceID, int id)
+    public BlockLogicGlassTinted(Block<?> block)
     {
-        super(key, namespaceID, id, Material.glass);
+        super(block, Material.glass);
     }
 
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockGlowStone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGlowStone.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockGlowStone.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicGlowStone.java
index 01954344b..00691447e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockGlowStone.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGlowStone.java
@@ -8,12 +8,12 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockGlowStone extends Block
+public class BlockLogicGlowStone extends BlockLogic
 {
 
-    public BlockGlowStone(String key, String namespaceId, int id, Material material)
+    public BlockLogicGlowStone(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockGrass.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGrass.java
similarity index 73%
rename from game/core/src/main/java/net/minecraft/core/block/BlockGrass.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicGrass.java
index e8264b535..1851857df 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockGrass.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGrass.java
@@ -10,12 +10,14 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.biome.Biomes;
 
-public class BlockGrass extends Block
+public class BlockLogicGrass extends BlockLogic
 {
-    public BlockGrass(String key, String namespaceId, int id, Material material)
+    public final Block<?> dirt;
+    public BlockLogicGrass(Block<?> block, Block<?> dirt)
     {
-        super(key, namespaceId, id, material);
-        setTicking(true);
+        super(block, Material.grass);
+        block.setTicking(true);
+        this.dirt = dirt;
     }
 
     @Override
@@ -31,7 +33,7 @@ public class BlockGrass extends Block
             {
                 return;
             }
-            world.setBlockWithNotify(x, y, z, Blocks.DIRT.id);
+            world.setBlockWithNotify(x, y, z, dirt.id());
         } else
         if(world.getBlockLightValue(x, y + 1, z) >= 9)
         {
@@ -39,9 +41,9 @@ public class BlockGrass extends Block
             int i1 = (y + rand.nextInt(5)) - 3;
             int j1 = (z + rand.nextInt(3)) - 1;
             int k1 = world.getBlockId(l, i1 + 1, j1);
-            if(world.getBlockId(l, i1, j1) == Blocks.DIRT.id && world.getBlockLightValue(l, i1 + 1, j1) >= 4 && Blocks.lightBlock[k1] <= 2)
+            if(world.getBlockId(l, i1, j1) == dirt.id() && world.getBlockLightValue(l, i1 + 1, j1) >= 4 && Blocks.lightBlock[k1] <= 2)
             {
-                world.setBlockWithNotify(l, i1, j1, this.id);
+                world.setBlockWithNotify(l, i1, j1, block.id());
             }
             if (world.getGameRuleValue(GameRules.DO_SEASONAL_GROWTH) && world.getBlockId(x, y + 1, z) == 0 && world.getSeasonManager().getCurrentSeason() != null && world.getSeasonManager().getCurrentSeason().growFlowers && rand.nextInt(256) == 0)
             {
@@ -49,23 +51,23 @@ public class BlockGrass extends Block
                 int r = rand.nextInt(400);
 
                 if (r < 26) {
-                    idToSpawn = Blocks.FLOWER_RED.id;
+                    idToSpawn = Blocks.FLOWER_RED.id();
                 } else if (r < 41) {
-                    idToSpawn = Blocks.FLOWER_YELLOW.id;
+                    idToSpawn = Blocks.FLOWER_YELLOW.id();
                 } else if (r < 60) {
                     Biome biome = world.getBlockBiome(x, y + 1, z);
                     if (biome == Biomes.OVERWORLD_BIRCH_FOREST || biome == Biomes.OVERWORLD_SEASONAL_FOREST){
-                        idToSpawn = Blocks.FLOWER_PINK.id;
+                        idToSpawn = Blocks.FLOWER_PINK.id();
                     } else if (biome == Biomes.OVERWORLD_MEADOW || biome == Biomes.OVERWORLD_BOREAL_FOREST || biome == Biomes.OVERWORLD_SHRUBLAND) {
-                        idToSpawn = Blocks.FLOWER_PURPLE.id;
+                        idToSpawn = Blocks.FLOWER_PURPLE.id();
                     } else if (biome == Biomes.OVERWORLD_FOREST || biome == Biomes.OVERWORLD_SWAMPLAND || biome == Biomes.OVERWORLD_RAINFOREST || biome == Biomes.OVERWORLD_CAATINGA) {
-                        idToSpawn = Blocks.FLOWER_LIGHT_BLUE.id;
+                        idToSpawn = Blocks.FLOWER_LIGHT_BLUE.id();
                     }
                 } else {
                     if(rand.nextInt(8) == 0) {
-                        idToSpawn = Blocks.TALLGRASS_FERN.id;
+                        idToSpawn = Blocks.TALLGRASS_FERN.id();
                     }else {
-                        idToSpawn = Blocks.TALLGRASS.id;
+                        idToSpawn = Blocks.TALLGRASS.id();
                     }
                 }
 
@@ -83,7 +85,7 @@ public class BlockGrass extends Block
             case PICK_BLOCK:
                 return new ItemStack[] { new ItemStack(this) };
             default:
-                return new ItemStack[] { new ItemStack(Blocks.DIRT) };
+                return new ItemStack[] { new ItemStack(dirt) };
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockGravel.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGravel.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockGravel.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicGravel.java
index 09c457898..684c1627b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockGravel.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicGravel.java
@@ -6,12 +6,12 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 
-public class BlockGravel extends BlockSand
+public class BlockLogicGravel extends BlockLogicSand
 {
 
-    public BlockGravel(String key, String namespaceId, int id)
+    public BlockLogicGravel(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockIce.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicIce.java
similarity index 75%
rename from game/core/src/main/java/net/minecraft/core/block/BlockIce.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicIce.java
index 9844438a9..af17b0cb8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockIce.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicIce.java
@@ -10,14 +10,14 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockIce extends BlockTransparent
+public class BlockLogicIce extends BlockLogicTransparent
 {
 
-    public BlockIce(String key, String namespaceId, int id)
+    public BlockLogicIce(Block<?> block)
     {
-        super(key, namespaceId, id, Material.ice);
-        friction = 0.98F;
-        setTicking(true);
+        super(block, Material.ice);
+        block.friction = 0.98F;
+        block.setTicking(true);
     }
 
     @Override
@@ -34,22 +34,22 @@ public class BlockIce extends BlockTransparent
     }
 
     @Override
-    public void harvestBlock(World world, Player entityplayer, int x, int y, int z, int meta, TileEntity tileEntity)
+    public void harvestBlock(World world, Player player, int x, int y, int z, int meta, TileEntity tileEntity)
     {
-        super.harvestBlock(world, entityplayer, x, y, z, meta, tileEntity);
+        super.harvestBlock(world, player, x, y, z, meta, tileEntity);
         Material material = world.getBlockMaterial(x, y - 1, z);
         if(material.blocksMotion() || material.isLiquid())
         {
-            world.setBlockWithNotify(x, y, z, Blocks.FLUID_WATER_FLOWING.id);
+            world.setBlockWithNotify(x, y, z, Blocks.FLUID_WATER_FLOWING.id());
         }
     }
 
     @Override
 	public void updateTick(World world, int x, int y, int z, Random rand)
     {
-        if(world.getSavedLightValue(LightLayer.Block, x, y, z) > 11 - Blocks.lightBlock[id])
+        if(world.getSavedLightValue(LightLayer.Block, x, y, z) > 11 - block.lightBlock)
         {
-            world.setBlockWithNotify(x, y, z, Blocks.FLUID_WATER_STILL.id);
+            world.setBlockWithNotify(x, y, z, Blocks.FLUID_WATER_STILL.id());
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockJar.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicJar.java
similarity index 77%
rename from game/core/src/main/java/net/minecraft/core/block/BlockJar.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicJar.java
index 28d2458f9..1efef53b4 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockJar.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicJar.java
@@ -18,11 +18,12 @@ import org.jetbrains.annotations.NotNull;
 
 import java.util.function.Supplier;
 
-public class BlockJar extends BlockTileEntity {
+public class BlockLogicJar extends BlockLogic {
 
     private final Supplier<Item> itemSupplier;
-    public BlockJar(String key, String namespaceId, int id, @NotNull Supplier<Item> itemSupplier) {
-        super(key, namespaceId, id, Material.glass);
+    public BlockLogicJar(Block<?> block, @NotNull Supplier<Item> itemSupplier) {
+        super(block, Material.glass);
+        block.withEntity(TileEntityFlowerJar::new);
         setBlockBounds(0.3125f, 0, 0.3125f, 1 - 0.3125f, 0.375f, 1 - 0.3125f);
         this.itemSupplier = itemSupplier;
     }
@@ -64,7 +65,7 @@ public class BlockJar extends BlockTileEntity {
                 TileEntityFlowerJar tileEntity = (TileEntityFlowerJar) world.getBlockEntity(x, y, z);
                 int flowerInPot = tileEntity.flowerInPot;
                 int flowerData = tileEntity.flowerData;
-                if (flowerInPot > 0 && hasTag(flowerInPot, BlockTags.PLANTABLE_IN_JAR)) {
+                if (flowerInPot > 0 && Blocks.hasTag(flowerInPot, BlockTags.PLANTABLE_IN_JAR)) {
                     tileEntity.flowerInPot = 0;
                     world.setBlockMetadataWithNotify(x, y, z, 0);
                     world.playSoundAtEntity(player, player, "item.pickup", 1f, 1f);
@@ -74,25 +75,25 @@ public class BlockJar extends BlockTileEntity {
                 }
             }
         } else if (player.getHeldItem().getItem() instanceof ItemBlock) {
-            Block blockInHand = ((ItemBlock) player.getHeldItem().getItem()).getBlock();
-            if (hasTag(blockInHand.id, BlockTags.PLANTABLE_IN_JAR)) {
+            Block<?> blockInHand = ((ItemBlock<?>) player.getHeldItem().getItem()).getBlock();
+            if (Blocks.hasTag(blockInHand.id(), BlockTags.PLANTABLE_IN_JAR)) {
                 TileEntityFlowerJar tileEntity = (TileEntityFlowerJar) world.getBlockEntity(x, y, z);
                 if(world.getBlockMetadata(x, y, z) == 0) {
                     player.getHeldItem().consumeItem(player);
                     world.setBlockMetadataWithNotify(x, y, z, 1);
-                    tileEntity.flowerInPot = blockInHand.id;
+                    tileEntity.flowerInPot = blockInHand.id();
                     tileEntity.flowerData = player.getHeldItem().getMetadata();
-                    world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, this, EnumBlockSoundEffectType.PLACE);
+                    world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, block, EnumBlockSoundEffectType.PLACE);
                     return true;
-                } else if (blockInHand instanceof BlockFlowerStackable && blockInHand == Blocks.getBlock(tileEntity.flowerInPot)) {
+                } else if (blockInHand.getLogic() instanceof BlockLogicFlowerStackable && blockInHand == Blocks.getBlock(tileEntity.flowerInPot)) {
                     final int metadata = tileEntity.flowerData;
-                    final int currentStackCount = BlockFlowerStackable.getStackCount(metadata);
-                    if (currentStackCount >= BlockFlowerStackable.MAX_STACK_COUNT) {
+                    final int currentStackCount = BlockLogicFlowerStackable.getStackCount(metadata);
+                    if (currentStackCount >= BlockLogicFlowerStackable.MAX_STACK_COUNT) {
                         return false;
                     }
 
-                    tileEntity.flowerData = BlockFlowerStackable.setPermanent(BlockFlowerStackable.setStackCount(metadata, currentStackCount + 1), true);
-                    world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, this, EnumBlockSoundEffectType.PLACE);
+                    tileEntity.flowerData = BlockLogicFlowerStackable.setPermanent(BlockLogicFlowerStackable.setStackCount(metadata, currentStackCount + 1), true);
+                    world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, block, EnumBlockSoundEffectType.PLACE);
                     player.getHeldItem().consumeItem(player);
                     return true;
                 }
@@ -126,10 +127,4 @@ public class BlockJar extends BlockTileEntity {
         return false;
     }
 
-    @Override
-    protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityFlowerJar();
-    }
-
 }
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockJukebox.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicJukebox.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockJukebox.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicJukebox.java
index f83a6c989..9b1844041 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockJukebox.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicJukebox.java
@@ -9,12 +9,13 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 
-public class BlockJukebox extends BlockTileEntity
+public class BlockLogicJukebox extends BlockLogic
 {
 
-	public BlockJukebox(String key, String namespaceId, int id)
+	public BlockLogicJukebox(Block<?> block)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
+        block.withEntity(TileEntityJukebox::new);
     }
 
     @Override
@@ -56,10 +57,4 @@ public class BlockJukebox extends BlockTileEntity
         TileEntity tileEntity = world.getBlockEntity(x, y, z);
         tileEntity.dropContents(world, x, y, z);
     }
-
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityJukebox();
-    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLadder.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLadder.java
similarity index 95%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLadder.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLadder.java
index b477fd781..e6849807b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLadder.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLadder.java
@@ -7,10 +7,10 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockLadder extends Block {
+public class BlockLogicLadder extends BlockLogic {
 
-	public BlockLadder(String key, String namespaceId, int id) {
-		super(key, namespaceId, id, Material.wood);
+	public BlockLogicLadder(Block<?> block) {
+		super(block, Material.wood);
 	}
 	
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLamp.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLamp.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java
index fb75a470b..b14e07bd4 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLamp.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java
@@ -9,11 +9,11 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 
-public class BlockLamp extends Block implements IPainted {
+public class BlockLogicLamp extends BlockLogic implements IPainted {
     public boolean isActive;
 
-    public BlockLamp(String key, String namespaceId, int id, boolean isActivated) {
-        super(key, namespaceId, id, Material.stone);
+    public BlockLogicLamp(Block<?> block, boolean isActivated) {
+        super(block, Material.stone);
         isActive = isActivated;
     }
 
@@ -26,9 +26,9 @@ public class BlockLamp extends Block implements IPainted {
         final boolean hasSignal = world.hasDirectSignal(x, y, z) || world.hasNeighborSignal(x, y, z);
 
         if (hasSignal && !isActive) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_ACTIVE.id, world.getBlockMetadata(x, y, z));
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_ACTIVE.id(), world.getBlockMetadata(x, y, z));
         } else if (!hasSignal && isActive) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_IDLE.id, world.getBlockMetadata(x, y, z));
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_IDLE.id(), world.getBlockMetadata(x, y, z));
         }
     }
 
@@ -37,9 +37,9 @@ public class BlockLamp extends Block implements IPainted {
         final boolean hasSignal = world.hasDirectSignal(x, y, z) || world.hasNeighborSignal(x, y, z);
 
         if (hasSignal && !isActive) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_ACTIVE.id, world.getBlockMetadata(x, y, z));
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_ACTIVE.id(), world.getBlockMetadata(x, y, z));
         } else if (!hasSignal && isActive) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_IDLE.id, world.getBlockMetadata(x, y, z));
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_IDLE.id(), world.getBlockMetadata(x, y, z));
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLanternFirefly.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLanternFirefly.java
similarity index 88%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLanternFirefly.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLanternFirefly.java
index a68da71e2..f6eb75ee8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLanternFirefly.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLanternFirefly.java
@@ -17,14 +17,14 @@ import org.jetbrains.annotations.NotNull;
 import java.util.Random;
 import java.util.function.Supplier;
 
-public class BlockLanternFirefly extends Block{
+public class BlockLogicLanternFirefly extends BlockLogic {
     public static final int MASK_HANGING = 0b0000_0001;
     public static final int MASK_ANGLED = 0b0000_0010;
     private final Supplier<Item> itemSupplier;
     private final MobFireflyCluster.FireflyColor color;
 
-    public BlockLanternFirefly(String key, String namespaceId, int id, MobFireflyCluster.FireflyColor colour, @NotNull Supplier<Item> itemSupplier) {
-        super(key, namespaceId, id, Material.glass);
+    public BlockLogicLanternFirefly(Block<?> block, MobFireflyCluster.FireflyColor colour, @NotNull Supplier<Item> itemSupplier) {
+        super(block, Material.glass);
         this.color = colour;
         this.itemSupplier = itemSupplier;
         setBlockBounds(0.3125f, 0, 0.3125f, 1 - 0.3125f, 0.5f, 1 - 0.3125f);
@@ -75,7 +75,7 @@ public class BlockLanternFirefly extends Block{
     }
     @Override
     public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
-        if ((side == Side.BOTTOM || (side != Side.TOP && yPlaced >= 0.5d)) && (world.isBlockNormalCube(x, y+1, z) || Block.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF))){
+        if ((side == Side.BOTTOM || (side != Side.TOP && yPlaced >= 0.5d)) && (world.isBlockNormalCube(x, y+1, z) || Blocks.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF))){
             world.setBlockMetadataWithNotify(x, y, z, MASK_HANGING);
             return;
         }
@@ -83,7 +83,7 @@ public class BlockLanternFirefly extends Block{
             world.setBlockMetadataWithNotify(x, y, z, 0);
             return;
         }
-        if(world.isBlockNormalCube(x, y+1, z) || Block.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF))
+        if(world.isBlockNormalCube(x, y+1, z) || Blocks.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF))
         {
             world.setBlockMetadataWithNotify(x, y, z, MASK_HANGING);
         } else world.setBlockMetadataWithNotify(x, y, z, 0);
@@ -92,7 +92,7 @@ public class BlockLanternFirefly extends Block{
     @Override
     public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
-        if(world.isBlockNormalCube(x, y + 1, z) || Block.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF)) {
+        if(world.isBlockNormalCube(x, y + 1, z) || Blocks.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF)) {
             return true;
         }
 
@@ -128,7 +128,7 @@ public class BlockLanternFirefly extends Block{
     {
         int meta = world.getBlockMetadata(x, y, z);
         if((meta & MASK_HANGING) != 0) {
-            return world.isBlockNormalCube(x, y + 1, z) || Block.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF);
+            return world.isBlockNormalCube(x, y + 1, z) || Blocks.hasTag(world.getBlockId(x, y + 1, z), BlockTags.CAN_HANG_OFF);
         }
 
         return world.canPlaceOnSurfaceOfBlock(x, y - 1, z);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLayerBase.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerBase.java
similarity index 58%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLayerBase.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerBase.java
index f6125a815..15424f0a8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLayerBase.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerBase.java
@@ -5,22 +5,16 @@ import net.minecraft.core.item.block.ItemBlockLayer;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-import java.util.function.Supplier;
-
-public abstract class BlockLayerBase extends Block
+public abstract class BlockLogicLayerBase extends BlockLogic
 {
-    private Supplier<Integer> idSupplier = () -> -1;
+    public Block<?> fullBlock = null;
 	
-	public BlockLayerBase(String key, String namespaceId, int id, Material material)
+	public BlockLogicLayerBase(Block<?> block, Block<?> fullBlock, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
-        setBlockItem(() -> new ItemBlockLayer(this));
-    }
-    public BlockLayerBase setFullBlockID(Supplier<Integer> idSupplier)
-    {
-    	this.idSupplier = idSupplier;
-    	return this;
+        block.setBlockItem(() -> new ItemBlockLayer<>((Block<? extends BlockLogicLayerBase>) block));
+        this.fullBlock = fullBlock;
     }
 
     @Override
@@ -42,7 +36,4 @@ public abstract class BlockLayerBase extends Block
         float f = (float)(2 * (1 + l)) / 16F;
         return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, f, 1.0F);
     }
-    public int getFullBlockID() {
-        return idSupplier.get();
-    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLayerLeaves.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerLeaves.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLayerLeaves.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerLeaves.java
index d28f0f521..6c7f4960d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLayerLeaves.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerLeaves.java
@@ -3,6 +3,7 @@ package net.minecraft.core.block;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.item.block.ItemBlockLayerLeaves;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.phys.AABB;
@@ -10,15 +11,16 @@ import net.minecraft.core.world.WorldSource;
 
 import java.util.Random;
 
-public class BlockLayerLeaves extends BlockLayerBase
+public class BlockLogicLayerLeaves extends BlockLogicLayerBase
 {
     public static final int MASK_PERMANENT = 0b1000_0000;
 
-	public BlockLayerLeaves(String key, String namespaceId, int id, Material material)
+	public BlockLogicLayerLeaves(Block<?> block, Block<?> fullBlock, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, fullBlock, material);
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
-        setTicking(true);
+        block.setTicking(true);
+        block.setBlockItem(() -> new ItemBlockLayerLeaves<>((Block<? extends BlockLogicLayerLeaves>) block));
     }
 
     @Override
@@ -32,13 +34,13 @@ public class BlockLayerLeaves extends BlockLayerBase
     	int myMetadata = world.getBlockMetadata(x, y, z);
     	if (myMetadata == 0x7) return;
     	
-    	boolean posXValid = (world.isBlockOpaqueCube(x + 1, y, z)) || (world.getBlockId(x + 1, y, z) == this.id && world.getBlockMetadata(x + 1, y, z) >= myMetadata);
+    	boolean posXValid = (world.isBlockOpaqueCube(x + 1, y, z)) || (world.getBlockId(x + 1, y, z) == block.id() && world.getBlockMetadata(x + 1, y, z) >= myMetadata);
     	if (!posXValid) return;
-    	boolean posZValid = (world.isBlockOpaqueCube(x, y, z + 1)) || (world.getBlockId(x, y, z + 1) == this.id && world.getBlockMetadata(x, y, z + 1) >= myMetadata);
+    	boolean posZValid = (world.isBlockOpaqueCube(x, y, z + 1)) || (world.getBlockId(x, y, z + 1) == block.id() && world.getBlockMetadata(x, y, z + 1) >= myMetadata);
     	if (!posZValid) return;
-    	boolean negXValid = (world.isBlockOpaqueCube(x - 1, y, z)) || (world.getBlockId(x - 1, y, z) == this.id && world.getBlockMetadata(x - 1, y, z) >= myMetadata);
+    	boolean negXValid = (world.isBlockOpaqueCube(x - 1, y, z)) || (world.getBlockId(x - 1, y, z) == block.id() && world.getBlockMetadata(x - 1, y, z) >= myMetadata);
     	if (!negXValid) return;
-    	boolean negZValid = (world.isBlockOpaqueCube(x, y, z - 1)) || (world.getBlockId(x, y, z - 1) == this.id && world.getBlockMetadata(x, y, z - 1) >= myMetadata);
+    	boolean negZValid = (world.isBlockOpaqueCube(x, y, z - 1)) || (world.getBlockId(x, y, z - 1) == block.id() && world.getBlockMetadata(x, y, z - 1) >= myMetadata);
     	if (!negZValid) return;
     	
     	world.setBlockMetadata(x, y, z, myMetadata + 1);
@@ -49,7 +51,7 @@ public class BlockLayerLeaves extends BlockLayerBase
 	public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
         int l = world.getBlockId(x, y - 1, z);
-        if(l == 0 || (!Blocks.blocksList[l].isSolidRender() && !(Blocks.blocksList[l] instanceof BlockLeavesBase)))
+        if(l == 0 || (!Blocks.blocksList[l].isSolidRender() && !(Blocks.blocksList[l].getLogic() instanceof BlockLogicLeavesBase)))
         {
         	return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLayerSlate.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSlate.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLayerSlate.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSlate.java
index 3305b34b2..1fcff0f15 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLayerSlate.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSlate.java
@@ -7,11 +7,11 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 
 
-public class BlockLayerSlate extends BlockLayerBase
+public class BlockLogicLayerSlate extends BlockLogicLayerBase
 {
-	public BlockLayerSlate(String key, String namespaceId, int id, Material material)
+	public BlockLogicLayerSlate(Block<?> block, Block<?> fullBlock, Material material)
 	{
-		super(key, namespaceId, id, material);
+		super(block, fullBlock, material);
 	}
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLayerSnow.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSnow.java
similarity index 81%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLayerSnow.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSnow.java
index b96913312..081207a22 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLayerSnow.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSnow.java
@@ -10,14 +10,14 @@ import net.minecraft.core.block.material.Material;
 
 import java.util.Random;
 
-public class BlockLayerSnow extends BlockLayerBase
+public class BlockLogicLayerSnow extends BlockLogicLayerBase
 {
 
-	public BlockLayerSnow(String key, String namespaceId, int id, Material material)
+	public BlockLogicLayerSnow(Block<?> block, Block<?> fullBlock, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, fullBlock, material);
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
-        setTicking(true);
+        block.setTicking(true);
     }
 
     public void accumulate(World world, int x, int y, int z)
@@ -25,13 +25,13 @@ public class BlockLayerSnow extends BlockLayerBase
     	int myMetadata = world.getBlockMetadata(x, y, z);
     	if (myMetadata == 0x7) return;
     	
-    	boolean posXValid = (world.isBlockOpaqueCube(x + 1, y, z)) || (world.getBlockId(x + 1, y, z) == this.id && world.getBlockMetadata(x + 1, y, z) >= myMetadata);
+    	boolean posXValid = (world.isBlockOpaqueCube(x + 1, y, z)) || (world.getBlockId(x + 1, y, z) == block.id() && world.getBlockMetadata(x + 1, y, z) >= myMetadata);
     	if (!posXValid) return;
-    	boolean posZValid = (world.isBlockOpaqueCube(x, y, z + 1)) || (world.getBlockId(x, y, z + 1) == this.id && world.getBlockMetadata(x, y, z + 1) >= myMetadata);
+    	boolean posZValid = (world.isBlockOpaqueCube(x, y, z + 1)) || (world.getBlockId(x, y, z + 1) == block.id() && world.getBlockMetadata(x, y, z + 1) >= myMetadata);
     	if (!posZValid) return;
-    	boolean negXValid = (world.isBlockOpaqueCube(x - 1, y, z)) || (world.getBlockId(x - 1, y, z) == this.id && world.getBlockMetadata(x - 1, y, z) >= myMetadata);
+    	boolean negXValid = (world.isBlockOpaqueCube(x - 1, y, z)) || (world.getBlockId(x - 1, y, z) == block.id() && world.getBlockMetadata(x - 1, y, z) >= myMetadata);
     	if (!negXValid) return;
-    	boolean negZValid = (world.isBlockOpaqueCube(x, y, z - 1)) || (world.getBlockId(x, y, z - 1) == this.id && world.getBlockMetadata(x, y, z - 1) >= myMetadata);
+    	boolean negZValid = (world.isBlockOpaqueCube(x, y, z - 1)) || (world.getBlockId(x, y, z - 1) == block.id() && world.getBlockMetadata(x, y, z - 1) >= myMetadata);
     	if (!negZValid) return;
     	
     	world.setBlockMetadata(x, y, z, myMetadata + 1);
@@ -42,7 +42,7 @@ public class BlockLayerSnow extends BlockLayerBase
 	public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
         int l = world.getBlockId(x, y - 1, z);
-        if(l == 0 || (!Blocks.blocksList[l].isSolidRender() && !(Blocks.blocksList[l] instanceof BlockLeavesBase)))
+        if(l == 0 || (!Blocks.blocksList[l].isSolidRender() && !(Blocks.blocksList[l].getLogic() instanceof BlockLogicLeavesBase)))
         {
         	return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesBase.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesBase.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesBase.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesBase.java
index 6fc2ba75e..909c71149 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesBase.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesBase.java
@@ -14,17 +14,20 @@ import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.season.Season;
 import org.jetbrains.annotations.Nullable;
 
-public abstract class BlockLeavesBase extends Block
+public class BlockLogicLeavesBase extends BlockLogic
 {
     public static final int MASK_DECAY_DATA = 0b0000_1111;
     public static final int NUM_DECAY_BITS = 4;
     public static final int DECAY_FLAG_BIT = 3;
     public static final int PERMANENT_FLAG_BIT = 0;
 
-	public BlockLeavesBase(String key, String namespaceId, int id, Material material)
+    protected Block<?> sapling;
+
+	public BlockLogicLeavesBase(Block<?> block, Material material, Block<?> sapling)
     {
-        super(key, namespaceId, id, material);
-        setTicking(true);
+        super(block, material);
+        block.setTicking(true);
+        this.sapling = sapling;
     }
 
     @Override
@@ -39,7 +42,7 @@ public abstract class BlockLeavesBase extends Block
 
         Season season = world.getSeasonManager().getCurrentSeason();
         float dropRate = season != null ? 20 / season.saplingDropFactor : 20;
-        if (dropCause == EnumDropCause.PICK_BLOCK || dropCause == EnumDropCause.SILK_TOUCH) return new ItemStack[] { new ItemStack(this) };
+        if (dropCause == EnumDropCause.PICK_BLOCK || dropCause == EnumDropCause.SILK_TOUCH) return new ItemStack[] { new ItemStack(block) };
 
         int numDropped = 1;
 
@@ -48,7 +51,9 @@ public abstract class BlockLeavesBase extends Block
         return new ItemStack[] { new ItemStack(getSapling(), numDropped) };
     }
 
-    protected abstract Block getSapling();
+    protected Block<?> getSapling() {
+        return sapling;
+    }
     
     @Override
     public void onBlockRemoved(World world, int x, int y, int z, int data)
@@ -67,8 +72,8 @@ public abstract class BlockLeavesBase extends Block
                 {
                     for(int dz = -radius; dz <= radius; dz++)
                     {
-                        int blockId = world.getBlockId(x + dx, y + dy, z + dz);
-                        if(Blocks.blocksList[blockId] instanceof BlockLeavesBase)
+                        Block<?> block = world.getBlock(x + dx, y + dy, z + dz);
+                        if(block != null && block.getLogic() instanceof BlockLogicLeavesBase)
                         {
                             int meta = world.getBlockMetadata(x + dx, y + dy, z + dz);
                             if (!isPermanent(meta))
@@ -108,13 +113,13 @@ public abstract class BlockLeavesBase extends Block
                     {
                         for(int zOffset = -byte0; zOffset <= byte0; zOffset++)
                         {
-                            int k3 = world.getBlockId(x + xOffset, y + yOffset, z + zOffset);
-                            if(Blocks.blocksList[k3] instanceof BlockLog)
+                            Block<?> block = world.getBlock(x + xOffset, y + yOffset, z + zOffset);
+                            if(block != null && block.getLogic() instanceof BlockLogicLog)
                             {
                                 adjacentTreeBlocks[(xOffset + halfLength) * xSpan + (yOffset + halfLength) * ySpan + (zOffset + halfLength)] = 0;
                                 continue;
                             }
-                            if(Blocks.blocksList[k3] instanceof BlockLeavesBase)
+                            if(block != null && block.getLogic() instanceof BlockLogicLeavesBase)
                             {
                                 adjacentTreeBlocks[(xOffset + halfLength) * xSpan + (yOffset + halfLength) * ySpan + (zOffset + halfLength)] = -2;
                             } else
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesCacao.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCacao.java
similarity index 92%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesCacao.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCacao.java
index ae27a6f24..6314b44be 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesCacao.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCacao.java
@@ -18,14 +18,14 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockLeavesCacao extends BlockLeavesBase implements IBonemealable {
+public class BlockLogicLeavesCacao extends BlockLogicLeavesBase implements IBonemealable {
 
     public static final int MASK_GROWTH_DATA = 0b1111_0000;
     public static final int MAX_GROWTH_STATE = 4;
     static final int BEAN_GROWTH_RATE = 50;
-    public BlockLeavesCacao(String key, String namespaceId, int id) {
-        super(key, namespaceId, id, Material.leaves);
-        setTicking(true);
+    public BlockLogicLeavesCacao(Block<?> block) {
+        super(block, Material.leaves, Blocks.SAPLING_CACAO);
+        block.setTicking(true);
     }
 
     public boolean canBeansGrow(World world, int x, int y, int z){
@@ -77,7 +77,7 @@ public class BlockLeavesCacao extends BlockLeavesBase implements IBonemealable {
                 dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null, null);
             }
             world.setBlockMetadataWithNotify(x, y, z, setGrowthRate(meta, 0));
-            world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CACAO.id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CACAO.id(), tickDelay());
             return true;
         }
         return false;
@@ -98,22 +98,17 @@ public class BlockLeavesCacao extends BlockLeavesBase implements IBonemealable {
                 if (canBeansGrow(world, x, y, z)) {
                     if (growthRate < MAX_GROWTH_STATE) {
                         world.setBlockMetadataWithNotify(x, y, z, setGrowthRate(meta, ++growthRate));
-                        world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CACAO.id, tickDelay());
+                        world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CACAO.id(), tickDelay());
                     }
                 }
             }
             else if(growthRate > 0){
                 world.setBlockMetadataWithNotify(x, y, z, setGrowthRate(meta, 0));
-                world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CACAO.id, tickDelay());
+                world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CACAO.id(), tickDelay());
             }
         }
     }
 
-    @Override
-    protected Block getSapling() {
-        return Blocks.SAPLING_CACAO;
-    }
-
     @Override
     public boolean onBonemealUsed(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
         int meta = world.getBlockMetadata(blockX, blockY, blockZ);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesCherry.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCherry.java
similarity index 68%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesCherry.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCherry.java
index 7586cca01..7002bb67e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesCherry.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCherry.java
@@ -6,12 +6,12 @@ import net.minecraft.core.world.season.Seasons;
 
 import java.util.Random;
 
-public class BlockLeavesCherry extends BlockLeavesBase
+public class BlockLogicLeavesCherry extends BlockLogicLeavesBase
 {
 
-	public BlockLeavesCherry(String key, String namespaceId, int id)
+	public BlockLogicLeavesCherry(Block<?> block)
     {
-        super(key, namespaceId, id, Material.leaves);
+        super(block, Material.leaves, Blocks.SAPLING_CHERRY);
     }
 
     @Override
@@ -23,9 +23,4 @@ public class BlockLeavesCherry extends BlockLeavesBase
         }
     }
 
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_CHERRY;
-    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesCherryFlowering.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCherryFlowering.java
similarity index 93%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesCherryFlowering.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCherryFlowering.java
index 6d991b53d..9bf773bc7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesCherryFlowering.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesCherryFlowering.java
@@ -15,12 +15,12 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockLeavesCherryFlowering extends BlockLeavesCherry implements IBonemealable
+public class BlockLogicLeavesCherryFlowering extends BlockLogicLeavesCherry implements IBonemealable
 {
     public static final int MASK_GROWTH_DATA = 0b1111_0000;
     public static final int MAX_GROWTH_STATE = 1;
-	public BlockLeavesCherryFlowering(String key, String namespaceId, int id) {
-        super(key, namespaceId, id);
+	public BlockLogicLeavesCherryFlowering(Block<?> block) {
+        super(block);
     }
 
     @Override
@@ -61,7 +61,7 @@ public class BlockLeavesCherryFlowering extends BlockLeavesCherry implements IBo
                 dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null, null);
             }
             world.setBlockMetadataWithNotify(x, y, z, setGrowthRate(meta, 0));
-            world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id(), tickDelay());
             return true;
         }
         return false;
@@ -82,13 +82,13 @@ public class BlockLeavesCherryFlowering extends BlockLeavesCherry implements IBo
             if (rand.nextInt(20) == 0) {
                 if ((growthRate) == 0) {
                     world.setBlockMetadataWithNotify(x, y, z, setGrowthRate(meta, MAX_GROWTH_STATE));
-                    world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id, tickDelay());
+                    world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id(), tickDelay());
                 }
             }
         }
        else if(growthRate > 0){
             world.setBlockMetadataWithNotify(x, y, z, meta & MASK_DECAY_DATA);
-            world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id(), tickDelay());
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesEucalyptus.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesEucalyptus.java
similarity index 64%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesEucalyptus.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesEucalyptus.java
index 90c2efb10..6ad966948 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesEucalyptus.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesEucalyptus.java
@@ -5,18 +5,12 @@ import net.minecraft.core.block.material.Material;
 
 import java.util.Random;
 
-public class BlockLeavesEucalyptus extends BlockLeavesBase
+public class BlockLogicLeavesEucalyptus extends BlockLogicLeavesBase
 {
 
-	public BlockLeavesEucalyptus(String key, String namespaceId, int id)
+	public BlockLogicLeavesEucalyptus(Block<?> block)
     {
-        super(key, namespaceId, id, Material.leaves);
-    }
-
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_EUCALYPTUS;
+        super(block, Material.leaves, Blocks.SAPLING_EUCALYPTUS);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesOak.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesOak.java
similarity index 78%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesOak.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesOak.java
index e446d3bdd..699fc0242 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesOak.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesOak.java
@@ -6,11 +6,11 @@ import net.minecraft.core.world.wind.WindProvider;
 
 import java.util.Random;
 
-public class BlockLeavesOak extends BlockLeavesBase
+public class BlockLogicLeavesOak extends BlockLogicLeavesBase
 {
-	public BlockLeavesOak(String key, String namespaceId, int id)
+	public BlockLogicLeavesOak(Block<?> block)
     {
-        super(key, namespaceId, id, Material.leaves);
+        super(block, Material.leaves, Blocks.SAPLING_OAK);
     }
 
     @Override
@@ -23,26 +23,20 @@ public class BlockLeavesOak extends BlockLeavesBase
             {
                 int id = world.getBlockId(x, y + q, z);
                 if (id != 0) break;
-                if (Blocks.LAYER_LEAVES_OAK.canPlaceBlockAt(world, x, y + q, z) && Blocks.blocksList[world.getBlockId(x, y + q - 1, z)].blockMaterial.blocksMotion())
+                if (Blocks.LAYER_LEAVES_OAK.canPlaceBlockAt(world, x, y + q, z) && Blocks.blocksList[world.getBlockId(x, y + q - 1, z)].getMaterial().blocksMotion())
                 {
-                    world.setBlockWithNotify(x, y + q, z, Blocks.LAYER_LEAVES_OAK.id);
+                    world.setBlockWithNotify(x, y + q, z, Blocks.LAYER_LEAVES_OAK.id());
                     break;
                 }
-                else if (world.getBlockId(x, y + q, z) == Blocks.LAYER_LEAVES_OAK.id)
+                else if (world.getBlockId(x, y + q, z) == Blocks.LAYER_LEAVES_OAK.id())
                 {
-                    ((BlockLayerLeaves) Blocks.LAYER_LEAVES_OAK).accumulate(world, x, y + q, z);
+                    Blocks.LAYER_LEAVES_OAK.getLogic().accumulate(world, x, y + q, z);
                     break;
                 }
             }
         }
     }
 
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_OAK;
-    }
-
     @Override
     public void animationTick(World world, int x, int y, int z, Random rand)
     {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesPine.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesPine.java
similarity index 73%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesPine.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesPine.java
index 91102df67..5d0398f43 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesPine.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesPine.java
@@ -6,12 +6,12 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 
-public class BlockLeavesPine extends BlockLeavesBase
+public class BlockLogicLeavesPine extends BlockLogicLeavesBase
 {
 
-	public BlockLeavesPine(String key, String namespaceId, int id)
+	public BlockLogicLeavesPine(Block<?> block)
     {
-        super(key, namespaceId, id, Material.leaves);
+        super(block, Material.leaves, Blocks.SAPLING_PINE);
     }
 
     @Override
@@ -26,9 +26,4 @@ public class BlockLeavesPine extends BlockLeavesBase
         return new ItemStack[] { new ItemStack(getSapling(), numDropped) };
     }
 
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_PINE;
-    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesShrub.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesShrub.java
similarity index 66%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLeavesShrub.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesShrub.java
index 92b3f9e93..d145488a7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLeavesShrub.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesShrub.java
@@ -5,18 +5,12 @@ import net.minecraft.core.block.material.Material;
 
 import java.util.Random;
 
-public class BlockLeavesShrub extends BlockLeavesBase
+public class BlockLogicLeavesShrub extends BlockLogicLeavesBase
 {
 
-	public BlockLeavesShrub(String key, String namespaceId, int id)
+	public BlockLogicLeavesShrub(Block<?> block)
     {
-        super(key, namespaceId, id, Material.leaves);
-    }
-
-    @Override
-    protected Block getSapling()
-    {
-        return Blocks.SAPLING_SHRUB;
+        super(block, Material.leaves, Blocks.SAPLING_SHRUB);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLever.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLever.java
similarity index 94%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLever.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLever.java
index dd455cbb6..f621491c2 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLever.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLever.java
@@ -17,7 +17,7 @@ import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockLever extends Block
+public class BlockLogicLever extends BlockLogic
 {
     public static final int MASK_POWERED = 0b0001_0000;
     public static final int MASK_ROTATION = 0b0000_1111;
@@ -30,9 +30,9 @@ public class BlockLever extends Block
     public static final int ROTATION_BOTTOM_NS = 7;
     public static final int ROTATION_BOTTOM_WE = 8;
 
-	public BlockLever(String key, String namespaceId, int id)
+	public BlockLogicLever(Block<?> block)
     {
-        super(key, namespaceId, id, Material.decoration);
+        super(block, Material.decoration);
     }
 
     @Override
@@ -265,19 +265,19 @@ public class BlockLever extends Block
 
         world.markBlocksDirty(x, y, z, x, y, z);
         world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, (double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "random.click", 0.3F, isPowered(meta) ? 0.5F : 0.6F);
-        world.notifyBlocksOfNeighborChange(x, y, z, id);
+        world.notifyBlocksOfNeighborChange(x, y, z, block.id());
         if(rotation == ROTATION_EAST) {
-            world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
+            world.notifyBlocksOfNeighborChange(x - 1, y, z, block.id());
         } else if(rotation == ROTATION_WEST) {
-            world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
+            world.notifyBlocksOfNeighborChange(x + 1, y, z, block.id());
         } else if(rotation == ROTATION_SOUTH) {
-            world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
+            world.notifyBlocksOfNeighborChange(x, y, z - 1, block.id());
         } else if(rotation == ROTATION_NORTH) {
-            world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
+            world.notifyBlocksOfNeighborChange(x, y, z + 1, block.id());
         } else if (rotation == ROTATION_TOP_NS || rotation == ROTATION_TOP_WE){
-            world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+            world.notifyBlocksOfNeighborChange(x, y - 1, z, block.id());
         } else {
-            world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+            world.notifyBlocksOfNeighborChange(x, y + 1, z, block.id());
         }
     }
 
@@ -291,20 +291,20 @@ public class BlockLever extends Block
     {
         if(isPowered(data))
         {
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
+            world.notifyBlocksOfNeighborChange(x, y, z, block.id());
             int rotation = getRotation(data);
             if(rotation == ROTATION_EAST) {
-                world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
+                world.notifyBlocksOfNeighborChange(x - 1, y, z, block.id());
             } else if(rotation == ROTATION_WEST) {
-                world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
+                world.notifyBlocksOfNeighborChange(x + 1, y, z, block.id());
             } else if(rotation == ROTATION_SOUTH) {
-                world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
+                world.notifyBlocksOfNeighborChange(x, y, z - 1, block.id());
             } else if(rotation == ROTATION_NORTH) {
-                world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
+                world.notifyBlocksOfNeighborChange(x, y, z + 1, block.id());
             } else if (rotation == ROTATION_TOP_NS || rotation == ROTATION_TOP_WE){
-                world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+                world.notifyBlocksOfNeighborChange(x, y - 1, z, block.id());
             } else {
-                world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+                world.notifyBlocksOfNeighborChange(x, y + 1, z, block.id());
             }
         }
         super.onBlockRemoved(world, x, y, z, data);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLog.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java
similarity index 67%
rename from game/core/src/main/java/net/minecraft/core/block/BlockLog.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java
index 02df9bd44..ba90139c3 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLog.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java
@@ -3,12 +3,12 @@ package net.minecraft.core.block;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 
-public class BlockLog extends BlockAxisAligned
+public class BlockLogicLog extends BlockLogicAxisAligned
 {
 
-	public BlockLog(String key, String namespaceId, int id)
+	public BlockLogicLog(Block<?> block)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
     }
 
     @Override
@@ -24,15 +24,15 @@ public class BlockLog extends BlockAxisAligned
                 {
                     for(int _z = -r; _z <= r; _z++)
                     {
-                        int l1 = world.getBlockId(x + _x, y + _y, z + _z);
-                        if(!(Blocks.blocksList[l1] instanceof BlockLeavesBase))
+                        Block<?> block = world.getBlock(x + _x, y + _y, z + _z);
+                        if(!(block != null && block.getLogic() instanceof BlockLogicLeavesBase))
                         {
                             continue;
                         }
                         int leavesMeta = world.getBlockMetadata(x + _x, y + _y, z + _z);
-                        if(!BlockLeavesBase.isPermanent(leavesMeta))
+                        if(!BlockLogicLeavesBase.isPermanent(leavesMeta))
                         {
-                            world.setBlockMetadata(x + _x, y + _y, z + _z, BlockLeavesBase.setDecaying(leavesMeta, true));
+                            world.setBlockMetadata(x + _x, y + _y, z + _z, BlockLogicLeavesBase.setDecaying(leavesMeta, true));
                         }
                     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMesh.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMesh.java
similarity index 77%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMesh.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMesh.java
index b3234266a..614f7d8ec 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMesh.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMesh.java
@@ -5,12 +5,12 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.world.World;
 
-public class BlockMesh extends BlockTransparent
+public class BlockLogicMesh extends BlockLogicTransparent
 {
 
-    public BlockMesh(String key, String namespaceId, int id)
+    public BlockLogicMesh(Block<?> block)
     {
-        super(key, namespaceId, id, Material.metal);
+        super(block, Material.metal);
     }
     
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMeshGold.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMeshGold.java
similarity index 68%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMeshGold.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMeshGold.java
index 70f09e2b5..d8468e00d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMeshGold.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMeshGold.java
@@ -1,8 +1,6 @@
 package net.minecraft.core.block;
 
-import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityMeshGold;
-import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
@@ -10,31 +8,12 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
-public class BlockMeshGold extends BlockTileEntity {
-    public BlockMeshGold(String key, String namespaceId, int id) {
-        super(key, namespaceId, id, Material.metal);
+public class BlockLogicMeshGold extends BlockLogicMesh {
+    public BlockLogicMeshGold(Block<?> block) {
+        super(block);
+        block.withEntity(TileEntityMeshGold::new);
     }
 
-    @Override
-    protected TileEntity getNewBlockEntity() {
-        return new TileEntityMeshGold();
-    }
-    @Override
-    public boolean isSolidRender()
-    {
-        return false;
-    }
-    @Override
-    public boolean isCubeShaped()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean canPlaceOnSurface()
-    {
-        return true;
-    }
     @Override
     public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xPlaced, double yPlaced)
     {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMobSpawner.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawner.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMobSpawner.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawner.java
index f3ca1073d..b586c93e1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMobSpawner.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawner.java
@@ -2,8 +2,6 @@ package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityMobSpawner;
-import net.minecraft.core.block.material.Material;
-import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
@@ -14,12 +12,13 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 
-public class BlockMobSpawner extends BlockTileEntity
+public class BlockLogicMobSpawner extends BlockLogicMobSpawnerDeactivated
 {
 
-	public BlockMobSpawner(String key, String namespaceId, int id)
+	public BlockLogicMobSpawner(Block<?> block)
     {
-        super(key, namespaceId, id, Material.stone);
+        super(block);
+        block.withEntity(TileEntityMobSpawner::new);
     }
 
     @Override
@@ -32,22 +31,12 @@ public class BlockMobSpawner extends BlockTileEntity
         return true;
     }
 
-    @Override
-	public TileEntity getNewBlockEntity()
-    {
-        return new TileEntityMobSpawner();
-    }
-
     @Override
 	public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
     	TileEntityMobSpawner tileEntity = (TileEntityMobSpawner) world.getBlockEntity(x, y, z);
     	tileEntity.setMobId("none");
     }
 
-    @Override
-    public boolean collidesWithEntity(Entity entity, World world, int x, int y, int z) {
-        return !(entity instanceof EntityItem);
-    }
     @Override
     public void onBlockRemoved(World world, int x, int y, int z, int data)
     {
@@ -61,22 +50,22 @@ public class BlockMobSpawner extends BlockTileEntity
                 if(mobInSpawner != null) {
                     ItemStack itemstack;
                     switch (mobInSpawner) {
-                        case "Zombie":
+                        case "minecraft:zombie":
                             itemstack = new ItemStack(Items.CLOTH);
                             break;
-                        case "Skeleton":
+                        case "minecraft:skeleton":
                             if (world.rand.nextInt(2) == 0)
                                 itemstack = new ItemStack(Items.BONE);
                             else
                                 itemstack = new ItemStack(Items.AMMO_ARROW);
                             break;
-                        case "ArmouredZombie":
+                        case "minecraft:zombie_armored":
                             itemstack = new ItemStack(Items.CHAINLINK);
                             break;
-                        case "Spider":
+                        case "minecraft:spider":
                             itemstack = new ItemStack(Items.STRING);
                             break;
-                        case "Snowman":
+                        case "minecraft:snowman":
                             itemstack = new ItemStack(Items.AMMO_SNOWBALL);
                             break;
                         default:
@@ -121,15 +110,4 @@ public class BlockMobSpawner extends BlockTileEntity
         }
         return null;
     }
-
-    @Override
-	public boolean isSolidRender()
-    {
-        return false;
-    }
-    
-    @Override
-	public boolean isCubeShaped() {
-    	return false;
-    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMobSpawnerDeactivated.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawnerDeactivated.java
similarity index 83%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMobSpawnerDeactivated.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawnerDeactivated.java
index ec0bbf5b5..faa6eefdf 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMobSpawnerDeactivated.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawnerDeactivated.java
@@ -8,10 +8,10 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 
-public class BlockMobSpawnerDeactivated extends BlockTransparent {
-    public BlockMobSpawnerDeactivated(String key, String namespaceId, int id, Material material)
+public class BlockLogicMobSpawnerDeactivated extends BlockLogicTransparent {
+    public BlockLogicMobSpawnerDeactivated(Block<?> block)
     {
-        super(key, namespaceId, id, material);
+        super(block, Material.stone);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMoss.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMoss.java
similarity index 74%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMoss.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMoss.java
index 86fc4ab67..00f2150aa 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMoss.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMoss.java
@@ -13,12 +13,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Random;
 
-public class BlockMoss extends Block implements IBonemealable {
+public class BlockLogicMoss extends BlockLogic implements IBonemealable {
 	public static Map<Integer, Integer> variantMap = new HashMap<>();
-	public BlockMoss(String key, String namespaceId, int id, int parentId) {
-		super(key, namespaceId, id, Material.moss);
-		setTicking(true);
-		variantMap.put(parentId, id);
+	public BlockLogicMoss(Block<?> block, Block<?> parentBlock) {
+		super(block, Material.moss);
+		block.setTicking(true);
+		variantMap.put(parentBlock.id(), block.id());
 	}
 
 	@Override
@@ -54,9 +54,9 @@ public class BlockMoss extends Block implements IBonemealable {
 		}
 		
 		if (ignoreLight || !Block.isBuried(world, mossX, mossY, mossZ)) {
-			Block mossStone = getMossBlock(world.getBlockId(mossX, mossY, mossZ));
+			Block<?> mossStone = getMossBlock(world.getBlockId(mossX, mossY, mossZ));
 			if (mossStone != null) {
-				world.setBlockWithNotify(mossX, mossY, mossZ, mossStone.id);
+				world.setBlockWithNotify(mossX, mossY, mossZ, mossStone.id());
 				return true;
 			}
 		}
@@ -73,30 +73,33 @@ public class BlockMoss extends Block implements IBonemealable {
 		return true;
 	}
 
-	public static Block getMossBlock(int blockId) {
+	public static Block<?> getMossBlock(int blockId) {
 		if (blockId == 0)
 			return null;
 		return getMossBlock(Blocks.blocksList[blockId]);
 	}
 
-	public static Block getMossBlock(Block stoneBlock) {
+	public static Block<?> getMossBlock(Block<?> stoneBlock) {
 		return stoneToMossMap.get(stoneBlock);
 	}
 	
-	public static Block getStoneBlock(int blockId) {
+	public static Block<?> getStoneBlock(int blockId) {
 		if (blockId == 0)
 			return null;
 		return getStoneBlock(Blocks.blocksList[blockId]);
 	}
 	
-	public static Block getStoneBlock(Block mossBlock) {
+	public static Block<?> getStoneBlock(Block<?> mossBlock) {
 		return mossToStoneMap.get(mossBlock);
 	}
 
-	public static final Map<Block, Block> stoneToMossMap = new HashMap<>();
-	public static final Map<Block, Block> mossToStoneMap = new HashMap<>();
+	public static final Map<Block<?>, Block<?>> stoneToMossMap = new HashMap<>();
+	public static final Map<Block<?>, Block<?>> mossToStoneMap = new HashMap<>();
 
 	public static void initMossMap() {
+		stoneToMossMap.clear();
+		mossToStoneMap.clear();
+
 		stoneToMossMap.put(Blocks.STONE, Blocks.MOSS_STONE);
 		stoneToMossMap.put(Blocks.GRANITE, Blocks.MOSS_GRANITE);
 		stoneToMossMap.put(Blocks.LIMESTONE, Blocks.MOSS_LIMESTONE);
@@ -105,7 +108,7 @@ public class BlockMoss extends Block implements IBonemealable {
 		stoneToMossMap.put(Blocks.BRICK_STONE_POLISHED, Blocks.BRICK_STONE_POLISHED_MOSSY);
 		stoneToMossMap.put(Blocks.LOG_OAK, Blocks.LOG_OAK_MOSSY);
 		
-		for(Entry<Block, Block> entry : stoneToMossMap.entrySet()) {
+		for(Entry<Block<?>, Block<?>> entry : stoneToMossMap.entrySet()) {
 			mossToStoneMap.put(entry.getValue(), entry.getKey());
 		}
 	}
@@ -145,20 +148,21 @@ public class BlockMoss extends Block implements IBonemealable {
 					continue;
 				}
 
-				if(world.getBlockId(k1, l1, i2) == Blocks.STONE.id)
-					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_STONE.id);
-				else if(world.getBlockId(k1, l1, i2) == Blocks.LIMESTONE.id)
-					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_LIMESTONE.id);
-				else if(world.getBlockId(k1, l1, i2) == Blocks.GRANITE.id)
-					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_GRANITE.id);
-				else if(world.getBlockId(k1, l1, i2) == Blocks.BASALT.id)
-					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_BASALT.id);
-				else if(world.getBlockId(k1, l1, i2) == Blocks.COBBLE_STONE.id)
-					world.setBlockWithNotify(k1, l1, i2, Blocks.COBBLE_STONE_MOSSY.id);
-				else if(world.getBlockId(k1, l1, i2) == Blocks.BRICK_STONE_POLISHED.id)
-					world.setBlockWithNotify(k1, l1, i2, Blocks.BRICK_STONE_POLISHED_MOSSY.id);
-				else if(world.getBlockId(k1, l1, i2) == Blocks.LOG_OAK.id)
-					world.setBlockWithNotify(k1, l1, i2, Blocks.LOG_OAK_MOSSY.id);
+				int blockId = world.getBlockId(k1, l1, i2);
+				if(blockId == Blocks.STONE.id())
+					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_STONE.id());
+				else if(blockId == Blocks.LIMESTONE.id())
+					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_LIMESTONE.id());
+				else if(blockId == Blocks.GRANITE.id())
+					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_GRANITE.id());
+				else if(blockId == Blocks.BASALT.id())
+					world.setBlockWithNotify(k1, l1, i2, Blocks.MOSS_BASALT.id());
+				else if(blockId == Blocks.COBBLE_STONE.id())
+					world.setBlockWithNotify(k1, l1, i2, Blocks.COBBLE_STONE_MOSSY.id());
+				else if(blockId == Blocks.BRICK_STONE_POLISHED.id())
+					world.setBlockWithNotify(k1, l1, i2, Blocks.BRICK_STONE_POLISHED_MOSSY.id());
+				else if(blockId == Blocks.LOG_OAK.id())
+					world.setBlockWithNotify(k1, l1, i2, Blocks.LOG_OAK_MOSSY.id());
 
 			}
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMotionSensor.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMotionSensor.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMotionSensor.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMotionSensor.java
index 7f9756446..2c0bcdb7c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMotionSensor.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMotionSensor.java
@@ -13,14 +13,15 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockMotionSensor extends BlockTileEntityVeryRotatable
+public class BlockLogicMotionSensor extends BlockLogicVeryRotatable
 {
     public final boolean isActive;
 
-    public BlockMotionSensor(String key, String namespaceId, int id, boolean isActive)
+    public BlockLogicMotionSensor(Block<?> block, boolean isActive)
     {
-        super(key, namespaceId, id, Material.glass);
+        super(block, Material.glass);
         this.isActive = isActive;
+        block.withEntity(TileEntitySensor::new);
     }
 
     @Override
@@ -70,12 +71,6 @@ public class BlockMotionSensor extends BlockTileEntityVeryRotatable
         return isActive;
     }
 
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntitySensor();
-    }
-
     @Override
     public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity) {
         if (dropCause == EnumDropCause.IMPROPER_TOOL) {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMud.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMud.java
similarity index 78%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMud.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMud.java
index 10c9c4c29..ac2356d97 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMud.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMud.java
@@ -12,10 +12,10 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockMud extends Block{
-    public BlockMud(String key, String namespaceId, int id, Material material, boolean isHardened)
+public class BlockLogicMud extends BlockLogic {
+    public BlockLogicMud(Block<?> block, Material material, boolean isHardened)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         this.isHardened = isHardened;
     }
 
@@ -28,7 +28,7 @@ public class BlockMud extends Block{
     @Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+        world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
     }
 
     private boolean isWaterNearby(final World world, final int x, final int y, final int z, int range)
@@ -39,7 +39,7 @@ public class BlockMud extends Block{
             {
                 for (int z1 = z - range; z1 <= z + range; z1++)
                 {
-                    if (Block.hasTag(world.getBlockId(x1, y1, z1), BlockTags.IS_WATER))
+                    if (Blocks.hasTag(world.getBlockId(x1, y1, z1), BlockTags.IS_WATER))
                     {
                         return true;
                     }
@@ -59,7 +59,7 @@ public class BlockMud extends Block{
             {
                 for (int z1 = z - 1; z1 <= z + 1; z1++)
                 {
-                    if (Block.hasTag(world.getBlockId(x1, y1, z1), BlockTags.IS_LAVA))
+                    if (Blocks.hasTag(world.getBlockId(x1, y1, z1), BlockTags.IS_LAVA))
                     {
                         return true;
                     }
@@ -87,7 +87,7 @@ public class BlockMud extends Block{
                     {
                         //...And the block is next to another wet mud block, it can become wet
                         int bID = world.getBlockId(x1, y1, z1);
-                        if (bID == Blocks.MUD.id || (bID == Blocks.FARMLAND_DIRT.id && BlockFarmland.isWet(world.getBlockMetadata(x1, y1, z1))))
+                        if (bID == Blocks.MUD.id() || (bID == Blocks.FARMLAND_DIRT.id() && BlockLogicFarmland.isWet(world.getBlockMetadata(x1, y1, z1))))
                         {
                             return true;
                         }
@@ -102,7 +102,7 @@ public class BlockMud extends Block{
     @Override
 	public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
     {
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+        world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
     }
 
 
@@ -114,7 +114,7 @@ public class BlockMud extends Block{
 
     private void tryToFall(World world, int x, int y, int z)
     {
-        if(world.getBlockId(x, y, z) == Blocks.MUD_BAKED.id){
+        if(world.getBlockId(x, y, z) == Blocks.MUD_BAKED.id()){
             return;
         }
 
@@ -130,12 +130,12 @@ public class BlockMud extends Block{
                 for(; canFallBelow(world, x, y - 1, z) && y > 0; y--) { }
                 if(y > 0)
                 {
-                    world.setBlockWithNotify(x, y, z, id);
+                    world.setBlockWithNotify(x, y, z, block.id());
 
                 }
             } else
             {
-                EntityFallingBlock entityFallingBlock = new EntityFallingBlock(world, x + 0.5, y + 0.5, z + 0.5, id, 0, null);
+                EntityFallingBlock entityFallingBlock = new EntityFallingBlock(world, x + 0.5, y + 0.5, z + 0.5, block.id(), 0, null);
                 world.entityJoinedWorld(entityFallingBlock);
             }
         }
@@ -144,19 +144,7 @@ public class BlockMud extends Block{
     public static boolean canFallBelow(World world, int x, int y, int z)
     {
         int blockId = world.getBlockId(x, y, z);
-        if(blockId == 0)
-        {
-            return true;
-        }
-        if(blockId == Blocks.FIRE.id)
-        {
-            return true;
-        }
-        if(Block.hasTag(blockId, BlockTags.IS_WATER))
-        {
-            return true;
-        }
-        return Block.hasTag(blockId, BlockTags.IS_LAVA);
+        return blockId == 0 || blockId == Blocks.FIRE.id() || Blocks.hasTag(blockId, BlockTags.IS_WATER) || Blocks.hasTag(blockId, BlockTags.IS_LAVA);
     }
 
 
@@ -167,8 +155,8 @@ public class BlockMud extends Block{
         if(isHardened) {
             if(!isLavaNearby(world, x, y, z)) {
                 if (canBecomeWet(world, x, y, z)) {
-                    world.setBlock(x, y, z, Blocks.MUD.id);
-                    world.notifyBlockChange(x, y, z, Blocks.MUD.id);
+                    world.setBlock(x, y, z, Blocks.MUD.id());
+                    world.notifyBlockChange(x, y, z, Blocks.MUD.id());
                     return;
                 }
             }
@@ -176,14 +164,14 @@ public class BlockMud extends Block{
 
         // dry out mud
         if(!isHardened){
-            if(isLavaNearby(world, x, y, z) || world.dimension.id == Dimension.NETHER.id) {
+            if(isLavaNearby(world, x, y, z) || world.dimension == Dimension.NETHER) {
                 world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, x + 0.5D, y + 0.5D, z + 0.5D, "random.fizz", 0.5F, 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
                 for(int l = 0; l < 8; l++)
                 {
                     world.spawnParticle("largesmoke", (double)x + Math.random(), (double)y + Math.random(), (double)z + Math.random(), 0.0D, 0.0D, 0.0D, 0);
                 }
-                world.setBlock(x, y, z, Blocks.MUD_BAKED.id);
-                world.notifyBlockChange(x, y, z, Blocks.MUD_BAKED.id);
+                world.setBlock(x, y, z, Blocks.MUD_BAKED.id());
+                world.notifyBlockChange(x, y, z, Blocks.MUD_BAKED.id());
                 return;
             }
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockMushroom.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMushroom.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockMushroom.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicMushroom.java
index 4b2bb9d9d..8b58a6564 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockMushroom.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMushroom.java
@@ -4,15 +4,15 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockMushroom extends BlockFlower
+public class BlockLogicMushroom extends BlockLogicFlower
 {
 
-	public BlockMushroom(String key, String namespaceId, int id)
+	public BlockLogicMushroom(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
         float f = 0.2F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 2.0F, 0.5F + f);
-        setTicking(true);
+        block.setTicking(true);
     }
 
     @Override
@@ -29,7 +29,7 @@ public class BlockMushroom extends BlockFlower
                 int z2 = z + rand.nextInt(3) - 1;
                 if(world.isAirBlock(x2, randY, z2) && canBlockStay(world, x2, randY, z2))
                 {
-                    world.setBlockWithNotify(x2, randY, z2, id);
+                    world.setBlockWithNotify(x2, randY, z2, block.id());
                 }
             }
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockNetherrackIgneous.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicNetherrackIgneous.java
similarity index 73%
rename from game/core/src/main/java/net/minecraft/core/block/BlockNetherrackIgneous.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicNetherrackIgneous.java
index e6ef87d3d..27e3a4e03 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockNetherrackIgneous.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicNetherrackIgneous.java
@@ -10,10 +10,10 @@ import net.minecraft.core.world.WorldSource;
 
 import java.util.Random;
 
-public class BlockNetherrackIgneous extends Block{
-    public BlockNetherrackIgneous(String translationKey, String namespaceId, int id) {
-        super(translationKey, namespaceId, id, Material.netherrack);
-        setTicking(true);
+public class BlockLogicNetherrackIgneous extends BlockLogic {
+    public BlockLogicNetherrackIgneous(Block<?> block) {
+        super(block, Material.netherrack);
+        block.setTicking(true);
     }
 
     @Override
@@ -37,19 +37,19 @@ public class BlockNetherrackIgneous extends Block{
 
     @Override
     public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay() + world.rand.nextInt(5) - world.rand.nextInt(5));
+        world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay() + world.rand.nextInt(5) - world.rand.nextInt(5));
     }
 
     @Override
     public void onBlockPlacedByWorld(World world, int x, int y, int z) {
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay() + world.rand.nextInt(5) - world.rand.nextInt(5));
+        world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay() + world.rand.nextInt(5) - world.rand.nextInt(5));
     }
 
     public boolean canMelt(World world, int x, int y, int z) {
         boolean canMelt = false;
         for (Side side : Side.sides) {
-            Block block = world.getBlock(x + side.getOffsetX(), y + side.getOffsetY(), z + side.getOffsetZ());
-            Material adjacentMaterial = block == null ? Material.air : block.blockMaterial;
+            Block<?> block = world.getBlock(x + side.getOffsetX(), y + side.getOffsetY(), z + side.getOffsetZ());
+            Material adjacentMaterial = block == null ? Material.air : block.getMaterial();
             if (adjacentMaterial == Material.water) {
                 return false;
             }
@@ -61,7 +61,7 @@ public class BlockNetherrackIgneous extends Block{
     @Override
     public void updateTick(World world, int x, int y, int z, Random rand) {
         if (canMelt(world, x, y, z)) {
-            world.setBlockWithNotify(x, y, z, Blocks.FLUID_LAVA_FLOWING.id);
+            world.setBlockWithNotify(x, y, z, Blocks.FLUID_LAVA_FLOWING.id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockNote.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicNote.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockNote.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicNote.java
index 095bda4b3..f8be60f35 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockNote.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicNote.java
@@ -2,7 +2,6 @@ package net.minecraft.core.block;
 
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.entity.TileEntityActivator;
-import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.Direction;
@@ -16,7 +15,7 @@ import org.slf4j.Logger;
 import java.util.HashMap;
 import java.util.Map;
 
-public class BlockNote extends BlockTileEntity
+public class BlockLogicNote extends BlockLogic
 {
     private static final Logger LOGGER = LogUtils.getLogger();
     public static final int MASK_NOTE = 0b0011_1111;
@@ -24,9 +23,10 @@ public class BlockNote extends BlockTileEntity
 
     public static final byte MAX_NOTE = 24;
 
-    public BlockNote(String key, String namespaceId, int id)
+    public BlockLogicNote(Block<?> block)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
+        block.withEntity(null);
     }
 
     @Override
@@ -108,18 +108,6 @@ public class BlockNote extends BlockTileEntity
         world.spawnParticle("note", (double) x + 0.5D, (double) y + 1.2D, (double) z + 0.5D, 0.0, 0.0D, 0.0D, data);
     }
 
-
-    // These below 2 methods are for Legacy noteblock entity support, do not delete them or terrible things will happen
-    @Override
-    public void onBlockPlacedByWorld(World world, int x, int y, int z)
-    {
-    }
-
-    @Override
-    protected TileEntity getNewBlockEntity() {
-        return null;
-    }
-
     public static class Instrument {
         public static final Map<Integer, Instrument> instrumentMap = new HashMap<>();
         public final int index;
@@ -139,20 +127,20 @@ public class BlockNote extends BlockTileEntity
             return instrumentMap.getOrDefault(index, DEFAULT);
         }
 
-        public static @NotNull Instrument getInstrumentFromBlock(@Nullable Block block) {
+        public static @NotNull Instrument getInstrumentFromBlock(@Nullable Block<?> block) {
             if (block == null) return DEFAULT;
 
             if (block == Blocks.BLOCK_OLIVINE) {
                 return CHIP_TRIANGLE;
             }
-            if (block == Blocks.BLOCK_REDSTONE || block == Blocks.PUMPKIN_REDSTONE || block instanceof BlockOreRedstone) { // Should be any block thats basically just redstone
+            if (block == Blocks.BLOCK_REDSTONE || block == Blocks.PUMPKIN_REDSTONE || block.getLogic() instanceof BlockLogicOreRedstone) { // Should be any block thats basically just redstone
                 return GUITAR_ELECTRIC;
             }
             if (block == Blocks.CHEST_PLANKS_OAK || block == Blocks.CHEST_PLANKS_OAK_PAINTED) {
                 return WOOD_BLOCK;
             }
 
-            Material material = block.blockMaterial;
+            Material material = block.getMaterial();
             if (material == Material.permafrost || material == Material.ice) {
                 return CELESTA;
             }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOreCoal.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreCoal.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOreCoal.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOreCoal.java
index 4ba57e030..4664fdd7a 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOreCoal.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreCoal.java
@@ -10,13 +10,13 @@ import net.minecraft.core.world.World;
 import java.util.HashMap;
 import java.util.Map;
 
-public class BlockOreCoal extends Block
+public class BlockLogicOreCoal extends BlockLogic
 {
     public static Map<Integer, Integer> variantMap = new HashMap<>();
 
-    public BlockOreCoal(String key, String namespaceId, int id, int parentId, Material material){
-        super(key, namespaceId, id, material);
-        variantMap.put(parentId, id);
+    public BlockLogicOreCoal(Block<?> block, Block<?> parentBlock, Material material){
+        super(block, material);
+        variantMap.put(parentBlock.id(), block.id());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOreDiamond.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreDiamond.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOreDiamond.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOreDiamond.java
index 56f61dd6a..1d13014cc 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOreDiamond.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreDiamond.java
@@ -10,13 +10,13 @@ import net.minecraft.core.world.World;
 import java.util.HashMap;
 import java.util.Map;
 
-public class BlockOreDiamond extends Block
+public class BlockLogicOreDiamond extends BlockLogic
 {
     public static Map<Integer, Integer> variantMap = new HashMap<>();
-    public BlockOreDiamond(String key, String namespaceId, int id, int parentId, Material material)
+    public BlockLogicOreDiamond(Block<?> block, Block<?> parentBlock, Material material)
     {
-        super(key, namespaceId, id, material);
-        variantMap.put(parentId, id);
+        super(block, material);
+        variantMap.put(parentBlock.id(), block.id());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOreGold.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreGold.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOreGold.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOreGold.java
index 243f0799b..28905c573 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOreGold.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreGold.java
@@ -11,12 +11,12 @@ import java.util.HashMap;
 import java.util.Map;
 
 
-public class BlockOreGold extends Block {
+public class BlockLogicOreGold extends BlockLogic {
     public static Map<Integer, Integer> variantMap = new HashMap<>();
 
-    public BlockOreGold(String key, String namespaceId, int id, int parentId, Material material) {
-        super(key, namespaceId, id, material);
-        variantMap.put(parentId, id);
+    public BlockLogicOreGold(Block<?> block, Block<?> parentBlock, Material material) {
+        super(block, material);
+        variantMap.put(parentBlock.id(), block.id());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOreIron.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreIron.java
similarity index 81%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOreIron.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOreIron.java
index 0707e8981..242dede8f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOreIron.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreIron.java
@@ -10,12 +10,12 @@ import net.minecraft.core.world.World;
 import java.util.HashMap;
 import java.util.Map;
 
-public class BlockOreIron extends Block
+public class BlockLogicOreIron extends BlockLogic
 {
     public static Map<Integer, Integer> variantMap = new HashMap<>();
-    public BlockOreIron(String key, String namespaceId, int id, int parentID, Material material) {
-        super(key, namespaceId, id, material);
-        variantMap.put(parentID, id);
+    public BlockLogicOreIron(Block<?> block, Block<?> parentBlock, Material material) {
+        super(block, material);
+        variantMap.put(parentBlock.id(), block.id());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOreLapis.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreLapis.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOreLapis.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOreLapis.java
index 822422768..dbfcc4240 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOreLapis.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreLapis.java
@@ -11,13 +11,13 @@ import net.minecraft.core.world.World;
 import java.util.HashMap;
 import java.util.Map;
 
-public class BlockOreLapis extends Block
+public class BlockLogicOreLapis extends BlockLogic
 {
     public static Map<Integer, Integer> variantMap = new HashMap<>();
-    public BlockOreLapis(String key, String namespaceId, int id, int parentId, Material material)
+    public BlockLogicOreLapis(Block<?> block, Block<?> parentBlock, Material material)
     {
-        super(key, namespaceId, id, material);
-        variantMap.put(parentId, id);
+        super(block, material);
+        variantMap.put(parentBlock.id(), block.id());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOreNetherCoal.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreNetherCoal.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOreNetherCoal.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOreNetherCoal.java
index 52f7d1535..60d98c69d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOreNetherCoal.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreNetherCoal.java
@@ -7,12 +7,12 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 
-public class BlockOreNetherCoal extends Block
+public class BlockLogicOreNetherCoal extends BlockLogic
 {
 
-    public BlockOreNetherCoal(String key, String namespaceId, int id)
+    public BlockLogicOreNetherCoal(Block<?> block)
     {
-        super(key, namespaceId, id, Material.netherrack);
+        super(block, Material.netherrack);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOreRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreRedstone.java
similarity index 83%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOreRedstone.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOreRedstone.java
index 188e28b22..858cdf7e0 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOreRedstone.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreRedstone.java
@@ -13,26 +13,25 @@ import net.minecraft.core.block.material.Material;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Random;
-import java.util.function.Supplier;
 
-public class BlockOreRedstone extends Block
+public class BlockLogicOreRedstone extends BlockLogic
 {
     public static Map<Integer, Integer> variantMap = new HashMap<>();
     private final boolean illuminated;
-    private final Supplier<Block> normalBlock;
-    private final Supplier<Block> illuminatedBlock;
-    public BlockOreRedstone(String key, String namespaceId, int id, int parentId, Material material, boolean illuminated, Supplier<Block> normalBlock, Supplier<Block> illuminatedBlock)
+    private final Block<?> normalBlock;
+    private final Block<?> illuminatedBlock;
+    public BlockLogicOreRedstone(Block<?> block, Block<?> parentBlock, Material material, boolean illuminated, Block<?> normalBlock, Block<?> illuminatedBlock)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         if(illuminated)
         {
-            setTicking(true);
+            block.setTicking(true);
         }
         this.illuminated = illuminated;
         this.normalBlock = normalBlock;
         this.illuminatedBlock = illuminatedBlock;
-        if (parentId > 0){
-            variantMap.put(parentId, id);
+        if (parentBlock != null){
+            variantMap.put(parentBlock.id(), block.id());
         }
     }
 
@@ -62,7 +61,7 @@ public class BlockOreRedstone extends Block
         spawnParticles(world, x, y, z);
         if (!illuminated)
         {
-        	world.setBlockWithNotify(x, y, z, illuminatedBlock.get().id);
+        	world.setBlockWithNotify(x, y, z, illuminatedBlock.id());
         }
     }
 
@@ -71,7 +70,7 @@ public class BlockOreRedstone extends Block
     {
         if(illuminated)
         {
-            world.setBlockWithNotify(x, y, z, normalBlock.get().id);
+            world.setBlockWithNotify(x, y, z, normalBlock.id());
         }
     }
 
@@ -82,7 +81,7 @@ public class BlockOreRedstone extends Block
         {
             case SILK_TOUCH:
             case PICK_BLOCK:
-                return new ItemStack[] { new ItemStack(normalBlock.get()) };
+                return new ItemStack[] { new ItemStack(normalBlock) };
             case EXPLOSION:
             case PROPER_TOOL:
             case PISTON_CRUSH:
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockOverlayPebbles.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOverlayPebbles.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockOverlayPebbles.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicOverlayPebbles.java
index 2442aa9e5..4ecb2bf6d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockOverlayPebbles.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOverlayPebbles.java
@@ -9,19 +9,19 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockOverlayPebbles extends Block
+public class BlockLogicOverlayPebbles extends BlockLogic
 {
-    public BlockOverlayPebbles(String key, String namespaceId, int id, Material material)
+    public BlockLogicOverlayPebbles(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         setBlockBounds(0, 0, 0, 1, 0.0625F, 1);
     }
 
     @Override
     public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
-        Block block = world.getBlock(x, y - 1, z);
-        return block != null && block.blockMaterial.isSolid();
+        Block<?> block = world.getBlock(x, y - 1, z);
+        return block != null && block.getMaterial().isSolid();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPathDirt.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPathDirt.java
similarity index 76%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPathDirt.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPathDirt.java
index 19b8f929f..2b9271246 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPathDirt.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPathDirt.java
@@ -8,20 +8,20 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockPathDirt extends Block
+public class BlockLogicPathDirt extends BlockLogic
 {
-	public BlockPathDirt(String key, String namespaceId, int id)
+	public BlockLogicPathDirt(Block<?> block)
     {
-        super(key, namespaceId, id, Material.dirt);
-        setTicking(true);
+        super(block, Material.dirt);
+        block.setTicking(true);
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.9375F, 1.0F);
-        withLightBlock(255);
+        block.withLightBlock(255);
     }
 
     @Override
 	public AABB getCollisionBoundingBoxFromPool(WorldSource world, int x, int y, int z)
     {
-        return AABB.getTemporaryBB(x + 0, y + 0, z + 0, x + 1, y + 1, z + 1);
+        return AABB.getTemporaryBB(x, y, z, x + 1, y + 1, z + 1);
     }
 
     @Override
@@ -42,9 +42,9 @@ public class BlockPathDirt extends Block
         super.onNeighborBlockChange(world, x, y, z, blockId);
         Material material = world.getBlockMaterial(x, y + 1, z);
         int id = world.getBlockId(x, y + 1, z);
-        if(material.isSolid() && id != Blocks.FENCE_GATE_PLANKS_OAK.id && id != Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id && id != Blocks.SIGN_WALL_PLANKS_OAK.id)
+        if(material.isSolid() && id != Blocks.FENCE_GATE_PLANKS_OAK.id() && id != Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id() && id != Blocks.SIGN_WALL_PLANKS_OAK.id())
         {
-            world.setBlockWithNotify(x, y, z, Blocks.DIRT.id);
+            world.setBlockWithNotify(x, y, z, Blocks.DIRT.id());
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPiePumpkin.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPiePumpkin.java
similarity index 74%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPiePumpkin.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPiePumpkin.java
index 4248f8671..c14db095c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPiePumpkin.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPiePumpkin.java
@@ -4,12 +4,12 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockPiePumpkin extends BlockEdible
+public class BlockLogicPiePumpkin extends BlockLogicEdible
 {
 
-    public BlockPiePumpkin(String key, String namespaceId, int id)
+    public BlockLogicPiePumpkin(Block<?> block)
     {
-        super(key, namespaceId, id, 4, 5, () -> Items.FOOD_PUMPKIN_PIE);
+        super(block, 4, 5, () -> Items.FOOD_PUMPKIN_PIE);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicPlanks.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPlanks.java
new file mode 100644
index 000000000..87058f921
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPlanks.java
@@ -0,0 +1,17 @@
+package net.minecraft.core.block;
+
+import net.minecraft.core.block.material.Material;
+import net.minecraft.core.util.helper.DyeColor;
+import net.minecraft.core.world.World;
+
+public class BlockLogicPlanks extends BlockLogic implements IPaintable {
+    public BlockLogicPlanks(Block<?> block) {
+        super(block, Material.wood);
+    }
+
+    @Override
+    public void setColor(World world, int x, int y, int z, DyeColor color) {
+        world.setBlock(x, y, z, Blocks.PLANKS_OAK_PAINTED.id());
+        Blocks.PLANKS_OAK_PAINTED.getLogic().setColor(world, x, y, z, color);
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPlanksPainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPlanksPainted.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPlanksPainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPlanksPainted.java
index fff3ef678..951d1b47c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPlanksPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPlanksPainted.java
@@ -10,11 +10,11 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockPlanksPainted extends Block implements IPainted
+public class BlockLogicPlanksPainted extends BlockLogic implements IPainted
 {
-    public BlockPlanksPainted(String key, String namespaceId, int id)
+    public BlockLogicPlanksPainted(Block<?> block)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
     }
     
     @Override
@@ -46,7 +46,7 @@ public class BlockPlanksPainted extends Block implements IPainted
 
     @Override
     public void removeDye(World world, int x, int y, int z) {
-        world.setBlockWithNotify(x, y, z, Blocks.PLANKS_OAK.id);
+        world.setBlockWithNotify(x, y, z, Blocks.PLANKS_OAK.id());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPortal.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPortal.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java
index 1ff1eacf2..85d7ac890 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPortal.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java
@@ -10,13 +10,14 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.phys.AABB;
+import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockPortal extends BlockTransparent implements IPainted
+public class BlockLogicPortal extends BlockLogicTransparent implements IPainted
 {
     public static final int MAX_PORTAL_SIZE = 32;
     public static final int MASK_COLOR = 0b1111_0000;
@@ -25,16 +26,16 @@ public class BlockPortal extends BlockTransparent implements IPainted
 
     public static final int ORIENTATION_X = 0;
     public static final int ORIENTATION_Z = 1;
-	public int targetDimension;
-	public int portalFrameId;
-	public int portalTriggerId;
+	public Dimension targetDimension;
+	public Block<?> portalFrame;
+	public Block<?> portalTrigger;
 		
-    public BlockPortal(String key, String namespaceId, int id, int targetDimension, int portalMaterialId, int portalTriggerId)
+    public BlockLogicPortal(Block<?> block, Dimension targetDimension, Block<?> portalMaterial, Block<?> portalTrigger)
     {
-        super(key, namespaceId, id, Material.portal);
+        super(block, Material.portal);
         this.targetDimension = targetDimension;
-        this.portalFrameId = portalMaterialId;
-        this.portalTriggerId = portalTriggerId;
+        this.portalFrame = portalMaterial;
+        this.portalTrigger = portalTrigger;
     }
    
 
@@ -94,12 +95,12 @@ public class BlockPortal extends BlockTransparent implements IPainted
         boolean orientation = false;
         
         // Check if valid dimension
-        if (world.dimension.portalBlockId != -1 && world.dimension.portalBlockId != this.id) return null;
+        if (world.dimension.portalBlock != null && world.dimension.portalBlock != block) return null;
 
         // Sink to minimum Y
         for (int ry = 0; ry > -maxDims; ry--)
         {
-            if (world.getBlockId(x, y + ry, z) == portalFrameId)
+            if (world.getBlockId(x, y + ry, z) == portalFrame.id())
             {
                 foundBottom = true;
                 y += ry;
@@ -107,16 +108,16 @@ public class BlockPortal extends BlockTransparent implements IPainted
             }
         }
 
-        if (foundBottom == false) return null;
+        if (!foundBottom) return null;
 
         y++;
 
-        if (swapOrientation == false)
+        if (!swapOrientation)
         {
         	// Find orientation and minimum bound
         	for (int rx = 0; rx > -maxDims; rx--)
         	{
-        		if (world.getBlockId(x + rx, y, z) == portalFrameId)
+        		if (world.getBlockId(x + rx, y, z) == portalFrame.id())
         		{
         			foundOrientation = true;
         			orientation = false;
@@ -125,11 +126,11 @@ public class BlockPortal extends BlockTransparent implements IPainted
         		}
         	}
         	
-        	if (foundOrientation == false)
+        	if (!foundOrientation)
         	{
         		for (int rz = 0; rz > -maxDims; rz--)
         		{
-        			if (world.getBlockId(x, y, z + rz) == portalFrameId)
+        			if (world.getBlockId(x, y, z + rz) == portalFrame.id())
         			{
         				foundOrientation = true;
         				orientation = true;
@@ -144,7 +145,7 @@ public class BlockPortal extends BlockTransparent implements IPainted
         	// Find orientation and minimum bound
         	for (int rz = 0; rz > -maxDims; rz--)
         	{
-        		if (world.getBlockId(x, y, z + rz) == portalFrameId)
+        		if (world.getBlockId(x, y, z + rz) == portalFrame.id())
         		{
         			foundOrientation = true;
         			orientation = true;
@@ -153,11 +154,11 @@ public class BlockPortal extends BlockTransparent implements IPainted
         		}
         	}
         	
-        	if (foundOrientation == false)
+        	if (!foundOrientation)
         	{
         		for (int rx = 0; rx > -maxDims; rx--)
         		{
-        			if (world.getBlockId(x + rx, y, z) == portalFrameId)
+        			if (world.getBlockId(x + rx, y, z) == portalFrame.id())
         			{
         				foundOrientation = true;
         				orientation = false;
@@ -168,15 +169,15 @@ public class BlockPortal extends BlockTransparent implements IPainted
         	}
         }
 
-        if (foundOrientation == false) return null;
+        if (!foundOrientation) return null;
 
         // Find maximum bound
-        if (orientation == false)
+        if (!orientation)
         {
             // Find in X direction
             for (int rx = 1; rx < maxDims; rx++)
             {
-                if (world.getBlockId(x + rx, y, z) == portalFrameId)
+                if (world.getBlockId(x + rx, y, z) == portalFrame.id())
                 {
                     maxBoundA = rx;
                     break;
@@ -188,7 +189,7 @@ public class BlockPortal extends BlockTransparent implements IPainted
             // Find in Z direction
             for (int rz = 1; rz < maxDims; rz++)
             {
-                if (world.getBlockId(x, y, z + rz) == portalFrameId)
+                if (world.getBlockId(x, y, z + rz) == portalFrame.id())
                 {
                     maxBoundA = rz;
                     break;
@@ -207,7 +208,7 @@ public class BlockPortal extends BlockTransparent implements IPainted
         {
             if (y + ry >= world.getHeightBlocks()) return swapOrientation ? null : getPortalDims(world, ox, oy, oz, true, expectMiddle);
 
-            if (world.getBlockId(x + (orientation == false ? 1 : 0), y + ry, z + (orientation == true ? 1 : 0)) == portalFrameId)
+            if (world.getBlockId(x + (!orientation ? 1 : 0), y + ry, z + (orientation ? 1 : 0)) == portalFrame.id())
             {
                 maxBoundY = ry;
                 break;
@@ -225,16 +226,16 @@ public class BlockPortal extends BlockTransparent implements IPainted
                 // Check edges are correct
                 if (ra == 0 || ra == maxBoundA || ry == 0 || ry == maxBoundY)
                 {
-                    if (world.getBlockId(x + (orientation == false ? ra : 0), y + ry, z + (orientation == true ? ra : 0)) != portalFrameId)
+                    if (world.getBlockId(x + (!orientation ? ra : 0), y + ry, z + (orientation ? ra : 0)) != portalFrame.id())
                     {
                     	return swapOrientation ? null : getPortalDims(world, ox, oy, oz, true, expectMiddle);
                     }
                 }
                 else // Check interior is empty/fire
                 {
-                    int id = world.getBlockId(x + (orientation == false ? ra : 0), y + ry, z + (orientation == true ? ra : 0));
+                    int id = world.getBlockId(x + (!orientation ? ra : 0), y + ry, z + (orientation ? ra : 0));
 
-                    if (id != 0 && id != portalTriggerId && id != this.id)
+                    if (id != 0 && id != portalTrigger.id() && id != block.id())
                     {
                     	return swapOrientation ? null : getPortalDims(world, ox, oy, oz, true, expectMiddle);
                     }
@@ -249,9 +250,9 @@ public class BlockPortal extends BlockTransparent implements IPainted
             {
                 for (int ry = 1; ry < maxBoundY; ry++)
                 {
-                    int id = world.getBlockId(x + (orientation == false ? ra : 0), y + ry, z + (orientation == true ? ra : 0));
+                    int id = world.getBlockId(x + (!orientation ? ra : 0), y + ry, z + (orientation ? ra : 0));
 
-                    if (id != this.id)
+                    if (id != block.id())
                     {
                     	return swapOrientation ? null : getPortalDims(world, ox, oy, oz, true, true);
                     }
@@ -283,7 +284,7 @@ public class BlockPortal extends BlockTransparent implements IPainted
                 int _x = x + (bounds[0] == 0 ? ra : 0);
                 int _y = y + ry;
                 int _z = z + (bounds[0] == 1 ? ra : 0);
-                world.setBlockAndMetadata(_x, _y, _z, this.id, bounds[0] & 0x1);
+                world.setBlockAndMetadata(_x, _y, _z, block.id(), bounds[0] & 0x1);
             }
 
         }
@@ -335,7 +336,7 @@ public class BlockPortal extends BlockTransparent implements IPainted
         }
         if(entity.vehicle == null && entity.passenger == null)
         {
-            entity.handlePortal(this.id, getColor(world, x, y, z));
+            entity.handlePortal(block.id(), getColor(world, x, y, z));
         }
     }
 
@@ -356,7 +357,7 @@ public class BlockPortal extends BlockTransparent implements IPainted
             double xd = (rand.nextDouble() - 0.5D) * 0.5D;
             double yd = (rand.nextDouble() - 0.5D) * 0.5D;
             double zd = (rand.nextDouble() - 0.5D) * 0.5D;
-            if(world.getBlockId(x - 1, y, z) == id || world.getBlockId(x + 1, y, z) == id)
+            if(world.getBlockId(x - 1, y, z) == block.id() || world.getBlockId(x + 1, y, z) == block.id())
             {
                 pz = (double) z + 0.5D + 0.25D * (double)i1;
                 zd = rand.nextFloat() * 2.0D * (double)i1;
@@ -389,7 +390,7 @@ public class BlockPortal extends BlockTransparent implements IPainted
     @Override
     public void removeDye(World world, int x, int y, int z) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.STAIRS_PLANKS_OAK.id, stripColorFromMetadata(meta));
+        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.STAIRS_PLANKS_OAK.id(), stripColorFromMetadata(meta));
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPressurePlate.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPressurePlate.java
similarity index 87%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPressurePlate.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPressurePlate.java
index 0ca4062b0..7575767fc 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPressurePlate.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPressurePlate.java
@@ -13,17 +13,17 @@ import org.jetbrains.annotations.NotNull;
 import java.util.List;
 import java.util.Random;
 
-public class BlockPressurePlate extends Block
+public class BlockLogicPressurePlate<T extends Entity> extends BlockLogic
 {
     public static final int MASK_POWERED = 0b0000_0001;
     public static final int MASK_CEILING = 0b0000_0010;
-    private final Class<? extends Entity> triggerMobClass;
+    private final Class<T> triggerMobClass;
 
-	public BlockPressurePlate(String key, String namespaceId, int id, Class<? extends Entity> mobType, Material material)
+	public BlockLogicPressurePlate(Block<?> block, Class<T> mobType, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         triggerMobClass = mobType;
-        setTicking(true);
+        block.setTicking(true);
         float pixel = 1 / 16f;
         setBlockBounds(pixel, 0.0F, pixel, 1.0F - pixel, pixel / 2, 1.0F - pixel);
     }
@@ -100,7 +100,7 @@ public class BlockPressurePlate extends Block
         boolean isCeiling = onCeiling(meta);
         boolean isSteppedOn = false;
         float f = 0.125F;
-        List<Entity> list = world.getEntitiesWithinAABB(triggerMobClass, AABB.getTemporaryBB((float)x + f, y + (isCeiling ? .85f : 0f), (float)z + f, (float)(x + 1) - f, (double)y + (isCeiling ? 1 : 0.25D), (float)(z + 1) - f));;
+        List<T> list = world.getEntitiesWithinAABB(triggerMobClass, AABB.getTemporaryBB((float)x + f, y + (isCeiling ? .85f : 0f), (float)z + f, (float)(x + 1) - f, (double)y + (isCeiling ? 1 : 0.25D), (float)(z + 1) - f));;
         if(list != null && !list.isEmpty())
         {
             isSteppedOn = true;
@@ -108,22 +108,22 @@ public class BlockPressurePlate extends Block
         if(isSteppedOn && !isPressed)
         {
             world.setBlockMetadataWithNotify(x, y, z, meta | MASK_POWERED);
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y + (isCeiling ? 1 : -1), z, id);
+            world.notifyBlocksOfNeighborChange(x, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y + (isCeiling ? 1 : -1), z, id());
             world.markBlocksDirty(x, y, z, x, y, z);
             world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double)x + 0.5D, (double)y + 0.1D, (double)z + 0.5D, "random.click", 0.3F, 0.6F);
         }
         if(!isSteppedOn && isPressed)
         {
             world.setBlockMetadataWithNotify(x, y, z, meta & ~MASK_POWERED);
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y + (isCeiling ? 1 : -1), z, id);
+            world.notifyBlocksOfNeighborChange(x, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y + (isCeiling ? 1 : -1), z, id());
             world.markBlocksDirty(x, y, z, x, y, z);
             world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double)x + 0.5D, (double)y + 0.1D, (double)z + 0.5D, "random.click", 0.3F, 0.5F);
         }
         if(isSteppedOn)
         {
-            world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, id(), tickDelay());
         }
     }
 
@@ -133,8 +133,8 @@ public class BlockPressurePlate extends Block
         boolean isCeiling = onCeiling(world.getBlockMetadata(x, y, z));
         if(isPressed(data))
         {
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y + (isCeiling ? 1 : -1), z, id);
+            world.notifyBlocksOfNeighborChange(x, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y + (isCeiling ? 1 : -1), z, id());
         }
         super.onBlockRemoved(world, x, y, z, data);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPumice.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumice.java
similarity index 77%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPumice.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPumice.java
index 764b29e48..dc255f166 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPumice.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumice.java
@@ -9,11 +9,11 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockPumice extends Block {
+public class BlockLogicPumice extends BlockLogic {
     final boolean isWet;
-    public BlockPumice(String key, String namespaceId, int id, boolean isWet)
+    public BlockLogicPumice(Block<?> block, boolean isWet)
     {
-        super(key, namespaceId, id, Material.stone);
+        super(block, Material.stone);
         this.isWet = isWet;
     }
 
@@ -23,7 +23,7 @@ public class BlockPumice extends Block {
         super.onBlockPlacedByWorld(world, x, y, z);
         byte radius = 2;
         if(isWet && (inWater(world, x, y, z) || world.dimension.id == Dimension.PARADISE.id)){
-            world.setBlockWithNotify(x, y, z, Blocks.PUMICE_DRY.id);
+            world.setBlockWithNotify(x, y, z, Blocks.PUMICE_DRY.id());
             world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, x + 0.5D, y + 0.5D, z + 0.5D, "random.fizz", 0.5F, 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
             for(int l = 0; l < 8; l++)
             {
@@ -34,45 +34,45 @@ public class BlockPumice extends Block {
             for (int _x = x - radius; _x <= x + radius; _x++) {
                 for (int _y = y - radius; _y <= y + radius; _y++) {
                     for (int _z = z - radius; _z <= z + radius; _z++) {
-                        if (Block.hasTag(world.getBlockId(_x, _y, _z), BlockTags.IS_LAVA)) {
+                        if (Blocks.hasTag(world.getBlockId(_x, _y, _z), BlockTags.IS_LAVA)) {
                             world.setBlockWithNotify(_x, _y, _z, 0);
                         }
                     }
                 }
             }
-            world.setBlockWithNotify(x, y, z, Blocks.PUMICE_WET.id);
+            world.setBlockWithNotify(x, y, z, Blocks.PUMICE_WET.id());
         }
     }
 
 
     public boolean inLava(World world, int x, int y, int z){
-        if (Block.hasTag(world.getBlockId(x + 1, y, z), BlockTags.IS_LAVA))
+        if (Blocks.hasTag(world.getBlockId(x + 1, y, z), BlockTags.IS_LAVA))
             return true;
-        if (Block.hasTag(world.getBlockId(x - 1, y, z), BlockTags.IS_LAVA))
+        if (Blocks.hasTag(world.getBlockId(x - 1, y, z), BlockTags.IS_LAVA))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y + 1, z), BlockTags.IS_LAVA))
+        if (Blocks.hasTag(world.getBlockId(x, y + 1, z), BlockTags.IS_LAVA))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_LAVA))
+        if (Blocks.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_LAVA))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y , z + 1), BlockTags.IS_LAVA))
+        if (Blocks.hasTag(world.getBlockId(x, y , z + 1), BlockTags.IS_LAVA))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y , z - 1), BlockTags.IS_LAVA))
+        if (Blocks.hasTag(world.getBlockId(x, y , z - 1), BlockTags.IS_LAVA))
             return true;
         return false;
     }
 
     public boolean inWater(World world, int x, int y, int z){
-        if (Block.hasTag(world.getBlockId(x + 1, y, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x + 1, y, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x - 1, y, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x - 1, y, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y + 1, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y + 1, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y , z + 1), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y , z + 1), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y , z - 1), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y , z - 1), BlockTags.IS_WATER))
             return true;
         return false;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPumpkin.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkin.java
similarity index 66%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPumpkin.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkin.java
index ea902c242..2a79c1605 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPumpkin.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkin.java
@@ -9,16 +9,16 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
-public class BlockPumpkin extends BlockRotatable
+public class BlockLogicPumpkin extends BlockLogicRotatable
 {
     private final boolean isCarvable;
 
-	public BlockPumpkin(String key, String namespaceId, int id, boolean isCarvable)
+	public BlockLogicPumpkin(Block<?> block, boolean isCarvable)
     {
-        super(key, namespaceId, id, Material.vegetable);
-        setTicking(true);
+        super(block, Material.vegetable);
+        block.setTicking(true);
         this.isCarvable = isCarvable;
-        withOverrideColor(MaterialColor.paintedOrange);
+        block.withOverrideColor(MaterialColor.paintedOrange);
     }
 
     @Override
@@ -27,14 +27,10 @@ public class BlockPumpkin extends BlockRotatable
         ItemStack heldItem = player.getHeldItem();
         if (heldItem != null && heldItem.getItem() instanceof ItemToolSword){
             heldItem.damageItem(1,player);
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.PUMPKIN_CARVED_IDLE.id, player.getHorizontalPlacementDirection(Direction.getHorizontalDirection(player).getSide()).getOpposite().getId());
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.PUMPKIN_CARVED_IDLE.id(), player.getHorizontalPlacementDirection(Direction.getHorizontalDirection(player).getSide()).getOpposite().getId());
             return true;
         }
         return false;
     }
 
-    @Override
-    public void onBlockPlacedByWorld(World world, int x, int y, int z)
-    {
-    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPumpkinRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkinRedstone.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockPumpkinRedstone.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkinRedstone.java
index 5410f5bfe..ccc9ebe0c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPumpkinRedstone.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkinRedstone.java
@@ -5,17 +5,17 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockPumpkinRedstone extends BlockRotatable {
+public class BlockLogicPumpkinRedstone extends BlockLogicRotatable {
 
-    public BlockPumpkinRedstone(String translationKey, String namespaceId, int id) {
-        super(translationKey, namespaceId, id, Material.vegetable);
+    public BlockLogicPumpkinRedstone(Block<?> block) {
+        super(block, Material.vegetable);
     }
 
     @Override
     public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
         for (Side s : Side.sides){
-            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id);
+            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id());
         }
     }
 
@@ -23,7 +23,7 @@ public class BlockPumpkinRedstone extends BlockRotatable {
     public void onBlockRemoved(World world, int x, int y, int z, int data)
     {
         for (Side s : Side.sides){
-            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id);
+            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id());
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockRail.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRail.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockRail.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicRail.java
index c6b17eb1b..5b3a4ee52 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockRail.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRail.java
@@ -12,13 +12,14 @@ import net.minecraft.core.world.chunk.ChunkPosition;
 import java.util.ArrayList;
 import java.util.List;
 
-public class BlockRail extends Block {
+public class BlockLogicRail extends BlockLogic {
     public static final int MASK_DIRECTION = 0b0000_0111;
     public static final int MASK_POWERED = 0b0000_1000;
     public final boolean isPowered;
 
     public static boolean isRailBlockAt(World world, int x, int y, int z) {
-        return world.getBlock(x, y, z) instanceof BlockRail;
+        Block<?> b;
+        return (b = world.getBlock(x, y, z)) != null && b.getLogic() instanceof BlockLogicRail;
     }
     public RailDirection getRailDirection(WorldSource world, int x, int y, int z){
         int meta = world.getBlockMetadata(x, y, z);
@@ -28,8 +29,8 @@ public class BlockRail extends Block {
         return RailDirection.getFromMeta(meta);
     }
 
-    protected BlockRail(String key, String namespaceId, int id, boolean isPowered) {
-        super(key, namespaceId, id, Material.decoration);
+    protected BlockLogicRail(Block<?> block, boolean isPowered) {
+        super(block, Material.decoration);
         this.isPowered = isPowered;
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
     }
@@ -74,8 +75,8 @@ public class BlockRail extends Block {
     @Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z) {
         performRailTurn(world, x, y, z, true);
-        if(this == Blocks.RAIL_POWERED) {
-        	onNeighborBlockChange(world, x, y, z, id);
+        if(this.block == Blocks.RAIL_POWERED) {
+        	onNeighborBlockChange(world, x, y, z, id());
         }
     }
     @Override
@@ -93,9 +94,9 @@ public class BlockRail extends Block {
             return;
         }
 
-        Block block = Blocks.getBlock(blockId);
+        Block<?> block = Blocks.getBlock(blockId);
 
-        if(this == Blocks.RAIL_POWERED) {
+        if(this.block == Blocks.RAIL_POWERED) {
             boolean gettingPower =
                     world.hasNeighborSignal(x, y, z) ||
                     world.hasNeighborSignal(x, y + 1, z) ||
@@ -114,9 +115,9 @@ public class BlockRail extends Block {
             }
 
             if(changedMeta) {
-                world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+                world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
                 if(railDirection.isSloped()) {
-                    world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+                    world.notifyBlocksOfNeighborChange(x, y + 1, z, id());
                 }
             }
         } else if(block != null && block.isSignalSource() && Rail.getNAdjacentTracks(new Rail(world, x, y, z)) == 3) {
@@ -190,7 +191,7 @@ public class BlockRail extends Block {
 
     private boolean isConnectedPoweredRail2(World world, int x, int y, int z, boolean forward, int distance, Axis axis) {
         int blockId = world.getBlockId(x, y, z);
-        if(blockId == Blocks.RAIL_POWERED.id) {
+        if(blockId == Blocks.RAIL_POWERED.id()) {
             int meta = world.getBlockMetadata(x, y, z);
             boolean isPoweredFlagSet = (meta & MASK_POWERED) != 0;
             RailDirection direction = getRailDirection(world, x, y, z);
@@ -239,10 +240,10 @@ public class BlockRail extends Block {
             this.x = x;
             this.y = y;
             this.z = z;
-            Block block = world.getBlock(x, y, z);
+            Block<?> block = world.getBlock(x, y, z);
             int meta = world.getBlockMetadata(x, y, z);
 
-            isPoweredRail = block instanceof BlockRail && ((BlockRail) block).isPowered;
+            isPoweredRail = (block != null && block.getLogic() instanceof BlockLogicRail) && ((BlockLogicRail) block.getLogic()).isPowered;
 
             setConnections(RailDirection.getFromMeta(meta));
         }
@@ -266,23 +267,23 @@ public class BlockRail extends Block {
         }
 
         private boolean isMinecartTrack(int x, int y, int z) {
-            if(BlockRail.isRailBlockAt(world, x, y, z)) {
+            if(BlockLogicRail.isRailBlockAt(world, x, y, z)) {
                 return true;
             }
-            if(BlockRail.isRailBlockAt(world, x, y + 1, z)) {
+            if(BlockLogicRail.isRailBlockAt(world, x, y + 1, z)) {
                 return true;
             }
-            return BlockRail.isRailBlockAt(world, x, y - 1, z);
+            return BlockLogicRail.isRailBlockAt(world, x, y - 1, z);
         }
 
         private Rail getMinecartTrackLogic(ChunkPosition chunkposition) {
-            if(BlockRail.isRailBlockAt(world, chunkposition.x, chunkposition.y, chunkposition.z)) {
+            if(BlockLogicRail.isRailBlockAt(world, chunkposition.x, chunkposition.y, chunkposition.z)) {
                 return new Rail(world, chunkposition.x, chunkposition.y, chunkposition.z);
             }
-            if(BlockRail.isRailBlockAt(world, chunkposition.x, chunkposition.y + 1, chunkposition.z)) {
+            if(BlockLogicRail.isRailBlockAt(world, chunkposition.x, chunkposition.y + 1, chunkposition.z)) {
                 return new Rail(world, chunkposition.x, chunkposition.y + 1, chunkposition.z);
             }
-            if(BlockRail.isRailBlockAt(world, chunkposition.x, chunkposition.y - 1, chunkposition.z)) {
+            if(BlockLogicRail.isRailBlockAt(world, chunkposition.x, chunkposition.y - 1, chunkposition.z)) {
                 return new Rail(world, chunkposition.x, chunkposition.y - 1, chunkposition.z);
             } else {
                 return null;
@@ -403,18 +404,18 @@ public class BlockRail extends Block {
                 }
             }
             if(railType == RailDirection.STRAIGHT_NS) {
-                if(BlockRail.isRailBlockAt(world, x, y + 1, z - 1)) {
+                if(BlockLogicRail.isRailBlockAt(world, x, y + 1, z - 1)) {
                     railType = RailDirection.SLOPE_N;
                 }
-                if(BlockRail.isRailBlockAt(world, x, y + 1, z + 1)) {
+                if(BlockLogicRail.isRailBlockAt(world, x, y + 1, z + 1)) {
                     railType = RailDirection.SLOPE_S;
                 }
             }
             if(railType == RailDirection.STRAIGHT_EW) {
-                if(BlockRail.isRailBlockAt(world, x + 1, y + 1, z)) {
+                if(BlockLogicRail.isRailBlockAt(world, x + 1, y + 1, z)) {
                     railType = RailDirection.SLOPE_E;
                 }
-                if(BlockRail.isRailBlockAt(world, x - 1, y + 1, z)) {
+                if(BlockLogicRail.isRailBlockAt(world, x - 1, y + 1, z)) {
                     railType = RailDirection.SLOPE_W;
                 }
             }
@@ -471,18 +472,18 @@ public class BlockRail extends Block {
                 }
             }
             if(railDirection == RailDirection.STRAIGHT_NS) {
-                if(BlockRail.isRailBlockAt(world, x, y + 1, z - 1)) {
+                if(BlockLogicRail.isRailBlockAt(world, x, y + 1, z - 1)) {
                     railDirection = RailDirection.SLOPE_N;
                 }
-                if(BlockRail.isRailBlockAt(world, x, y + 1, z + 1)) {
+                if(BlockLogicRail.isRailBlockAt(world, x, y + 1, z + 1)) {
                     railDirection = RailDirection.SLOPE_S;
                 }
             }
             if(railDirection == RailDirection.STRAIGHT_EW) {
-                if(BlockRail.isRailBlockAt(world, x + 1, y + 1, z)) {
+                if(BlockLogicRail.isRailBlockAt(world, x + 1, y + 1, z)) {
                     railDirection = RailDirection.SLOPE_E;
                 }
-                if(BlockRail.isRailBlockAt(world, x - 1, y + 1, z)) {
+                if(BlockLogicRail.isRailBlockAt(world, x - 1, y + 1, z)) {
                     railDirection = RailDirection.SLOPE_W;
                 }
             }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockRailDetector.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRailDetector.java
similarity index 77%
rename from game/core/src/main/java/net/minecraft/core/block/BlockRailDetector.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicRailDetector.java
index 3332a6844..df2c001f8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockRailDetector.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRailDetector.java
@@ -9,11 +9,11 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.World;
-public class BlockRailDetector extends BlockRail {
-    public BlockRailDetector(String key, String namespaceId, int id)
+public class BlockLogicRailDetector extends BlockLogicRail {
+    public BlockLogicRailDetector(Block<?> block)
     {
-        super(key, namespaceId, id, true);
-        setTicking(true);
+        super(block, true);
+        block.setTicking(true);
     }
 
     @Override
@@ -67,27 +67,27 @@ public class BlockRailDetector extends BlockRail {
         boolean isPowered = (meta & MASK_POWERED) != 0;
         boolean minecartPresent = false;
         float offset = 0.125f;
-        List<Entity> list = world.getEntitiesWithinAABB(MinecartEntity.class, AABB.getTemporaryBB(x + offset, y + offset, z + offset, x + 1 - offset, y + 1 - offset, z + 1 - offset));
+        List<MinecartEntity> list = world.getEntitiesWithinAABB(MinecartEntity.class, AABB.getTemporaryBB(x + offset, y + offset, z + offset, x + 1 - offset, y + 1 - offset, z + 1 - offset));
         if(!list.isEmpty()) {
             minecartPresent = true;
         }
         if(minecartPresent && !isPowered) {
             // Set rail to powered
             world.setBlockMetadataWithNotify(x, y, z, meta | MASK_POWERED);
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+            world.notifyBlocksOfNeighborChange(x, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
             world.markBlockDirty(x, y, z);
         }
         if(!minecartPresent && isPowered) {
             // Set rail to unpowered
             world.setBlockMetadataWithNotify(x, y, z, meta & ~MASK_POWERED);
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+            world.notifyBlocksOfNeighborChange(x, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
             world.markBlockDirty(x, y, z);
         }
         if(minecartPresent) {
             // Schedule update if minecart in rail
-            world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+            world.scheduleBlockUpdate(x, y, z, id(), tickDelay());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRedstone.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/BlockRedstone.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicRedstone.java
index 4736796e4..748c6f92d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockRedstone.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRedstone.java
@@ -7,11 +7,11 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockRedstone extends Block
+public class BlockLogicRedstone extends BlockLogic
 {
-	public BlockRedstone(String key, String namespaceId, int id, Material material)
+	public BlockLogicRedstone(Block<?> block, Material material)
     {
-		super(key, namespaceId, id, material);
+		super(block, material);
 	}
 
 	@Override
@@ -36,7 +36,7 @@ public class BlockRedstone extends Block
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
         for (Side s : Side.sides){
-            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id);
+            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id());
         }
     }
 
@@ -44,7 +44,7 @@ public class BlockRedstone extends Block
     public void onBlockRemoved(World world, int x, int y, int z, int data)
     {
         for (Side s : Side.sides){
-            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id);
+            world.notifyBlocksOfNeighborChange(x + s.getOffsetX(), y + s.getOffsetY(), z + s.getOffsetZ(), id());
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockRepeater.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRepeater.java
similarity index 84%
rename from game/core/src/main/java/net/minecraft/core/block/BlockRepeater.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicRepeater.java
index ce3e7cb36..2e6fdd9ad 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockRepeater.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRepeater.java
@@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
-public class BlockRepeater extends Block
+public class BlockLogicRepeater extends BlockLogic
 {
     public static final double[] torchPosOffset = {
         -0.0625D, 0.0625D, 0.1875D, 0.3125D
@@ -29,9 +29,9 @@ public class BlockRepeater extends Block
 
     public final boolean isRepeaterPowered;
 
-	public BlockRepeater(String key, String namespaceId, int id, boolean flag)
+	public BlockLogicRepeater(Block<?> block, boolean flag)
     {
-        super(key, namespaceId, id, Material.decoration);
+        super(block, Material.decoration);
         isRepeaterPowered = flag;
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
     }
@@ -77,12 +77,12 @@ public class BlockRepeater extends Block
         int meta = world.getBlockMetadata(x, y, z);
         boolean flag = isGettingPower(world, x, y, z, meta);
         if(isRepeaterPowered && !flag) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.REPEATER_IDLE.id, meta);
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.REPEATER_IDLE.id(), meta);
         } else if(!isRepeaterPowered) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.REPEATER_ACTIVE.id, meta);
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.REPEATER_ACTIVE.id(), meta);
             if(!flag) {
                 int i1 = (meta & MASK_TICK_DELAY) >> 2;
-                world.scheduleBlockUpdate(x, y, z, Blocks.REPEATER_ACTIVE.id, tickDelayMap[i1] * 2);
+                world.scheduleBlockUpdate(x, y, z, Blocks.REPEATER_ACTIVE.id(), tickDelayMap[i1] * 2);
             }
         }
     }
@@ -121,9 +121,9 @@ public class BlockRepeater extends Block
         boolean flag = isGettingPower(world, x, y, z, meta);
         int tickDelay = (meta & MASK_TICK_DELAY) >> 2;
         if(isRepeaterPowered && !flag) {
-            world.scheduleBlockUpdate(x, y, z, id, tickDelayMap[tickDelay] * 2);
+            world.scheduleBlockUpdate(x, y, z, id(), tickDelayMap[tickDelay] * 2);
         } else if(!isRepeaterPowered && flag) {
-            world.scheduleBlockUpdate(x, y, z, id, tickDelayMap[tickDelay] * 2);
+            world.scheduleBlockUpdate(x, y, z, id(), tickDelayMap[tickDelay] * 2);
         }
     }
 
@@ -133,16 +133,16 @@ public class BlockRepeater extends Block
         switch(direction)
         {
         case 0: // '\0'
-            return world.getSignal(x, y, z + 1, Side.SOUTH) || world.getBlockId(x, y, z + 1) == Blocks.WIRE_REDSTONE.id && world.getBlockMetadata(x, y, z + 1) > 0;
+            return world.getSignal(x, y, z + 1, Side.SOUTH) || world.getBlockId(x, y, z + 1) == Blocks.WIRE_REDSTONE.id() && world.getBlockMetadata(x, y, z + 1) > 0;
 
         case 2: // '\002'
-            return world.getSignal(x, y, z - 1, Side.NORTH) || world.getBlockId(x, y, z - 1) == Blocks.WIRE_REDSTONE.id && world.getBlockMetadata(x, y, z - 1) > 0;
+            return world.getSignal(x, y, z - 1, Side.NORTH) || world.getBlockId(x, y, z - 1) == Blocks.WIRE_REDSTONE.id() && world.getBlockMetadata(x, y, z - 1) > 0;
 
         case 3: // '\003'
-            return world.getSignal(x + 1, y, z, Side.EAST) || world.getBlockId(x + 1, y, z) == Blocks.WIRE_REDSTONE.id && world.getBlockMetadata(x + 1, y, z) > 0;
+            return world.getSignal(x + 1, y, z, Side.EAST) || world.getBlockId(x + 1, y, z) == Blocks.WIRE_REDSTONE.id() && world.getBlockMetadata(x + 1, y, z) > 0;
 
         case 1: // '\001'
-            return world.getSignal(x - 1, y, z, Side.WEST) || world.getBlockId(x - 1, y, z) == Blocks.WIRE_REDSTONE.id && world.getBlockMetadata(x - 1, y, z) > 0;
+            return world.getSignal(x - 1, y, z, Side.WEST) || world.getBlockId(x - 1, y, z) == Blocks.WIRE_REDSTONE.id() && world.getBlockMetadata(x - 1, y, z) > 0;
         }
         return false;
     }
@@ -169,7 +169,7 @@ public class BlockRepeater extends Block
 		boolean flag = isGettingPower(world, x, y, z, l);
 		if(flag)
 		{
-		    world.scheduleBlockUpdate(x, y, z, id, 1);
+		    world.scheduleBlockUpdate(x, y, z, id(), 1);
 		}
     }
 
@@ -181,19 +181,19 @@ public class BlockRepeater extends Block
         boolean flag = isGettingPower(world, x, y, z, l);
         if(flag)
         {
-            world.scheduleBlockUpdate(x, y, z, id, 1);
+            world.scheduleBlockUpdate(x, y, z, id(), 1);
         }
     }
 
     @Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
-        world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
-        world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
-        world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
-        world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
-        world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
-        world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+        world.notifyBlocksOfNeighborChange(x + 1, y, z, id());
+        world.notifyBlocksOfNeighborChange(x - 1, y, z, id());
+        world.notifyBlocksOfNeighborChange(x, y, z + 1, id());
+        world.notifyBlocksOfNeighborChange(x, y, z - 1, id());
+        world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
+        world.notifyBlocksOfNeighborChange(x, y + 1, z, id());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockRope.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRope.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockRope.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicRope.java
index d81c2a43a..c41a0d261 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockRope.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRope.java
@@ -13,11 +13,11 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockRope
-    extends Block {
+public class BlockLogicRope
+    extends BlockLogic {
     public static final int MASK_ROPE_CONNECT = 0b1000_0000;
-    public BlockRope(String key, String namespaceId, int id) {
-        super(key, namespaceId,id, Material.cloth);
+    public BlockLogicRope(Block<?> block) {
+        super(block, Material.cloth);
     }
 
     @Override
@@ -43,12 +43,12 @@ public class BlockRope
     @Override
     public AABB getBlockBoundsFromState(WorldSource world, int x, int y, int z)
     {
-        boolean hasBlockNegX = world.getBlockId(x - 1, y, z) == this.id;
-        boolean hasBlockPosX = world.getBlockId(x + 1, y, z) == this.id;
-        boolean hasBlockNegY = world.getBlockId(x, y - 1, z) == this.id;
-        boolean hasBlockPosY = world.getBlockId(x, y + 1, z) == this.id || world.isBlockOpaqueCube(x, y + 1, z);
-        boolean hasBlockNegZ = world.getBlockId(x, y, z - 1) == this.id;
-        boolean hasBlockPosZ = world.getBlockId(x, y, z + 1) == this.id;
+        boolean hasBlockNegX = world.getBlockId(x - 1, y, z) == this.id();
+        boolean hasBlockPosX = world.getBlockId(x + 1, y, z) == this.id();
+        boolean hasBlockNegY = world.getBlockId(x, y - 1, z) == this.id();
+        boolean hasBlockPosY = world.getBlockId(x, y + 1, z) == this.id() || world.isBlockOpaqueCube(x, y + 1, z);
+        boolean hasBlockNegZ = world.getBlockId(x, y, z - 1) == this.id();
+        boolean hasBlockPosZ = world.getBlockId(x, y, z + 1) == this.id();
 
         float minX = 5 / 16.0f;
         float maxX = 11 / 16.0f;
@@ -91,15 +91,15 @@ public class BlockRope
     }
     
     public void pickUpRope(World world, int x, int y, int z, Player player) {
-    	if(world.isClientSide || world.getBlock(x, y, z) != this) {
+    	if(world.isClientSide || world.getBlock(x, y, z) != this.block) {
     		return;
     	}
     	
     	final int highestRope = y;
     	// Find the position of the lowest rope
     	while(y > 0) {
-    		Block block = world.getBlock(x, y - 1, z);
-    		if(block != this) {
+    		Block<?> block = world.getBlock(x, y - 1, z);
+    		if(block != this.block) {
     			break;
     		}
     		y--;
@@ -138,7 +138,7 @@ public class BlockRope
         	}	
     	}
     	
-    	world.playBlockSoundEffect(player, x + 0.5, highestRope + 0.5, z + 0.5, this, EnumBlockSoundEffectType.PLACE);
+    	world.playBlockSoundEffect(player, x + 0.5, highestRope + 0.5, z + 0.5, block, EnumBlockSoundEffectType.PLACE);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockRotatable.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRotatable.java
similarity index 87%
rename from game/core/src/main/java/net/minecraft/core/block/BlockRotatable.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicRotatable.java
index b024201b6..4f6fc2717 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockRotatable.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRotatable.java
@@ -7,10 +7,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 
-public abstract class BlockRotatable extends Block{
+public abstract class BlockLogicRotatable extends BlockLogic {
     public static final int MASK_DIRECTION = 0b0000_0111;
-    public BlockRotatable(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
+    public BlockLogicRotatable(Block<?> block, Material material) {
+        super(block, material);
     }
 
     public static Direction getDirectionFromMeta(int meta)
@@ -30,7 +30,7 @@ public abstract class BlockRotatable extends Block{
     @Override
     public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
         if (!side.isHorizontal()) side = Side.SOUTH;
-        world.setBlockMetadataWithNotify(x, y, z, BlockRotatable.setDirection(0, side.getDirection()));
+        world.setBlockMetadataWithNotify(x, y, z, BlockLogicRotatable.setDirection(0, side.getDirection()));
     }
 
     public static void setDefaultDirection(World world, int x, int y, int z)
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSand.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSand.java
similarity index 77%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSand.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSand.java
index 66e9fd101..7fcb7733c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSand.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSand.java
@@ -7,24 +7,24 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockSand extends Block
+public class BlockLogicSand extends BlockLogic
 {
 
-    public BlockSand(String key, String namespaceId, int id)
+    public BlockLogicSand(Block<?> block)
     {
-        super(key, namespaceId, id, Material.sand);
+        super(block, Material.sand);
     }
 
     @Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+        world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
     }
 
     @Override
 	public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
     {
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+        world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
     }
 
     @Override
@@ -44,11 +44,11 @@ public class BlockSand extends Block
                 for(; canFallBelow(world, x, y - 1, z) && y > 0; y--) { }
                 if(y > 0)
                 {
-                    world.setBlockWithNotify(x, y, z, id);
+                    world.setBlockWithNotify(x, y, z, block.id());
                 }
             } else
             {
-                EntityFallingBlock entityFallingBlock = new EntityFallingBlock(world, x + 0.5, y + 0.5, z + 0.5, id, 0, null);
+                EntityFallingBlock entityFallingBlock = new EntityFallingBlock(world, x + 0.5, y + 0.5, z + 0.5, block.id(), 0, null);
                 world.entityJoinedWorld(entityFallingBlock);
             }
         }
@@ -62,7 +62,7 @@ public class BlockSand extends Block
 
     public static boolean canFallBelow(World world, int x, int y, int z)
     {
-        Block block = world.getBlock(x, y, z);
+        Block<?> block = world.getBlock(x, y, z);
         return block == null || block.hasTag(BlockTags.PLACE_OVERWRITES);
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingBase.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBase.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingBase.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBase.java
index 0b0652607..e90f16de9 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingBase.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBase.java
@@ -10,13 +10,13 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public abstract class BlockSaplingBase extends BlockFlower implements IBonemealable
+public abstract class BlockLogicSaplingBase extends BlockLogicFlower implements IBonemealable
 {
 	public boolean canGrowOnSand = false;
 
-	public BlockSaplingBase(String key, String namespaceId, int id)
+	public BlockLogicSaplingBase(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
         float f = 0.4F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 2.0F, 0.5F + f);
     }
@@ -24,7 +24,7 @@ public abstract class BlockSaplingBase extends BlockFlower implements IBonemeala
 	@Override
 	public boolean mayPlaceOn(int blockId)
     {
-        return blockId == Blocks.SAND.id || super.mayPlaceOn(blockId);
+        return blockId == Blocks.SAND.id() || super.mayPlaceOn(blockId);
     }
 
     @Override
@@ -36,8 +36,8 @@ public abstract class BlockSaplingBase extends BlockFlower implements IBonemeala
         }
 
         if(!canGrowOnSand) {
-            if(world.getBlockId(x, y -1, z) == Blocks.SAND.id) {
-                world.setBlockWithNotify(x, y, z, Blocks.DEADBUSH.id);
+            if(world.getBlockId(x, y -1, z) == Blocks.SAND.id()) {
+                world.setBlockWithNotify(x, y, z, Blocks.DEADBUSH.id());
             }	
         }
 
@@ -63,7 +63,7 @@ public abstract class BlockSaplingBase extends BlockFlower implements IBonemeala
     public boolean onBonemealUsed(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced){
         if(!world.isClientSide)
         {
-            ((BlockSaplingBase)Blocks.blocksList[id]).growTree(world, blockX, blockY, blockZ, world.rand);
+            growTree(world, blockX, blockY, blockZ, world.rand);
             if (player == null || player.getGamemode().consumeBlocks())
             {
                 itemstack.stackSize--;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingBirch.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBirch.java
similarity index 69%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingBirch.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBirch.java
index 9b92072a0..5efc283cb 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingBirch.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBirch.java
@@ -6,12 +6,12 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 
 import java.util.Random;
 
-public class BlockSaplingBirch extends BlockSaplingBase
+public class BlockLogicSaplingBirch extends BlockLogicSaplingBase
 {
 
-	public BlockSaplingBirch(String key, String namespaceId, int id)
+	public BlockLogicSaplingBirch(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
 
 
@@ -21,11 +21,11 @@ public class BlockSaplingBirch extends BlockSaplingBase
 
         world.setBlock(x, y, z, 0);
 
-        WorldFeature tree = new WorldFeatureTree(Blocks.LEAVES_BIRCH.id, Blocks.LOG_BIRCH.id, 5);
+        WorldFeature tree = new WorldFeatureTree(Blocks.LEAVES_BIRCH.id(), Blocks.LOG_BIRCH.id(), 5);
 
         if(!tree.place(world, random, x, y, z))
         {
-            world.setBlock(x, y, z, id);
+            world.setBlock(x, y, z, id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingCacao.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCacao.java
similarity index 51%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingCacao.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCacao.java
index e7086fe14..04d90e460 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingCacao.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCacao.java
@@ -6,23 +6,23 @@ import net.minecraft.core.world.generate.feature.tree.WorldFeatureTree;
 
 import java.util.Random;
 
-public class BlockSaplingCacao extends BlockSaplingBase
+public class BlockLogicSaplingCacao extends BlockLogicSaplingBase
 {
 
-    public BlockSaplingCacao(String key, String namespaceId, int id)
+    public BlockLogicSaplingCacao(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
 
     @Override
     public void growTree(World world, int x, int y, int z, Random random)
     {
-        Object treeSmall = new WorldFeatureTree(Blocks.LEAVES_CACAO.id, Blocks.LOG_OAK_MOSSY.id, 4);
+        WorldFeature treeSmall = new WorldFeatureTree(Blocks.LEAVES_CACAO.id(), Blocks.LOG_OAK_MOSSY.id(), 4);
         world.setBlock(x, y, z, 0);
 
-        if(!((WorldFeature) (treeSmall)).place(world, random, x, y, z))
+        if(!treeSmall.place(world, random, x, y, z))
         {
-                world.setBlock(x, y, z, id);
+                world.setBlock(x, y, z, id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingCherry.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCherry.java
similarity index 71%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingCherry.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCherry.java
index 2da2ab4a8..9fd501014 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingCherry.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCherry.java
@@ -7,25 +7,25 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTreeCherry;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTreeFancy;
 
-public class BlockSaplingCherry extends BlockSaplingBase
+public class BlockLogicSaplingCherry extends BlockLogicSaplingBase
 {
 
-	public BlockSaplingCherry(String key, String namespaceId, int id)
+	public BlockLogicSaplingCherry(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
 
     @Override
 	public void growTree(World world, int x, int y, int z, Random random)
     {
-        WorldFeature treeBig  = new WorldFeatureTreeFancy(Blocks.LEAVES_CHERRY.id, Blocks.LOG_CHERRY.id);
-        WorldFeature treeSmall = new WorldFeatureTreeCherry(Blocks.LEAVES_CHERRY.id, Blocks.LOG_CHERRY.id, 4);
+        WorldFeature treeBig  = new WorldFeatureTreeFancy(Blocks.LEAVES_CHERRY.id(), Blocks.LOG_CHERRY.id());
+        WorldFeature treeSmall = new WorldFeatureTreeCherry(Blocks.LEAVES_CHERRY.id(), Blocks.LOG_CHERRY.id(), 4);
         world.setBlock(x, y, z, 0);
 
         if(!treeSmall.place(world, random, x, y, z))
         {
             if(!treeBig.place(world, random, x, y, z)) {
-                world.setBlock(x, y, z, id);
+                world.setBlock(x, y, z, id());
             }
         }
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingEucalyptus.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingEucalyptus.java
similarity index 68%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingEucalyptus.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingEucalyptus.java
index db7174b2b..74c99042b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingEucalyptus.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingEucalyptus.java
@@ -6,12 +6,12 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 
 import java.util.Random;
 
-public class BlockSaplingEucalyptus extends BlockSaplingBase
+public class BlockLogicSaplingEucalyptus extends BlockLogicSaplingBase
 {
 
-	public BlockSaplingEucalyptus(String key, String namespaceId, int id)
+	public BlockLogicSaplingEucalyptus(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
     
     @Override
@@ -20,11 +20,11 @@ public class BlockSaplingEucalyptus extends BlockSaplingBase
 
         world.setBlock(x, y, z, 0);
 
-        WorldFeature tree = new WorldFeatureTreeEucalyptus(Blocks.LEAVES_EUCALYPTUS.id, Blocks.LOG_EUCALYPTUS.id);
+        WorldFeature tree = new WorldFeatureTreeEucalyptus(Blocks.LEAVES_EUCALYPTUS.id(), Blocks.LOG_EUCALYPTUS.id());
         tree.init(1.0D, 1.0D, 1.0D);
         if(!tree.place(world, random, x, y, z))
         {
-            world.setBlock(x, y, z, id);
+            world.setBlock(x, y, z, id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingOak.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingOak.java
similarity index 73%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingOak.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingOak.java
index 3e4cacce2..e1176335f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingOak.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingOak.java
@@ -7,25 +7,25 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 
 import java.util.Random;
 
-public class BlockSaplingOak extends BlockSaplingBase
+public class BlockLogicSaplingOak extends BlockLogicSaplingBase
 {
 
-	public BlockSaplingOak(String key, String namespaceId, int id)
+	public BlockLogicSaplingOak(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
     
     @Override
 	public void growTree(World world, int x, int y, int z, Random random)
     {
-    	WorldFeature treeBig = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id);
-        WorldFeature treeSmall = new WorldFeatureTree(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id, 4);
+    	WorldFeature treeBig = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id());
+        WorldFeature treeSmall = new WorldFeatureTree(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id(), 4);
     	world.setBlock(x, y, z, 0);
 
         if(!treeSmall.place(world, random, x, y, z))
         {
             if(!treeBig.place(world, random, x, y, z)) {
-                world.setBlock(x, y, z, id);
+                world.setBlock(x, y, z, id());
             }
         }
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingPalm.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingPalm.java
similarity index 76%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingPalm.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingPalm.java
index 2ad4876a4..1d7214e41 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingPalm.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingPalm.java
@@ -5,17 +5,17 @@ import java.util.Random;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTreePalm;
 
-public class BlockSaplingPalm extends BlockSaplingBase {
+public class BlockLogicSaplingPalm extends BlockLogicSaplingBase {
 
-	public BlockSaplingPalm(String key, String namespaceId, int id) {
-		super(key, namespaceId, id);
+	public BlockLogicSaplingPalm(Block<?> block) {
+		super(block);
 		
 		this.canGrowOnSand = true;
 	}
 	
 	@Override
 	public void growTree(World world, int x, int y, int z, Random random) {
-    	boolean big = world.getBlockId(x, y - 1, z) != Blocks.SAND.id;
+    	boolean big = world.getBlockId(x, y - 1, z) != Blocks.SAND.id();
     	
     	new WorldFeatureTreePalm(Blocks.LOG_PALM, Blocks.LEAVES_PALM, big, true, false).place(world, random, x, y, z);
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingPine.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingPine.java
similarity index 67%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingPine.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingPine.java
index f783e9865..0ec3595da 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingPine.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingPine.java
@@ -7,12 +7,12 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 
 import java.util.Random;
 
-public class BlockSaplingPine extends BlockSaplingBase
+public class BlockLogicSaplingPine extends BlockLogicSaplingBase
 {
 
-	public BlockSaplingPine(String key, String namespaceId, int id)
+	public BlockLogicSaplingPine(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
 
     @Override
@@ -40,15 +40,15 @@ public class BlockSaplingPine extends BlockSaplingBase
     @Override
 	public void growTree(World world, int x, int y, int z, Random random)
     {
-        Object treeBig  = new WorldFeatureTreeTaigaTall(Blocks.LEAVES_PINE.id, Blocks.LOG_PINE.id);
-        Object treeSmall = new WorldFeatureTreeTaigaBushy(Blocks.LEAVES_PINE.id, Blocks.LOG_PINE.id);
+        WorldFeature treeBig  = new WorldFeatureTreeTaigaTall(Blocks.LEAVES_PINE.id(), Blocks.LOG_PINE.id());
+        WorldFeature treeSmall = new WorldFeatureTreeTaigaBushy(Blocks.LEAVES_PINE.id(), Blocks.LOG_PINE.id());
         
     	world.setBlock(x, y, z, 0);
 
-        if(!((WorldFeature) (treeSmall)).place(world, random, x, y, z))
+        if(!treeSmall.place(world, random, x, y, z))
         {
-            if(!((WorldFeature) (treeBig)).place(world, random, x, y, z)) {
-                world.setBlock(x, y, z, id);
+            if(!treeBig.place(world, random, x, y, z)) {
+                world.setBlock(x, y, z, id());
             }
         }
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingRetro.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingRetro.java
similarity index 72%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingRetro.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingRetro.java
index 24e2c885b..37b2fc574 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingRetro.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingRetro.java
@@ -7,26 +7,26 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 
 import java.util.Random;
 
-public class BlockSaplingRetro extends BlockSaplingBase
+public class BlockLogicSaplingRetro extends BlockLogicSaplingBase
 {
 
-	public BlockSaplingRetro(String key, String namespaceId, int id)
+	public BlockLogicSaplingRetro(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
 
 
     @Override
 	public void growTree(World world, int x, int y, int z, Random random)
     {
-        WorldFeature treeBig  = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK_RETRO.id, Blocks.LOG_OAK.id);
-        WorldFeature treeSmall = new WorldFeatureTree(Blocks.LEAVES_OAK_RETRO.id, Blocks.LOG_OAK.id, 4);
+        WorldFeature treeBig  = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK_RETRO.id(), Blocks.LOG_OAK.id());
+        WorldFeature treeSmall = new WorldFeatureTree(Blocks.LEAVES_OAK_RETRO.id(), Blocks.LOG_OAK.id(), 4);
         world.setBlock(x, y, z, 0);
 
         if(!treeSmall.place(world, random, x, y, z))
         {
             if(!treeBig.place(world, random, x, y, z)) {
-                world.setBlock(x, y, z, id);
+                world.setBlock(x, y, z, id());
             }
         }
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingShrub.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingShrub.java
similarity index 69%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingShrub.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingShrub.java
index 4a329f5e7..488b42591 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingShrub.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingShrub.java
@@ -6,12 +6,12 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 
 import java.util.Random;
 
-public class BlockSaplingShrub extends BlockSaplingBase
+public class BlockLogicSaplingShrub extends BlockLogicSaplingBase
 {
 
-	public BlockSaplingShrub(String key, String namespaceId, int id)
+	public BlockLogicSaplingShrub(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
     
     @Override
@@ -20,11 +20,11 @@ public class BlockSaplingShrub extends BlockSaplingBase
 
         world.setBlock(x, y, z, 0);
 
-        WorldFeature tree = new WorldFeatureTreeShrub(Blocks.LEAVES_SHRUB.id, Blocks.LOG_OAK.id);
+        WorldFeature tree = new WorldFeatureTreeShrub(Blocks.LEAVES_SHRUB.id(), Blocks.LOG_OAK.id());
         
         if(!tree.place(world, random, x, y, z))
         {
-            world.setBlock(x, y, z, id);
+            world.setBlock(x, y, z, id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingThorn.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingThorn.java
similarity index 67%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSaplingThorn.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingThorn.java
index 59ba350e7..9a5a74d83 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSaplingThorn.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingThorn.java
@@ -6,12 +6,12 @@ import net.minecraft.core.world.generate.feature.WorldFeature;
 
 import java.util.Random;
 
-public class BlockSaplingThorn extends BlockSaplingBase
+public class BlockLogicSaplingThorn extends BlockLogicSaplingBase
 {
 
-    public BlockSaplingThorn(String key, String namespaceId, int id)
+    public BlockLogicSaplingThorn(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
     }
 
 
@@ -20,11 +20,11 @@ public class BlockSaplingThorn extends BlockSaplingBase
     {
 
         world.setBlock(x, y, z, 0);
-        WorldFeature treeFeature = new WorldFeatureTreeThorn(1, Blocks.LOG_THORN.id, 0, Blocks.LEAVES_THORN.id, 0);
+        WorldFeature treeFeature = new WorldFeatureTreeThorn(1, Blocks.LOG_THORN.id(), 0, Blocks.LEAVES_THORN.id(), 0);
 
         if(!treeFeature.place(world, random, x, y, z))
         {
-            world.setBlock(x, y, z, id);
+            world.setBlock(x, y, z, id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSeat.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSeat.java
similarity index 86%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSeat.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSeat.java
index 268be8395..7a46e4ab6 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSeat.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSeat.java
@@ -10,13 +10,12 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
-public class BlockSeat
-    extends BlockTileEntity
+public class BlockLogicSeat extends BlockLogic
 {
-    public BlockSeat(String key, String namespaceId, int id) {
-        super(key, namespaceId, id, Material.wood);
-        
+    public BlockLogicSeat(Block<?> block) {
+        super(block, Material.wood);
         setBlockBounds(0f, 0f, 0f, 1f, 9f / 16f, 1f);
+        block.withEntity(() -> new TileEntitySeat(block));
     }
 
     @Override
@@ -54,11 +53,6 @@ public class BlockSeat
     public boolean isSolidRender() {
         return false;
     }
-    
-    @Override
-    protected TileEntity getNewBlockEntity() {
-        return new TileEntitySeat(this);
-    }
 
     @Override
     public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity) {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSign.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSign.java
similarity index 94%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSign.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSign.java
index 02db3af0a..11124b42c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSign.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSign.java
@@ -13,17 +13,18 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockSign extends BlockTileEntity
+public class BlockLogicSign extends BlockLogic
 {
     private final boolean isFreeStanding;
 
-	public BlockSign(String key, String namespaceId, int id, boolean isFreeStanding)
+	public BlockLogicSign(Block<?> block, boolean isFreeStanding)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
         this.isFreeStanding = isFreeStanding;
         float f = 0.25F;
         float f1 = 1.0F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f1, 0.5F + f);
+        block.withEntity(TileEntitySign::new);
     }
 
     @Override
@@ -94,12 +95,6 @@ public class BlockSign extends BlockTileEntity
         return false;
     }
 
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntitySign();
-    }
-
     @Override
 	public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
     {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSlab.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlab.java
similarity index 85%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSlab.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSlab.java
index 84bfed3e5..e5ba5926a 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSlab.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlab.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.material.MaterialColor;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.Mob;
@@ -18,24 +19,31 @@ import org.jetbrains.annotations.NotNull;
 
 import java.util.Random;
 
-public class BlockSlab extends Block
+public class BlockLogicSlab extends BlockLogic
 {
+    public Block<?> modelBlock;
+    public int modelBlockMetadata;
 
-    public BlockSlab(Block modelBlock, String namespaceId, int id)
+    public BlockLogicSlab(Block<?> block, Block<?> modelBlock)
     {
-        this(modelBlock, namespaceId, id, 0);
-        setBlockItem(() -> new ItemBlockSlab(this));
+        this(modelBlock, modelBlock, 0);
+        block.setBlockItem(() -> new ItemBlockSlab<>(block));
     }
-    
-    public BlockSlab(Block modelBlock, String namespaceId, int id, int modelBlockMetadata)
+
+    public BlockLogicSlab(Block<?> block, Block<?> modelBlock, int modelBlockMetadata)
     {
-    	super("slab." + modelBlock.key.substring(5), namespaceId, id, modelBlock.blockMaterial);
+    	super(block, Material.stone);
         this.modelBlock = modelBlock;
         this.modelBlockMetadata = modelBlockMetadata;
-        withHardness(modelBlock.blockHardness);
-        withBlastResistance(modelBlock.blastResistance / 3F);
-        withLightEmission(Blocks.lightEmission[modelBlock.id]);
-        withLightBlock(1);
+        block.withHardness(modelBlock.blockHardness);
+        block.withBlastResistance(modelBlock.blastResistance / 3F);
+        block.withLightEmission(modelBlock.emission);
+        block.withLightBlock(1);
+    }
+
+    @Override
+    public @NotNull Material getMaterial() {
+        return modelBlock.getMaterial();
     }
 
     @Override
@@ -83,10 +91,10 @@ public class BlockSlab extends Block
         {
             for (ItemStack stack : result)
             {
-                if (stack.itemID == modelBlock.id)
+                if (stack.itemID == modelBlock.id())
                 {
                     stack.setMetadata(meta & 0xF0);
-                    stack.itemID = this.id;
+                    stack.itemID = this.id();
                     if ((meta & 0x3) == 1 && dropCause != EnumDropCause.PICK_BLOCK) stack.stackSize = 2;
                     else stack.stackSize = 1;
                 }
@@ -105,10 +113,10 @@ public class BlockSlab extends Block
         {
             for (ItemStack stack : result)
             {
-                if (stack.itemID == modelBlock.id)
+                if (stack.itemID == modelBlock.id())
                 {
                     stack.setMetadata(meta & 0xF0);
-                    stack.itemID = this.id;
+                    stack.itemID = this.id();
                     if ((meta & 0x3) == 1 && dropCause != EnumDropCause.PICK_BLOCK) stack.stackSize = 2;
                     else stack.stackSize = 1;
                 }
@@ -123,12 +131,12 @@ public class BlockSlab extends Block
     {
         return modelBlock.tickDelay();
     }
-
     @Override
     public void handleEntityInside(World world, int x, int y, int z, Entity entity, Vec3 entityVelocity)
     {
         modelBlock.handleEntityInside(world, x, y, z, entity, entityVelocity);
     }
+
     @Override
     public boolean isCollidable()
     {
@@ -144,11 +152,10 @@ public class BlockSlab extends Block
     @Override
 	public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
-        return world.getBlockId(x, y -1, z) == id ||
-                world.getBlockId(x, y +1, z) == id ||
+        return world.getBlockId(x, y -1, z) == id() ||
+                world.getBlockId(x, y +1, z) == id() ||
                 super.canPlaceBlockAt(world, x, y, z);
     }
-
     @Override
     public void onEntityWalking(World world, int x, int y, int z, Entity entity)
     {
@@ -164,6 +171,7 @@ public class BlockSlab extends Block
     {
         return modelBlock.onBlockRightClicked(world, x, y, z, player, side, xPlaced, yPlaced);
     }
+
     @Override
     public void onBlockDestroyedByExplosion(World world, int x, int y, int z)
     {
@@ -189,7 +197,7 @@ public class BlockSlab extends Block
             world.setBlockMetadataWithNotify(x, y, z, 0);
         }
     }
-    
+
     @Override
 	public void onBlockPlacedByWorld(World world, int x, int y, int z)
     {
@@ -208,24 +216,21 @@ public class BlockSlab extends Block
     {
         return modelBlock.getBlockBrightness(blockAccess, x, y, z);
     }
-    
+
     @Override
     public void onBlockLeftClicked(World world, int x, int y, int z, Player player, Side side, double xHit, double yHit)
     {
         modelBlock.onBlockLeftClicked(world, x, y, z, player, side, xHit, yHit);
     }
-
     @Override
 	public void animationTick(World world, int x, int y, int z, Random rand)
     {
         modelBlock.animationTick(world, x, y, z, rand);
     }
+
     @Override
-    public MaterialColor getMaterialColor(){
+    public @NotNull MaterialColor getMaterialColor(){
         return modelBlock.getMaterialColor();
     }
 
-    public Block modelBlock;
-    public int modelBlockMetadata;
-
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSlabPaintable.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlabPaintable.java
similarity index 54%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSlabPaintable.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSlabPaintable.java
index 2952fb178..f06aa7f0e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSlabPaintable.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlabPaintable.java
@@ -3,15 +3,15 @@ package net.minecraft.core.block;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.world.World;
 
-public class BlockSlabPaintable extends BlockSlab implements IPaintable {
-    public BlockSlabPaintable(Block modelBlock, String namespaceId, int id) {
-        super(modelBlock, namespaceId, id);
+public class BlockLogicSlabPaintable extends BlockLogicSlab implements IPaintable {
+    public BlockLogicSlabPaintable(Block<?> block, Block<?> modelBlock) {
+        super(block, modelBlock);
     }
 
     @Override
     public void setColor(World world, int x, int y, int z, DyeColor color) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadata(x, y, z, Blocks.SLAB_PLANKS_PAINTED.id, meta);
-        ((IPaintable) Blocks.SLAB_PLANKS_PAINTED).setColor(world, x, y, z, color);
+        world.setBlockAndMetadata(x, y, z, Blocks.SLAB_PLANKS_PAINTED.id(), meta);
+        Blocks.SLAB_PLANKS_PAINTED.getLogic().setColor(world, x, y, z, color);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSlabPainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlabPainted.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSlabPainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSlabPainted.java
index 1e00cbd03..438524d4c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSlabPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlabPainted.java
@@ -10,11 +10,11 @@ import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockSlabPainted extends BlockSlab implements IPainted
+public class BlockLogicSlabPainted extends BlockLogicSlab implements IPainted
 {
-	public BlockSlabPainted(Block modelBlock, String namespaceId, int id)
+	public BlockLogicSlabPainted(Block<?> block, Block<?> modelBlock)
 	{
-		super(modelBlock, namespaceId, id);
+		super(block, modelBlock);
 	}
 	
 	@Override
@@ -52,7 +52,7 @@ public class BlockSlabPainted extends BlockSlab implements IPainted
 	@Override
 	public void removeDye(World world, int x, int y, int z) {
 		final int meta = world.getBlockMetadata(x, y, z);
-		world.setBlockAndMetadataWithNotify(x, y, z, Blocks.PLANKS_OAK.id, meta & 0xF);
+		world.setBlockAndMetadataWithNotify(x, y, z, Blocks.PLANKS_OAK.id(), meta & 0xF);
 	}
 
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlippery.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlippery.java
new file mode 100644
index 000000000..7a8aa2e09
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlippery.java
@@ -0,0 +1,11 @@
+package net.minecraft.core.block;
+
+import net.minecraft.core.block.material.Material;
+
+public class BlockLogicSlippery extends BlockLogic {
+
+    public BlockLogicSlippery(Block<?> block, Material material) {
+        super(block, material);
+        block.friction = 0.98F;
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSnow.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSnow.java
similarity index 87%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSnow.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSnow.java
index 1edae8d5c..2f2b636bb 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSnow.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSnow.java
@@ -10,13 +10,13 @@ import net.minecraft.core.block.material.Material;
 
 import java.util.Random;
 
-public class BlockSnow extends Block
+public class BlockLogicSnow extends BlockLogic
 {
 
-	public BlockSnow(String key, String namespaceId, int id)
+	public BlockLogicSnow(Block<?> block)
     {
-        super(key, namespaceId, id, Material.snow);
-        setTicking(true);
+        super(block, Material.snow);
+        block.setTicking(true);
     }
 
     public int quantityDropped(int meta, Random rand)
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSoulSand.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSoulSand.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSoulSand.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSoulSand.java
index 3086d2d15..b326e2e02 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSoulSand.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSoulSand.java
@@ -6,12 +6,12 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockSoulSand extends Block
+public class BlockLogicSoulSand extends BlockLogic
 {
 
-    public BlockSoulSand(String key, String namespaceId, int id)
+    public BlockLogicSoulSand(Block<?> block)
     {
-        super(key, namespaceId, id, Material.soulsand);
+        super(block, Material.soulsand);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSpikes.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpikes.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSpikes.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSpikes.java
index 51c8ca404..d3ba8da2a 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSpikes.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpikes.java
@@ -16,13 +16,13 @@ import net.minecraft.core.util.helper.DamageType;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.NotNull;
 
-public class BlockSpikes extends Block
+public class BlockLogicSpikes extends BlockLogic
 {
     public static final int MASK_POWERED = 0b0000_0001;
 
-    public BlockSpikes(String key, String namespaceId, int id, Material mat)
+    public BlockLogicSpikes(Block<?> block, Material mat)
     {
-        super(key, namespaceId, id, mat);
+        super(block, mat);
     }
 
     @Override
@@ -46,7 +46,7 @@ public class BlockSpikes extends Block
     @Override
 	public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
-        return world.canPlaceOnSurfaceOfBlock(x, y -1, z) || world.getBlockId(x, y - 1, z) == Blocks.MOBSPAWNER.id;
+        return world.canPlaceOnSurfaceOfBlock(x, y -1, z) || world.getBlockId(x, y - 1, z) == Blocks.MOBSPAWNER.id();
     }
 
 	@Override
@@ -55,7 +55,7 @@ public class BlockSpikes extends Block
 			return;
 		}
 		
-		boolean destroy = !world.canPlaceOnSurfaceOfBlock(x, y - 1, z) && world.getBlockId(x, y - 1, z) != Blocks.MESH.id && world.getBlockId(x, y - 1, z) != Blocks.MOBSPAWNER.id;
+		boolean destroy = !world.canPlaceOnSurfaceOfBlock(x, y - 1, z) && world.getBlockId(x, y - 1, z) != Blocks.MESH.id() && world.getBlockId(x, y - 1, z) != Blocks.MOBSPAWNER.id();
 		if(destroy) {
 			dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
 			world.setBlockWithNotify(x, y, z, 0);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSpinifex.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpinifex.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSpinifex.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSpinifex.java
index d8d413723..18fb54366 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSpinifex.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpinifex.java
@@ -5,12 +5,12 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 
-public class BlockSpinifex extends BlockFlower
+public class BlockLogicSpinifex extends BlockLogicFlower
 {
 
-	public BlockSpinifex(String key, String namespaceId, int id)
+	public BlockLogicSpinifex(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
         float f = 0.4F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.8F, 0.5F + f);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSponge.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSponge.java
similarity index 82%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSponge.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSponge.java
index 37a3a523a..ae5ae401e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSponge.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSponge.java
@@ -9,12 +9,12 @@ import net.minecraft.core.world.World;
 
 import java.util.Random;
 
-public class BlockSponge extends Block
+public class BlockLogicSponge extends BlockLogic
 {
     final boolean isWet;
-	public BlockSponge(String key, String namespaceId, int id, boolean isWet)
+	public BlockLogicSponge(Block<?> block, boolean isWet)
     {
-        super(key, namespaceId, id, Material.sponge);
+        super(block, Material.sponge);
         this.isWet = isWet;
     }
 
@@ -23,8 +23,8 @@ public class BlockSponge extends Block
     {
         super.onBlockPlacedByWorld(world, x, y, z);
         byte byte0 = 2;
-        if(world.dimension.id == Dimension.NETHER.id && isWet){
-            world.setBlockWithNotify(x, y, z, Blocks.SPONGE_DRY.id);
+        if(world.dimension == Dimension.NETHER && isWet){
+            world.setBlockWithNotify(x, y, z, Blocks.SPONGE_DRY.id());
             world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, x + 0.5D, y + 0.5D, z + 0.5D, "random.fizz", 0.5F, 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
             for(int l = 0; l < 8; l++)
             {
@@ -35,30 +35,30 @@ public class BlockSponge extends Block
             for (int l = x - byte0; l <= x + byte0; l++) {
                 for (int i1 = y - byte0; i1 <= y + byte0; i1++) {
                     for (int j1 = z - byte0; j1 <= z + byte0; j1++) {
-                        if (Block.hasTag(world.getBlockId(l, i1, j1), BlockTags.IS_WATER)) {
+                        if (Blocks.hasTag(world.getBlockId(l, i1, j1), BlockTags.IS_WATER)) {
                             world.setBlockWithNotify(l, i1, j1, 0);
 
                         }
                     }
                 }
             }
-            world.setBlockWithNotify(x, y, z, Blocks.SPONGE_WET.id);
+            world.setBlockWithNotify(x, y, z, Blocks.SPONGE_WET.id());
         }
     }
 
 
     public boolean inWater(World world, int x, int y, int z){
-        if (Block.hasTag(world.getBlockId(x + 1, y, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x + 1, y, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x - 1, y, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x - 1, y, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y + 1, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y + 1, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y - 1, z), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y , z + 1), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y , z + 1), BlockTags.IS_WATER))
             return true;
-        if (Block.hasTag(world.getBlockId(x, y , z - 1), BlockTags.IS_WATER))
+        if (Blocks.hasTag(world.getBlockId(x, y , z - 1), BlockTags.IS_WATER))
             return true;
         return false;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockStairs.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairs.java
similarity index 92%
rename from game/core/src/main/java/net/minecraft/core/block/BlockStairs.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicStairs.java
index d2c46316f..d17029996 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockStairs.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairs.java
@@ -4,6 +4,7 @@ import java.util.ArrayList;
 import java.util.Random;
 
 import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.material.MaterialColor;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.entity.player.Player;
@@ -18,7 +19,7 @@ import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 
-public class BlockStairs extends Block
+public class BlockLogicStairs extends BlockLogic
 {
 //    private static final Map<Integer, BoundingVolume> selectionVolumes = new HashMap<>();
 //
@@ -81,13 +82,20 @@ public class BlockStairs extends Block
 //        selectionVolumes.put(0b1011, vol);
 //    }
 
-	public BlockStairs(Block block, String namespaceId, int id)
+    public Block<?> modelBlock;
+
+	public BlockLogicStairs(Block<?> block, Block<?> modelBlock)
     {
-        super("stairs." + block.key.substring(5), namespaceId, id, block.blockMaterial);
-        modelBlock = block;
-        withHardness(block.blockHardness);
-        withBlastResistance(block.blastResistance / 3F);
-        withLightBlock(255);
+        super(block, Material.stone);
+        this.modelBlock = modelBlock;
+        block.withHardness(block.blockHardness);
+        block.withBlastResistance(block.blastResistance / 3F);
+        block.withLightBlock(255);
+    }
+
+    @Override
+    public @NotNull Material getMaterial() {
+        return modelBlock.getMaterial();
     }
 
     @Override
@@ -101,7 +109,7 @@ public class BlockStairs extends Block
     {
         return false;
     }
-    
+
     @Override
     public boolean canPlaceOnSurfaceOnCondition(World world, int x, int y, int z) {
     	return (world.getBlockMetadata(x, y, z) & 8) > 0;
@@ -145,10 +153,10 @@ public class BlockStairs extends Block
         {
             for (ItemStack stack : result)
             {
-                if (stack.itemID == modelBlock.id)
+                if (stack.itemID == modelBlock.id())
                 {
                     stack.setMetadata(meta & 0xF0);
-                    stack.itemID = this.id;
+                    stack.itemID = this.id();
                 }
             }
         }
@@ -165,10 +173,10 @@ public class BlockStairs extends Block
         {
             for (ItemStack stack : result)
             {
-                if (stack.itemID == modelBlock.id)
+                if (stack.itemID == modelBlock.id())
                 {
                     stack.setMetadata(meta & 0xF0);
-                    stack.itemID = this.id;
+                    stack.itemID = this.id();
                 }
             }
         }
@@ -205,7 +213,6 @@ public class BlockStairs extends Block
     {
         return modelBlock.tickDelay();
     }
-
 //    @Override
 //    public BoundingVolume getBoundingVolume(World world, int x, int y, int z)
 //    {
@@ -213,6 +220,7 @@ public class BlockStairs extends Block
 //        return selectionVolumes.getOrDefault(meta & 0x0F, null);
 //    }
 
+
     @Override
     public void handleEntityInside(World world, int x, int y, int z, Entity entity, Vec3 entityVelocity)
     {
@@ -267,11 +275,11 @@ public class BlockStairs extends Block
     {
         modelBlock.onBlockDestroyedByExplosion(world, x, y, z);
     }
-    
+
     @Override
     public void onBlockPlacedByMob(World world, int x, int y, int z, @NotNull Side side, Mob mob, double xPlaced, double yPlaced) {
 //    	System.out.println("Placed Side: "+side+" Height: "+sideHeight);
-    	
+
         int meta = world.getBlockMetadata(x, y, z) & 0xF0;
 
         Direction hRotation = mob.getHorizontalPlacementDirection(side).getOpposite();
@@ -311,10 +319,8 @@ public class BlockStairs extends Block
     public float getAmbientOcclusionStrength(WorldSource blockAccess, int x, int y, int z) {
     	return 0.0f;
     }
-
     @Override
-    public MaterialColor getMaterialColor(){
+    public @NotNull MaterialColor getMaterialColor(){
         return modelBlock.getMaterialColor();
     }
-    public Block modelBlock;
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockStairsPaintable.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairsPaintable.java
similarity index 53%
rename from game/core/src/main/java/net/minecraft/core/block/BlockStairsPaintable.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicStairsPaintable.java
index 833b05b3f..b1c8de1a1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockStairsPaintable.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairsPaintable.java
@@ -3,15 +3,15 @@ package net.minecraft.core.block;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.world.World;
 
-public class BlockStairsPaintable extends BlockStairs implements IPaintable {
-    public BlockStairsPaintable(Block block, String namespaceId, int id) {
-        super(block, namespaceId, id);
+public class BlockLogicStairsPaintable extends BlockLogicStairs implements IPaintable {
+    public BlockLogicStairsPaintable(Block<?> block, Block<?> modelBlock) {
+        super(block, modelBlock);
     }
 
     @Override
     public void setColor(World world, int x, int y, int z, DyeColor color) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadata(x, y, z, Blocks.STAIRS_PLANKS_PAINTED.id, meta);
-        ((IPaintable) Blocks.STAIRS_PLANKS_PAINTED).setColor(world, x, y, z, color);
+        world.setBlockAndMetadata(x, y, z, Blocks.STAIRS_PLANKS_PAINTED.id(), meta);
+        Blocks.STAIRS_PLANKS_PAINTED.getLogic().setColor(world, x, y, z, color);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockStairsPainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairsPainted.java
similarity index 77%
rename from game/core/src/main/java/net/minecraft/core/block/BlockStairsPainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicStairsPainted.java
index 3f15f550e..ee1966f1a 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockStairsPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairsPainted.java
@@ -3,9 +3,9 @@ package net.minecraft.core.block;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.world.World;
 
-public class BlockStairsPainted extends BlockStairs implements IPainted {
-    public BlockStairsPainted(Block block, String namespaceId, int id) {
-        super(block, namespaceId, id);
+public class BlockLogicStairsPainted extends BlockLogicStairs implements IPainted {
+    public BlockLogicStairsPainted(Block<?> block, Block<?> modelBlock) {
+        super(block, modelBlock);
     }
 
     @Override
@@ -26,7 +26,7 @@ public class BlockStairsPainted extends BlockStairs implements IPainted {
     @Override
     public void removeDye(World world, int x, int y, int z) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.STAIRS_PLANKS_OAK.id, stripColorFromMetadata(meta));
+        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.STAIRS_PLANKS_OAK.id(), stripColorFromMetadata(meta));
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockStone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStone.java
similarity index 81%
rename from game/core/src/main/java/net/minecraft/core/block/BlockStone.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicStone.java
index 8b3559dff..2649185b6 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockStone.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStone.java
@@ -11,15 +11,14 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.chunk.Chunk;
 
 import java.util.Random;
-import java.util.function.Supplier;
 
-public class BlockStone extends Block {
+public class BlockLogicStone extends BlockLogic {
 
-	private final Supplier<Block> cobblestoneSupplier;
+	private final Block<?> cobble;
 
-	public BlockStone(String key, String namespaceId, int id, Supplier<Block> cobbleStoneSupplier, Material material) {
-		super(key, namespaceId, id, material);
-		this.cobblestoneSupplier = cobbleStoneSupplier;
+	public BlockLogicStone(Block<?> block, Block<?> cobbleStone, Material material) {
+		super(block, material);
+		this.cobble = cobbleStone;
 	}
 
 	@Override
@@ -56,7 +55,7 @@ public class BlockStone extends Block {
 			case WORLD:
 			case EXPLOSION:
 			case PROPER_TOOL:
-				return new ItemStack[] { new ItemStack(cobblestoneSupplier.get()) };
+				return new ItemStack[] { new ItemStack(cobble) };
 			case PICK_BLOCK:
 			case SILK_TOUCH:
 				return new ItemStack[] { new ItemStack(this) };
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSugarcane.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSugarcane.java
similarity index 79%
rename from game/core/src/main/java/net/minecraft/core/block/BlockSugarcane.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicSugarcane.java
index 55af54518..c06688617 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSugarcane.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSugarcane.java
@@ -16,15 +16,15 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class BlockSugarcane extends Block implements IBonemealable
+public class BlockLogicSugarcane extends BlockLogic implements IBonemealable
 {
 
-	public BlockSugarcane(String key, String namespaceId, int id)
+	public BlockLogicSugarcane(Block<?> block)
     {
-        super(key, namespaceId, id, Material.plant);
+        super(block, Material.plant);
         float f = 0.375F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 1.0F, 0.5F + f);
-        setTicking(true);
+        block.setTicking(true);
     }
 
     @Override
@@ -33,13 +33,13 @@ public class BlockSugarcane extends Block implements IBonemealable
         if(world.isAirBlock(x, y + 1, z))
         {
             int l;
-            for(l = 1; world.getBlockId(x, y - l, z) == id; l++) { }
+            for(l = 1; world.getBlockId(x, y - l, z) == id(); l++) { }
             if(l < 3)
             {
                 int i1 = world.getBlockMetadata(x, y, z);
                 if(i1 == 15)
                 {
-                    world.setBlockWithNotify(x, y + 1, z, id);
+                    world.setBlockWithNotify(x, y + 1, z, id());
                     world.setBlockMetadataWithNotify(x, y, z, 0);
                 } else
                 {
@@ -51,9 +51,9 @@ public class BlockSugarcane extends Block implements IBonemealable
 
     public void growReedOnTop(World world, int x, int y, int z){
             int l;
-            for(l = 1; world.getBlockId(x, y + l, z) == id; l++) { }
+            for(l = 1; world.getBlockId(x, y + l, z) == id(); l++) { }
             if(world.isAirBlock(x, y+l, z)){
-                world.setBlockWithNotify(x, y + l, z, id);
+                world.setBlockWithNotify(x, y + l, z, id());
             }
     }
 
@@ -61,7 +61,7 @@ public class BlockSugarcane extends Block implements IBonemealable
 	public boolean canPlaceBlockAt(World world, int x, int y, int z)
     {
         int l = world.getBlockId(x, y - 1, z);
-        if(l == id)
+        if(l == id())
         {
             return true;
         }
@@ -73,19 +73,19 @@ public class BlockSugarcane extends Block implements IBonemealable
         {
             return false;
         }
-        if(Block.hasTag(world.getBlockId(x - 1, y - 1, z), BlockTags.IS_WATER))
+        if(Blocks.hasTag(world.getBlockId(x - 1, y - 1, z), BlockTags.IS_WATER))
         {
             return true;
         }
-        if(Block.hasTag(world.getBlockId(x + 1, y - 1, z), BlockTags.IS_WATER))
+        if(Blocks.hasTag(world.getBlockId(x + 1, y - 1, z), BlockTags.IS_WATER))
         {
             return true;
         }
-        if(Block.hasTag(world.getBlockId(x, y - 1, z - 1), BlockTags.IS_WATER))
+        if(Blocks.hasTag(world.getBlockId(x, y - 1, z - 1), BlockTags.IS_WATER))
         {
             return true;
         }
-        return Block.hasTag(world.getBlockId(x, y - 1, z + 1), BlockTags.IS_WATER);
+        return Blocks.hasTag(world.getBlockId(x, y - 1, z + 1), BlockTags.IS_WATER);
     }
 
     @Override
@@ -137,7 +137,7 @@ public class BlockSugarcane extends Block implements IBonemealable
     public boolean onBonemealUsed(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
         if(!world.isClientSide)
         {
-            ((BlockSugarcane)Blocks.blocksList[id]).growReedOnTop(world, blockX, blockY, blockZ);
+            growReedOnTop(world, blockX, blockY, blockZ);
             if (player == null || player.getGamemode().consumeBlocks())
             {
                 itemstack.stackSize--;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSupplier.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSupplier.java
new file mode 100644
index 000000000..5cd03155f
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSupplier.java
@@ -0,0 +1,6 @@
+package net.minecraft.core.block;
+
+@FunctionalInterface
+public interface BlockLogicSupplier<T extends BlockLogic> {
+    T get(Block<T> b);
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTNT.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTNT.java
similarity index 95%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTNT.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTNT.java
index 9b5d0b718..a648a7a60 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTNT.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTNT.java
@@ -10,10 +10,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 
-public class BlockTNT extends Block {
+public class BlockLogicTNT extends BlockLogic {
 
-	public BlockTNT(String key, String namespaceId, int id) {
-		super(key, namespaceId, id, Material.explosive);
+	public BlockLogicTNT(Block<?> block) {
+		super(block, Material.explosive);
 	}
 
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTallGrass.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTallGrass.java
similarity index 74%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTallGrass.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTallGrass.java
index 4b74de667..ce1918d84 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTallGrass.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTallGrass.java
@@ -6,20 +6,20 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 
-public class BlockTallGrass extends BlockFlower
+public class BlockLogicTallGrass extends BlockLogicFlower
 {
-	public BlockTallGrass(String key, String namespaceId, int id)
+	public BlockLogicTallGrass(Block<?> block)
     {
-        super(key, namespaceId, id);
+        super(block);
         float f = 0.4F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.8F, 0.5F + f);
-        withOverrideColor(MaterialColor.grass);
+        block.withOverrideColor(MaterialColor.grass);
     }
 
     @Override
     protected boolean mayPlaceOn(int blockId) {
-    	Block block = Blocks.getBlock(blockId);
-    	if(block instanceof BlockMoss) {
+    	Block<?> block = Blocks.getBlock(blockId);
+    	if(block != null && block.getLogic() instanceof BlockLogicMoss) {
     		return true;
     	}
     	return super.mayPlaceOn(blockId);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTorch.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorch.java
similarity index 92%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTorch.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTorch.java
index 35f06cfcf..2ff1784a7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTorch.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorch.java
@@ -1,19 +1,17 @@
 package net.minecraft.core.block;
 
-import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
-import net.minecraft.core.util.phys.Vec3;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Random;
 
-public class BlockTorch extends Block
+public class BlockLogicTorch extends BlockLogic
 {
     public static final int MASK_DIRECTION = 0b0000_0111;
     public static final int SIDE_NONE = 0;
@@ -24,10 +22,10 @@ public class BlockTorch extends Block
     public static final int SIDE_BOTTOM = 5;
     public static final int SIDE_TOP = 6;
 
-	public BlockTorch(String key, String namespaceId, int id)
+	public BlockLogicTorch(Block<?> block)
     {
-        super(key, namespaceId, id, Material.decoration);
-        setTicking(true);
+        super(block, Material.decoration);
+        block.setTicking(true);
     }
 
     @Override
@@ -72,11 +70,11 @@ public class BlockTorch extends Block
     {
         int blockBelow = world.getBlockId(x, y, z);
         return world.canPlaceOnSurfaceOfBlock(x, y, z)
-            || blockBelow == Blocks.FENCE_PLANKS_OAK.id
-            || blockBelow == Blocks.FENCE_PLANKS_OAK_PAINTED.id
-            || blockBelow == Blocks.FENCE_CHAINLINK.id
-            || blockBelow == Blocks.FENCE_PAPER_WALL.id
-            || blockBelow == Blocks.FENCE_STEEL.id;
+            || blockBelow == Blocks.FENCE_PLANKS_OAK.id()
+            || blockBelow == Blocks.FENCE_PLANKS_OAK_PAINTED.id()
+            || blockBelow == Blocks.FENCE_CHAINLINK.id()
+            || blockBelow == Blocks.FENCE_PAPER_WALL.id()
+            || blockBelow == Blocks.FENCE_STEEL.id();
     }
 
     @Override
@@ -266,11 +264,11 @@ public class BlockTorch extends Block
             case SIDE_BOTTOM:
                 int blockBelow = world.getBlockId(x, y - 1, z);
                 invalid = !(world.canPlaceOnSurfaceOfBlock(x, y - 1, z)
-                    || blockBelow == Blocks.FENCE_PLANKS_OAK.id
-                    || blockBelow == Blocks.FENCE_PLANKS_OAK_PAINTED.id
-                    || blockBelow == Blocks.FENCE_CHAINLINK.id
-                    || blockBelow == Blocks.FENCE_PAPER_WALL.id
-                    || blockBelow == Blocks.FENCE_STEEL.id);
+                    || blockBelow == Blocks.FENCE_PLANKS_OAK.id()
+                    || blockBelow == Blocks.FENCE_PLANKS_OAK_PAINTED.id()
+                    || blockBelow == Blocks.FENCE_CHAINLINK.id()
+                    || blockBelow == Blocks.FENCE_PAPER_WALL.id()
+                    || blockBelow == Blocks.FENCE_STEEL.id());
                 break;
             default:
                 invalid = true;
@@ -330,6 +328,6 @@ public class BlockTorch extends Block
     
     @Override
     public int getLightmapCoord(WorldSource blockAccess, int x, int y, int z) {
-		return blockAccess.getLightmapCoord(x, y, z, Blocks.lightEmission[id] > 0 ? 15 : 0);
+		return blockAccess.getLightmapCoord(x, y, z, block.emission > 0 ? 15 : 0);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTorchRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorchRedstone.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTorchRedstone.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTorchRedstone.java
index f151e3d1e..19e7dd9b4 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTorchRedstone.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorchRedstone.java
@@ -9,13 +9,13 @@ import net.minecraft.core.world.WorldSource;
 
 import java.util.Random;
 
-public class BlockTorchRedstone extends BlockTorch {
+public class BlockLogicTorchRedstone extends BlockLogicTorch {
     private final boolean torchActive;
 
-    public BlockTorchRedstone(String key, String namespaceId, int id, boolean isActive) {
-        super(key, namespaceId, id);
+    public BlockLogicTorchRedstone(Block<?> block, boolean isActive) {
+        super(block);
         torchActive = isActive;
-        setTicking(true);
+        block.setTicking(true);
     }
 
     @Override
@@ -29,24 +29,24 @@ public class BlockTorchRedstone extends BlockTorch {
             super.onBlockPlacedByWorld(world, x, y, z);
         }
         if (torchActive) {
-            world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
-            world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
-            world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
-            world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
-            world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
+            world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
+            world.notifyBlocksOfNeighborChange(x, y + 1, z, id());
+            world.notifyBlocksOfNeighborChange(x - 1, y, z, id());
+            world.notifyBlocksOfNeighborChange(x + 1, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y, z - 1, id());
+            world.notifyBlocksOfNeighborChange(x, y, z + 1, id());
         }
     }
 
     @Override
     public void onBlockRemoved(World world, int x, int y, int z, int data) {
         if (torchActive) {
-            world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
-            world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
-            world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
-            world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
-            world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
+            world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
+            world.notifyBlocksOfNeighborChange(x, y + 1, z, id());
+            world.notifyBlocksOfNeighborChange(x - 1, y, z, id());
+            world.notifyBlocksOfNeighborChange(x + 1, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y, z - 1, id());
+            world.notifyBlocksOfNeighborChange(x, y, z + 1, id());
         }
     }
 
@@ -94,17 +94,17 @@ public class BlockTorchRedstone extends BlockTorch {
         boolean isPowered = hasNeighborSignal(world, x, y, z);
         if (torchActive) {
             if (isPowered) {
-                world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TORCH_REDSTONE_IDLE.id, world.getBlockMetadata(x, y, z));
+                world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TORCH_REDSTONE_IDLE.id(), world.getBlockMetadata(x, y, z));
             }
         } else if (!isPowered) {
-            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TORCH_REDSTONE_ACTIVE.id, world.getBlockMetadata(x, y, z));
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TORCH_REDSTONE_ACTIVE.id(), world.getBlockMetadata(x, y, z));
         }
     }
 
     @Override
     public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
         super.onNeighborBlockChange(world, x, y, z, blockId);
-        world.scheduleBlockUpdate(x, y, z, id, tickDelay());
+        world.scheduleBlockUpdate(x, y, z, id(), tickDelay());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTransparent.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTransparent.java
similarity index 51%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTransparent.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTransparent.java
index 9e3ee745b..d671696a3 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTransparent.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTransparent.java
@@ -2,12 +2,12 @@ package net.minecraft.core.block;
 
 import net.minecraft.core.block.material.Material;
 
-public class BlockTransparent extends Block
+public class BlockLogicTransparent extends BlockLogic
 {
 
-	public BlockTransparent(String key, String namespaceId, int id, Material material)
+	public BlockLogicTransparent(Block<?> block, Material material)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTrapDoor.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoor.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTrapDoor.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoor.java
index ad1a1e9f0..58b7e4e4f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTrapDoor.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoor.java
@@ -11,15 +11,13 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
-import net.minecraft.core.util.phys.HitResult;
-import net.minecraft.core.util.phys.Vec3;
 import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockTrapDoor extends Block implements IPaintable {
+public class BlockLogicTrapDoor extends BlockLogic implements IPaintable {
     public static final int DIRECTION_SOUTH = 0;
     public static final int DIRECTION_NORTH = 1;
     public static final int DIRECTION_EAST = 2;
@@ -29,8 +27,8 @@ public class BlockTrapDoor extends Block implements IPaintable {
     public static final int MASK_OPEN = 0b0000_0100;
     public static final int MASK_UPPER_HALF = 0b0000_1000;
 
-    public BlockTrapDoor(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
+    public BlockLogicTrapDoor(Block<?> block, Material material) {
+        super(block, material);
         float f = 0.5F;
         float f1 = 1.0F;
         setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f1, 0.5F + f);
@@ -92,7 +90,7 @@ public class BlockTrapDoor extends Block implements IPaintable {
 
     @Override
     public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xPlaced, double yPlaced) {
-        if (blockMaterial != Material.metal && blockMaterial != Material.steel) {
+        if (material != Material.metal && material != Material.steel) {
             int l = world.getBlockMetadata(x, y, z);
             world.setBlockMetadataWithNotify(x, y, z, l ^ MASK_OPEN);
             world.playBlockEvent(player, LevelListener.EVENT_DOOR_SOUND, x, y, z, 0);
@@ -103,7 +101,7 @@ public class BlockTrapDoor extends Block implements IPaintable {
 
     @Override
     public void onActivatorInteract(World world, int x, int y, int z, TileEntityActivator activator, Direction direction) {
-        if (blockMaterial != Material.metal && blockMaterial != Material.steel) {
+        if (material != Material.metal && material != Material.steel) {
             int l = world.getBlockMetadata(x, y, z);
             world.setBlockMetadataWithNotify(x, y, z, l ^ MASK_OPEN);
             world.playBlockEvent(null, LevelListener.EVENT_DOOR_SOUND, x, y, z, 0);
@@ -116,7 +114,7 @@ public class BlockTrapDoor extends Block implements IPaintable {
             return;
         }
 
-        Block block = Blocks.getBlock(blockId);
+        Block<?> block = Blocks.getBlock(blockId);
         if (block == null || block.isSignalSource()) {
             int meta = world.getBlockMetadata(x, y, z);
             boolean isOpened = isTrapdoorOpen(meta);
@@ -140,10 +138,10 @@ public class BlockTrapDoor extends Block implements IPaintable {
 
     @Override
     public boolean isClimbable(World world, int x, int y, int z) {
-        Block block = world.getBlock(x, y - 1, z);
+        Block<?> block = world.getBlock(x, y - 1, z);
         int meta = world.getBlockMetadata(x, y, z);
-        if (isTrapdoorOpen(meta) && block instanceof BlockLadder) {
-            BlockLadder ladder = (BlockLadder) block;
+        if (isTrapdoorOpen(meta) && (block != null && block.getLogic() instanceof BlockLogicLadder)) {
+            BlockLogicLadder ladder = (BlockLogicLadder) block.getLogic();
             Side ladderSide = ladder.getSideFromMeta(world.getBlockMetadata(x, y - 1, z));
             Direction trapdoorDirection = getDirectionForMeta(meta);
             return ladderSide.getDirection().getOpposite() == trapdoorDirection;
@@ -197,12 +195,12 @@ public class BlockTrapDoor extends Block implements IPaintable {
 
     @Override
     public boolean canBePainted() {
-        return blockMaterial == Material.wood;
+        return material == Material.wood;
     }
 
     @Override
     public void setColor(World world, int x, int y, int z, DyeColor color) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TRAPDOOR_PLANKS_PAINTED.id, meta & 0xF | color.blockMeta << 4);
+        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TRAPDOOR_PLANKS_PAINTED.id(), meta & 0xF | color.blockMeta << 4);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTrapDoorPainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoorPainted.java
similarity index 87%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTrapDoorPainted.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoorPainted.java
index daa594a01..9a0deb9aa 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTrapDoorPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoorPainted.java
@@ -10,9 +10,9 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockTrapDoorPainted extends BlockTrapDoor implements IPainted {
-    public BlockTrapDoorPainted(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
+public class BlockLogicTrapDoorPainted extends BlockLogicTrapDoor implements IPainted {
+    public BlockLogicTrapDoorPainted(Block<?> block, Material material) {
+        super(block, material);
     }
     
     @Override
@@ -44,7 +44,7 @@ public class BlockTrapDoorPainted extends BlockTrapDoor implements IPainted {
     @Override
     public void removeDye(World world, int x, int y, int z) {
         final int meta = world.getBlockMetadata(x, y, z);
-        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TRAPDOOR_PLANKS_OAK.id, meta & 0xF);
+        world.setBlockAndMetadataWithNotify(x, y, z, Blocks.TRAPDOOR_PLANKS_OAK.id(), meta & 0xF);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTrommel.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrommel.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTrommel.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicTrommel.java
index 2f73d17eb..facc7586c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTrommel.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrommel.java
@@ -14,13 +14,14 @@ import org.slf4j.Logger;
 
 import java.util.Random;
 
-public class BlockTrommel extends BlockTileEntityRotatable
+public class BlockLogicTrommel extends BlockLogicRotatable
 {
     private static final Logger LOGGER = LogUtils.getLogger();
-	public BlockTrommel(String key, String namespaceId, int id, Material material, boolean isActive)
+	public BlockLogicTrommel(Block<?> block, Material material, boolean isActive)
     {
-        super(key, namespaceId, id, material);
+        super(block, material);
         this.isActive = isActive;
+        block.withEntity(TileEntityTrommel::new);
     }
 
     @Override
@@ -75,10 +76,10 @@ public class BlockTrommel extends BlockTileEntityRotatable
         keepTrommelInventory = true;
         if(lit)
         {
-            world.setBlockWithNotify(x, y, z, Blocks.TROMMEL_ACTIVE.id);
+            world.setBlockWithNotify(x, y, z, Blocks.TROMMEL_ACTIVE.id());
         } else
         {
-            world.setBlockWithNotify(x, y, z, Blocks.TROMMEL_IDLE.id);
+            world.setBlockWithNotify(x, y, z, Blocks.TROMMEL_IDLE.id());
         }
         keepTrommelInventory = false;
         world.setBlockMetadataWithNotify(x, y, z, l);
@@ -86,13 +87,6 @@ public class BlockTrommel extends BlockTileEntityRotatable
         world.setBlockTileEntity(x, y, z, tileEntity);
     }
 
-
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return new TileEntityTrommel();
-    }
-
     private boolean isActive;
     public static boolean keepTrommelInventory = false;
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTileEntityVeryRotatable.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicVeryRotatable.java
similarity index 83%
rename from game/core/src/main/java/net/minecraft/core/block/BlockTileEntityVeryRotatable.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicVeryRotatable.java
index 7f43eca35..5c33ced29 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTileEntityVeryRotatable.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicVeryRotatable.java
@@ -7,10 +7,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
 
-public abstract class BlockTileEntityVeryRotatable extends BlockTileEntityRotatable {
+public class BlockLogicVeryRotatable extends BlockLogic {
     public static final int MASK_DIRECTION = 0b0000_0111;
-	public BlockTileEntityVeryRotatable(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
+    public BlockLogicVeryRotatable(Block<?> block, Material material) {
+        super(block, material);
     }
 
     @Override
@@ -33,4 +33,4 @@ public abstract class BlockTileEntityVeryRotatable extends BlockTileEntityRotata
         return Direction.getDirectionById(meta & MASK_DIRECTION);
     }
 
-}
+}
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockWireRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWireRedstone.java
similarity index 90%
rename from game/core/src/main/java/net/minecraft/core/block/BlockWireRedstone.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicWireRedstone.java
index f53ec0923..f8d281138 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockWireRedstone.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWireRedstone.java
@@ -17,12 +17,12 @@ import java.util.HashSet;
 import java.util.Random;
 import java.util.Set;
 
-public class BlockWireRedstone extends Block {
+public class BlockLogicWireRedstone extends BlockLogic {
     private boolean shouldSignal = true;
     private final Set<ChunkPosition> toUpdate = new HashSet<>();
 
-    public BlockWireRedstone(String key, String namespaceId, int id) {
-        super(key, namespaceId, id, Material.decoration);
+    public BlockLogicWireRedstone(Block<?> block) {
+        super(block, Material.decoration);
         setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.0625F, 1.0F);
     }
 
@@ -51,7 +51,7 @@ public class BlockWireRedstone extends Block {
         ArrayList<ChunkPosition> toUpdate = new ArrayList<>(this.toUpdate);
         this.toUpdate.clear();
         for (ChunkPosition pos : toUpdate) {
-            world.notifyBlocksOfNeighborChange(pos.x, pos.y, pos.z, id);
+            world.notifyBlocksOfNeighborChange(pos.x, pos.y, pos.z, id());
         }
     }
 
@@ -101,7 +101,7 @@ public class BlockWireRedstone extends Block {
         }
         if (strength != newStrength) {
             int blockId = world.getBlockId(x0, y0, z0);
-            if (blockId == id || blockId == Blocks.FLUID_LAVA_STILL.id || blockId == Blocks.FLUID_LAVA_FLOWING.id) { // Intentionally keeping lava transmutation, do not delete carelessly
+            if (blockId == id() || blockId == Blocks.FLUID_LAVA_STILL.id() || blockId == Blocks.FLUID_LAVA_FLOWING.id()) { // Intentionally keeping lava transmutation, do not delete carelessly
                 world.noNeighborUpdate = true;
                 world.setBlockMetadataWithNotify(x0, y0, z0, newStrength);
                 world.markBlocksDirty(x0, y0, z0, x0, y0, z0);
@@ -157,14 +157,14 @@ public class BlockWireRedstone extends Block {
     }
 
     private void checkCornerChangeAt(World world, int x, int y, int z) {
-        if (world.getBlockId(x, y, z) == id) {
-            world.notifyBlocksOfNeighborChange(x, y, z, id);
-            world.notifyBlocksOfNeighborChange(x - 1, y, z, id);
-            world.notifyBlocksOfNeighborChange(x + 1, y, z, id);
-            world.notifyBlocksOfNeighborChange(x, y, z - 1, id);
-            world.notifyBlocksOfNeighborChange(x, y, z + 1, id);
-            world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
-            world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
+        if (world.getBlockId(x, y, z) == id()) {
+            world.notifyBlocksOfNeighborChange(x, y, z, id());
+            world.notifyBlocksOfNeighborChange(x - 1, y, z, id());
+            world.notifyBlocksOfNeighborChange(x + 1, y, z, id());
+            world.notifyBlocksOfNeighborChange(x, y, z - 1, id());
+            world.notifyBlocksOfNeighborChange(x, y, z + 1, id());
+            world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
+            world.notifyBlocksOfNeighborChange(x, y + 1, z, id());
         }
     }
 
@@ -175,8 +175,8 @@ public class BlockWireRedstone extends Block {
             return;
         }
         updatePowerStrength(world, x, y, z);
-        world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
-        world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+        world.notifyBlocksOfNeighborChange(x, y + 1, z, id());
+        world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
         checkCornerChangeAt(world, x - 1, y, z);
         checkCornerChangeAt(world, x + 1, y, z);
         checkCornerChangeAt(world, x, y, z - 1);
@@ -209,8 +209,8 @@ public class BlockWireRedstone extends Block {
         if (world.isClientSide) {
             return;
         }
-        world.notifyBlocksOfNeighborChange(x, y + 1, z, id);
-        world.notifyBlocksOfNeighborChange(x, y - 1, z, id);
+        world.notifyBlocksOfNeighborChange(x, y + 1, z, id());
+        world.notifyBlocksOfNeighborChange(x, y - 1, z, id());
         updatePowerStrength(world, x, y, z);
         checkCornerChangeAt(world, x - 1, y, z);
         checkCornerChangeAt(world, x + 1, y, z);
@@ -239,7 +239,7 @@ public class BlockWireRedstone extends Block {
     }
 
     private int checkTarget(World world, int x, int y, int z, int sourceStrength) {
-        if (world.getBlockId(x, y, z) != id) {
+        if (world.getBlockId(x, y, z) != id()) {
             return sourceStrength;
         }
 
@@ -344,7 +344,7 @@ public class BlockWireRedstone extends Block {
 
     public static boolean shouldConnectTo(WorldSource worldSource, int x, int y, int z, int data) {
         int blockId = worldSource.getBlockId(x, y, z);
-        if (blockId == Blocks.WIRE_REDSTONE.id) {
+        if (blockId == Blocks.WIRE_REDSTONE.id()) {
             return true;
         }
         if (blockId <= 0) {
@@ -353,7 +353,7 @@ public class BlockWireRedstone extends Block {
         if (Blocks.blocksList[blockId].isSignalSource()) {
             return true;
         }
-        if (blockId == Blocks.PUMPKIN_REDSTONE.id) {
+        if (blockId == Blocks.PUMPKIN_REDSTONE.id()) {
             if (data < 0 || data > 3) {
                 return false;
             }
@@ -361,9 +361,9 @@ public class BlockWireRedstone extends Block {
             Side side = Side.getSideById(worldSource.getBlockMetadata(x, y, z));
             return side == lookup[data];
         }
-        if (blockId == Blocks.REPEATER_IDLE.id || blockId == Blocks.REPEATER_ACTIVE.id) {
+        if (blockId == Blocks.REPEATER_IDLE.id() || blockId == Blocks.REPEATER_ACTIVE.id()) {
             int meta = worldSource.getBlockMetadata(x, y, z);
-            return data == BlockBed.footToHeadMap[meta & 0b11];
+            return data == BlockLogicBed.footToHeadMap[meta & 0b11];
         } else {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockWool.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWool.java
similarity index 88%
rename from game/core/src/main/java/net/minecraft/core/block/BlockWool.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicWool.java
index 9c15e00ca..8df4d3256 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockWool.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWool.java
@@ -10,11 +10,11 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockWool extends Block implements IPainted
+public class BlockLogicWool extends BlockLogic implements IPainted
 {
-    public BlockWool(String key, String namespaceId, int id) {
+    public BlockLogicWool(Block<?> block) {
 
-        super(key, namespaceId, id, Material.cloth);
+        super(block, Material.cloth);
     }
     
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockWorkbench.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWorkbench.java
similarity index 76%
rename from game/core/src/main/java/net/minecraft/core/block/BlockWorkbench.java
rename to game/core/src/main/java/net/minecraft/core/block/BlockLogicWorkbench.java
index 19540ea0e..68d59df2a 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockWorkbench.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWorkbench.java
@@ -5,12 +5,12 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 
-public class BlockWorkbench extends Block
+public class BlockLogicWorkbench extends BlockLogic
 {
 
-	public BlockWorkbench(String key, String namespaceId, int id)
+	public BlockLogicWorkbench(Block<?> block)
     {
-        super(key, namespaceId, id, Material.wood);
+        super(block, Material.wood);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockPlanks.java b/game/core/src/main/java/net/minecraft/core/block/BlockPlanks.java
deleted file mode 100644
index 6b8654659..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockPlanks.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-import net.minecraft.core.util.helper.DyeColor;
-import net.minecraft.core.world.World;
-
-public class BlockPlanks extends Block implements IPaintable {
-    public BlockPlanks(String translationKey, String namespaceId, int id, Material material) {
-        super(translationKey, namespaceId, id, material);
-    }
-
-    @Override
-    public void setColor(World world, int x, int y, int z, DyeColor color) {
-        world.setBlock(x, y, z, Blocks.PLANKS_OAK_PAINTED.id);
-        ((IPaintable) Blocks.PLANKS_OAK_PAINTED).setColor(world, x, y, z, color);
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockSlippery.java b/game/core/src/main/java/net/minecraft/core/block/BlockSlippery.java
deleted file mode 100644
index c604966ea..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockSlippery.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-
-public class BlockSlippery extends Block {
-
-    public BlockSlippery(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
-        friction = 0.98F;
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTileEntity.java b/game/core/src/main/java/net/minecraft/core/block/BlockTileEntity.java
deleted file mode 100644
index ac2396e27..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTileEntity.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.block.material.Material;
-import net.minecraft.core.world.World;
-
-public abstract class BlockTileEntity extends Block
-{
-    public static boolean createNewEntityOnPlace = true;
-
-	public BlockTileEntity(String key, String namespaceId, int id, Material material)
-    {
-        super(key, namespaceId, id, material);
-        Blocks.isEntityTile[id] = true;
-    }
-
-    @Override
-	public void onBlockPlacedByWorld(World world, int x, int y, int z)
-    {
-        super.onBlockPlacedByWorld(world, x, y, z);
-        if (createNewEntityOnPlace) {
-            world.setBlockTileEntity(x, y, z, getNewBlockEntity());
-        }
-    }
-
-    @Override
-    public void onBlockRemoved(World world, int x, int y, int z, int data)
-    {
-        super.onBlockRemoved(world, x, y, z, data);
-        if (!world.isClientSide) {
-            TileEntity tileEntity = world.getBlockEntity(x, y, z);
-            if(tileEntity != null) {
-                tileEntity.dropContents(world, x, y, z);
-            }
-        }
-        world.removeBlockTileEntity(x, y, z);
-    }
-
-    protected abstract TileEntity getNewBlockEntity();
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockTileEntityRotatable.java b/game/core/src/main/java/net/minecraft/core/block/BlockTileEntityRotatable.java
deleted file mode 100644
index e3ec97846..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockTileEntityRotatable.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.material.Material;
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.world.World;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class BlockTileEntityRotatable extends BlockTileEntity {
-
-	public BlockTileEntityRotatable(String key, String namespaceId, int id, Material material) {
-        super(key, namespaceId, id, material);
-    }
-
-    @Override
-    public void onBlockPlacedByMob(World world, int x, int y, int z, @NotNull Side side, Mob mob, double xPlaced, double yPlaced) {
-    	world.setBlockMetadataWithNotify(x, y, z, mob.getHorizontalPlacementDirection(side).getOpposite().getId());
-    }
-
-    @Override
-    public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
-        if (!side.isHorizontal()) side = Side.SOUTH;
-        world.setBlockMetadataWithNotify(x, y, z, BlockRotatable.setDirection(0, side.getDirection()));
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/Blocks.java b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
index 961b5ae59..d0c56f5d2 100644
--- a/game/core/src/main/java/net/minecraft/core/block/Blocks.java
+++ b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
@@ -2,12 +2,13 @@ package net.minecraft.core.block;
 
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.material.MaterialColor;
-import net.minecraft.core.block.piston.BlockPistonBase;
-import net.minecraft.core.block.piston.BlockPistonHead;
-import net.minecraft.core.block.piston.BlockPistonMoving;
-import net.minecraft.core.block.piston.BlockPistonBaseSteel;
-import net.minecraft.core.block.piston.BlockPistonBaseSticky;
+import net.minecraft.core.block.piston.BlockLogicPistonBase;
+import net.minecraft.core.block.piston.BlockLogicPistonHead;
+import net.minecraft.core.block.piston.BlockLogicPistonMoving;
+import net.minecraft.core.block.piston.BlockLogicPistonBaseSteel;
+import net.minecraft.core.block.piston.BlockLogicPistonBaseSticky;
 import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.data.tag.Tag;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.entity.animal.MobFireflyCluster;
@@ -16,23 +17,24 @@ import net.minecraft.core.item.Item;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.block.ItemBlockAlgae;
 import net.minecraft.core.item.block.ItemBlockLadder;
-import net.minecraft.core.item.block.ItemBlockLayerLeaves;
 import net.minecraft.core.item.block.ItemBlockPainted;
 import net.minecraft.core.item.block.ItemBlockStairsPainted;
 import net.minecraft.core.item.block.ItemBlockLamp;
 import net.minecraft.core.item.block.ItemBlockSlabPainted;
 import net.minecraft.core.sound.BlockSounds;
 import net.minecraft.core.util.collection.NamespaceID;
+import net.minecraft.core.world.Dimension;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
 public final class Blocks {
-    public static final @Nullable Block @NotNull [] blocksList = new Block[16384];
-    public static final Map<NamespaceID, Block> blockMap = new LinkedHashMap<>();
+    public static final @Nullable Block<?> @NotNull [] blocksList = new Block<?>[16384];
+    public static final Map<NamespaceID, Block<?>> blockMap = new LinkedHashMap<>();
     @Deprecated public static final Map<String, Integer> keyToIdMap = new HashMap<>();
     public static final boolean[] shouldTick = new boolean[blocksList.length];
     public static final boolean[] solid = new boolean[blocksList.length];
@@ -43,434 +45,1175 @@ public final class Blocks {
     public static final boolean[] neighborNotifyOnMetadataChangeDisabled = new boolean[blocksList.length];
     public static int highestBlockId = 0;
 
-    public static Block STONE;
-    public static Block BASALT;
-    public static Block LIMESTONE;
-    public static Block GRANITE;
-    public static Block MARBLE;
-    public static Block SLATE;
-    public static Block PERMAFROST;
-
-    public static Block COBBLE_STONE;
-    public static Block COBBLE_STONE_MOSSY;
-    public static Block COBBLE_BASALT;
-    public static Block COBBLE_LIMESTONE;
-    public static Block COBBLE_GRANITE;
-    public static Block COBBLE_PERMAFROST;
-
-    public static Block STONE_POLISHED;
-    public static Block GRANITE_POLISHED;
-    public static Block LIMESTONE_POLISHED;
-    public static Block BASALT_POLISHED;
-    public static Block SLATE_POLISHED;
-    public static Block PERMAFROST_POLISHED;
-    public static Block NETHERRACK_POLISHED;
-
-    public static Block PILLAR_MARBLE;
-    public static Block CAPSTONE_MARBLE;
-
-    public static Block SANDSTONE;
-
-    public static Block STONE_CARVED;
-    public static Block GRANITE_CARVED;
-    public static Block LIMESTONE_CARVED;
-    public static Block BASALT_CARVED;
-    public static Block PERMAFROST_CARVED;
-    public static Block NETHERRACK_CARVED;
-
-    public static Block PLANKS_OAK;
-    public static Block PLANKS_OAK_PAINTED;
-
-    public static Block TORCH_COAL;
-//    public static Block candleSoulwax;
-
-    public static Block LADDER_OAK;
-
-    public static Block FENCE_PLANKS_OAK;
-    public static Block FENCE_PLANKS_OAK_PAINTED;
-
-    public static Block FENCE_GATE_PLANKS_OAK;
-    public static Block FENCE_GATE_PLANKS_OAK_PAINTED;
-
-    public static Block BOOKSHELF_PLANKS_OAK;
-
-    public static Block WOOL;
-    public static Block ROPE;
-
-    public static Block BRICK_CLAY;
-    public static Block BRICK_STONE_POLISHED;
-    public static Block BRICK_STONE_POLISHED_MOSSY;
-    public static Block BRICK_SANDSTONE;
-    public static Block BRICK_GOLD;
-    public static Block BRICK_LAPIS;
-    public static Block BRICK_BASALT;
-    public static Block BRICK_LIMESTONE;
-    public static Block BRICK_GRANITE;
-    public static Block BRICK_MARBLE;
-    public static Block BRICK_SLATE;
-    public static Block BRICK_STONE;
-    public static Block BRICK_PERMAFROST;
-    public static Block BRICK_IRON;
-    public static Block BRICK_STEEL;
-
-    public static Block SLAB_PLANKS_OAK;
-    public static Block SLAB_COBBLE_STONE;
-    public static Block SLAB_SANDSTONE;
-    public static Block SLAB_BRICK_STONE_POLISHED;
-    public static Block SLAB_STONE_POLISHED;
-    public static Block SLAB_BRICK_MARBLE;
-    public static Block SLAB_BRICK_CLAY;
-    public static Block SLAB_CAPSTONE_MARBLE;
-    public static Block SLAB_COBBLE_BASALT;
-    public static Block SLAB_COBBLE_LIMESTONE;
-    public static Block SLAB_COBBLE_GRANITE;
-    public static Block SLAB_BRICK_BASALT;
-    public static Block SLAB_BRICK_LIMESTONE;
-    public static Block SLAB_BRICK_GRANITE;
-    public static Block SLAB_PLANKS_PAINTED;
-    public static Block SLAB_BRICK_SLATE;
-    public static Block SLAB_BRICK_STONE;
-    public static Block SLAB_GRANITE_POLISHED;
-    public static Block SLAB_LIMESTONE_POLISHED;
-    public static Block SLAB_BASALT_POLISHED;
-
-    public static Block STAIRS_PLANKS_OAK;
-    public static Block STAIRS_COBBLE_STONE;
-    public static Block STAIRS_BRICK_STONE_POLISHED;
-    public static Block STAIRS_BRICK_MARBLE;
-    public static Block STAIRS_COBBLE_BASALT;
-    public static Block STAIRS_COBBLE_LIMESTONE;
-    public static Block STAIRS_COBBLE_GRANITE;
-    public static Block STAIRS_BRICK_BASALT;
-    public static Block STAIRS_BRICK_LIMESTONE;
-    public static Block STAIRS_BRICK_GRANITE;
-    public static Block STAIRS_BRICK_CLAY;
-    public static Block STAIRS_PLANKS_PAINTED;
-    public static Block STAIRS_BRICK_SLATE;
-    public static Block STAIRS_BRICK_STONE;
-    public static Block STAIRS_SANDSTONE;
-    public static Block STAIRS_BRICK_SANDSTONE;
-    public static Block STAIRS_COBBLE_PERMAFROST;
-    public static Block STAIRS_BRICK_PERMAFROST;
-
-    public static Block OBSIDIAN;
-
-    public static Block GLASS;
-    public static Block GLASS_TINTED;
-    public static Block GLASS_STEEL;
-
-    public static Block GRASS;
-    public static Block GRASS_RETRO;
-    public static Block GRASS_SCORCHED;
-
-    public static Block PATH_DIRT;
-
-    public static Block DIRT;
-    public static Block DIRT_SCORCHED;
-    public static Block DIRT_SCORCHED_RICH;
-
-    public static Block MUD;
-    public static Block MUD_BAKED;
-
-    public static Block SPONGE_DRY;
-    public static Block SPONGE_WET;
-    public static Block PUMICE_DRY;
-    public static Block PUMICE_WET;
-
-    public static Block MOSS_STONE;
-    public static Block MOSS_BASALT;
-    public static Block MOSS_LIMESTONE;
-    public static Block MOSS_GRANITE;
-
-    public static Block SAND;
-    public static Block GRAVEL;
-
-    public static Block BEDROCK;
-    public static Block BONESHALE;
-
-    public static Block FLUID_WATER_FLOWING;
-    public static Block FLUID_WATER_STILL;
-    public static Block FLUID_LAVA_FLOWING;
-    public static Block FLUID_LAVA_STILL;
-
-    public static Block LOG_OAK;
-    public static Block LOG_PINE;
-    public static Block LOG_BIRCH;
-    public static Block LOG_CHERRY;
-    public static Block LOG_EUCALYPTUS;
-    public static Block LOG_OAK_MOSSY;
-    public static Block LOG_THORN;
-    public static Block LOG_PALM;
-
-    public static Block LEAVES_OAK;
-    public static Block LEAVES_OAK_RETRO;
-    public static Block LEAVES_PINE;
-    public static Block LEAVES_BIRCH;
-    public static Block LEAVES_CHERRY;
-    public static Block LEAVES_EUCALYPTUS;
-    public static Block LEAVES_SHRUB;
-    public static Block LEAVES_CHERRY_FLOWERING;
-    public static Block LEAVES_CACAO;
-    public static Block LEAVES_THORN;
-    public static Block LEAVES_PALM;
-
-
-    public static Block SAPLING_OAK;
-    public static Block SAPLING_OAK_RETRO;
-    public static Block SAPLING_PINE;
-    public static Block SAPLING_BIRCH;
-    public static Block SAPLING_CHERRY;
-    public static Block SAPLING_EUCALYPTUS;
-    public static Block SAPLING_SHRUB;
-    public static Block SAPLING_CACAO;
-    public static Block SAPLING_THORN;
-    public static Block SAPLING_PALM;
-
-    public static Block TALLGRASS;
-    public static Block TALLGRASS_FERN;
-    public static Block DEADBUSH;
-    public static Block SPINIFEX;
-    public static Block ALGAE;
-
-    public static Block FLOWER_YELLOW;
-    public static Block FLOWER_RED;
-    public static Block FLOWER_PINK;
-    public static Block FLOWER_PURPLE;
-    public static Block FLOWER_LIGHT_BLUE;
-    public static Block FLOWER_ORANGE;
-
-    public static Block MUSHROOM_BROWN;
-    public static Block MUSHROOM_RED;
-
-    public static Block ORE_COAL_STONE;
-    public static Block ORE_COAL_BASALT;
-    public static Block ORE_COAL_LIMESTONE;
-    public static Block ORE_COAL_GRANITE;
-    public static Block ORE_COAL_PERMAFROST;
-
-    public static Block ORE_IRON_STONE;
-    public static Block ORE_IRON_BASALT;
-    public static Block ORE_IRON_LIMESTONE;
-    public static Block ORE_IRON_GRANITE;
-    public static Block ORE_IRON_PERMAFROST;
-
-    public static Block ORE_GOLD_STONE;
-    public static Block ORE_GOLD_BASALT;
-    public static Block ORE_GOLD_LIMESTONE;
-    public static Block ORE_GOLD_GRANITE;
-    public static Block ORE_GOLD_PERMAFROST;
-
-    public static Block ORE_LAPIS_STONE;
-    public static Block ORE_LAPIS_BASALT;
-    public static Block ORE_LAPIS_LIMESTONE;
-    public static Block ORE_LAPIS_GRANITE;
-    public static Block ORE_LAPIS_PERMAFROST;
-
-    public static Block ORE_REDSTONE_STONE;
-    public static Block ORE_REDSTONE_BASALT;
-    public static Block ORE_REDSTONE_LIMESTONE;
-    public static Block ORE_REDSTONE_GRANITE;
-    public static Block ORE_REDSTONE_PERMAFROST;
-
-    public static Block ORE_REDSTONE_GLOWING_STONE;
-    public static Block ORE_REDSTONE_GLOWING_BASALT;
-    public static Block ORE_REDSTONE_GLOWING_LIMESTONE;
-    public static Block ORE_REDSTONE_GLOWING_GRANITE;
-    public static Block ORE_REDSTONE_GLOWING_PERMAFROST ;
-
-    public static Block ORE_DIAMOND_STONE;
-    public static Block ORE_DIAMOND_BASALT;
-    public static Block ORE_DIAMOND_LIMESTONE;
-    public static Block ORE_DIAMOND_GRANITE;
-    public static Block ORE_DIAMOND_PERMAFROST;
-
-    public static Block ORE_NETHERCOAL_NETHERRACK;
-
-    public static Block BLOCK_COAL;
-    public static Block BLOCK_IRON;
-    public static Block BLOCK_GOLD;
-    public static Block BLOCK_LAPIS;
-    public static Block BLOCK_REDSTONE;
-    public static Block BLOCK_DIAMOND;
-    public static Block BLOCK_NETHER_COAL;
-    public static Block BLOCK_STEEL;
-    public static Block BLOCK_QUARTZ;
-    public static Block BLOCK_OLIVINE;
-    public static Block BLOCK_CHARCOAL;
-
-    public static Block WIRE_REDSTONE;
-
-    public static Block TORCH_REDSTONE_IDLE;
-    public static Block TORCH_REDSTONE_ACTIVE;
-
-    public static Block BUTTON_STONE;
-
-    public static Block LEVER_COBBLE_STONE;
-
-    public static Block PRESSURE_PLATE_STONE;
-    public static Block PRESSURE_PLATE_PLANKS_OAK;
-    public static Block PRESSURE_PLATE_COBBLE_STONE;
-
-    public static Block MOTION_SENSOR_IDLE;
-    public static Block MOTION_SENSOR_ACTIVE;
-
-    public static Block REPEATER_IDLE;
-    public static Block REPEATER_ACTIVE;
-
-    public static Block PISTON_BASE;
-    public static Block PISTON_BASE_STICKY;
-    public static Block PISTON_HEAD;
-    public static Block PISTON_MOVING;
-    public static Block PISTON_BASE_STEEL;
-    public static Block PISTON_HEAD_STEEL;
-
-    public static Block NOTEBLOCK;
-
-    public static Block RAIL;
-    public static Block RAIL_POWERED;
-    public static Block RAIL_DETECTOR;
-
-    public static Block SPIKES;
-
-    public static Block DISPENSER_COBBLE_STONE;
-    public static Block ACTIVATOR_COBBLE_NETHERRACK;
-
-    public static Block TRAPDOOR_PLANKS_OAK;
-    public static Block TRAPDOOR_IRON;
-    public static Block TRAPDOOR_GLASS;
-    public static Block TRAPDOOR_PLANKS_PAINTED;
-    public static Block TRAPDOOR_STEEL;
-
-    public static Block TNT;
-
-    public static Block DOOR_PLANKS_OAK_BOTTOM;
-    public static Block DOOR_PLANKS_OAK_TOP;
-    public static Block DOOR_IRON_BOTTOM;
-    public static Block DOOR_IRON_TOP;
-    public static Block DOOR_PLANKS_PAINTED_BOTTOM;
-    public static Block DOOR_PLANKS_PAINTED_TOP;
-    public static Block DOOR_GLASS_BOTTOM;
-    public static Block DOOR_GLASS_TOP;
-    public static Block DOOR_STEEL_BOTTOM;
-    public static Block DOOR_STEEL_TOP;
-
-    public static Block MESH;
-    public static Block MESH_GOLD;
-
-    public static Block BED;
-    public static Block SEAT;
-
-    public static Block COBWEB;
-
-    public static Block FIRE;
-    public static Block BRAZIER_INACTIVE;
-    public static Block BRAZIER_ACTIVE;
-
-    public static Block MOBSPAWNER;
-    public static Block MOBSPAWNER_DEACTIVATED;
-
-    public static Block WORKBENCH;
-
-    public static Block FURNACE_STONE_IDLE;
-    public static Block FURNACE_STONE_ACTIVE;
-    public static Block FURNACE_BLAST_IDLE;
-    public static Block FURNACE_BLAST_ACTIVE;
-
-    public static Block TROMMEL_IDLE;
-    public static Block TROMMEL_ACTIVE;
-
-    public static Block CHEST_LEGACY;
-    public static Block CHEST_LEGACY_PAINTED;
-    public static Block CHEST_PLANKS_OAK;
-    public static Block CHEST_PLANKS_OAK_PAINTED;
-
-    public static Block CROPS_WHEAT;
-    public static Block CROPS_PUMPKIN;
-
-    public static Block FARMLAND_DIRT;
-
-    public static Block SIGN_POST_PLANKS_OAK;
-    public static Block SIGN_WALL_PLANKS_OAK;
-
-    public static Block FLAG;
-
-    public static Block LAYER_SNOW;
-    public static Block LAYER_LEAVES_OAK;
-    public static Block LAYER_SLATE;
-
-    public static Block ICE;
-    public static Block PERMAICE;
-
-    public static Block BLOCK_SNOW;
-
-    public static Block CACTUS;
-
-    public static Block BLOCK_CLAY;
-
-    public static Block SUGARCANE;
-    public static Block BLOCK_SUGARCANE;
-    public static Block BLOCK_SUGARCANE_BAKED;
-
-    public static Block JUKEBOX;
-
-    public static Block PUMPKIN;
-    public static Block PUMPKIN_CARVED_IDLE;
-    public static Block PUMPKIN_CARVED_ACTIVE;
-    public static Block PUMPKIN_REDSTONE;
-
-    public static Block COBBLE_NETHERRACK;
-    public static Block COBBLE_NETHERRACK_IGNEOUS;
-    public static Block COBBLE_NETHERRACK_MOSSY;
-    public static Block NETHERRACK;
-    public static Block BRICK_NETHERRACK;
-    public static Block SLAB_NETHERRACK_POLISHED;
-    public static Block SLAB_COBBLE_NETHERRACK;
-    public static Block SLAB_BRICK_NETHERRACK;
-    public static Block STAIRS_COBBLE_NETHERRACK;
-    public static Block STAIRS_BRICK_NETHERRACK;
-
-    public static Block SOULSAND;
-    public static Block SOULSCHIST;
-
-    public static Block GLOWSTONE;
-
-    public static Block PORTAL_NETHER;
-    public static Block PORTAL_PARADISE;
-
-    public static Block CAKE;
-    public static Block PUMPKIN_PIE;
-
-    public static Block LAMP_IDLE;
-    public static Block LAMP_ACTIVE;
-
-    public static Block LANTERN_FIREFLY_GREEN;
-    public static Block LANTERN_FIREFLY_BLUE;
-    public static Block LANTERN_FIREFLY_ORANGE;
-    public static Block LANTERN_FIREFLY_RED;
-    public static Block JAR_GLASS;
-
-    public static Block OVERLAY_PEBBLES;
-
-    public static Block FENCE_CHAINLINK;
-    public static Block FENCE_PAPER_WALL;
-    public static Block FENCE_STEEL;
-
-    public static Block BASKET;
+    public static final Block<?> STONE = register("stone", "minecraft:block/stone", 1, (b) -> new BlockLogicStone(b, Blocks.COBBLE_STONE, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BASALT = register("basalt", "minecraft:block/basalt", 2, (b) -> new BlockLogicStone(b, Blocks.COBBLE_BASALT, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> LIMESTONE = register("limestone", "minecraft:block/limestone", 3, (b) -> new BlockLogicStone(b, Blocks.COBBLE_LIMESTONE, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> GRANITE = register("granite", "minecraft:block/granite", 4, (b) -> new BlockLogicStone(b, Blocks.COBBLE_GRANITE, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> MARBLE = register("marble", "minecraft:block/marble", 5, (b) -> new BlockLogic(b, Material.marble))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> SLATE = register("slate", "minecraft:block/slate", 6, (b) -> new BlockLogic(b, Material.slate))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> PERMAFROST = register("permafrost", "minecraft:block/permafrost", 7, (b) -> new BlockLogicStone(b, Blocks.COBBLE_PERMAFROST, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> COBBLE_STONE = register("cobble.stone", "minecraft:block/cobble_stone", 10, (b) -> new BlockLogicCobble(b, Material.stone, () -> Blocks.GRAVEL))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> COBBLE_STONE_MOSSY = register("cobble.stone.mossy", "minecraft:block/cobble_stone_mossy", 11, (b) -> new BlockLogicCobble(b, Material.stone, () -> Blocks.GRAVEL))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> COBBLE_BASALT = register("cobble.basalt", "minecraft:block/cobble_basalt", 12, (b) -> new BlockLogicCobble(b, Material.basalt, () -> Blocks.GRAVEL))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> COBBLE_LIMESTONE = register("cobble.limestone", "minecraft:block/cobble_limestone", 13, (b) -> new BlockLogicCobble(b, Material.limestone, () -> Blocks.GRAVEL))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> COBBLE_GRANITE = register("cobble.granite", "minecraft:block/cobble_granite", 14, (b) -> new BlockLogicCobble(b, Material.granite, () -> Blocks.GRAVEL))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> COBBLE_PERMAFROST = register("cobble.permafrost", "minecraft:block/cobble_permafrost", 15, (b) -> new BlockLogicCobble(b, Material.permafrost, () -> Blocks.GRAVEL))
+        .withSound(BlockSounds.PERMAFROST).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> STONE_POLISHED = register("stone.polished", "minecraft:block/stone_polished", 860, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> GRANITE_POLISHED = register("granite.polished", "minecraft:block/granite_polished", 861, (b) -> new BlockLogic(b, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> LIMESTONE_POLISHED = register("limestone.polished", "minecraft:block/limestone_polished", 862, (b) -> new BlockLogic(b, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BASALT_POLISHED = register("basalt.polished", "minecraft:block/basalt_polished", 863, (b) -> new BlockLogic(b, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> SLATE_POLISHED = register("slate.polished", "minecraft:block/slate_polished", 864, (b) -> new BlockLogic(b, Material.slate))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> PERMAFROST_POLISHED = register("permafrost.polished", "minecraft:block/permafrost_polished", 865, (b) -> new BlockLogic(b, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> NETHERRACK_POLISHED = register("netherrack.polished", "minecraft:block/netherrack_polished", 866, (b) -> new BlockLogic(b, Material.netherrack))
+        .withSound(BlockSounds.STONE).withHardness(0.4F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> PILLAR_MARBLE = register("pillar.marble", "minecraft:block/pillar_marble", 20, (b) -> new BlockLogicAxisAligned(b, Material.marble))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> CAPSTONE_MARBLE = register("capstone.marble", "minecraft:block/capstone_marble", 21, (b) -> new BlockLogic(b, Material.marble))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> SANDSTONE = register("sandstone", "minecraft:block/sandstone", 30, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(0.8F).withOverrideColor(MaterialColor.sand)
+        .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> STONE_CARVED = register("stone.carved", "minecraft:block/stone_carved", 40, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> GRANITE_CARVED = register("granite.carved", "minecraft:block/granite_carved", 41, (b) -> new BlockLogic(b, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> LIMESTONE_CARVED = register("limestone.carved", "minecraft:block/limestone_carved", 42, (b) -> new BlockLogic(b, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BASALT_CARVED = register("basalt.carved", "minecraft:block/basalt_carved", 43, (b) -> new BlockLogic(b, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> PERMAFROST_CARVED = register("permafrost.carved", "minecraft:block/permafrost_carved", 44, (b) -> new BlockLogic(b, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> NETHERRACK_CARVED = register("netherrack.carved", "minecraft:block/netherrack_carved", 45, (b) -> new BlockLogic(b, Material.netherrack))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> PLANKS_OAK = register("planks.oak", "minecraft:block/planks_oak", 50, BlockLogicPlanks::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicPlanksPainted> PLANKS_OAK_PAINTED = register("planks.oak.painted", "minecraft:block/planks_oak_painted", 51, BlockLogicPlanksPainted::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, false))
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> TORCH_COAL = register("torch.coal", "minecraft:block/torch_coal", 60, BlockLogicTorch::new)
+        .withSound(BlockSounds.WOOD).withHardness(0.0F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS);
+//    public static final BlockContainer<?> candleSoulwax;
+
+    public static final Block<?> LADDER_OAK = register("ladder.oak", "minecraft:block/ladder_oak", 70, BlockLogicLadder::new)
+        .withSound(BlockSounds.WOOD).withHardness(0.4F).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem(ItemBlockLadder::new)
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<BlockLogicFence> FENCE_PLANKS_OAK = register("fence.planks.oak", "minecraft:block/fence_planks_oak", 80, BlockLogicFence::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE, BlockTags.CAN_HANG_OFF);
+    public static final Block<BlockLogicFencePainted> FENCE_PLANKS_OAK_PAINTED = register("fence.planks.oak.painted", "minecraft:block/fence_planks_oak_painted", 81, BlockLogicFencePainted::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, false))
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE, BlockTags.CAN_HANG_OFF);
+
+    public static final Block<BlockLogicFenceGate> FENCE_GATE_PLANKS_OAK = register("fencegate.planks.oak", "minecraft:block/fence_gate_planks_oak", 90, BlockLogicFenceGate::new)
+        .withSound(BlockSounds.WOOD).withHardness(2F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicFenceGatePainted> FENCE_GATE_PLANKS_OAK_PAINTED = register("fencegate.planks.oak.painted", "minecraft:block/fence_gate_planks_oak_painted", 91, BlockLogicFenceGatePainted::new)
+        .withSound(BlockSounds.WOOD).withHardness(2F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, true))
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> BOOKSHELF_PLANKS_OAK = register("bookshelf.planks.oak", "minecraft:block/bookshelf_planks_oak", 100, (b) -> new BlockLogic(b, Material.wood))
+        .withSound(BlockSounds.WOOD).withHardness(1.5F)
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> WOOL = register("wool", "minecraft:block/wool", 110, BlockLogicWool::new)
+        .withSound(BlockSounds.CLOTH).withHardness(0.8F).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, false))
+        .withTags(BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<BlockLogicRope> ROPE = register("rope", "minecraft:block/rope", 111, BlockLogicRope::new)
+        .withSound(BlockSounds.CLOTH).withHardness(0.01F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.ROPE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS, BlockTags.CAN_HANG_OFF, BlockTags.INSTANT_PICKUP);
+
+    public static final Block<?> BRICK_CLAY = register("brick.clay", "minecraft:block/brick_clay", 120, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3.0F).withBlastResistance(10F).withOverrideColor(MaterialColor.brick)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_STONE_POLISHED = register("brick.stone.polished", "minecraft:block/brick_stone_polished", 121, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_STONE_POLISHED_MOSSY = register("brick.stone.polished.mossy", "minecraft:block/brick_stone_polished_mossy", 122, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(2F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_SANDSTONE = register("brick.sandstone", "minecraft:block/brick_sandstone", 123, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(0.8F).withBlastResistance(10F).withOverrideColor(MaterialColor.sand)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_GOLD = register("brick.gold", "minecraft:block/brick_gold", 124, (b) -> new BlockLogic(b, Material.metal))
+        .withSound(BlockSounds.METAL).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.gold)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_LAPIS = register("brick.lapis", "minecraft:block/brick_lapis", 125, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.lapis)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_BASALT = register("brick.basalt", "minecraft:block/brick_basalt", 126, (b) -> new BlockLogic(b, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_LIMESTONE = register("brick.limestone", "minecraft:block/brick_limestone", 127, (b) -> new BlockLogic(b, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_GRANITE = register("brick.granite", "minecraft:block/brick_granite", 128, (b) -> new BlockLogic(b, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_MARBLE = register("brick.marble", "minecraft:block/brick_marble", 129, (b) -> new BlockLogic(b, Material.marble))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_SLATE = register("brick.slate", "minecraft:block/brick_slate", 130, (b) -> new BlockLogic(b, Material.slate))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_STONE = register("brick.stone", "minecraft:block/brick_stone", 131, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_PERMAFROST = register("brick.permafrost", "minecraft:block/brick_permafrost", 132, (b) -> new BlockLogic(b, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(1.0F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_IRON = register("brick.iron", "minecraft:block/brick_iron", 133, (b) -> new BlockLogic(b, Material.metal))
+        .withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.iron)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BRICK_STEEL = register("brick.steel", "minecraft:block/brick_steel", 134, (b) -> new BlockLogic(b, Material.steel))
+        .withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(2000F).withOverrideColor(MaterialColor.steel)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<BlockLogicSlab> SLAB_PLANKS_OAK = register("slab.planks.oak", "minecraft:block/slab_planks_oak", 140, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlabPaintable(b, Blocks.PLANKS_OAK))
+        .withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicSlab> SLAB_COBBLE_STONE = register("slab.cobble.stone", "minecraft:block/slab_cobble_stone", 141, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.COBBLE_STONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_SANDSTONE = register("slab.sandstone", "minecraft:block/slab_sandstone", 142, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.SANDSTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_STONE_POLISHED = register("slab.brick.stone.polished", "minecraft:block/slab_brick_stone_polished", 143, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_STONE_POLISHED))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_STONE_POLISHED = register("slab.stone.carved", "minecraft:block/slab_stone_carved", 144, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.STONE_CARVED))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_MARBLE = register("slab.brick.marble", "minecraft:block/slab_brick_marble", 145, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_MARBLE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_CLAY = register("slab.brick.clay", "minecraft:block/slab_brick_clay", 146, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_CLAY))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_CAPSTONE_MARBLE = register("slab.capstone.marble", "minecraft:block/slab_capstone_marble", 147, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.CAPSTONE_MARBLE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_COBBLE_BASALT = register("slab.cobble.basalt", "minecraft:block/slab_cobble_basalt", 148, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.COBBLE_BASALT))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_COBBLE_LIMESTONE = register("slab.cobble.limestone", "minecraft:block/slab_cobble_limestone", 149, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.COBBLE_LIMESTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_COBBLE_GRANITE = register("slab.cobble.granite", "minecraft:block/slab_cobble_granite", 150, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.COBBLE_GRANITE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_BASALT = register("slab.brick.basalt", "minecraft:block/slab_brick_basalt", 151, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_BASALT))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_LIMESTONE = register("slab.brick.limestone", "minecraft:block/slab_brick_limestone", 152, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_LIMESTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_GRANITE = register("slab.brick.granite", "minecraft:block/slab_brick_granite", 153, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_GRANITE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlabPainted> SLAB_PLANKS_PAINTED = register("slab.planks.painted", "minecraft:block/slab_planks_oak_painted", 154, (BlockLogicSupplier<BlockLogicSlabPainted>) b -> new BlockLogicSlabPainted(b, Blocks.PLANKS_OAK_PAINTED))
+        .withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .setBlockItem(ItemBlockSlabPainted::new)
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_SLATE = register("slab.brick.slate", "minecraft:block/slab_brick_slate", 155, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_SLATE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_STONE = register("slab.brick.stone", "minecraft:block/slab_brick_stone", 156, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_STONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_GRANITE_POLISHED = register("slab.granite.carved", "minecraft:block/slab_granite_carved", 157, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.GRANITE_CARVED))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_LIMESTONE_POLISHED = register("slab.limestone.carved", "minecraft:block/slab_limestone_carved", 158, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.LIMESTONE_CARVED))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BASALT_POLISHED = register("slab.basalt.carved", "minecraft:block/slab_basalt_carved", 159, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BASALT_CARVED))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<BlockLogicStairs> STAIRS_PLANKS_OAK = register("stairs.planks.oak", "minecraft:block/stairs_planks_oak", 160, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairsPaintable(b, Blocks.PLANKS_OAK))
+        .withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicStairs> STAIRS_COBBLE_STONE = register("stairs.cobble.stone", "minecraft:block/stairs_cobble_stone", 161, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.COBBLE_STONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_STONE_POLISHED = register("stairs.brick.stone.polished", "minecraft:block/stairs_brick_stone_polished", 162, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_STONE_POLISHED))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_MARBLE = register("stairs.brick.marble", "minecraft:block/stairs_brick_marble", 163, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_MARBLE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_COBBLE_BASALT = register("stairs.cobble.basalt", "minecraft:block/stairs_cobble_basalt", 164, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.COBBLE_BASALT))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_COBBLE_LIMESTONE = register("stairs.cobble.limestone", "minecraft:block/stairs_cobble_limestone", 165, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.COBBLE_LIMESTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_COBBLE_GRANITE = register("stairs.cobble.granite", "minecraft:block/stairs_cobble_granite", 166, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.COBBLE_GRANITE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_BASALT = register("stairs.brick.basalt", "minecraft:block/stairs_brick_basalt", 167, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_BASALT))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_LIMESTONE = register("stairs.brick.limestone", "minecraft:block/stairs_brick_limestone", 168, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_LIMESTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_GRANITE = register("stairs.brick.granite", "minecraft:block/stairs_brick_granite", 169, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_GRANITE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_CLAY = register("stairs.brick.clay", "minecraft:block/stairs_brick_clay", 170, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_CLAY))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairsPainted> STAIRS_PLANKS_PAINTED = register("stairs.planks.oak.painted", "minecraft:block/stairs_planks_oak_painted", 171, (BlockLogicSupplier<BlockLogicStairsPainted>) b -> new BlockLogicStairsPainted(b, Blocks.PLANKS_OAK_PAINTED))
+        .withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .setBlockItem(ItemBlockStairsPainted::new)
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_SLATE = register("stairs.brick.slate", "minecraft:block/stairs_brick_slate", 172, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_SLATE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_STONE = register("stairs.brick.stone", "minecraft:block/stairs_brick_stone", 173, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_STONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_SANDSTONE = register("stairs.sandstone", "minecraft:block/stairs_sandstone", 174, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.SANDSTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_SANDSTONE = register("stairs.brick.sandstone", "minecraft:block/stairs_brick_sandstone", 175, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_SANDSTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_COBBLE_PERMAFROST = register("stairs.cobble.permafrost", "minecraft:block/stairs_cobble_permafrost", 176, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.COBBLE_PERMAFROST))
+        .withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_PERMAFROST = register("stairs.brick.permafrost", "minecraft:block/stairs_brick_permafrost", 177, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_PERMAFROST))
+        .withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> OBSIDIAN = register("obsidian", "minecraft:block/obsidian", 180, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(10F).withBlastResistance(2000F).withOverrideColor(MaterialColor.paintedBlack).withImmovableFlagSet()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PISTON_CRUSHING);
+
+    public static final Block<?> GLASS = register("glass", "minecraft:block/glass", 190, (b) -> new BlockLogicGlass(b, Material.glass))
+        .withSound(BlockSounds.GLASS).withHardness(0.3F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.EXTENDS_MOTION_SENSOR_RANGE);
+    public static final Block<?> GLASS_TINTED = register("glass.tinted", "minecraft:block/glass_tinted", 191, BlockLogicGlassTinted::new)
+        .withSound(BlockSounds.GLASS).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> GLASS_STEEL = register("glass.steel", "minecraft:block/glass_steel", 192, (b) -> new BlockLogicTransparent(b, Material.glass))
+        .withSound(BlockSounds.GLASS).withHardness(0.3F).withBlastResistance(2000F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.EXTENDS_MOTION_SENSOR_RANGE);
+
+    public static final Block<?> GRASS = register("grass", "minecraft:block/grass", 200, (b) -> new BlockLogicGrass(b, Blocks.DIRT))
+        .withSound(BlockSounds.GRASS).withHardness(0.6F)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.PASSIVE_MOBS_SPAWN, BlockTags.FIREFLIES_CAN_SPAWN, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.CAVE_GEN_REPLACES_SURFACE);
+    public static final Block<?> GRASS_RETRO = register("grass.retro", "minecraft:block/grass_retro", 201, (b) -> new BlockLogicGrass(b, Blocks.DIRT))
+        .withSound(BlockSounds.GRASS).withHardness(0.6F)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.PASSIVE_MOBS_SPAWN, BlockTags.FIREFLIES_CAN_SPAWN, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.CAVE_GEN_REPLACES_SURFACE);
+    public static final Block<?> GRASS_SCORCHED = register("grass.scorched", "minecraft:block/grass_scorched", 202, (b) -> new BlockLogicGrass(b, Blocks.DIRT_SCORCHED))
+        .withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.grassScorched)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.PASSIVE_MOBS_SPAWN, BlockTags.FIREFLIES_CAN_SPAWN, BlockTags.GROWS_CACTI, BlockTags.CAVE_GEN_REPLACES_SURFACE);
+
+    public static final Block<?> PATH_DIRT = register("path.dirt", "minecraft:block/path_dirt", 210, BlockLogicPathDirt::new)
+        .withSound(BlockSounds.GRAVEL).withHardness(0.5F).withLitInteriorSurface(true).withOverrideColor(MaterialColor.grassScorched)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL);
+
+    public static final Block<?> DIRT = register("dirt", "minecraft:block/dirt", 220, (b) -> new BlockLogic(b, Material.dirt))
+        .withSound(BlockSounds.GRAVEL).withHardness(0.5F)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH);
+    public static final Block<?> DIRT_SCORCHED = register("dirt.scorched", "minecraft:block/dirt_scorched", 221, (b) -> new BlockLogic(b, Material.dirt))
+        .withSound(BlockSounds.GRAVEL).withHardness(0.5F).withOverrideColor(MaterialColor.dirtScorched)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_CACTI, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH);
+    public static final Block<?> DIRT_SCORCHED_RICH = register("dirt.scorched.rich", "minecraft:block/dirt_scorched_rich", 222, (b) -> new BlockLogic(b, Material.dirt))
+        .withSound(BlockSounds.GRAVEL).withHardness(0.6F).withOverrideColor(MaterialColor.dirtScorched)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_CACTI, BlockTags.CAVES_CUT_THROUGH);
+
+    public static final Block<?> MUD = register("mud", "minecraft:block/mud", 225, (b) -> new BlockLogicMud(b, Material.dirt, false))
+        .withSound(BlockSounds.GRAVEL).withHardness(0.6F).withOverrideColor(MaterialColor.mud)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_CACTI, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.GROWS_SUGAR_CANE);
+    public static final Block<?> MUD_BAKED = register("mud.baked", "minecraft:block/mud_baked", 226, (b) -> new BlockLogicMud(b, Material.steel, true))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withOverrideColor(MaterialColor.dirt)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_CACTI, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.GROWS_SUGAR_CANE);
+
+    public static final Block<?> SPONGE_DRY = register("sponge.dry", "minecraft:block/sponge_dry", 230, (b) -> new BlockLogicSponge(b, false))
+        .withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.paintedYellow)
+        .withTags(BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> SPONGE_WET = register("sponge.wet", "minecraft:block/sponge_wet", 231, (b) -> new BlockLogicSponge(b, true))
+        .withSound(BlockSounds.GRASS).withHardness(1.0F).withOverrideColor(MaterialColor.paintedYellow)
+        .withTags(BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> PUMICE_DRY = register("pumice.dry", "minecraft:block/pumice_dry", 232, (b) -> new BlockLogicPumice(b, false))
+        .withSound(BlockSounds.STONE).withHardness(0.6F).withOverrideColor(MaterialColor.fire)
+        .withTags(BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> PUMICE_WET = register("pumice.wet", "minecraft:block/pumice_wet", 233, (b) -> new BlockLogicPumice(b, true))
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withLightEmission(0.625F).withOverrideColor(MaterialColor.fire)
+        .withTags(BlockTags.MINEABLE_BY_SHEARS);
+
+    public static final Block<?> MOSS_STONE = register("moss.stone", "minecraft:block/moss_stone", 240, (b) -> new BlockLogicMoss(b, Blocks.STONE))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
+    public static final Block<?> MOSS_BASALT = register("moss.basalt", "minecraft:block/moss_basalt", 241, (b) -> new BlockLogicMoss(b, Blocks.BASALT))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
+    public static final Block<?> MOSS_LIMESTONE = register("moss.limestone", "minecraft:block/moss_limestone", 242, (b) -> new BlockLogicMoss(b, Blocks.LIMESTONE))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
+    public static final Block<?> MOSS_GRANITE = register("moss.granite", "minecraft:block/moss_granite", 243, (b) -> new BlockLogicMoss(b, Blocks.GRANITE))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
+
+    public static final Block<?> SAND = register("sand", "minecraft:block/sand", 250, BlockLogicSand::new)
+        .withSound(BlockSounds.SAND).withHardness(0.5F)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_CACTI, BlockTags.CAVES_CUT_THROUGH, BlockTags.FIREFLIES_CAN_SPAWN);
+    public static final Block<?> GRAVEL = register("gravel", "minecraft:block/gravel", 251, BlockLogicGravel::new)
+        .withSound(BlockSounds.GRAVEL).withHardness(0.6F)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL);
+
+    public static final Block<?> BEDROCK = register("bedrock", "minecraft:block/bedrock", 260, (b) -> new BlockLogicBedrock(b, Material.stone))
+        .withSound(BlockSounds.STONE).withSetUnbreakable().withBlastResistance(6000000F).withImmovableFlagSet()
+        .withTags(BlockTags.PISTON_CRUSHING);
+    public static final Block<?> BONESHALE = register("boneshale", "minecraft:block/boneshale", 261, (b) -> new BlockLogicBoneShale(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(16F).withBlastResistance(6000000F).withImmovableFlagSet()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NETHER_MOBS_SPAWN);
+
+    public static final Block<BlockLogicFluid> FLUID_WATER_FLOWING = register("fluid.water.flowing", "minecraft:block/fluid_water_flowing", 270, (BlockLogicSupplier<BlockLogicFluid>) b -> new BlockLogicFluidFlowing(b, Material.water, Blocks.FLUID_WATER_STILL))
+        .withHardness(100F).withLightBlock(3).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
+        .withTags(BlockTags.IS_WATER, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<BlockLogicFluid> FLUID_WATER_STILL = register("fluid.water.still", "minecraft:block/fluid_water_still", 271, (BlockLogicSupplier<BlockLogicFluid>) b -> new BlockLogicFluidStill(b, Material.water, Blocks.FLUID_WATER_FLOWING))
+        .withHardness(100F).withLightBlock(3).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().setStatParent(() -> FLUID_WATER_FLOWING)
+        .withTags(BlockTags.IS_WATER, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<BlockLogicFluid> FLUID_LAVA_FLOWING = register("fluid.lava.flowing", "minecraft:block/fluid_lava_flowing", 272, (BlockLogicSupplier<BlockLogicFluid>) b -> new BlockLogicFluidFlowing(b, Material.lava, Blocks.FLUID_LAVA_STILL))
+        .withHardness(0.0F).withLightEmission(1.0F).withLightBlock(255).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
+        .withTags(BlockTags.IS_LAVA, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<BlockLogicFluid> FLUID_LAVA_STILL = register("fluid.lava.still", "minecraft:block/fluid_lava_still", 273, (BlockLogicSupplier<BlockLogicFluid>) b -> new BlockLogicFluidStill(b, Material.lava, Blocks.FLUID_LAVA_FLOWING))
+        .withHardness(100F).withLightEmission(1.0F).withLightBlock(255).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().setStatParent(() -> FLUID_LAVA_FLOWING)
+        .withTags(BlockTags.IS_LAVA, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
+
+    public static final Block<?> LOG_OAK = register("log.oak", "minecraft:block/log_oak", 280, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> LOG_PINE = register("log.pine", "minecraft:block/log_pine", 281, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> LOG_BIRCH = register("log.birch", "minecraft:block/log_birch", 282, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> LOG_CHERRY = register("log.cherry", "minecraft:block/log_cherry", 283, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> LOG_EUCALYPTUS = register("log.eucalyptus", "minecraft:block/log_eucalyptus", 284, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> LOG_OAK_MOSSY = register("log.oak.mossy", "minecraft:block/log_oak_mossy", 285, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> LOG_THORN = register("log.thorn", "minecraft:block/log_thorn", 286, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> LOG_PALM = register("log.palm", "minecraft:block/log_palm", 287, BlockLogicLog::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> LEAVES_OAK = register("leaves.oak", "minecraft:block/leaves_oak", 290, BlockLogicLeavesOak::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_OAK_RETRO = register("leaves.oak.retro", "minecraft:block/leaves_oak_retro", 291, (b) -> new BlockLogicLeavesBase(b, Material.leaves, Blocks.SAPLING_OAK_RETRO))
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_PINE = register("leaves.pine", "minecraft:block/leaves_pine", 292, BlockLogicLeavesPine::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.pineLeaves)
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_BIRCH = register("leaves.birch", "minecraft:block/leaves_birch", 293, (b) -> new BlockLogicLeavesBase(b, Material.leaves, Blocks.SAPLING_BIRCH))
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.birchLeaves)
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_CHERRY = register("leaves.cherry", "minecraft:block/leaves_cherry", 294, BlockLogicLeavesCherry::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.cherryLeaves)
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_EUCALYPTUS = register("leaves.eucalyptus", "minecraft:block/leaves_eucalyptus", 295, BlockLogicLeavesEucalyptus::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_SHRUB = register("leaves.shrub", "minecraft:block/leaves_shrub", 296, BlockLogicLeavesShrub::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_CHERRY_FLOWERING = register("leaves.cherry.flowering", "minecraft:block/leaves_cherry_flowering", 297, BlockLogicLeavesCherryFlowering::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.cherryLeaves)
+        .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_CACAO = register("leaves.cacao", "minecraft:block/leaves_cacao", 298, BlockLogicLeavesCacao::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_THORN = register("leaves.thorn", "minecraft:block/leaves_thorn", 299, (b) -> new BlockLogicLeavesBase(b, Material.leaves, Blocks.SAPLING_THORN))
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.thornLeaves)
+        .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+    public static final Block<?> LEAVES_PALM = register("leaves.palm", "minecraft:block/leaves_palm", 300, (b) -> new BlockLogicLeavesBase(b, Material.leaves, Blocks.SAPLING_PALM))
+        .withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.palmLeaves)
+        .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
+
+    public static final Block<?> SAPLING_OAK = register("sapling.oak", "minecraft:block/sapling_oak", 310, BlockLogicSaplingOak::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_OAK_RETRO = register("sapling.oak.retro", "minecraft:block/sapling_oak_retro", 311, BlockLogicSaplingRetro::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_PINE = register("sapling.pine", "minecraft:block/sapling_pine", 312, BlockLogicSaplingPine::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_BIRCH = register("sapling.birch", "minecraft:block/sapling_birch", 313, BlockLogicSaplingBirch::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_CHERRY = register("sapling.cherry", "minecraft:block/sapling_cherry", 314, BlockLogicSaplingCherry::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_EUCALYPTUS = register("sapling.eucalyptus", "minecraft:block/sapling_eucalyptus", 315, BlockLogicSaplingEucalyptus::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_SHRUB = register("sapling.shrub", "minecraft:block/sapling_shrub", 316, BlockLogicSaplingShrub::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_CACAO = register("sapling.cacao", "minecraft:block/sapling_cacao", 317, BlockLogicSaplingCacao::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_THORN = register("sapling.thorn", "minecraft:block/sapling_thorn", 318, BlockLogicSaplingThorn::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SAPLING_PALM = register("sapling.palm", "minecraft:block/sapling_palm", 319, BlockLogicSaplingPalm::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+
+    public static final Block<?> TALLGRASS = register("tallgrass", "minecraft:block/tallgrass", 320, b -> new BlockLogicTallGrass(b).setKilledByWeather())
+        .withSound(BlockSounds.GRASS).withHardness(0.0F)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.SHEEPS_FAVOURITE_BLOCK);
+    public static final Block<?> TALLGRASS_FERN = register("tallgrass.fern", "minecraft:block/tallgrass_fern", 321, b -> new BlockLogicTallGrass(b).setKilledByWeather())
+        .withSound(BlockSounds.GRASS).withHardness(0.0F)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
+    public static final Block<?> DEADBUSH = register("deadbush", "minecraft:block/deadbush", 322, BlockLogicDeadBush::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.wood)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.PLANTABLE_IN_JAR);
+    public static final Block<?> SPINIFEX = register("spinifex", "minecraft:block/spinifex", 323, BlockLogicSpinifex::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH);
+    public static final Block<?> ALGAE = register("algae", "minecraft:block/algae", 324, (b) -> new BlockLogicAlgae(b, Material.plant))
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withLitInteriorSurface(true)
+        .setBlockItem(ItemBlockAlgae::new)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH);
+
+    public static final Block<BlockLogicFlowerStackable> FLOWER_YELLOW = register("flower.yellow", "minecraft:block/flower_yellow", 330, (BlockLogicSupplier<BlockLogicFlowerStackable>)b -> (BlockLogicFlowerStackable) new BlockLogicFlowerStackable(b).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);
+    public static final Block<BlockLogicFlowerStackable> FLOWER_RED = register("flower.red", "minecraft:block/flower_red", 331, (BlockLogicSupplier<BlockLogicFlowerStackable>)b -> (BlockLogicFlowerStackable) new BlockLogicFlowerStackable(b).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);
+    public static final Block<BlockLogicFlowerStackable> FLOWER_PINK = register("flower.pink", "minecraft:block/flower_pink", 332, (BlockLogicSupplier<BlockLogicFlowerStackable>)b -> (BlockLogicFlowerStackable) new BlockLogicFlowerStackable(b).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);
+    public static final Block<BlockLogicFlowerStackable> FLOWER_PURPLE = register("flower.purple", "minecraft:block/flower_purple", 333, (BlockLogicSupplier<BlockLogicFlowerStackable>)b -> (BlockLogicFlowerStackable) new BlockLogicFlowerStackable(b).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);
+    public static final Block<BlockLogicFlowerStackable> FLOWER_LIGHT_BLUE = register("flower.lightblue", "minecraft:block/flower_light_blue", 334, (BlockLogicSupplier<BlockLogicFlowerStackable>)b -> (BlockLogicFlowerStackable) new BlockLogicFlowerStackable(b).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);
+    public static final Block<BlockLogicFlowerStackable> FLOWER_ORANGE = register("flower.orange", "minecraft:block/flower_orange", 335, (BlockLogicSupplier<BlockLogicFlowerStackable>)b -> (BlockLogicFlowerStackable) new BlockLogicFlowerStackable(b).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);
+
+    public static final Block<?> MUSHROOM_BROWN = register("mushroom.brown", "minecraft:block/mushroom_brown", 340, BlockLogicMushroom::new)
+        .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);
+    public static final Block<?> MUSHROOM_RED = register("mushroom.red", "minecraft:block/mushroom_red", 341, BlockLogicMushroom::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedRed)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.PIGS_FAVOURITE_BLOCK);
+
+    public static final Block<?> ORE_COAL_STONE = register("ore.coal.stone", "minecraft:block/ore_coal_stone", 350, (b) -> new BlockLogicOreCoal(b, Blocks.STONE, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_COAL_BASALT = register("ore.coal.basalt", "minecraft:block/ore_coal_basalt", 351, (b) -> new BlockLogicOreCoal(b, Blocks.BASALT, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_COAL_LIMESTONE = register("ore.coal.limestone", "minecraft:block/ore_coal_limestone", 352, (b) -> new BlockLogicOreCoal(b, Blocks.LIMESTONE, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_COAL_GRANITE = register("ore.coal.granite", "minecraft:block/ore_coal_granite", 353, (b) -> new BlockLogicOreCoal(b, Blocks.GRANITE, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_COAL_PERMAFROST = register("ore.coal.permafrost", "minecraft:block/ore_coal_permafrost", 354, (b) -> new BlockLogicOreCoal(b, Blocks.PERMAFROST, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ORE_IRON_STONE = register("ore.iron.stone", "minecraft:block/ore_iron_stone", 360, (b) -> new BlockLogicOreIron(b, Blocks.STONE, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_IRON_BASALT = register("ore.iron.basalt", "minecraft:block/ore_iron_basalt", 361, (b) -> new BlockLogicOreIron(b, Blocks.BASALT, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_IRON_LIMESTONE = register("ore.iron.limestone", "minecraft:block/ore_iron_limestone", 362, (b) -> new BlockLogicOreIron(b, Blocks.LIMESTONE, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_IRON_GRANITE = register("ore.iron.granite", "minecraft:block/ore_iron_granite", 363, (b) -> new BlockLogicOreIron(b, Blocks.GRANITE, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_IRON_PERMAFROST = register("ore.iron.permafrost", "minecraft:block/ore_iron_permafrost", 364, (b) -> new BlockLogicOreIron(b, Blocks.PERMAFROST, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ORE_GOLD_STONE = register("ore.gold.stone", "minecraft:block/ore_gold_stone", 370, (b) -> new BlockLogicOreGold(b, Blocks.STONE, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_GOLD_BASALT = register("ore.gold.basalt", "minecraft:block/ore_gold_basalt", 371, (b) -> new BlockLogicOreGold(b, Blocks.BASALT, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_GOLD_LIMESTONE = register("ore.gold.limestone", "minecraft:block/ore_gold_limestone", 372, (b) -> new BlockLogicOreGold(b, Blocks.LIMESTONE, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_GOLD_GRANITE = register("ore.gold.granite", "minecraft:block/ore_gold_granite", 373, (b) -> new BlockLogicOreGold(b, Blocks.GRANITE, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_GOLD_PERMAFROST = register("ore.gold.permafrost", "minecraft:block/ore_gold_permafrost",374, (b) -> new BlockLogicOreGold(b, Blocks.PERMAFROST, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ORE_LAPIS_STONE = register("ore.lapis.stone", "minecraft:block/ore_lapis_stone", 380, (b) -> new BlockLogicOreLapis(b, Blocks.STONE, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_LAPIS_BASALT = register("ore.lapis.basalt", "minecraft:block/ore_lapis_basalt", 381, (b) -> new BlockLogicOreLapis(b, Blocks.BASALT, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_LAPIS_LIMESTONE = register("ore.lapis.limestone", "minecraft:block/ore_lapis_limestone", 382, (b) -> new BlockLogicOreLapis(b, Blocks.LIMESTONE, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_LAPIS_GRANITE = register("ore.lapis.granite", "minecraft:block/ore_lapis_granite", 383, (b) -> new BlockLogicOreLapis(b, Blocks.GRANITE, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_LAPIS_PERMAFROST = register("ore.lapis.permafrost", "minecraft:block/ore_lapis_permafrost", 384, (b) -> new BlockLogicOreLapis(b, Blocks.PERMAFROST, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ORE_REDSTONE_STONE = register("ore.redstone.stone", "minecraft:block/ore_redstone_stone", 390,
+        (b) -> new BlockLogicOreRedstone(b, Blocks.STONE, Material.stone, false, Blocks.ORE_REDSTONE_STONE, Blocks.ORE_REDSTONE_GLOWING_STONE))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_BASALT = register("ore.redstone.basalt", "minecraft:block/ore_redstone_basalt", 391,
+        (b) -> new BlockLogicOreRedstone(b, Blocks.BASALT, Material.basalt, false, Blocks.ORE_REDSTONE_BASALT, Blocks.ORE_REDSTONE_GLOWING_BASALT))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_LIMESTONE = register("ore.redstone.limestone", "minecraft:block/ore_redstone_limestone", 392,
+        (b) -> new BlockLogicOreRedstone(b, Blocks.LIMESTONE, Material.limestone, false, Blocks.ORE_REDSTONE_LIMESTONE, Blocks.ORE_REDSTONE_GLOWING_LIMESTONE))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_GRANITE = register("ore.redstone.granite", "minecraft:block/ore_redstone_granite", 393,
+        (b) -> new BlockLogicOreRedstone(b, Blocks.GRANITE, Material.granite, false, Blocks.ORE_REDSTONE_GRANITE, Blocks.ORE_REDSTONE_GLOWING_GRANITE))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_PERMAFROST = register("ore.redstone.permafrost", "minecraft:block/ore_redstone_permafrost", 394,
+        (b) -> new BlockLogicOreRedstone(b, Blocks.PERMAFROST, Material.permafrost, false, Blocks.ORE_REDSTONE_PERMAFROST, Blocks.ORE_REDSTONE_GLOWING_PERMAFROST))
+        .withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ORE_REDSTONE_GLOWING_STONE = register("ore.redstone.glowing.stone", "minecraft:block/ore_redstone_glowing_stone", 400,
+        (b) -> new BlockLogicOreRedstone(b, null, Material.stone, true, Blocks.ORE_REDSTONE_STONE, Blocks.ORE_REDSTONE_GLOWING_STONE))
+        .withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_STONE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_GLOWING_BASALT = register("ore.redstone.glowing.basalt", "minecraft:block/ore_redstone_glowing_basalt", 401,
+        (b) -> new BlockLogicOreRedstone(b, null, Material.basalt, true, Blocks.ORE_REDSTONE_BASALT, Blocks.ORE_REDSTONE_GLOWING_BASALT))
+        .withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_BASALT)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_GLOWING_LIMESTONE = register("ore.redstone.glowing.limestone", "minecraft:block/ore_redstone_glowing_limestone", 402,
+        (b) -> new BlockLogicOreRedstone(b, null, Material.limestone, true, Blocks.ORE_REDSTONE_LIMESTONE, Blocks.ORE_REDSTONE_GLOWING_LIMESTONE))
+        .withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_LIMESTONE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_GLOWING_GRANITE = register("ore.redstone.glowing.granite", "minecraft:block/ore_redstone_glowing_granite", 403,
+        (b) -> new BlockLogicOreRedstone(b, null, Material.granite, true, Blocks.ORE_REDSTONE_GRANITE, Blocks.ORE_REDSTONE_GLOWING_GRANITE))
+        .withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_GRANITE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_REDSTONE_GLOWING_PERMAFROST = register("ore.redstone.glowing.permafrost", "minecraft:block/ore_redstone_glowing_permafrost", 404,
+        (b) -> new BlockLogicOreRedstone(b, null, Material.permafrost, true, Blocks.ORE_REDSTONE_PERMAFROST, Blocks.ORE_REDSTONE_GLOWING_PERMAFROST))
+        .withSound(BlockSounds.PERMAFROST).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_PERMAFROST)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ORE_DIAMOND_STONE = register("ore.diamond.stone", "minecraft:block/ore_diamond_stone", 410, (b) -> new BlockLogicOreDiamond(b, Blocks.STONE, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_DIAMOND_BASALT = register("ore.diamond.basalt", "minecraft:block/ore_diamond_basalt", 411, (b) -> new BlockLogicOreDiamond(b, Blocks.BASALT, Material.basalt))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_DIAMOND_LIMESTONE = register("ore.diamond.limestone", "minecraft:block/ore_diamond_limestone", 412, (b) -> new BlockLogicOreDiamond(b, Blocks.LIMESTONE, Material.limestone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_DIAMOND_GRANITE = register("ore.diamond.granite", "minecraft:block/ore_diamond_granite", 413, (b) -> new BlockLogicOreDiamond(b, Blocks.GRANITE, Material.granite))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ORE_DIAMOND_PERMAFROST = register("ore.diamond.permafrost", "minecraft:block/ore_diamond_permafrost", 414, (b) -> new BlockLogicOreDiamond(b, Blocks.PERMAFROST, Material.permafrost))
+        .withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ORE_NETHERCOAL_NETHERRACK = register("ore.nethercoal.netherrack", "minecraft:block/ore_nethercoal_netherrack", 420, BlockLogicOreNetherCoal::new)
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F).withLightEmission(0.625F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NETHER_MOBS_SPAWN);
+
+    public static final Block<?> BLOCK_COAL = register("block.coal", "minecraft:block/block_coal", 430, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.coal)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_IRON = register("block.iron", "minecraft:block/block_iron", 431, (b) -> new BlockLogic(b, Material.metal))
+        .withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.iron)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_GOLD = register("block.gold", "minecraft:block/block_gold", 432, (b) -> new BlockLogic(b, Material.metal))
+        .withSound(BlockSounds.METAL).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.gold)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_LAPIS = register("block.lapis", "minecraft:block/block_lapis", 433, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F).withOverrideColor(MaterialColor.lapis)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_REDSTONE = register("block.redstone", "minecraft:block/block_redstone", 434, (b) -> new BlockLogicRedstone(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.redstone)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_DIAMOND = register("block.diamond", "minecraft:block/block_diamond", 435, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.diamond)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_NETHER_COAL = register("block.nethercoal", "minecraft:block/block_nethercoal", 436, (b) -> new BlockLogic(b, Material.netherrack))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_STEEL = register("block.steel", "minecraft:block/block_steel", 437, (b) -> new BlockLogic(b, Material.steel))
+        .withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(2000F).withOverrideColor(MaterialColor.steel)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_QUARTZ = register("block.quartz", "minecraft:block/block_quartz", 438, (b) -> new BlockLogic(b, Material.steel))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.quartz)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_OLIVINE = register("block.olivine", "minecraft:block/block_olivine", 439, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.olivine)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> BLOCK_CHARCOAL = register("block.charcoal", "minecraft:block/block_charcoal", 440, (b) -> new BlockLogic(b, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.coal)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> WIRE_REDSTONE = register("wire.redstone", "minecraft:block/wire_redstone", 450, BlockLogicWireRedstone::new)
+        .withSound(BlockSounds.STONE).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> Items.DUST_REDSTONE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
+
+    public static final Block<?> TORCH_REDSTONE_IDLE = register("torch.redstone.idle", "minecraft:block/torch_redstone_idle", 460, (b) -> new BlockLogicTorchRedstone(b, false))
+        .withSound(BlockSounds.WOOD).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> Blocks.TORCH_REDSTONE_ACTIVE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
+    public static final Block<?> TORCH_REDSTONE_ACTIVE = register("torch.redstone.active", "minecraft:block/torch_redstone_active", 461, (b) -> new BlockLogicTorchRedstone(b, true))
+        .withSound(BlockSounds.WOOD).withHardness(0.0F).withLightEmission(0.5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PREVENT_MOB_SPAWNS);
+
+    public static final Block<?> BUTTON_STONE = register("button.stone", "minecraft:block/button_stone", 470, BlockLogicButton::new)
+        .withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
+
+    public static final Block<?> LEVER_COBBLE_STONE = register("lever.cobble.stone", "minecraft:block/lever_cobble_stone", 480, BlockLogicLever::new)
+        .withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
+
+    public static final Block<?> PRESSURE_PLATE_STONE = register("pressureplate.stone", "minecraft:block/pressure_plate_stone", 490, (b) -> new BlockLogicPressurePlate<>(b, Mob.class, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
+    public static final Block<?> PRESSURE_PLATE_PLANKS_OAK = register("pressureplate.planks.oak", "minecraft:block/pressure_plate_planks_oak", 491, (b) -> new BlockLogicPressurePlate<>(b, Entity.class, Material.wood))
+        .withSound(BlockSounds.WOOD).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.PREVENT_MOB_SPAWNS);
+    public static final Block<?> PRESSURE_PLATE_COBBLE_STONE = register("pressureplate.cobble.stone", "minecraft:block/pressure_plate_cobble_stone", 492, (b) -> new BlockLogicPressurePlate<>(b, Player.class, Material.stone))
+        .withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
+
+    public static final Block<BlockLogicMotionSensor> MOTION_SENSOR_IDLE = register("motionsensor.idle", "minecraft:block/motion_sensor_idle", 500, (BlockLogicSupplier<BlockLogicMotionSensor>)(b) -> new BlockLogicMotionSensor(b, false))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.stone)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicMotionSensor> MOTION_SENSOR_ACTIVE = register("motionsensor.active", "minecraft:block/motion_sensor_active", 501, (BlockLogicSupplier<BlockLogicMotionSensor>)(b) -> new BlockLogicMotionSensor(b, true))
+        .withSound(BlockSounds.STONE).withLightEmission(0.3F).withHardness(2.0F).withBlastResistance(10F).withOverrideColor(MaterialColor.stone).setStatParent(() -> MOTION_SENSOR_IDLE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<BlockLogicRepeater> REPEATER_IDLE = register("repeater.idle", "minecraft:block/repeater_idle", 510, (BlockLogicSupplier<BlockLogicRepeater>)b -> new BlockLogicRepeater(b, false))
+        .withSound(BlockSounds.STONE).withHardness(0.0F).withDisabledStats().withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> Items.REPEATER)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
+    public static final Block<BlockLogicRepeater> REPEATER_ACTIVE = register("repeater.active", "minecraft:block/repeater_active", 511, (BlockLogicSupplier<BlockLogicRepeater>)b -> new BlockLogicRepeater(b, true))
+        .withSound(BlockSounds.STONE).withHardness(0.0F).withLightEmission(0.625F).withDisabledStats().withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> REPEATER_IDLE)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
+
+    public static final Block<BlockLogicPistonBase> PISTON_BASE = register("piston.base", "minecraft:block/piston_base", 520, (BlockLogicSupplier<BlockLogicPistonBase>)b -> new BlockLogicPistonBase(b, 12))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicPistonBase> PISTON_BASE_STICKY = register("piston.base.sticky", "minecraft:block/piston_base_sticky", 521, (BlockLogicSupplier<BlockLogicPistonBase>)b -> new BlockLogicPistonBaseSticky(b, 12))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicPistonHead> PISTON_HEAD = register("piston.head", "minecraft:block/piston_head", 522, (BlockLogicSupplier<BlockLogicPistonHead>)(b) -> new BlockLogicPistonHead(b, 4/16d))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().withImmovableFlagSet()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicPistonMoving> PISTON_MOVING = register("piston.moving", "minecraft:block/piston_moving", 523, BlockLogicPistonMoving::new)
+        .withSound(BlockSounds.STONE).withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<BlockLogicPistonBase> PISTON_BASE_STEEL = register("piston.base.steel", "minecraft:block/piston_base_steel", 524, (BlockLogicSupplier<BlockLogicPistonBase>)b -> new BlockLogicPistonBaseSteel(b, 24))
+        .withSound(BlockSounds.METAL).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicPistonHead> PISTON_HEAD_STEEL = register("piston.head.steel", "minecraft:block/piston_head_steel", 525, (BlockLogicSupplier<BlockLogicPistonHead>)(b) -> new BlockLogicPistonHead(b, 6/16d))
+        .withSound(BlockSounds.METAL).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> NOTEBLOCK = register("noteblock", "minecraft:block/noteblock", 530, BlockLogicNote::new)
+        .withSound(BlockSounds.WOOD).withHardness(0.8F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<BlockLogicRail> RAIL = register("rail", "minecraft:block/rail", 540, (BlockLogicSupplier<BlockLogicRail>)b -> new BlockLogicRail(b, false))
+        .withSound(BlockSounds.METAL).withHardness(0.7F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
+    public static final Block<BlockLogicRail> RAIL_POWERED = register("rail.powered", "minecraft:block/rail_powered", 541, (BlockLogicSupplier<BlockLogicRail>)b -> new BlockLogicRail(b, true))
+        .withSound(BlockSounds.METAL).withHardness(0.7F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
+    public static final Block<BlockLogicRail> RAIL_DETECTOR = register("rail.detector", "minecraft:block/rail_detector", 542, (BlockLogicSupplier<BlockLogicRail>)BlockLogicRailDetector::new)
+        .withSound(BlockSounds.METAL).withHardness(0.7F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
+
+    public static final Block<?> SPIKES = register("spikes", "minecraft:block/spikes", 550, (b) -> new BlockLogicSpikes(b, Material.metal))
+        .withSound(BlockSounds.METAL).withLightBlock(3).withHardness(2F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> DISPENSER_COBBLE_STONE = register("dispenser.cobble.stone", "minecraft:block/dispenser_cobble_stone", 560, BlockLogicDispenser::new)
+        .withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> ACTIVATOR_COBBLE_NETHERRACK = register("activator.cobble.netherrack", "minecraft:block/activator_cobble_netherrack", 561, BlockLogicActivator::new)
+        .withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> TRAPDOOR_PLANKS_OAK = register("trapdoor.planks.oak", "minecraft:block/trapdoor_planks_oak", 570, (b) -> new BlockLogicTrapDoor(b, Material.wood))
+        .withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> TRAPDOOR_IRON = register("trapdoor.iron", "minecraft:block/trapdoor_iron", 571, (b) -> new BlockLogicTrapDoor(b, Material.metal))
+        .withSound(BlockSounds.METAL).withHardness(5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.iron)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> TRAPDOOR_GLASS = register("trapdoor.glass", "minecraft:block/trapdoor_glass", 572, (b) -> new BlockLogicTrapDoor(b, Material.glass))
+        .withSound(BlockSounds.GLASS).withHardness(0.3F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> TRAPDOOR_PLANKS_PAINTED = register("trapdoor.planks.oak.painted", "minecraft:block/trapdoor_planks_oak_painted", 573, (b) -> new BlockLogicTrapDoorPainted(b, Material.wood))
+        .withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, true))
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> TRAPDOOR_STEEL = register("trapdoor.steel", "minecraft:block/trapdoor_steel", 574, (b) -> new BlockLogicTrapDoor(b, Material.steel))
+        .withSound(BlockSounds.METAL).withOverrideColor(MaterialColor.steel).withHardness(5F).withBlastResistance(2000F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<BlockLogicTNT> TNT = register("tnt", "minecraft:block/tnt", 580, BlockLogicTNT::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F);
+
+    public static final Block<BlockLogicDoor> DOOR_PLANKS_OAK_BOTTOM = register("door.planks.oak.bottom", "minecraft:block/door_planks_oak_bottom", 590,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.wood, false, false, () -> Items.DOOR_OAK))
+        .withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.DOOR_OAK)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicDoor> DOOR_PLANKS_OAK_TOP = register("door.planks.oak.top", "minecraft:block/doors_planks_oak_top", 591,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.wood, true, false, () -> Items.DOOR_OAK))
+        .withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> DOOR_PLANKS_OAK_BOTTOM)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicDoor> DOOR_IRON_BOTTOM = register("door.iron.bottom", "minecraft:block/door_iron_bottom", 592,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.metal, false, true, () -> Items.DOOR_IRON))
+        .withSound(BlockSounds.METAL).withHardness(5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.iron).setStatParent(() -> Items.DOOR_IRON)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicDoor> DOOR_IRON_TOP = register("door.iron.top", "minecraft:block/door_iron_top", 593,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.metal, true, true, () -> Items.DOOR_IRON))
+        .withSound(BlockSounds.METAL).withHardness(5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.iron).setStatParent(() -> DOOR_IRON_BOTTOM)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicDoorPainted> DOOR_PLANKS_PAINTED_BOTTOM = register("door.planks.oak.painted.bottom", "minecraft:block/door_planks_oak_painted_bottom", 594,
+        (BlockLogicSupplier<BlockLogicDoorPainted>)(b) -> new BlockLogicDoorPainted(b, Material.wood, false))
+        .withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.DOOR_OAK_PAINTED)
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, true))
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicDoorPainted> DOOR_PLANKS_PAINTED_TOP = register("door.planks.oak.painted.top", "minecraft:block/door_planks_oak_painted_top", 595,
+        (BlockLogicSupplier<BlockLogicDoorPainted>)(b) -> new BlockLogicDoorPainted(b, Material.wood, true))
+        .withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> DOOR_PLANKS_PAINTED_BOTTOM)
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, true))
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicDoor> DOOR_GLASS_BOTTOM = register("door.glass.bottom", "minecraft:block/door_glass_bottom", 596,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.glass, false, false, () -> Items.DOOR_GLASS))
+        .withSound(BlockSounds.GLASS).withHardness(0.3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.DOOR_GLASS)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicDoor> DOOR_GLASS_TOP = register("door.glass.top", "minecraft:block/door_glass_top", 597,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.glass, true, false, () -> Items.DOOR_GLASS))
+        .withSound(BlockSounds.GLASS).withHardness(0.3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> DOOR_GLASS_BOTTOM)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicDoor> DOOR_STEEL_BOTTOM = register("door.steel.bottom", "minecraft:block/door_steel_bottom", 598,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.steel, false, true, () -> Items.DOOR_STEEL))
+        .withSound(BlockSounds.METAL).withHardness(5F).withOverrideColor(MaterialColor.steel).withBlastResistance(2000F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel).setStatParent(() -> Items.DOOR_STEEL)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicDoor> DOOR_STEEL_TOP = register("door.steel.top", "minecraft:block/door_steel_top", 599,
+        (BlockLogicSupplier<BlockLogicDoor>)b -> new BlockLogicDoor(b, Material.steel, true, true, () -> Items.DOOR_STEEL))
+        .withSound(BlockSounds.METAL).withHardness(5F).withOverrideColor(MaterialColor.steel).withBlastResistance(2000F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel).setStatParent(() -> DOOR_STEEL_BOTTOM)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> MESH = register("mesh", "minecraft:block/mesh", 600, BlockLogicMesh::new)
+        .withSound(BlockSounds.METAL).withHardness(1.5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CAN_HANG_OFF);
+    public static final Block<?> MESH_GOLD = register("mesh.gold", "minecraft:block/mesh_gold", 601, BlockLogicMeshGold::new)
+        .withSound(BlockSounds.METAL).withHardness(1F).withOverrideColor(MaterialColor.gold)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CAN_HANG_OFF);
+
+    public static final Block<BlockLogicBed> BED = register("bed", "minecraft:block/bed", 610, (BlockLogicSupplier<BlockLogicBed>)BlockLogicBed::new)
+        .withSound(BlockSounds.WOOD).withHardness(0.2F).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true).setStatParent(() -> Items.BED)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> SEAT = register("seat", "minecraft:block/seat", 611, BlockLogicSeat::new)
+        .withSound(BlockSounds.WOOD).withHardness(0.2F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.SEAT)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> COBWEB = register("cobweb", "minecraft:block/cobweb", 620, (b) -> new BlockLogicCobweb(b, Material.web))
+        .withSound(BlockSounds.CLOTH).withLightBlock(1).withHardness(4F)
+        .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_SHEARS, BlockTags.MINEABLE_BY_SWORD);
+
+    public static final Block<BlockLogicFire> FIRE = register("fire", "minecraft:block/fire", 630, BlockLogicFire::new)
+        .withSound(BlockSounds.FIRE).withHardness(0.0F).withLightEmission(1.0F).withDisabledStats().withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<BlockLogicBrazier> BRAZIER_INACTIVE = register("brazier.inactive", "minecraft:block/brazier_inactive", 631, (BlockLogicSupplier<BlockLogicBrazier>)b -> new BlockLogicBrazier(b, false))
+        .withSound(BlockSounds.METAL).withHardness(1.5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicBrazier> BRAZIER_ACTIVE = register("brazier.active", "minecraft:block/brazier_active", 632, (BlockLogicSupplier<BlockLogicBrazier>)b -> new BlockLogicBrazier(b, true))
+        .withSound(BlockSounds.FIRE).withHardness(1.5F).withLightEmission(1.0F).setStatParent(() -> BRAZIER_INACTIVE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> MOBSPAWNER = register("mobspawner", "minecraft:block/mobspawner", 640, BlockLogicMobSpawner::new)
+        .withSound(BlockSounds.METAL).withHardness(5F).withImmovableFlagSet()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> MOBSPAWNER_DEACTIVATED = register("mobspawner.deactivated", "minecraft:block/mobspawner_deactivated", 641, BlockLogicMobSpawnerDeactivated::new)
+        .withSound(BlockSounds.METAL).withHardness(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> WORKBENCH = register("workbench", "minecraft:block/workbench", 650, BlockLogicWorkbench::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.5F)
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> FURNACE_STONE_IDLE = register("furnace.stone.idle", "minecraft:block/furnace_stone_idle", 660, (b) -> new BlockLogicFurnace(b, false))
+        .withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> FURNACE_STONE_ACTIVE = register("furnace.stone.active", "minecraft:block/furnace_stone_active", 661, (b) -> new BlockLogicFurnace(b, true))
+        .withSound(BlockSounds.STONE).withHardness(3.5F).withLightEmission(0.875F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> FURNACE_STONE_IDLE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> FURNACE_BLAST_IDLE = register("furnace.blast.idle", "minecraft:block/furnace_blast_idle", 662, (b) -> new BlockLogicFurnaceBlast(b, false))
+        .withSound(BlockSounds.METAL).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> FURNACE_BLAST_ACTIVE = register("furnace.blast.active", "minecraft:block/furnace_blast_active", 663, (b) -> new BlockLogicFurnaceBlast(b, true))
+        .withSound(BlockSounds.METAL).withHardness(3.5F).withLightEmission(0.875F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel).setStatParent(() -> FURNACE_BLAST_IDLE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> TROMMEL_IDLE = register("trommel.idle", "minecraft:block/trommel_idle", 670, (b) -> new BlockLogicTrommel(b, Material.stone, false))
+        .withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> TROMMEL_ACTIVE = register("trommel.active", "minecraft:block/trommel_active", 671, (b) -> new BlockLogicTrommel(b, Material.stone, true))
+        .withSound(BlockSounds.STONE).withHardness(3.5F).withLightEmission(0.875F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> TROMMEL_IDLE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    @SuppressWarnings("deprecation")
+    public static final Block<BlockLogicChestLegacy> CHEST_LEGACY = register("chest.legacy", "minecraft:block/chest_legacy", 680, BlockLogicChestLegacy::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.5f).withBlastResistance(5.0f).setStatParent(() -> Blocks.CHEST_PLANKS_OAK)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    @SuppressWarnings("deprecation")
+    public static final Block<BlockLogicChestLegacy> CHEST_LEGACY_PAINTED = register("chest.legacy.painted", "minecraft:block/chest_legacy_painted", 681, BlockLogicChestLegacy::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.5f).withBlastResistance(5.0f).setStatParent(() -> Blocks.CHEST_PLANKS_OAK_PAINTED)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicChest> CHEST_PLANKS_OAK = register("chest.planks.oak", "minecraft:block/chest_planks_oak", 682, (BlockLogicSupplier<BlockLogicChest>)(b) -> new BlockLogicChest(b, Material.wood))
+        .withSound(BlockSounds.WOOD).withHardness(2.5F).withBlastResistance(5.0f).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicChest> CHEST_PLANKS_OAK_PAINTED = register("chest.planks.oak.painted", "minecraft:block/chest_planks_oak_painted", 683, (BlockLogicSupplier<BlockLogicChest>)(b) -> new BlockLogicChestPainted(b, Material.wood))
+        .withSound(BlockSounds.WOOD).withHardness(2.5F).withBlastResistance(5.0f).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem((b) -> new ItemBlockPainted<>(b, true))
+        .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> CROPS_WHEAT = register("crops.wheat", "minecraft:block/crops_wheat", 690, BlockLogicCropsWheat::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.SEEDS_WHEAT)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<?> CROPS_PUMPKIN = register("crops.pumpkin", "minecraft:block/crops_pumpkin", 691, BlockLogicCropsPumpkin::new)
+        .withSound(BlockSounds.WOOD).withHardness(0.0f).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true).setStatParent(() -> Items.SEEDS_PUMPKIN)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.OVERRIDE_STEPSOUND);
+
+    public static final Block<?> FARMLAND_DIRT = register("farmland.dirt", "minecraft:block/farmland_dirt", 700, BlockLogicFarmland::new)
+        .withSound(BlockSounds.GRAVEL).withHardness(0.6F).withLitInteriorSurface(true).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL);
+
+    public static final Block<?> SIGN_POST_PLANKS_OAK = register("sign.post.planks.oak", "minecraft:block/sign_post_planks_oak", 710, (b) -> new BlockLogicSign(b, true))
+        .withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.SIGN)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> SIGN_WALL_PLANKS_OAK = register("sign.wall.planks.oak", "minecraft:block/sign_wall_planks_oak", 711, (b) -> new BlockLogicSign(b, false))
+        .withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> SIGN_POST_PLANKS_OAK)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> FLAG = register("flag", "minecraft:block/flag", 712, (b) -> new BlockLogicFlag(b, Material.wood))
+        .withSound(BlockSounds.WOOD).withHardness(1.0F).setStatParent(() -> Items.FLAG)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<BlockLogicLayerSnow> LAYER_SNOW = register("layer.snow", "minecraft:block/layer_snow", 720, (BlockLogicSupplier<BlockLogicLayerSnow>)(b) -> new BlockLogicLayerSnow(b, Blocks.BLOCK_SNOW, Material.topSnow))
+        .withSound(BlockSounds.CLOTH).withHardness(0.1F).withLitInteriorSurface(true)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.MINEABLE_BY_SHOVEL, BlockTags.OVERRIDE_STEPSOUND);
+    public static final Block<BlockLogicLayerLeaves> LAYER_LEAVES_OAK = register("layer.leaves.oak", "minecraft:block/layer_leaves_oak", 721, (BlockLogicSupplier<BlockLogicLayerLeaves>)(b) -> new BlockLogicLayerLeaves(b, Blocks.LEAVES_OAK, Material.leaves))
+        .withSound(BlockSounds.GRASS).withLitInteriorSurface(true)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_SHEARS, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE);
+    public static final Block<?> LAYER_SLATE = register("layer.slate", "minecraft:block/layer_slate", 722, (b) -> new BlockLogicLayerSlate(b, Blocks.SLATE, Material.slate))
+        .withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F).withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> ICE = register("ice", "minecraft:block/ice", 730, BlockLogicIce::new)
+        .withSound(BlockSounds.GLASS).withHardness(0.5F).withLightBlock(3)
+        .withTags(BlockTags.SKATEABLE, BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> PERMAICE = register("ice.perma", "minecraft:block/permaice", 731, (b) -> new BlockLogicSlippery(b, Material.ice))
+        .withSound(BlockSounds.GLASS).withHardness(1.5F).withBlastResistance(10F)
+        .withTags(BlockTags.SKATEABLE, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> BLOCK_SNOW = register("block.snow", "minecraft:block/block_snow", 740, BlockLogicSnow::new)
+        .withSound(BlockSounds.CLOTH).withHardness(0.2F)
+        .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_SHOVEL, BlockTags.FIREFLIES_CAN_SPAWN);
+
+    public static final Block<?> CACTUS = register("cactus", "minecraft:block/cactus", 750, BlockLogicCactus::new)
+        .withSound(BlockSounds.CLOTH).withHardness(0.4F)
+        .withTags(BlockTags.GROWS_CACTI, BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_SHEARS, BlockTags.MINEABLE_BY_HOE);
+
+    public static final Block<?> BLOCK_CLAY = register("block.clay", "minecraft:block/block_clay", 760, BlockLogicClay::new)
+        .withSound(BlockSounds.GRAVEL).withHardness(0.6F)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL);
+
+    public static final Block<?> SUGARCANE = register("sugarcane", "minecraft:block/sugarcane", 770, BlockLogicSugarcane::new)
+        .withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedLime).setStatParent(() -> Items.SUGARCANE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<?> BLOCK_SUGARCANE = register("block.sugarcane", "minecraft:block/block_sugarcane", 771, (b) -> new BlockLogicAxisAligned(b, Material.moss))
+        .withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.paintedLime)
+        .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.FENCES_CONNECT);
+    public static final Block<?> BLOCK_SUGARCANE_BAKED = register("block.sugarcane.baked", "minecraft:block/block_sugarcane_baked", 772, (b) -> new BlockLogicAxisAligned(b, Material.moss))
+        .withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.wood)
+        .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.FENCES_CONNECT);
+
+    public static final Block<BlockLogicJukebox> JUKEBOX = register("jukebox", "minecraft:block/jukebox", 780, BlockLogicJukebox::new)
+        .withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> PUMPKIN = register("pumpkin", "minecraft:block/pumpkin", 790, (b) -> new BlockLogicPumpkin(b, true))
+        .withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> PUMPKIN_CARVED_IDLE = register("pumpkin.carved.idle", "minecraft:block/pumpkin_carved_idle", 791, (b) -> new BlockLogicPumpkin(b, false))
+        .withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> PUMPKIN_CARVED_ACTIVE = register("pumpkin.carved.active", "minecraft:block/pumpkin_carved_active", 792, (b) -> new BlockLogicPumpkin(b, false))
+        .withSound(BlockSounds.WOOD).withHardness(1.0F).withLightEmission(1.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+    public static final Block<?> PUMPKIN_REDSTONE = register("pumpkin.redstone", "minecraft:block/pumpkin_redstone", 793, BlockLogicPumpkinRedstone::new)
+        .withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange()
+        .withTags(BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<?> COBBLE_NETHERRACK = register("cobble.netherrack", "minecraft:block/cobble_netherrack", 800, (b) -> new BlockLogicCobble(b, Material.netherrack, null))
+        .withSound(BlockSounds.STONE).withHardness(0.4F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.INFINITE_BURN, BlockTags.CAVES_CUT_THROUGH, BlockTags.NETHER_MOBS_SPAWN);
+    public static final Block<?> COBBLE_NETHERRACK_IGNEOUS = register("cobble.netherrack.igneous", "minecraft:block/cobble_netherrack_igneous", 801, BlockLogicNetherrackIgneous::new)
+        .withSound(BlockSounds.STONE).withHardness(1.25F).withBlastResistance(7F).withLightEmission(10)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<?> COBBLE_NETHERRACK_MOSSY = register("cobble.netherrack.mossy", "minecraft:block/cobble_netherrack_mossy", 802, (b) -> new BlockLogicCobble(b, Material.netherrack, null))
+        .withSound(BlockSounds.STONE).withHardness(0.4F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.INFINITE_BURN);
+    public static final Block<?> NETHERRACK = register("netherrack", "minecraft:block/netherrack", 803, (b) -> new BlockLogicStone(b, 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);
+    public static final Block<?> BRICK_NETHERRACK = register("brick.netherrack", "minecraft:block/brick_netherrack", 804, (b) -> new BlockLogic(b, Material.netherrack))
+        .withSound(BlockSounds.STONE).withHardness(0.4F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_NETHERRACK_POLISHED = register("slab.netherrack.carved", "minecraft:block/slab_netherrack_carved", 805, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.NETHERRACK_CARVED))
+        .withSound(BlockSounds.STONE).withHardness(0.4F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_COBBLE_NETHERRACK = register("slab.cobble.netherrack", "minecraft:block/slab_cobble_netherrack", 806, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.COBBLE_NETHERRACK))
+        .withSound(BlockSounds.STONE).withHardness(0.4F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_NETHERRACK = register("slab.brick.netherrack", "minecraft:block/slab_brick_netherrack", 807, (BlockLogicSupplier<BlockLogicSlab>)b -> new BlockLogicSlab(b, Blocks.BRICK_NETHERRACK))
+        .withSound(BlockSounds.STONE).withHardness(0.4F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_COBBLE_NETHERRACK = register("stairs.cobble.netherrack", "minecraft:block/stairs_cobble_netherrack", 808, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.COBBLE_NETHERRACK))
+        .withSound(BlockSounds.STONE).withHardness(0.4F).withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicStairs> STAIRS_BRICK_NETHERRACK = register("stairs.brick.netherrack", "minecraft:block/stairs_brick_netherrack", 809, (BlockLogicSupplier<BlockLogicStairs>)b -> new BlockLogicStairs(b, Blocks.BRICK_NETHERRACK))
+        .withSound(BlockSounds.STONE).withHardness(0.4F).withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> SOULSAND = register("soulsand", "minecraft:block/soulsand", 810, BlockLogicSoulSand::new)
+        .withSound(BlockSounds.SAND).withHardness(0.5F).withOverrideColor(MaterialColor.paintedBrown)
+        .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.CAVES_CUT_THROUGH, BlockTags.NETHER_MOBS_SPAWN);
+    public static final Block<?> SOULSCHIST = register("soulschist", "minecraft:block/soulschist", 811, (b) -> new BlockLogicCobble(b, Material.stone, () -> Blocks.SOULSAND))
+        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withOverrideColor(MaterialColor.paintedBrown)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NETHER_MOBS_SPAWN);
+
+    public static final Block<?> GLOWSTONE = register("glowstone", "minecraft:block/glowstone", 820, (b) -> new BlockLogicGlowStone(b, Material.stone))
+        .withSound(BlockSounds.GLASS).withHardness(0.3F).withLightEmission(1.0F).withOverrideColor(MaterialColor.paintedYellow)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<BlockLogicPortal> PORTAL_NETHER = register("portal.nether", "minecraft:block/portal_nether", 830, (BlockLogicSupplier<BlockLogicPortal>) b -> new BlockLogicPortal(b, Dimension.NETHER, Blocks.OBSIDIAN, Blocks.FIRE))
+        .withSound(BlockSounds.GLASS).withHardness(-1F).withLightEmission(0.75F).withOverrideColor(MaterialColor.paintedPurple).withDisabledStats()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<BlockLogicPortal> PORTAL_PARADISE = register("portal.paradise", "minecraft:block/portal_paradise", 831, (BlockLogicSupplier<BlockLogicPortal>) b -> new BlockLogicPortal(b, Dimension.PARADISE, Blocks.GLOWSTONE, Blocks.BEDROCK))
+        .withSound(BlockSounds.GLASS).withHardness(-1F).withLightEmission(0.75f).withOverrideColor(MaterialColor.paintedPurple).withDisabledStats()
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
+
+    public static final Block<?> CAKE = register("cake", "minecraft:block/cake", 840, BlockLogicCake::new)
+        .withSound(BlockSounds.CLOTH).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.FOOD_CAKE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<BlockLogicEdible> PUMPKIN_PIE = register("pumpkin_pie", "minecraft:block/pumpkin_pie", 841, (BlockLogicSupplier<BlockLogicEdible>)BlockLogicPiePumpkin::new)
+        .withSound(BlockSounds.CLOTH).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.paintedOrange).setStatParent(() -> Items.FOOD_PUMPKIN_PIE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
+
+    public static final Block<BlockLogicLamp> LAMP_IDLE = register("lamp.idle", "minecraft:block/lamp_idle", 850, (BlockLogicSupplier<BlockLogicLamp>)b -> new BlockLogicLamp(b, false))
+        .withSound(BlockSounds.GLASS).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
+        .setBlockItem(ItemBlockLamp::new)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicLamp> LAMP_ACTIVE = register("lamp.active", "minecraft:block/lamp_active", 851, (BlockLogicSupplier<BlockLogicLamp>)b -> new BlockLogicLamp(b, true))
+        .withSound(BlockSounds.GLASS).withLightEmission(0.9375F).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> LAMP_IDLE)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static final Block<?> LANTERN_FIREFLY_GREEN = register("lantern.firefly.green", "minecraft:block/lantern_firefly_green", 870,
+        (b) -> new BlockLogicLanternFirefly(b, MobFireflyCluster.FireflyColor.GREEN, () -> Items.LANTERN_FIREFLY_GREEN))
+        .withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_GREEN)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<?> LANTERN_FIREFLY_BLUE = register("lantern.firefly.blue", "minecraft:block/lantern_firefly_blue", 871,
+        (b) -> new BlockLogicLanternFirefly(b, MobFireflyCluster.FireflyColor.BLUE, () -> Items.LANTERN_FIREFLY_BLUE))
+        .withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_BLUE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<?> LANTERN_FIREFLY_ORANGE = register("lantern.firefly.orange", "minecraft:block/lantern_firefly_orange", 872,
+        (b) -> new BlockLogicLanternFirefly(b, MobFireflyCluster.FireflyColor.ORANGE, () -> Items.LANTERN_FIREFLY_ORANGE))
+        .withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_ORANGE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<?> LANTERN_FIREFLY_RED = register("lantern.firefly.red", "minecraft:block/lantern_firefly_red", 873,
+        (b) -> new BlockLogicLanternFirefly(b, MobFireflyCluster.FireflyColor.RED, () -> Items.LANTERN_FIREFLY_RED))
+        .withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_RED)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
+    public static final Block<?> JAR_GLASS = register("jar.glass", "minecraft:block/jar_glass", 874,
+        (b) -> new BlockLogicJar(b, () -> Items.JAR))
+        .withSound(BlockSounds.GLASS).withHardness(0.1F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.JAR)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
+
+    public static final Block<?> OVERLAY_PEBBLES = register("overlay.pebbles", "minecraft:block/overlay_pebbles", 880, (b) -> new BlockLogicOverlayPebbles(b, Material.decoration))
+        .withSound(BlockSounds.STONE).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.AMMO_PEBBLE)
+        .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
+
+    public static final Block<BlockLogicFenceThin> FENCE_CHAINLINK = register("fence.chainlink", "minecraft:block/fence_chainlink", 890, (BlockLogicSupplier<BlockLogicFenceThin>)b -> new BlockLogicFenceChainlink(b, Material.metal))
+        .withSound(BlockSounds.METAL).withHardness(5F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CHAINLINK_FENCES_CONNECT, BlockTags.CAN_HANG_OFF);
+    public static final Block<BlockLogicFenceThin> FENCE_PAPER_WALL = register("fence.paper_wall", "minecraft:block/fence_paper_wall", 891, (BlockLogicSupplier<BlockLogicFenceThin>)b -> new BlockLogicFenceWallPaper(b, Material.cloth))
+        .withSound(BlockSounds.CLOTH).withHardness(0.5F)
+        .withTags(BlockTags.MINEABLE_BY_SHEARS, BlockTags.FENCES_CONNECT, BlockTags.CAN_HANG_OFF, BlockTags.MINEABLE_BY_AXE);
+    public static final Block<BlockLogicFenceThin> FENCE_STEEL = register("fence.steel", "minecraft:block/fence_steel", 892, (BlockLogicSupplier<BlockLogicFenceThin>)b -> new BlockLogicFenceSteel(b, Material.steel))
+        .withSound(BlockSounds.METAL).withHardness(8F).withOverrideColor(MaterialColor.steel).withBlastResistance(2000F)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CHAINLINK_FENCES_CONNECT, BlockTags.CAN_HANG_OFF);
+
+    public static final Block<BlockLogicBasket> BASKET = register("basket", "minecraft:block/basket", 900, (BlockLogicSupplier<BlockLogicBasket>)(b) -> new BlockLogicBasket(b, Material.cloth))
+        .withSound(BlockSounds.CLOTH).withHardness(0.5F).withOverrideColor(MaterialColor.wood).setStatParent(() -> Items.BASKET)
+        .withTags(BlockTags.NOT_IN_CREATIVE_MENU);
+
+    public static final Block<?> PAPER_WALL = register("paper_wall", "minecraft:block/paper_wall", 910, (b) -> new BlockLogic(b, Material.cloth))
+        .withSound(BlockSounds.CLOTH).withHardness(0.7F)
+        .withTags(BlockTags.MINEABLE_BY_SHEARS, BlockTags.FENCES_CONNECT, BlockTags.CAN_HANG_OFF, BlockTags.MINEABLE_BY_AXE);
+
+    public static final Block<BlockLogicSlab> SLAB_BRICK_SANDSTONE = register("slab.brick.sandstone", "minecraft:block/slab_brick_sandstone", 1000, (BlockLogicSupplier<BlockLogicSlab>) b -> new BlockLogicSlab(b, Blocks.BRICK_SANDSTONE))
+        .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_COBBLE_PERMAFROST = register("slab.cobble.permafrost", "minecraft:block/slab_cobble_permafrost", 1001, (BlockLogicSupplier<BlockLogicSlab>) b -> new BlockLogicSlab(b, Blocks.COBBLE_PERMAFROST))
+        .withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_BRICK_PERMAFROST = register("slab.brick.permafrost", "minecraft:block/slab_brick_permafrost", 1002, (BlockLogicSupplier<BlockLogicSlab>) b -> new BlockLogicSlab(b, Blocks.BRICK_PERMAFROST))
+        .withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static final Block<BlockLogicSlab> SLAB_PERMAFROST_POLISHED = register("slab.permafrost.carved", "minecraft:block/slab_permafrost_carved", 1003, (BlockLogicSupplier<BlockLogicSlab>) b -> new BlockLogicSlab(b, Blocks.PERMAFROST_CARVED))
+        .withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
+        .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+
+    public static <T extends BlockLogic> Block<T> register(String key, String namespaceId, int id, BlockLogicSupplier<T> logicSupplier) {
+        Block<T> container = new Block<>(id, key, namespaceId, logicSupplier);
+
+        if (Blocks.blocksList[container.id()] != null) throw new IllegalArgumentException("Id '" + id + "' of block '" + container.namespaceId() + "' is already being used by '" + Blocks.blocksList[container.id()].namespaceId() + "'!");
+        Blocks.blocksList[container.id()] = container;
+        if (Blocks.keyToIdMap.containsKey(container.getKey())) throw new IllegalArgumentException("Key '" + container.getKey() + "' of block '" + container.namespaceId() + "' is already being used by '" + Blocks.getBlock(Blocks.keyToIdMap.get(container.getKey())).namespaceId() + "'!");
+        Blocks.keyToIdMap.put(container.getKey(), container.id());
+        if (Blocks.blockMap.containsKey(container.namespaceId())) throw new IllegalArgumentException("NamespaceId '" + container.namespaceId() + "' of block '" + container.getKey() + "' is already being used by '" + Blocks.blockMap.get(container.namespaceId()).namespaceId() + "'!");
+        Blocks.blockMap.put(container.namespaceId(), container);
+
+        if (Blocks.highestBlockId < container.id()) Blocks.highestBlockId = container.id();
+
+        return container;
+    }
 
-    public static Block PAPER_WALL;
+    private static void resetCaches() {
+        for (int i = 0; i < Blocks.blocksList.length; i++) {
+            Arrays.fill(Blocks.solid, false);
+            Arrays.fill(Blocks.lightBlock, 0);
+            Arrays.fill(Blocks.translucent, false);
+            Arrays.fill(Blocks.isEntityTile, false);
+            Arrays.fill(Blocks.lightEmission, 0);
+            Arrays.fill(Blocks.lightBlock, 0);
+            Arrays.fill(Blocks.neighborNotifyOnMetadataChangeDisabled, false);
+            Arrays.fill(Blocks.shouldTick, false);
+        }
+        translucent[0] = true;
+    }
 
-    public static Block SLAB_BRICK_SANDSTONE;
-    public static Block SLAB_COBBLE_PERMAFROST;
-    public static Block SLAB_BRICK_PERMAFROST;
-    public static Block SLAB_PERMAFROST_POLISHED;
+    private static void cacheBlock(Block<?> container) {
+        Blocks.solid[container.id()] = container.isSolidRender();
+        Blocks.lightBlock[container.id()] = (container.isSolidRender() || container.blocksLight()) ? 255 : 0;
+        Blocks.translucent[container.id()] = !container.getMaterial().blocksLight();
+        Blocks.isEntityTile[container.id()] = container.isEntityTile;
+        Blocks.lightEmission[container.id()] = container.emission;
+        Blocks.lightBlock[container.id()] = container.lightBlock;
+        Blocks.neighborNotifyOnMetadataChangeDisabled[container.id()] = container.disabledNeighborMetaNotify;
+        Blocks.shouldTick[container.id()] = container.shouldTick;
+    }
 
     public static void init(){
-        setupBlocks();
-        BlockMoss.initMossMap();
+        resetCaches();
+        for (Block<?> b : blocksList) {
+            if (b == null) continue;
+            b.init();
+        }
+
+        BlockLogicMoss.initMossMap();
 
         for(int i = 0; i < blocksList.length; i++)
         {
-            Block block;
+            Block<?> block;
             if((block = blocksList[i]) != null)
             {
                 if (Item.itemsList[i] == null){
@@ -480,779 +1223,29 @@ public final class Blocks {
                     }
                     Item.itemsList[i] = item;
                 }
-                block.initializeBlock();
+                block.getLogic().initializeBlock();
             }
         }
 
-        translucent[0] = true;
-
         MaterialColor.assignManualEntries();
+
+        for (Block<?> b : blocksList) {
+            if (b == null) continue;
+            cacheBlock(b);
+        }
     }
 
     @Nullable
-    public static Block getBlock(int id)
+    public static Block<?> getBlock(int id)
     {
-        return Blocks.blocksList[Math.max(id, 0)];
+        return Blocks.blocksList[id];
     }
 
-    public static void setupBlocks(){
-        STONE = new BlockStone("stone", "minecraft:block/stone", 1, () -> Blocks.COBBLE_STONE, Material.stone).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
-        BASALT = new BlockStone("basalt", "minecraft:block/basalt", 2, () -> Blocks.COBBLE_BASALT, Material.basalt).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
-        LIMESTONE = new BlockStone("limestone", "minecraft:block/limestone", 3, () -> Blocks.COBBLE_LIMESTONE, Material.limestone).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
-        GRANITE = new BlockStone("granite", "minecraft:block/granite", 4, () -> Blocks.COBBLE_GRANITE, Material.granite).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
-        MARBLE = new Block("marble", "minecraft:block/marble", 5, Material.marble).withSound(BlockSounds.STONE).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLATE = new Block("slate", "minecraft:block/slate", 6, Material.slate).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        PERMAFROST = new BlockStone("permafrost", "minecraft:block/permafrost", 7, () -> Blocks.COBBLE_PERMAFROST, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
-
-        COBBLE_STONE = new BlockCobble("cobble.stone", "minecraft:block/cobble_stone", 10, Material.stone, () -> GRAVEL).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        COBBLE_STONE_MOSSY = new BlockCobble("cobble.stone.mossy", "minecraft:block/cobble_stone_mossy", 11, Material.stone, () -> GRAVEL).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        COBBLE_BASALT = new BlockCobble("cobble.basalt", "minecraft:block/cobble_basalt", 12, Material.basalt, () -> GRAVEL).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        COBBLE_LIMESTONE = new BlockCobble("cobble.limestone", "minecraft:block/cobble_limestone", 13, Material.limestone, () -> GRAVEL).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        COBBLE_GRANITE = new BlockCobble("cobble.granite", "minecraft:block/cobble_granite", 14, Material.granite, () -> GRAVEL).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        COBBLE_PERMAFROST = new BlockCobble("cobble.permafrost", "minecraft:block/cobble_permafrost", 15, Material.permafrost, () -> GRAVEL).withSound(BlockSounds.PERMAFROST).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        STONE_POLISHED = new Block("stone.polished", "minecraft:block/stone_polished", 860, Material.stone).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        GRANITE_POLISHED = new Block("granite.polished", "minecraft:block/granite_polished", 861, Material.granite).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        LIMESTONE_POLISHED = new Block("limestone.polished", "minecraft:block/limestone_polished", 862, Material.limestone).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BASALT_POLISHED = new Block("basalt.polished", "minecraft:block/basalt_polished", 863, Material.basalt).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLATE_POLISHED = new Block("slate.polished", "minecraft:block/slate_polished", 864, Material.slate).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        PERMAFROST_POLISHED = new Block("permafrost.polished", "minecraft:block/permafrost_polished", 865, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        NETHERRACK_POLISHED = new Block("netherrack.polished", "minecraft:block/netherrack_polished", 866, Material.netherrack).withSound(BlockSounds.STONE).withHardness(0.4F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        PILLAR_MARBLE = new BlockAxisAligned("pillar.marble", "minecraft:block/pillar_marble", 20, Material.marble).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        CAPSTONE_MARBLE = new Block("capstone.marble", "minecraft:block/capstone_marble", 21, Material.marble).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        SANDSTONE = new Block("sandstone", "minecraft:block/sandstone", 30, Material.stone).withSound(BlockSounds.STONE).withHardness(0.8F).withOverrideColor(MaterialColor.sand)
-            .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
-
-        STONE_CARVED = new Block("stone.carved", "minecraft:block/stone_carved", 40, Material.stone).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        GRANITE_CARVED = new Block("granite.carved", "minecraft:block/granite_carved", 41, Material.granite).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        LIMESTONE_CARVED = new Block("limestone.carved", "minecraft:block/limestone_carved", 42, Material.limestone).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        BASALT_CARVED = new Block("basalt.carved", "minecraft:block/basalt_carved", 43, Material.basalt).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        PERMAFROST_CARVED = new Block("permafrost.carved", "minecraft:block/permafrost_carved", 44, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        NETHERRACK_CARVED = new Block("netherrack.carved", "minecraft:block/netherrack_carved", 45, Material.netherrack).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        PLANKS_OAK = new BlockPlanks("planks.oak", "minecraft:block/planks_oak", 50, Material.wood).withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        PLANKS_OAK_PAINTED = new BlockPlanksPainted("planks.oak.painted", "minecraft:block/planks_oak_painted", 51).withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockPainted(b, false))
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-
-        TORCH_COAL = new BlockTorch("torch.coal", "minecraft:block/torch_coal", 60).withSound(BlockSounds.WOOD).withHardness(0.0F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS);
-
-        LADDER_OAK = new BlockLadder("ladder.oak", "minecraft:block/ladder_oak", 70).withSound(BlockSounds.WOOD).withHardness(0.4F).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockLadder((BlockLadder) b))
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-
-        FENCE_PLANKS_OAK = new BlockFence("fence.planks.oak", "minecraft:block/fence_planks_oak", 80).withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE, BlockTags.CAN_HANG_OFF);
-        FENCE_PLANKS_OAK_PAINTED = new BlockFencePainted("fence.planks.oak.painted", "minecraft:block/fence_planks_oak_painted", 81).withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockPainted(b, false))
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE, BlockTags.CAN_HANG_OFF);
-
-        FENCE_GATE_PLANKS_OAK = new BlockFenceGate("fencegate.planks.oak", "minecraft:block/fence_gate_planks_oak", 90).withSound(BlockSounds.WOOD).withHardness(2F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        FENCE_GATE_PLANKS_OAK_PAINTED = new BlockFenceGatePainted("fencegate.planks.oak.painted", "minecraft:block/fence_gate_planks_oak_painted", 91).withSound(BlockSounds.WOOD).withHardness(2F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockPainted(b, true))
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-
-        BOOKSHELF_PLANKS_OAK = new Block("bookshelf.planks.oak", "minecraft:block/bookshelf_planks_oak", 100, Material.wood).withSound(BlockSounds.WOOD).withHardness(1.5F)
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-
-        WOOL = new BlockWool("wool", "minecraft:block/wool", 110).withSound(BlockSounds.CLOTH).withHardness(0.8F).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockPainted(b, false))
-            .withTags(BlockTags.MINEABLE_BY_SHEARS);
-        ROPE = new BlockRope("rope", "minecraft:block/rope", 111).withSound(BlockSounds.CLOTH).withHardness(0.01F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.ROPE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS, BlockTags.CAN_HANG_OFF, BlockTags.INSTANT_PICKUP);
-
-        BRICK_CLAY = new Block("brick.clay", "minecraft:block/brick_clay", 120, Material.stone).withSound(BlockSounds.STONE).withHardness(3.0F).withBlastResistance(10F).withOverrideColor(MaterialColor.brick)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_STONE_POLISHED = new Block("brick.stone.polished", "minecraft:block/brick_stone_polished", 121, Material.stone).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_STONE_POLISHED_MOSSY = new Block("brick.stone.polished.mossy", "minecraft:block/brick_stone_polished_mossy", 122, Material.stone).withSound(BlockSounds.STONE).withHardness(2F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_SANDSTONE = new Block("brick.sandstone", "minecraft:block/brick_sandstone", 123, Material.stone).withSound(BlockSounds.STONE).withHardness(0.8F).withBlastResistance(10F).withOverrideColor(MaterialColor.sand)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_GOLD = new Block("brick.gold", "minecraft:block/brick_gold", 124, Material.metal).withSound(BlockSounds.METAL).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.gold)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_LAPIS = new Block("brick.lapis", "minecraft:block/brick_lapis", 125, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.lapis)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_BASALT = new Block("brick.basalt", "minecraft:block/brick_basalt", 126, Material.basalt).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_LIMESTONE = new Block("brick.limestone", "minecraft:block/brick_limestone", 127, Material.limestone).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_GRANITE = new Block("brick.granite", "minecraft:block/brick_granite", 128, Material.granite).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_MARBLE = new Block("brick.marble", "minecraft:block/brick_marble", 129, Material.marble).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_SLATE = new Block("brick.slate", "minecraft:block/brick_slate", 130, Material.slate).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_STONE = new Block("brick.stone", "minecraft:block/brick_stone", 131, Material.stone).withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_PERMAFROST = new Block("brick.permafrost", "minecraft:block/brick_permafrost", 132, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(1.0F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_IRON = new Block("brick.iron", "minecraft:block/brick_iron", 133, Material.metal).withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.iron)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRICK_STEEL = new Block("brick.steel", "minecraft:block/brick_steel", 134, Material.metal).withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(2000F).withOverrideColor(MaterialColor.steel)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        SLAB_PLANKS_OAK = new BlockSlabPaintable(PLANKS_OAK, "minecraft:block/slab_planks_oak", 140).withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        SLAB_COBBLE_STONE = new BlockSlab(COBBLE_STONE, "minecraft:block/slab_cobble_stone", 141).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_SANDSTONE = new BlockSlab(SANDSTONE, "minecraft:block/slab_sandstone", 142).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_STONE_POLISHED = new BlockSlab(BRICK_STONE_POLISHED, "minecraft:block/slab_brick_stone_polished", 143).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_STONE_POLISHED = new BlockSlab(STONE_CARVED, "minecraft:block/slab_stone_polished", 144).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_MARBLE = new BlockSlab(BRICK_MARBLE, "minecraft:block/slab_brick_marble", 145).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_CLAY = new BlockSlab(BRICK_CLAY, "minecraft:block/slab_brick_clay", 146).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_CAPSTONE_MARBLE = new BlockSlab(CAPSTONE_MARBLE, "minecraft:block/slab_capstone_marble", 147).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_COBBLE_BASALT = new BlockSlab(COBBLE_BASALT, "minecraft:block/slab_cobble_basalt", 148).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_COBBLE_LIMESTONE = new BlockSlab(COBBLE_LIMESTONE, "minecraft:block/slab_cobble_limestone", 149).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_COBBLE_GRANITE = new BlockSlab(COBBLE_GRANITE, "minecraft:block/slab_cobble_granite", 150).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_BASALT = new BlockSlab(BRICK_BASALT, "minecraft:block/slab_brick_basalt", 151).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_LIMESTONE = new BlockSlab(BRICK_LIMESTONE, "minecraft:block/slab_brick_limestone", 152).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_GRANITE = new BlockSlab(BRICK_GRANITE, "minecraft:block/slab_brick_granite", 153).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_PLANKS_PAINTED = new BlockSlabPainted(PLANKS_OAK_PAINTED, "minecraft:block/slab_planks_oak_painted", 154).withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .setBlockItem(ItemBlockSlabPainted::new)
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        SLAB_BRICK_SLATE = new BlockSlab(BRICK_SLATE, "minecraft:block/slab_brick_slate", 155).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_STONE = new BlockSlab(BRICK_STONE, "minecraft:block/slab_brick_stone", 156).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_GRANITE_POLISHED = new BlockSlab(GRANITE_CARVED, "minecraft:block/slab_granite_carved", 157).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_LIMESTONE_POLISHED = new BlockSlab(LIMESTONE_CARVED, "minecraft:block/slab_limestone_carved", 158).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BASALT_POLISHED = new BlockSlab(BASALT_CARVED, "minecraft:block/slab_basalt_carved", 159).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        STAIRS_PLANKS_OAK = new BlockStairsPaintable(PLANKS_OAK, "minecraft:block/stairs_planks_oak", 160).withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        STAIRS_COBBLE_STONE = new BlockStairs(COBBLE_STONE, "minecraft:block/stairs_cobble_stone", 161).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_STONE_POLISHED = new BlockStairs(BRICK_STONE_POLISHED, "minecraft:block/stairs_brick_stone_polished", 162).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_MARBLE = new BlockStairs(BRICK_MARBLE, "minecraft:block/stairs_brick_marble", 163).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_COBBLE_BASALT = new BlockStairs(COBBLE_BASALT, "minecraft:block/stairs_cobble_basalt", 164).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_COBBLE_LIMESTONE = new BlockStairs(COBBLE_LIMESTONE, "minecraft:block/stairs_cobble_limestone", 165).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_COBBLE_GRANITE = new BlockStairs(COBBLE_GRANITE, "minecraft:block/stairs_cobble_granite", 166).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_BASALT = new BlockStairs(BRICK_BASALT, "minecraft:block/stairs_brick_basalt", 167).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_LIMESTONE = new BlockStairs(BRICK_LIMESTONE, "minecraft:block/stairs_brick_limestone", 168).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_GRANITE = new BlockStairs(BRICK_GRANITE, "minecraft:block/stairs_brick_granite", 169).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_CLAY = new BlockStairs(BRICK_CLAY, "minecraft:block/stairs_brick_clay", 170).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_PLANKS_PAINTED = new BlockStairsPainted(PLANKS_OAK_PAINTED, "minecraft:block/stairs_planks_oak_painted", 171).withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .setBlockItem(ItemBlockStairsPainted::new)
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        STAIRS_BRICK_SLATE = new BlockStairs(BRICK_SLATE, "minecraft:block/stairs_brick_slate", 172).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_STONE = new BlockStairs(BRICK_STONE, "minecraft:block/stairs_brick_stone", 173).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_SANDSTONE = new BlockStairs(SANDSTONE, "minecraft:block/stairs_sandstone", 174).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_SANDSTONE = new BlockStairs(BRICK_SANDSTONE, "minecraft:block/stairs_brick_sandstone", 175).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_COBBLE_PERMAFROST = new BlockStairs(COBBLE_PERMAFROST, "minecraft:block/stairs_cobble_permafrost", 176).withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_PERMAFROST = new BlockStairs(BRICK_PERMAFROST, "minecraft:block/stairs_brick_permafrost", 177).withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        OBSIDIAN = new Block("obsidian", "minecraft:block/obsidian", 180, Material.stone).withSound(BlockSounds.STONE).withHardness(10F).withBlastResistance(2000F).withOverrideColor(MaterialColor.paintedBlack).withImmovableFlagSet()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PISTON_CRUSHING);
-
-        GLASS = new BlockGlass("glass", "minecraft:block/glass", 190, Material.glass).withSound(BlockSounds.GLASS).withHardness(0.3F).withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.EXTENDS_MOTION_SENSOR_RANGE);
-        GLASS_TINTED = new BlockGlassTinted("glass.tinted", "minecraft:block/glass_tinted", 191).withSound(BlockSounds.GLASS).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange().withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        GLASS_STEEL = new BlockTransparent("glass.steel", "minecraft:block/glass_steel", 192, Material.glass).withSound(BlockSounds.GLASS).withHardness(0.3F).withBlastResistance(2000F).withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.EXTENDS_MOTION_SENSOR_RANGE);
-
-        GRASS = new BlockGrass("grass", "minecraft:block/grass", 200, Material.grass).withSound(BlockSounds.GRASS).withHardness(0.6F)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.PASSIVE_MOBS_SPAWN, BlockTags.FIREFLIES_CAN_SPAWN, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.CAVE_GEN_REPLACES_SURFACE);
-        GRASS_RETRO = new BlockGrass("grass.retro", "minecraft:block/grass_retro", 201, Material.grass).withSound(BlockSounds.GRASS).withHardness(0.6F)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.PASSIVE_MOBS_SPAWN, BlockTags.FIREFLIES_CAN_SPAWN, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.CAVE_GEN_REPLACES_SURFACE);
-        GRASS_SCORCHED = new BlockGrassScorched("grass.scorched", "minecraft:block/grass_scorched", 202, Material.grass).withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.grassScorched)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.PASSIVE_MOBS_SPAWN, BlockTags.FIREFLIES_CAN_SPAWN, BlockTags.GROWS_CACTI, BlockTags.CAVE_GEN_REPLACES_SURFACE);
-
-        PATH_DIRT = new BlockPathDirt("path.dirt", "minecraft:block/path_dirt", 210).withSound(BlockSounds.GRAVEL).withHardness(0.5F).withLitInteriorSurface(true).withOverrideColor(MaterialColor.grassScorched)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL);
-
-        DIRT = new Block("dirt", "minecraft:block/dirt", 220, Material.dirt).withSound(BlockSounds.GRAVEL).withHardness(0.5F)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH);
-        DIRT_SCORCHED = new Block("dirt.scorched", "minecraft:block/dirt_scorched", 221, Material.dirt).withSound(BlockSounds.GRAVEL).withHardness(0.5F).withOverrideColor(MaterialColor.dirtScorched)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_CACTI, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH);
-        DIRT_SCORCHED_RICH = new Block("dirt.scorched.rich", "minecraft:block/dirt_scorched_rich", 222, Material.dirt).withSound(BlockSounds.GRAVEL).withHardness(0.6F).withOverrideColor(MaterialColor.dirtScorched)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_CACTI, BlockTags.CAVES_CUT_THROUGH);
-
-        MUD = new BlockMud("mud", "minecraft:block/mud", 225, Material.dirt, false).withSound(BlockSounds.GRAVEL).withHardness(0.6F).withOverrideColor(MaterialColor.mud)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_CACTI, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.GROWS_SUGAR_CANE);
-        MUD_BAKED = new BlockMud("mud.baked", "minecraft:block/mud_baked", 226, Material.stone, true).withSound(BlockSounds.STONE).withHardness(1.5F).withOverrideColor(MaterialColor.dirt)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_CACTI, BlockTags.GROWS_TREES, BlockTags.CAVES_CUT_THROUGH, BlockTags.GROWS_SUGAR_CANE);
-
-        SPONGE_DRY = new BlockSponge("sponge.dry", "minecraft:block/sponge_dry", 230, false).withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.paintedYellow)
-            .withTags(BlockTags.MINEABLE_BY_SHEARS);
-        SPONGE_WET = new BlockSponge("sponge.wet", "minecraft:block/sponge_wet", 231, true).withSound(BlockSounds.GRASS).withHardness(1.0F).withOverrideColor(MaterialColor.paintedYellow)
-            .withTags(BlockTags.MINEABLE_BY_SHEARS);
-        PUMICE_DRY = new BlockPumice("pumice.dry", "minecraft:block/pumice_dry", 232, false).withSound(BlockSounds.STONE).withHardness(0.6F).withOverrideColor(MaterialColor.fire)
-            .withTags(BlockTags.MINEABLE_BY_SHEARS);
-        PUMICE_WET = new BlockPumice("pumice.wet", "minecraft:block/pumice_wet", 233, true).withSound(BlockSounds.STONE).withHardness(1.0F).withLightEmission(0.625F).withOverrideColor(MaterialColor.fire)
-            .withTags(BlockTags.MINEABLE_BY_SHEARS);
-
-        MOSS_STONE = new BlockMoss("moss.stone", "minecraft:block/moss_stone", 240, STONE.id).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
-        MOSS_BASALT = new BlockMoss("moss.basalt", "minecraft:block/moss_basalt", 241, BASALT.id).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
-        MOSS_LIMESTONE = new BlockMoss("moss.limestone", "minecraft:block/moss_limestone", 242, LIMESTONE.id).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
-        MOSS_GRANITE = new BlockMoss("moss.granite", "minecraft:block/moss_granite", 243, GRANITE.id).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.GROWS_FLOWERS, BlockTags.GROWS_SUGAR_CANE);
-
-        SAND = new BlockSand("sand", "minecraft:block/sand", 250).withSound(BlockSounds.SAND).withHardness(0.5F)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.GROWS_SUGAR_CANE, BlockTags.GROWS_CACTI, BlockTags.CAVES_CUT_THROUGH, BlockTags.FIREFLIES_CAN_SPAWN);
-        GRAVEL = new BlockGravel("gravel", "minecraft:block/gravel", 251).withSound(BlockSounds.GRAVEL).withHardness(0.6F)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL);
-
-        BEDROCK = new BlockBedrock("bedrock", "minecraft:block/bedrock", 260, Material.stone).withSound(BlockSounds.STONE).withSetUnbreakable().withBlastResistance(6000000F).withImmovableFlagSet()
-            .withTags(BlockTags.PISTON_CRUSHING);
-        BONESHALE = new BlockBoneShale("boneshale", "minecraft:block/boneshale", 261, Material.stone).withSound(BlockSounds.STONE).withHardness(16F).withBlastResistance(6000000F).withImmovableFlagSet()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NETHER_MOBS_SPAWN);
-
-        FLUID_WATER_FLOWING = new BlockFluidFlowing("fluid.water.flowing", "minecraft:block/fluid_water_flowing", 270, Material.water).withHardness(100F).withLightBlock(3).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
-            .withTags(BlockTags.IS_WATER, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
-        FLUID_WATER_STILL = new BlockFluidStill("fluid.water.still", "minecraft:block/fluid_water_still", 271, Material.water).withHardness(100F).withLightBlock(3).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().setStatParent(() -> FLUID_WATER_FLOWING)
-            .withTags(BlockTags.IS_WATER, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
-        FLUID_LAVA_FLOWING = new BlockFluidFlowing("fluid.lava.flowing", "minecraft:block/fluid_lava_flowing", 272, Material.lava).withHardness(0.0F).withLightEmission(1.0F).withLightBlock(255).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
-            .withTags(BlockTags.IS_LAVA, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
-        FLUID_LAVA_STILL = new BlockFluidStill("fluid.lava.still", "minecraft:block/fluid_lava_still", 273, Material.lava).withHardness(100F).withLightEmission(1.0F).withLightBlock(255).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().setStatParent(() -> FLUID_LAVA_FLOWING)
-            .withTags(BlockTags.IS_LAVA, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
-
-        LOG_OAK = new BlockLog("log.oak", "minecraft:block/log_oak", 280).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        LOG_PINE = new BlockLog("log.pine", "minecraft:block/log_pine", 281).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        LOG_BIRCH = new BlockLog("log.birch", "minecraft:block/log_birch", 282).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        LOG_CHERRY = new BlockLog("log.cherry", "minecraft:block/log_cherry", 283).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        LOG_EUCALYPTUS = new BlockLog("log.eucalyptus", "minecraft:block/log_eucalyptus", 284).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        LOG_OAK_MOSSY = new BlockLog("log.oak.mossy", "minecraft:block/log_oak_mossy", 285).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        LOG_THORN = new BlockLog("log.thorn", "minecraft:block/log_thorn", 286).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        LOG_PALM = new BlockLog("log.palm", "minecraft:block/log_palm", 287).withSound(BlockSounds.WOOD).withHardness(2.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-
-        LEAVES_OAK = new BlockLeavesOak("leaves.oak", "minecraft:block/leaves_oak", 290).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_OAK_RETRO = new BlockLeavesRetro("leaves.oak.retro", "minecraft:block/leaves_oak_retro", 291).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_PINE = new BlockLeavesPine("leaves.pine", "minecraft:block/leaves_pine", 292).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.pineLeaves)
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_BIRCH = new BlockLeavesBirch("leaves.birch", "minecraft:block/leaves_birch", 293).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.birchLeaves)
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_CHERRY = new BlockLeavesCherry("leaves.cherry", "minecraft:block/leaves_cherry", 294).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.cherryLeaves)
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_EUCALYPTUS = new BlockLeavesEucalyptus("leaves.eucalyptus", "minecraft:block/leaves_eucalyptus", 295).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_SHRUB = new BlockLeavesShrub("leaves.shrub", "minecraft:block/leaves_shrub", 296).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_CHERRY_FLOWERING = new BlockLeavesCherryFlowering("leaves.cherry.flowering", "minecraft:block/leaves_cherry_flowering", 297).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.cherryLeaves)
-            .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_CACAO = new BlockLeavesCacao("leaves.cacao", "minecraft:block/leaves_cacao", 298).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_THORN = new BlockLeavesThorn("leaves.thorn", "minecraft:block/leaves_thorn", 299).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.thornLeaves)
-            .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-        LEAVES_PALM = new BlockLeavesPalm("leaves.palm", "minecraft:block/leaves_palm", 300).withSound(BlockSounds.GRASS).withHardness(0.2F).withLightBlock(1).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.palmLeaves)
-            .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_SHEARS);
-
-
-        SAPLING_OAK = new BlockSaplingOak("sapling.oak", "minecraft:block/sapling_oak", 310).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_OAK_RETRO = new BlockSaplingRetro("sapling.oak.retro", "minecraft:block/sapling_oak_retro", 311).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_PINE = new BlockSaplingPine("sapling.pine", "minecraft:block/sapling_pine", 312).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_BIRCH = new BlockSaplingBirch("sapling.birch", "minecraft:block/sapling_birch", 313).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_CHERRY = new BlockSaplingCherry("sapling.cherry", "minecraft:block/sapling_cherry", 314).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_EUCALYPTUS = new BlockSaplingEucalyptus("sapling.eucalyptus", "minecraft:block/sapling_eucalyptus", 315).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_SHRUB = new BlockSaplingShrub("sapling.shrub", "minecraft:block/sapling_shrub", 316).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_CACAO = new BlockSaplingCacao("sapling.cacao", "minecraft:block/sapling_cacao", 317).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_THORN = new BlockSaplingThorn("sapling.thorn", "minecraft:block/sapling_thorn", 318).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-        SAPLING_PALM = new BlockSaplingPalm("sapling.palm", "minecraft:block/sapling_palm", 319).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
-
-        TALLGRASS = new BlockTallGrass("tallgrass", "minecraft:block/tallgrass", 320).setKilledByWeather().withSound(BlockSounds.GRASS).withHardness(0.0F)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.SHEEPS_FAVOURITE_BLOCK);
-        TALLGRASS_FERN = new BlockTallGrass("tallgrass.fern", "minecraft:block/tallgrass_fern", 321).setKilledByWeather().withSound(BlockSounds.GRASS).withHardness(0.0F)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
-        DEADBUSH = new BlockDeadBush("deadbush", "minecraft:block/deadbush", 322).withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.wood)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.PLANTABLE_IN_JAR);
-        SPINIFEX = new BlockSpinifex("spinifex", "minecraft:block/spinifex", 323).withSound(BlockSounds.GRASS).withHardness(0.0F)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH);
-        ALGAE = new BlockAlgae("algae", "minecraft:block/algae", 324, Material.plant).withSound(BlockSounds.GRASS).withHardness(0.0F).withLitInteriorSurface(true)
-            .setBlockItem((b) -> new ItemBlockAlgae(b))
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH);
-
-        FLOWER_YELLOW = new BlockFlowerStackable("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 BlockFlowerStackable("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 BlockFlowerStackable("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 BlockFlowerStackable("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 BlockFlowerStackable("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 BlockFlowerStackable("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 BlockMushroom("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);
-        MUSHROOM_RED = new BlockMushroom("mushroom.red", "minecraft:block/mushroom_red", 341).withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedRed)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.PIGS_FAVOURITE_BLOCK);
-
-
-        ORE_COAL_STONE = new BlockOreCoal("ore.coal.stone", "minecraft:block/ore_coal_stone", 350, STONE.id, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_COAL_BASALT = new BlockOreCoal("ore.coal.basalt", "minecraft:block/ore_coal_basalt", 351, BASALT.id, Material.basalt).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_COAL_LIMESTONE = new BlockOreCoal("ore.coal.limestone", "minecraft:block/ore_coal_limestone", 352, LIMESTONE.id, Material.limestone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_COAL_GRANITE = new BlockOreCoal("ore.coal.granite", "minecraft:block/ore_coal_granite", 353, GRANITE.id, Material.granite).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_COAL_PERMAFROST = new BlockOreCoal("ore.coal.permafrost", "minecraft:block/ore_coal_permafrost", 354, PERMAFROST.id, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        ORE_IRON_STONE = new BlockOreIron("ore.iron.stone", "minecraft:block/ore_iron_stone", 360, STONE.id, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_IRON_BASALT = new BlockOreIron("ore.iron.basalt", "minecraft:block/ore_iron_basalt", 361, BASALT.id, Material.basalt).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_IRON_LIMESTONE = new BlockOreIron("ore.iron.limestone", "minecraft:block/ore_iron_limestone", 362, LIMESTONE.id, Material.limestone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_IRON_GRANITE = new BlockOreIron("ore.iron.granite", "minecraft:block/ore_iron_granite", 363, GRANITE.id, Material.granite).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_IRON_PERMAFROST = new BlockOreIron("ore.iron.permafrost", "minecraft:block/ore_iron_permafrost", 364, PERMAFROST.id, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        ORE_GOLD_STONE = new BlockOreGold("ore.gold.stone", "minecraft:block/ore_gold_stone", 370, STONE.id, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_GOLD_BASALT = new BlockOreGold("ore.gold.basalt", "minecraft:block/ore_gold_basalt", 371, BASALT.id, Material.basalt).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_GOLD_LIMESTONE = new BlockOreGold("ore.gold.limestone", "minecraft:block/ore_gold_limestone", 372, LIMESTONE.id, Material.limestone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_GOLD_GRANITE = new BlockOreGold("ore.gold.granite", "minecraft:block/ore_gold_granite", 373, GRANITE.id, Material.granite).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_GOLD_PERMAFROST = new BlockOreGold("ore.gold.permafrost", "minecraft:block/ore_gold_permafrost",374, PERMAFROST.id, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        ORE_LAPIS_STONE = new BlockOreLapis("ore.lapis.stone", "minecraft:block/ore_lapis_stone", 380, STONE.id, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_LAPIS_BASALT = new BlockOreLapis("ore.lapis.basalt", "minecraft:block/ore_lapis_basalt", 381, BASALT.id, Material.basalt).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_LAPIS_LIMESTONE = new BlockOreLapis("ore.lapis.limestone", "minecraft:block/ore_lapis_limestone", 382, LIMESTONE.id, Material.limestone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_LAPIS_GRANITE = new BlockOreLapis("ore.lapis.granite", "minecraft:block/ore_lapis_granite", 383, GRANITE.id, Material.granite).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_LAPIS_PERMAFROST = new BlockOreLapis("ore.lapis.permafrost", "minecraft:block/ore_lapis_permafrost", 384, PERMAFROST.id, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        ORE_REDSTONE_STONE = new BlockOreRedstone("ore.redstone.stone", "minecraft:block/ore_redstone_stone", 390, STONE.id, Material.stone, false, () -> ORE_REDSTONE_STONE, () -> ORE_REDSTONE_GLOWING_STONE).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_BASALT = new BlockOreRedstone("ore.redstone.basalt", "minecraft:block/ore_redstone_basalt", 391, BASALT.id, Material.basalt, false, () -> ORE_REDSTONE_BASALT, () -> ORE_REDSTONE_GLOWING_BASALT).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_LIMESTONE = new BlockOreRedstone("ore.redstone.limestone", "minecraft:block/ore_redstone_limestone", 392, LIMESTONE.id, Material.limestone, false, () -> ORE_REDSTONE_LIMESTONE, () -> ORE_REDSTONE_GLOWING_LIMESTONE).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_GRANITE = new BlockOreRedstone("ore.redstone.granite", "minecraft:block/ore_redstone_granite", 393, GRANITE.id, Material.granite, false, () -> ORE_REDSTONE_GRANITE, () -> ORE_REDSTONE_GLOWING_GRANITE).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_PERMAFROST = new BlockOreRedstone("ore.redstone.permafrost", "minecraft:block/ore_redstone_permafrost", 394, PERMAFROST.id, Material.permafrost, false, () -> ORE_REDSTONE_PERMAFROST, () -> ORE_REDSTONE_GLOWING_PERMAFROST).withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(2F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        ORE_REDSTONE_GLOWING_STONE = new BlockOreRedstone("ore.redstone.glowing.stone", "minecraft:block/ore_redstone_glowing_stone", 400, -1, Material.stone, true, () -> ORE_REDSTONE_STONE, () -> ORE_REDSTONE_GLOWING_STONE).withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_STONE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_GLOWING_BASALT = new BlockOreRedstone("ore.redstone.glowing.basalt", "minecraft:block/ore_redstone_glowing_basalt", 401, -1, Material.basalt, true, () -> ORE_REDSTONE_BASALT, () -> ORE_REDSTONE_GLOWING_BASALT).withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_BASALT)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_GLOWING_LIMESTONE = new BlockOreRedstone("ore.redstone.glowing.limestone", "minecraft:block/ore_redstone_glowing_limestone", 402, -1, Material.limestone, true, () -> ORE_REDSTONE_LIMESTONE, () -> ORE_REDSTONE_GLOWING_LIMESTONE).withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_LIMESTONE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_GLOWING_GRANITE = new BlockOreRedstone("ore.redstone.glowing.granite", "minecraft:block/ore_redstone_glowing_granite", 403, -1, Material.granite, true, () -> ORE_REDSTONE_GRANITE, () -> ORE_REDSTONE_GLOWING_GRANITE).withSound(BlockSounds.STONE).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_GRANITE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_REDSTONE_GLOWING_PERMAFROST = new BlockOreRedstone("ore.redstone.glowing.permafrost", "minecraft:block/ore_redstone_glowing_permafrost", 404, -1, Material.permafrost, true, () -> ORE_REDSTONE_PERMAFROST, () -> ORE_REDSTONE_GLOWING_PERMAFROST).withSound(BlockSounds.PERMAFROST).withLightEmission(0.2F).withHardness(3F).withBlastResistance(5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> ORE_REDSTONE_PERMAFROST)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        ORE_DIAMOND_STONE = new BlockOreDiamond("ore.diamond.stone", "minecraft:block/ore_diamond_stone", 410, STONE.id, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_DIAMOND_BASALT = new BlockOreDiamond("ore.diamond.basalt", "minecraft:block/ore_diamond_basalt", 411, BASALT.id, Material.basalt).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_DIAMOND_LIMESTONE = new BlockOreDiamond("ore.diamond.limestone", "minecraft:block/ore_diamond_limestone", 412, LIMESTONE.id, Material.limestone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_DIAMOND_GRANITE = new BlockOreDiamond("ore.diamond.granite", "minecraft:block/ore_diamond_granite", 413, GRANITE.id, Material.granite).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ORE_DIAMOND_PERMAFROST = new BlockOreDiamond("ore.diamond.permafrost", "minecraft:block/ore_diamond_permafrost", 414, PERMAFROST.id, Material.permafrost).withSound(BlockSounds.PERMAFROST).withHardness(3F).withBlastResistance(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        ORE_NETHERCOAL_NETHERRACK = new BlockOreNetherCoal("ore.nethercoal.netherrack", "minecraft:block/ore_nethercoal_netherrack", 420).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F).withLightEmission(0.625F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NETHER_MOBS_SPAWN);
-
-        BLOCK_COAL = new Block("block.coal", "minecraft:block/block_coal", 430, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.coal)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_IRON = new Block("block.iron", "minecraft:block/block_iron", 431, Material.metal).withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.iron)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_GOLD = new Block("block.gold", "minecraft:block/block_gold", 432, Material.metal).withSound(BlockSounds.METAL).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.gold)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_LAPIS = new Block("block.lapis", "minecraft:block/block_lapis", 433, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F).withOverrideColor(MaterialColor.lapis)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_REDSTONE = new BlockRedstone("block.redstone", "minecraft:block/block_redstone", 434, Material.stone).withSound(BlockSounds.STONE).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.redstone)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_DIAMOND = new Block("block.diamond", "minecraft:block/block_diamond", 435, Material.stone).withSound(BlockSounds.STONE).withHardness(5F).withBlastResistance(10F).withOverrideColor(MaterialColor.diamond)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_NETHER_COAL = new Block("block.nethercoal", "minecraft:block/block_nethercoal", 436, Material.netherrack).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_STEEL = new Block("block.steel", "minecraft:block/block_steel", 437, Material.steel).withSound(BlockSounds.METAL).withHardness(5F).withBlastResistance(2000F).withOverrideColor(MaterialColor.steel)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_QUARTZ = new Block("block.quartz", "minecraft:block/block_quartz", 438, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.quartz)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_OLIVINE = new Block("block.olivine", "minecraft:block/block_olivine", 439, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.olivine)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BLOCK_CHARCOAL = new Block("block.charcoal", "minecraft:block/block_charcoal", 440, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(10F).withOverrideColor(MaterialColor.coal)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        WIRE_REDSTONE = new BlockWireRedstone("wire.redstone", "minecraft:block/wire_redstone", 450).withSound(BlockSounds.STONE).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> Items.DUST_REDSTONE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
-
-        TORCH_REDSTONE_IDLE = new BlockTorchRedstone("torch.redstone.idle", "minecraft:block/torch_redstone_idle", 460, false).withSound(BlockSounds.WOOD).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> TORCH_REDSTONE_ACTIVE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
-        TORCH_REDSTONE_ACTIVE = new BlockTorchRedstone("torch.redstone.active", "minecraft:block/torch_redstone_active", 461, true).withSound(BlockSounds.WOOD).withHardness(0.0F).withLightEmission(0.5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PREVENT_MOB_SPAWNS);
-
-        BUTTON_STONE = new BlockButton("button.stone", "minecraft:block/button_stone", 470).withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-
-        LEVER_COBBLE_STONE = new BlockLever("lever.cobble.stone", "minecraft:block/lever_cobble_stone", 480).withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-
-        PRESSURE_PLATE_STONE = new BlockPressurePlate("pressureplate.stone", "minecraft:block/pressure_plate_stone", 490, Mob.class, Material.stone).withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-        PRESSURE_PLATE_PLANKS_OAK = new BlockPressurePlate("pressureplate.planks.oak", "minecraft:block/pressure_plate_planks_oak", 491, Entity.class, Material.wood).withSound(BlockSounds.WOOD).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.PREVENT_MOB_SPAWNS);
-        PRESSURE_PLATE_COBBLE_STONE = new BlockPressurePlate("pressureplate.cobble.stone", "minecraft:block/pressure_plate_cobble_stone", 492, Player.class, Material.stone).withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-
-        MOTION_SENSOR_IDLE = new BlockMotionSensor("motionsensor.idle", "minecraft:block/motion_sensor_idle", 500, false).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.stone)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        MOTION_SENSOR_ACTIVE = new BlockMotionSensor("motionsensor.active", "minecraft:block/motion_sensor_active", 501, true).withSound(BlockSounds.STONE).withLightEmission(0.3F).withHardness(2.0F).withBlastResistance(10F).withOverrideColor(MaterialColor.stone).setStatParent(() -> MOTION_SENSOR_IDLE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        REPEATER_IDLE = new BlockRepeater("repeater.idle", "minecraft:block/repeater_idle", 510, false).withSound(BlockSounds.STONE).withHardness(0.0F).withDisabledStats().withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> Items.REPEATER)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
-        REPEATER_ACTIVE = new BlockRepeater("repeater.active", "minecraft:block/repeater_active", 511, true).withSound(BlockSounds.STONE).withHardness(0.0F).withLightEmission(0.625F).withDisabledStats().withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.redstone).setStatParent(() -> REPEATER_IDLE)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS);
-
-        PISTON_BASE = new BlockPistonBase("piston.base", "minecraft:block/piston_base", 520, 12).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        PISTON_BASE_STICKY = new BlockPistonBaseSticky("piston.base.sticky", "minecraft:block/piston_base_sticky", 521, 12).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        PISTON_HEAD = new BlockPistonHead("piston.head", "minecraft:block/piston_head", 522, 4/16d).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().withImmovableFlagSet()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        PISTON_MOVING = new BlockPistonMoving("piston.moving", "minecraft:block/piston_moving", 523).withSound(BlockSounds.STONE).withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU);
-        PISTON_BASE_STEEL = new BlockPistonBaseSteel("piston.base.steel", "minecraft:block/piston_base_steel", 524, 24).withSound(BlockSounds.METAL).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        PISTON_HEAD_STEEL = new BlockPistonHead("piston.head.steel", "minecraft:block/piston_head_steel", 525, 6/16d).withSound(BlockSounds.METAL).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        NOTEBLOCK = new BlockNote("noteblock", "minecraft:block/noteblock", 530).withSound(BlockSounds.WOOD).withHardness(0.8F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-
-        RAIL = new BlockRail("rail", "minecraft:block/rail", 540, false).withSound(BlockSounds.METAL).withHardness(0.7F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-        RAIL_POWERED = new BlockRail("rail.powered", "minecraft:block/rail_powered", 541, true).withSound(BlockSounds.METAL).withHardness(0.7F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-        RAIL_DETECTOR = new BlockRailDetector("rail.detector", "minecraft:block/rail_detector", 542).withSound(BlockSounds.METAL).withHardness(0.7F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-
-        SPIKES = new BlockSpikes("spikes", "minecraft:block/spikes", 550, Material.metal).withSound(BlockSounds.METAL).withLightBlock(3).withHardness(2F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        DISPENSER_COBBLE_STONE = new BlockDispenser("dispenser.cobble.stone", "minecraft:block/dispenser_cobble_stone", 560).withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        ACTIVATOR_COBBLE_NETHERRACK = new BlockActivator("activator.cobble.netherrack", "minecraft:block/activator_cobble_netherrack", 561).withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        TRAPDOOR_PLANKS_OAK = new BlockTrapDoor("trapdoor.planks.oak", "minecraft:block/trapdoor_planks_oak", 570, Material.wood).withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        TRAPDOOR_IRON = new BlockTrapDoor("trapdoor.iron", "minecraft:block/trapdoor_iron", 571, Material.metal).withSound(BlockSounds.METAL).withHardness(5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.iron)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        TRAPDOOR_GLASS = new BlockTrapDoor("trapdoor.glass", "minecraft:block/trapdoor_glass", 572, Material.glass).withSound(BlockSounds.GLASS).withHardness(0.3F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        TRAPDOOR_PLANKS_PAINTED = new BlockTrapDoorPainted("trapdoor.planks.oak.painted", "minecraft:block/trapdoor_planks_oak_painted", 573, Material.wood).withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockPainted(b, true))
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        TRAPDOOR_STEEL = new BlockTrapDoor("trapdoor.steel", "minecraft:block/trapdoor_steel", 574, Material.metal).withSound(BlockSounds.METAL).withOverrideColor(MaterialColor.steel).withHardness(5F).withBlastResistance(2000F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        TNT = new BlockTNT("tnt", "minecraft:block/tnt", 580).withSound(BlockSounds.GRASS).withHardness(0.0F);
-
-        DOOR_PLANKS_OAK_BOTTOM = new BlockDoor("door.planks.oak.bottom", "minecraft:block/door_planks_oak_bottom", 590, Material.wood, false, false, () -> Items.DOOR_OAK).withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.DOOR_OAK)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        DOOR_PLANKS_OAK_TOP = new BlockDoor("door.planks.oak.top", "minecraft:block/doors_planks_oak_top", 591, Material.wood, true, false, () -> Items.DOOR_OAK).withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> DOOR_PLANKS_OAK_BOTTOM)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        DOOR_IRON_BOTTOM = new BlockDoor("door.iron.bottom", "minecraft:block/door_iron_bottom", 592, Material.metal, false, true, () -> Items.DOOR_IRON).withSound(BlockSounds.METAL).withHardness(5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.iron).setStatParent(() -> Items.DOOR_IRON)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        DOOR_IRON_TOP = new BlockDoor("door.iron.top", "minecraft:block/door_iron_top", 593, Material.metal, true, true, () -> Items.DOOR_IRON).withSound(BlockSounds.METAL).withHardness(5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.iron).setStatParent(() -> DOOR_IRON_BOTTOM)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        DOOR_PLANKS_PAINTED_BOTTOM = new BlockDoorPainted("door.planks.oak.painted.bottom", "minecraft:block/door_planks_oak_painted_bottom", 594, Material.wood, false).withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.DOOR_OAK_PAINTED)
-            .setBlockItem((b) -> new ItemBlockPainted(b, true))
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        DOOR_PLANKS_PAINTED_TOP = new BlockDoorPainted("door.planks.oak.painted.top", "minecraft:block/door_planks_oak_painted_top", 595, Material.wood, true).withSound(BlockSounds.WOOD).withHardness(3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> DOOR_PLANKS_PAINTED_BOTTOM)
-            .setBlockItem((b) -> new ItemBlockPainted(b, true))
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        DOOR_GLASS_BOTTOM = new BlockDoor("door.glass.bottom", "minecraft:block/door_glass_bottom", 596, Material.glass, false, false, () -> Items.DOOR_GLASS).withSound(BlockSounds.GLASS).withHardness(0.3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.DOOR_GLASS)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        DOOR_GLASS_TOP = new BlockDoor("door.glass.top", "minecraft:block/door_glass_top", 597, Material.glass, true, false, () -> Items.DOOR_GLASS).withSound(BlockSounds.GLASS).withHardness(0.3F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> DOOR_GLASS_BOTTOM)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        DOOR_STEEL_BOTTOM = new BlockDoor("door.steel.bottom", "minecraft:block/door_steel_bottom", 598, Material.metal, false, true, () -> Items.DOOR_STEEL).withSound(BlockSounds.METAL).withHardness(5F).withOverrideColor(MaterialColor.steel).withBlastResistance(2000F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel).setStatParent(() -> Items.DOOR_STEEL)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        DOOR_STEEL_TOP = new BlockDoor("door.steel.top", "minecraft:block/door_steel_top", 599, Material.metal, true, true, () -> Items.DOOR_STEEL).withSound(BlockSounds.METAL).withHardness(5F).withOverrideColor(MaterialColor.steel).withBlastResistance(2000F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel).setStatParent(() -> DOOR_STEEL_BOTTOM)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        MESH = new BlockMesh("mesh", "minecraft:block/mesh", 600).withSound(BlockSounds.METAL).withHardness(1.5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CAN_HANG_OFF);
-        MESH_GOLD = new BlockMeshGold("mesh.gold", "minecraft:block/mesh_gold", 601).withSound(BlockSounds.METAL).withHardness(1F).withOverrideColor(MaterialColor.gold)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CAN_HANG_OFF);
-
-        BED = new BlockBed("bed", "minecraft:block/bed", 610).withSound(BlockSounds.WOOD).withHardness(0.2F).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true).setStatParent(() -> Items.BED)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        SEAT = new BlockSeat("seat", "minecraft:block/seat", 611).withSound(BlockSounds.WOOD).withHardness(0.2F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.SEAT)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-
-        COBWEB = new BlockCobweb("cobweb", "minecraft:block/cobweb", 620, Material.web).withSound(BlockSounds.CLOTH).withLightBlock(1).withHardness(4F)
-            .withTags(BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_SHEARS, BlockTags.MINEABLE_BY_SWORD);
-
-        FIRE = new BlockFire("fire", "minecraft:block/fire", 630).withSound(BlockSounds.FIRE).withHardness(0.0F).withLightEmission(1.0F).withDisabledStats().withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU);
-        BRAZIER_INACTIVE = new BlockBrazier("brazier.inactive", "minecraft:block/brazier_inactive", 631, false).withSound(BlockSounds.METAL).withHardness(1.5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        BRAZIER_ACTIVE = new BlockBrazier("brazier.active", "minecraft:block/brazier_active", 632, true).withSound(BlockSounds.FIRE).withHardness(1.5F).withLightEmission(1.0F).setStatParent(() -> BRAZIER_INACTIVE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        MOBSPAWNER = new BlockMobSpawner("mobspawner", "minecraft:block/mobspawner", 640).withSound(BlockSounds.METAL).withHardness(5F).withImmovableFlagSet().withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        MOBSPAWNER_DEACTIVATED = new BlockMobSpawnerDeactivated("mobspawner.deactivated", "minecraft:block/mobspawner_deactivated", 641, Material.stone).withSound(BlockSounds.METAL).withHardness(5F).withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        WORKBENCH = new BlockWorkbench("workbench", "minecraft:block/workbench", 650).withSound(BlockSounds.WOOD).withHardness(2.5F)
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-
-        FURNACE_STONE_IDLE = new BlockFurnace("furnace.stone.idle", "minecraft:block/furnace_stone_idle", 660, false).withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        FURNACE_STONE_ACTIVE = new BlockFurnace("furnace.stone.active", "minecraft:block/furnace_stone_active", 661, true).withSound(BlockSounds.STONE).withHardness(3.5F).withLightEmission(0.875F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> FURNACE_STONE_IDLE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-        FURNACE_BLAST_IDLE = new BlockFurnaceBlast("furnace.blast.idle", "minecraft:block/furnace_blast_idle", 662, false).withSound(BlockSounds.METAL).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        FURNACE_BLAST_ACTIVE = new BlockFurnaceBlast("furnace.blast.active", "minecraft:block/furnace_blast_active", 663, true).withSound(BlockSounds.METAL).withHardness(3.5F).withLightEmission(0.875F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.steel).setStatParent(() -> FURNACE_BLAST_IDLE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        TROMMEL_IDLE = new BlockTrommel("trommel.idle", "minecraft:block/trommel_idle", 670, Material.stone, false).withSound(BlockSounds.STONE).withHardness(3.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        TROMMEL_ACTIVE = new BlockTrommel("trommel.active", "minecraft:block/trommel_active", 671, Material.stone, true).withSound(BlockSounds.STONE).withHardness(3.5F).withLightEmission(0.875F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> TROMMEL_IDLE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        CHEST_LEGACY = new BlockChestLegacy("chest.legacy", "minecraft:block/chest_legacy", 680).withSound(BlockSounds.WOOD).withHardness(2.5f).withBlastResistance(5.0f).setStatParent(() -> CHEST_PLANKS_OAK)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        CHEST_LEGACY_PAINTED = new BlockChestLegacy("chest.legacy.painted", "minecraft:block/chest_legacy_painted", 681).withSound(BlockSounds.WOOD).withHardness(2.5f).withBlastResistance(5.0f).setStatParent(() -> CHEST_PLANKS_OAK_PAINTED)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        CHEST_PLANKS_OAK = new BlockChest("chest.planks.oak", "minecraft:block/chest_planks_oak", 682, Material.wood).withSound(BlockSounds.WOOD).withHardness(2.5F).withBlastResistance(5.0f).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-        CHEST_PLANKS_OAK_PAINTED = new BlockChestPainted("chest.planks.oak.painted", "minecraft:block/chest_planks_oak_painted", 683, Material.wood).withSound(BlockSounds.WOOD).withHardness(2.5F).withBlastResistance(5.0f).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockPainted(b, true))
-            .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE);
-
-        CROPS_WHEAT = new BlockCropsWheat("crops.wheat", "minecraft:block/crops_wheat", 690).withSound(BlockSounds.GRASS).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.SEEDS_WHEAT)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
-        CROPS_PUMPKIN = new BlockCropsPumpkin("crops.pumpkin", "minecraft:block/crops_pumpkin", 691).withSound(BlockSounds.WOOD).withHardness(0.0f).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true).setStatParent(() -> Items.SEEDS_PUMPKIN)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.OVERRIDE_STEPSOUND);
-
-        FARMLAND_DIRT = new BlockFarmland("farmland.dirt", "minecraft:block/farmland_dirt", 700).withSound(BlockSounds.GRAVEL).withHardness(0.6F).withLitInteriorSurface(true).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL);
-
-        SIGN_POST_PLANKS_OAK = new BlockSign("sign.post.planks.oak", "minecraft:block/sign_post_planks_oak", 710, true).withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.SIGN)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-        SIGN_WALL_PLANKS_OAK = new BlockSign("sign.wall.planks.oak", "minecraft:block/sign_wall_planks_oak", 711, false).withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> SIGN_POST_PLANKS_OAK)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-
-        FLAG = new BlockFlag("flag", "minecraft:block/flag", 712, Material.wood).withSound(BlockSounds.WOOD).withHardness(1.0F).setStatParent(() -> Items.FLAG)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_AXE);
-
-        LAYER_SNOW = new BlockLayerSnow("layer.snow", "minecraft:block/layer_snow", 720, Material.topSnow).setFullBlockID(() -> Blocks.BLOCK_SNOW.id).withSound(BlockSounds.CLOTH).withHardness(0.1F).withLitInteriorSurface(true)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.MINEABLE_BY_SHOVEL, BlockTags.OVERRIDE_STEPSOUND);
-        LAYER_LEAVES_OAK = new BlockLayerLeaves("layer.leaves.oak", "minecraft:block/layer_leaves_oak", 721, Material.leaves).setFullBlockID(() -> LEAVES_OAK.id).withSound(BlockSounds.GRASS).withLitInteriorSurface(true)
-            .setBlockItem(ItemBlockLayerLeaves::new)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.MINEABLE_BY_SHEARS, BlockTags.MINEABLE_BY_SWORD, BlockTags.MINEABLE_BY_AXE, BlockTags.MINEABLE_BY_HOE);
-        LAYER_SLATE = new BlockLayerSlate("layer.slate", "minecraft:block/layer_slate", 722, Material.slate).setFullBlockID(() -> SLATE.id).withSound(BlockSounds.STONE).withHardness(1.5F).withBlastResistance(10F).withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        ICE = new BlockIce("ice", "minecraft:block/ice", 730).withSound(BlockSounds.GLASS).withHardness(0.5F).withLightBlock(3)
-            .withTags(BlockTags.SKATEABLE, BlockTags.MINEABLE_BY_PICKAXE);
-        PERMAICE = new BlockSlippery("ice.perma", "minecraft:block/permaice", 731, Material.ice).withSound(BlockSounds.GLASS).withHardness(1.5F).withBlastResistance(10F)
-            .withTags(BlockTags.SKATEABLE, BlockTags.MINEABLE_BY_PICKAXE);
-
-        BLOCK_SNOW = new BlockSnow("block.snow", "minecraft:block/block_snow", 740).withSound(BlockSounds.CLOTH).withHardness(0.2F)
-            .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_SHOVEL, BlockTags.FIREFLIES_CAN_SPAWN);
-
-        CACTUS = new BlockCactus("cactus", "minecraft:block/cactus", 750).withSound(BlockSounds.GRASS).withHardness(0.4F)
-            .withTags(BlockTags.GROWS_CACTI, BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_SHEARS, BlockTags.MINEABLE_BY_HOE);
-
-        BLOCK_CLAY = new BlockClay("block.clay", "minecraft:block/block_clay", 760).withSound(BlockSounds.GRAVEL).withHardness(0.6F)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL);
-
-        SUGARCANE = new BlockSugarcane("sugarcane", "minecraft:block/sugarcane", 770).withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedLime).setStatParent(() -> Items.SUGARCANE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
-        BLOCK_SUGARCANE = new BlockAxisAligned("block.sugarcane", "minecraft:block/block_sugarcane", 771, Material.moss).withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.paintedLime)
-            .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.FENCES_CONNECT);
-        BLOCK_SUGARCANE_BAKED = new BlockAxisAligned("block.sugarcane.baked", "minecraft:block/block_sugarcane_baked", 772, Material.moss).withSound(BlockSounds.GRASS).withHardness(0.6F).withOverrideColor(MaterialColor.wood)
-            .withTags(BlockTags.MINEABLE_BY_AXE, BlockTags.FENCES_CONNECT);
-
-        JUKEBOX = new BlockJukebox("jukebox", "minecraft:block/jukebox", 780).withSound(BlockSounds.WOOD).withHardness(2.0F).withBlastResistance(10F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-
-        PUMPKIN = new BlockPumpkin("pumpkin", "minecraft:block/pumpkin", 790, true).withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        PUMPKIN_CARVED_IDLE = new BlockPumpkin("pumpkin.carved.idle", "minecraft:block/pumpkin_carved_idle", 791, false).withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        PUMPKIN_CARVED_ACTIVE = new BlockPumpkin("pumpkin.carved.active", "minecraft:block/pumpkin_carved_active", 792, false).withSound(BlockSounds.WOOD).withHardness(1.0F).withLightEmission(1.0F).withDisabledNeighborNotifyOnMetadataChange()
-            .withTags(BlockTags.MINEABLE_BY_AXE);
-        PUMPKIN_REDSTONE = new BlockPumpkinRedstone("pumpkin.redstone", "minecraft:block/pumpkin_redstone", 793).withSound(BlockSounds.WOOD).withHardness(1.0F).withDisabledNeighborNotifyOnMetadataChange();
-
-
-        COBBLE_NETHERRACK = new BlockCobble("cobble.netherrack", "minecraft:block/cobble_netherrack", 800, Material.netherrack, null).withSound(BlockSounds.STONE).withHardness(0.4F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.INFINITE_BURN, BlockTags.CAVES_CUT_THROUGH, BlockTags.NETHER_MOBS_SPAWN);
-        COBBLE_NETHERRACK_IGNEOUS = new BlockNetherrackIgneous("cobble.netherrack.igneous", "minecraft:block/cobble_netherrack_igneous", 801).withSound(BlockSounds.STONE).withHardness(1.25F).withBlastResistance(7F).withLightEmission(10)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        COBBLE_NETHERRACK_MOSSY = new BlockCobble("cobble.netherrack.mossy", "minecraft:block/cobble_netherrack_mossy", 802, Material.netherrack, null).withSound(BlockSounds.STONE).withHardness(0.4F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.INFINITE_BURN);
-        NETHERRACK = new BlockStone("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);
-        SLAB_NETHERRACK_POLISHED = new BlockSlab(NETHERRACK_CARVED, "minecraft:block/slab_netherrack_polished", 805).withSound(BlockSounds.STONE).withHardness(0.4F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_COBBLE_NETHERRACK = new BlockSlab(COBBLE_NETHERRACK, "minecraft:block/slab_cobble_netherrack", 806).withSound(BlockSounds.STONE).withHardness(0.4F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_NETHERRACK = new BlockSlab(BRICK_NETHERRACK, "minecraft:block/slab_brick_netherrack", 807).withSound(BlockSounds.STONE).withHardness(0.4F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_COBBLE_NETHERRACK = new BlockStairs(COBBLE_NETHERRACK, "minecraft:block/stairs_cobble_netherrack", 808).withSound(BlockSounds.STONE).withHardness(0.4F).withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        STAIRS_BRICK_NETHERRACK = new BlockStairs(BRICK_NETHERRACK, "minecraft:block/stairs_brick_netherrack", 809).withSound(BlockSounds.STONE).withHardness(0.4F).withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        SOULSAND = new BlockSoulSand("soulsand", "minecraft:block/soulsand", 810).withSound(BlockSounds.SAND).withHardness(0.5F).withOverrideColor(MaterialColor.paintedBrown)
-            .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.CAVES_CUT_THROUGH, BlockTags.NETHER_MOBS_SPAWN);
-        SOULSCHIST = new BlockCobble("soulschist", "minecraft:block/soulschist", 811, Material.stone, () -> Blocks.SOULSAND).withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withOverrideColor(MaterialColor.paintedBrown)
-
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NETHER_MOBS_SPAWN);
-
-        GLOWSTONE = new BlockGlowStone("glowstone", "minecraft:block/glowstone", 820, Material.stone).withSound(BlockSounds.GLASS).withHardness(0.3F).withLightEmission(1.0F).withOverrideColor(MaterialColor.paintedYellow)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-
-        PORTAL_NETHER = new BlockPortal("portal.nether", "minecraft:block/portal_nether", 830,1, OBSIDIAN.id, FIRE.id).withSound(BlockSounds.GLASS).withHardness(-1F).withLightEmission(0.75F).withOverrideColor(MaterialColor.paintedPurple).withDisabledStats()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
-        PORTAL_PARADISE = new BlockPortal("portal.paradise", "minecraft:block/portal_paradise", 831, 2, GLOWSTONE.id, BEDROCK.id).withSound(BlockSounds.GLASS).withHardness(-1F).withLightEmission(0.75f).withOverrideColor(MaterialColor.paintedPurple).withDisabledStats()
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
-
-        CAKE = new BlockCake("cake", "minecraft:block/cake", 840).withHardness(0.5F).withSound(BlockSounds.CLOTH).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.FOOD_CAKE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
-        PUMPKIN_PIE = new BlockPiePumpkin("pumpkin_pie", "minecraft:block/pumpkin_pie", 841).withSound(BlockSounds.CLOTH).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange().withOverrideColor(MaterialColor.paintedOrange).setStatParent(() -> Items.FOOD_PUMPKIN_PIE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
-
-        LAMP_IDLE = new BlockLamp("lamp.idle", "minecraft:block/lamp_idle", 850, false).withSound(BlockSounds.GLASS).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
-            .setBlockItem((b) -> new ItemBlockLamp(b))
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        LAMP_ACTIVE = new BlockLamp("lamp.active", "minecraft:block/lamp_active", 851, true).withSound(BlockSounds.GLASS).withLightEmission(0.9375F).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> LAMP_IDLE)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
-
-        LANTERN_FIREFLY_GREEN = new BlockLanternFirefly("lantern.firefly.green", "minecraft:block/lantern_firefly_green", 870, MobFireflyCluster.FireflyColor.GREEN, () -> Items.LANTERN_FIREFLY_GREEN).withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_GREEN)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
-        LANTERN_FIREFLY_BLUE = new BlockLanternFirefly("lantern.firefly.blue", "minecraft:block/lantern_firefly_blue", 871, MobFireflyCluster.FireflyColor.BLUE, () -> Items.LANTERN_FIREFLY_BLUE).withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_BLUE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
-        LANTERN_FIREFLY_ORANGE = new BlockLanternFirefly("lantern.firefly.orange", "minecraft:block/lantern_firefly_orange", 872, MobFireflyCluster.FireflyColor.ORANGE, () -> Items.LANTERN_FIREFLY_ORANGE).withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_ORANGE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
-        LANTERN_FIREFLY_RED = new BlockLanternFirefly("lantern.firefly.red", "minecraft:block/lantern_firefly_red", 873, MobFireflyCluster.FireflyColor.RED, () -> Items.LANTERN_FIREFLY_RED).withSound(BlockSounds.GLASS).withHardness(0.1F).withLightEmission(0.9375F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.LANTERN_FIREFLY_RED)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
-        JAR_GLASS = new BlockJar("jar.glass", "minecraft:block/jar_glass", 874, () -> Items.JAR).withSound(BlockSounds.GLASS).withHardness(0.1F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.JAR)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NOT_IN_CREATIVE_MENU);
-
-        OVERLAY_PEBBLES = new BlockOverlayPebbles("overlay.pebbles", "minecraft:block/overlay_pebbles", 880, Material.decoration).withSound(BlockSounds.STONE).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.AMMO_PEBBLE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU);
-
-        FENCE_CHAINLINK = new BlockFenceChainlink("fence.chainlink", "minecraft:block/fence_chainlink", 890, Material.metal).withSound(BlockSounds.METAL).withHardness(5F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CHAINLINK_FENCES_CONNECT, BlockTags.CAN_HANG_OFF);
-        FENCE_PAPER_WALL = new BlockFenceWallPaper("fence.paper_wall", "minecraft:block/fence_paper_wall", 891, Material.cloth).withSound(BlockSounds.CLOTH).withHardness(0.5F)
-            .withTags(BlockTags.MINEABLE_BY_SHEARS, BlockTags.FENCES_CONNECT, BlockTags.CAN_HANG_OFF, BlockTags.MINEABLE_BY_AXE);
-        FENCE_STEEL = new BlockFenceSteel("fence.steel", "minecraft:block/fence_steel", 892, Material.metal).withSound(BlockSounds.METAL).withHardness(8F).withOverrideColor(MaterialColor.steel).withBlastResistance(2000F)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CHAINLINK_FENCES_CONNECT, BlockTags.CAN_HANG_OFF);
-
-        BASKET = new BlockBasket("basket", "minecraft:block/basket", 900, Material.cloth).withSound(BlockSounds.CLOTH).withHardness(0.5F).withOverrideColor(MaterialColor.wood).setStatParent(() -> Items.BASKET)
-            .withTags(BlockTags.NOT_IN_CREATIVE_MENU);
-
-        PAPER_WALL = new Block("paper_wall", "minecraft:block/paper_wall", 910, Material.cloth).withSound(BlockSounds.CLOTH).withHardness(0.7F)
-            .withTags(BlockTags.MINEABLE_BY_SHEARS, BlockTags.FENCES_CONNECT, BlockTags.CAN_HANG_OFF, BlockTags.MINEABLE_BY_AXE);
-
-        SLAB_BRICK_SANDSTONE = new BlockSlab(BRICK_SANDSTONE, "minecraft:block/slab_brick_sandstone", 1000).withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_COBBLE_PERMAFROST = new BlockSlab(COBBLE_PERMAFROST, "minecraft:block/slab_cobble_permafrost", 1001).withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_BRICK_PERMAFROST = new BlockSlab(BRICK_PERMAFROST, "minecraft:block/slab_brick_permafrost", 1002).withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-        SLAB_PERMAFROST_POLISHED = new BlockSlab(PERMAFROST_CARVED, "minecraft:block/slab_permafrost_polished", 1003).withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
-            .withTags(BlockTags.MINEABLE_BY_PICKAXE);
+    public static boolean hasTag(int id, Tag<Block<?>> tag)
+    {
+        if (id < 0) return false;
+        Block<?> block = Blocks.blocksList[id];
+        if (block == null) return false;
+        return block.hasTag(tag);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java
index 41ff5a94d..16ffaba39 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.block.entity;
 
-import net.minecraft.core.block.Block;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.block.motion.CarriedBlock;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.Mob;
@@ -54,7 +54,7 @@ public class TileEntity implements ICarriable
         }
     }
 
-    public Block getBlock() {
+    public Block<?> getBlock() {
         if (carriedBlock != null) {
             return carriedBlock.block();
         } else {
@@ -132,7 +132,7 @@ public class TileEntity implements ICarriable
         y = blockY + side.getOffsetY();
         z = blockZ + side.getOffsetZ();
 
-        Block currentBlock = world.getBlock(x, y, z);
+        Block<?> currentBlock = world.getBlock(x, y, z);
         if (currentBlock != null && !currentBlock.hasTag(BlockTags.PLACE_OVERWRITES)) return false;
         world.setBlockAndMetadata(x, y, z, carriedBlock.blockId, carriedBlock.metadata);
 
@@ -140,7 +140,7 @@ public class TileEntity implements ICarriable
         this.validate();
         world.removeBlockTileEntity(x, y, z);
         world.setBlockTileEntity(x, y, z, this);
-        Block b = world.getBlock(x, y, z);
+        Block<?> b = world.getBlock(x, y, z);
         if (b != null && holder instanceof Mob) {
             b.onBlockPlacedByMob(world, x, y, z, side, (Mob) holder, xPlaced, yPlaced);
         }
@@ -175,7 +175,7 @@ public class TileEntity implements ICarriable
 
     @Override
     public ICarriable pickup(World world, Entity holder) {
-        Block currentBlock = world.getBlock(x, y, z);
+        Block<?> currentBlock = world.getBlock(x, y, z);
         int currentMeta = world.getBlockMetadata(x, y, z);
         world.removeBlockTileEntity(x, y, z);
         world.setBlockRaw(x, y, z, 0);
@@ -185,7 +185,7 @@ public class TileEntity implements ICarriable
         return carriedBlock;
     }
 
-    public CarriedBlock getCarriedEntry(World world, Entity holder, Block currentBlock, int currentMeta) {
+    public CarriedBlock getCarriedEntry(World world, Entity holder, Block<?> currentBlock, int currentMeta) {
         return new CarriedBlock(holder, currentBlock, currentMeta, this);
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
index dd6b623f9..9f35209bb 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
@@ -2,9 +2,9 @@ package net.minecraft.core.block.entity;
 
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockRotatable;
+import net.minecraft.core.block.BlockLogicRotatable;
 import net.minecraft.core.block.motion.CarriedBlock;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
@@ -233,7 +233,7 @@ public class TileEntityActivator extends TileEntity implements Container {
     }
 
     @Override
-    public CarriedBlock getCarriedEntry(World world, Entity holder, Block currentBlock, int currentMeta) {
-        return super.getCarriedEntry(world, holder, currentBlock, BlockRotatable.setDirection(currentMeta, Direction.NORTH) /*Reset rotation, primarily to make it render in hand properly*/);
+    public CarriedBlock getCarriedEntry(World world, Entity holder, Block<?> currentBlock, int currentMeta) {
+        return super.getCarriedEntry(world, holder, currentBlock, BlockLogicRotatable.setDirection(currentMeta, Direction.NORTH) /*Reset rotation, primarily to make it render in hand properly*/);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
index 7c317a9d4..7f4698c60 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
@@ -99,7 +99,7 @@ public class TileEntityBasket extends TileEntity
 		}
 
 		updateNumUnits();
-        world.notifyBlockChange(x, y, z, Blocks.BASKET.id);
+        world.notifyBlockChange(x, y, z, Blocks.BASKET.id());
 	}
 
     @Override
@@ -142,21 +142,20 @@ public class TileEntityBasket extends TileEntity
 
         final AABB aabb = AABB.getTemporaryBB(posX, posY, posZ, posX + 1, posY + 2, posZ + 1);
 
-        final List<Entity> entities = workingWorld.getEntitiesWithinAABB(EntityItem.class, aabb);
+        final List<EntityItem> entities = workingWorld.getEntitiesWithinAABB(EntityItem.class, aabb);
 
         boolean shouldUpdate = false;
 
         if (!entities.isEmpty())
         {
-            for (final Entity e : entities)
+            for (final EntityItem e : entities)
             {
-                final EntityItem entity = (EntityItem) e;
-                if (entity.item != null && entity.item.stackSize > 0 && entity.basketPickupDelay == 0)
+                if (e.item != null && e.item.stackSize > 0 && e.basketPickupDelay == 0)
                 {
-                    shouldUpdate = importItemStack(entity.item);
-                    if (entity.item.stackSize <= 0)
+                    shouldUpdate = importItemStack(e.item);
+                    if (e.item.stackSize <= 0)
                     {
-                        entity.item.stackSize = 0;
+                        e.item.stackSize = 0;
                         e.outOfWorld();
                     }
                 }
@@ -166,7 +165,7 @@ public class TileEntityBasket extends TileEntity
         if (shouldUpdate)
         {
             if (worldObj != null) {
-                worldObj.notifyBlockChange(x, y, z, Blocks.BASKET.id);
+                worldObj.notifyBlockChange(x, y, z, Blocks.BASKET.id());
             }
             updateNumUnits();
         }
@@ -230,7 +229,7 @@ public class TileEntityBasket extends TileEntity
 
         contents.clear();
 
-        world.notifyBlockChange(x, y, z, Blocks.BASKET.id);
+        world.notifyBlockChange(x, y, z, Blocks.BASKET.id());
         updateNumUnits();
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
index 3b69525d4..441ee6897 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.block.entity;
 
 import com.mojang.logging.LogUtils;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockChest;
+import net.minecraft.core.block.BlockLogicChest;
 import net.minecraft.core.block.motion.CarriedBlock;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
@@ -157,8 +157,8 @@ public class TileEntityChest extends TileEntity
     }
 
     @Override
-    public CarriedBlock getCarriedEntry(World world, Entity holder, Block currentBlock, int currentMeta) {
-        return super.getCarriedEntry(world, holder, currentBlock, BlockChest.getMetaWithDirection(BlockChest.getMetaWithType(currentMeta, BlockChest.Type.SINGLE), Direction.NORTH));
+    public CarriedBlock getCarriedEntry(World world, Entity holder, Block<?> currentBlock, int currentMeta) {
+        return super.getCarriedEntry(world, holder, currentBlock, BlockLogicChest.getMetaWithDirection(BlockLogicChest.getMetaWithType(currentMeta, BlockLogicChest.Type.SINGLE), Direction.NORTH));
     }
 
     private ItemStack[] chestContents;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java
index 97f5d0948..e968923ec 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java
@@ -76,7 +76,7 @@ public class TileEntityDispatcher {
         addMapping(TileEntitySign.class, new NamespaceID("minecraft", "sign"));
         addMapping(TileEntityMobSpawner.class, new NamespaceID("minecraft", "mob_spawner"));
         addMapping(TileEntityMovingPistonBlock.class, new NamespaceID("minecraft", "piston_moving"));
-        addMapping(TileEntityFurnaceBlastFurnace.class, new NamespaceID("minecraft", "furnace_blast"));
+        addMapping(TileEntityFurnaceBlast.class, new NamespaceID("minecraft", "furnace_blast"));
         addMapping(TileEntitySensor.class, new NamespaceID("minecraft", "sensor"));
         addMapping(TileEntityTrommel.class, new NamespaceID("minecraft", "trommel"));
         addMapping(TileEntityBasket.class, new NamespaceID("minecraft", "basket"));
@@ -131,7 +131,7 @@ public class TileEntityDispatcher {
             addMapping(TileEntityMobSpawner.class, "MobSpawner");
             addMapping(TileEntityNoteblock.class, "Music");
             addMapping(TileEntityMovingPistonBlock.class, "Piston");
-            addMapping(TileEntityFurnaceBlastFurnace.class, "BlastFurnace");
+            addMapping(TileEntityFurnaceBlast.class, "BlastFurnace");
             addMapping(TileEntitySensor.class, "Sensor");
             addMapping(TileEntityTrommel.class, "Trommel");
             addMapping(TileEntityBasket.class, "Basket");
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
index aaf5ebfb1..72aaac246 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.block.entity;
 
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockRotatable;
+import net.minecraft.core.block.BlockLogicRotatable;
 import net.minecraft.core.block.motion.CarriedBlock;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
@@ -206,8 +206,8 @@ public class TileEntityDispenser extends TileEntity
     }
 
     @Override
-    public CarriedBlock getCarriedEntry(World world, Entity holder, Block currentBlock, int currentMeta) {
-        return super.getCarriedEntry(world, holder, currentBlock, BlockRotatable.setDirection(currentMeta, Direction.NORTH) /*Reset rotation, primarily to make it render in hand properly*/);
+    public CarriedBlock getCarriedEntry(World world, Entity holder, Block<?> currentBlock, int currentMeta) {
+        return super.getCarriedEntry(world, holder, currentBlock, BlockLogicRotatable.setDirection(currentMeta, Direction.NORTH) /*Reset rotation, primarily to make it render in hand properly*/);
     }
 
     private ItemStack dispenserContents[];
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java
index cfc9e0f57..2c6399051 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java
@@ -2,7 +2,7 @@ package net.minecraft.core.block.entity;
 
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFlowerStackable;
+import net.minecraft.core.block.BlockLogicFlowerStackable;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.item.ItemStack;
@@ -34,10 +34,10 @@ public class TileEntityFlowerJar extends TileEntity {
     @Override
     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)) {
+        if (flowerInPot > 0 && Blocks.hasTag(flowerInPot, BlockTags.PLANTABLE_IN_JAR)) {
             if (!world.isClientSide) {
-                if (Blocks.getBlock(flowerInPot) instanceof BlockFlowerStackable) {
-                    world.dropItem(x, y, z, new ItemStack(flowerInPot, BlockFlowerStackable.getStackCount(flowerData) + 1, 0));
+                if (Block.hasLogicClass(Blocks.getBlock(flowerInPot), BlockLogicFlowerStackable.class)) {
+                    world.dropItem(x, y, z, new ItemStack(flowerInPot, BlockLogicFlowerStackable.getStackCount(flowerData) + 1, 0));
                 } else {
                     world.dropItem(x, y, z, new ItemStack(flowerInPot, 1, flowerData));
                 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
index fbb60f1e0..1976b97d5 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
@@ -2,10 +2,10 @@ package net.minecraft.core.block.entity;
 
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFurnace;
+import net.minecraft.core.block.BlockLogicFurnace;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.motion.CarriedBlock;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.crafting.LookupFuelFurnace;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.recipe.entry.RecipeEntryFurnace;
@@ -178,9 +178,9 @@ public class TileEntityFurnace extends TileEntity
         }
         if(worldObj == null || !worldObj.isClientSide)
         {
-        	if(worldObj == null || worldObj.getBlockId(x, y, z) == Blocks.FURNACE_STONE_IDLE.id) {
+        	if(worldObj == null || worldObj.getBlockId(x, y, z) == Blocks.FURNACE_STONE_IDLE.id()) {
             	if(currentBurnTime == 0 && furnaceItemStacks[0] == null) {
-            		if(furnaceItemStacks[1] != null && furnaceItemStacks[1].itemID == Blocks.COBBLE_NETHERRACK.id) {
+            		if(furnaceItemStacks[1] != null && furnaceItemStacks[1].itemID == Blocks.COBBLE_NETHERRACK.id()) {
             			furnaceItemStacks[1].stackSize--;
             			if(furnaceItemStacks[1].stackSize <= 0) furnaceItemStacks[1] = null;
             			updateFurnace(true);
@@ -306,9 +306,9 @@ public class TileEntityFurnace extends TileEntity
 
     protected void updateFurnace(boolean forceLit){
         if (worldObj != null) {
-            BlockFurnace.updateFurnaceBlockState( forceLit | (currentBurnTime > 0), worldObj, x, y, z);
+            BlockLogicFurnace.updateFurnaceBlockState( forceLit | (currentBurnTime > 0), worldObj, x, y, z);
         } else if (carriedBlock != null) {
-            carriedBlock.blockId = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_STONE_ACTIVE.id : Blocks.FURNACE_STONE_IDLE.id;
+            carriedBlock.blockId = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_STONE_ACTIVE.id() : Blocks.FURNACE_STONE_IDLE.id();
         }
     }
 
@@ -332,7 +332,7 @@ public class TileEntityFurnace extends TileEntity
     @Override
     public void dropContents(World world, int x, int y, int z) {
         super.dropContents(world, x, y, z);
-        if(!BlockFurnace.keepFurnaceInventory)
+        if(!BlockLogicFurnace.keepFurnaceInventory)
         {
             label0:
             for(int l = 0; l < this.getContainerSize(); l++)
@@ -399,7 +399,7 @@ public class TileEntityFurnace extends TileEntity
     }
 
     @Override
-    public CarriedBlock getCarriedEntry(World world, Entity holder, Block currentBlock, int currentMeta) {
+    public CarriedBlock getCarriedEntry(World world, Entity holder, Block<?> currentBlock, int currentMeta) {
         return super.getCarriedEntry(world, holder, currentBlock, (currentMeta & ~0b111) | 0b010 /*Reset rotation, primarily to make it render in hand properly*/);
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlastFurnace.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlast.java
similarity index 94%
rename from game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlastFurnace.java
rename to game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlast.java
index 2a7200eee..6bf07adcb 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlastFurnace.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlast.java
@@ -2,7 +2,7 @@ package net.minecraft.core.block.entity;
 
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
-import net.minecraft.core.block.BlockFurnaceBlast;
+import net.minecraft.core.block.BlockLogicFurnaceBlast;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.crafting.LookupFuelFurnaceBlast;
 import net.minecraft.core.data.registry.Registries;
@@ -12,12 +12,12 @@ import net.minecraft.core.player.inventory.container.Container;
 
 import java.util.List;
 
-public class TileEntityFurnaceBlastFurnace extends TileEntityFurnace
+public class TileEntityFurnaceBlast extends TileEntityFurnace
         implements Container
 {
 
 
-    public TileEntityFurnaceBlastFurnace()
+    public TileEntityFurnaceBlast()
     {
         super();
         maxCookTime = 100;
@@ -84,9 +84,9 @@ public class TileEntityFurnaceBlastFurnace extends TileEntityFurnace
         }
         if(worldObj == null || !worldObj.isClientSide)
         {
-        	if(worldObj == null || worldObj.getBlockId(x, y, z) == Blocks.FURNACE_BLAST_IDLE.id) {
+        	if(worldObj == null || worldObj.getBlockId(x, y, z) == Blocks.FURNACE_BLAST_IDLE.id()) {
             	if(currentBurnTime == 0 && furnaceItemStacks[0] == null) {
-            		if(furnaceItemStacks[1] != null && furnaceItemStacks[1].itemID == Blocks.COBBLE_NETHERRACK.id) {
+            		if(furnaceItemStacks[1] != null && furnaceItemStacks[1].itemID == Blocks.COBBLE_NETHERRACK.id()) {
             			furnaceItemStacks[1].stackSize--;
             			if(furnaceItemStacks[1].stackSize <= 0) furnaceItemStacks[1] = null;
             			updateFurnace(true);
@@ -138,9 +138,9 @@ public class TileEntityFurnaceBlastFurnace extends TileEntityFurnace
     @Override
     protected void updateFurnace(boolean forceLit){
         if (worldObj != null) {
-            BlockFurnaceBlast.updateFurnaceBlockState(forceLit | (currentBurnTime > 0), worldObj, x, y, z);
+            BlockLogicFurnaceBlast.updateFurnaceBlockState(forceLit | (currentBurnTime > 0), worldObj, x, y, z);
         } else if (carriedBlock != null) {
-            carriedBlock.blockId = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_BLAST_ACTIVE.id : Blocks.FURNACE_BLAST_IDLE.id;
+            carriedBlock.blockId = (forceLit | (currentBurnTime > 0)) ? Blocks.FURNACE_BLAST_ACTIVE.id() : Blocks.FURNACE_BLAST_IDLE.id();
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java
index 4f3e6649a..09c956409 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java
@@ -55,7 +55,7 @@ public class TileEntityMobSpawner extends TileEntity
     @Override
 	public void tick()
     {
-        if (worldObj.getBlockId(x, y, z) != Blocks.MOBSPAWNER.id) return; // dumb fix for mp particle bug, need proper way to inform client to remove tileEntity
+        if (worldObj.getBlockId(x, y, z) != Blocks.MOBSPAWNER.id()) return; // dumb fix for mp particle bug, need proper way to inform client to remove tileEntity
         yaw2 = yaw;
         if(!anyPlayerInRange())
         {
@@ -148,7 +148,7 @@ public class TileEntityMobSpawner extends TileEntity
     		for(int j = -r; j <= r; j++) {
     			for(int k = -r; k <= r; k++) {
     				int id = worldObj.getBlockId(x + i, y + j, z + k);
-    				if(id == Blocks.MOBSPAWNER.id) {
+    				if(id == Blocks.MOBSPAWNER.id()) {
     					count++;
     				}
     			}
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java
index 7e00eb25b..342f815df 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.block.entity;
 
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockNote;
+import net.minecraft.core.block.BlockLogicNote;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.util.helper.MathHelper;
 
@@ -19,7 +19,7 @@ public class TileEntityNoteblock extends TileEntity
     @Override
     public void tick() {
         if (worldObj.getBlock(x, y, z) == Blocks.NOTEBLOCK) { // Set note block pitch
-            worldObj.setBlockMetadata(x, y, z, BlockNote.setNote(0, note));
+            worldObj.setBlockMetadata(x, y, z, BlockLogicNote.setNote(0, note));
         }
         invalidate(); // Delete self
     }
@@ -33,7 +33,7 @@ public class TileEntityNoteblock extends TileEntity
     @Override
 	public void readFromNBT(CompoundTag tag) {
         super.readFromNBT(tag);
-        note = MathHelper.clamp(tag.getByte("note"), (byte) 0, BlockNote.MAX_NOTE);
+        note = MathHelper.clamp(tag.getByte("note"), (byte) 0, BlockLogicNote.MAX_NOTE);
     }
 
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java
index 2485e6d0f..e8f32984e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.block.entity;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.IVehicle;
@@ -13,11 +13,11 @@ public class TileEntitySeat
     implements IVehicle {
     private Entity passenger;
 
-    public Block seat;
+    public Block<?> seat;
     public TileEntitySeat() {
         this(null);
     }
-    public TileEntitySeat(Block seat) {
+    public TileEntitySeat(Block<?> seat) {
         passenger = null;
         this.seat = seat;
     }
@@ -142,7 +142,7 @@ public class TileEntitySeat
     {
         super.writeToNBT(compoundTag);
         if (seat != null && seat != Blocks.SEAT) {
-            compoundTag.putInt("Block", seat.id);
+            compoundTag.putInt("Block", seat.id());
         }
     }
 
@@ -150,6 +150,6 @@ public class TileEntitySeat
     public void readFromNBT(CompoundTag compoundTag)
     {
         super.readFromNBT(compoundTag);
-        seat = Blocks.getBlock(compoundTag.getIntegerOrDefault("Block", Blocks.SEAT.id));
+        seat = Blocks.getBlock(compoundTag.getIntegerOrDefault("Block", Blocks.SEAT.id()));
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
index 39a23e871..a699744a0 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
@@ -3,9 +3,8 @@ package net.minecraft.core.block.entity;
 import java.util.List;
 
 import net.minecraft.core.achievement.Achievements;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockMotionSensor;
+import net.minecraft.core.block.BlockLogicMotionSensor;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.Player;
@@ -24,7 +23,7 @@ public class TileEntitySensor extends TileEntity {
 		
 		int range = 4;
 		int blockInFront = world.getBlockId(MathHelper.round(x + facing.getOffsetX()), MathHelper.round(y + facing.getOffsetY()), MathHelper.round(z + facing.getOffsetZ()));
-		if(Block.hasTag(blockInFront, BlockTags.EXTENDS_MOTION_SENSOR_RANGE)) {
+		if(Blocks.hasTag(blockInFront, BlockTags.EXTENDS_MOTION_SENSOR_RANGE)) {
 			range = 8;
 		}
 		
@@ -33,7 +32,7 @@ public class TileEntitySensor extends TileEntity {
 			int y1 = MathHelper.round(y + facing.getOffsetY() * i);
 			int z1 = MathHelper.round(z + facing.getOffsetZ() * i);
 			int id = world.getBlockId(x1, y1, z1);
-			if(Blocks.solid[id] && !Block.hasTag(id, BlockTags.EXTENDS_MOTION_SENSOR_RANGE)) {
+			if(Blocks.solid[id] && !Blocks.hasTag(id, BlockTags.EXTENDS_MOTION_SENSOR_RANGE)) {
 				return i - 1;
 			}
 		}
@@ -71,7 +70,7 @@ public class TileEntitySensor extends TileEntity {
 		int meta = worldObj.getBlockMetadata(x, y, z);
 		
 		boolean shouldBeActive = false;
-		Direction facing = BlockMotionSensor.getFacingDirection(meta);
+		Direction facing = BlockLogicMotionSensor.getFacingDirection(meta);
 		int effectiveRange = getSightRange(worldObj, x, y, z, facing);
 		if(effectiveRange > 0) {
 			AABB detectionBox = getDetectionBox(x, y, z, facing, effectiveRange);
@@ -86,11 +85,11 @@ public class TileEntitySensor extends TileEntity {
 			}
 		}
 		
-		if(shouldBeActive && id == Blocks.MOTION_SENSOR_IDLE.id) {
+		if(shouldBeActive && id == Blocks.MOTION_SENSOR_IDLE.id()) {
 			worldObj.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, x + 0.5, y + 0.5, z + 0.5, "tile.sensor_block.sense", 1f, worldObj.rand.nextFloat());
 			updateSensorBlockState(true, worldObj);
 		}
-		if(!shouldBeActive && id == Blocks.MOTION_SENSOR_ACTIVE.id) {
+		if(!shouldBeActive && id == Blocks.MOTION_SENSOR_ACTIVE.id()) {
 			updateSensorBlockState(false, worldObj);
 		}
 	}
@@ -106,7 +105,7 @@ public class TileEntitySensor extends TileEntity {
 		int meta = carriedBlock.metadata;
 
 		boolean shouldBeActive = false;
-		Direction facing = BlockMotionSensor.getFacingDirection(meta);
+		Direction facing = BlockLogicMotionSensor.getFacingDirection(meta);
 		int effectiveRange = getSightRange(world, holder.x, holder.y, holder.z, facing);
 		if(effectiveRange > 0) {
 			AABB detectionBox = getDetectionBox(holder.x, holder.y, holder.z, facing, effectiveRange);
@@ -122,11 +121,11 @@ public class TileEntitySensor extends TileEntity {
 			}
 		}
 
-		if(shouldBeActive && id == Blocks.MOTION_SENSOR_IDLE.id) {
+		if(shouldBeActive && id == Blocks.MOTION_SENSOR_IDLE.id()) {
 			world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, x + 0.5, y + 0.5, z + 0.5, "tile.sensor_block.sense", 1f, world.rand.nextFloat());
 			updateSensorBlockState(true, world);
 		}
-		if(!shouldBeActive && id == Blocks.MOTION_SENSOR_ACTIVE.id) {
+		if(!shouldBeActive && id == Blocks.MOTION_SENSOR_ACTIVE.id()) {
 			updateSensorBlockState(false, world);
 		}
 	}
@@ -134,17 +133,17 @@ public class TileEntitySensor extends TileEntity {
 	public void updateSensorBlockState(boolean active, World world) {
 		if (carriedBlock != null) {
             if(active) {
-				carriedBlock.blockId = Blocks.MOTION_SENSOR_ACTIVE.id;
+				carriedBlock.blockId = Blocks.MOTION_SENSOR_ACTIVE.id();
 			}else {
-				carriedBlock.blockId = Blocks.MOTION_SENSOR_IDLE.id;
+				carriedBlock.blockId = Blocks.MOTION_SENSOR_IDLE.id();
 			}
 		} else {
 			int meta = world.getBlockMetadata(x, y, z);
 			int blockId;
 			if(active) {
-				blockId = Blocks.MOTION_SENSOR_ACTIVE.id;
+				blockId = Blocks.MOTION_SENSOR_ACTIVE.id();
 			}else {
-				blockId = Blocks.MOTION_SENSOR_IDLE.id;
+				blockId = Blocks.MOTION_SENSOR_IDLE.id();
 			}
 			world.setBlock(x, y, z, blockId);
 			world.setBlockMetadata(x, y, z, meta);
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
index aee215574..0df117025 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
@@ -4,11 +4,11 @@ package net.minecraft.core.block.entity;
 import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockChest;
-import net.minecraft.core.block.BlockTrommel;
+import net.minecraft.core.block.BlockLogicChest;
+import net.minecraft.core.block.BlockLogicTrommel;
 import net.minecraft.core.block.motion.CarriedBlock;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.crafting.LookupFuelFurnace;
 import net.minecraft.core.data.DataLoader;
 import net.minecraft.core.data.registry.recipe.entry.RecipeEntryTrommel;
@@ -180,15 +180,15 @@ public class TileEntityTrommel extends TileEntity
         }
         if(worldObj == null || !worldObj.isClientSide)
         {
-        	if(worldObj == null || worldObj.getBlockId(x, y, z) == Blocks.TROMMEL_IDLE.id) {
+        	if(worldObj == null || worldObj.getBlockId(x, y, z) == Blocks.TROMMEL_IDLE.id()) {
             	if(currentItemBurnTime == 0 && itemStacks[0] == null) {
-            		if(itemStacks[4] != null && itemStacks[4].itemID == Blocks.COBBLE_NETHERRACK.id) {
+            		if(itemStacks[4] != null && itemStacks[4].itemID == Blocks.COBBLE_NETHERRACK.id()) {
             			itemStacks[4].stackSize--;
             			if(itemStacks[4].stackSize <= 0) itemStacks[4] = null;
             			if (worldObj != null) {
-                            BlockTrommel.updateTrommelBlockState(true, worldObj, x, y, z);
+                            BlockLogicTrommel.updateTrommelBlockState(true, worldObj, x, y, z);
                         } else if (carriedBlock != null) {
-                            carriedBlock.blockId = Blocks.TROMMEL_ACTIVE.id;
+                            carriedBlock.blockId = Blocks.TROMMEL_ACTIVE.id();
                         }
                         flag1 = true;
                     }
@@ -234,9 +234,9 @@ public class TileEntityTrommel extends TileEntity
             {
                 flag1 = true;
                 if (worldObj != null) {
-                    BlockTrommel.updateTrommelBlockState(burnTime > 0, worldObj, x, y, z);
+                    BlockLogicTrommel.updateTrommelBlockState(burnTime > 0, worldObj, x, y, z);
                 } else if (carriedBlock != null) {
-                    carriedBlock.blockId = burnTime > 0 ? Blocks.TROMMEL_ACTIVE.id : Blocks.TROMMEL_IDLE.id;
+                    carriedBlock.blockId = burnTime > 0 ? Blocks.TROMMEL_ACTIVE.id() : Blocks.TROMMEL_IDLE.id();
                 }
             }
         }
@@ -291,9 +291,9 @@ public class TileEntityTrommel extends TileEntity
         	int adjacentId = worldObj != null ? worldObj.getBlockId(x + xOffset, y, z + zOffset) : 0;
         	
         	Container chest = null;
-        	if (Blocks.blocksList[adjacentId] instanceof BlockChest) {
+        	if (Block.hasLogicClass(Blocks.blocksList[adjacentId], BlockLogicChest.class)) {
                 assert worldObj != null;
-                chest = BlockChest.getInventory(worldObj, x + xOffset, y, z + zOffset);
+                chest = BlockLogicChest.getInventory(worldObj, x + xOffset, y, z + zOffset);
         	}
         	
         	if (chest != null)
@@ -405,7 +405,7 @@ public class TileEntityTrommel extends TileEntity
     @Override
     public void dropContents(World world, int x, int y, int z) {
         super.dropContents(world, x, y, z);
-        if (!BlockTrommel.keepTrommelInventory)
+        if (!BlockLogicTrommel.keepTrommelInventory)
         {
             if(world.getBlockEntity(x, y, z) != null)
             {
@@ -535,7 +535,7 @@ public class TileEntityTrommel extends TileEntity
     }
 
     @Override
-    public CarriedBlock getCarriedEntry(World world, Entity holder, Block currentBlock, int currentMeta) {
+    public CarriedBlock getCarriedEntry(World world, Entity holder, Block<?> currentBlock, int currentMeta) {
         return super.getCarriedEntry(world, holder, currentBlock, (currentMeta & ~0b111) | 0b010 /*Reset rotation, primarily to make it render in hand properly*/);
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/material/MaterialColor.java b/game/core/src/main/java/net/minecraft/core/block/material/MaterialColor.java
index e8ab9faef..c1957bf50 100644
--- a/game/core/src/main/java/net/minecraft/core/block/material/MaterialColor.java
+++ b/game/core/src/main/java/net/minecraft/core/block/material/MaterialColor.java
@@ -90,14 +90,14 @@ public class MaterialColor {
         materialColors[id] = this;
     }
 
-    private static int makeBlockIndex(Block block, int meta){
-        return block.id << 8 | meta;
+    private static int makeBlockIndex(Block<?> block, int meta){
+        return block.id() << 8 | meta;
     }
-    public static void registerManualBlockColor(Block block, int meta, MaterialColor color){
+    public static void registerManualBlockColor(Block<?> block, int meta, MaterialColor color){
         int blockIndex = makeBlockIndex(block, meta);
         blockIdColorIndexMap.put(blockIndex, color.id);
     }
-    public static int getColorIndexFromBlock(Block block, int meta){
+    public static int getColorIndexFromBlock(Block<?> block, int meta){
         int blockIndex = makeBlockIndex(block, meta);
         if (blockIdColorIndexMap.containsKey(blockIndex)){
             return blockIdColorIndexMap.get(blockIndex);
diff --git a/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java b/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
index 05af9554c..ac6113479 100644
--- a/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
@@ -1,10 +1,10 @@
 package net.minecraft.core.block.motion;
 
 import com.mojang.nbt.CompoundTag;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityDispatcher;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.Mob;
@@ -23,8 +23,8 @@ public class CarriedBlock implements ICarriable {
     // 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 TileEntity entity) {
-        this(holder, block.id, metadata, entity);
+    public CarriedBlock(@NotNull Entity holder, @NotNull Block<?> block, int metadata, @Nullable TileEntity entity) {
+        this(holder, block.id(), metadata, entity);
     }
 
     public CarriedBlock(@NotNull Entity holder, int blockId, int metadata, @Nullable TileEntity entity) {
@@ -42,7 +42,7 @@ public class CarriedBlock implements ICarriable {
         assert world != null : "Carried block world ref must not be null!";
     }
 
-    public Block block() {
+    public Block<?> block() {
         return Blocks.getBlock(blockId);
     }
 
@@ -62,11 +62,11 @@ public class CarriedBlock implements ICarriable {
             int y = blockY + side.getOffsetY();
             int z = blockZ + side.getOffsetZ();
 
-            Block currentBlock = world.getBlock(x, y, z);
+            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);
+            Block<?> b = world.getBlock(x, y, z);
             if (b != null && holder instanceof Mob) {
                 b.onBlockPlacedByMob(world, x, y, z, side, (Mob) holder, xPlaced, yPlaced);
             }
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBase.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBase.java
rename to game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java
index 8bf4f9f0d..357ff1c97 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBase.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java
@@ -1,11 +1,10 @@
 package net.minecraft.core.block.piston;
 
-import java.util.ArrayList;
-
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.entity.player.Player;
@@ -21,7 +20,7 @@ import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockPistonBase extends Block
+public class BlockLogicPistonBase extends BlockLogic
 {
     public static final int MASK_DIRECTION = 0b0000_0111;
     public static final int MASK_POWERED = 0b0000_1000;
@@ -31,11 +30,11 @@ public class BlockPistonBase extends Block
 
     private final int maxPushedBlocks;
 
-    public BlockPistonBase(String key, String namespaceId, int id, int maxPushedBlocks)
+    public BlockLogicPistonBase(Block<?> block, int maxPushedBlocks)
     {
-        super(key, namespaceId, id, Material.piston);
+        super(block, Material.piston);
         this.maxPushedBlocks = maxPushedBlocks;
-        withHardness(0.5F);
+        block.withHardness(0.5F);
     }
 
     @Override
@@ -175,8 +174,8 @@ public class BlockPistonBase extends Block
                 world.setBlock(x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ(), 0);
             }
         }
-        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id, direction.getId());
-        world.replaceBlockTileEntity(x, y, z, BlockPistonMoving.createTileEntity(id, direction.getId(), null, direction, false, true));
+        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id(), direction.getId());
+        world.replaceBlockTileEntity(x, y, z, BlockLogicPistonMoving.createTileEntity(block.id(), direction.getId(), null, direction, false, true));
         world.setBlockWithNotify(x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ(), 0);
         world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double)x + 0.5D, (double)y + 0.5D, (double)z + 0.5D, "tile.piston.in", 0.5F, world.rand.nextFloat() * 0.15F + 0.6F);
     }
@@ -227,7 +226,7 @@ public class BlockPistonBase extends Block
     
     protected boolean isPushable(int id, World world, int x, int y, int z, boolean canDestroy)
     {
-        Block block = Blocks.getBlock(id);
+        Block<?> block = Blocks.getBlock(id);
         if (block == null) return false;
         int pushReaction = block.getPistonPushReaction(world, x, y, z);
         if (block.hasTag(BlockTags.PISTON_CRUSHING) ||
@@ -289,7 +288,7 @@ public class BlockPistonBase extends Block
         int x2 = x + direction.getOffsetX();
         int y2 = y + direction.getOffsetY();
         int z2 = z + direction.getOffsetZ();
-        Block block = world.getBlock(x2, y2, z2);
+        Block<?> block = world.getBlock(x2, y2, z2);
         if (block == null) return true;
         world.playBlockEvent(null, LevelListener.EVENT_BLOCK_BREAK, x2, y2, z2, world.getBlockId(x2, y2, z2));
         block.dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x2, y2, z2, world.getBlockMetadata(x2, y2, z2), null, null);
@@ -340,10 +339,10 @@ public class BlockPistonBase extends Block
             if (pushEntity instanceof TileEntityMovingPistonBlock && px == x && py == y && pz == z) {
                 break;
             }
-            if(pushId == id && px == x && py == y && pz == z)
+            if(pushId == block.id() && px == x && py == y && pz == z)
             {
                 createPistonHeadAt(world, xo, yo, zo, data, direction);
-            } else if (pushId == Blocks.PISTON_MOVING.id)
+            } else if (pushId == Blocks.PISTON_MOVING.id())
             {
                 TileEntity old = world.getBlockEntity(px, py, pz);
                 if (old instanceof TileEntityMovingPistonBlock) {
@@ -355,13 +354,13 @@ public class BlockPistonBase extends Block
                     }
                 }
                 world.removeBlockTileEntity(px, py, pz);
-                world.setBlockAndMetadata(xo, yo, zo, Blocks.PISTON_MOVING.id, pushMeta);
-                world.replaceBlockTileEntity(xo, yo, zo, BlockPistonMoving.createTileEntity(pushId, pushMeta, pushEntity, direction, true, false));
+                world.setBlockAndMetadata(xo, yo, zo, Blocks.PISTON_MOVING.id(), pushMeta);
+                world.replaceBlockTileEntity(xo, yo, zo, BlockLogicPistonMoving.createTileEntity(pushId, pushMeta, pushEntity, direction, true, false));
             } else
             {
                 world.removeBlockTileEntity(px, py, pz);
-                world.setBlockAndMetadata(xo, yo, zo, Blocks.PISTON_MOVING.id, pushMeta);
-                world.replaceBlockTileEntity(xo, yo, zo, BlockPistonMoving.createTileEntity(pushId, pushMeta, pushEntity, direction, true, false));
+                world.setBlockAndMetadata(xo, yo, zo, Blocks.PISTON_MOVING.id(), pushMeta);
+                world.replaceBlockTileEntity(xo, yo, zo, BlockLogicPistonMoving.createTileEntity(pushId, pushMeta, pushEntity, direction, true, false));
             }
             if (!(px == x && py == y && pz == z))
                 world.setBlockAndMetadataRaw(px, py, pz, 0, 0);
@@ -374,8 +373,8 @@ public class BlockPistonBase extends Block
     }
 
     public void createPistonHeadAt(World world, int x, int y, int z, int data, Direction direction) {
-        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id, BlockPistonHead.setPistonType(BlockPistonHead.TYPE_NORMAL, direction.getId()));
-        world.replaceBlockTileEntity(x, y, z, BlockPistonMoving.createTileEntity(Blocks.PISTON_HEAD.id, BlockPistonHead.setPistonType(BlockPistonHead.TYPE_NORMAL, direction.getId()), null, direction, true, false));
+        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id(), BlockLogicPistonHead.setPistonType(BlockLogicPistonHead.TYPE_NORMAL, direction.getId()));
+        world.replaceBlockTileEntity(x, y, z, BlockLogicPistonMoving.createTileEntity(Blocks.PISTON_HEAD.id(), BlockLogicPistonHead.setPistonType(BlockLogicPistonHead.TYPE_NORMAL, direction.getId()), null, direction, true, false));
     }
     
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBaseSteel.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBaseSteel.java
similarity index 89%
rename from game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBaseSteel.java
rename to game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBaseSteel.java
index b1db533be..d338c927d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBaseSteel.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBaseSteel.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.block.piston;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityFallingBlock;
@@ -18,13 +18,13 @@ import net.minecraft.core.world.WorldSource;
 import java.util.ArrayList;
 import java.util.List;
 
-public class BlockPistonBaseSteel extends BlockPistonBase {
+public class BlockLogicPistonBaseSteel extends BlockLogicPistonBase {
     public static final double HEAD_THICKNESS_STEEL = 6/16d;
 
     private Entity flungBlock = null;
 
-    public BlockPistonBaseSteel(String key, String namespaceId, int id, int maxPushedBlocks) {
-        super(key, namespaceId, id, maxPushedBlocks);
+    public BlockLogicPistonBaseSteel(Block<?> container, int maxPushedBlocks) {
+        super(container, maxPushedBlocks);
     }
 
     @Override
@@ -96,13 +96,13 @@ public class BlockPistonBaseSteel extends BlockPistonBase {
             xo = x + direction.getOffsetX();
             yo = y + direction.getOffsetY();
             zo = z + direction.getOffsetZ();
-            Block block = world.getBlock(xo, yo, zo);
+            Block<?> block = world.getBlock(xo, yo, zo);
             if (block == null) return true;
             int blockMeta = world.getBlockMetadata(xo, yo, zo);
             TileEntity tileEntity = world.getBlockEntity(xo, yo, zo);
             world.removeBlockTileEntity(xo, yo, zo);
             world.setBlockWithNotify(xo, yo, zo, 0);
-            EntityFallingBlock entityFallingBlock = new EntityFallingBlock(world, xo + 0.5, yo + 0.5, zo + 0.5, block.id, blockMeta, tileEntity);
+            EntityFallingBlock entityFallingBlock = new EntityFallingBlock(world, xo + 0.5, yo + 0.5, zo + 0.5, block.id(), blockMeta, tileEntity);
             entityFallingBlock.hasRemovedBlock = true;
             if (tileEntity instanceof IVehicle) {
                 Entity rider = ((IVehicle) tileEntity).getPassenger();
@@ -122,7 +122,7 @@ public class BlockPistonBaseSteel extends BlockPistonBase {
         int x2 = x + direction.getOffsetX();
         int y2 = y + direction.getOffsetY();
         int z2 = z + direction.getOffsetZ();
-        Block block = world.getBlock(x2, y2, z2);
+        Block<?> block = world.getBlock(x2, y2, z2);
         if (block == null) return true;
         world.playBlockEvent(null, LevelListener.EVENT_BLOCK_BREAK, x2, y2, z2, world.getBlockId(x2, y2, z2));
         block.dropBlockWithCause(world, EnumDropCause.PISTON_CRUSH, x2, y2, z2, world.getBlockMetadata(x2, y2, z2), null, null);
@@ -144,8 +144,8 @@ public class BlockPistonBaseSteel extends BlockPistonBase {
 
     @Override
     public void createPistonHeadAt(World world, int x, int y, int z, int data, Direction direction) {
-        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id,  BlockPistonHead.setPistonType(BlockPistonHead.TYPE_STEEL, direction.getId()));
-        world.replaceBlockTileEntity(x, y, z, BlockPistonMoving.createTileEntity(Blocks.PISTON_HEAD_STEEL.id, BlockPistonHead.setPistonType(BlockPistonHead.TYPE_STEEL, direction.getId()), null, direction, true, false));
+        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id(),  BlockLogicPistonHead.setPistonType(BlockLogicPistonHead.TYPE_STEEL, direction.getId()));
+        world.replaceBlockTileEntity(x, y, z, BlockLogicPistonMoving.createTileEntity(Blocks.PISTON_HEAD_STEEL.id(), BlockLogicPistonHead.setPistonType(BlockLogicPistonHead.TYPE_STEEL, direction.getId()), null, direction, true, false));
     }
 
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBaseSticky.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBaseSticky.java
similarity index 73%
rename from game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBaseSticky.java
rename to game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBaseSticky.java
index caf6c3129..d10a577f1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonBaseSticky.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBaseSticky.java
@@ -1,16 +1,16 @@
 package net.minecraft.core.block.piston;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
 
-public class BlockPistonBaseSticky extends BlockPistonBase {
-    public BlockPistonBaseSticky(String key, String namespaceId, int id, int maxPushedBlocks) {
-        super(key, namespaceId, id, maxPushedBlocks);
+public class BlockLogicPistonBaseSticky extends BlockLogicPistonBase {
+    public BlockLogicPistonBaseSticky(Block<?> block, int maxPushedBlocks) {
+        super(block, maxPushedBlocks);
     }
 
     @Override
@@ -25,8 +25,8 @@ public class BlockPistonBaseSticky extends BlockPistonBase {
                 world.setBlock(x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ(), 0);
             }
         }
-        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id, direction.getId());
-        world.replaceBlockTileEntity(x, y, z, BlockPistonMoving.createTileEntity(id, direction.getId(), null, direction, false, true));
+        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id(), direction.getId());
+        world.replaceBlockTileEntity(x, y, z, BlockLogicPistonMoving.createTileEntity(block.id(), direction.getId(), null, direction, false, true));
         int x1 = x + direction.getOffsetX() * 2;
         int y1 = y + direction.getOffsetY() * 2;
         int z1 = z + direction.getOffsetZ() * 2;
@@ -34,7 +34,7 @@ public class BlockPistonBaseSticky extends BlockPistonBase {
         int retactMeta = world.getBlockMetadata(x1, y1, z1);
         TileEntity retractEntity = world.getBlockEntity(x1, y1, z1);
         boolean pulledMoving = false;
-        if(retractId == Blocks.PISTON_MOVING.id)
+        if(retractId == Blocks.PISTON_MOVING.id())
         {
             TileEntity tileEntity1 = world.getBlockEntity(x1, y1, z1);
             if((tileEntity1 instanceof TileEntityMovingPistonBlock))
@@ -50,9 +50,10 @@ public class BlockPistonBaseSticky extends BlockPistonBase {
                 }
             }
         }
-        if(!pulledMoving && retractId > 0 &&
+        Block<?> retractedBlock = Blocks.getBlock(retractId);
+        if(!pulledMoving && retractedBlock != null &&
             isPushable(retractId, world, x1, y1, z1, false) &&
-            (Blocks.blocksList[retractId].getPistonPushReaction(world, x1, y1, z1) == Material.PISTON_PUSHABLE || (Blocks.getBlock(retractId) instanceof BlockPistonBase)))
+            (retractedBlock.getPistonPushReaction(world, x1, y1, z1) == Material.PISTON_PUSHABLE || (retractedBlock.getLogic() instanceof BlockLogicPistonBase)))
         {
             if (!(retractEntity instanceof TileEntityMovingPistonBlock)) {
                 world.removeBlockTileEntity(x1, y1, z1);
@@ -61,8 +62,8 @@ public class BlockPistonBaseSticky extends BlockPistonBase {
             x += direction.getOffsetX();
             y += direction.getOffsetY();
             z += direction.getOffsetZ();
-            world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id, retactMeta);
-            world.replaceBlockTileEntity(x, y, z, BlockPistonMoving.createTileEntity(retractId, retactMeta, retractEntity, direction, false, false));
+            world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id(), retactMeta);
+            world.replaceBlockTileEntity(x, y, z, BlockLogicPistonMoving.createTileEntity(retractId, retactMeta, retractEntity, direction, false, false));
             world.notifyBlockChange(x1, y1, z1, 0);
         } else
         if(!pulledMoving)
@@ -73,7 +74,7 @@ public class BlockPistonBaseSticky extends BlockPistonBase {
     }
     @Override
     public void createPistonHeadAt(World world, int x, int y, int z, int data, Direction direction) {
-        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id,  BlockPistonHead.setPistonType(BlockPistonHead.TYPE_STICKY, direction.getId()));
-        world.replaceBlockTileEntity(x, y, z, BlockPistonMoving.createTileEntity(Blocks.PISTON_HEAD.id, BlockPistonHead.setPistonType(BlockPistonHead.TYPE_STICKY, direction.getId()), null, direction, true, false));
+        world.setBlockAndMetadata(x, y, z, Blocks.PISTON_MOVING.id(),  BlockLogicPistonHead.setPistonType(BlockLogicPistonHead.TYPE_STICKY, direction.getId()));
+        world.replaceBlockTileEntity(x, y, z, BlockLogicPistonMoving.createTileEntity(Blocks.PISTON_HEAD.id(), BlockLogicPistonHead.setPistonType(BlockLogicPistonHead.TYPE_STICKY, direction.getId()), null, direction, true, false));
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonHead.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonHead.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonHead.java
rename to game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonHead.java
index 6a6ca3fe7..8d031144e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonHead.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonHead.java
@@ -2,10 +2,11 @@ package net.minecraft.core.block.piston;
 
 import java.util.ArrayList;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Direction;
@@ -14,7 +15,7 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 
-public class BlockPistonHead extends Block
+public class BlockLogicPistonHead extends BlockLogic
 {
     public static final int MASK_DIRECTION = 0b0000_0111;
     public static final int MASK_TYPE = 0b1111_1000;
@@ -23,10 +24,10 @@ public class BlockPistonHead extends Block
     public static final int TYPE_STEEL = 2;
 
     private final double headThickness;
-    public BlockPistonHead(String key, String namespaceId, int id, double headThickness)
+    public BlockLogicPistonHead(Block<?> block, double headThickness)
     {
-        super(key, namespaceId, id, Material.piston);
-        withHardness(0.5F);
+        super(block, Material.piston);
+        block.withHardness(0.5F);
         this.headThickness = headThickness;
     }
 
@@ -42,11 +43,11 @@ public class BlockPistonHead extends Block
         int x2 = x + orientation.getOffsetX();
         int y2 = y + orientation.getOffsetY();
         int z2 = z + orientation.getOffsetZ();
-        Block block = world.getBlock(x2, y2, z2);
-        if(block instanceof BlockPistonBase)
+        Block<?> block = world.getBlock(x2, y2, z2);
+        if(block != null && block.getLogic() instanceof BlockLogicPistonBase)
         {
             int data2 = world.getBlockMetadata(x2, y2, z2);
-            if(BlockPistonBase.isPowered(data2))
+            if(BlockLogicPistonBase.isPowered(data2))
             {
                 block.dropBlockWithCause(world, EnumDropCause.PROPER_TOOL, x2, y2, z2, data2, null, null);
                 world.setBlockWithNotify(x2, y2, z2, 0);
@@ -139,8 +140,8 @@ public class BlockPistonHead extends Block
         if(direction == Direction.NONE) {
         	return;
         }
-        Block block = world.getBlock(x - direction.getOffsetX(), y - direction.getOffsetY(), z - direction.getOffsetZ());
-        if (block instanceof BlockPistonBase) {
+        Block<?> block = world.getBlock(x - direction.getOffsetX(), y - direction.getOffsetY(), z - direction.getOffsetZ());
+        if (block != null && block.getLogic() instanceof BlockLogicPistonBase) {
             block.onNeighborBlockChange(world, x - direction.getOffsetX(), y - direction.getOffsetY(), z - direction.getOffsetZ(), blockId);
         } else {
             world.setBlockWithNotify(x, y, z, 0);
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonMoving.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java
similarity index 91%
rename from game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonMoving.java
rename to game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java
index 8f2887ba2..8d51ad975 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockPistonMoving.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.block.piston;
 
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockTileEntity;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
@@ -15,18 +15,13 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 import org.jetbrains.annotations.Nullable;
 
-public class BlockPistonMoving extends BlockTileEntity
+public class BlockLogicPistonMoving extends BlockLogic
 {
-    public BlockPistonMoving(String key, String namespaceId, int id)
+    public BlockLogicPistonMoving(Block<?> container)
     {
-        super(key, namespaceId, id, Material.piston);
-        withHardness(-1F);
-    }
-
-    @Override
-	protected TileEntity getNewBlockEntity()
-    {
-        return null;
+        super(container, Material.piston);
+        container.withHardness(-1F);
+        container.withEntity(null);
     }
 
     @Override
@@ -144,8 +139,8 @@ public class BlockPistonMoving extends BlockTileEntity
         TileEntityMovingPistonBlock pistonBlockEntity = getBlockEntity(world, x, y, z);
         if(pistonBlockEntity != null)
         {
-            Block block = Blocks.blocksList[pistonBlockEntity.getMovedId()];
-            if(block == null || block == this)
+            Block<?> block = Blocks.blocksList[pistonBlockEntity.getMovedId()];
+            if(block == null || block == this.block)
             {
                 return getBlockBoundsFromState(world, x, y, z);
             }
@@ -164,12 +159,12 @@ public class BlockPistonMoving extends BlockTileEntity
             otherBounds.minZ - direction.getOffsetZ() * f,
             otherBounds.maxZ - direction.getOffsetZ() * f);
         }
-        return getBlockBoundsFromState(world, x, y, z);
+        return super.getBlockBoundsFromState(world, x, y, z);
     }
 
     public AABB getCollisionShapeFromTileEntity(WorldSource world, int x, int y, int z, int blockID, float directionStretch, Direction direction)
     {
-        if(blockID == 0 || blockID == id)
+        if(blockID == 0 || blockID == block.id())
         {
             return null;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
index d42b85a25..f2e3b4510 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
@@ -1,10 +1,9 @@
 package net.minecraft.core.block.piston;
 
-import net.minecraft.core.block.BlockTileEntity;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityDispatcher;
-import net.minecraft.core.entity.Entity;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.entity.Entity;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.AABB;
@@ -124,7 +123,7 @@ public class TileEntityMovingPistonBlock extends TileEntity
         {
             stretch = 1.0F - stretch;
         }
-        AABB aabb = ((BlockPistonMoving) Blocks.PISTON_MOVING).getCollisionShapeFromTileEntity(worldObj, x, y, z, movedId, stretch, direction);
+        AABB aabb = Blocks.PISTON_MOVING.getLogic().getCollisionShapeFromTileEntity(worldObj, x, y, z, movedId, stretch, direction);
         if (aabb == null) return;
 
         List<Entity> list = worldObj.getEntitiesWithinAABBExcludingEntity(null, aabb);
@@ -144,7 +143,7 @@ public class TileEntityMovingPistonBlock extends TileEntity
         progressO = progress = 1.0F;
         worldObj.removeBlockTileEntity(x, y, z);
         invalidate();
-        if(worldObj.getBlockId(x, y, z) == Blocks.PISTON_MOVING.id) {
+        if(worldObj.getBlockId(x, y, z) == Blocks.PISTON_MOVING.id()) {
             worldObj.setBlockAndMetadataRaw(x, y, z, movedId, movedData);
             if (movedEntity != null) {
                 TileEntity oldEnt = worldObj.getBlockEntity(x, y, z);
@@ -158,9 +157,9 @@ public class TileEntityMovingPistonBlock extends TileEntity
                 worldObj.replaceBlockTileEntity(x, y, z, movedEntity);
             }
             if (movedId != 0) {
-                BlockTileEntity.createNewEntityOnPlace = false;
+                Block.disableNormalEntityLogic = true;
                 Blocks.blocksList[movedId].onBlockPlacedByWorld(worldObj, x, y, z);
-                BlockTileEntity.createNewEntityOnPlace = true;
+                Block.disableNormalEntityLogic = false;
             }
             assert movedEntity == null || worldObj.getBlockEntity(x, y, z) == movedEntity : "Piston failed to actually move entity!";
             worldObj.notifyBlockChange(x, y, z, movedId);
diff --git a/game/core/src/main/java/net/minecraft/core/block/support/ISupportable.java b/game/core/src/main/java/net/minecraft/core/block/support/ISupportable.java
index b472066d1..f7fcb3828 100644
--- a/game/core/src/main/java/net/minecraft/core/block/support/ISupportable.java
+++ b/game/core/src/main/java/net/minecraft/core/block/support/ISupportable.java
@@ -8,7 +8,7 @@ public interface ISupportable {
     ISupport getSupportConstraint(final World world, final int x, final int y, final int z, final Side side);
 
     default boolean isSupported(final World world, final int x, final int y, final int z, final Side side) {
-        final Block supportingBlock = world.getBlock(x, y, z);
+        final Block<?> supportingBlock = world.getBlock(x, y, z);
         if (supportingBlock == null) {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/block/tag/BlockTags.java b/game/core/src/main/java/net/minecraft/core/block/tag/BlockTags.java
index 1ff5af05f..790e9c36f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/tag/BlockTags.java
+++ b/game/core/src/main/java/net/minecraft/core/block/tag/BlockTags.java
@@ -1,17 +1,17 @@
 package net.minecraft.core.block.tag;
 
 import com.mojang.logging.LogUtils;
+import net.minecraft.core.block.BlockLogicCactus;
+import net.minecraft.core.block.BlockLogicFence;
+import net.minecraft.core.block.BlockLogicFenceChainlink;
+import net.minecraft.core.block.BlockLogicFlower;
+import net.minecraft.core.block.BlockLogicFire;
+import net.minecraft.core.block.BlockLogicFluid;
+import net.minecraft.core.block.BlockLogicLanternFirefly;
+import net.minecraft.core.block.BlockLogicJar;
+import net.minecraft.core.block.BlockLogicSugarcane;
+import net.minecraft.core.block.BlockLogicTallGrass;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockCactus;
-import net.minecraft.core.block.BlockFence;
-import net.minecraft.core.block.BlockFenceChainlink;
-import net.minecraft.core.block.BlockFlower;
-import net.minecraft.core.block.BlockFire;
-import net.minecraft.core.block.BlockFluid;
-import net.minecraft.core.block.BlockLanternFirefly;
-import net.minecraft.core.block.BlockJar;
-import net.minecraft.core.block.BlockSugarcane;
-import net.minecraft.core.block.BlockTallGrass;
 import net.minecraft.core.data.tag.Tag;
 import net.minecraft.core.entity.animal.MobFireflyCluster;
 import net.minecraft.core.entity.monster.MobZombiePig;
@@ -30,7 +30,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Holds all the tags that can be applied to {@link net.minecraft.core.block.Block Block}.
+ * Holds all the tags that can be applied to {@link Block Block}.
  */
 public abstract class BlockTags
 {
@@ -38,146 +38,146 @@ public abstract class BlockTags
     /**
      * block can be mined by {@link ItemToolPickaxe ItemToolPickaxe}.
      */
-    public static Tag<Block> MINEABLE_BY_PICKAXE = Tag.of("mineable_by_pickaxe");
+    public static Tag<Block<?>> MINEABLE_BY_PICKAXE = Tag.of("mineable_by_pickaxe");
     /**
      * block can be mined by {@link ItemToolAxe ItemToolAxe}.
      */
-    public static Tag<Block> MINEABLE_BY_AXE = Tag.of("mineable_by_axe");
+    public static Tag<Block<?>> MINEABLE_BY_AXE = Tag.of("mineable_by_axe");
     /**
      * block can be mined by {@link ItemToolShovel ItemToolShovel}.
      */
-    public static Tag<Block> MINEABLE_BY_SHOVEL = Tag.of("mineable_by_shovel");
+    public static Tag<Block<?>> MINEABLE_BY_SHOVEL = Tag.of("mineable_by_shovel");
     /**
      * block can be mined by {@link ItemToolHoe ItemToolHoe}.
      */
-    public static Tag<Block> MINEABLE_BY_HOE = Tag.of("mineable_by_hoe");
+    public static Tag<Block<?>> MINEABLE_BY_HOE = Tag.of("mineable_by_hoe");
     /**
      * block can be mined by {@link ItemToolSword ItemToolSword}.
      */
-    public static Tag<Block> MINEABLE_BY_SWORD = Tag.of("mineable_by_sword");
+    public static Tag<Block<?>> MINEABLE_BY_SWORD = Tag.of("mineable_by_sword");
     /**
      * block can be mined by {@link ItemToolShears ItemShears}.
      */
-    public static Tag<Block> MINEABLE_BY_SHEARS = Tag.of("mineable_by_shears");
+    public static Tag<Block<?>> MINEABLE_BY_SHEARS = Tag.of("mineable_by_shears");
     /**
      * derived block has the properties of water.
      */
-    public static Tag<Block> IS_WATER = Tag.of("is_water");
+    public static Tag<Block<?>> IS_WATER = Tag.of("is_water");
     /**
      * derived block has the properties of lava.
      */
-    public static Tag<Block> IS_LAVA = Tag.of("is_lava");
+    public static Tag<Block<?>> IS_LAVA = Tag.of("is_lava");
     /**
-     * {@link BlockFlower BlockFlower}-derived blocks can be placed on this block.
+     * {@link BlockLogicFlower BlockFlower}-derived blocks can be placed on this block.
      */
-    public static Tag<Block> GROWS_FLOWERS = Tag.of("grows_flowers");
+    public static Tag<Block<?>> GROWS_FLOWERS = Tag.of("grows_flowers");
     /**
-     * {@link BlockSugarcane BlockSugarcane} can be placed on this block.
+     * {@link BlockLogicSugarcane BlockSugarcane} can be placed on this block.
      */
-    public static Tag<Block> GROWS_SUGAR_CANE = Tag.of("grows_sugar_cane");
+    public static Tag<Block<?>> GROWS_SUGAR_CANE = Tag.of("grows_sugar_cane");
     /**
-     * {@link BlockCactus BlockCactus} can be placed on this block.
+     * {@link BlockLogicCactus BlockCactus} can be placed on this block.
      */
-    public static Tag<Block> GROWS_CACTI = Tag.of("grows_cacti");
+    public static Tag<Block<?>> GROWS_CACTI = Tag.of("grows_cacti");
     /**
      * {@link net.minecraft.core.world.generate.feature.tree.WorldFeatureTree WorldFeatureTree} and its variations can be placed on this block.
      */
-    public static Tag<Block> GROWS_TREES = Tag.of("grows_trees");
-    public static Tag<Block> GROWS_SPINIFEX = Tag.of("grows_spinifex");
+    public static Tag<Block<?>> GROWS_TREES = Tag.of("grows_trees");
+    public static Tag<Block<?>> GROWS_SPINIFEX = Tag.of("grows_spinifex");
     /**
-     * This block is destroyed when {@link BlockFluid BlockFluid}-derived blocks try to move into its space.
+     * This block is destroyed when {@link BlockLogicFluid BlockFluid}-derived blocks try to move into its space.
      */
-    public static Tag<Block> BROKEN_BY_FLUIDS = Tag.of("broken_by_fluids");
+    public static Tag<Block<?>> BROKEN_BY_FLUIDS = Tag.of("broken_by_fluids");
     /**
-     * The block can have other blocks placed "into" it, like how {@link BlockTallGrass BlockTallGrass} behaves.
+     * The block can have other blocks placed "into" it, like how {@link BlockLogicTallGrass BlockTallGrass} behaves.
      */
-    public static Tag<Block> PLACE_OVERWRITES = Tag.of("place_overwrites");
+    public static Tag<Block<?>> PLACE_OVERWRITES = Tag.of("place_overwrites");
     /**
      * Passive mobs can spawn on this block.
      */
-    public static Tag<Block> PASSIVE_MOBS_SPAWN = Tag.of("passive_mobs_spawn");
+    public static Tag<Block<?>> PASSIVE_MOBS_SPAWN = Tag.of("passive_mobs_spawn");
     /**
      * {@link MobFireflyCluster MobFireflyCluster} can spawn on this block.
      */
-    public static Tag<Block> FIREFLIES_CAN_SPAWN = Tag.of("fireflies_can_spawn");
+    public static Tag<Block<?>> FIREFLIES_CAN_SPAWN = Tag.of("fireflies_can_spawn");
     /**
-     * {@link BlockFence BlockFence} visually connects to this block.
+     * {@link BlockLogicFence BlockFence} visually connects to this block.
      */
-    public static Tag<Block> FENCES_CONNECT = Tag.of("fences_connect");
+    public static Tag<Block<?>> FENCES_CONNECT = Tag.of("fences_connect");
     /**
      * This block does <b>not</b> appear in the creative menu.
      */
-    public static Tag<Block> NOT_IN_CREATIVE_MENU = Tag.of("not_in_creative_menu");
+    public static Tag<Block<?>> NOT_IN_CREATIVE_MENU = Tag.of("not_in_creative_menu");
     /**
      * This block drops as if using a silk touch tool when broken by {@link ItemToolShears ItemShears}.
      */
-    public static Tag<Block> SHEARS_DO_SILK_TOUCH = Tag.of("shears_do_silk_touch");
+    public static Tag<Block<?>> SHEARS_DO_SILK_TOUCH = Tag.of("shears_do_silk_touch");
     /**
      * This block can be skated on using {@link net.minecraft.core.item.Items#ARMOR_BOOTS_ICESKATES ice skates}.
      */
-    public static Tag<Block> SKATEABLE = Tag.of("skateable");
+    public static Tag<Block<?>> SKATEABLE = Tag.of("skateable");
     /**
      * Detects grass surface blocks so that {@link CavesLargeFeature MapGenCaves} can replace any exposed dirt with grass once it has finished generating a surface cave.
      */
-    public static Tag<Block> CAVE_GEN_REPLACES_SURFACE = Tag.of("cave_gen_replaces_surface");
+    public static Tag<Block<?>> CAVE_GEN_REPLACES_SURFACE = Tag.of("cave_gen_replaces_surface");
     /**
      * Determines which blocks {@link CavesLargeFeature MapGenCaves} can cut through
      */
-    public static Tag<Block> CAVES_CUT_THROUGH = Tag.of("caves_cut_through");
+    public static Tag<Block<?>> CAVES_CUT_THROUGH = Tag.of("caves_cut_through");
     /**
-     * Blocks such as {@link BlockLanternFirefly BlockLanternFirefly} can hang off this block.
+     * Blocks such as {@link BlockLogicLanternFirefly BlockLanternFirefly} can hang off this block.
      */
-    public static Tag<Block> CAN_HANG_OFF = Tag.of("can_hang_off");
+    public static Tag<Block<?>> CAN_HANG_OFF = Tag.of("can_hang_off");
     /**
      * Blocks like snow layers play their own sound when walking in them, instead of the sound of the block below
      */
-    public static Tag<Block> OVERRIDE_STEPSOUND = Tag.of("override_stepsound");
+    public static Tag<Block<?>> OVERRIDE_STEPSOUND = Tag.of("override_stepsound");
     /**
-     * {@link BlockFenceChainlink BlockFenceChainlink} visually connects to this block.
+     * {@link BlockLogicFenceChainlink BlockFenceChainlink} visually connects to this block.
      */
-    public static Tag<Block> CHAINLINK_FENCES_CONNECT = Tag.of("chainlink_fences_connect");
+    public static Tag<Block<?>> CHAINLINK_FENCES_CONNECT = Tag.of("chainlink_fences_connect");
     /**
      * Prevent mobs from spawning inside these blocks. Used for blocks with no collision like rails and redstone components
      */
-    public static Tag<Block> PREVENT_MOB_SPAWNS = Tag.of("prevent_mob_spawns");
+    public static Tag<Block<?>> PREVENT_MOB_SPAWNS = Tag.of("prevent_mob_spawns");
     /**
-     * Block can be planted inside a {@link BlockJar JarBlock}
+     * Block can be planted inside a {@link BlockLogicJar JarBlock}
      */
-    public static Tag<Block> PLANTABLE_IN_JAR = Tag.of("plantable_in_jar");
+    public static Tag<Block<?>> PLANTABLE_IN_JAR = Tag.of("plantable_in_jar");
     /**
-     * Block allows fire to burn forever on it {@link BlockFire BlockFire}
+     * Block allows fire to burn forever on it {@link BlockLogicFire BlockFire}
      */
-    public static Tag<Block> INFINITE_BURN = Tag.of("infinite_burn");
+    public static Tag<Block<?>> INFINITE_BURN = Tag.of("infinite_burn");
     /**
      * Block is broken on contact with an {@link EntityBoat EntityBoat}
      */
-    public static Tag<Block> BOAT_BREAKS = Tag.of("boat_breaks");
+    public static Tag<Block<?>> BOAT_BREAKS = Tag.of("boat_breaks");
     /**
      * Block extends the range of a motion sensor's sight.
      */
-    public static Tag<Block> EXTENDS_MOTION_SENSOR_RANGE = Tag.of("extends_motion_sensor_range");
+    public static Tag<Block<?>> EXTENDS_MOTION_SENSOR_RANGE = Tag.of("extends_motion_sensor_range");
     /**
      * When broken, items go into the player's inventory immediately instead of being dropped
      */
-    public static Tag<Block> INSTANT_PICKUP = Tag.of("instant_pickup");
+    public static Tag<Block<?>> INSTANT_PICKUP = Tag.of("instant_pickup");
     /**
      * Sheep will follow the player if they are holding this block.
      */
-    public static Tag<Block> SHEEPS_FAVOURITE_BLOCK = Tag.of("sheeps_favourite_block");
+    public static Tag<Block<?>> SHEEPS_FAVOURITE_BLOCK = Tag.of("sheeps_favourite_block");
     /**
      * Pigs will follow the player if they are holding this block.
      */
-    public static Tag<Block> PIGS_FAVOURITE_BLOCK = Tag.of("pigs_favourite_block");
+    public static Tag<Block<?>> PIGS_FAVOURITE_BLOCK = Tag.of("pigs_favourite_block");
     /**
      * Nether mobs can spawn on this block {@link MobZombiePig MobZombiePig}}.
      */
-    public static Tag<Block> NETHER_MOBS_SPAWN = Tag.of("nether_mobs_spawn");
+    public static Tag<Block<?>> NETHER_MOBS_SPAWN = Tag.of("nether_mobs_spawn");
     /**
      * Will drop block when piston extends into it
      */
-    public static Tag<Block> PISTON_CRUSHING = Tag.of("piston_crushing");
+    public static Tag<Block<?>> PISTON_CRUSHING = Tag.of("piston_crushing");
 
-    public static List<Tag<Block>> TAG_LIST;
+    public static List<Tag<Block<?>>> TAG_LIST;
 
     static
     {
@@ -189,7 +189,7 @@ public abstract class BlockTags
             {
                 try
                 {
-                    TAG_LIST.add((Tag<Block>)field.get(null));
+                    TAG_LIST.add((Tag<Block<?>>)field.get(null));
                 }
                 catch (Exception e)
                 {
diff --git a/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnace.java b/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnace.java
index 312b89c88..f8250a653 100644
--- a/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnace.java
+++ b/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnace.java
@@ -16,50 +16,50 @@ public class LookupFuelFurnace {
 	}
 
 	protected void register() {
-		addFuelEntry(Blocks.PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.PLANKS_OAK_PAINTED.id, 300);
-		addFuelEntry(Blocks.STAIRS_PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.STAIRS_PLANKS_PAINTED.id, 300);
-		addFuelEntry(Blocks.SLAB_PLANKS_OAK.id, 150);
-		addFuelEntry(Blocks.SLAB_PLANKS_PAINTED.id, 150);
-		addFuelEntry(Blocks.FENCE_PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.FENCE_PLANKS_OAK_PAINTED.id, 300);
-		addFuelEntry(Blocks.FENCE_GATE_PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id, 300);
-		addFuelEntry(Blocks.LADDER_OAK.id, 300);
-		addFuelEntry(Blocks.BOOKSHELF_PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.CHEST_PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.CHEST_PLANKS_OAK_PAINTED.id, 300);
-		addFuelEntry(Blocks.WORKBENCH.id, 300);
-		addFuelEntry(Blocks.PRESSURE_PLATE_PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.TRAPDOOR_PLANKS_OAK.id, 300);
-		addFuelEntry(Blocks.TRAPDOOR_PLANKS_PAINTED.id, 300);
-
-		addFuelEntry(Blocks.LOG_OAK.id, 300);
-		addFuelEntry(Blocks.LOG_BIRCH.id, 300);
-		addFuelEntry(Blocks.LOG_PINE.id, 300);
-		addFuelEntry(Blocks.LOG_CHERRY.id, 300);
-		addFuelEntry(Blocks.LOG_OAK_MOSSY.id, 300);
-		addFuelEntry(Blocks.LOG_EUCALYPTUS.id, 300);
-		addFuelEntry(Blocks.LOG_THORN.id, 300);
-		addFuelEntry(Blocks.LOG_PALM.id, 300);
-
-		addFuelEntry(Blocks.SAPLING_OAK.id, 100);
-		addFuelEntry(Blocks.SAPLING_PINE.id, 100);
-		addFuelEntry(Blocks.SAPLING_BIRCH.id, 100);
-		addFuelEntry(Blocks.SAPLING_CHERRY.id, 100);
-		addFuelEntry(Blocks.SAPLING_EUCALYPTUS.id, 100);
-		addFuelEntry(Blocks.SAPLING_SHRUB.id, 100);
-		addFuelEntry(Blocks.SAPLING_OAK_RETRO.id, 100);
-		addFuelEntry(Blocks.SAPLING_CACAO.id, 100);
-		addFuelEntry(Blocks.SAPLING_THORN.id, 100);
-		addFuelEntry(Blocks.SAPLING_PALM.id, 100);
-		addFuelEntry(Blocks.DEADBUSH.id, 100);
-		addFuelEntry(Blocks.SPINIFEX.id, 100);
-
-		addFuelEntry(Blocks.BLOCK_COAL.id, 12800);
-		addFuelEntry(Blocks.BLOCK_CHARCOAL.id, 12800);
-		addFuelEntry(Blocks.BLOCK_NETHER_COAL.id, 25600);
+		addFuelEntry(Blocks.PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.PLANKS_OAK_PAINTED.id(), 300);
+		addFuelEntry(Blocks.STAIRS_PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.STAIRS_PLANKS_PAINTED.id(), 300);
+		addFuelEntry(Blocks.SLAB_PLANKS_OAK.id(), 150);
+		addFuelEntry(Blocks.SLAB_PLANKS_PAINTED.id(), 150);
+		addFuelEntry(Blocks.FENCE_PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.FENCE_PLANKS_OAK_PAINTED.id(), 300);
+		addFuelEntry(Blocks.FENCE_GATE_PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id(), 300);
+		addFuelEntry(Blocks.LADDER_OAK.id(), 300);
+		addFuelEntry(Blocks.BOOKSHELF_PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.CHEST_PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.CHEST_PLANKS_OAK_PAINTED.id(), 300);
+		addFuelEntry(Blocks.WORKBENCH.id(), 300);
+		addFuelEntry(Blocks.PRESSURE_PLATE_PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.TRAPDOOR_PLANKS_OAK.id(), 300);
+		addFuelEntry(Blocks.TRAPDOOR_PLANKS_PAINTED.id(), 300);
+
+		addFuelEntry(Blocks.LOG_OAK.id(), 300);
+		addFuelEntry(Blocks.LOG_BIRCH.id(), 300);
+		addFuelEntry(Blocks.LOG_PINE.id(), 300);
+		addFuelEntry(Blocks.LOG_CHERRY.id(), 300);
+		addFuelEntry(Blocks.LOG_OAK_MOSSY.id(), 300);
+		addFuelEntry(Blocks.LOG_EUCALYPTUS.id(), 300);
+		addFuelEntry(Blocks.LOG_THORN.id(), 300);
+		addFuelEntry(Blocks.LOG_PALM.id(), 300);
+
+		addFuelEntry(Blocks.SAPLING_OAK.id(), 100);
+		addFuelEntry(Blocks.SAPLING_PINE.id(), 100);
+		addFuelEntry(Blocks.SAPLING_BIRCH.id(), 100);
+		addFuelEntry(Blocks.SAPLING_CHERRY.id(), 100);
+		addFuelEntry(Blocks.SAPLING_EUCALYPTUS.id(), 100);
+		addFuelEntry(Blocks.SAPLING_SHRUB.id(), 100);
+		addFuelEntry(Blocks.SAPLING_OAK_RETRO.id(), 100);
+		addFuelEntry(Blocks.SAPLING_CACAO.id(), 100);
+		addFuelEntry(Blocks.SAPLING_THORN.id(), 100);
+		addFuelEntry(Blocks.SAPLING_PALM.id(), 100);
+		addFuelEntry(Blocks.DEADBUSH.id(), 100);
+		addFuelEntry(Blocks.SPINIFEX.id(), 100);
+
+		addFuelEntry(Blocks.BLOCK_COAL.id(), 12800);
+		addFuelEntry(Blocks.BLOCK_CHARCOAL.id(), 12800);
+		addFuelEntry(Blocks.BLOCK_NETHER_COAL.id(), 25600);
 
 		addFuelEntry(Items.STICK.id, 100);
 
diff --git a/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnaceBlast.java b/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnaceBlast.java
index d47da7159..d79297b77 100644
--- a/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnaceBlast.java
+++ b/game/core/src/main/java/net/minecraft/core/crafting/LookupFuelFurnaceBlast.java
@@ -13,8 +13,8 @@ public class LookupFuelFurnaceBlast extends LookupFuelFurnace {
 
 	@Override
 	protected void register() {
-		addFuelEntry(Blocks.BLOCK_NETHER_COAL.id, 12800);
-		addFuelEntry(Blocks.BLOCK_OLIVINE.id, 1600);
+		addFuelEntry(Blocks.BLOCK_NETHER_COAL.id(), 12800);
+		addFuelEntry(Blocks.BLOCK_OLIVINE.id(), 1600);
 
 		addFuelEntry(Items.NETHERCOAL.id, 1600);
 		addFuelEntry(Items.OLIVINE.id, 200);
diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/TreecapitatorHelper.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/TreecapitatorHelper.java
index e795341fe..c2442ba8e 100644
--- a/game/core/src/main/java/net/minecraft/core/data/gamerule/TreecapitatorHelper.java
+++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/TreecapitatorHelper.java
@@ -6,8 +6,8 @@ import java.util.List;
 import java.util.Set;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLeavesBase;
-import net.minecraft.core.block.BlockLog;
+import net.minecraft.core.block.BlockLogicLeavesBase;
+import net.minecraft.core.block.BlockLogicLog;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
@@ -133,12 +133,10 @@ public class TreecapitatorHelper {
 		// Break leaves
 		for(int i=0; i < allBlocksList.size(); i++) {
 			ChunkPosition pos = allBlocksList.get(i);
-			Block block = world.getBlock(pos.x, pos.y, pos.z);
-			if(block instanceof BlockLeavesBase) {
-				BlockLeavesBase blockLeaves = (BlockLeavesBase) block;
-				
+			Block<?> block = world.getBlock(pos.x, pos.y, pos.z);
+			if(block != null && block.getLogic() instanceof BlockLogicLeavesBase) {
 				if(player.getGamemode().dropBlockOnBreak()) {
-					ItemStack[] drops = blockLeaves.getBreakResult(world, EnumDropCause.PROPER_TOOL, pos.x, pos.y, pos.z, world.getBlockMetadata(pos.x, pos.y, pos.z), null);
+					ItemStack[] drops = block.getBreakResult(world, EnumDropCause.PROPER_TOOL, pos.x, pos.y, pos.z, world.getBlockMetadata(pos.x, pos.y, pos.z), null);
 					if(itemList != null) {
 						itemList.addAll(drops);
 					}else {
@@ -196,7 +194,7 @@ public class TreecapitatorHelper {
 	}
 	
 	protected boolean breakBlock(ChunkPosition pos, boolean particle, ItemList itemList) {
-		Block block = world.getBlock(pos.x, pos.y, pos.z);
+		Block<?> block = world.getBlock(pos.x, pos.y, pos.z);
 		if(world.setBlockWithNotify(pos.x, pos.y, pos.z, 0)) {
 			int meta = world.getBlockMetadata(pos.x, pos.y, pos.z);
 			ItemStack[] drops = block.getBreakResult(world, EnumDropCause.PROPER_TOOL, pos.x, pos.y, pos.z, meta, null);
@@ -208,22 +206,22 @@ public class TreecapitatorHelper {
 				}	
 			}
 			if(particle) {
-				world.playBlockEvent(player, LevelListener.EVENT_BLOCK_BREAK, pos.x, pos.y, pos.z, block.id);
+				world.playBlockEvent(player, LevelListener.EVENT_BLOCK_BREAK, pos.x, pos.y, pos.z, block.id());
 			}
 			return true;
 		}
 		return false;
 	}
 	
-	protected boolean isLog(Block block) {
-		return block instanceof BlockLog;
+	protected boolean isLog(Block<?> block) {
+		return block != null && block.getLogic() instanceof BlockLogicLog;
 	}
 	
 	protected boolean isDecayableLeaf(ChunkPosition pos) {
-		Block block = world.getBlock(pos.x, pos.y, pos.z);
-		if(block instanceof BlockLeavesBase) {
+		Block<?> block = world.getBlock(pos.x, pos.y, pos.z);
+		if(block != null && block.getLogic() instanceof BlockLogicLeavesBase) {
 			int meta = world.getBlockMetadata(pos.x, pos.y, pos.z);
-			if(BlockLeavesBase.isPermanent(meta)) {
+			if(BlockLogicLeavesBase.isPermanent(meta)) {
 				return false;
 			}
 			
@@ -264,10 +262,10 @@ public class TreecapitatorHelper {
 			for (int offX = -range; offX <= range; offX++) {
 				for (int offY = -range; offY <= range; offY++) {
 					for (int offZ = -range; offZ <= range; offZ++) {
-						Block block = world.getBlock(x + offX, y + offY, z + offZ);
+						Block<?> block = world.getBlock(x + offX, y + offY, z + offZ);
 						if(isLog(block)) {
 							adjacentTreeBlocks[(offX + b) * a + (offY + b) * byte1 + (offZ + b)] = 0;
-						}else if(block instanceof BlockLeavesBase) {
+						}else if(block != null && block.getLogic() instanceof BlockLogicLeavesBase) {
 							adjacentTreeBlocks[(offX + b) * a + (offY + b) * byte1 + (offZ + b)] = -2;
 						} else {
 							adjacentTreeBlocks[(offX + b) * a + (offY + b) * byte1 + (offZ + b)] = -1;
diff --git a/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java b/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java
index 2540a7826..889b19ca9 100644
--- a/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java
+++ b/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java
@@ -138,7 +138,7 @@ public class Registries extends Registry<Registry<?>>
         ArrayList<ItemStack> list = new ArrayList<>();
         for (Object item : items) {
             if (item instanceof Block) {
-                list.add(new ItemStack((Block) item));
+                list.add(new ItemStack((Block<?>) item));
             } else if (item instanceof Item) {
                 list.add(new ItemStack((Item) item));
             } else if (item instanceof ItemStack) {
diff --git a/game/core/src/main/java/net/minecraft/core/data/registry/recipe/RecipeRegistry.java b/game/core/src/main/java/net/minecraft/core/data/registry/recipe/RecipeRegistry.java
index 736695519..daba7734f 100644
--- a/game/core/src/main/java/net/minecraft/core/data/registry/recipe/RecipeRegistry.java
+++ b/game/core/src/main/java/net/minecraft/core/data/registry/recipe/RecipeRegistry.java
@@ -214,7 +214,7 @@ public class RecipeRegistry extends Registry<RecipeNamespace> {
             } else
             if(aobj[i + 1] instanceof Block)
             {
-                recipeSymbol = new RecipeSymbol(character,new ItemStack((Block)aobj[i + 1]),null);
+                recipeSymbol = new RecipeSymbol(character,new ItemStack((Block<?>)aobj[i + 1]),null);
             } else
             if(aobj[i + 1] instanceof ItemStack)
             {
@@ -284,7 +284,7 @@ public class RecipeRegistry extends Registry<RecipeNamespace> {
             } else
             if(aobj[i + 1] instanceof Block)
             {
-                recipeSymbol = new RecipeSymbol(character,new ItemStack((Block)aobj[i + 1]),null);
+                recipeSymbol = new RecipeSymbol(character,new ItemStack((Block<?>)aobj[i + 1]),null);
             } else
             if(aobj[i + 1] instanceof ItemStack)
             {
@@ -348,7 +348,7 @@ public class RecipeRegistry extends Registry<RecipeNamespace> {
             }else if(obj instanceof Item) {
                 list.add(new RecipeSymbol('\0', new ItemStack((Item) obj),null));
             }else if(obj instanceof Block) {
-                list.add(new RecipeSymbol('\0', new ItemStack((Block) obj),null));
+                list.add(new RecipeSymbol('\0', new ItemStack((Block<?>) obj),null));
             } else if (obj instanceof String) {
                 list.add(new RecipeSymbol('\0', null, (String) obj));
             } else {
@@ -370,7 +370,7 @@ public class RecipeRegistry extends Registry<RecipeNamespace> {
         }else if(input instanceof Item) {
             symbol = new RecipeSymbol('\0', new ItemStack((Item) input),null);
         }else if(input instanceof Block) {
-            symbol = new RecipeSymbol('\0', new ItemStack((Block) input),null);
+            symbol = new RecipeSymbol('\0', new ItemStack((Block<?>) input),null);
         } else if (input instanceof String) {
             symbol = new RecipeSymbol('\0', null, (String) input);
         } else {
@@ -390,7 +390,7 @@ public class RecipeRegistry extends Registry<RecipeNamespace> {
         }else if(input instanceof Item) {
             symbol = new RecipeSymbol('\0', new ItemStack((Item) input),null);
         }else if(input instanceof Block) {
-            symbol = new RecipeSymbol('\0', new ItemStack((Block) input),null);
+            symbol = new RecipeSymbol('\0', new ItemStack((Block<?>) input),null);
         } else if (input instanceof String) {
             symbol = new RecipeSymbol('\0', null, (String) input);
         } else {
@@ -410,7 +410,7 @@ public class RecipeRegistry extends Registry<RecipeNamespace> {
         }else if(input instanceof Item) {
             symbol = new RecipeSymbol('\0', new ItemStack((Item) input),null);
         }else if(input instanceof Block) {
-            symbol = new RecipeSymbol('\0', new ItemStack((Block) input),null);
+            symbol = new RecipeSymbol('\0', new ItemStack((Block<?>) input),null);
         } else if (input instanceof String) {
             symbol = new RecipeSymbol('\0', null, (String) input);
         } else {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Entity.java b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
index 8f5c71d20..7bf09ecd0 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Entity.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
@@ -3,7 +3,7 @@ package net.minecraft.core.entity;
 import java.util.List;
 import java.util.Random;
 
-import net.minecraft.core.block.BlockFluid;
+import net.minecraft.core.block.BlockLogicFluid;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.DyeColor;
@@ -597,13 +597,13 @@ public abstract class Entity
             int blockX = MathHelper.floor(this.x);
             int blockY = MathHelper.floor(boundingBox.minY);
             int blockZ = MathHelper.floor(this.z);
-            
-            Block blockWalkedOn = null;
+
+            Block<?> blockWalkedOn = null;
 
             blockCheck: for (int x = blockX - 1; x <= blockX + 1; x++) {
                 for (int z = blockZ - 1; z <= blockZ + 1; z++) {
                     for (int y = blockY - 1; y < blockY + 1; y++) {
-                        Block block = world.getBlock(x, y, z);
+                        Block<?> block = world.getBlock(x, y, z);
                         if(block == null) {
                             continue;
                         }
@@ -624,7 +624,7 @@ public abstract class Entity
             
             // Check for snow layers
             int blockYUp = MathHelper.floor(boundingBox.maxY);
-            Block blockAbove = world.getBlock(blockX, blockYUp, blockZ);
+            Block<?> blockAbove = world.getBlock(blockX, blockYUp, blockZ);
             if(blockAbove != null && blockAbove.hasTag(BlockTags.OVERRIDE_STEPSOUND)) {
             	blockWalkedOn = blockAbove;
             	blockY = blockYUp;
@@ -780,9 +780,9 @@ public abstract class Entity
         int j = MathHelper.floor_float(MathHelper.floor(d));
         int k = MathHelper.floor(z);
         int l = world.getBlockId(i, j, k);
-        if(l != 0 && Blocks.blocksList[l].blockMaterial == material)
+        if(l != 0 && Blocks.blocksList[l].getMaterial() == material)
         {
-            float f = BlockFluid.getWaterVolume(world.getBlockMetadata(i, j, k)) - 0.2F;
+            float f = BlockLogicFluid.getWaterVolume(world.getBlockMetadata(i, j, k)) - 0.2F;
             float f1 = (float)(j + 1) - f;
             return d < (double)f1;
         } else
@@ -943,7 +943,7 @@ public abstract class Entity
         return true;
     }
 
-    public boolean collidesWithBlock(Block block, int metadata) {
+    public boolean collidesWithBlock(Block<?> block, int metadata) {
         return true;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
index 22a1a068d..953aa3d2e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.entity;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockSand;
+import net.minecraft.core.block.BlockLogicSand;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityDispatcher;
@@ -78,7 +78,7 @@ public class EntityFallingBlock extends Entity
         if (pushTime < 0.05f || (pushTime < 0.25 && onGround)){
             pushTime = 0;
         }
-        if (isOnFire() && carriedBlock.blockId == Blocks.TNT.id) {
+        if (isOnFire() && carriedBlock.blockId == Blocks.TNT.id()) {
             remove();
             EntityPrimedTNT entityPrimedTNT = new EntityPrimedTNT(world, x, y, z);
             entityPrimedTNT.xd = this.xd;
@@ -108,8 +108,8 @@ public class EntityFallingBlock extends Entity
             hasRemovedBlock = true;
         }
         if (onGround) {
-            Block selfBlock = carriedBlock.block();
-            Block blockBelow = world.getBlock(x, y - 1, z);
+            Block<?> selfBlock = carriedBlock.block();
+            Block<?> blockBelow = world.getBlock(x, y - 1, z);
             double friction = selfBlock.friction;
             friction *= blockBelow == null ? 0.98 : blockBelow.friction * 0.91f;
             xd *= friction;
@@ -125,7 +125,7 @@ public class EntityFallingBlock extends Entity
                 Entity rider = getPassenger();
                 ejectRider();
                 remove();
-                if((!world.canBlockBePlacedAt(carriedBlock.blockId, x, y, z, true, Side.TOP) || BlockSand.canFallBelow(world, x, y - 1, z) || !world.setBlock(x, y, z, carriedBlock.blockId)) && !world.isClientSide)
+                if((!world.canBlockBePlacedAt(carriedBlock.blockId, x, y, z, true, Side.TOP) || BlockLogicSand.canFallBelow(world, x, y - 1, z) || !world.setBlock(x, y, z, carriedBlock.blockId)) && !world.isClientSide)
                 {
                     if(hasRemovedBlock) {
                         drop();
@@ -164,7 +164,7 @@ public class EntityFallingBlock extends Entity
     }
 
     public void drop() {
-        Block block = carriedBlock.block();
+        Block<?> block = carriedBlock.block();
         if (block != null) {
             ItemStack[] drops = block.getBreakResult(world, EnumDropCause.SILK_TOUCH, carriedBlock.metadata, carriedBlock.entity);
             if (drops != null && drops.length > 0) {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java b/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
index 07c83dbfb..8d08c9732 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
@@ -196,7 +196,7 @@ public class EntityFishingBobber extends Entity
             }
         }
         if (isInGround()) {
-            if (world.getBlockId(xTile, yTile, zTile) == Blocks.ROPE.id) {
+            if (world.getBlockId(xTile, yTile, zTile) == Blocks.ROPE.id()) {
                 x = xTile + 0.5D;
                 y = yTile + 0.5D;
                 z = zTile + 0.5D;
@@ -219,7 +219,7 @@ public class EntityFishingBobber extends Entity
         if(clip != null)
         {
             nextPos = Vec3.getTempVec3(clip.location.x, clip.location.y, clip.location.z);
-            if (clip.hitType == HitResult.HitType.TILE && world.getBlockId(clip.x, clip.y, clip.z) == Blocks.ROPE.id) {
+            if (clip.hitType == HitResult.HitType.TILE && world.getBlockId(clip.x, clip.y, clip.z) == Blocks.ROPE.id()) {
                 setInGround(true);
                 xTile = clip.x;
                 yTile = clip.y;
@@ -305,7 +305,7 @@ public class EntityFishingBobber extends Entity
                     rainRate = 200;
                 }
 
-                if(world.getBlockId(MathHelper.floor(x), MathHelper.floor(y) + 1, MathHelper.floor(z)) == Blocks.ALGAE.id) {
+                if(world.getBlockId(MathHelper.floor(x), MathHelper.floor(y) + 1, MathHelper.floor(z)) == Blocks.ALGAE.id()) {
                     algaeRate = 100;
                 }
                 catchRate = (catchRate - rainRate) - algaeRate;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java b/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java
index 218c8ead2..cccec28aa 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java
@@ -6,8 +6,8 @@ import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicLog;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockLog;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemDiscMusic;
@@ -17,6 +17,7 @@ import net.minecraft.core.util.helper.DamageType;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 public class EntityItem extends Entity
 {
@@ -201,7 +202,8 @@ public class EntityItem extends Entity
 
 			if(item.stackSize < previousStackSize) {
 				if(item.itemID < 16384) {
-					if(Blocks.blocksList[item.itemID] instanceof BlockLog) {
+                    Block<?> b = Blocks.blocksList[item.itemID];
+					if(b != null && b.getLogic() instanceof BlockLogicLog) {
 						player.triggerAchievement(Achievements.MINE_WOOD);
 					}
 				}
@@ -214,7 +216,7 @@ public class EntityItem extends Entity
                 if(item.itemID == Items.NETHERCOAL.id) {
                     player.triggerAchievement(Achievements.GET_NETHERCOAL);
                 }
-				if(item.itemID == Blocks.ICE.id) {
+				if(item.itemID == Blocks.ICE.id()) {
 					player.triggerAchievement(Achievements.CRUSH_BLOCKS);
 				}
 				
@@ -262,26 +264,25 @@ public class EntityItem extends Entity
 
     public void clumpToNearbyStack() {
     	AABB boundingBox = this.bb.grow(0.5, 0.0, 0.5);
-    	List<Entity> entities = world.getEntitiesWithinAABB(EntityItem.class, boundingBox);
+    	List<@NotNull EntityItem> entities = world.getEntitiesWithinAABB(EntityItem.class, boundingBox);
     	
-    	for(Entity otherEntity : entities) {
-    		if(otherEntity == this || !(otherEntity instanceof EntityItem) || !otherEntity.isAlive() || !this.isAlive()) {
+    	for(EntityItem otherEntity : entities) {
+    		if(otherEntity == this || !otherEntity.isAlive() || !this.isAlive()) {
     			continue;
     		}
-    		EntityItem otherEntityItem = (EntityItem) otherEntity;
-    		
-    		ItemStack thisItemStack = this.item;
-    		ItemStack otherItemStack = otherEntityItem.item;
+
+            ItemStack thisItemStack = this.item;
+    		ItemStack otherItemStack = otherEntity.item;
     		
-    		if(this.item.canStackWith(otherEntityItem.item)) {
+    		if(this.item.canStackWith(otherEntity.item)) {
     			if(thisItemStack.stackSize + otherItemStack.stackSize > 64) {
     				continue;
     			}
     			
     			if(otherItemStack.stackSize > thisItemStack.stackSize) {
-    				combineItems(otherEntityItem, this);
+    				combineItems(otherEntity, this);
     			}else {
-    				combineItems(this, otherEntityItem);
+    				combineItems(this, otherEntity);
     			}
     		}
     	}
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
index 7eb092cea..037fa0d1e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
@@ -58,7 +58,7 @@ public class EntityLightning extends Entity
                     int k = MathHelper.floor(z);
                     if(world.getBlockId(i, j, k) == 0 && Blocks.FIRE.canPlaceBlockAt(world, i, j, k))
                     {
-                        world.setBlockWithNotify(i, j, k, Blocks.FIRE.id);
+                        world.setBlockWithNotify(i, j, k, Blocks.FIRE.id());
                     }
                 }
             }
@@ -90,7 +90,7 @@ public class EntityLightning extends Entity
             int i1 = MathHelper.floor(z);
             if(world.getBlockId(i, k, i1) == 0 && Blocks.FIRE.canPlaceBlockAt(world, i, k, i1))
             {
-                world.setBlockWithNotify(i, k, i1, Blocks.FIRE.id);
+                world.setBlockWithNotify(i, k, i1, Blocks.FIRE.id());
             }
             for(int j = 0; j < 4; j++)
             {
@@ -99,7 +99,7 @@ public class EntityLightning extends Entity
                 int k1 = (MathHelper.floor(z) + random.nextInt(3)) - 1;
                 if(world.getBlockId(l, j1, k1) == 0 && Blocks.FIRE.canPlaceBlockAt(world, l, j1, k1))
                 {
-                    world.setBlockWithNotify(l, j1, k1, Blocks.FIRE.id);
+                    world.setBlockWithNotify(l, j1, k1, Blocks.FIRE.id());
                 }
             }
         }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Mob.java b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
index b23d62aab..f0b2abdcc 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Mob.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
@@ -159,7 +159,6 @@ public abstract class Mob extends Entity
 
     @Override
 	public String getEntityTexture() {
-        SkinVariantList variantList = Global.accessor.getSkinVariantList();
         String basePath = String.format("/assets/%s/textures/entity/%s/", textureIdentifier.namespace, textureIdentifier.value);
         return basePath + getTextureReference() + ".png";
     }
@@ -652,7 +651,7 @@ public abstract class Mob extends Entity
         {
             return String.format("%s%s swam in lava.", name, deathMsgColor);
         }
-        if (world.getBlockId(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)) == Blocks.SPIKES.id)
+        if (world.getBlockId(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)) == Blocks.SPIKES.id())
         {
             return String.format("%s%s got impaled.", name, deathMsgColor);
         }
@@ -767,7 +766,7 @@ public abstract class Mob extends Entity
             int blockX = MathHelper.floor(x);
             int blockY = MathHelper.floor(y - heightOffset);
             int blockZ = MathHelper.floor(z);
-            Block b = world.getBlock(blockX, blockY, blockZ);
+            Block<?> b = world.getBlock(blockX, blockY, blockZ);
             float depth = 0.6f;
             if (b != null) {
                 depth = 1 - (float) b.getBlockBoundsFromState(world, blockX, blockY, blockZ).maxY;
@@ -910,7 +909,7 @@ public abstract class Mob extends Entity
         int i = MathHelper.floor(x);
         int j = MathHelper.floor(bb.minY);
         int k = MathHelper.floor(z);
-        Block block = world.getBlock(i, j, k);
+        Block<?> block = world.getBlock(i, j, k);
         return block != null && block.isClimbable(world, i, j, k);
     }
 
@@ -968,16 +967,16 @@ public abstract class Mob extends Entity
             newPosRotationIncrements--;
             setPos(d, d1, d2);
             setRot(yRot, xRot);
-            List list1 = world.getCubes(this, bb.getInsetBoundingBox(0.03125D, 0.0D, 0.03125D));
-            if(list1.size() > 0)
+            List<AABB> list1 = world.getCubes(this, bb.getInsetBoundingBox(0.03125D, 0.0D, 0.03125D));
+            if(!list1.isEmpty())
             {
                 double d4 = 0.0D;
                 for(int j = 0; j < list1.size(); j++)
                 {
-                    AABB axisalignedbb = (AABB)list1.get(j);
-                    if(axisalignedbb.maxY > d4)
+                    AABB aabb = list1.get(j);
+                    if(aabb.maxY > d4)
                     {
-                        d4 = axisalignedbb.maxY;
+                        d4 = aabb.maxY;
                     }
                 }
 
@@ -1017,12 +1016,12 @@ public abstract class Mob extends Entity
         moveForward *= 0.98F;
         randomYawVelocity *= 0.9F;
         moveEntityWithHeading(moveStrafing, moveForward);
-        List list = world.getEntitiesWithinAABBExcludingEntity(this, bb.grow(0.2D, 0.0D, 0.2D));
-        if(list != null && list.size() > 0)
+        List<Entity> list = world.getEntitiesWithinAABBExcludingEntity(this, bb.grow(0.2D, 0.0D, 0.2D));
+        if(list != null && !list.isEmpty())
         {
             for(int i = 0; i < list.size(); i++)
             {
-                Entity entity = (Entity)list.get(i);
+                Entity entity = list.get(i);
                 if(entity.isPushable())
                 {
                     entity.push(this);
@@ -1185,7 +1184,7 @@ public abstract class Mob extends Entity
         int blockX = MathHelper.floor(x);
         int blockY = MathHelper.floor(bb.minY);
         int blockZ = MathHelper.floor(z);
-        if(Block.hasTag(world.getBlockId(blockX, blockY, blockZ), BlockTags.PREVENT_MOB_SPAWNS)) {
+        if(Blocks.hasTag(world.getBlockId(blockX, blockY, blockZ), BlockTags.PREVENT_MOB_SPAWNS)) {
         	return false;
         }
         return world.checkIfAABBIsClear(bb) && world.getCubes(this, bb).size() == 0 && !world.getIsAnyLiquid(bb);
diff --git a/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java b/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java
index 538b5a8bc..9691b3cfb 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.entity;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java b/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
index 3b10a9791..b3cf3e964 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
@@ -141,13 +141,13 @@ public abstract class MobPathfinder extends Mob
     }
 
     protected Entity getClosestFireflyToEntity (int x, int y, int z, float radius){
-        List<Entity> nearbyFireflies = world.getEntitiesWithinAABB(MobFireflyCluster.class, AABB.getTemporaryBB(this.x, this.y, this.z, this.x + 1.0D, this.y + 1.0D, this.z + 1.0D).grow(radius, 4D, radius));
+        List<MobFireflyCluster> nearbyFireflies = world.getEntitiesWithinAABB(MobFireflyCluster.class, AABB.getTemporaryBB(this.x, this.y, this.z, this.x + 1.0D, this.y + 1.0D, this.z + 1.0D).grow(radius, 4D, radius));
 
         double closestDistance = -1D;
-        Entity cluster = null;
+        MobFireflyCluster cluster = null;
         for(int i = 0; i < nearbyFireflies.size(); i++)
         {
-            Entity clusterInList = nearbyFireflies.get(i);
+            MobFireflyCluster clusterInList = nearbyFireflies.get(i);
             double currentDistance = clusterInList.distanceToSqr(x, y, z);
             if((radius < 0.0D || currentDistance < radius * radius) && (closestDistance == -1D || currentDistance < closestDistance))
             {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java
index 28459fb84..65a54063d 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java
@@ -7,7 +7,6 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.world.World;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.season.Seasons;
 
@@ -60,7 +59,7 @@ public abstract class MobAnimal extends MobPathfinder
     @Override
 	protected float getBlockPathWeight(int x, int y, int z)
     {
-        if(world.getBlockId(x, y - 1, z) == Blocks.GRASS.id)
+        if(world.getBlockId(x, y - 1, z) == Blocks.GRASS.id())
         {
             return 10F;
         } else
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
index fa28fdcc4..e3b5637cd 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
@@ -1,7 +1,6 @@
 package net.minecraft.core.entity.animal;
 
 import com.mojang.nbt.CompoundTag;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
@@ -12,6 +11,7 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.biome.Biomes;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -360,7 +360,7 @@ public class MobFireflyCluster extends MobFlying
 	private void merge() {
 		slowUpdateCooldown = slowUpdateCooldownMax;
 		
-		List<Entity> nearbyFireflies = world.getEntitiesWithinAABB(getClass(), bb.grow(2, 2, 2));
+		List<@NotNull MobFireflyCluster> nearbyFireflies = world.getEntitiesWithinAABB(MobFireflyCluster.class, bb.grow(2, 2, 2));
 		int nearbyCount = nearbyFireflies.size();
 		
 		if(nearbyCount == 1) {
@@ -369,11 +369,10 @@ public class MobFireflyCluster extends MobFlying
 		}
 		
 		for(int i=0; i < nearbyCount; i++) {
-			Entity entity = nearbyFireflies.get(i);
-			if(entity == this || !(entity instanceof MobFireflyCluster)) {
+			MobFireflyCluster fireflyCluster = nearbyFireflies.get(i);
+			if(fireflyCluster == this) {
 				continue;
 			}
-			MobFireflyCluster fireflyCluster = (MobFireflyCluster) entity;
 			if(fireflyCluster.getColor() != this.getColor()) {
 				continue;
 			}
@@ -403,7 +402,7 @@ public class MobFireflyCluster extends MobFlying
 		setSizeBasedOnClusterSize(prevSize + 1);
 		setPos(x, y, z); // Update bounding box
 		
-		if(world.getCollidingSolidBlockBoundingBoxes(this, bb).size() == 0) {
+		if(world.getCollidingSolidBlockBoundingBoxes(this, bb).isEmpty()) {
 			setClusterSize(prevSize + 1);
 			return;
 		}
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
index b1e97986e..25fb24f0c 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
@@ -2,7 +2,6 @@ package net.minecraft.core.entity.animal;
 
 import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.achievement.Achievements;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.EntityLightning;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
index 110088d9f..77d962d46 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
@@ -50,7 +50,7 @@ public class MobSheep extends MobAnimal
         super.dropDeathItems();
         if(!getSheared())
         {
-            spawnAtLocation(new ItemStack(Blocks.WOOL.id, 1, getFleeceColor().blockMeta), 0.0F);
+            spawnAtLocation(new ItemStack(Blocks.WOOL.id(), 1, getFleeceColor().blockMeta), 0.0F);
         }
     }
     @Override
@@ -65,7 +65,7 @@ public class MobSheep extends MobAnimal
                     setSheared(true);
                     int count = 2 + random.nextInt(3);
                     for (int j = 0; j < count; j++) {
-                        EntityItem entityitem = spawnAtLocation(new ItemStack(Blocks.WOOL.id, 1, getFleeceColor().blockMeta), 1.0F);
+                        EntityItem entityitem = spawnAtLocation(new ItemStack(Blocks.WOOL.id(), 1, getFleeceColor().blockMeta), 1.0F);
                         entityitem.yd += random.nextFloat() * 0.05F;
                         entityitem.xd += (random.nextFloat() - random.nextFloat()) * 0.1F;
                         entityitem.zd += (random.nextFloat() - random.nextFloat()) * 0.1F;
@@ -87,7 +87,7 @@ public class MobSheep extends MobAnimal
                 setSheared(true);
                 int count = 2 + random.nextInt(3);
                 for (int j = 0; j < count; j++) {
-                    EntityItem entityItem = spawnAtLocation(new ItemStack(Blocks.WOOL.id, 1, getFleeceColor().blockMeta), 1.0F);
+                    EntityItem entityItem = spawnAtLocation(new ItemStack(Blocks.WOOL.id(), 1, getFleeceColor().blockMeta), 1.0F);
                     entityItem.yd += random.nextFloat() * 0.05F;
                     entityItem.xd += (random.nextFloat() - random.nextFloat()) * 0.1F;
                     entityItem.zd += (random.nextFloat() - random.nextFloat()) * 0.1F;
@@ -144,7 +144,7 @@ public class MobSheep extends MobAnimal
 			int blockX = MathHelper.floor(x);
 			int blockY = MathHelper.floor(y);
 			int blockZ = MathHelper.floor(z);
-			Block blockBelow = world.getBlock(blockX, blockY - 1, blockZ);
+            Block<?> blockBelow = world.getBlock(blockX, blockY - 1, blockZ);
 			
 			growthTimer = 0;
 			if (blockBelow == Blocks.GRASS || blockBelow == Blocks.GRASS_RETRO) {
@@ -161,7 +161,7 @@ public class MobSheep extends MobAnimal
 			int blockX = MathHelper.floor(x);
 			int blockY = MathHelper.floor(y);
 			int blockZ = MathHelper.floor(z);
-			Block blockBelow = world.getBlock(blockX, blockY - 1, blockZ);
+            Block<?> blockBelow = world.getBlock(blockX, blockY - 1, blockZ);
 			
 			if (timeSheepEating >= 5 && timeSheepEating <= 35 && timeSheepEating % 5 == 0 && !world.isClientSide) {
 				world.playBlockSoundEffect(null, x + 0.5, y + 0.5, z + 0.5, Blocks.GRASS, EnumBlockSoundEffectType.DIG);
@@ -173,7 +173,7 @@ public class MobSheep extends MobAnimal
 				if(blockBelow == Blocks.GRASS || blockBelow == Blocks.GRASS_RETRO) {
 					if(!world.isClientSide) {
 						world.playBlockEvent(null, LevelListener.EVENT_BLOCK_BREAK, (int) x, (int) y - 1, (int) z, world.getBlockId((int) x, (int) y - 1, (int) z));
-						world.setBlockWithNotify(blockX, blockY - 1, blockZ, Blocks.DIRT.id);
+						world.setBlockWithNotify(blockX, blockY - 1, blockZ, Blocks.DIRT.id());
 						setSheared(false);
 					}
 				}
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java
index c586e6ab7..42dbead8a 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java
@@ -2,7 +2,6 @@ package net.minecraft.core.entity.animal;
 
 import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Items;
@@ -170,17 +169,17 @@ public class MobSquid extends MobWaterAnimal
         {
             float f = random.nextFloat() * MathHelper.PI * 2.0F;
             tx = MathHelper.cos(f) * 0.2F;
-            Block upwardsBlock = world.getBlock((int) x, (int) y + 3, (int) z);
-            Block downwardsBlock = world.getBlock((int) x, (int) y - 3, (int) z);
+            Block<?> upwardsBlock = world.getBlock((int) x, (int) y + 3, (int) z);
+            Block<?> downwardsBlock = world.getBlock((int) x, (int) y - 3, (int) z);
 
             boolean isTouchingBlock = isTouchingBlock();
 
             if (isTouchingBlock && isInWater() && !world.isAirBlock((int) x, (int) (y + 1), (int) z) && !world.isAirBlock((int) x, (int) (y + 2), (int) z)){
                 ty = random.nextFloat() * 0.2F;
             } else {
-                if (upwardsBlock == null || upwardsBlock.blockMaterial != Material.water){
+                if (upwardsBlock == null || upwardsBlock.getMaterial() != Material.water){
                     ty = -0.15F + random.nextFloat() * 0.2F; // Swim with bias down
-                } else if (downwardsBlock == null || downwardsBlock.blockMaterial != Material.water) {
+                } else if (downwardsBlock == null || downwardsBlock.getMaterial() != Material.water) {
                     ty = -0.05F + random.nextFloat() * 0.4F; // Swim with bias up
                 } else {
                     ty = -0.1F + random.nextFloat() * 0.2F; // Swim with no bias
@@ -206,8 +205,8 @@ public class MobSquid extends MobWaterAnimal
                 {
                     for(int _z = minZ; _z <= maxZ; _z++)
                     {
-                        int blockId = world.getBlockId(_x, _y, _z);
-                        if(blockId != 0 && Blocks.blocksList[blockId].blockMaterial != Material.water)
+                        Block<?> block = world.getBlock(_x, _y, _z);
+                        if(block != null && block.getMaterial() != Material.water)
                         {
                             return true;
                         }
@@ -227,6 +226,6 @@ public class MobSquid extends MobWaterAnimal
     }
 
     public boolean isSpecial() {
-        return nickname != null && nickname.hashCode() == 678229435;
+        return "Useless7695".equals(nickname);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
index 3bab971d1..b8b6b4bd7 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
@@ -325,20 +325,20 @@ public class MobWolf extends MobAnimal
         if(target == null && !hasPath())
         {
             if(!isWolfTamed() && world.rand.nextInt(100) == 0){
-                List<Entity> nearbySheep = world.getEntitiesWithinAABB(MobSheep.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
+                List<MobSheep> nearbySheep = world.getEntitiesWithinAABB(MobSheep.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
                 if (!nearbySheep.isEmpty()) {
-                    setTarget((Entity) nearbySheep.get(world.rand.nextInt(nearbySheep.size())));
+                    setTarget(nearbySheep.get(world.rand.nextInt(nearbySheep.size())));
                 }
             }
         }
         ItemStack heldItemSlot = getWolfHeldItem();
         if((heldItemSlot == null || heldItemSlot.itemID <= 0)) {
-            List<Entity> triedItems = new ArrayList<>();
-            List<Entity> nearbyItems = world.getEntitiesWithinAABB(EntityItem.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
+            List<EntityItem> triedItems = new ArrayList<>();
+            List<EntityItem> nearbyItems = world.getEntitiesWithinAABB(EntityItem.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
             if (!nearbyItems.isEmpty()) {
                 while (triedItems.size() != nearbyItems.size())
                 {
-                    EntityItem item = (EntityItem) nearbyItems.get(world.rand.nextInt(nearbyItems.size()));
+                    EntityItem item = nearbyItems.get(world.rand.nextInt(nearbyItems.size()));
                     if (triedItems.contains(item))
                     {
                         continue;
@@ -408,7 +408,7 @@ public class MobWolf extends MobAnimal
         super.tick();
 
         List<Entity> entitiesNearWolf = world.getEntitiesWithinAABBExcludingEntity(this, bb);
-        if(entitiesNearWolf != null && entitiesNearWolf.size() > 0 && isAlive())
+        if(entitiesNearWolf != null && !entitiesNearWolf.isEmpty() && isAlive())
         {
             for (Entity entity : entitiesNearWolf) {
                 if(entity instanceof EntityItem && (this.getWolfHeldItem() == null || this.getWolfHeldItem().getItem() == null)){
@@ -578,22 +578,21 @@ public class MobWolf extends MobAnimal
                 }
                 if(attacker instanceof Mob)
                 {
-                    List<Entity> list = world.getEntitiesWithinAABB(MobWolf.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
-                    Iterator<Entity> iterator = list.iterator();
+                    List<MobWolf> list = world.getEntitiesWithinAABB(MobWolf.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
+                    Iterator<MobWolf> iterator = list.iterator();
                     do
                     {
                         if(!iterator.hasNext())
                         {
                             break;
                         }
-                        Entity entity1 = iterator.next();
-                        MobWolf entitywolf = (MobWolf)entity1;
-                        if(!entitywolf.isWolfTamed() && entitywolf.target == null)
+                        MobWolf mobWolf = iterator.next();
+                        if(!mobWolf.isWolfTamed() && mobWolf.target == null)
                         {
-                            entitywolf.target = attacker;
+                            mobWolf.target = attacker;
                             if(attacker instanceof Player)
                             {
-                                entitywolf.setWolfAngry(true);
+                                mobWolf.setWolfAngry(true);
                             }
                         }
                     } while(true);
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java
index cd0a55f6e..2d2c333f8 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java
@@ -52,7 +52,7 @@ public class MobSnowman extends MobMonster
             {
                 if(!world.isClientSide) {
                     ProjectileSnowball projectileSnowball = new ProjectileSnowball(world, this);
-                    if (world.getBlockId((int) x, (int) y - 1, (int) z) == Blocks.GRAVEL.id)
+                    if (world.getBlockId((int) x, (int) y - 1, (int) z) == Blocks.GRAVEL.id())
                     {
                         projectileSnowball.damage = 1;
                     }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
index 970af73a8..1e6c85ec7 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
@@ -63,11 +63,11 @@ public class MobZombiePig extends MobZombie
     	int y = MathHelper.floor(this.y);
     	int z = MathHelper.floor(this.z);
     	if(world.getBlockId(x, y, z) != 0) return false;
-        Block below = world.getBlock(x, y - 1, z);
+        Block<?> below = world.getBlock(x, y - 1, z);
         if (!BlockTags.NETHER_MOBS_SPAWN.appliesTo(below)) return false;
         int blockLight = world.getSavedLightValue(LightLayer.Block, x, y, z);
     	if(blockLight > 7) return false;
-        return world.getDifficulty().canHostileMobsSpawn() && world.checkIfAABBIsClear(bb) && world.getCubes(this, bb).size() == 0 && !world.getIsAnyLiquid(bb);
+        return world.getDifficulty().canHostileMobsSpawn() && world.checkIfAABBIsClear(bb) && world.getCubes(this, bb).isEmpty() && !world.getIsAnyLiquid(bb);
     }
 
     @Override
@@ -104,14 +104,14 @@ public class MobZombiePig extends MobZombie
     	}
         if(attacker instanceof Player)
         {
-            List list = world.getEntitiesWithinAABBExcludingEntity(this, bb.grow(32D, 32D, 32D));
+            List<Entity> list = world.getEntitiesWithinAABBExcludingEntity(this, bb.grow(32D, 32D, 32D));
             for(int j = 0; j < list.size(); j++)
             {
-                Entity entity1 = (Entity)list.get(j);
-                if(entity1 instanceof MobZombiePig)
+                Entity e = list.get(j);
+                if(e instanceof MobZombiePig)
                 {
-                    MobZombiePig entitypigzombie = (MobZombiePig)entity1;
-                    entitypigzombie.becomeAngryAt(attacker);
+                    MobZombiePig mobZombiePig = (MobZombiePig)e;
+                    mobZombiePig.becomeAngryAt(attacker);
                 }
             }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
index 0b8c2b39e..630c8cbe9 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
@@ -2,7 +2,7 @@ package net.minecraft.core.entity.player;
 
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
-import net.minecraft.core.block.BlockBed;
+import net.minecraft.core.block.BlockLogicBed;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.entity.TileEntitySign;
 import net.minecraft.core.entity.EntityItem;
@@ -578,7 +578,7 @@ public abstract class Player extends Mob
             {
                 return getDisplayName() + deathMsgColor + " got lost in the sauce.";
             }
-            if (world.getBlockId(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)) == Blocks.SPIKES.id)
+            if (world.getBlockId(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)) == Blocks.SPIKES.id())
             {
                 return getDisplayName() + deathMsgColor + " fell for the trap.";
             }
@@ -710,7 +710,7 @@ public abstract class Player extends Mob
         world.entityJoinedWorld(entityitem);
     }
 
-    public float getCurrentPlayerStrVsBlock(Block block)
+    public float getCurrentPlayerStrVsBlock(Block<?> block)
     {
         float f = inventory.getStrVsBlock(block);
         float defaultBreakSpeed = (inventory.getCurrentItem() != null && inventory.getCurrentItem().getItem() instanceof ItemToolSword) ? 1.51f : 1.01f;
@@ -726,7 +726,7 @@ public abstract class Player extends Mob
         return f;
     }
 
-    public boolean canHarvestBlock(Block block)
+    public boolean canHarvestBlock(Block<?> block)
     {
         if (block == null) return false;
         return inventory.canHarvestBlock(block);
@@ -938,9 +938,8 @@ public abstract class Player extends Mob
         {
             return;
         }
-        List<Entity> list = world.getEntitiesWithinAABB(MobWolf.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
-        for (Entity entity : list) {
-            MobWolf wolf = (MobWolf) entity;
+        List<MobWolf> list = world.getEntitiesWithinAABB(MobWolf.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
+        for (MobWolf wolf : list) {
             if (wolf.isWolfTamed() && wolf.getTarget() == null && uuid.equals(wolf.getWolfOwner()) && (!flag || !wolf.isWolfSitting())) {
                 wolf.setTarget(attacker);
             }
@@ -1164,7 +1163,7 @@ public abstract class Player extends Mob
         if(world.isBlockLoaded(x, y, z))
         {
             int meta = world.getBlockMetadata(x, y, z);
-            int dir = BlockBed.getDirection(meta);
+            int dir = BlockLogicBed.getDirection(meta);
             float xOff = 0.5F;
             float zOff = 0.5F;
             
@@ -1222,10 +1221,11 @@ public abstract class Player extends Mob
         setSize(0.6F, 1.8F);
         resetHeight();
         ChunkCoordinates chunkcoordinates = bedChunkCoordinates;
-        if(chunkcoordinates != null && world.getBlock(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z) instanceof BlockBed)
+        Block<?> b;
+        if(chunkcoordinates != null && (b = world.getBlock(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z)) != null && b.getLogic() instanceof BlockLogicBed)
         {
-            BlockBed.setBedOccupied(world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, false);
-            ChunkCoordinates chunkcoordinates2 = BlockBed.getNearestEmptyChunkCoordinates(world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, 0);
+            BlockLogicBed.setBedOccupied(world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, false);
+            ChunkCoordinates chunkcoordinates2 = BlockLogicBed.getNearestEmptyChunkCoordinates(world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, 0);
             if(chunkcoordinates2 == null)
             {
                 chunkcoordinates2 = new ChunkCoordinates(chunkcoordinates.x, chunkcoordinates.y + 1, chunkcoordinates.z);
@@ -1248,7 +1248,8 @@ public abstract class Player extends Mob
 
     private boolean isInBed()
     {
-        return world.getBlock(bedChunkCoordinates.x, bedChunkCoordinates.y, bedChunkCoordinates.z) instanceof BlockBed;
+        Block<?> b;
+        return (b = world.getBlock(bedChunkCoordinates.x, bedChunkCoordinates.y, bedChunkCoordinates.z)) != null && b.getLogic() instanceof BlockLogicBed;
     }
 
     public static ChunkCoordinates getValidBedSpawnCoordinates(World world, ChunkCoordinates coords)
@@ -1259,8 +1260,9 @@ public abstract class Player extends Mob
         chunkProvider.prepareChunk(coords.x + 3 >> 4, coords.z - 3 >> 4);
         chunkProvider.prepareChunk(coords.x - 3 >> 4, coords.z + 3 >> 4);
         chunkProvider.prepareChunk(coords.x + 3 >> 4, coords.z + 3 >> 4);
-        if (world.getBlock(coords.x, coords.y, coords.z) instanceof BlockBed) {
-            return BlockBed.getNearestEmptyChunkCoordinates(world, coords.x, coords.y, coords.z, 0);
+        Block<?> b;
+        if ((b = world.getBlock(coords.x, coords.y, coords.z)) != null && b.getLogic() instanceof BlockLogicBed) {
+            return BlockLogicBed.getNearestEmptyChunkCoordinates(world, coords.x, coords.y, coords.z, 0);
         } else {
             return null;
         }
@@ -1271,7 +1273,7 @@ public abstract class Player extends Mob
         if(bedChunkCoordinates != null)
         {
             int i = world.getBlockMetadata(bedChunkCoordinates.x, bedChunkCoordinates.y, bedChunkCoordinates.z);
-            int j = BlockBed.getDirection(i);
+            int j = BlockLogicBed.getDirection(i);
             switch(j)
             {
             case 0: // '\0'
@@ -1548,7 +1550,7 @@ public abstract class Player extends Mob
     }
 
     public void pickBlock(int x, int y, int z) {
-    	Block block = world.getBlock(x, y, z);
+        Block<?> block = world.getBlock(x, y, z);
     	int meta = world.getBlockMetadata(x, y, z);
     	
     	if(block == null) {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
index 02853f6af..9f68bc9d9 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
@@ -115,7 +115,7 @@ public class ProjectileArrow extends Projectile
             yRotO = yRot = (float)((Math.atan2(xd, zd) * 180D) / Math.PI);
             xRotO = xRot = (float)((Math.atan2(yd, f) * 180D) / Math.PI);
         }
-        Block block = world.getBlock(xTile, yTile, zTile);
+        Block<?> block = world.getBlock(xTile, yTile, zTile);
         if(block != null)
         {
             AABB aabb = block.getCollisionBoundingBoxFromPool(world, xTile, yTile, zTile);
diff --git a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java
index 31e44a513..8c97a350c 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java
@@ -116,7 +116,7 @@ public class EntityBoat extends Entity
         int numParticles = random.nextInt(8) + 1;
         for (int q = 0; q < numParticles; q++)
         {
-            world.spawnParticle("block", x, y, z, xd, yd, zd, BlockParticleHelper.encodeBlockData(Blocks.PLANKS_OAK.id, 0, Side.BOTTOM));
+            world.spawnParticle("block", x, y, z, xd, yd, zd, BlockParticleHelper.encodeBlockData(Blocks.PLANKS_OAK.id(), 0, Side.BOTTOM));
         }
         if(world.isClientSide || removed)
         {
@@ -146,7 +146,7 @@ public class EntityBoat extends Entity
                 spawnAtLocation(Items.BOAT.id, 1, 0.0F);
             }else {
                 for (int j = 0; j < 3; j++) {
-                    spawnAtLocation(Blocks.PLANKS_OAK.id, 1, 0.0F);
+                    spawnAtLocation(Blocks.PLANKS_OAK.id(), 1, 0.0F);
                 }
 
                 for (int k = 0; k < 2; k++) {
@@ -350,7 +350,7 @@ public class EntityBoat extends Entity
             int blockX = MathHelper.floor(x + ((double)(i % 2) - 0.5D) * 0.8D);
             int blockY = MathHelper.floor(y);
             int blockZ = MathHelper.floor(z + ((double)(i / 2) - 0.5D) * 0.8D);
-            Block block = world.getBlock(blockX, blockY, blockZ);
+            Block<?> block = world.getBlock(blockX, blockY, blockZ);
             if(block != null && block.hasTag(BlockTags.BOAT_BREAKS))
             {
                 world.setBlockWithNotify(blockX, blockY, blockZ, 0);
diff --git a/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java b/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
index 61f9ef542..5fd66e042 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
@@ -3,7 +3,7 @@ package net.minecraft.core.entity.vehicle;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockRail;
+import net.minecraft.core.block.BlockLogicRail;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityChest;
 import net.minecraft.core.block.logic.RailDirection;
@@ -200,11 +200,11 @@ public class MinecartEntity extends Entity implements Container {
                         if ((typeMeta & TYPE_MASK_PAINTED_CHEST) != 0) {
                             spawnAtLocation(new ItemStack(Blocks.CHEST_PLANKS_OAK_PAINTED, 1, typeMeta & TYPE_MASK_COLOR), 0.0F);
                         } else {
-                            spawnAtLocation(Blocks.CHEST_PLANKS_OAK.id, 1, 0.0F);
+                            spawnAtLocation(Blocks.CHEST_PLANKS_OAK.id(), 1, 0.0F);
                         }
                         break;
                     case FURNACE_CART:
-                        spawnAtLocation(Blocks.FURNACE_STONE_IDLE.id, 1, 0.0F);
+                        spawnAtLocation(Blocks.FURNACE_STONE_IDLE.id(), 1, 0.0F);
                         break;
                 }
             }
@@ -287,20 +287,20 @@ public class MinecartEntity extends Entity implements Container {
         int blockX = MathHelper.floor(x);
         int blockY = MathHelper.floor(y);
         int blockZ = MathHelper.floor(z);
-        if(BlockRail.isRailBlockAt(world, blockX, blockY - 1, blockZ)) {
+        if(BlockLogicRail.isRailBlockAt(world, blockX, blockY - 1, blockZ)) {
             blockY--;
         }
         final double maxSpeed = 0.4D;
         boolean didFurnacePush = false;
         final double d5 = 0.0078125D;
-        Block block = world.getBlock(blockX, blockY, blockZ);
-        if(block instanceof BlockRail) {
-            BlockRail rail = (BlockRail) block;
+        Block<?> block = world.getBlock(blockX, blockY, blockZ);
+        if(block != null && block.getLogic() instanceof BlockLogicRail) {
+            BlockLogicRail rail = (BlockLogicRail) block.getLogic();
             Vec3 vec3d = getPos(x, y, z);
             y = blockY;
             boolean onPoweredPoweredRail = false;
             boolean onUnpoweredPoweredRail = false;
-            if(rail == Blocks.RAIL_POWERED) {
+            if(block == Blocks.RAIL_POWERED) {
                 onPoweredPoweredRail = (world.getBlockMetadata(blockX, blockY, blockZ) & 0b1000) != 0;
                 onUnpoweredPoweredRail = !onPoweredPoweredRail;
             }
@@ -518,14 +518,14 @@ public class MinecartEntity extends Entity implements Container {
         int blockX = MathHelper.floor(x);
         int blockY = MathHelper.floor(y);
         int blockZ = MathHelper.floor(z);
-        if(BlockRail.isRailBlockAt(world, blockX, blockY - 1, blockZ)) {
+        if(BlockLogicRail.isRailBlockAt(world, blockX, blockY - 1, blockZ)) {
             blockY--;
         }
 
-        Block block = world.getBlock(blockX, blockY, blockZ);
-        if (!(block instanceof BlockRail)) { return null; }
+        Block<?> block = world.getBlock(blockX, blockY, blockZ);
+        if (!(block != null && block.getLogic() instanceof BlockLogicRail)) { return null; }
 
-        BlockRail rail = (BlockRail) block;
+        BlockLogicRail rail = (BlockLogicRail) block.getLogic();
         int meta = world.getBlockMetadata(blockX, blockY, blockZ);
         if(rail.getIsPowered()) {
             meta &= 0b111;
@@ -559,13 +559,13 @@ public class MinecartEntity extends Entity implements Container {
         int blockY = MathHelper.floor(y);
         int blockZ = MathHelper.floor(z);
 
-        if(BlockRail.isRailBlockAt(world, blockX, blockY - 1, blockZ)) {
+        if(BlockLogicRail.isRailBlockAt(world, blockX, blockY - 1, blockZ)) {
             blockY--;
         }
-        Block block = world.getBlock(blockX, blockY, blockZ);
-        if (!(block instanceof BlockRail)) { return null; }
+        Block<?> block = world.getBlock(blockX, blockY, blockZ);
+        if (!(Block.hasLogicClass(block, BlockLogicRail.class))) { return null; }
 
-        BlockRail rail = (BlockRail) block;
+        BlockLogicRail rail = (BlockLogicRail) block.getLogic();
         RailDirection direction = rail.getRailDirection(world, blockX, blockY, blockZ);
 
         int[][] offsetMap = EXITS[direction.meta];
@@ -707,7 +707,7 @@ public class MinecartEntity extends Entity implements Container {
                     if (carriedBlock.entity instanceof TileEntityChest) {
                         TileEntityChest chest = (TileEntityChest) carriedBlock.entity;
                         this.type = CHEST_CART;
-                        if (carriedBlock.blockId == Blocks.CHEST_PLANKS_OAK_PAINTED.id) {
+                        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;
@@ -736,7 +736,7 @@ public class MinecartEntity extends Entity implements Container {
                             this.setItem(i, null);
                         }
                         blockEntity.worldObj = null;
-                        Block block;
+                        Block<?> block;
                         if ((typeMeta & TYPE_MASK_PAINTED_CHEST) != 0) {
                             block = Blocks.CHEST_PLANKS_OAK_PAINTED;
                         } else {
diff --git a/game/core/src/main/java/net/minecraft/core/item/Item.java b/game/core/src/main/java/net/minecraft/core/item/Item.java
index ad227b48c..1f51d14a9 100644
--- a/game/core/src/main/java/net/minecraft/core/item/Item.java
+++ b/game/core/src/main/java/net/minecraft/core/item/Item.java
@@ -165,7 +165,7 @@ public class Item implements ITaggable<Item>, IItemConvertible
     public void onUseByActivator(ItemStack itemStack, TileEntityActivator activatorBlock, World world, Random random, int blockX, int blockY, int blockZ, double offX, double offY, double offZ, Direction direction) {
     }
 
-    public float getStrVsBlock(ItemStack itemstack, Block block)
+    public float getStrVsBlock(ItemStack itemstack, Block<?> block)
     {
         return 1.0F;
     }
@@ -185,9 +185,9 @@ public class Item implements ITaggable<Item>, IItemConvertible
         return hasSubtypes;
     }
 
-    protected Item setHasSubtypes(boolean flag)
+    protected Item setHasSubtypes(boolean hasSubtypes)
     {
-        hasSubtypes = flag;
+        this.hasSubtypes = hasSubtypes;
         return this;
     }
 
@@ -207,7 +207,7 @@ public class Item implements ITaggable<Item>, IItemConvertible
         return maxDamage > 0 && !hasSubtypes;
     }
 
-    public boolean hitEntity(ItemStack itemstack, Mob entityliving, Mob entityliving1)
+    public boolean hitEntity(ItemStack itemstack, Mob target, Mob attacker)
     {
         return false;
     }
@@ -230,12 +230,12 @@ public class Item implements ITaggable<Item>, IItemConvertible
         return 1;
     }
 
-    public boolean canHarvestBlock(Mob entityLiving, ItemStack itemStack, Block block)
+    public boolean canHarvestBlock(Mob mob, ItemStack itemStack, Block<?> block)
     {
         return false;
     }
 
-    public boolean useItemOnEntity(ItemStack itemstack, Mob entityliving, Player entityPlayer)
+    public boolean useItemOnEntity(ItemStack itemstack, Mob mob, Player player)
     {
         return false;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemBed.java b/game/core/src/main/java/net/minecraft/core/item/ItemBed.java
index ccad71853..3fb6abc01 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemBed.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemBed.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.item;
 
-import net.minecraft.core.block.BlockBed;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
@@ -23,7 +22,6 @@ public class ItemBed extends Item
     		blockY += side.getOffsetY();
     		blockZ += side.getOffsetZ();
     	}
-        BlockBed blockbed = (BlockBed) Blocks.BED;
         int i1 = entityplayer.getHorizontalPlacementDirection(null).getOpposite().getHorizontalIndex();
         byte byte0 = 0;
         byte byte1 = 0;
@@ -45,10 +43,10 @@ public class ItemBed extends Item
         }
         if(world.isAirBlock(blockX, blockY, blockZ) && world.isAirBlock(blockX + byte0, blockY, blockZ + byte1) && world.canPlaceOnSurfaceOfBlock(blockX, blockY - 1, blockZ) && world.canPlaceOnSurfaceOfBlock(blockX + byte0, blockY - 1, blockZ + byte1))
         {
-            if(world.canBlockBePlacedAt(blockbed.id, blockX, blockY, blockZ, false, side) && itemstack.consumeItem(entityplayer)) {
-                world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockbed, EnumBlockSoundEffectType.PLACE);
-                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockbed.id, i1);
-                world.setBlockAndMetadataWithNotify(blockX + byte0, blockY, blockZ + byte1, blockbed.id, i1 + 8);
+            if(world.canBlockBePlacedAt(Blocks.BED.id(), blockX, blockY, blockZ, false, side) && itemstack.consumeItem(entityplayer)) {
+                world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.BED, EnumBlockSoundEffectType.PLACE);
+                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.BED.id(), i1);
+                world.setBlockAndMetadataWithNotify(blockX + byte0, blockY, blockZ + byte1, Blocks.BED.id(), i1 + 8);
                 return true;
             }
         }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemBoat.java b/game/core/src/main/java/net/minecraft/core/item/ItemBoat.java
index f3408371a..88d499739 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemBoat.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemBoat.java
@@ -51,7 +51,7 @@ public class ItemBoat extends Item
             int k = movingobjectposition.z;
             if(!world.isClientSide)
             {
-                if(world.getBlockId(i, j, k) == Blocks.LAYER_SNOW.id)
+                if(world.getBlockId(i, j, k) == Blocks.LAYER_SNOW.id())
                 {
                     j--;
                 }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java b/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java
index 96034047b..7bc7d50d4 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java
@@ -12,30 +12,29 @@ import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
 public class ItemBucket extends Item
 {
-	private final int idToPlace;
-    public ItemBucket(String name, String namespaceId, int id, Block blockToPlace)
+	private final @Nullable Block<?> blockToPlace;
+    public ItemBucket(String name, String namespaceId, int id, @Nullable Block<?> blockToPlace)
     {
         super(name, namespaceId, id);
         maxStackSize = 1;
-        if (blockToPlace == null)
-        {
-            this.idToPlace = -1;
-        }
-        else
-        {
-            this.idToPlace = blockToPlace.id;
-        }
+        this.blockToPlace = blockToPlace;
     }
 
     @Override
 	public ItemStack onUseItem(ItemStack stack, World world, Player player) {
+		if(blockToPlace == null) {
+			// Milk
+			return new ItemStack(Items.BUCKET);
+		}
+
 		double reachDistance = player.getGamemode().getBlockReachDistance();
-		HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, idToPlace == 0, false);
+		HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, false, false);
 		
 		if(rayTraceResult == null || rayTraceResult.hitType != HitResult.HitType.TILE) {
 			return stack;
@@ -49,12 +48,7 @@ public class ItemBucket extends Item
 			return stack;
 		}
 		
-		if(idToPlace < 0) {
-			// Milk
-			return new ItemStack(Items.BUCKET);
-		}
-		
-		Block block = world.getBlock(x, y, z);
+		Block<?> block = world.getBlock(x, y, z);
 		if(block != null && !block.hasTag(BlockTags.PLACE_OVERWRITES) && !block.hasTag(BlockTags.BROKEN_BY_FLUIDS)) {
 			Side side = rayTraceResult.side;
 			x += side.getOffsetX();
@@ -67,21 +61,21 @@ public class ItemBucket extends Item
 		}
 		
 		if(world.isAirBlock(x, y, z) || !world.getBlockMaterial(x, y, z).isSolid()) {
-			if(world.dimension == Dimension.NETHER && idToPlace == Blocks.FLUID_WATER_FLOWING.id) {
+			if(world.dimension == Dimension.NETHER && blockToPlace == Blocks.FLUID_WATER_FLOWING) {
 				world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, z + 0.5, y + 0.5, x + 0.5, "random.fizz", 0.5F, 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
 				for (int l = 0; l < 8; l++) {
 					world.spawnParticle("largesmoke", x + Math.random(), y + Math.random(), z + Math.random(), 0.0D, 0.0D, 0.0D, 0);
 				}
 			} else {
-				if(idToPlace == Blocks.FLUID_WATER_FLOWING.id) {
+				if(blockToPlace == Blocks.FLUID_WATER_FLOWING) {
 					world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, x + 0.5F, y + 0.5F, z + 0.5F, "liquid.splash", 0.5f, 1.0f);
 				}
 				player.swingItem();
-				Block block1 = world.getBlock(x, y, z);
+				Block<?> block1 = world.getBlock(x, y, z);
 				if(block1 != null) {
 					block1.dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
 				}
-				world.setBlockAndMetadataWithNotify(x, y, z, idToPlace, 0);
+				world.setBlockAndMetadataWithNotify(x, y, z, blockToPlace.id(), 0);
 			}
 			if(player.getGamemode().consumeBlocks()) {
 				return new ItemStack(Items.BUCKET);
@@ -93,16 +87,16 @@ public class ItemBucket extends Item
 
 	@Override
 	public void onUseByActivator(ItemStack itemStack, TileEntityActivator activatorBlock, World world, Random random, int blockX, int blockY, int blockZ, double offX, double offY, double offZ, Direction direction) {
-		if (idToPlace < 0) {
+		if (blockToPlace == null) {
 			itemStack.itemID = Items.BUCKET.id;
 			return;
 		}
 		int x = blockX + direction.getOffsetX();
 		int y = blockY + direction.getOffsetY();
 		int z = blockZ + direction.getOffsetZ();
-		Block b = world.getBlock(x, y, z);
+		Block<?> b = world.getBlock(x, y, z);
 		if (b == null || BlockTags.PLACE_OVERWRITES.appliesTo(b) || BlockTags.BROKEN_BY_FLUIDS.appliesTo(b)) {
-			world.setBlockWithNotify(x, y, z, idToPlace);
+			world.setBlockWithNotify(x, y, z, blockToPlace.id());
 			itemStack.itemID = Items.BUCKET.id;
 		}
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java b/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java
index 6573ae216..14ed270b6 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java
@@ -1,7 +1,6 @@
 package net.minecraft.core.item;
 
 import net.minecraft.core.block.entity.TileEntityActivator;
-import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.animal.MobCow;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.helper.Direction;
@@ -82,7 +81,7 @@ public class ItemBucketEmpty extends Item
         }
 
         AABB box = AABB.getTemporaryBB(x, y, z, x + 1, y + 1, z + 1);
-        List<Entity> entities = world.getEntitiesWithinAABB(MobCow.class, box);
+        List<MobCow> entities = world.getEntitiesWithinAABB(MobCow.class, box);
         if (!entities.isEmpty()) {
             itemStack.itemID = Items.BUCKET_MILK.id;
             return;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java b/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java
index 0e9dc9935..b276c13d4 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.item;
 
-import net.minecraft.core.block.BlockJukebox;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.helper.Direction;
@@ -28,10 +27,10 @@ public class ItemDiscMusic extends Item
     @Override
     public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
     {
-        if(world.getBlockId(blockX, blockY, blockZ) == Blocks.JUKEBOX.id && world.getBlockMetadata(blockX, blockY, blockZ) == 0)
+        if(world.getBlockId(blockX, blockY, blockZ) == Blocks.JUKEBOX.id() && world.getBlockMetadata(blockX, blockY, blockZ) == 0)
         {
             if (!world.isClientSide) {
-                ((BlockJukebox) Blocks.JUKEBOX).playRecord(world, blockX, blockY, blockZ, id);
+                Blocks.JUKEBOX.getLogic().playRecord(world, blockX, blockY, blockZ, id);
                 world.playBlockEvent(null, LevelListener.EVENT_JUKEBOX_TOGGLE, blockX, blockY, blockZ, id);
                 itemstack.consumeItem(entityplayer);
             }
@@ -48,8 +47,8 @@ public class ItemDiscMusic extends Item
         int y = blockY + direction.getOffsetY();
         int z = blockZ + direction.getOffsetZ();
         int b = world.getBlockId(x, y, z);
-        if (b == Blocks.JUKEBOX.id && world.getBlockMetadata(x, y, z) == 0) {
-            ((BlockJukebox) Blocks.JUKEBOX).playRecord(world, x, y, z, id);
+        if (b == Blocks.JUKEBOX.id() && world.getBlockMetadata(x, y, z) == 0) {
+            Blocks.JUKEBOX.getLogic().playRecord(world, x, y, z, id);
             world.playBlockEvent(null, LevelListener.EVENT_JUKEBOX_TOGGLE, blockX, blockY, blockZ, id);
             itemStack.consumeItem(null);
         }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java b/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java
index eaa4805ec..bba919c71 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java
@@ -11,10 +11,10 @@ import net.minecraft.core.world.World;
 import java.util.Random;
 
 public class ItemDoor extends Item {
-	protected final Block doorBlockBottom;
-	protected final Block doorBlockTop;
+	protected final Block<?> doorBlockBottom;
+	protected final Block<?> doorBlockTop;
 
-	public ItemDoor(String name, String namespaceId, int id, Block doorBlockBottom, Block doorBlockTop) {
+	public ItemDoor(String name, String namespaceId, int id, Block<?> doorBlockBottom, Block<?> doorBlockTop) {
 		super(name, namespaceId, id);
 		maxStackSize = 64;
         this.doorBlockBottom = doorBlockBottom;
@@ -40,8 +40,8 @@ public class ItemDoor extends Item {
 
 		int isSolidBlockLeft = (world.isBlockNormalCube(blockX - xOffset, blockY, blockZ - zOffset) ? 1 : 0) + (world.isBlockNormalCube(blockX - xOffset, blockY + 1, blockZ - zOffset) ? 1 : 0);
 		int isSolidBlockRight = (world.isBlockNormalCube(blockX + xOffset, blockY, blockZ + zOffset) ? 1 : 0) + (world.isBlockNormalCube(blockX + xOffset, blockY + 1, blockZ + zOffset) ? 1 : 0);
-		boolean isDoorLeft = world.getBlockId(blockX - xOffset, blockY, blockZ - zOffset) == doorBlockBottom.id || world.getBlockId(blockX - xOffset, blockY + 1, blockZ - zOffset) == doorBlockTop.id;
-		boolean isDoorRight = world.getBlockId(blockX + xOffset, blockY, blockZ + zOffset) == doorBlockBottom.id || world.getBlockId(blockX + xOffset, blockY + 1, blockZ + zOffset) == doorBlockTop.id;
+		boolean isDoorLeft = world.getBlockId(blockX - xOffset, blockY, blockZ - zOffset) == doorBlockBottom.id() || world.getBlockId(blockX - xOffset, blockY + 1, blockZ - zOffset) == doorBlockTop.id();
+		boolean isDoorRight = world.getBlockId(blockX + xOffset, blockY, blockZ + zOffset) == doorBlockBottom.id() || world.getBlockId(blockX + xOffset, blockY + 1, blockZ + zOffset) == doorBlockTop.id();
 		boolean isMirrored = false;
 		
 		if(isDoorLeft && !isDoorRight) {
@@ -56,11 +56,11 @@ public class ItemDoor extends Item {
 		}
 		
 		world.noNeighborUpdate = true;
-		world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, doorBlockBottom.id, meta);
-		world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, doorBlockTop.id, meta);
+		world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, doorBlockBottom.id(), meta);
+		world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, doorBlockTop.id(), meta);
 		world.noNeighborUpdate = false;
-		world.notifyBlocksOfNeighborChange(blockX, blockY, blockZ, doorBlockBottom.id);
-		world.notifyBlocksOfNeighborChange(blockX, blockY + 1, blockZ, doorBlockTop.id);
+		world.notifyBlocksOfNeighborChange(blockX, blockY, blockZ, doorBlockBottom.id());
+		world.notifyBlocksOfNeighborChange(blockX, blockY + 1, blockZ, doorBlockTop.id());
 		world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, doorBlockBottom, EnumBlockSoundEffectType.PLACE);
 		doorBlockBottom.onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
 		doorBlockTop.onBlockPlacedByMob(world, blockX, blockY + 1, blockZ, side, player, xPlaced, yPlaced);
@@ -88,8 +88,8 @@ public class ItemDoor extends Item {
 
 		int isSolidBlockLeft = (world.isBlockNormalCube(blockX - xOffset, blockY, blockZ - zOffset) ? 1 : 0) + (world.isBlockNormalCube(blockX - xOffset, blockY + 1, blockZ - zOffset) ? 1 : 0);
 		int isSolidBlockRight = (world.isBlockNormalCube(blockX + xOffset, blockY, blockZ + zOffset) ? 1 : 0) + (world.isBlockNormalCube(blockX + xOffset, blockY + 1, blockZ + zOffset) ? 1 : 0);
-		boolean isDoorLeft = world.getBlockId(blockX - xOffset, blockY, blockZ - zOffset) == doorBlockBottom.id || world.getBlockId(blockX - xOffset, blockY + 1, blockZ - zOffset) == doorBlockTop.id;
-		boolean isDoorRight = world.getBlockId(blockX + xOffset, blockY, blockZ + zOffset) == doorBlockBottom.id || world.getBlockId(blockX + xOffset, blockY + 1, blockZ + zOffset) == doorBlockTop.id;
+		boolean isDoorLeft = world.getBlockId(blockX - xOffset, blockY, blockZ - zOffset) == doorBlockBottom.id() || world.getBlockId(blockX - xOffset, blockY + 1, blockZ - zOffset) == doorBlockTop.id();
+		boolean isDoorRight = world.getBlockId(blockX + xOffset, blockY, blockZ + zOffset) == doorBlockBottom.id() || world.getBlockId(blockX + xOffset, blockY + 1, blockZ + zOffset) == doorBlockTop.id();
 		boolean isMirrored = false;
 
 		if(isDoorLeft && !isDoorRight) {
@@ -104,11 +104,11 @@ public class ItemDoor extends Item {
 		}
 
 		world.noNeighborUpdate = true;
-		world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, doorBlockBottom.id, meta);
-		world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, doorBlockTop.id, meta);
+		world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, doorBlockBottom.id(), meta);
+		world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, doorBlockTop.id(), meta);
 		world.noNeighborUpdate = false;
-		world.notifyBlocksOfNeighborChange(blockX, blockY, blockZ, doorBlockBottom.id);
-		world.notifyBlocksOfNeighborChange(blockX, blockY + 1, blockZ, doorBlockTop.id);
+		world.notifyBlocksOfNeighborChange(blockX, blockY, blockZ, doorBlockBottom.id());
+		world.notifyBlocksOfNeighborChange(blockX, blockY + 1, blockZ, doorBlockTop.id());
 		world.playBlockSoundEffect(null, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, doorBlockBottom, EnumBlockSoundEffectType.PLACE);
 		doorBlockBottom.onBlockPlacedOnSide(world, blockX, blockY, blockZ, direction.getSide(), 0.5, 0.5);
 		doorBlockTop.onBlockPlacedOnSide(world, blockX, blockY + 1, blockZ, direction.getSide(), 0.5, 0.5);
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java b/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java
index 79afeb75b..0b53ff9e3 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java
@@ -9,7 +9,7 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
 public class ItemDoorPainted extends ItemDoor {
-    public ItemDoorPainted(String name, String namespaceId, int id, Block doorBottom, Block doorTopId) {
+    public ItemDoorPainted(String name, String namespaceId, int id, Block<?> doorBottom, Block<?> doorTopId) {
         super(name, namespaceId, id, doorBottom, doorTopId);
     }
     @Override
@@ -31,8 +31,8 @@ public class ItemDoorPainted extends ItemDoor {
 
         int isSolidBlockLeft = (world.isBlockNormalCube(blockX - xOffset, blockY, blockZ - zOffset) ? 1 : 0) + (world.isBlockNormalCube(blockX - xOffset, blockY + 1, blockZ - zOffset) ? 1 : 0);
         int isSolidBlockRight = (world.isBlockNormalCube(blockX + xOffset, blockY, blockZ + zOffset) ? 1 : 0) + (world.isBlockNormalCube(blockX + xOffset, blockY + 1, blockZ + zOffset) ? 1 : 0);
-        boolean isDoorLeft = world.getBlockId(blockX - xOffset, blockY, blockZ - zOffset) == doorBlockBottom.id || world.getBlockId(blockX - xOffset, blockY + 1, blockZ - zOffset) == doorBlockTop.id;
-        boolean isDoorRight = world.getBlockId(blockX + xOffset, blockY, blockZ + zOffset) == doorBlockBottom.id || world.getBlockId(blockX + xOffset, blockY + 1, blockZ + zOffset) == doorBlockTop.id;
+        boolean isDoorLeft = world.getBlockId(blockX - xOffset, blockY, blockZ - zOffset) == doorBlockBottom.id() || world.getBlockId(blockX - xOffset, blockY + 1, blockZ - zOffset) == doorBlockTop.id();
+        boolean isDoorRight = world.getBlockId(blockX + xOffset, blockY, blockZ + zOffset) == doorBlockBottom.id() || world.getBlockId(blockX + xOffset, blockY + 1, blockZ + zOffset) == doorBlockTop.id();
         boolean isMirrored = false;
 
         if(isDoorLeft && !isDoorRight) {
@@ -48,11 +48,11 @@ public class ItemDoorPainted extends ItemDoor {
         meta |= (15 - itemstack.getMetadata()) << 4 &0xF0;
 
         world.noNeighborUpdate = true;
-        world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, doorBlockBottom.id, meta);
-        world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, doorBlockTop.id, meta);
+        world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, doorBlockBottom.id(), meta);
+        world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, doorBlockTop.id(), meta);
         world.noNeighborUpdate = false;
-        world.notifyBlocksOfNeighborChange(blockX, blockY, blockZ, doorBlockBottom.id);
-        world.notifyBlocksOfNeighborChange(blockX, blockY + 1, blockZ, doorBlockTop.id);
+        world.notifyBlocksOfNeighborChange(blockX, blockY, blockZ, doorBlockBottom.id());
+        world.notifyBlocksOfNeighborChange(blockX, blockY + 1, blockZ, doorBlockTop.id());
         world.playBlockSoundEffect(player,blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, doorBlockBottom, EnumBlockSoundEffectType.PLACE);
         itemstack.consumeItem(player);
         return true;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDye.java b/game/core/src/main/java/net/minecraft/core/item/ItemDye.java
index cb6c392bf..175a52360 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDye.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDye.java
@@ -40,7 +40,7 @@ public class ItemDye extends Item
     @Override
     public boolean onUseItemOnBlock(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
     {
-        if (world.getBlockId(blockX, blockY, blockZ) == Blocks.SIGN_POST_PLANKS_OAK.id || world.getBlockId(blockX, blockY, blockZ) == Blocks.SIGN_WALL_PLANKS_OAK.id)
+        if (world.getBlockId(blockX, blockY, blockZ) == Blocks.SIGN_POST_PLANKS_OAK.id() || world.getBlockId(blockX, blockY, blockZ) == Blocks.SIGN_WALL_PLANKS_OAK.id())
         {
             TileEntitySign sign = (TileEntitySign) world.getBlockEntity(blockX, blockY, blockZ);
             if ((DyeColor.WHITE.itemMeta - itemstack.getMetadata()) != sign.getColor().id)
@@ -57,20 +57,20 @@ public class ItemDye extends Item
         if(itemstack.getMetadata() == DyeColor.WHITE.itemMeta)
         {
             int id = world.getBlockId(blockX, blockY, blockZ);
-            Block block = Blocks.blocksList[id];
-            if (block instanceof IBonemealable){
-               if (((IBonemealable) block).onBonemealUsed(itemstack, player, world, blockX, blockY, blockZ, side, xPlaced, yPlaced)){
+            Block<?> block = Blocks.blocksList[id];
+            if (Block.hasLogicClass(block, IBonemealable.class)){
+               if (((IBonemealable) block.getLogic()).onBonemealUsed(itemstack, player, world, blockX, blockY, blockZ, side, xPlaced, yPlaced)){
                    return true;
                }
             }
-            if(id == Blocks.DIRT.id)
+            if(id == Blocks.DIRT.id())
             {
                 if(!world.isClientSide)
                 {
                     if(Blocks.lightBlock[world.getBlockId(blockX, blockY + 1, blockZ)] <= 2) {
-                    	int grass = Blocks.GRASS.id;
+                    	int grass = Blocks.GRASS.id();
                     	if(world.dimensionData.getWorldType() == WorldTypes.OVERWORLD_RETRO) {
-                    		grass = Blocks.GRASS_RETRO.id;
+                    		grass = Blocks.GRASS_RETRO.id();
                     	}
                         world.setBlockWithNotify(blockX, blockY, blockZ, grass);
                         if (player == null || player.getGamemode().consumeBlocks())
@@ -81,12 +81,12 @@ public class ItemDye extends Item
                 }
                 return true;
             }
-            if(id == Blocks.DIRT_SCORCHED.id)
+            if(id == Blocks.DIRT_SCORCHED.id())
             {
                 if (!world.isClientSide)
                 {
                     if(Blocks.lightBlock[world.getBlockId(blockX, blockY + 1, blockZ)] <= 2) {
-                        int grass = Blocks.GRASS_SCORCHED.id;
+                        int grass = Blocks.GRASS_SCORCHED.id();
                         world.setBlockWithNotify(blockX, blockY, blockZ, grass);
                         if (player == null || player.getGamemode().consumeBlocks())
                         {
@@ -129,27 +129,27 @@ label0:
                         }
                         if(itemRand.nextInt(10) != 0)
                         {
-                            if(world.getBlockId(k1, l1-1, i2) == Blocks.DIRT_SCORCHED.id ||
-                                    world.getBlockId(k1, l1-1, i2) == Blocks.DIRT_SCORCHED_RICH.id)
-                                world.setBlockWithNotify(k1, l1, i2, Blocks.SPINIFEX.id);
+                            if(world.getBlockId(k1, l1-1, i2) == Blocks.DIRT_SCORCHED.id() ||
+                                    world.getBlockId(k1, l1-1, i2) == Blocks.DIRT_SCORCHED_RICH.id())
+                                world.setBlockWithNotify(k1, l1, i2, Blocks.SPINIFEX.id());
                             else
-                                world.setBlockWithNotify(k1, l1, i2, Blocks.TALLGRASS.id);
+                                world.setBlockWithNotify(k1, l1, i2, Blocks.TALLGRASS.id());
                             continue;
                         }
                         int r = itemRand.nextInt(12);
                         Biome biome = world.getBlockBiome(k1, l1, i2);
                         if (r < 1){
-                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_YELLOW.id);
+                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_YELLOW.id());
                         } else if (r < 2) {
-                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_RED.id);
+                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_RED.id());
                         } else if (r < 4 && (biome == Biomes.OVERWORLD_BIRCH_FOREST || biome == Biomes.OVERWORLD_SEASONAL_FOREST)) {
-                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_PINK.id);
+                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_PINK.id());
                         } else if (r < 6 && (biome == Biomes.OVERWORLD_MEADOW || biome == Biomes.OVERWORLD_BOREAL_FOREST || biome == Biomes.OVERWORLD_SHRUBLAND)) {
-                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_PURPLE.id);
+                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_PURPLE.id());
                         } else if (r < 8 && (biome == Biomes.OVERWORLD_FOREST || biome == Biomes.OVERWORLD_SWAMPLAND || biome == Biomes.OVERWORLD_RAINFOREST || biome == Biomes.OVERWORLD_GRASSLANDS || biome == Biomes.OVERWORLD_CAATINGA)) {
-                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_LIGHT_BLUE.id);
+                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_LIGHT_BLUE.id());
                         } else if (r < 10 && (biome == Biomes.OVERWORLD_PLAINS || biome == Biomes.OVERWORLD_GRASSLANDS || biome == Biomes.OVERWORLD_OUTBACK || biome == Biomes.OVERWORLD_OUTBACK_GRASSY)) {
-                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_ORANGE.id);
+                            world.setBlockWithNotify(k1, l1, i2, Blocks.FLOWER_ORANGE.id());
                         }
                     }
                 }
@@ -165,13 +165,13 @@ label0:
     }
 
     @Override
-    public boolean useItemOnEntity(ItemStack itemstack, Mob mob, Player entityPlayer)
+    public boolean useItemOnEntity(ItemStack itemstack, Mob mob, Player player)
     {
         if(mob instanceof MobSheep)
         {
             MobSheep mobSheep = (MobSheep)mob;
             DyeColor woolColor = DyeColor.colorFromItemMeta(itemstack.getMetadata());
-            if(mobSheep.getFleeceColor() != woolColor && itemstack.consumeItem(entityPlayer))
+            if(mobSheep.getFleeceColor() != woolColor && itemstack.consumeItem(player))
             {
                 mobSheep.setFleeceColor(woolColor);
                 return true;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java b/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java
index 1a78d77de..593c81c89 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.item;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockBrazier;
-import net.minecraft.core.block.BlockFluid;
-import net.minecraft.core.block.BlockTNT;
+import net.minecraft.core.block.BlockLogicBrazier;
+import net.minecraft.core.block.BlockLogicFluid;
+import net.minecraft.core.block.BlockLogicTNT;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.material.ToolMaterial;
@@ -34,7 +34,7 @@ public class ItemFireStriker extends Item
         int i1 = world.getBlockId(blockX, blockY, blockZ);
         if(i1 == 0)
         {
-            if(world.setBlockWithNotify(blockX, blockY, blockZ, Blocks.FIRE.id)){
+            if(world.setBlockWithNotify(blockX, blockY, blockZ, Blocks.FIRE.id())){
                 world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double) blockX + 0.5D, (double) blockY + 0.5D, (double) blockZ + 0.5D, "fire.ignite", 1.0F, itemRand.nextFloat() * 0.4F + 0.8F);
                 itemstack.damageItem(1, entityplayer);
                 return true;
@@ -50,19 +50,19 @@ public class ItemFireStriker extends Item
             blockX += direction.getOffsetX();
             blockY += direction.getOffsetY();
             blockZ += direction.getOffsetZ();
-            Block b = world.getBlock(blockX, blockY, blockZ);
-            if (b instanceof BlockBrazier && !((BlockBrazier)b).isBurning()) {
-                if (world.getBlock(blockX + 1,  blockY, blockZ) instanceof BlockFluid ||
-                    world.getBlock(blockX - 1,  blockY, blockZ) instanceof BlockFluid ||
-                    world.getBlock(blockX,      blockY, blockZ + 1) instanceof BlockFluid ||
-                    world.getBlock(blockX,      blockY, blockZ - 1) instanceof BlockFluid) {
+            Block<?> b = world.getBlock(blockX, blockY, blockZ);
+            if (Block.hasLogicClass(b, BlockLogicBrazier.class) && !(((BlockLogicBrazier)(b.getLogic())).isBurning())) {
+                if (Block.hasLogicClass(world.getBlock(blockX + 1,  blockY, blockZ), BlockLogicFluid.class) ||
+                    Block.hasLogicClass(world.getBlock(blockX - 1,  blockY, blockZ), BlockLogicFluid.class) ||
+                    Block.hasLogicClass(world.getBlock(blockX,  blockY, blockZ + 1), BlockLogicFluid.class) ||
+                    Block.hasLogicClass(world.getBlock(blockX,  blockY, blockZ - 1), BlockLogicFluid.class)) {
                     return;
                 }
-                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.BRAZIER_ACTIVE.id, 0);
+                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.BRAZIER_ACTIVE.id(), 0);
                 itemStack.damageItem(1, null);
                 world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double) blockX + 0.5D, (double) blockY + 0.5D, (double) blockZ + 0.5D, "fire.ignite", 1.0F, world.rand.nextFloat() * 0.4F + 0.8F);
-            } else if (b instanceof BlockTNT) {
-                ((BlockTNT)b).ignite(world, blockX, blockY, blockZ, true);
+            } else if (Block.hasLogicClass(b, BlockLogicTNT.class)) {
+                ((BlockLogicTNT)b.getLogic()).ignite(world, blockX, blockY, blockZ, true);
             }
         }
     }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java b/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java
index 50ee6e1bb..70c0d2f9f 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java
@@ -32,7 +32,7 @@ public class ItemFlag extends Item
     public boolean onUseItemOnBlock(ItemStack stack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
     {
         // copy flag data to empty flag
-		if (world.getBlockId(blockX, blockY, blockZ) == Blocks.FLAG.id && !entityplayer.isSneaking()) {
+		if (world.getBlockId(blockX, blockY, blockZ) == Blocks.FLAG.id() && !entityplayer.isSneaking()) {
 			TileEntityFlag flag = (TileEntityFlag) world.getBlockEntity(blockX, blockY, blockZ);
 			if (flag != null) {
 				CompoundTag flagData = stack.getData().getCompoundOrDefault("FlagData", new CompoundTag());
@@ -71,7 +71,7 @@ public class ItemFlag extends Item
         }
 
         world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.FLAG, EnumBlockSoundEffectType.PLACE);
-        world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.FLAG.id, 0);
+        world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.FLAG.id(), 0);
         
         stack.consumeItem(entityplayer);
         TileEntityFlag tileEntityFlag = (TileEntityFlag) world.getBlockEntity(blockX, blockY, blockZ);
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemMap.java b/game/core/src/main/java/net/minecraft/core/item/ItemMap.java
index 044790b29..422979c86 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemMap.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemMap.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.item;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityFlag;
 import net.minecraft.core.block.material.Material;
@@ -121,7 +120,7 @@ public class ItemMap extends Item implements IComplexItem
 	}
 	@Override
 	public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
-		if (world.getBlockId(blockX, blockY, blockZ) == Blocks.FLAG.id) {
+		if (world.getBlockId(blockX, blockY, blockZ) == Blocks.FLAG.id()) {
 			ItemMapSavedData mapData = getOrCreateSavedData(itemstack, world);
 			if (mapData != null){
 				TileEntityFlag flag = (TileEntityFlag) world.getBlockEntity(blockX, blockY, blockZ);
@@ -200,11 +199,11 @@ public class ItemMap extends Item implements IComplexItem
 					int rand = blockX + blockZ * 0x389bf;
 					rand = rand * rand * 0x1dd6751 + rand * 11;
 					if((rand >> 20 & 1) == 0) {
-						blockCounts.putIfAbsent(Blocks.DIRT.id, new HashMap<>());
-						blockCounts.get(Blocks.DIRT.id).put(-1, blockCounts.get(Blocks.DIRT.id).getOrDefault(-1, 0) + 10);
+						blockCounts.putIfAbsent(Blocks.DIRT.id(), new HashMap<>());
+						blockCounts.get(Blocks.DIRT.id()).put(-1, blockCounts.get(Blocks.DIRT.id()).getOrDefault(-1, 0) + 10);
 					} else {
-						blockCounts.putIfAbsent(Blocks.STONE.id, new HashMap<>());
-						blockCounts.get(Blocks.STONE.id).put(-1, blockCounts.get(Blocks.STONE.id).getOrDefault(-1, 0) + 10);
+						blockCounts.putIfAbsent(Blocks.STONE.id(), new HashMap<>());
+						blockCounts.get(Blocks.STONE.id()).put(-1, blockCounts.get(Blocks.STONE.id()).getOrDefault(-1, 0) + 10);
 					}
 					pixelHeight = 100D;
 				} else {
@@ -218,16 +217,16 @@ public class ItemMap extends Item implements IComplexItem
 								do {
 									runLoop = false;
 									id = chunk.getBlockID(_x + blockInChunkX, height, _z + blockInChunkZ);
-									if(id <= 0 || (height > 0 && Blocks.blocksList[id].blockMaterial.color == MaterialColor.none)) {
+									if(id <= 0 || (height > 0 && Blocks.blocksList[id].getMaterial().color == MaterialColor.none)) {
 										runLoop = true;
 										height--;
 									}
 								} while (runLoop);
-								if(Blocks.blocksList[id].blockMaterial == Material.water) {
+								if(Blocks.blocksList[id].getMaterial() == Material.water) {
 									int _y = height;
                                     int _blockID = chunk.getBlockID(_x + blockInChunkX, _y--, _z + blockInChunkZ);
                                     waterDepth++;
-                                    while (_y > 0 && _blockID > 0 && Blocks.blocksList[_blockID].blockMaterial == Material.water) {
+                                    while (_y > 0 && _blockID > 0 && Blocks.blocksList[_blockID].getMaterial() == Material.water) {
                                         _blockID = chunk.getBlockID(_x + blockInChunkX, _y--, _z + blockInChunkZ);
                                         waterDepth++;
                                     }
@@ -270,7 +269,7 @@ public class ItemMap extends Item implements IComplexItem
 				
 				int colorIndex = 0;
 				if(id > 0) {
-					MaterialColor mapcolor = Blocks.blocksList[id].blockMaterial.color;
+					MaterialColor mapcolor = Blocks.blocksList[id].getMaterial().color;
 					if(mapcolor == MaterialColor.water) {
 						double d3 = (double) waterDepth * 0.1D + (double) (x + z & 1) * 0.2D;
 						brightness = 1;
@@ -372,7 +371,7 @@ public class ItemMap extends Item implements IComplexItem
 		}
 		return null;
     }
-    
+
     @Override
     public String getTranslatedName(ItemStack itemstack) {
 		if (!hasInitialized(itemstack)) return I18n.getInstance().translateKey(itemstack.getItemKey() + ".blank.name");
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java b/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java
index 7bbacc395..83e29e168 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java
@@ -2,8 +2,8 @@ package net.minecraft.core.item;
 
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockRail;
 
+import net.minecraft.core.block.BlockLogicRail;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.entity.vehicle.MinecartEntity;
@@ -24,8 +24,8 @@ public class ItemMinecart extends Item {
 
     @Override
     public boolean onUseItemOnBlock(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
-        Block block = world.getBlock(blockX, blockY, blockZ);
-        if (!(block instanceof BlockRail)) { return false; }
+        Block<?> block = world.getBlock(blockX, blockY, blockZ);
+        if (!Block.hasLogicClass(block, BlockLogicRail.class)) { return false; }
 
         if(!world.isClientSide) {
             world.entityJoinedWorld(new MinecartEntity(world, (float) blockX + 0.5F, (float) blockY + 0.5F, (float) blockZ + 0.5F, minecartType));
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java b/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java
index 79d9dac51..f3a75adf5 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java
@@ -32,10 +32,10 @@ public class ItemPaintBrush extends Item {
         }
 
         final int id = world.getBlockId(blockX, blockY, blockZ);
-        final Block block = Blocks.getBlock(id);
+        final Block<?> block = Blocks.getBlock(id);
 
-        if (block instanceof IPaintable) {
-            final IPaintable paintable = (IPaintable) block;
+        if (Block.hasLogicClass(block, IPaintable.class)) {
+            final IPaintable paintable = (IPaintable) block.getLogic();
             if (!paintable.canBePainted()) return false;
             final DyeColor color = getColor(itemstack);
             if (color != null) {
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java b/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java
index db97cf0ad..0ada25eff 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.item;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.tag.BlockTags;
@@ -42,7 +41,7 @@ public class ItemPebble extends Item implements IDispensable
     {
         int id = world.getBlockId(blockX, blockY, blockZ);
         int meta = world.getBlockMetadata(blockX, blockY, blockZ);
-        if (id != Blocks.OVERLAY_PEBBLES.id && Blocks.blocksList[id] != null && Blocks.blocksList[id].hasTag(BlockTags.PLACE_OVERWRITES))
+        if (id != Blocks.OVERLAY_PEBBLES.id() && Blocks.blocksList[id] != null && Blocks.blocksList[id].hasTag(BlockTags.PLACE_OVERWRITES))
         {
             id = 0;
             meta = 0;
@@ -51,13 +50,13 @@ public class ItemPebble extends Item implements IDispensable
         {
             return false;
         }
-        if (blockY == world.getHeightBlocks() - 1 && Blocks.OVERLAY_PEBBLES.blockMaterial.isSolid())
+        if (blockY == world.getHeightBlocks() - 1 && Blocks.OVERLAY_PEBBLES.getMaterial().isSolid())
         {
             return false;
         }
 
         // Check if we're placing "inside" a layer
-        if (id == Blocks.OVERLAY_PEBBLES.id && side == Side.TOP)
+        if (id == Blocks.OVERLAY_PEBBLES.id() && side == Side.TOP)
         {
 
             final int newMeta = meta + 1;
@@ -68,7 +67,7 @@ public class ItemPebble extends Item implements IDispensable
 
             if (newMeta < 3)
             {
-                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.OVERLAY_PEBBLES.id, newMeta);
+                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.OVERLAY_PEBBLES.id(), newMeta);
                 world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.OVERLAY_PEBBLES, EnumBlockSoundEffectType.PLACE);
                 itemstack.consumeItem(player);
                 return true;
@@ -88,7 +87,7 @@ public class ItemPebble extends Item implements IDispensable
         }
 
         // Check if the block we're placing into is a layer
-        if (id == Blocks.OVERLAY_PEBBLES.id)
+        if (id == Blocks.OVERLAY_PEBBLES.id())
         {
             final int newMeta = meta + 1;
 
@@ -100,7 +99,7 @@ public class ItemPebble extends Item implements IDispensable
 
             if (newMeta < 3)
             {
-                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.OVERLAY_PEBBLES.id, newMeta);
+                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.OVERLAY_PEBBLES.id(), newMeta);
                 world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.OVERLAY_PEBBLES, EnumBlockSoundEffectType.PLACE);
                 itemstack.consumeItem(player);
                 return true;
@@ -109,9 +108,9 @@ public class ItemPebble extends Item implements IDispensable
         }
 
         // Regular placement, as all else fails
-        if (world.canBlockBePlacedAt(Blocks.OVERLAY_PEBBLES.id, blockX, blockY, blockZ, false, side) && world.isBlockOpaqueCube(blockX, blockY - 1, blockZ))
+        if (world.canBlockBePlacedAt(Blocks.OVERLAY_PEBBLES.id(), blockX, blockY, blockZ, false, side) && world.isBlockOpaqueCube(blockX, blockY - 1, blockZ))
         {
-            if (world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.OVERLAY_PEBBLES.id, 0))
+            if (world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.OVERLAY_PEBBLES.id(), 0))
             {
                 Blocks.OVERLAY_PEBBLES.onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
                 world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.OVERLAY_PEBBLES, EnumBlockSoundEffectType.PLACE);
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java b/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java
index 9ca22a495..2f08bbaa2 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java
@@ -14,9 +14,9 @@ import java.util.Random;
 
 public class ItemPlaceable extends Item {
 	
-	public Block blockToPlace;
+	public Block<?> blockToPlace;
 	
-	public ItemPlaceable(String name, String namespaceId, int id, Block blockToPlace) {
+	public ItemPlaceable(String name, String namespaceId, int id, Block<?> blockToPlace) {
 		super(name, namespaceId, id);
 		
 		this.blockToPlace = blockToPlace;
@@ -36,8 +36,8 @@ public class ItemPlaceable extends Item {
 		if(blockY < 0 || blockY >= world.getHeightBlocks()) {
 			return false;
 		}
-		if(world.canBlockBePlacedAt(blockToPlace.id, blockX, blockY, blockZ, false, side) && stack.consumeItem(player)) {
-			if(world.setBlockWithNotify(blockX, blockY, blockZ, blockToPlace.id)) {
+		if(world.canBlockBePlacedAt(blockToPlace.id(), blockX, blockY, blockZ, false, side) && stack.consumeItem(player)) {
+			if(world.setBlockWithNotify(blockX, blockY, blockZ, blockToPlace.id())) {
 				if (player == null) {
 					blockToPlace.onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
 				} else {
@@ -55,7 +55,7 @@ public class ItemPlaceable extends Item {
 		int x = blockX + direction.getOffsetX();
 		int y = blockY + direction.getOffsetY();
 		int z = blockZ + direction.getOffsetZ();
-		Block b = world.getBlock(x, y, z);
+		Block<?> b = world.getBlock(x, y, z);
 		if (b == null || BlockTags.PLACE_OVERWRITES.appliesTo(b)) {
 			onUseItemOnBlock(itemStack, null, world, x, y, z, direction.getSide(), 0.5, 0.5);
 		}
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemRope.java b/game/core/src/main/java/net/minecraft/core/item/ItemRope.java
index 0cb154f31..bf6d2d424 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemRope.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemRope.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.item;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockRope;
+import net.minecraft.core.block.BlockLogicRope;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.Side;
@@ -9,7 +9,7 @@ import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
 public class ItemRope extends ItemPlaceable {
-    public ItemRope(String name, String namespaceId, int id, Block blockToPlace) {
+    public ItemRope(String name, String namespaceId, int id, Block<?> blockToPlace) {
         super(name, namespaceId, id, blockToPlace);
     }
     @Override
@@ -23,7 +23,7 @@ public class ItemRope extends ItemPlaceable {
             int _y = blockY;
             while (_y > 0){
                 _y--;
-                if (world.canBlockBePlacedAt(blockToPlace.id, blockX, _y, blockZ, false, side)){
+                if (world.canBlockBePlacedAt(blockToPlace.id(), blockX, _y, blockZ, false, side)){
                     blockY = _y;
                     break;
                 } else if (world.getBlock(blockX, _y, blockZ) != blockToPlace) {
@@ -43,8 +43,8 @@ public class ItemRope extends ItemPlaceable {
         if(blockY < 0 || blockY >= world.getHeightBlocks()) {
             return false;
         }
-        if(world.canBlockBePlacedAt(blockToPlace.id, blockX, blockY, blockZ, false, side) && stack.consumeItem(player)) {
-            if(world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockToPlace.id, placeOnSide ? BlockRope.MASK_ROPE_CONNECT : 0)) {
+        if(world.canBlockBePlacedAt(blockToPlace.id(), blockX, blockY, blockZ, false, side) && stack.consumeItem(player)) {
+            if(world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockToPlace.id(), placeOnSide ? BlockLogicRope.MASK_ROPE_CONNECT : 0)) {
                 if (player == null) {
                     blockToPlace.onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
                 } else {
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemSaddle.java b/game/core/src/main/java/net/minecraft/core/item/ItemSaddle.java
index ecb9f337a..58b40e401 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemSaddle.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemSaddle.java
@@ -14,11 +14,11 @@ public class ItemSaddle extends Item
     }
 
     @Override
-    public boolean useItemOnEntity(ItemStack itemstack, Mob entityliving, Player entityPlayer)
+    public boolean useItemOnEntity(ItemStack itemstack, Mob mob, Player player)
     {
-        if(entityliving instanceof MobPig && itemstack.consumeItem(entityPlayer))
+        if(mob instanceof MobPig && itemstack.consumeItem(player))
         {
-            MobPig entitypig = (MobPig)entityliving;
+            MobPig entitypig = (MobPig) mob;
             if(!entitypig.getSaddled())
             {
                 entitypig.setSaddled(true);
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java b/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java
index b40949425..2d85a85ca 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java
@@ -14,11 +14,11 @@ import net.minecraft.core.world.World;
 import java.util.Random;
 
 public class ItemSeeds extends Item {
-	private int cropsId;
+	private final Block<?> cropsBlock;
 
-	public ItemSeeds(String name, String namespaceId, int id, Block cropsBlock) {
+	public ItemSeeds(String name, String namespaceId, int id, Block<?> cropsBlock) {
 		super(name, namespaceId, id);
-		cropsId = cropsBlock.id;
+		this.cropsBlock = cropsBlock;
 	}
 
 	@Override
@@ -28,9 +28,9 @@ public class ItemSeeds extends Item {
 			blockY += side.getOffsetY();
 			blockZ += side.getOffsetZ();
 		}
-		if(world.getBlockId(blockX, blockY - 1, blockZ) == Blocks.FARMLAND_DIRT.id && world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
-			if(world.setBlockWithNotify(blockX, blockY, blockZ, cropsId)) {
-				world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.blocksList[cropsId], EnumBlockSoundEffectType.PLACE);
+		if(world.getBlockId(blockX, blockY - 1, blockZ) == Blocks.FARMLAND_DIRT.id() && world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
+			if(world.setBlockWithNotify(blockX, blockY, blockZ, cropsBlock.id())) {
+				world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, cropsBlock, EnumBlockSoundEffectType.PLACE);
 				itemstack.consumeItem(entityplayer);
 				return true;
 			}
@@ -42,7 +42,7 @@ public class ItemSeeds extends Item {
 		int x = blockX + direction.getOffsetX();
 		int y = blockY + direction.getOffsetY();
 		int z = blockZ + direction.getOffsetZ();
-		Block b = world.getBlock(x, y, z);
+		Block<?> b = world.getBlock(x, y, z);
 		if (b == null || BlockTags.PLACE_OVERWRITES.appliesTo(b)) {
 			onUseItemOnBlock(itemStack, null, world, x, y, z, direction.getSide(), 0.5, 0.5);
 		}
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemSign.java b/game/core/src/main/java/net/minecraft/core/item/ItemSign.java
index b9283d055..d092dd03b 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemSign.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemSign.java
@@ -45,11 +45,11 @@ public class ItemSign extends Item
         if(sideHit == 1)
         {
             world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.SIGN_POST_PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
-            world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.SIGN_POST_PLANKS_OAK.id, MathHelper.floor((double)(((entityplayer.yRot + 180F) * 16F) / 360F) + 0.5D) & 0xf);
+            world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.SIGN_POST_PLANKS_OAK.id(), MathHelper.floor((double)(((entityplayer.yRot + 180F) * 16F) / 360F) + 0.5D) & 0xf);
         } else
         {
             world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.SIGN_WALL_PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
-            world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.SIGN_WALL_PLANKS_OAK.id, sideHit);
+            world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.SIGN_WALL_PLANKS_OAK.id(), sideHit);
         }
         itemstack.consumeItem(entityplayer);
         TileEntitySign tileentitysign = (TileEntitySign)world.getBlockEntity(blockX, blockY, blockZ);
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemStack.java b/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
index f62dbcf25..b341462d1 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
@@ -42,24 +42,24 @@ public final class ItemStack {
         this(item.asItem(), stackSize, metadata);
     }
 
-    public ItemStack(Block block)
+    public ItemStack(Block<?> block)
     {
         this(block, 1);
     }
 
-    public ItemStack(Block block, int stackSize)
+    public ItemStack(Block<?> block, int stackSize)
     {
-        this(block.id, stackSize, 0);
+        this(block.id(), stackSize, 0);
     }
 
-    public ItemStack(Block block, int stackSize, int metadata)
+    public ItemStack(Block<?> block, int stackSize, int metadata)
     {
-        this(block.id, stackSize, metadata);
+        this(block.id(), stackSize, metadata);
     }
 
-    public ItemStack(Block block, int stackSize, int metadata, @Nullable CompoundTag tag)
+    public ItemStack(Block<?> block, int stackSize, int metadata, @Nullable CompoundTag tag)
     {
-        this(block.id, stackSize, metadata, tag);
+        this(block.id(), stackSize, metadata, tag);
     }
 
     public ItemStack(Item item)
@@ -92,6 +92,7 @@ public final class ItemStack {
         this.metadata = itemStack.metadata;
         this.stackSize = itemStack.stackSize;
         this.tag = new CompoundTag(itemStack.tag);
+        this.animationsToGo = 0;
     }
 
     public ItemStack(int itemID, int stackSize, int metadata, @Nullable CompoundTag tag)
@@ -131,7 +132,7 @@ public final class ItemStack {
         return flag;
     }
 
-    public float getStrVsBlock(Block block)
+    public float getStrVsBlock(Block<?> block)
     {
         return getItem().getStrVsBlock(this, block);
     }
@@ -200,8 +201,8 @@ public final class ItemStack {
 			itemID = 0;
 		}
 		
-		if(itemID == Blocks.CHEST_LEGACY.id) itemID = Blocks.CHEST_PLANKS_OAK.id;
-		if(itemID == Blocks.CHEST_LEGACY_PAINTED.id) itemID = Blocks.CHEST_PLANKS_OAK_PAINTED.id;
+		if(itemID == Blocks.CHEST_LEGACY.id()) itemID = Blocks.CHEST_PLANKS_OAK.id();
+		if(itemID == Blocks.CHEST_LEGACY_PAINTED.id()) itemID = Blocks.CHEST_PLANKS_OAK_PAINTED.id();
 	}
 
     public int getMaxStackSize()
@@ -291,12 +292,12 @@ public final class ItemStack {
         metadata -= i;
     }
 
-    public void hitEntity(Mob entityliving, Player entityplayer)
+    public void hitEntity(Mob target, Player attacker)
     {
-        boolean flag = Item.itemsList[itemID].hitEntity(this, entityliving, entityplayer);
+        boolean flag = Item.itemsList[itemID].hitEntity(this, target, attacker);
         if(flag)
         {
-            entityplayer.addStat(getItem().getStat(StatList.STAT_USED), 1);
+            attacker.addStat(getItem().getStat(StatList.STAT_USED), 1);
         }
     }
     
@@ -328,14 +329,14 @@ public final class ItemStack {
         return Item.itemsList[itemID].getDamageVsEntity(entity);
     }
 
-    public boolean canHarvestBlock(Mob entityLiving, Block block)
+    public boolean canHarvestBlock(Mob mob, Block<?> block)
     {
-        return Item.itemsList[itemID].canHarvestBlock(entityLiving, this, block);
+        return Item.itemsList[itemID].canHarvestBlock(mob, this, block);
     }
 
-    public boolean useItemOnEntity(Mob entityliving, Player entityPlayer)
+    public boolean useItemOnEntity(Mob mob, Player entityPlayer)
     {
-        return Item.itemsList[itemID].useItemOnEntity(this, entityliving, entityPlayer);
+        return Item.itemsList[itemID].useItemOnEntity(this, mob, entityPlayer);
     }
 
     public ItemStack copy()
diff --git a/game/core/src/main/java/net/minecraft/core/item/Items.java b/game/core/src/main/java/net/minecraft/core/item/Items.java
index e4a528f69..aa7b83735 100644
--- a/game/core/src/main/java/net/minecraft/core/item/Items.java
+++ b/game/core/src/main/java/net/minecraft/core/item/Items.java
@@ -2,7 +2,6 @@ package net.minecraft.core.item;
 
 import net.minecraft.core.achievement.stat.Stat;
 import net.minecraft.core.achievement.stat.StatList;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.vehicle.MinecartEntity;
 import net.minecraft.core.item.material.ArmorMaterial;
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
index fec0178f8..f9921b073 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
@@ -11,25 +11,27 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Objects;
 import java.util.Random;
 
-public class ItemBlock extends Item
+public class ItemBlock<T extends BlockLogic> extends Item
 {
 
-    protected int blockID;
+    protected @NotNull Block<T> block;
 
-    public ItemBlock(Block block)
+    public ItemBlock(@NotNull Block<T> block)
     {
-        super(block.namespaceID, block.id);
-        blockID = block.id;
+        super(block.namespaceId(), block.id());
+        this.block = Objects.requireNonNull(block);
         setKey(block.getKey());
     }
 
-    public Block getBlock()
+    public @NotNull Block<T> getBlock()
     {
-        return Blocks.blocksList[blockID];
+        return block;
     }
 
     @Override
@@ -45,10 +47,9 @@ public class ItemBlock extends Item
 		if(y < 0 || y >= world.getHeightBlocks()) {
 			return false;
 		}
-		if(world.canBlockBePlacedAt(blockID, x, y, z, false, side)) {
-			Block block = Blocks.blocksList[blockID];
+		if(world.canBlockBePlacedAt(block.id(), x, y, z, false, side)) {
 			int meta = getPlacedBlockMetadata(player, stack, world, x, y, z, side, xPlaced, yPlaced);
-			if(world.setBlockAndMetadataWithNotify(x, y, z, blockID, meta)) {
+			if(world.setBlockAndMetadataWithNotify(x, y, z, block.id(), meta)) {
 				stack.consumeItem(player);
 				if (player == null) {
                     block.onBlockPlacedOnSide(world, x, y, z, side, xPlaced, yPlaced);
@@ -67,7 +68,7 @@ public class ItemBlock extends Item
         int x = blockX + direction.getOffsetX();
         int y = blockY + direction.getOffsetY();
         int z = blockZ + direction.getOffsetZ();
-        Block b = world.getBlock(x, y, z);
+        Block<?> b = world.getBlock(x, y, z);
         if (b == null || BlockTags.PLACE_OVERWRITES.appliesTo(b)) {
             onUseItemOnBlock(itemStack, null, world, x, y, z, direction.getSide(), 0.5, 0.5);
         }
@@ -75,18 +76,18 @@ public class ItemBlock extends Item
 
     public int getPlacedBlockMetadata(@Nullable Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced)
     {
-    	return Blocks.getBlock(blockID).getPlacedBlockMetadata(player, stack, world, x, y, z, side, xPlaced, yPlaced);
+    	return block.getPlacedBlockMetadata(player, stack, world, x, y, z, side, xPlaced, yPlaced);
     }
 
     @Override
     public String getLanguageKey(ItemStack itemstack)
     {
-        return Blocks.blocksList[blockID].getLanguageKey(itemstack.getMetadata());
+        return block.getLanguageKey(itemstack.getMetadata());
     }
 
     @Override
     public String getKey()
     {
-        return Blocks.blocksList[blockID].getKey();
+        return block.getKey();
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java
index cf75bd63c..4c855eb14 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java
@@ -1,26 +1,25 @@
 package net.minecraft.core.item.block;
 
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
-import net.minecraft.core.util.helper.Direction;
-import net.minecraft.core.util.phys.HitResult;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.util.phys.Vec3;
+import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class ItemBlockAlgae extends ItemBlock
+public class ItemBlockAlgae<T extends BlockLogic> extends ItemBlock<T>
 {
 
-    public ItemBlockAlgae(Block block)
+    public ItemBlockAlgae(Block<T> block)
     {
         super(block);
         setMaxDamage(0);
@@ -36,34 +35,19 @@ public class ItemBlockAlgae extends ItemBlock
     @Override
     public ItemStack onUseItem(ItemStack itemstack, World world, Player player)
     {
-        float f = 1.0F;
-        float f1 = player.xRotO + (player.xRot - player.xRotO) * f;
-        float f2 = player.yRotO + (player.yRot - player.yRotO) * f;
-        double d = player.xo + (player.x - player.xo) * (double)f;
-        double d1 = (player.yo + (player.y - player.yo) * (double)f + 1.62D) - (double)player.heightOffset;
-        double d2 = player.zo + (player.z - player.zo) * (double)f;
-        Vec3 vec3 = Vec3.getTempVec3(d, d1, d2);
-        float f3 = MathHelper.cos(-f2 * 0.01745329F - MathHelper.PI);
-        float f4 = MathHelper.sin(-f2 * 0.01745329F - MathHelper.PI);
-        float f5 = -MathHelper.cos(-f1 * 0.01745329F);
-        float f6 = MathHelper.sin(-f1 * 0.01745329F);
-        float f7 = f4 * f5;
-        float f8 = f6;
-        float f9 = f3 * f5;
-        double d3 = 5D;
-        Vec3 vec31 = vec3.add((double)f7 * d3, (double)f8 * d3, (double)f9 * d3);
-        HitResult movingobjectposition = world.checkBlockCollisionBetweenPoints(vec3, vec31, true);
-        if(movingobjectposition == null)
+        double reachDistance = player.getGamemode().getBlockReachDistance();
+        HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, true, false);
+        if(rayTraceResult == null)
         {
             return itemstack;
         }
-        if(movingobjectposition.hitType == HitResult.HitType.TILE)
+        if(rayTraceResult.hitType == HitResult.HitType.TILE)
         {
-            int blockX = movingobjectposition.x;
-            int blockY = movingobjectposition.y;
-            int blockZ = movingobjectposition.z;
+            int blockX = rayTraceResult.x;
+            int blockY = rayTraceResult.y;
+            int blockZ = rayTraceResult.z;
 
-            if(world.getBlockId(blockX, blockY, blockZ) == Blocks.FLUID_WATER_STILL.id)
+            if(world.getBlockId(blockX, blockY, blockZ) == Blocks.FLUID_WATER_STILL.id())
             {
                 blockY++;
             }
@@ -73,10 +57,9 @@ public class ItemBlockAlgae extends ItemBlock
 
             if(world.getBlockId(blockX, blockY, blockZ) != 0)
                 return itemstack;
-            Block block = Blocks.blocksList[Blocks.ALGAE.id];
-            if(itemstack.consumeItem(player) && world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.ALGAE.id, 0))
+            if(itemstack.consumeItem(player) && world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, block.id(), 0))
             {
-                Blocks.blocksList[blockID].onBlockPlacedByMob(world, blockX, blockY, blockZ, Side.NONE, player, 0.5, 0.5);
+                block.onBlockPlacedByMob(world, blockX, blockY, blockZ, Side.NONE, player, 0.5, 0.5);
                 world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
                 player.swingItem();
             }
@@ -90,11 +73,11 @@ public class ItemBlockAlgae extends ItemBlock
         int x = blockX + direction.getOffsetX();
         int y = blockY + direction.getOffsetY();
         int z = blockZ + direction.getOffsetZ();
-        Block b = world.getBlock(x, y, z);
-        Block bAbove = world.getBlock(x, y + 1, z);
+        Block<?> b = world.getBlock(x, y, z);
+        Block<?> bAbove = world.getBlock(x, y + 1, z);
         if (b == Blocks.FLUID_WATER_STILL && (bAbove == null || bAbove.hasTag(BlockTags.PLACE_OVERWRITES))) {
-            world.setBlockWithNotify(x, y + 1, z, Blocks.ALGAE.id);
-            Blocks.ALGAE.onBlockPlacedOnSide(world, x, y + 1, z, Side.NONE, 0.5, 0.5);
+            world.setBlockWithNotify(x, y + 1, z, block.id());
+            block.onBlockPlacedOnSide(world, x, y + 1, z, Side.NONE, 0.5, 0.5);
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
index f9920881b..d874c0e49 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
@@ -1,8 +1,7 @@
 package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLadder;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.BlockLogicLadder;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.item.ItemStack;
@@ -10,25 +9,23 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class ItemBlockLadder extends ItemBlock {
+public class ItemBlockLadder<T extends BlockLogicLadder> extends ItemBlock<T> {
 
-	private BlockLadder ladderBlock;
-	
-	public ItemBlockLadder(BlockLadder block) {
+	public ItemBlockLadder(Block<T> block) {
 		super(block);
-		
-		this.ladderBlock = block;
 	}
 	
 	@Override
 	public boolean onUseItemOnBlock(ItemStack stack, @Nullable Player player, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
-		Block clickedBlock = world.getBlock(x, y, z);
-		
-		if(clickedBlock == ladderBlock && player != null && !player.isSneaking()) {
-			Side clickedLadderSide = ladderBlock.getSideFromMeta(world.getBlockMetadata(x, y, z));
-			while(world.getBlock(x, y, z) == ladderBlock && ladderBlock.getSideFromMeta(world.getBlockMetadata(x, y, z)) == clickedLadderSide) y--;
-			int meta = ladderBlock.getMetaForSide(clickedLadderSide);
-			if(ladderBlock.canExistAt(world, x, y, z, meta)) {
+		Block<?> clickedBlock = world.getBlock(x, y, z);
+
+		BlockLogicLadder ladder = block.getLogic();
+
+		if(clickedBlock == block && player != null && !player.isSneaking()) {
+			Side clickedLadderSide = ladder.getSideFromMeta(world.getBlockMetadata(x, y, z));
+			while(world.getBlock(x, y, z) == block && ladder.getSideFromMeta(world.getBlockMetadata(x, y, z)) == clickedLadderSide) y--;
+			int meta = ladder.getMetaForSide(clickedLadderSide);
+			if(ladder.canExistAt(world, x, y, z, meta)) {
 				return placeBlock(world, x, y, z, meta, player, stack, clickedLadderSide, 0.5, 0.5);
 			}
 			
@@ -41,13 +38,13 @@ public class ItemBlockLadder extends ItemBlock {
 			z += side.getOffsetZ();
 		}
 		
-		Side sideForPlacement = ladderBlock.getSideForPlacement(world, x, y, z, side);
+		Side sideForPlacement = ladder.getSideForPlacement(world, x, y, z, side);
 		if(sideForPlacement == null) {
 			return false;
 		}
 		
-		int meta = ladderBlock.getMetaForSide(sideForPlacement);
-		if(ladderBlock.canExistAt(world, x, y, z, meta)) {
+		int meta = ladder.getMetaForSide(sideForPlacement);
+		if(ladder.canExistAt(world, x, y, z, meta)) {
 			return placeBlock(world, x, y, z, meta, player, stack, sideForPlacement, xPlaced, yPlaced);
 		}
 		
@@ -55,10 +52,10 @@ public class ItemBlockLadder extends ItemBlock {
 	}
 	
 	public boolean placeBlock(World world, int x, int y, int z, int meta, @Nullable Player player, ItemStack stack, Side side, double xPlaced, double yPlaced) {
-		if(world.canPlaceInsideBlock(x, y, z) && world.canBlockBePlacedAt(blockID, x, y, z, false, side) && stack.consumeItem(player)) {
-			if(world.setBlockAndMetadataWithNotify(x, y, z, blockID, meta)) {
-				Blocks.getBlock(blockID).onBlockPlacedByMob(world, x, y, z, side, player, xPlaced, yPlaced);
-				world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, ladderBlock, EnumBlockSoundEffectType.PLACE);
+		if(world.canPlaceInsideBlock(x, y, z) && world.canBlockBePlacedAt(block.id(), x, y, z, false, side) && stack.consumeItem(player)) {
+			if(world.setBlockAndMetadataWithNotify(x, y, z, block.id(), meta)) {
+				block.onBlockPlacedByMob(world, x, y, z, side, player, xPlaced, yPlaced);
+				world.playBlockSoundEffect(player, x + 0.5f, y + 0.5f, z + 0.5f, block, EnumBlockSoundEffectType.PLACE);
 				return true;
 			}
 		}
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLamp.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLamp.java
index 4414c2bb8..f51eca773 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLamp.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLamp.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.DyeColor;
@@ -8,10 +9,10 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class ItemBlockLamp extends ItemBlock
+public class ItemBlockLamp<T extends BlockLogic> extends ItemBlock<T>
 {
 
-    public ItemBlockLamp(Block block)
+    public ItemBlockLamp(Block<T> block)
     {
         super(block);
         setMaxDamage(0);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java
index 38c9c089e..4f512a8a9 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java
@@ -1,8 +1,7 @@
 package net.minecraft.core.item.block;
 
-import net.minecraft.core.block.BlockLayerBase;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.BlockLogicLayerBase;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
@@ -13,9 +12,9 @@ import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
 
-public class ItemBlockLayer extends ItemBlock
+public class ItemBlockLayer<T extends BlockLogicLayerBase> extends ItemBlock<T>
 {
-	public ItemBlockLayer(Block block)
+	public ItemBlockLayer(Block<T> block)
 	{
 		super(block);
 	}
@@ -23,27 +22,27 @@ public class ItemBlockLayer extends ItemBlock
 	@Override
 	public boolean onUseItemOnBlock(final ItemStack itemstack, final @Nullable Player player, final World world, int blockX, int blockY, int blockZ, final Side side, double xPlaced, final double yPlaced)
 	{
-		int id = world.getBlockId(blockX, blockY, blockZ);
+		Block<?> targetBlock = world.getBlock(blockX, blockY, blockZ);
 		int meta = world.getBlockMetadata(blockX, blockY, blockZ);
-		if (id != blockID && Blocks.blocksList[id] != null && Blocks.blocksList[id].hasTag(BlockTags.PLACE_OVERWRITES))
+		if (targetBlock != block && targetBlock != null && targetBlock.hasTag(BlockTags.PLACE_OVERWRITES))
 		{
-			id = 0;
+			targetBlock = null;
 			meta = 0;
 		}
 		if (itemstack.stackSize <= 0)
 		{
 			return false;
 		}
-		if (blockY == world.getHeightBlocks() - 1 && Blocks.blocksList[blockID].blockMaterial.isSolid())
+		if (blockY == world.getHeightBlocks() - 1 && block.getMaterial().isSolid())
 		{
 			return false;
 		}
 
 		// Check if we're placing "inside" a layer
-		if (id == blockID && side == Side.TOP)
+		if (targetBlock == block && side == Side.TOP)
 		{
 
-			final BlockLayerBase blockLayer = (BlockLayerBase) Blocks.blocksList[blockID];
+			final BlockLogicLayerBase blockLayer = block.getLogic();
 
 			final int newMeta = meta + 1;
 
@@ -55,40 +54,40 @@ public class ItemBlockLayer extends ItemBlock
 
 			if (newMeta < 7)
 			{
-				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockID, newMeta);
+				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, block.id(), newMeta);
 			}
 			else
 			{
-				if (blockLayer.getFullBlockID() != -1)
+				if (blockLayer.fullBlock != null)
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.getFullBlockID(), 0);
+					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.fullBlock.id(), 0);
 				}
 				else
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, blockID, 0);
+					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, block.id(), 0);
 				}
 			}
-			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockLayer, EnumBlockSoundEffectType.PLACE);
+			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 			itemstack.consumeItem(player);
 			return true;
 
 		}
 
 		// Offset position
-		if (id != 0)
+		if (targetBlock != null)
 		{
 			blockX += side.getOffsetX();
 			blockY += side.getOffsetY();
 			blockZ += side.getOffsetZ();
-			id = world.getBlockId(blockX, blockY, blockZ);
+			targetBlock = world.getBlock(blockX, blockY, blockZ);
 			meta = world.getBlockMetadata(blockX, blockY, blockZ);
 		}
 
 		// Check if the block we're placing into is a layer
-		if (id == blockID)
+		if (targetBlock == block)
 		{
 
-			final BlockLayerBase blockLayer = (BlockLayerBase) Blocks.blocksList[blockID];
+			final BlockLogicLayerBase blockLayer = block.getLogic();
 
 			final int newMeta = meta + 1;
 
@@ -100,35 +99,34 @@ public class ItemBlockLayer extends ItemBlock
 
 			if (newMeta < 7)
 			{
-				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockID, newMeta);
+				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, block.id(), newMeta);
 			}
 			else
 			{
-				if (blockLayer.getFullBlockID() != -1)
+				if (blockLayer.fullBlock != null)
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.getFullBlockID(), 0);
+					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.fullBlock.id(), 0);
 				}
 				else
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, blockID, 0);
+					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, block.id(), 0);
 				}
 			}
-			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockLayer, EnumBlockSoundEffectType.PLACE);
+			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 			itemstack.consumeItem(player);
 			return true;
 		}
 
 		// Regular placement, as all else fails
-		if (world.canBlockBePlacedAt(blockID, blockX, blockY, blockZ, false, side))
+		if (world.canBlockBePlacedAt(block.id(), blockX, blockY, blockZ, false, side))
 		{
-			final Block block = Blocks.blocksList[blockID];
 			int placeMeta = getPlacedBlockMetadata(player, itemstack, world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
-			if (world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockID, placeMeta))
+			if (world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, block.id(), placeMeta))
 			{
 				if (player == null) {
-					Blocks.blocksList[blockID].onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
+					block.onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
 				} else {
-					Blocks.blocksList[blockID].onBlockPlacedByMob(world, blockX, blockY, blockZ, Side.NONE, player, xPlaced, yPlaced);
+					block.onBlockPlacedByMob(world, blockX, blockY, blockZ, Side.NONE, player, xPlaced, yPlaced);
 				}
 				world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 				itemstack.consumeItem(player);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java
index d189a96cc..2515d87a0 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java
@@ -1,10 +1,9 @@
 package net.minecraft.core.item.block;
 
-import net.minecraft.core.block.BlockLayerBase;
-import net.minecraft.core.block.BlockLeavesBase;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLayerLeaves;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.BlockLogicLayerBase;
+import net.minecraft.core.block.BlockLogicLayerLeaves;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
@@ -14,9 +13,9 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class ItemBlockLayerLeaves extends ItemBlock
+public class ItemBlockLayerLeaves<T extends BlockLogicLayerLeaves> extends ItemBlock<T>
 {
-	public ItemBlockLayerLeaves(Block block)
+	public ItemBlockLayerLeaves(Block<T> block)
 	{
 		super(block);
 	}
@@ -24,27 +23,27 @@ public class ItemBlockLayerLeaves extends ItemBlock
 	@Override
 	public boolean onUseItemOnBlock(final ItemStack itemstack, final Player player, final World world, int blockX, int blockY, int blockZ, final Side side, double xPlaced, final double yPlaced)
 	{
-		int id = world.getBlockId(blockX, blockY, blockZ);
+		Block<?> targetBlock = world.getBlock(blockX, blockY, blockZ);
 		int meta = world.getBlockMetadata(blockX, blockY, blockZ);
-		if (id != blockID && Blocks.blocksList[id] != null && Blocks.blocksList[id].hasTag(BlockTags.PLACE_OVERWRITES))
+		if (targetBlock != block && targetBlock != null && targetBlock.hasTag(BlockTags.PLACE_OVERWRITES))
 		{
-			id = 0;
+			targetBlock = null;
 			meta = 0;
 		}
 		if (itemstack.stackSize <= 0)
 		{
 			return false;
 		}
-		if (blockY == world.getHeightBlocks() - 1 && Blocks.blocksList[blockID].blockMaterial.isSolid())
+		if (blockY == world.getHeightBlocks() - 1 && block.getMaterial().isSolid())
 		{
 			return false;
 		}
 
 		// Check if we're placing "inside" a layer
-		if (id == blockID && side == Side.TOP)
+		if (targetBlock == block && side == Side.TOP)
 		{
 
-			final BlockLayerBase blockLayer = (BlockLayerBase) Blocks.blocksList[blockID];
+			final BlockLogicLayerBase blockLayer = block.getLogic();
 
 			final int newMeta = meta + 1;
 
@@ -56,40 +55,40 @@ public class ItemBlockLayerLeaves extends ItemBlock
 
 			if ((newMeta & 0b00001111) < 7)
 			{
-				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockID, BlockLayerLeaves.setPermanent(newMeta, true));
+				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, block.id(), BlockLogicLayerLeaves.setPermanent(newMeta, true));
 			}
 			else
 			{
-				if (blockLayer.getFullBlockID() != -1)
+				if (blockLayer.fullBlock != null)
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.getFullBlockID(), BlockLeavesBase.setPermanent(0, true));
+					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.fullBlock.id(), BlockLogicLeavesBase.setPermanent(0, true));
 				}
 				else
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, blockID, BlockLayerLeaves.setPermanent(0, true));
+					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, block.id(), BlockLogicLayerLeaves.setPermanent(0, true));
 				}
 			}
-			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockLayer, EnumBlockSoundEffectType.PLACE);
+			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 			itemstack.consumeItem(player);
 			return true;
 
 		}
 
 		// Offset position
-		if (id != 0)
+		if (targetBlock != null)
 		{
 			blockX += side.getOffsetX();
 			blockY += side.getOffsetY();
 			blockZ += side.getOffsetZ();
-			id = world.getBlockId(blockX, blockY, blockZ);
+			targetBlock = world.getBlock(blockX, blockY, blockZ);
 			meta = world.getBlockMetadata(blockX, blockY, blockZ);
 		}
 
 		// Check if the block we're placing into is a layer
-		if (id == blockID)
+		if (targetBlock == block)
 		{
 
-			final BlockLayerBase blockLayer = (BlockLayerBase) Blocks.blocksList[blockID];
+			final BlockLogicLayerBase blockLayer = block.getLogic();
 
 			final int newMeta = meta + 1;
 
@@ -101,35 +100,34 @@ public class ItemBlockLayerLeaves extends ItemBlock
 
 			if ((newMeta & 0b00001111) < 7)
 			{
-				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockID, BlockLayerLeaves.setPermanent(newMeta, true));
+				world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, block.id(), BlockLogicLayerLeaves.setPermanent(newMeta, true));
 			}
 			else
 			{
-				if (blockLayer.getFullBlockID() != -1)
+				if (blockLayer.fullBlock != null)
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.getFullBlockID(), BlockLeavesBase.setPermanent(0, true));
+					world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockLayer.fullBlock.id(), BlockLogicLeavesBase.setPermanent(0, true));
 				}
 				else
 				{
-					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, blockID, BlockLayerLeaves.setPermanent(0, true));
+					world.setBlockAndMetadataWithNotify(blockX, blockY + 1, blockZ, block.id(), BlockLogicLayerLeaves.setPermanent(0, true));
 				}
 			}
-			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockLayer, EnumBlockSoundEffectType.PLACE);
+			world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 			itemstack.consumeItem(player);
 			return true;
 		}
 
 		// Regular placement, as all else fails
-		if (world.canBlockBePlacedAt(blockID, blockX, blockY, blockZ, false, side))
+		if (world.canBlockBePlacedAt(block.id(), blockX, blockY, blockZ, false, side))
 		{
-			final Block block = Blocks.blocksList[blockID];
 			int placeMeta = getPlacedBlockMetadata(player, itemstack, world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
-			if (world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockID, placeMeta))
+			if (world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, this.block.id(), placeMeta))
 			{
 				if (player == null) {
-					Blocks.blocksList[blockID].onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
+					block.onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
 				} else {
-					Blocks.blocksList[blockID].onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
+					block.onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
 				}
 				world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 				itemstack.consumeItem(player);
@@ -142,7 +140,7 @@ public class ItemBlockLayerLeaves extends ItemBlock
 	
 	@Override
 	public int getPlacedBlockMetadata(@Nullable Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
-		return BlockLayerLeaves.MASK_PERMANENT;
+		return BlockLogicLayerLeaves.MASK_PERMANENT;
 	}
 
 }
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockPainted.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockPainted.java
index d69af94ac..8137681df 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockPainted.java
@@ -1,14 +1,15 @@
 package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.DyeColor;
 
-public class ItemBlockPainted extends ItemBlock
+public class ItemBlockPainted<T extends BlockLogic> extends ItemBlock<T>
 {
 	private final boolean upperMetadata;
 	
-    public ItemBlockPainted(Block block, boolean upperMetadata)
+    public ItemBlockPainted(Block<T> block, boolean upperMetadata)
     {
         super(block);
         setMaxDamage(0);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
index a18eeac44..f7cfc2be5 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
@@ -11,10 +12,10 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
-public class ItemBlockSlab extends ItemBlock
+public class ItemBlockSlab<T extends BlockLogic> extends ItemBlock<T>
 {
 
-    public ItemBlockSlab(Block block)
+    public ItemBlockSlab(Block<T> block)
     {
         super(block);
     }
@@ -34,13 +35,13 @@ public class ItemBlockSlab extends ItemBlock
         {
             return false;
         }
-        if(blockY == world.getHeightBlocks() - 1 && Blocks.blocksList[blockID].blockMaterial.isSolid())
+        if(blockY == world.getHeightBlocks() - 1 && block.getMaterial().isSolid())
         {
             return false;
         }
 
         // Check if we're placing "inside" a slab
-        if (id == blockID && otherMeta == itemstack.getMetadata() && (side == Side.TOP || side == Side.BOTTOM))
+        if (id == block.id() && otherMeta == itemstack.getMetadata() && (side == Side.TOP || side == Side.BOTTOM))
         {
         	if ((side == Side.TOP && meta == 0) || (side == Side.BOTTOM && meta == 2))
         	{
@@ -48,9 +49,8 @@ public class ItemBlockSlab extends ItemBlock
                 if(!world.checkIfAABBIsClear(bbBox))
                     return false;
 
-        		Block blockSlab = Blocks.blocksList[blockID];
         		world.setBlockMetadataWithNotify(blockX, blockY, blockZ, 1 | itemstack.getMetadata());
-                world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockSlab, EnumBlockSoundEffectType.PLACE);
+                world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
             	itemstack.consumeItem(player);
             	return true;
         	}
@@ -68,7 +68,7 @@ public class ItemBlockSlab extends ItemBlock
         }
 
         // Check if the block we're placing into is a slab
-        if (id == blockID && otherMeta == itemstack.getMetadata())
+        if (id == block.id() && otherMeta == itemstack.getMetadata())
         {
         	if ((yPlaced > 0.5f && meta == 0) || (yPlaced <= 0.5f && meta == 2) || (side == Side.BOTTOM && meta == 0) || (side == Side.TOP && meta == 2))
         	{
@@ -76,25 +76,23 @@ public class ItemBlockSlab extends ItemBlock
                 if(!world.checkIfAABBIsClear(bbBox))
                     return false;
 
-        		Block blockSlab = Blocks.blocksList[blockID];
         		world.setBlockMetadataWithNotify(blockX, blockY, blockZ, 1 | itemstack.getMetadata());
-                world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockSlab, EnumBlockSoundEffectType.PLACE);
+                world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
                 itemstack.consumeItem(player);
             	return true;
         	}
         }
 
         // Regular placement, as all else fails
-        if(world.canBlockBePlacedAt(blockID, blockX, blockY, blockZ, false, side))
+        if(world.canBlockBePlacedAt(block.id(), blockX, blockY, blockZ, false, side))
         {
-            Block block = Blocks.blocksList[blockID];
             int placeMeta = getPlacedBlockMetadata(player, itemstack, world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
-            if(world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, blockID, placeMeta))
+            if(world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, this.block.id(), placeMeta))
             {
                 if (player == null) {
-                    Blocks.blocksList[blockID].onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
+                    block.onBlockPlacedOnSide(world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
                 } else {
-                    Blocks.blocksList[blockID].onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
+                    block.onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
                 }
                 world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, block, EnumBlockSoundEffectType.PLACE);
                 itemstack.consumeItem(player);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlabPainted.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlabPainted.java
index b5cfe3993..7f57b0bbe 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlabPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlabPainted.java
@@ -1,14 +1,15 @@
 package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.DyeColor;
 
-public class ItemBlockSlabPainted extends ItemBlockSlab
+public class ItemBlockSlabPainted<T extends BlockLogic> extends ItemBlockSlab<T>
 {
 	private final boolean upperMetadata;
 	
-    public ItemBlockSlabPainted(Block block)
+    public ItemBlockSlabPainted(Block<T> block)
     {
         super(block);
         setMaxDamage(0);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockStairsPainted.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockStairsPainted.java
index 0cfa3c679..d1a672086 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockStairsPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockStairsPainted.java
@@ -1,16 +1,17 @@
 package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
-public class ItemBlockStairsPainted extends ItemBlock
+public class ItemBlockStairsPainted<T extends BlockLogic> extends ItemBlock<T>
 {
 
-    public ItemBlockStairsPainted(Block block)
+    public ItemBlockStairsPainted(Block<T> block)
     {
         super(block);
         setMaxDamage(0);
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemTool.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemTool.java
index 84341cb2d..7ee3bd957 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemTool.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemTool.java
@@ -15,12 +15,12 @@ import net.minecraft.core.world.World;
 public class ItemTool extends Item
 {
 
-	private final Tag<Block> tagEffectiveAgainst;
+	private final Tag<Block<?>> tagEffectiveAgainst;
 	private final int damageVsEntity;
 	protected ToolMaterial material;
 
 	@SuppressWarnings("unchecked")
-	protected ItemTool(String name, String namespaceId, int id, int damageDealt, ToolMaterial toolMaterial, Tag<Block> tagEffectiveAgainst) {
+	protected ItemTool(String name, String namespaceId, int id, int damageDealt, ToolMaterial toolMaterial, Tag<Block<?>> tagEffectiveAgainst) {
 		super(name, namespaceId, id);
 		this.material = toolMaterial;
 		this.tagEffectiveAgainst = tagEffectiveAgainst;
@@ -32,7 +32,7 @@ public class ItemTool extends Item
 	}
 
 	@Override
-	public float getStrVsBlock(ItemStack itemstack, Block block) {
+	public float getStrVsBlock(ItemStack itemstack, Block<?> block) {
 		if(block.hasTag(tagEffectiveAgainst))
 			return material.getEfficiency(false);
 
@@ -40,14 +40,14 @@ public class ItemTool extends Item
 	}
 
 	@Override
-	public boolean hitEntity(ItemStack itemstack, Mob entityliving, Mob entityliving1) {
-		itemstack.damageItem(2, entityliving1);
+	public boolean hitEntity(ItemStack itemstack, Mob target, Mob attacker) {
+		itemstack.damageItem(2, attacker);
 		return true;
 	}
 
 	@Override
 	public boolean onBlockDestroyed(World world, ItemStack itemstack, int i, int x, int y, int z, Side side, Mob mob) {
-		Block block = Blocks.blocksList[i];
+		Block<?> block = Blocks.blocksList[i];
 		if(block != null) {
 			if(block.getHardness() > 0.0f || isSilkTouch()) {
 				itemstack.damageItem(1, mob);
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java
index 6a9750bcf..eac76dd9d 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolAxe.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.item.tool;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLog;
+import net.minecraft.core.block.BlockLogicLog;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.data.gamerule.GameRules;
@@ -22,7 +22,7 @@ public class ItemToolAxe extends ItemTool
     }
 
     @Override
-    public boolean canHarvestBlock(Mob entityLiving, ItemStack itemStack, Block block)
+    public boolean canHarvestBlock(Mob mob, ItemStack itemStack, Block<?> block)
     {
         return block.hasTag(BlockTags.MINEABLE_BY_AXE);
     }
@@ -32,7 +32,7 @@ public class ItemToolAxe extends ItemTool
     {
     	if(!world.isClientSide && world.getGameRuleValue(GameRules.TREECAPITATOR) && !player.isSneaking()) {
     		int id = world.getBlockId(x, y, z);
-    		if(Blocks.getBlock(id) instanceof BlockLog) {
+    		if(Block.hasLogicClass(Blocks.getBlock(id), BlockLogicLog.class)) {
             	return !new TreecapitatorHelper(world, x, y, z, player).chopTree();
     		}
     	}
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java
index a8f8a59a9..ac0240994 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java
@@ -28,7 +28,7 @@ public class ItemToolHoe extends ItemTool
     }
 
     @Override
-    public boolean canHarvestBlock(Mob entityLiving, ItemStack itemStack, Block block)
+    public boolean canHarvestBlock(Mob mob, ItemStack itemStack, Block<?> block)
     {
         return block.hasTag(BlockTags.MINEABLE_BY_HOE);
     }
@@ -42,15 +42,14 @@ public class ItemToolHoe extends ItemTool
     public boolean till(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side) {
         int id = world.getBlockId(blockX, blockY, blockZ);
         int j1 = world.getBlockId(blockX, blockY + 1, blockZ);
-        if(side != Side.BOTTOM && j1 == 0 && (id == Blocks.GRASS.id || id == Blocks.DIRT.id || id == Blocks.PATH_DIRT.id || id == Blocks.GRASS_RETRO.id || id == Blocks.MUD.id))
+        if(side != Side.BOTTOM && j1 == 0 && (id == Blocks.GRASS.id() || id == Blocks.DIRT.id() || id == Blocks.PATH_DIRT.id() || id == Blocks.GRASS_RETRO.id() || id == Blocks.MUD.id()))
         {
             int meta = 0;
-            if(id == Blocks.MUD.id)
+            if(id == Blocks.MUD.id())
                 meta = 1;
-            Block block = Blocks.FARMLAND_DIRT;
             world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.DIRT, EnumBlockSoundEffectType.MINE);
             if(!world.isClientSide) {
-                if(id == Blocks.GRASS.id || id == Blocks.GRASS_RETRO.id || id == Blocks.GRASS_SCORCHED.id) {
+                if(id == Blocks.GRASS.id() || id == Blocks.GRASS_RETRO.id() || id == Blocks.GRASS_SCORCHED.id()) {
                     if(world.rand.nextInt(5) == 0) {
                         world.dropItem(blockX, blockY + 1, blockZ, new ItemStack(Items.SEEDS_WHEAT));
                     }
@@ -61,7 +60,7 @@ public class ItemToolHoe extends ItemTool
                 return true;
             } else
             {
-                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, block.id, meta);
+                world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.FARMLAND_DIRT.id(), meta);
                 itemstack.damageItem(1, player);
                 return true;
             }
@@ -79,7 +78,7 @@ public class ItemToolHoe extends ItemTool
     @Override
     public boolean onBlockDestroyed(World world, ItemStack itemstack, int id, int x, int y, int z, Side side, Mob mob) {
     	if(mob != null && !mob.world.isClientSide) {
-        	if(id == Blocks.TALLGRASS.id || id == Blocks.TALLGRASS_FERN.id) {
+        	if(id == Blocks.TALLGRASS.id() || id == Blocks.TALLGRASS_FERN.id()) {
         		if(this.material.isSilkTouch()) {
         			mob.world.dropItem(x, y, z, new ItemStack(Item.itemsList[id]));
             		itemstack.damageItem(1, mob);
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolPickaxe.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolPickaxe.java
index 4bea3675b..0b2bae886 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolPickaxe.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolPickaxe.java
@@ -12,7 +12,7 @@ import net.minecraft.core.item.material.ToolMaterial;
 
 public class ItemToolPickaxe extends ItemTool {
 	
-	public static Map<Block, Integer> miningLevels = new HashMap<>();
+	public static Map<Block<?>, Integer> miningLevels = new HashMap<>();
 	
 	static {
 		miningLevels.put(Blocks.OBSIDIAN, 3);
@@ -61,7 +61,7 @@ public class ItemToolPickaxe extends ItemTool {
 	}
 
 	@Override
-	public boolean canHarvestBlock(Mob entityLiving, ItemStack itemStack, Block block)
+	public boolean canHarvestBlock(Mob mob, ItemStack itemStack, Block<?> block)
 	{
 		Integer miningLevel = miningLevels.get(block);
 		if(miningLevel != null) return material.getMiningLevel() >= miningLevel;
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShears.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShears.java
index 58ba5b5e3..f0f28e0b8 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShears.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShears.java
@@ -1,9 +1,8 @@
 package net.minecraft.core.item.tool;
 
-import net.minecraft.core.block.BlockLeavesBase;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.tag.BlockTags;
-import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.entity.animal.MobSheep;
 import net.minecraft.core.item.Item;
@@ -33,15 +32,15 @@ public class ItemToolShears extends Item
     }
 
     @Override
-    public boolean canHarvestBlock(Mob entityLiving, ItemStack itemStack, Block block)
+    public boolean canHarvestBlock(Mob mob, ItemStack itemStack, Block<?> block)
     {
         return block.hasTag(BlockTags.MINEABLE_BY_SHEARS);
     }
 
     @Override
-    public float getStrVsBlock(ItemStack itemstack, Block block)
+    public float getStrVsBlock(ItemStack itemstack, Block<?> block)
     {
-        if(block.id == Blocks.COBWEB.id || block instanceof BlockLeavesBase)
+        if(block == Blocks.COBWEB || Block.hasLogicClass(block, BlockLogicLeavesBase.class))
         {
             return 15F;
         }
@@ -59,9 +58,9 @@ public class ItemToolShears extends Item
         blockY += direction.getOffsetY();
         blockZ += direction.getOffsetZ();
         AABB box = AABB.getTemporaryBB(blockX, blockY, blockZ, blockX + 1, blockY + 1, blockZ + 1);
-        List<Entity> entities = world.getEntitiesWithinAABB(MobSheep.class, box);
+        List<MobSheep> entities = world.getEntitiesWithinAABB(MobSheep.class, box);
         if (!entities.isEmpty()) {
-            ((MobSheep)(entities.get(0))).onItemInteract(itemStack);
+            entities.get(0).onItemInteract(itemStack);
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java
index efbd496a2..37de18a58 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java
@@ -24,7 +24,7 @@ public class ItemToolShovel extends ItemTool
     }
 
     @Override
-    public boolean canHarvestBlock(Mob entityLiving, ItemStack itemStack, Block block)
+    public boolean canHarvestBlock(Mob mob, ItemStack itemStack, Block<?> block)
     {
         return block.hasTag(BlockTags.MINEABLE_BY_SHOVEL);
     }
@@ -38,12 +38,11 @@ public class ItemToolShovel extends ItemTool
     public boolean shovelBlock(ItemStack itemstack, @Nullable Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side) {
         int blockId = world.getBlockId(blockX, blockY, blockZ);
         int blockAbove = world.getBlockId(blockX, blockY + 1, blockZ);
-        if(side != Side.BOTTOM && blockAbove == 0 && (blockId == Blocks.GRASS.id || blockId == Blocks.DIRT.id || blockId == Blocks.GRASS_RETRO.id || blockId == Blocks.FARMLAND_DIRT.id))
+        if(side != Side.BOTTOM && blockAbove == 0 && (blockId == Blocks.GRASS.id() || blockId == Blocks.DIRT.id() || blockId == Blocks.GRASS_RETRO.id() || blockId == Blocks.FARMLAND_DIRT.id()))
         {
-            Block block = Blocks.PATH_DIRT;
             world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.blocksList[blockId], EnumBlockSoundEffectType.PLACE);
             if (!world.isClientSide) {
-                world.setBlockWithNotify(blockX, blockY, blockZ, block.id);
+                world.setBlockWithNotify(blockX, blockY, blockZ, Blocks.PATH_DIRT.id());
                 itemstack.damageItem(1, entityplayer);
             }
             return true;
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolSword.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolSword.java
index 7289f11c9..d63651dae 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolSword.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolSword.java
@@ -28,22 +28,22 @@ public class ItemToolSword extends Item
     }
 
     @Override
-    public float getStrVsBlock(ItemStack itemstack, Block block)
+    public float getStrVsBlock(ItemStack itemstack, Block<?> block)
     {
-        return block.id != Blocks.COBWEB.id ? 1.5F : 15F;
+        return block != Blocks.COBWEB ? 1.5F : 15F;
     }
 
     @Override
-    public boolean hitEntity(ItemStack itemstack, Mob entityliving, Mob entityliving1)
+    public boolean hitEntity(ItemStack itemstack, Mob target, Mob attacker)
     {
-        itemstack.damageItem(1, entityliving1);
+        itemstack.damageItem(1, attacker);
         return true;
     }
 
     @Override
     public boolean onBlockDestroyed(World world, ItemStack itemstack, int i, int x, int y, int z, Side side, Mob mob)
     {
-        Block block = Blocks.blocksList[i];
+        Block<?> block = Blocks.blocksList[i];
         if(block != null) {
             if(block.getHardness() > 0.0f || isSilkTouch()) {
                 itemstack.damageItem(2, mob);
@@ -57,9 +57,9 @@ public class ItemToolSword extends Item
         blockX += direction.getOffsetX();
         blockY += direction.getOffsetY();
         blockZ += direction.getOffsetZ();
-        Block b = world.getBlock(blockX, blockY, blockZ);
+        Block<?> b = world.getBlock(blockX, blockY, blockZ);
         if (b == Blocks.PUMPKIN) {
-            world.setBlockAndMetadata(blockX, blockY, blockZ, Blocks.PUMPKIN_CARVED_IDLE.id, direction.getOpposite().getId());
+            world.setBlockAndMetadata(blockX, blockY, blockZ, Blocks.PUMPKIN_CARVED_IDLE.id(), direction.getOpposite().getId());
             itemStack.damageItem(1, null);
         }
     }
@@ -71,7 +71,7 @@ public class ItemToolSword extends Item
     }
 
     @Override
-    public boolean canHarvestBlock(Mob entityLiving, ItemStack itemStack, Block block)
+    public boolean canHarvestBlock(Mob mob, ItemStack itemStack, Block<?> block)
     {
         return block.hasTag(BlockTags.MINEABLE_BY_SWORD);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeBlock.java b/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeBlock.java
index c1c7ec628..e84bc21ec 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeBlock.java
@@ -41,9 +41,9 @@ public class ArgumentTypeBlock implements ArgumentType<BlockInput> {
         } catch (CommandSyntaxException ignored) {}
         return parser.fillSuggestions(builder, suggestionsBuilder -> {
             String remaining = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
-            for (Block block : Blocks.blocksList) {
+            for (Block<?> block : Blocks.blocksList) {
                 if (block == null) continue;
-                CommandHelper.getStringToSuggest(block.namespaceID.toString(), remaining).ifPresent(suggestionsBuilder::suggest);
+                CommandHelper.getStringToSuggest(block.namespaceId().toString(), remaining).ifPresent(suggestionsBuilder::suggest);
             }
             CommandHelper.getStringToSuggest(BlockArgumentParser.AIR_BLOCK.toString(), remaining).ifPresent(suggestionsBuilder::suggest);
             suggestionsBuilder.buildFuture();
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java
index 3dc79c20d..4eb2116cb 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java
@@ -53,8 +53,8 @@ public class CommandTestFor implements CommandManager.CommandRegistry {
                                             IntegerCoordinates firstPos = c.getArgument("first", IntegerCoordinates.class);
                                             IntegerCoordinates secondPos = c.getArgument("second", IntegerCoordinates.class);
 
-                                            Block firstBlock = c.getSource().getWorld().getBlock(firstPos.getX(c.getSource()), firstPos.getY(c.getSource(), true), firstPos.getZ(c.getSource()));
-                                            Block secondBlock = c.getSource().getWorld().getBlock(secondPos.getX(c.getSource()), secondPos.getY(c.getSource(), true), secondPos.getZ(c.getSource()));
+                                            Block<?> firstBlock = c.getSource().getWorld().getBlock(firstPos.getX(c.getSource()), firstPos.getY(c.getSource(), true), firstPos.getZ(c.getSource()));
+                                            Block<?> secondBlock = c.getSource().getWorld().getBlock(secondPos.getX(c.getSource()), secondPos.getY(c.getSource(), true), secondPos.getZ(c.getSource()));
 
                                             if (firstBlock != secondBlock) {
                                                 c.getSource().sendTranslatableMessage("command.commands.testfor.block.failure");
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java
index 549ccb6f7..281c9df23 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java
@@ -18,7 +18,7 @@ import java.util.function.Consumer;
 public class BlockArgumentParser extends ArgumentParser {
     private static final SimpleCommandExceptionType INVALID_BLOCK = new SimpleCommandExceptionType(() -> I18n.getInstance().translateKey("command.argument_types.block.invalid_block"));
     public static final NamespaceID AIR_BLOCK = new NamespaceID("minecraft", "block/air");
-    private Block block;
+    private Block<?> block;
     private int metadata = 0;
     private CompoundTag tag = new CompoundTag();
 
@@ -67,9 +67,9 @@ public class BlockArgumentParser extends ArgumentParser {
             this.block = null;
             isAir = true;
         } else {
-            for (Block blockInList : Blocks.blocksList) {
+            for (Block<?> blockInList : Blocks.blocksList) {
                 if (blockInList == null) continue;
-                if (CommandHelper.matchesNamespaceId(blockInList.namespaceID, string)) {
+                if (CommandHelper.matchesNamespaceId(blockInList.namespaceId(), string)) {
                     this.block = blockInList;
                     break;
                 }
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java
index f1ef4e5ec..1a1dd7e01 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java
@@ -6,22 +6,22 @@ import org.jetbrains.annotations.Nullable;
 
 public class BlockInput {
     @Nullable
-    private final Block block;
+    private final Block<?> block;
     private final int metadata;
     private final CompoundTag tag;
 
-    public BlockInput(@Nullable Block block, int metadata, CompoundTag tag) {
+    public BlockInput(@Nullable Block<?> block, int metadata, CompoundTag tag) {
         this.block = block;
         this.metadata = metadata;
         this.tag = tag;
     }
 
-    public @Nullable Block getBlock() {
+    public @Nullable Block<?> getBlock() {
         return this.block;
     }
 
     public int getBlockId() {
-        return this.block == null ? 0 : this.block.id;
+        return this.block == null ? 0 : this.block.id();
     }
 
     public int getMetadata() {
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/ClonedBlock.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/ClonedBlock.java
index 2eaae1ce7..cddff7fb4 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/ClonedBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/ClonedBlock.java
@@ -6,23 +6,23 @@ import org.jetbrains.annotations.Nullable;
 
 public class ClonedBlock {
     @Nullable
-    private final Block block;
+    private final Block<?> block;
     private final int metadata;
     @Nullable
     private final TileEntity tileEntity;
 
-    public ClonedBlock(@Nullable Block block, int metadata, @Nullable TileEntity tileEntity) {
+    public ClonedBlock(@Nullable Block<?> block, int metadata, @Nullable TileEntity tileEntity) {
         this.block = block;
         this.metadata = metadata;
         this.tileEntity = tileEntity;
     }
 
-    public @Nullable Block getBlock() {
+    public @Nullable Block<?> getBlock() {
         return this.block;
     }
 
     public int getBlockId() {
-        return this.block == null ? 0 : this.block.id;
+        return this.block == null ? 0 : this.block.id();
     }
 
     public int getMetadata() {
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/WorldFeatureParameterTypes.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/WorldFeatureParameterTypes.java
index ea043a279..8b88a3ee6 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/WorldFeatureParameterTypes.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/WorldFeatureParameterTypes.java
@@ -32,13 +32,13 @@ public class WorldFeatureParameterTypes {
         throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(stringReader);
     }
 
-    private static Block parseBlock(StringReader reader, WorldFeatureParser parser) throws CommandSyntaxException {
+    private static Block<?> parseBlock(StringReader reader, WorldFeatureParser parser) throws CommandSyntaxException {
         parser.setSuggestions(CommandHelper.SUGGEST_BLOCKS);
 
         int cursor = reader.getCursor();
         final String string = reader.readString();
 
-        for (Block blockInList : Blocks.blocksList) {
+        for (Block<?> blockInList : Blocks.blocksList) {
             if (blockInList == null) continue;
             if (CommandHelper.matchesKeyString(blockInList.getKey(), string)) {
                 return blockInList;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java b/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java
index 20d263128..1a4cd1151 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java
@@ -30,7 +30,7 @@ public class CommandHelper {
     public static final BiFunction<SuggestionsBuilder, Consumer<SuggestionsBuilder>, CompletableFuture<Suggestions>> NO_SUGGESTIONS = (builder, consumer) -> builder.buildFuture();
     public static final BiFunction<SuggestionsBuilder, Consumer<SuggestionsBuilder>, CompletableFuture<Suggestions>> SUGGEST_BLOCKS = (builder, consumer) -> {
         String remaining = builder.getRemaining().toLowerCase(Locale.ROOT);
-        for (Block block : Blocks.blocksList) {
+        for (Block<?> block : Blocks.blocksList) {
             if (block == null) continue;
             CommandHelper.getStringToSuggest(block.getKey(), remaining).ifPresent(builder::suggest);
         }
diff --git a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryFallingBlock.java b/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryFallingBlock.java
index 3d49e2850..a2cf723ce 100644
--- a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryFallingBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryFallingBlock.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.net.entity.entries;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityFallingBlock;
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
index 04bb5881a..4c7bfb860 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
@@ -276,7 +276,7 @@ public class ContainerInventory
         aitemstack[index] = itemstack;
     }
 
-    public float getStrVsBlock(Block block)
+    public float getStrVsBlock(Block<?> block)
     {
         float f = 1.0F;
         if(mainInventory[currentItem] != null)
@@ -380,10 +380,10 @@ public class ContainerInventory
         }
     }
 
-    public boolean canHarvestBlock(Block block)
+    public boolean canHarvestBlock(Block<?> block)
     {
         if (block == null) return false;
-        if(block.blockMaterial.isAlwaysDestroyable())
+        if(block.getMaterial().isAlwaysDestroyable())
         {
             return true;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuCrafting.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuCrafting.java
index bae51791c..7ff5c8ea1 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuCrafting.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuCrafting.java
@@ -86,7 +86,7 @@ public class MenuCrafting extends MenuAbstract
     @Override
 	public boolean stillValid(Player entityplayer)
     {
-        if(world.getBlockId(x, y, z) != Blocks.WORKBENCH.id)
+        if(world.getBlockId(x, y, z) != Blocks.WORKBENCH.id())
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java
index da517e6ab..dc68f4736 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java
@@ -6,7 +6,6 @@ import net.minecraft.core.lang.I18n;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.player.inventory.container.ContainerInventory;
 import net.minecraft.core.player.inventory.slot.SlotCreative;
@@ -137,7 +136,7 @@ public class MenuInventoryCreative extends MenuInventory
 				creativeItems.add(new ItemStack(Blocks.blocksList[id]));
 				count++;
 				
-				if (id == Blocks.WOOL.id || id == Blocks.PLANKS_OAK_PAINTED.id || id == Blocks.LAMP_IDLE.id || id == Blocks.FENCE_PLANKS_OAK_PAINTED.id)
+				if (id == Blocks.WOOL.id() || id == Blocks.PLANKS_OAK_PAINTED.id() || id == Blocks.LAMP_IDLE.id() || id == Blocks.FENCE_PLANKS_OAK_PAINTED.id())
 				{
 					for (int i = 1; i < 16; i++)
 					{
@@ -145,9 +144,9 @@ public class MenuInventoryCreative extends MenuInventory
 						count++;
 					}
 				}
-				else if (id == Blocks.CHEST_PLANKS_OAK_PAINTED.id || id == Blocks.SLAB_PLANKS_PAINTED.id || id == Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id
-					  || id == Blocks.STAIRS_PLANKS_PAINTED.id || id == Blocks.DOOR_PLANKS_PAINTED_BOTTOM.id || id == Blocks.DOOR_PLANKS_PAINTED_TOP.id
-					  || id == Blocks.TRAPDOOR_PLANKS_PAINTED.id)
+				else if (id == Blocks.CHEST_PLANKS_OAK_PAINTED.id() || id == Blocks.SLAB_PLANKS_PAINTED.id() || id == Blocks.FENCE_GATE_PLANKS_OAK_PAINTED.id()
+					  || id == Blocks.STAIRS_PLANKS_PAINTED.id() || id == Blocks.DOOR_PLANKS_PAINTED_BOTTOM.id() || id == Blocks.DOOR_PLANKS_PAINTED_TOP.id()
+					  || id == Blocks.TRAPDOOR_PLANKS_PAINTED.id())
 				{
 					for (int i = 0x10; i < 0x100; i += 0x10)
 					{
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotResult.java b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotResult.java
index 323c03dd2..cd181212d 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotResult.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotResult.java
@@ -37,8 +37,8 @@ public class SlotResult extends Slot
 
 		Item item = itemStack.getItem();
 		
-		if(item.id == Blocks.WORKBENCH.id) thePlayer.addStat(Achievements.BUILD_WORKBENCH, 1);
-		if(item.id == Blocks.FURNACE_STONE_IDLE.id) thePlayer.addStat(Achievements.BUILD_FURNACE, 1);
+		if(item.id == Blocks.WORKBENCH.id()) thePlayer.addStat(Achievements.BUILD_WORKBENCH, 1);
+		if(item.id == Blocks.FURNACE_STONE_IDLE.id()) thePlayer.addStat(Achievements.BUILD_FURNACE, 1);
 		if(item.id == Items.FOOD_BREAD.id) thePlayer.addStat(Achievements.MAKE_BREAD, 1);
 		if(item.id == Items.FOOD_CAKE.id) thePlayer.addStat(Achievements.BAKE_CAKE, 1);
 		if(item.id == Items.BUCKET_ICECREAM.id) thePlayer.addStat(Achievements.CRAFT_ICECREAM, 1);
diff --git a/game/core/src/main/java/net/minecraft/core/world/BlocksContainer.java b/game/core/src/main/java/net/minecraft/core/world/BlocksContainer.java
index b4ad36886..e8fd35cdd 100644
--- a/game/core/src/main/java/net/minecraft/core/world/BlocksContainer.java
+++ b/game/core/src/main/java/net/minecraft/core/world/BlocksContainer.java
@@ -55,7 +55,7 @@ public class BlocksContainer implements WorldSource {
     }
 
     @Override
-    public Block getBlock(int x, int y, int z) {
+    public @Nullable Block<?> getBlock(int x, int y, int z) {
         return Blocks.getBlock(getBlockId(x, y, z));
     }
 
@@ -101,20 +101,20 @@ public class BlocksContainer implements WorldSource {
 
     @Override
     public Material getBlockMaterial(int x, int y, int z) {
-        Block b = getBlock(x, y, z);
-        return b == null ? Material.air : b.blockMaterial;
+        Block<?> b = getBlock(x, y, z);
+        return b == null ? Material.air : b.getMaterial();
     }
 
     @Override
     public boolean isBlockOpaqueCube(int x, int y, int z) {
-        Block b = getBlock(x, y, z);
+        Block<?> b = getBlock(x, y, z);
         return b != null && b.isSolidRender();
     }
 
     @Override
     public boolean isBlockNormalCube(int x, int y, int z) {
-        Block b = getBlock(x, y, z);
-        return b != null && b.blockMaterial.isSolidBlocking() && b.renderAsNormalBlockOnCondition(this, x, y, z);
+        Block<?> b = getBlock(x, y, z);
+        return b != null && b.getMaterial().isSolidBlocking() && b.renderAsNormalBlockOnCondition(this, x, y, z);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/world/Dimension.java b/game/core/src/main/java/net/minecraft/core/world/Dimension.java
index 77c53c5b7..c74e693f4 100644
--- a/game/core/src/main/java/net/minecraft/core/world/Dimension.java
+++ b/game/core/src/main/java/net/minecraft/core/world/Dimension.java
@@ -1,10 +1,13 @@
 package net.minecraft.core.world;
 
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicPortal;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.save.DimensionData;
 import net.minecraft.core.world.type.WorldType;
 import net.minecraft.core.world.type.WorldTypes;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -17,14 +20,14 @@ public class Dimension
 	public final Dimension homeDim;
 	public final WorldType defaultWorldType;
 	public final float worldScale;
-	public final int portalBlockId;
+	public final @Nullable Block<? extends BlockLogicPortal> portalBlock;
 	
-	public Dimension(String languageKey, Dimension homeDim, float worldScale, int portalBlockId, WorldType defaultWorldType)
+	public Dimension(String languageKey, Dimension homeDim, float worldScale, @Nullable Block<? extends BlockLogicPortal> portalBlock, WorldType defaultWorldType)
 	{
 		this.languageKey = languageKey;
 		this.homeDim = homeDim;
 		this.worldScale = worldScale;
-		this.portalBlockId = portalBlockId;
+		this.portalBlock = portalBlock;
 		this.defaultWorldType = defaultWorldType;
 	}
 	
@@ -74,9 +77,9 @@ public class Dimension
 
 	private static final Map<Integer, Dimension> dimensionList = new HashMap<>();
 
-	public static Dimension OVERWORLD;
-	public static Dimension NETHER;
-	public static Dimension PARADISE;
+	public static final Dimension OVERWORLD = new Dimension("overworld", null, 1.0f, null, WorldTypes.OVERWORLD_DEFAULT);
+	public static final Dimension NETHER = new Dimension("nether", OVERWORLD, 0.125f, Blocks.PORTAL_NETHER, WorldTypes.NETHER_DEFAULT);
+	public static final Dimension PARADISE = new Dimension("paradise", OVERWORLD, 8.0f, Blocks.PORTAL_PARADISE, WorldTypes.PARADISE_DEFAULT);
 
 	public static Map<Integer, Dimension> getDimensionList()
 	{
@@ -95,10 +98,6 @@ public class Dimension
 		dimensionList.put(id, dimension);
 	}
 	public static void init(){
-		OVERWORLD = new Dimension("overworld", null, 1.0f, -1, WorldTypes.OVERWORLD_DEFAULT);
-		NETHER = new Dimension("nether", OVERWORLD, 0.125f, Blocks.PORTAL_NETHER.id, WorldTypes.NETHER_DEFAULT);
-		PARADISE = new Dimension("paradise", OVERWORLD, 8.0f, Blocks.PORTAL_PARADISE.id, WorldTypes.PARADISE_DEFAULT);
-
 		registerDimension(0, OVERWORLD);
 		registerDimension(1, NETHER);
 		registerDimension(2, PARADISE);
diff --git a/game/core/src/main/java/net/minecraft/core/world/Explosion.java b/game/core/src/main/java/net/minecraft/core/world/Explosion.java
index 43fc7e8c4..efc1b3041 100644
--- a/game/core/src/main/java/net/minecraft/core/world/Explosion.java
+++ b/game/core/src/main/java/net/minecraft/core/world/Explosion.java
@@ -7,7 +7,6 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.MathHelper;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.util.phys.Vec3;
@@ -171,8 +170,7 @@ public class Explosion {
 	}
 
 	protected void createFire() {
-		List<ChunkPosition> arraylist = new ArrayList<>();
-		arraylist.addAll(destroyedBlockPositions);
+        List<ChunkPosition> arraylist = new ArrayList<>(destroyedBlockPositions);
 		for (int l2 = arraylist.size() - 1; l2 >= 0; l2--) {
 			ChunkPosition chunkposition = arraylist.get(l2);
 			
@@ -181,7 +179,7 @@ public class Explosion {
 			int z1 = chunkposition.z;
 			
 			if(worldObj.getBlockId(x1, y1, z1) == 0 && Blocks.solid[worldObj.getBlockId(x1, y1 - 1, z1)] && ExplosionRNG.nextInt(3) == 0) {
-				worldObj.setBlockWithNotify(x1, y1, z1, Blocks.FIRE.id);
+				worldObj.setBlockWithNotify(x1, y1, z1, Blocks.FIRE.id());
 			}
 		}
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/world/ExplosionCannonball.java b/game/core/src/main/java/net/minecraft/core/world/ExplosionCannonball.java
index 2faa0280b..4f9258d3f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/ExplosionCannonball.java
+++ b/game/core/src/main/java/net/minecraft/core/world/ExplosionCannonball.java
@@ -123,7 +123,7 @@ public class ExplosionCannonball extends Explosion{
                 int i4 = worldObj.getBlockId(i3, j3 - 1, k3);
                 if(l3 == 0 && Blocks.solid[i4] && ExplosionRNG.nextInt(3) == 0)
                 {
-                    worldObj.setBlockWithNotify(i3, j3, k3, Blocks.FIRE.id);
+                    worldObj.setBlockWithNotify(i3, j3, k3, Blocks.FIRE.id());
                 }
             }
 
@@ -143,7 +143,7 @@ public class ExplosionCannonball extends Explosion{
             int x = chunkposition.x;
             int y = chunkposition.y;
             int z = chunkposition.z;
-            int i1 = worldObj.getBlockId(x, y, z);
+            Block<?> block = worldObj.getBlock(x, y, z);
             TileEntity tileEntity = worldObj.getBlockEntity(x, y, z);
             if(flag)
             {
@@ -165,16 +165,16 @@ public class ExplosionCannonball extends Explosion{
                 worldObj.spawnParticle("explode", (d + explosionX) / 2D, (d1 + explosionY) / 2D, (d2 + explosionZ) / 2D, d3, d4, d5, 0 );
                 worldObj.spawnParticle("smoke", d, d1, d2, d3, d4, d5, 0);
             }
-            if(i1 > 0 && (Blocks.blocksList[i1].id == Blocks.GLASS.id
-                    ||  Blocks.blocksList[i1].blockMaterial == Material.topSnow
-                    ||  Blocks.blocksList[i1].blockMaterial == Material.plant
-                    ||  Blocks.blocksList[i1].blockMaterial == Material.web
-                    ||  Blocks.blocksList[i1].blockMaterial == Material.decoration
-                    ||  Blocks.blocksList[i1].blockMaterial == Material.ice))
+            if(block != null && (block == Blocks.GLASS
+                    ||  block.getMaterial() == Material.topSnow
+                    ||  block.getMaterial() == Material.plant
+                    ||  block.getMaterial() == Material.web
+                    ||  block.getMaterial() == Material.decoration
+                    ||  block.getMaterial() == Material.ice))
             {
-                Blocks.blocksList[i1].dropBlockWithCause(worldObj, EnumDropCause.EXPLOSION, x, y, z, worldObj.getBlockMetadata(x, y, z), tileEntity, null);
+                block.dropBlockWithCause(worldObj, EnumDropCause.EXPLOSION, x, y, z, worldObj.getBlockMetadata(x, y, z), tileEntity, null);
                 worldObj.setBlockWithNotify(x, y, z, 0);
-                Blocks.blocksList[i1].onBlockDestroyedByExplosion(worldObj, x, y, z);
+                block.onBlockDestroyedByExplosion(worldObj, x, y, z);
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java b/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java
index 5a5c1cac2..7cf290f5a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java
+++ b/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java
@@ -1,11 +1,10 @@
 package net.minecraft.core.world;
 
-import net.minecraft.core.block.BlockPortal;
-import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicPortal;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.MathHelper;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.world.type.WorldType;
 import org.jetbrains.annotations.Nullable;
 
@@ -13,6 +12,7 @@ import java.util.Random;
 
 public class PortalHandler
 {
+    private final Random rand;
 
     public PortalHandler()
     {
@@ -32,16 +32,16 @@ public class PortalHandler
         int searchRadius = 128;
         double lowestEntityDistanceSquaredXZ = -1D;
         double lowestEntityDistanceSquaredY = -1D;
-        int targetPortalId;
+        Block<? extends BlockLogicPortal> targetPortal;
         int closestPortalX = 0;
         int closestPortalY = 0;
         int closestPortalZ = 0;
         int entityBlockX = MathHelper.floor(entity.x);
         int entityBlockZ = MathHelper.floor(entity.z);
-        
+
         WorldType oldWorldType = oldDim.getDimensionData(world).getWorldType();
         WorldType newWorldType = newDim.getDimensionData(world).getWorldType();
-        
+
         double entityPosYScaled = entity.y - entity.heightOffset;
         int oldDimRangeY = oldWorldType.getMaxPortalY() - oldWorldType.getMinPortalY();
         entityPosYScaled -= oldWorldType.getMinPortalY();
@@ -53,13 +53,13 @@ public class PortalHandler
 
         if (newDim.homeDim == null)
         {
-        	targetPortalId = oldDim.portalBlockId;
+        	targetPortal = oldDim.portalBlock;
         }
         else
         {
-        	targetPortalId = newDim.portalBlockId;
+        	targetPortal = newDim.portalBlock;
         }
-        
+
         // Attempt to find closest portal along the xz plane
         for(int dx = entityBlockX - searchRadius; dx <= entityBlockX + searchRadius; dx++)
         {
@@ -69,18 +69,18 @@ public class PortalHandler
                 double zEntityDistance = ((double)dz + 0.5D) - entity.z;
                 for(int dy = newWorldType.getMaxPortalY() - 1; dy >= newWorldType.getMinPortalY(); dy--)
                 {
-                    if(world.getBlockId(dx, dy, dz) != targetPortalId)
+                    if(world.getBlock(dx, dy, dz) != targetPortal)
                     {
                         continue;
                     }
 
-                    if (portalColor != null && targetPortalId > 0 && ((BlockPortal)Blocks.getBlock(targetPortalId)).getColor(world, dx, dy, dz) != portalColor) {
+                    if (portalColor != null && targetPortal != null && targetPortal.getLogic().getColor(world, dx, dy, dz) != portalColor) {
                         continue;
                     }
-                    
+
                     // Find the bottom portal block of the portal
-                    for(; world.getBlockId(dx, dy - 1, dz) == targetPortalId; dy--);
-                    
+                    for(; world.getBlock(dx, dy - 1, dz) == targetPortal; dy--);
+
 //                    double yEntityDistance = ((double)dy + 0.5D) - entityPosYScaled;
                     double entityDistanceSquared = xEntityDistance * xEntityDistance /*+ yEntityDistance * yEntityDistance*/ + zEntityDistance * zEntityDistance;
                     if(lowestEntityDistanceSquaredXZ < 0.0D || entityDistanceSquared < lowestEntityDistanceSquaredXZ)
@@ -105,16 +105,16 @@ public class PortalHandler
                 for (int dz = cz - 1; dz <= cz + 1; dz++) {
                     double zEntityDistance = ((double) dz + 0.5D) - entity.z;
                     for (int dy = newWorldType.getMaxPortalY() - 1; dy >= newWorldType.getMinPortalY(); dy--) {
-                        if (world.getBlockId(dx, dy, dz) != targetPortalId) {
+                        if (world.getBlock(dx, dy, dz) != targetPortal) {
                             continue;
                         }
 
-                        if (portalColor != null && targetPortalId > 0 && ((BlockPortal) Blocks.getBlock(targetPortalId)).getColor(world, dx, dy, dz) != portalColor) {
+                        if (portalColor != null && targetPortal != null && targetPortal.getLogic().getColor(world, dx, dy, dz) != portalColor) {
                             continue;
                         }
 
                         // Find the bottom portal block of the portal
-                        for (; world.getBlockId(dx, dy - 1, dz) == targetPortalId; dy--) ;
+                        for (; world.getBlock(dx, dy - 1, dz) == targetPortal; dy--) ;
 
                         double yEntityDistance = ((double) dy + 0.5D) - entityPosYScaled;
                         double entityDistanceSquared = xEntityDistance * xEntityDistance + yEntityDistance * yEntityDistance + zEntityDistance * zEntityDistance;
@@ -137,26 +137,26 @@ public class PortalHandler
             double newEntityX = (double)portalX + 0.5D;
             double newEntityY = (double)portalY + 0.5D;
             double newEntityZ = (double)portalZ + 0.5D;
-            if(world.getBlockId(portalX - 1, portalY, portalZ) == targetPortalId)
+            if(world.getBlock(portalX - 1, portalY, portalZ) == targetPortal)
             {
                 newEntityX -= 0.5D;
             }
-            if(world.getBlockId(portalX + 1, portalY, portalZ) == targetPortalId)
+            if(world.getBlock(portalX + 1, portalY, portalZ) == targetPortal)
             {
                 newEntityX += 0.5D;
             }
-            if(world.getBlockId(portalX, portalY, portalZ - 1) == targetPortalId)
+            if(world.getBlock(portalX, portalY, portalZ - 1) == targetPortal)
             {
                 newEntityZ -= 0.5D;
             }
-            if(world.getBlockId(portalX, portalY, portalZ + 1) == targetPortalId)
+            if(world.getBlock(portalX, portalY, portalZ + 1) == targetPortal)
             {
                 newEntityZ += 0.5D;
             }
             entity.moveTo(newEntityX, newEntityY - 0.5f, newEntityZ, entity.yRot, 0.0F);
             entity.xd = entity.yd = entity.zd = 0.0D;
             return true;
-        } 
+        }
         else
         {
             return false;
@@ -188,20 +188,20 @@ public class PortalHandler
         int closestPortalZ = blockZ;
         int k1 = 0;
         int l1 = rand.nextInt(4);
-        int targetPortalFrameId;
-        int targetPortalId;
-        
+        Block<?> targetPortalFrame;
+        Block<? extends BlockLogicPortal> targetPortal;
+
         if (newDim.homeDim == null)
         {
-        	targetPortalFrameId = ((BlockPortal) Blocks.blocksList[oldDim.portalBlockId]).portalFrameId;
-        	targetPortalId = oldDim.portalBlockId;
+        	targetPortalFrame = oldDim.portalBlock.getLogic().portalFrame;
+        	targetPortal = oldDim.portalBlock;
         }
         else
         {
-        	targetPortalFrameId = ((BlockPortal)Blocks.blocksList[newDim.portalBlockId]).portalFrameId;
-        	targetPortalId = newDim.portalBlockId;
+        	targetPortalFrame = newDim.portalBlock.getLogic().portalFrame;
+        	targetPortal = newDim.portalBlock;
         }
-        
+
         for(int dx = blockX - portalSearchRadius; dx <= blockX + portalSearchRadius; dx++)
         {
             double xEntityDistance = ((double)dx + 0.5D) - entity.x;
@@ -340,7 +340,7 @@ label1:
                         int y = portalY + j7;
                         int z = (portalZ + (i6 - 1) * frameZMult) - i5 * frameXMult;
                         boolean flag = j7 < 0;
-                        world.setBlockWithNotify(x, y, z, flag ? targetPortalFrameId : 0);
+                        world.setBlockWithNotify(x, y, z, flag ? targetPortalFrame.id() : 0);
                     }
 
                 }
@@ -359,12 +359,12 @@ label1:
                     int lookupY = portalY + yOffset;
                     int lookupZ = portalZ + (xzOffset - 1) * frameZMult;
                     boolean isPortalBorder = xzOffset == 0 || xzOffset == 3 || yOffset == -1 || yOffset == 3;
-                    world.setBlockWithNotify(lookupX, lookupY, lookupZ, isPortalBorder ? targetPortalFrameId : 0);
+                    world.setBlockWithNotify(lookupX, lookupY, lookupZ, isPortalBorder ? targetPortalFrame.id() : 0);
                 }
 
             }
-            
-            ((BlockPortal)Blocks.blocksList[targetPortalId]).tryToCreatePortal(world, portalX,  portalY,  portalZ, portalColor);
+
+            targetPortal.getLogic().tryToCreatePortal(world, portalX,  portalY,  portalZ, portalColor);
 
             world.noNeighborUpdate = false;
             for(int k6 = 0; k6 < 4; k6++)
@@ -383,6 +383,4 @@ label1:
 
         return true;
     }
-
-    private Random rand;
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java b/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java
index 5921fe9e5..2e9befd64 100644
--- a/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java
+++ b/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world;
 
 import com.mojang.logging.LogUtils;
-import net.minecraft.core.block.BlockBed;
+import net.minecraft.core.block.BlockLogicBed;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.data.gamerule.GameRules;
 import net.minecraft.core.entity.EntityDispatcher;
@@ -281,7 +281,7 @@ public final class SpawnerMobs
 								Node pathPoint = pathEntity.last();
                                 boolean isCollisionFree = world.checkBlockCollisionBetweenPoints(Vec3.getTempVec3(player.x, player.y + 1.5f, player.z), Vec3.getTempVec3(pathPoint.x, pathPoint.y + 1.5f, pathPoint.z)) == null;
 								if(Math.abs(pathPoint.x + 0.5f - player.x) < 1.5 && Math.abs(pathPoint.z + 0.5f - player.z) < 1.5 && Math.abs(pathPoint.y + 0.5f - player.y) < 1.5 && isCollisionFree) {
-									ChunkCoordinates pos = BlockBed.getNearestEmptyChunkCoordinates(world, MathHelper.floor(player.x), MathHelper.floor(player.y), MathHelper.floor(player.z), 1);
+									ChunkCoordinates pos = BlockLogicBed.getNearestEmptyChunkCoordinates(world, MathHelper.floor(player.x), MathHelper.floor(player.y), MathHelper.floor(player.z), 1);
 									if(pos == null) {
 										pos = new ChunkCoordinates(x, spawnY + 1, z);
 									}
diff --git a/game/core/src/main/java/net/minecraft/core/world/World.java b/game/core/src/main/java/net/minecraft/core/world/World.java
index ea80c584b..5c6241087 100644
--- a/game/core/src/main/java/net/minecraft/core/world/World.java
+++ b/game/core/src/main/java/net/minecraft/core/world/World.java
@@ -445,7 +445,7 @@ public class World implements WorldSource {
     }
 
     @Override
-    public Block getBlock(int x, int y, int z) {
+    public @Nullable Block<?> getBlock(int x, int y, int z) {
         return Blocks.getBlock(getBlockId(x, y, z));
     }
 
@@ -738,7 +738,7 @@ public class World implements WorldSource {
             return Material.air;
         } else
         {
-            return Blocks.blocksList[l].blockMaterial;
+            return Blocks.blocksList[l].getMaterial();
         }
     }
 
@@ -883,7 +883,7 @@ public class World implements WorldSource {
         {
             return;
         }
-        Block block = Blocks.blocksList[getBlockId(x, y, z)];
+        Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
         if(block != null)
         {
             block.onNeighborBlockChange(this, x, y, z, blockId);
@@ -1169,7 +1169,7 @@ public class World implements WorldSource {
         int blockStartZ = MathHelper.floor(start.z);
         int id = getBlockId(blockStartX, blockStartY, blockStartZ);
         int meta = getBlockMetadata(blockStartX, blockStartY, blockStartZ);
-        Block block = Blocks.blocksList[id];
+        Block<?> block = Blocks.blocksList[id];
         if(
             (
                 !ignoreNonColliderBlocks ||
@@ -1307,7 +1307,7 @@ public class World implements WorldSource {
                 blockStartZ--;
                 vec32.z++;
             }
-            Block block1 = getBlock(blockStartX, blockStartY, blockStartZ);
+            Block<?> block1 = getBlock(blockStartX, blockStartY, blockStartZ);
             int metadata1 = getBlockMetadata(blockStartX, blockStartY, blockStartZ);
             if(
                 (!ignoreNonColliderBlocks || (block1 == null) || ((useSelectorBoxes ? block1.getSelectedBoundingBoxFromPool(this, blockStartX, blockStartY, blockStartZ) : block1.getCollisionBoundingBoxFromPool(this, blockStartX, blockStartY, blockStartZ)) != null)) && (block1 != null) && block1.canCollideCheck(metadata1, shouldCollideWithFluids))
@@ -1341,7 +1341,7 @@ public class World implements WorldSource {
         }
     }
     
-    public void playBlockSoundEffect(@Nullable Entity player, double x, double y, double z, Block block, EnumBlockSoundEffectType soundType)
+    public void playBlockSoundEffect(@Nullable Entity player, double x, double y, double z, Block<?> block, EnumBlockSoundEffectType soundType)
     {
         if (block == null) return;
 
@@ -1508,7 +1508,7 @@ public class World implements WorldSource {
                 }
                 for(int dy = minY - 1; dy <= maxY; dy++)
                 {
-                    Block block = getBlock(dx, dy, dz);
+                    Block<?> block = getBlock(dx, dy, dz);
                     if(block != null)
                     {
                         int metadata = getBlockMetadata(dx, dy, dz);
@@ -1554,11 +1554,11 @@ public class World implements WorldSource {
                 }
                 for(int dy = minY - 1; dy <= maxY; dy++)
                 {
-                    Block block = Blocks.blocksList[getBlockId(dx, dy, dz)];
+                    Block<?> block = Blocks.blocksList[getBlockId(dx, dy, dz)];
                     if(block != null && block.isSolidRender())
                     {
                         // ignore mesh blocks if entity is instance of an item
-                        if(!(entity instanceof EntityItem && (block.id == Blocks.MESH.id || block.id == Blocks.SPIKES.id || block.id == Blocks.MOBSPAWNER.id)))
+                        if(!(entity instanceof EntityItem && (block.id() == Blocks.MESH.id() || block.id() == Blocks.SPIKES.id() || block.id() == Blocks.MOBSPAWNER.id())))
                             block.getCollidingBoundingBoxes(this, dx, dy, dz, axisalignedbb, collidingBoundingBoxes);
                     }
                 }
@@ -1571,7 +1571,7 @@ public class World implements WorldSource {
         List<Entity> list = getEntitiesWithinAABBExcludingEntity(entity, axisalignedbb.grow(d, d, d));
         for(int j2 = 0; j2 < list.size(); j2++)
         {
-            AABB aabb = ((Entity)list.get(j2)).getBb();
+            AABB aabb = list.get(j2).getBb();
             if(aabb != null && aabb.intersects(axisalignedbb))
             {
                 collidingBoundingBoxes.add(aabb);
@@ -1621,7 +1621,7 @@ public class World implements WorldSource {
         while(y > 0)
         {
             int id = chunk.getBlockID(x, y, z);
-            Material material = id != 0 ? Blocks.blocksList[id].blockMaterial : Material.air;
+            Material material = id != 0 ? Blocks.blocksList[id].getMaterial() : Material.air;
             if(!material.blocksMotion() && !material.isLiquid())
             {
                 y--;
@@ -1642,8 +1642,8 @@ public class World implements WorldSource {
         z &= (Chunk.CHUNK_SIZE_Z - 1);
         while(y > 0)
         {
-            Block block = Blocks.getBlock(chunk.getBlockID(x, y, z));
-            Material material = block != null ? block.blockMaterial : Material.air;
+            Block<?> block = Blocks.getBlock(chunk.getBlockID(x, y, z));
+            Material material = block != null ? block.getMaterial() : Material.air;
             if(!material.blocksMotion())
             {
                 y--;
@@ -1888,7 +1888,7 @@ public class World implements WorldSource {
 		for(int x = minX; x <= maxX; x++) {
 			for(int y = minY; y <= maxY; y++) {
 				for(int z = minZ; z <= maxZ; z++) {
-					Block block = Blocks.blocksList[getBlockId(x, y, z)];
+                    Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
 					if(block != null) {
 						return true;
 					}
@@ -1920,8 +1920,8 @@ public class World implements WorldSource {
 		for(int x = minX; x <= maxX; x++) {
 			for(int y = minY; y <= maxY; y++) {
 				for(int z = minZ; z <= maxZ; z++) {
-					Block block = Blocks.blocksList[getBlockId(x, y, z)];
-					if(block != null && block.blockMaterial.isLiquid()) {
+                    Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
+					if(block != null && block.getMaterial().isLiquid()) {
 						return true;
 					}
 				}
@@ -1956,7 +1956,7 @@ public class World implements WorldSource {
             {
                 for(int i2 = i1; i2 < j1; i2++)
                 {
-                    Block block = Blocks.blocksList[getBlockId(k1, l1, i2)];
+                    Block<?> block = Blocks.blocksList[getBlockId(k1, l1, i2)];
                     if(block == null || !isMaterialInBB(aabb, material))
                     {
                         continue;
@@ -1994,11 +1994,11 @@ public class World implements WorldSource {
             {
                 for(int _z = minZ_i; _z < maxZ_i; _z++)
                 {
-                    Block block = Blocks.blocksList[getBlockId(_x, _y, _z)];
+                    Block<?> block = Blocks.blocksList[getBlockId(_x, _y, _z)];
                     if(block != null) {
                         boolean isMaterial = false;
                         for (Material m : materials){
-                            if (block.blockMaterial == m) {
+                            if (block.getMaterial() == m) {
                                 isMaterial = true;
                                 break;
                             }
@@ -2031,8 +2031,8 @@ public class World implements WorldSource {
             {
                 for(int i2 = i1; i2 < j1; i2++)
                 {
-                    Block block = Blocks.blocksList[getBlockId(k1, l1, i2)];
-                    if(block == null || block.blockMaterial != material)
+                    Block<?> block = Blocks.blocksList[getBlockId(k1, l1, i2)];
+                    if(block == null || block.getMaterial() != material)
                     {
                         continue;
                     }
@@ -2108,7 +2108,7 @@ public class World implements WorldSource {
         x += side.getOffsetX();
         y += side.getOffsetY();
         z += side.getOffsetZ();
-        if(getBlockId(x, y, z) == Blocks.FIRE.id)
+        if(getBlockId(x, y, z) == Blocks.FIRE.id())
         {
             playBlockEvent(entityplayer, LevelListener.EVENT_FIRE_EXTINGUISH, x, y, z, 0);
             setBlockWithNotify(x, y, z, 0);
@@ -2186,7 +2186,7 @@ public class World implements WorldSource {
     @Override
     public boolean isBlockOpaqueCube(int x, int y, int z)
     {
-        Block block = Blocks.blocksList[getBlockId(x, y, z)];
+        Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
         if(block == null)
         {
             return false;
@@ -2198,7 +2198,7 @@ public class World implements WorldSource {
 
     public boolean canPlaceOnSurfaceOfBlock(int x, int y, int z)
     {
-        Block block = Blocks.blocksList[getBlockId(x, y, z)];
+        Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
         if(block == null)
         {
             return false;
@@ -2211,13 +2211,13 @@ public class World implements WorldSource {
     @Override
     public boolean isBlockNormalCube(int x, int y, int z)
     {
-        Block block = Blocks.blocksList[getBlockId(x, y, z)];
+        Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
         if(block == null)
         {
             return false;
         } else
         {
-            return block.blockMaterial.isSolidBlocking() && block.renderAsNormalBlockOnCondition(this, x, y, z);
+            return block.getMaterial().isSolidBlocking() && block.renderAsNormalBlockOnCondition(this, x, y, z);
         }
     }
     
@@ -2542,7 +2542,7 @@ public class World implements WorldSource {
             int rx = (x + rand.nextInt(radius)) - rand.nextInt(radius);
             int ry = (y + rand.nextInt(radius)) - rand.nextInt(radius);
             int rz = (z + rand.nextInt(radius)) - rand.nextInt(radius);
-            Block block = getBlock(rx, ry, rz);
+            Block<?> block = getBlock(rx, ry, rz);
             if (block != null) {
                 block.animationTick(this, rx, ry, rz, random);
             }
@@ -2571,13 +2571,13 @@ public class World implements WorldSource {
         return entityBuffer;
     }
 
-    public List<Entity> getEntitiesWithinAABB(Class<? extends Entity> ofClass, AABB aabb)
+    public <T extends Entity> @NotNull List<@NotNull T> getEntitiesWithinAABB(Class<T> ofClass, AABB aabb)
     {
         int minX = MathHelper.floor((aabb.minX - 2D) / Chunk.CHUNK_SIZE_X);
         int maxX = MathHelper.floor((aabb.maxX + 2D) / Chunk.CHUNK_SIZE_X);
         int minZ = MathHelper.floor((aabb.minZ - 2D) / Chunk.CHUNK_SIZE_Z);
         int maxZ = MathHelper.floor((aabb.maxZ + 2D) / Chunk.CHUNK_SIZE_Z);
-        List<Entity> entities = new ArrayList<>();
+        List<@NotNull T> entities = new ArrayList<>();
         for(int x = minX; x <= maxX; x++)
         {
             for(int z = minZ; z <= maxZ; z++)
@@ -2654,8 +2654,8 @@ public class World implements WorldSource {
     		return false;
     	}
         int j1 = getBlockId(x, y, z);
-        Block block = Blocks.blocksList[j1];
-        Block block1 = Blocks.blocksList[blockId];
+        Block<?> block = Blocks.blocksList[j1];
+        Block<?> block1 = Blocks.blocksList[blockId];
         AABB axisalignedbb = block1.getCollisionBoundingBoxFromPool(this, x, y, z);
         if(flag)
         {
@@ -2705,7 +2705,7 @@ public class World implements WorldSource {
     }
 
     public boolean getDirectSignal(int x, int y, int z, Side side) {
-        Block block = getBlock(x, y, z);
+        Block<?> block = getBlock(x, y, z);
         if (block == null) return false;
         return block.getDirectSignal(this, x, y, z, side);
     }
@@ -2725,7 +2725,7 @@ public class World implements WorldSource {
     }
 
     public boolean getSignal(int x, int y, int z, Side side) {
-        Block block = getBlock(x, y, z);
+        Block<?> block = getBlock(x, y, z);
         if(isBlockNormalCube(x, y, z) && block != Blocks.BLOCK_REDSTONE && block != Blocks.PUMPKIN_REDSTONE) {
             return hasDirectSignal(x, y, z);
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/WorldSource.java b/game/core/src/main/java/net/minecraft/core/world/WorldSource.java
index 4e4b90303..208a53557 100644
--- a/game/core/src/main/java/net/minecraft/core/world/WorldSource.java
+++ b/game/core/src/main/java/net/minecraft/core/world/WorldSource.java
@@ -6,13 +6,14 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.season.SeasonManager;
+import org.jetbrains.annotations.Nullable;
 
 public interface WorldSource
 {
 
     int getBlockId(int x, int y, int z);
 
-    Block getBlock(int x, int y, int z);
+    @Nullable Block<?> getBlock(int x, int y, int z);
 
     TileEntity getBlockEntity(int x, int y, int z);
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/Biome.java b/game/core/src/main/java/net/minecraft/core/world/biome/Biome.java
index 38a5e5c08..ebda87dcb 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/Biome.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/Biome.java
@@ -41,8 +41,8 @@ public class Biome
     public Biome(String key)
     {
     	this.translationKey = "biome." + key; 
-        topBlock = (short) Blocks.GRASS.id;
-        fillerBlock = (short)Blocks.DIRT.id;
+        topBlock = (short) Blocks.GRASS.id();
+        fillerBlock = (short)Blocks.DIRT.id();
         spawnableMonsterList = new ArrayList<>();
         spawnableCreatureList = new ArrayList<>();
         spawnableWaterCreatureList = new ArrayList<>();
@@ -66,10 +66,10 @@ public class Biome
     {
         if(random.nextInt(10) == 0)
         {
-            return new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id);
+            return new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id());
         } else
         {
-            return new WorldFeatureTree(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id, 4);
+            return new WorldFeatureTree(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id(), 4);
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBirchForest.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBirchForest.java
index b3f418d72..a69354919 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBirchForest.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBirchForest.java
@@ -24,9 +24,9 @@ public class BiomeBirchForest extends Biome
 
         if(random.nextInt(10) == 0)
         {
-            return new WorldFeatureTreeTall(Blocks.LEAVES_BIRCH.id, Blocks.LOG_BIRCH.id);
+            return new WorldFeatureTreeTall(Blocks.LEAVES_BIRCH.id(), Blocks.LOG_BIRCH.id());
         } else
-            return new WorldFeatureTree(Blocks.LEAVES_BIRCH.id, Blocks.LOG_BIRCH.id, 8);
+            return new WorldFeatureTree(Blocks.LEAVES_BIRCH.id(), Blocks.LOG_BIRCH.id(), 8);
 
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBorealForest.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBorealForest.java
index 98f0e018f..48e72e0ad 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBorealForest.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeBorealForest.java
@@ -20,6 +20,6 @@ public class BiomeBorealForest extends Biome
     @Override
 	public WorldFeature getRandomWorldGenForTrees(Random random)
     {
-        return new WorldFeatureTreeTaigaBushy(Blocks.LEAVES_PINE.id, Blocks.LOG_PINE.id);
+        return new WorldFeatureTreeTaigaBushy(Blocks.LEAVES_PINE.id(), Blocks.LOG_PINE.id());
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeCaatinga.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeCaatinga.java
index 4477c5b1e..033c563fa 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeCaatinga.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeCaatinga.java
@@ -22,10 +22,10 @@ public class BiomeCaatinga extends Biome
     {
         if(random.nextInt(3) != 0)
         {
-            return new WorldFeatureTreeShrub(Blocks.LEAVES_THORN.id, Blocks.LOG_OAK.id);
+            return new WorldFeatureTreeShrub(Blocks.LEAVES_THORN.id(), Blocks.LOG_OAK.id());
         } else
         {
-            return new WorldFeatureTreeThorn(4, Blocks.LOG_THORN.id, 0, Blocks.LEAVES_THORN.id, 0);
+            return new WorldFeatureTreeThorn(4, Blocks.LOG_THORN.id(), 0, Blocks.LEAVES_THORN.id(), 0);
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeForest.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeForest.java
index 8da8c2cab..969bf77f6 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeForest.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeForest.java
@@ -23,16 +23,16 @@ public class BiomeForest extends Biome
     {
         if(random.nextInt(5) == 0)
         {
-            return new WorldFeatureTree(Blocks.LEAVES_BIRCH.id, Blocks.LOG_BIRCH.id, 5);
+            return new WorldFeatureTree(Blocks.LEAVES_BIRCH.id(), Blocks.LOG_BIRCH.id(), 5);
         }
         if(random.nextInt(3) == 0)
         {
-            return new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id);
+            return new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id());
         } else
         {
             if(random.nextInt(25) == 0)
-                return new WorldFeatureTree(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK_MOSSY.id, 4);
-            return new WorldFeatureTree(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id, 4);
+                return new WorldFeatureTree(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK_MOSSY.id(), 4);
+            return new WorldFeatureTree(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id(), 4);
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeOutback.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeOutback.java
index a8be3d53f..cbb17769a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeOutback.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeOutback.java
@@ -23,6 +23,6 @@ public class BiomeOutback extends Biome
     @Override
 	public WorldFeature getRandomWorldGenForTrees(Random random)
     {
-        return new WorldFeatureTreeEucalyptus(Blocks.LEAVES_EUCALYPTUS.id, Blocks.LOG_EUCALYPTUS.id);
+        return new WorldFeatureTreeEucalyptus(Blocks.LEAVES_EUCALYPTUS.id(), Blocks.LOG_EUCALYPTUS.id());
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomePlains.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomePlains.java
index d7e32c07b..0d858c304 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomePlains.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomePlains.java
@@ -15,6 +15,6 @@ public class BiomePlains extends Biome
     @Override
     public WorldFeature getRandomWorldGenForTrees(Random random)
     {
-        return new WorldFeatureTreeEucalyptus(Blocks.LEAVES_EUCALYPTUS.id, Blocks.LOG_EUCALYPTUS.id);
+        return new WorldFeatureTreeEucalyptus(Blocks.LEAVES_EUCALYPTUS.id(), Blocks.LOG_EUCALYPTUS.id());
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRainforest.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRainforest.java
index b3ff065da..713a64d42 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRainforest.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRainforest.java
@@ -22,23 +22,23 @@ public class BiomeRainforest extends Biome
 	public WorldFeature getRandomWorldGenForTrees(Random random) {
 		if(random.nextInt(1000) == 0) {
 			int treeHeight = 30 + random.nextInt(30);
-			return new WorldFeatureSpoonerTreeRound(treeHeight, Blocks.LOG_OAK.id, 0, Blocks.LEAVES_OAK.id, 0);
+			return new WorldFeatureSpoonerTreeRound(treeHeight, Blocks.LOG_OAK.id(), 0, Blocks.LEAVES_OAK.id(), 0);
 		}
 		if(random.nextInt(10) == 0) {
 			return new WorldFeatureTreePalm(Blocks.LOG_PALM, Blocks.LEAVES_PALM, true, false, true);
 		}
 		if(random.nextInt(3) == 0) {
 			if(random.nextInt(10) == 0) {
-				return new WorldFeatureTreeFancyRainforest(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK_MOSSY.id, 0);
+				return new WorldFeatureTreeFancyRainforest(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK_MOSSY.id(), 0);
 			}
-			return new WorldFeatureTreeFancyRainforest(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id, 0);
+			return new WorldFeatureTreeFancyRainforest(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id(), 0);
 		}
 		if(random.nextInt(5) == 0) {
-			return new WorldFeatureTreeShrub(Blocks.LEAVES_SHRUB.id, Blocks.LOG_OAK.id);
+			return new WorldFeatureTreeShrub(Blocks.LEAVES_SHRUB.id(), Blocks.LOG_OAK.id());
 		}
 		if(random.nextInt(10) == 0) {
-			return new WorldFeatureTree(Blocks.LEAVES_CACAO.id, Blocks.LOG_OAK_MOSSY.id, 4);
+			return new WorldFeatureTree(Blocks.LEAVES_CACAO.id(), Blocks.LOG_OAK_MOSSY.id(), 4);
 		}
-		return new WorldFeatureTree(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id, 6);
+		return new WorldFeatureTree(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id(), 6);
 	}
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRetro.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRetro.java
index 2c31c5f4b..0a8b84f2e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRetro.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeRetro.java
@@ -35,10 +35,10 @@ public class BiomeRetro
     @Override
     public WorldFeature getRandomWorldGenForTrees(Random random)
     {
-        WorldFeature feature = new WorldFeatureTree(Blocks.LEAVES_OAK_RETRO.id, Blocks.LOG_OAK.id, 4);
+        WorldFeature feature = new WorldFeatureTree(Blocks.LEAVES_OAK_RETRO.id(), Blocks.LOG_OAK.id(), 4);
         if (random.nextInt(10) == 0)
         {
-            feature = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK_RETRO.id, Blocks.LOG_OAK.id);
+            feature = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK_RETRO.id(), Blocks.LOG_OAK.id());
         }
 
         return feature;
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSeasonalForest.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSeasonalForest.java
index 949724290..04fae0399 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSeasonalForest.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSeasonalForest.java
@@ -25,16 +25,16 @@ public class BiomeSeasonalForest extends Biome
         {
             if(random.nextInt(2) == 0)
             {
-                return new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id);
+                return new WorldFeatureTreeFancy(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id());
             }
-            return new WorldFeatureTree(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id, 4);
+            return new WorldFeatureTree(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id(), 4);
         }
         if(random.nextInt(3) == 0)
         {
-            return new WorldFeatureTreeFancy(Blocks.LEAVES_CHERRY.id, Blocks.LOG_CHERRY.id);
+            return new WorldFeatureTreeFancy(Blocks.LEAVES_CHERRY.id(), Blocks.LOG_CHERRY.id());
         } else
         {
-            return new WorldFeatureTreeCherry(Blocks.LEAVES_CHERRY.id, Blocks.LOG_CHERRY.id, 4);
+            return new WorldFeatureTreeCherry(Blocks.LEAVES_CHERRY.id(), Blocks.LOG_CHERRY.id(), 4);
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeShrubland.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeShrubland.java
index 481087ab9..8d07d2ea1 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeShrubland.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeShrubland.java
@@ -15,6 +15,6 @@ public class BiomeShrubland extends Biome
 	@Override
 	public WorldFeature getRandomWorldGenForTrees(Random random)
     {
-        return new WorldFeatureTreeShrub(Blocks.LEAVES_SHRUB.id, Blocks.LOG_OAK.id);
+        return new WorldFeatureTreeShrub(Blocks.LEAVES_SHRUB.id(), Blocks.LOG_OAK.id());
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSwamp.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSwamp.java
index 23841fec0..0ece7c0cc 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSwamp.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeSwamp.java
@@ -15,6 +15,6 @@ public class BiomeSwamp extends Biome
 	@Override
 	public WorldFeature getRandomWorldGenForTrees(Random random)
     {
-        return new WorldFeatureTreeShapeSwamp(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK_MOSSY.id, 6);
+        return new WorldFeatureTreeShapeSwamp(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK_MOSSY.id(), 6);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeTaiga.java b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeTaiga.java
index 373eae536..be0f34a9a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/BiomeTaiga.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/BiomeTaiga.java
@@ -23,10 +23,10 @@ public class BiomeTaiga extends Biome
     {
         if(random.nextInt(3) == 0)
         {
-            return new WorldFeatureTreeTaigaTall(Blocks.LEAVES_PINE.id, Blocks.LOG_PINE.id);
+            return new WorldFeatureTreeTaigaTall(Blocks.LEAVES_PINE.id(), Blocks.LOG_PINE.id());
         } else
         {
-            return new WorldFeatureTreeTaigaBushy(Blocks.LEAVES_PINE.id, Blocks.LOG_PINE.id);
+            return new WorldFeatureTreeTaigaBushy(Blocks.LEAVES_PINE.id(), Blocks.LOG_PINE.id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/Biomes.java b/game/core/src/main/java/net/minecraft/core/world/biome/Biomes.java
index de9b6da70..9dc78e3b2 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/Biomes.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/Biomes.java
@@ -12,24 +12,24 @@ public class Biomes
     public static final Biome OVERWORLD_SEASONAL_FOREST = register("minecraft:overworld.seasonal_forest", new BiomeSeasonalForest("seasonal_forest").setColor(0x64ce15));
     public static final Biome OVERWORLD_FOREST = register("minecraft:overworld.forest", new BiomeForest("forest").setColor(0x26a615));
     public static final Biome OVERWORLD_GRASSLANDS = register("minecraft:overworld.grasslands", new Biome("grasslands").setColor(0xf0f048).setBlockedWeathers(Weathers.OVERWORLD_SNOW));
-    public static final Biome OVERWORLD_OUTBACK = register("minecraft:overworld.outback", new BiomeOutback("outback").setColor(0xd95e20).setBlockedWeathers(Weathers.OVERWORLD_SNOW).setTopBlock(Blocks.DIRT_SCORCHED.id).setFillerBlock(Blocks.DIRT_SCORCHED.id));
+    public static final Biome OVERWORLD_OUTBACK = register("minecraft:overworld.outback", new BiomeOutback("outback").setColor(0xd95e20).setBlockedWeathers(Weathers.OVERWORLD_SNOW).setTopBlock(Blocks.DIRT_SCORCHED.id()).setFillerBlock(Blocks.DIRT_SCORCHED.id()));
     public static final Biome OVERWORLD_SHRUBLAND = register("minecraft:overworld.shrubland", new BiomeShrubland("shrubland").setColor(0xbaba38));
     public static final Biome OVERWORLD_TAIGA = register("minecraft:overworld.taiga", new BiomeTaiga("taiga").setColor(0x8abcff).setSurfaceSnow());
     public static final Biome OVERWORLD_BOREAL_FOREST = register("minecraft:overworld.boreal_forest", new BiomeBorealForest("boreal_forest").setColor(0x148564));
-    public static final Biome OVERWORLD_DESERT = register("minecraft:overworld.desert", new BiomeDesert("desert").setColor(0xEDE26F).setBlockedWeathers(Weathers.OVERWORLD_RAIN, Weathers.OVERWORLD_SNOW, Weathers.OVERWORLD_STORM).setTopBlock(Blocks.SAND.id).setFillerBlock(Blocks.SAND.id));
+    public static final Biome OVERWORLD_DESERT = register("minecraft:overworld.desert", new BiomeDesert("desert").setColor(0xEDE26F).setBlockedWeathers(Weathers.OVERWORLD_RAIN, Weathers.OVERWORLD_SNOW, Weathers.OVERWORLD_STORM).setTopBlock(Blocks.SAND.id()).setFillerBlock(Blocks.SAND.id()));
     public static final Biome OVERWORLD_PLAINS = register("minecraft:overworld.plains", new BiomePlains("plains").setColor(0xA3C649));
-    public static final Biome OVERWORLD_GLACIER = register("minecraft:overworld.glacier", new Biome("glacier").setColor(0xcbf6ff).setSurfaceSnow().setTopBlock(Blocks.BLOCK_SNOW.id).setFillerBlock(Blocks.BLOCK_SNOW.id));
+    public static final Biome OVERWORLD_GLACIER = register("minecraft:overworld.glacier", new Biome("glacier").setColor(0xcbf6ff).setSurfaceSnow().setTopBlock(Blocks.BLOCK_SNOW.id()).setFillerBlock(Blocks.BLOCK_SNOW.id()));
     public static final Biome OVERWORLD_TUNDRA = register("minecraft:overworld.tundra", new Biome("tundra").setColor(0x57e0ff).setSurfaceSnow());
     public static final Biome OVERWORLD_MEADOW = register("minecraft:overworld.meadow", new BiomeBorealForest("meadow").setColor(0x8c8c22));
     public static final Biome NETHER_NETHER = register("minecraft:nether.nether", new BiomeNether("nether").setColor(0xDD0000).setBlockedWeathers(Weathers.OVERWORLD_RAIN, Weathers.OVERWORLD_SNOW, Weathers.OVERWORLD_STORM, Weathers.OVERWORLD_FOG));
     public static final Biome PARADISE_PARADISE = register("minecraft:paradise.paradise", new BiomeParadise("paradise").setColor(0x8080FF).setBlockedWeathers(Weathers.OVERWORLD_RAIN, Weathers.OVERWORLD_SNOW, Weathers.OVERWORLD_STORM, Weathers.OVERWORLD_FOG));
     public static final Biome OVERWORLD_BIRCH_FOREST = register("minecraft:overworld.birch_forest", new BiomeBirchForest("birch_forest").setColor(0x4bcb5e));
-    public static final Biome OVERWORLD_RETRO = register("minecraft:overworld.retro", new BiomeRetro("retro").setColor(0x76B14A).setTopBlock(Blocks.GRASS_RETRO.id));
-    public static final Biome OVERWORLD_HELL = register("minecraft:overworld.hell", new Biome("hell").setColor(0xD96223).setTopBlock(Blocks.DIRT_SCORCHED.id).setTopBlock(Blocks.DIRT_SCORCHED.id));
+    public static final Biome OVERWORLD_RETRO = register("minecraft:overworld.retro", new BiomeRetro("retro").setColor(0x76B14A).setTopBlock(Blocks.GRASS_RETRO.id()));
+    public static final Biome OVERWORLD_HELL = register("minecraft:overworld.hell", new Biome("hell").setColor(0xD96223).setTopBlock(Blocks.DIRT_SCORCHED.id()).setTopBlock(Blocks.DIRT_SCORCHED.id()));
     public static final Biome OVERWORLD_SWAMPLAND_MUDDY = register("minecraft:overworld.swampland.muddy", new BiomeSwamp("swampland.muddy").setColor(0x522700));
-    public static final Biome OVERWORLD_OUTBACK_GRASSY = register("minecraft:overworld.outback.grassy", new BiomeOutback("outback.grassy").setColor(0xf09037).setBlockedWeathers(Weathers.OVERWORLD_SNOW).setTopBlock(Blocks.GRASS_SCORCHED.id).setFillerBlock(Blocks.DIRT_SCORCHED.id));
-    public static final Biome OVERWORLD_CAATINGA = register("minecraft:overworld.caatinga", new BiomeCaatinga("caatinga").setColor(0xdecda6).setTopBlock(Blocks.MUD_BAKED.id).setFillerBlock(Blocks.MUD_BAKED.id).setBlockedWeathers(Weathers.OVERWORLD_SNOW));
-    public static final Biome OVERWORLD_CAATINGA_PLAINS = register("minecraft:overworld.caatinga.plains", new Biome("caatinga.plains").setColor(0xa19477).setTopBlock(Blocks.MUD_BAKED.id).setFillerBlock(Blocks.MUD_BAKED.id).setBlockedWeathers(Weathers.OVERWORLD_SNOW));
+    public static final Biome OVERWORLD_OUTBACK_GRASSY = register("minecraft:overworld.outback.grassy", new BiomeOutback("outback.grassy").setColor(0xf09037).setBlockedWeathers(Weathers.OVERWORLD_SNOW).setTopBlock(Blocks.GRASS_SCORCHED.id()).setFillerBlock(Blocks.DIRT_SCORCHED.id()));
+    public static final Biome OVERWORLD_CAATINGA = register("minecraft:overworld.caatinga", new BiomeCaatinga("caatinga").setColor(0xdecda6).setTopBlock(Blocks.MUD_BAKED.id()).setFillerBlock(Blocks.MUD_BAKED.id()).setBlockedWeathers(Weathers.OVERWORLD_SNOW));
+    public static final Biome OVERWORLD_CAATINGA_PLAINS = register("minecraft:overworld.caatinga.plains", new Biome("caatinga.plains").setColor(0xa19477).setTopBlock(Blocks.MUD_BAKED.id()).setFillerBlock(Blocks.MUD_BAKED.id()).setBlockedWeathers(Weathers.OVERWORLD_SNOW));
     public static Biome register(String key, Biome biome)
     {
         Registries.BIOMES.register(key, biome);
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java b/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java
index 67c5a6bd4..fcf6285b9 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.world.chunk;
 
 import com.mojang.logging.LogUtils;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.Entity;
@@ -9,8 +10,7 @@ import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.world.biome.Biome;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockTileEntity;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
@@ -495,13 +495,12 @@ public class Chunk
         TileEntity tileEntity = blockEntityMap.get(pos);
         if(tileEntity == null)
         {
-            int id = getBlockID(x, y, z);
-            if(!Blocks.isEntityTile[id])
+            Block<?> block = Blocks.getBlock(getBlockID(x, y, z));
+            if(block == null || !block.isEntityTile)
             {
                 return null;
             }
-            BlockTileEntity tileEntityBlock = (BlockTileEntity)Blocks.blocksList[id];
-            tileEntityBlock.onBlockPlacedByWorld(world, xPosition * CHUNK_SIZE_X + x, y, zPosition * CHUNK_SIZE_Z + z);
+            block.onBlockPlacedByWorld(world, xPosition * CHUNK_SIZE_X + x, y, zPosition * CHUNK_SIZE_Z + z);
             tileEntity = blockEntityMap.get(pos);
         }
         if(tileEntity != null && tileEntity.isInvalid())
@@ -537,7 +536,8 @@ public class Chunk
         tileEntity.x = xPosition * CHUNK_SIZE_X + x;
         tileEntity.y = y;
         tileEntity.z = zPosition * CHUNK_SIZE_Z + z;
-        if (!(Blocks.blocksList[getBlockID(x, y, z)] instanceof BlockTileEntity))
+        Block<?> b = Blocks.blocksList[getBlockID(x, y, z)];
+        if (b == null || !b.isEntityTile)
         {
             LOGGER.warn("Attempted to place a tile entity where there was no entity tile!");
             Thread.dumpStack();
@@ -612,7 +612,7 @@ public class Chunk
         }
     }
 
-    public void getEntitiesWithin(Class<? extends Entity> ofClass, AABB aabb, List<Entity> entities)
+    public <T extends Entity> void getEntitiesWithin(Class<T> ofClass, AABB aabb, List<@NotNull T> entities)
     {
         int minSection = Math.max(0, MathHelper.floor((aabb.minY - 2D) / 16D));
         int maxSection = Math.min(MathHelper.floor((aabb.maxY + 2D) / 16D), CHUNK_SECTIONS - 1);
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkCache.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkCache.java
index 57918ce91..472de83b1 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkCache.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkCache.java
@@ -9,6 +9,7 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.season.SeasonManager;
+import org.jetbrains.annotations.Nullable;
 
 public class ChunkCache
     implements WorldSource
@@ -65,7 +66,7 @@ public class ChunkCache
     }
 
     @Override
-    public Block getBlock(int x, int y, int z) {
+    public @Nullable Block<?> getBlock(int x, int y, int z) {
         return Blocks.getBlock(getBlockId(x, y, z));
     }
 
@@ -227,14 +228,14 @@ public class ChunkCache
             return Material.air;
         } else
         {
-            return Blocks.blocksList[l].blockMaterial;
+            return Blocks.blocksList[l].getMaterial();
         }
     }
 
     @Override
 	public boolean isBlockOpaqueCube(int x, int y, int z)
     {
-        Block block = Blocks.blocksList[getBlockId(x, y, z)];
+        Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
         if(block == null)
         {
             return false;
@@ -247,13 +248,13 @@ public class ChunkCache
     @Override
 	public boolean isBlockNormalCube(int x, int y, int z)
     {
-        Block block = Blocks.blocksList[getBlockId(x, y, z)];
+        Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
         if(block == null)
         {
             return false;
         } else
         {
-            return block.blockMaterial.blocksMotion() && block.isCubeShaped();
+            return block.getMaterial().blocksMotion() && block.isCubeShaped();
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java
index dd4557136..b4b0cfb22 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.chunk;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.entity.Entity;
@@ -10,6 +9,7 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.data.ChunkNibbleArray;
 import net.minecraft.core.world.data.ChunkUnsignedByteArray;
+import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
 import java.nio.ShortBuffer;
@@ -156,10 +156,11 @@ public class ChunkSection {
         }
     }
 
-    public void getEntitiesWithin(Class<? extends Entity> ofClass, AABB aabb, List<Entity> entities) {
+    public <T extends Entity> void getEntitiesWithin(Class<T> ofClass, AABB aabb, List<@NotNull T> entities) {
         for (Entity e : this.entities) {
             if (ofClass.isAssignableFrom(e.getClass()) && e.bb.intersects(aabb)) {
-                entities.add(e);
+                //noinspection unchecked
+                entities.add((T) e);
             }
         }
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/EmptyChunk.java b/game/core/src/main/java/net/minecraft/core/world/chunk/EmptyChunk.java
index 1cbad469f..1481d1491 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/EmptyChunk.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/EmptyChunk.java
@@ -5,6 +5,7 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
 import java.util.List;
@@ -152,13 +153,13 @@ public class EmptyChunk extends Chunk
     }
 
     @Override
-	public void getEntitiesWithin(Entity toExclude, AABB aabb, List entities)
+	public void getEntitiesWithin(Entity toExclude, AABB aabb, List<Entity> entities)
     {
     }
 
     @Override
-	public void getEntitiesWithin(Class ofClass, AABB aabb, List entities)
-    {
+    public <T extends Entity> void getEntitiesWithin(Class<T> ofClass, AABB aabb, List<@NotNull T> entities) {
+
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java b/game/core/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java
index 44cb500f6..1f4710cc7 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java
@@ -1,7 +1,6 @@
 package net.minecraft.core.world.chunk;
 
 import com.mojang.logging.LogUtils;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java b/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java
index ed62446aa..c6aeccc92 100644
--- a/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java
+++ b/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java
@@ -11,7 +11,6 @@ import org.slf4j.Logger;
 
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Locale;
 import java.util.Map;
 
 public class SpawnerConfig {
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/CavesLargeFeature.java b/game/core/src/main/java/net/minecraft/core/world/generate/CavesLargeFeature.java
index 4b08708c8..d79716469 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/CavesLargeFeature.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/CavesLargeFeature.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.util.helper.MathHelper;
@@ -129,7 +128,7 @@ public class CavesLargeFeature extends LargeFeature {
                         if (y < this.minY || y >= this.maxY) {
                             continue;
                         }
-                        if (Block.hasTag(blockId, BlockTags.IS_WATER)) {
+                        if (Blocks.hasTag(blockId, BlockTags.IS_WATER)) {
                             hasHitWater = true;
                         }
                         if (y != minY - 1 && x != minX && x != maxX - 1 && z != minZ && z != maxZ - 1) {
@@ -161,12 +160,12 @@ public class CavesLargeFeature extends LargeFeature {
                         double yPercentage = ((y + 0.5D) - blockY) / height;
                         if (yPercentage > -0.7D && xPercentage * xPercentage + yPercentage * yPercentage + zPercentage * zPercentage < 1.0D) {
                             int blockId = result.getBlock(x, yIndex, z);
-                            if (Block.hasTag(blockId, BlockTags.CAVE_GEN_REPLACES_SURFACE)) {
+                            if (Blocks.hasTag(blockId, BlockTags.CAVE_GEN_REPLACES_SURFACE)) {
                                 replaceTopBlock = true;
                             }
-                            if (Block.hasTag(blockId, BlockTags.CAVES_CUT_THROUGH)) {
+                            if (Blocks.hasTag(blockId, BlockTags.CAVES_CUT_THROUGH)) {
                                 if (y < 10) {
-                                    result.setBlock(x, yIndex, z, Blocks.FLUID_LAVA_STILL.id);
+                                    result.setBlock(x, yIndex, z, Blocks.FLUID_LAVA_STILL.id());
                                 } else {
                                     result.setBlock(x, yIndex, z, 0);
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/WarrensCavesLargeFeature.java b/game/core/src/main/java/net/minecraft/core/world/generate/WarrensCavesLargeFeature.java
index 81e74694c..b06374ddc 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/WarrensCavesLargeFeature.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/WarrensCavesLargeFeature.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.util.helper.MathHelper;
@@ -150,7 +149,7 @@ public class WarrensCavesLargeFeature extends LargeFeature {
                         if (y < this.minY || y >= this.maxY) {
                             continue;
                         }
-                        if (Block.hasTag(blockId, BlockTags.IS_WATER)) {
+                        if (Blocks.hasTag(blockId, BlockTags.IS_WATER)) {
                             hasHitWater = true;
                         }
                         if (y != minY - 1 && x != minX && x != maxX - 1 && z != minZ && z != maxZ - 1) {
@@ -181,7 +180,7 @@ public class WarrensCavesLargeFeature extends LargeFeature {
                         double yPercentage = ((y + 0.5D) - blockY) / height;
                         if (yPercentage > -0.7D && xPercentage * xPercentage + yPercentage * yPercentage + zPercentage * zPercentage < 1.0D) {
                             int blockId = result.getBlock(x, yIndex, z);
-                            if (blockId == Blocks.SOULSCHIST.id) {
+                            if (blockId == Blocks.SOULSCHIST.id()) {
                                 result.setBlock(x, yIndex, z, 0);
                             }
                         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/ChunkGeneratorResult.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/ChunkGeneratorResult.java
index c9b0b5e25..88ecdfe46 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/ChunkGeneratorResult.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/ChunkGeneratorResult.java
@@ -23,7 +23,7 @@ public class ChunkGeneratorResult {
         int section = y / ChunkSection.SECTION_SIZE_Y;
         int cy = y % ChunkSection.SECTION_SIZE_Y;
 
-        Block newBlock = Blocks.getBlock(id);
+        Block<?> newBlock = Blocks.getBlock(id);
 
         // If the array is null and we're only clearing a block, skip creating it; otherwise, create it
         if (sectionBlocksArray[section] == null) {
@@ -35,7 +35,7 @@ public class ChunkGeneratorResult {
         }
 
         // Increment or decrement numBlocksInSection depending on whether we're setting or clearing a block
-        Block currentBlock = Blocks.getBlock(getBlock(x, y, z));
+        Block<?> currentBlock = Blocks.getBlock(getBlock(x, y, z));
         if (newBlock == null && currentBlock != null) {
             numBlocksInSectionArray[section]--;
         } else if (newBlock != null && currentBlock == null) {
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java
index 78d293c46..9e640a581 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java
@@ -127,7 +127,7 @@ public class ChunkGeneratorClassic
 
                     if (y == 0)
                     {
-                        blockID = Blocks.BEDROCK.id;
+                        blockID = Blocks.BEDROCK.id();
                     }
 
                     result.setBlock(x, y, z, blockID);
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/empty/ChunkDecoratorEmpty.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/empty/ChunkDecoratorEmpty.java
index 0f681cd77..2fbafffa9 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/empty/ChunkDecoratorEmpty.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/empty/ChunkDecoratorEmpty.java
@@ -12,7 +12,7 @@ public class ChunkDecoratorEmpty
     {
         if (chunk.xPosition == 0 && chunk.zPosition == 0)
         {
-            chunk.setBlockID(0, 0, 0, Blocks.BEDROCK.id);
+            chunk.setBlockID(0, 0, 0, Blocks.BEDROCK.id());
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/flat/ChunkGeneratorFlat.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/flat/ChunkGeneratorFlat.java
index 96d8888e0..50b6e66cc 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/flat/ChunkGeneratorFlat.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/flat/ChunkGeneratorFlat.java
@@ -21,14 +21,14 @@ public class ChunkGeneratorFlat
 
         for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
             for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
-                result.setBlock(x, 0, z, Blocks.BEDROCK.id);
+                result.setBlock(x, 0, z, Blocks.BEDROCK.id());
                 for (int y = 1; y < 4; y++) {
-                    result.setBlock(x, y, z, Blocks.STONE.id);
+                    result.setBlock(x, y, z, Blocks.STONE.id());
                 }
                 for (int y = 4; y < 6; y++) {
-                    result.setBlock(x, y, z, Blocks.DIRT.id);
+                    result.setBlock(x, y, z, Blocks.DIRT.id());
                 }
-                result.setBlock(x, 6, z, Blocks.GRASS.id);
+                result.setBlock(x, 6, z, Blocks.GRASS.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/ChunkGeneratorIndev.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/ChunkGeneratorIndev.java
index 83aaa3447..a490a6f92 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/ChunkGeneratorIndev.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/ChunkGeneratorIndev.java
@@ -39,7 +39,7 @@ public class ChunkGeneratorIndev
         // Place bedrock
         for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
             for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
-                result.setBlock(x, 0, z, Blocks.BEDROCK.id);
+                result.setBlock(x, 0, z, Blocks.BEDROCK.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java
index 4bc7eb155..04a27a2b2 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java
@@ -150,7 +150,7 @@ public final class LevelGenerator {
                     for (int y = 0; y < sizeY; y++) {
                         int id = 0;
                         if (y <= height) {
-                            id = Blocks.STONE.id;
+                            id = Blocks.STONE.id();
                         }
 
                         if (worldType == IndevWorldType.FLOATING && y < floatingLayerMinY) {
@@ -192,17 +192,17 @@ public final class LevelGenerator {
 
                     int height = heightMap[x + z * Chunk.CHUNK_SIZE_X];
                     int topBlock = result.getBlock(x, height + 1, z);
-                    if ((topBlock == Blocks.FLUID_WATER_FLOWING.id || topBlock == Blocks.FLUID_WATER_STILL.id || topBlock == 0)
+                    if ((topBlock == Blocks.FLUID_WATER_FLOWING.id() || topBlock == Blocks.FLUID_WATER_STILL.id() || topBlock == 0)
                         && height <= waterLevel - 1 && isGravel) {
-                        result.setBlock(x, height, z, Blocks.GRAVEL.id);
+                        result.setBlock(x, height, z, Blocks.GRAVEL.id());
                     }
 
                     if (topBlock == 0) {
                         int id = -1;
                         if (height <= beachHeight && isSand) {
-                            id = Blocks.SAND.id;
+                            id = Blocks.SAND.id();
                             if (worldTheme == IndevWorldTheme.HELL) {
-                                id = Blocks.GRASS.id;
+                                id = Blocks.GRASS.id();
                             }
                         }
 
@@ -222,7 +222,7 @@ public final class LevelGenerator {
                         int i = Chunk.makeBlockIndex(x, y, z);
                         int id = result.getBlock(x, y, z);
                         if (id == 0 && y < waterLevel) {
-                            result.setBlock(x, y, z, Blocks.FLUID_WATER_STILL.id);
+                            result.setBlock(x, y, z, Blocks.FLUID_WATER_STILL.id());
                         }
                     }
                 }
@@ -238,11 +238,11 @@ public final class LevelGenerator {
         for (int x = xSpawn - 3; x <= xSpawn + 3; x++) {
             for (int y = ySpawn - 2; y <= ySpawn + 2; y++) {
                 for (int z = zSpawn - 3; z <= zSpawn + 3; z++) {
-                    int id = y < ySpawn - 1 ? Blocks.OBSIDIAN.id : 0;
+                    int id = y < ySpawn - 1 ? Blocks.OBSIDIAN.id() : 0;
                     if (x == xSpawn - 3 || z == zSpawn - 3 || x == xSpawn + 3 || z == zSpawn + 3 || y == ySpawn - 2 || y == ySpawn + 2) {
-                        id = Blocks.STONE.id;
+                        id = Blocks.STONE.id();
                         if (y >= ySpawn - 1) {
-                            id = Blocks.PLANKS_OAK.id;
+                            id = Blocks.PLANKS_OAK.id();
                         }
                     }
 
@@ -255,7 +255,7 @@ public final class LevelGenerator {
             }
         }
 
-        world.setBlockWithNotify(xSpawn - 3 + 1, ySpawn + 2, zSpawn, Blocks.TORCH_COAL.id);
-        world.setBlockWithNotify(xSpawn + 3 - 1, ySpawn + 2, zSpawn, Blocks.TORCH_COAL.id);
+        world.setBlockWithNotify(xSpawn - 3 + 1, ySpawn + 2, zSpawn, Blocks.TORCH_COAL.id());
+        world.setBlockWithNotify(xSpawn + 3 - 1, ySpawn + 2, zSpawn, Blocks.TORCH_COAL.id());
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java
index 6b7d61976..191b5727d 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.generate.chunk.perlin.nether;
 
-import net.minecraft.core.block.BlockSand;
+import net.minecraft.core.block.BlockLogicSand;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
@@ -31,7 +31,7 @@ public class ChunkDecoratorNether
 
         Random rand = new Random((long) chunkX * 0x4f9939f508L + (long) chunkZ * 0x1ef1565bd5L);
 
-        BlockSand.fallInstantly = true;
+        BlockLogicSand.fallInstantly = true;
         int x = chunkX * 16;
         int z = chunkZ * 16;
         for(int i = 0; i < 8; i++)
@@ -39,7 +39,7 @@ public class ChunkDecoratorNether
             int xf = x + rand.nextInt(16) + 8;
             int yf = minY + rand.nextInt(rangeY - 8) + 4;
             int zf = z + rand.nextInt(16) + 8;
-            (new WorldFeatureNetherLava(Blocks.FLUID_LAVA_FLOWING.id)).place(world, rand, xf, yf, zf);
+            new WorldFeatureNetherLava(Blocks.FLUID_LAVA_FLOWING.id()).place(world, rand, xf, yf, zf);
         }
 
         for(int i = 0; i < 10; i++)
@@ -47,7 +47,7 @@ public class ChunkDecoratorNether
             int xf = x + rand.nextInt(16);
             int yf = minY + rand.nextInt(rangeY - 8) + 4;
             int zf = z + rand.nextInt(16);
-            (new WorldFeatureOre(Blocks.ORE_NETHERCOAL_NETHERRACK.id, 12)).place(world, rand, xf, yf, zf);
+            new WorldFeatureOre(Blocks.ORE_NETHERCOAL_NETHERRACK.id(), 12).place(world, rand, xf, yf, zf);
         }
 
         int max = rand.nextInt(rand.nextInt(10) + 1);
@@ -56,7 +56,7 @@ public class ChunkDecoratorNether
             int xf = x + rand.nextInt(16) + 8;
             int yf = minY + rand.nextInt(rangeY - 8) + 4;
             int zf = z + rand.nextInt(16) + 8;
-            (new WorldFeatureFire()).place(world, rand, xf, yf, zf);
+            new WorldFeatureFire().place(world, rand, xf, yf, zf);
         }
 
         max = rand.nextInt(rand.nextInt(10) + 1);
@@ -65,7 +65,7 @@ public class ChunkDecoratorNether
             int xf = x + rand.nextInt(16) + 8;
             int yf = minY + rand.nextInt(rangeY - 8) + 4;
             int zf = z + rand.nextInt(16) + 8;
-            (new WorldFeatureGlowstoneA()).place(world, rand, xf, yf, zf);
+            new WorldFeatureGlowstoneA().place(world, rand, xf, yf, zf);
         }
 
         for(int i = 0; i < 10; i++)
@@ -73,24 +73,24 @@ public class ChunkDecoratorNether
             int xf = x + rand.nextInt(16) + 8;
             int yf = minY + rand.nextInt(rangeY - 8) + 4;
             int zf = z + rand.nextInt(16) + 8;
-            (new WorldFeatureGlowstoneB()).place(world, rand, xf, yf, zf);
+            new WorldFeatureGlowstoneB().place(world, rand, xf, yf, zf);
         }
 
         if (rand.nextInt(8) == 0) {
             int xf = x + rand.nextInt(16) + 8;
             int yf = minY + rand.nextInt(rangeY - 16) + 8;
             int zf = z + rand.nextInt(16) + 8;
-            (new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id)).place(world, rand, xf, yf, zf);
+            new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id()).place(world, rand, xf, yf, zf);
         }
 
         for (int i = 0; i < /*20*/80; i++) {
             int xf = x + rand.nextInt(16);
             int yf = minY + rand.nextInt(rangeY);
             int zf = z + rand.nextInt(16);
-            (new WorldFeaturePumice(32)).place(world, rand, xf, yf, zf);
+            new WorldFeaturePumice(32).place(world, rand, xf, yf, zf);
         }
 
-        BlockSand.fallInstantly = false;
+        BlockLogicSand.fallInstantly = false;
 
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java
index 30ab6ec5c..1243dfa7a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java
@@ -88,19 +88,19 @@ public class SurfaceGeneratorNether
                             fillerBlock = (short) worldFillBlock;
                             if(generateGravelBeach)
                             {
-                                topBlock = (short) Blocks.GRAVEL.id;
+                                topBlock = (short) Blocks.GRAVEL.id();
                             }
                             if(generateGravelBeach)
                             {
-                                fillerBlock = (short) Blocks.COBBLE_NETHERRACK.id;
+                                fillerBlock = (short) Blocks.COBBLE_NETHERRACK.id();
                             }
                             if(generateSandBeach)
                             {
-                                topBlock = (short) Blocks.SOULSAND.id;
+                                topBlock = (short) Blocks.SOULSAND.id();
                             }
                             if(generateSandBeach)
                             {
-                                fillerBlock = (short) Blocks.SOULSAND.id;
+                                fillerBlock = (short) Blocks.SOULSAND.id();
                             }
                         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java
index 67bd855e7..e61bd069e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java
@@ -26,19 +26,19 @@ public class TerrainGeneratorNether
 
         if (y >= type.getMaxY() - rand.nextInt(5))
         {
-            return Blocks.BEDROCK.id;
+            return Blocks.BEDROCK.id();
         }
         else if (y >= halfHeight - rand.nextInt(5) && y <= halfHeight + 5 - rand.nextInt(5))
         {
-            return Blocks.BONESHALE.id;
+            return Blocks.BONESHALE.id();
         }
         else if (y <= type.getMinY() + rand.nextInt(5))
         {
-            return Blocks.BEDROCK.id;
+            return Blocks.BEDROCK.id();
         }
         else if (y <= halfHeight)
         {
-            return Blocks.SOULSCHIST.id;
+            return Blocks.SOULSCHIST.id();
         }
         else if (density > 0.0)
         {
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
index bb43679a1..b8e5eeb6d 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
@@ -1,16 +1,15 @@
 package net.minecraft.core.world.generate.chunk.perlin.overworld;
 
-import net.minecraft.core.block.BlockLeavesBase;
-import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicLeavesBase;
+import net.minecraft.core.block.BlockLogicMoss;
+import net.minecraft.core.block.BlockLogicOreCoal;
+import net.minecraft.core.block.BlockLogicOreDiamond;
+import net.minecraft.core.block.BlockLogicOreGold;
+import net.minecraft.core.block.BlockLogicOreIron;
+import net.minecraft.core.block.BlockLogicOreLapis;
+import net.minecraft.core.block.BlockLogicOreRedstone;
+import net.minecraft.core.block.BlockLogicSand;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockOreCoal;
-import net.minecraft.core.block.BlockOreDiamond;
-import net.minecraft.core.block.BlockOreGold;
-import net.minecraft.core.block.BlockOreIron;
-import net.minecraft.core.block.BlockOreLapis;
-import net.minecraft.core.block.BlockMoss;
-import net.minecraft.core.block.BlockOreRedstone;
-import net.minecraft.core.block.BlockSand;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biomes;
@@ -57,7 +56,7 @@ public class ChunkDecoratorOverworld
 
         float oreHeightModifier = rangeY / 128f;
 
-        BlockSand.fallInstantly = true;
+        BlockLogicSand.fallInstantly = true;
         int x = chunkX * 16;
         int z = chunkZ * 16;
         int y = world.getHeightValue(x + 16, z + 16);
@@ -77,7 +76,7 @@ public class ChunkDecoratorOverworld
                 {
                     int topBlock = world.getHeightValue(x + dx, z + dz);
                     int id = world.getBlockId(x + dx, topBlock - 1, z + dz);
-                    if (id == Blocks.GRASS.id)
+                    if (id == Blocks.GRASS.id())
                     {
                         boolean shouldPlaceWater = swampRand.nextFloat() < 0.5f;
                         if (shouldPlaceWater)
@@ -88,14 +87,14 @@ public class ChunkDecoratorOverworld
                             int negZId = world.getBlockId(x + dx, topBlock - 1, z + dz - 1);
                             int negYId = world.getBlockId(x + dx, topBlock - 2, z + dz);
                             if (
-                                    posXId != 0 && (Blocks.blocksList[posXId].blockMaterial.isSolid() || Blocks.blocksList[posXId].blockMaterial == Material.water) &&
-                                            negXId != 0 && (Blocks.blocksList[negXId].blockMaterial.isSolid() || Blocks.blocksList[negXId].blockMaterial == Material.water) &&
-                                            posZId != 0 && (Blocks.blocksList[posZId].blockMaterial.isSolid() || Blocks.blocksList[posZId].blockMaterial == Material.water) &&
-                                            negZId != 0 && (Blocks.blocksList[negZId].blockMaterial.isSolid() || Blocks.blocksList[negZId].blockMaterial == Material.water) &&
-                                            negYId != 0 && Blocks.blocksList[negYId].blockMaterial.isSolid()
+                                    posXId != 0 && (Blocks.blocksList[posXId].getMaterial().isSolid() || Blocks.blocksList[posXId].getMaterial() == Material.water) &&
+                                            negXId != 0 && (Blocks.blocksList[negXId].getMaterial().isSolid() || Blocks.blocksList[negXId].getMaterial() == Material.water) &&
+                                            posZId != 0 && (Blocks.blocksList[posZId].getMaterial().isSolid() || Blocks.blocksList[posZId].getMaterial() == Material.water) &&
+                                            negZId != 0 && (Blocks.blocksList[negZId].getMaterial().isSolid() || Blocks.blocksList[negZId].getMaterial() == Material.water) &&
+                                            negYId != 0 && Blocks.blocksList[negYId].getMaterial().isSolid()
                             )
                             {
-                                world.setBlock(x + dx, topBlock - 1, z + dz, Blocks.FLUID_WATER_STILL.id);
+                                world.setBlock(x + dx, topBlock - 1, z + dz, Blocks.FLUID_WATER_STILL.id());
                                 world.setBlock(x + dx, topBlock, z + dz, 0);
                             }
                         }
@@ -110,22 +109,22 @@ public class ChunkDecoratorOverworld
         if (biome == Biomes.OVERWORLD_DESERT)
             lakeChance = 0;
         if (lakeChance != 0 && rand.nextInt(lakeChance) == 0) {
-            int fluid = Blocks.FLUID_WATER_STILL.id;
+            int fluid = Blocks.FLUID_WATER_STILL.id();
             if (biome.hasSurfaceSnow())
             {
-                fluid = Blocks.ICE.id;
+                fluid = Blocks.ICE.id();
             }
             int i1 = x + rand.nextInt(16) + 8;
             int l4 = minY + rand.nextInt(rangeY);
             int i8 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureLake(fluid)).place(world, rand, i1, l4, i8);
+            new WorldFeatureLake(fluid).place(world, rand, i1, l4, i8);
         }
         if (rand.nextInt(8) == 0) {
             int xf = x + rand.nextInt(16) + 8;
             int yf = minY + rand.nextInt(rand.nextInt(rangeY - (rangeY / 16)) + (rangeY / 16));
             int zf = z + rand.nextInt(16) + 8;
             if (yf < minY + rangeY / 2 || rand.nextInt(10) == 0) {
-                (new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id)).place(world, rand, xf, yf, zf);
+                new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id()).place(world, rand, xf, yf, zf);
             }
         }
         for (int k1 = 0; k1 < (8 * oreHeightModifier); k1++) {
@@ -133,9 +132,9 @@ public class ChunkDecoratorOverworld
             int k8 = minY + rand.nextInt(rangeY);
             int j11 = z + rand.nextInt(16) + 8;
             if (rand.nextInt(2) == 0) {
-                (new WorldFeatureDungeon(Blocks.BRICK_CLAY.id, Blocks.BRICK_CLAY.id, null)).place(world, rand, j5, k8, j11);
+                new WorldFeatureDungeon(Blocks.BRICK_CLAY.id(), Blocks.BRICK_CLAY.id(), null).place(world, rand, j5, k8, j11);
             } else {
-                (new WorldFeatureDungeon(Blocks.COBBLE_STONE.id, Blocks.COBBLE_STONE_MOSSY.id, null)).place(world, rand, j5, k8, j11);
+                new WorldFeatureDungeon(Blocks.COBBLE_STONE.id(), Blocks.COBBLE_STONE_MOSSY.id(), null).place(world, rand, j5, k8, j11);
             }
         }
 
@@ -181,63 +180,63 @@ public class ChunkDecoratorOverworld
             int l5 = x + rand.nextInt(16);
             int i9 = minY + rand.nextInt(rangeY);
             int l11 = z + rand.nextInt(16);
-            (new WorldFeatureOre(Blocks.DIRT.id, 32)).place(world, rand, l5, i9, l11);
+            (new WorldFeatureOre(Blocks.DIRT.id(), 32)).place(world, rand, l5, i9, l11);
         }
 
         for (int k2 = 0; k2 < (10 * oreHeightModifier); k2++) {
             int i6 = x + rand.nextInt(16);
             int j9 = minY + rand.nextInt(rangeY);
             int i12 = z + rand.nextInt(16);
-            (new WorldFeatureOre(Blocks.GRAVEL.id, 32)).place(world, rand, i6, j9, i12);
+            (new WorldFeatureOre(Blocks.GRAVEL.id(), 32)).place(world, rand, i6, j9, i12);
         }
 
         for (int i3 = 0; i3 < (20 * oreHeightModifier); i3++) {
             int j6 = x + rand.nextInt(16);
             int k9 = minY + rand.nextInt(rangeY);
             int j12 = z + rand.nextInt(16);
-            new WorldFeatureOre(BlockOreCoal.variantMap, 16).place(world, rand, j6, k9, j12);
+            new WorldFeatureOre(BlockLogicOreCoal.variantMap, 16).place(world, rand, j6, k9, j12);
         }
 
         for (int j3 = 0; j3 < (20 * oreHeightModifier); j3++) {
             int k6 = x + rand.nextInt(16);
             int l9 = minY + rand.nextInt(rangeY / 2);
             int k12 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreIron.variantMap, 8)).place(world, rand, k6, l9, k12);
+            (new WorldFeatureOre(BlockLogicOreIron.variantMap, 8)).place(world, rand, k6, l9, k12);
         }
 
         for (int k3 = 0; k3 < (2 * oreHeightModifier); k3++) {
             int l6 = x + rand.nextInt(16);
             int i10 = minY + rand.nextInt(rangeY / 4);
             int l12 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreGold.variantMap, 8)).place(world, rand, l6, i10, l12);
+            (new WorldFeatureOre(BlockLogicOreGold.variantMap, 8)).place(world, rand, l6, i10, l12);
         }
 
         for (int l3 = 0; l3 < (8 * oreHeightModifier); l3++) {
             int i7 = x + rand.nextInt(16);
             int j10 = minY + rand.nextInt(rangeY / 8);
             int i13 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreRedstone.variantMap, 7)).place(world, rand, i7, j10, i13);
+            (new WorldFeatureOre(BlockLogicOreRedstone.variantMap, 7)).place(world, rand, i7, j10, i13);
         }
 
         for (int i4 = 0; i4 < oreHeightModifier; i4++) {
             int j7 = x + rand.nextInt(16);
             int k10 = minY + rand.nextInt(rangeY / 8);
             int j13 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreDiamond.variantMap, 7)).place(world, rand, j7, k10, j13);
+            (new WorldFeatureOre(BlockLogicOreDiamond.variantMap, 7)).place(world, rand, j7, k10, j13);
         }
 
         for (int i4 = 0; i4 < oreHeightModifier; i4++) {
             int j7 = x + rand.nextInt(16);
             int k10 = minY + rand.nextInt(rangeY / 2);
             int j13 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockMoss.variantMap, 32)).place(world, rand, j7, k10, j13);
+            (new WorldFeatureOre(BlockLogicMoss.variantMap, 32)).place(world, rand, j7, k10, j13);
         }
 
         for (int j4 = 0; j4 < oreHeightModifier; j4++) {
             int k7 = x + rand.nextInt(16);
             int l10 = minY + rand.nextInt(rangeY / 8) + rand.nextInt(rangeY / 8);
             int k13 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreLapis.variantMap, 6)).place(world, rand, k7, l10, k13);
+            (new WorldFeatureOre(BlockLogicOreLapis.variantMap, 6)).place(world, rand, k7, l10, k13);
         }
 
 
@@ -288,7 +287,7 @@ public class ChunkDecoratorOverworld
         }
         if (treeDensityOverride != -1) treeDensity = treeDensityOverride;
         try {
-        	BlockLeavesBase.enableDecay = false;
+        	BlockLogicLeavesBase.enableDecay = false;
             for (int i11 = 0; i11 < treeDensity; i11++) {
                 int l13 = x + rand.nextInt(16) + 8;
                 int j14 = z + rand.nextInt(16) + 8;
@@ -297,7 +296,7 @@ public class ChunkDecoratorOverworld
                 feature.place(world, rand, l13, world.getHeightValue(l13, j14), j14);
             }
         }finally {
-        	BlockLeavesBase.enableDecay = true;
+            BlockLogicLeavesBase.enableDecay = true;
         }
         byte byteReeds = 0;
         if (biome == Biomes.OVERWORLD_RAINFOREST) {
@@ -318,7 +317,7 @@ public class ChunkDecoratorOverworld
             byteOrchid = 1;
         }
         for (int l14 = 0; l14 < byteOrchid; l14++) {
-            int[] flowerIds= { Blocks.FLOWER_YELLOW.id, Blocks.FLOWER_PINK.id, Blocks.FLOWER_RED.id };
+            int[] flowerIds= { Blocks.FLOWER_YELLOW.id(), Blocks.FLOWER_PINK.id(), Blocks.FLOWER_RED.id() };
 
             int l19 = x + rand.nextInt(16) + 8;
             int k22 = rand.nextInt(world.getHeightBlocks());
@@ -341,12 +340,12 @@ public class ChunkDecoratorOverworld
         }
 
         for (int l14 = 0; l14 < byteMeadow; l14++) {
-            int blockId = Blocks.FLOWER_PURPLE.id;
+            int blockId = Blocks.FLOWER_PURPLE.id();
             if (rand.nextInt(12) == 0) {
-                blockId = Blocks.FLOWER_RED.id;
+                blockId = Blocks.FLOWER_RED.id();
             }
             if (rand.nextInt(6) == 0) {
-                blockId = Blocks.FLOWER_YELLOW.id;
+                blockId = Blocks.FLOWER_YELLOW.id();
             }
             int l19 = x + rand.nextInt(16) + 8;
             int k22 = rand.nextInt(world.getHeightBlocks());
@@ -372,7 +371,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, 64, true)).place(world, rand, k14, l16, k19);
+            (new WorldFeatureFlowers(Blocks.FLOWER_LIGHT_BLUE.id(), 64, true)).place(world, rand, k14, l16, k19);
         }
 
         byte byteMarigold = 0;
@@ -395,7 +394,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, 64, true)).place(world, rand, k14, l16, k19);
+            (new WorldFeatureFlowers(Blocks.FLOWER_ORANGE.id(), 64, true)).place(world, rand, k14, l16, k19);
         }
 
         byte byte0 = 0;
@@ -423,7 +422,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, 64, true)).place(world, rand, k14, l16, k19);
+            (new WorldFeatureFlowers(Blocks.FLOWER_YELLOW.id(), 64, true)).place(world, rand, k14, l16, k19);
         }
 
         byte byte1 = 0;
@@ -458,9 +457,9 @@ public class ChunkDecoratorOverworld
             byte1 = 2;
         }
         for (int l14 = 0; l14 < byte1; l14++) {
-            int type = Blocks.TALLGRASS.id;
+            int type = Blocks.TALLGRASS.id();
             if ((biome == Biomes.OVERWORLD_RAINFOREST || biome == Biomes.OVERWORLD_SWAMPLAND || biome == Biomes.OVERWORLD_BOREAL_FOREST || biome == Biomes.OVERWORLD_TAIGA) && rand.nextInt(3) != 0) {
-                type = Blocks.TALLGRASS_FERN.id;
+                type = Blocks.TALLGRASS_FERN.id();
             }
             int l19 = x + rand.nextInt(16) + 8;
             int k22 = minY + rand.nextInt(rangeY);
@@ -490,26 +489,26 @@ public class ChunkDecoratorOverworld
             int i17 = x + rand.nextInt(16) + 8;
             int i20 = minY + rand.nextInt(rangeY);
             int l22 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureDeadBush(Blocks.DEADBUSH.id)).place(world, rand, i17, i20, l22);
+            (new WorldFeatureDeadBush(Blocks.DEADBUSH.id())).place(world, rand, i17, i20, l22);
         }
 
         if (rand.nextInt(2) == 0) {
             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, 64, true)).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, 64, false)).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, 64, false)).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;
@@ -555,7 +554,7 @@ public class ChunkDecoratorOverworld
             int l21 = x + rand.nextInt(16) + 8;
             int k23 = minY + rand.nextInt(rand.nextInt(rangeY - (rangeY / 16)) + (rangeY / 16));
             int l24 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureLiquid(Blocks.FLUID_WATER_FLOWING.id)).place(world, rand, l21, k23, l24);
+            (new WorldFeatureLiquid(Blocks.FLUID_WATER_FLOWING.id())).place(world, rand, l21, k23, l24);
         }
 
         for(int i19 = 0; i19 < 20; i19++)
@@ -563,7 +562,7 @@ public class ChunkDecoratorOverworld
             int i22 = x + rand.nextInt(16) + 8;
             int l23 = minY + rand.nextInt(rand.nextInt(rand.nextInt(rangeY - (rangeY / 8)) + (rangeY / 16)) + (rangeY / 16));
             int i25 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id)).place(world, rand, i22, l23, i25);
+            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id())).place(world, rand, i22, l23, i25);
         }
 
         int oceanY = world.getWorldType().getOceanY();
@@ -578,19 +577,19 @@ public class ChunkDecoratorOverworld
                 {
                     if (world.isAirBlock(dx, dy, dz) && world.getBlockMaterial(dx, dy - 1, dz).blocksMotion())
                     {
-                        world.setBlockWithNotify(dx, dy, dz, Blocks.LAYER_SNOW.id);
+                        world.setBlockWithNotify(dx, dy, dz, Blocks.LAYER_SNOW.id());
                     }
                 }
-                if ((localBiome.hasSurfaceSnow() || world.worldType == WorldTypes.OVERWORLD_WINTER) && (world.getBlockId(dx, oceanY - 1, dz) == Blocks.FLUID_WATER_STILL.id || world.getBlockId(dx, oceanY - 1, dz) == Blocks.FLUID_WATER_FLOWING.id))
+                if ((localBiome.hasSurfaceSnow() || world.worldType == WorldTypes.OVERWORLD_WINTER) && (world.getBlockId(dx, oceanY - 1, dz) == Blocks.FLUID_WATER_STILL.id() || world.getBlockId(dx, oceanY - 1, dz) == Blocks.FLUID_WATER_FLOWING.id()))
                 {
-                    world.setBlockWithNotify(dx, oceanY - 1, dz, Blocks.ICE.id);
+                    world.setBlockWithNotify(dx, oceanY - 1, dz, Blocks.ICE.id());
                 }
 
             }
 
         }
 
-        BlockSand.fallInstantly = false;
+        BlockLogicSand.fallInstantly = false;
         world.scheduledUpdatesAreImmediate = false;
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java
index e72eaa908..18c2f207f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java
@@ -156,24 +156,24 @@ public class SurfaceGeneratorOverworld
                                 fillerBlock = biome.fillerBlock;
                                 if(biomeGeneratesMud)
                                 {
-                                    topBlock = (short) Blocks.MUD.id;
-                                    fillerBlock = (short) Blocks.MUD.id;
+                                    topBlock = (short) Blocks.MUD.id();
+                                    fillerBlock = (short) Blocks.MUD.id();
                                 }
                                 else if(generateGravelBeach)
                                 {
                                     topBlock = 0;
-                                    fillerBlock = (short) Blocks.GRAVEL.id;
+                                    fillerBlock = (short) Blocks.GRAVEL.id();
                                 }
                                 else if(generateSandBeach)
                                 {
-                                    topBlock = (short) Blocks.SAND.id;
-                                    fillerBlock = (short) Blocks.SAND.id;
+                                    topBlock = (short) Blocks.SAND.id();
+                                    fillerBlock = (short) Blocks.SAND.id();
                                 }
                             } else if (y <= oceanY) {
                                 if(biomeGeneratesMud) // Make mud under the ocean always be regular mud
                                 {
-                                    topBlock = (short) Blocks.MUD.id;
-                                    fillerBlock = (short) Blocks.MUD.id;
+                                    topBlock = (short) Blocks.MUD.id();
+                                    fillerBlock = (short) Blocks.MUD.id();
                                 }
                             }
                         }
@@ -208,21 +208,21 @@ public class SurfaceGeneratorOverworld
                             {
                                 if (generateBasaltLayer)
                                 {
-                                    result.setBlock(x, y, z, Blocks.BASALT.id);
+                                    result.setBlock(x, y, z, Blocks.BASALT.id());
                                     continue;
                                 }
                             }
                             if(biome == Biomes.OVERWORLD_GLACIER){
                                 if (y >= (minY + 56 + graniteThicknessLevel/4 - rand.nextInt(3)) && y <= maxY)
                                 {
-                                    result.setBlock(x, y, z, Blocks.PERMAFROST.id);
+                                    result.setBlock(x, y, z, Blocks.PERMAFROST.id());
                                     continue;
                                 }
                             }
                             if(biome == Biomes.OVERWORLD_TUNDRA){
                                 if (y >= (minY + 56 + graniteThicknessLevel/4 - rand.nextInt(3)) && y <= (minY + (56 + 36) + graniteThicknessLevel/8 - rand.nextInt(3)))
                                 {
-                                    result.setBlock(x, y, z, Blocks.PERMAFROST.id);
+                                    result.setBlock(x, y, z, Blocks.PERMAFROST.id());
                                     continue;
                                 }
                             }
@@ -230,7 +230,7 @@ public class SurfaceGeneratorOverworld
                             {
                                 if (generateGraniteLayer)
                                 {
-                                    result.setBlock(x, y, z, Blocks.GRANITE.id);
+                                    result.setBlock(x, y, z, Blocks.GRANITE.id());
                                     continue;
                                 }
                             }
@@ -238,7 +238,7 @@ public class SurfaceGeneratorOverworld
                             {
                                 if (generateLimestoneLayer)
                                 {
-                                    result.setBlock(x, y, z, Blocks.LIMESTONE.id);
+                                    result.setBlock(x, y, z, Blocks.LIMESTONE.id());
                                     continue;
                                 }
                             }
@@ -256,12 +256,12 @@ public class SurfaceGeneratorOverworld
                     // if reached end of filler layer, fill world with sandstone/permafrost if inside a glacier or desert biome
                     if(currentLayerDepth == 0)
                     {
-                        if(biome == Biomes.OVERWORLD_DESERT && fillerBlock == Blocks.SAND.id) {
+                        if(biome == Biomes.OVERWORLD_DESERT && fillerBlock == Blocks.SAND.id()) {
                             currentLayerDepth = rand.nextInt(8) + 2;
-                            fillerBlock = (short)Blocks.SANDSTONE.id;
-                        } else if(biome == Biomes.OVERWORLD_GLACIER && fillerBlock == Blocks.BLOCK_SNOW.id){
+                            fillerBlock = (short)Blocks.SANDSTONE.id();
+                        } else if(biome == Biomes.OVERWORLD_GLACIER && fillerBlock == Blocks.BLOCK_SNOW.id()){
                             currentLayerDepth = rand.nextInt(8) + 14;
-                            fillerBlock = (short)Blocks.PERMAFROST.id;
+                            fillerBlock = (short)Blocks.PERMAFROST.id();
                         }
                     }
                 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/TerrainGeneratorOverworld.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/TerrainGeneratorOverworld.java
index 75ac3317f..2f3f21a09 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/TerrainGeneratorOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/TerrainGeneratorOverworld.java
@@ -30,7 +30,7 @@ public class TerrainGeneratorOverworld
 
         if (y <= type.getMinY() + rand.nextInt(5))
         {
-            return Blocks.BEDROCK.id;
+            return Blocks.BEDROCK.id();
         }
         else if (density > 0.0)
         {
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java
index 9ae76f29d..293c58a70 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java
@@ -1,13 +1,13 @@
 package net.minecraft.core.world.generate.chunk.perlin.overworld.hell;
 
-import net.minecraft.core.block.BlockSand;
+import net.minecraft.core.block.BlockLogicOreCoal;
+import net.minecraft.core.block.BlockLogicOreDiamond;
+import net.minecraft.core.block.BlockLogicOreGold;
+import net.minecraft.core.block.BlockLogicOreIron;
+import net.minecraft.core.block.BlockLogicOreLapis;
+import net.minecraft.core.block.BlockLogicOreRedstone;
+import net.minecraft.core.block.BlockLogicSand;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockOreCoal;
-import net.minecraft.core.block.BlockOreDiamond;
-import net.minecraft.core.block.BlockOreGold;
-import net.minecraft.core.block.BlockOreIron;
-import net.minecraft.core.block.BlockOreLapis;
-import net.minecraft.core.block.BlockOreRedstone;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.generate.chunk.ChunkDecorator;
@@ -43,7 +43,7 @@ public class ChunkDecoratorOverworldHell
 
 //        float oreHeightModifier = rangeY / 128f;
 
-        BlockSand.fallInstantly = true;
+        BlockLogicSand.fallInstantly = true;
         int x = chunkX * 16;
         int z = chunkZ * 16;
 //        int y = world.getHeightValue(x + 16, z + 16);
@@ -57,7 +57,7 @@ public class ChunkDecoratorOverworldHell
             int i1 = x + rand.nextInt(16) + 8;
             int l4 = minY + rand.nextInt(rangeY);
             int i8 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id)).place(world, rand, i1, l4, i8);
+            (new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id())).place(world, rand, i1, l4, i8);
         }
         if(rand.nextInt(16) == 0)
         {
@@ -69,11 +69,11 @@ public class ChunkDecoratorOverworldHell
             {
                 if(rand.nextInt(4) == 0)
                 {
-                    (new WorldFeatureLake(Blocks.OBSIDIAN.id)).place(world, rand, j1, i5, j8);
+                    (new WorldFeatureLake(Blocks.OBSIDIAN.id())).place(world, rand, j1, i5, j8);
                 }
                 else
                 {
-                    (new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id)).place(world, rand, j1, i5, j8);
+                    (new WorldFeatureLake(Blocks.FLUID_LAVA_STILL.id())).place(world, rand, j1, i5, j8);
                 }
             }
         }
@@ -84,7 +84,7 @@ public class ChunkDecoratorOverworldHell
             int k23 = minY + rand.nextInt(rangeY / 2);
             int l24 = z + rand.nextInt(16) + 8;
             if(k23 < minY + rangeY / 2) {
-                (new WorldFeatureLiquid(Blocks.FLUID_WATER_FLOWING.id)).place(world, rand, l21, k23, l24);
+                (new WorldFeatureLiquid(Blocks.FLUID_WATER_FLOWING.id())).place(world, rand, l21, k23, l24);
             }
         }
         for(int k1 = 0; k1 < 8; k1++)
@@ -94,11 +94,11 @@ public class ChunkDecoratorOverworldHell
             int j11 = z + rand.nextInt(16) + 8;
             if (rand.nextInt(2) == 0)
             {
-                (new WorldFeatureDungeon(Blocks.BRICK_CLAY.id, Blocks.BRICK_CLAY.id, null)).place(world, rand, j5, k8, j11);
+                (new WorldFeatureDungeon(Blocks.BRICK_CLAY.id(), Blocks.BRICK_CLAY.id(), null)).place(world, rand, j5, k8, j11);
             }
             else
             {
-                (new WorldFeatureDungeon(Blocks.COBBLE_STONE.id, Blocks.COBBLE_STONE_MOSSY.id, null)).place(world, rand, j5, k8, j11);
+                (new WorldFeatureDungeon(Blocks.COBBLE_STONE.id(), Blocks.COBBLE_STONE_MOSSY.id(), null)).place(world, rand, j5, k8, j11);
             }
         }
 
@@ -130,7 +130,7 @@ public class ChunkDecoratorOverworldHell
             int l5 = x + rand.nextInt(16);
             int i9 = minY + rand.nextInt(rangeY);
             int l11 = z + rand.nextInt(16);
-            (new WorldFeatureOre(Blocks.DIRT.id, 32)).place(world, rand, l5, i9, l11);
+            (new WorldFeatureOre(Blocks.DIRT.id(), 32)).place(world, rand, l5, i9, l11);
         }
 
         for(int k2 = 0; k2 < 10; k2++)
@@ -138,7 +138,7 @@ public class ChunkDecoratorOverworldHell
             int i6 = x + rand.nextInt(16);
             int j9 = minY + rand.nextInt(rangeY);
             int i12 = z + rand.nextInt(16);
-            (new WorldFeatureOre(Blocks.GRAVEL.id, 32)).place(world, rand, i6, j9, i12);
+            (new WorldFeatureOre(Blocks.GRAVEL.id(), 32)).place(world, rand, i6, j9, i12);
         }
 
         for(int i3 = 0; i3 < 20; i3++)
@@ -146,7 +146,7 @@ public class ChunkDecoratorOverworldHell
             int j6 = x + rand.nextInt(16);
             int k9 = minY + rand.nextInt(rangeY);
             int j12 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreCoal.variantMap, 16)).place(world, rand, j6, k9, j12);
+            (new WorldFeatureOre(BlockLogicOreCoal.variantMap, 16)).place(world, rand, j6, k9, j12);
         }
 
         for(int j3 = 0; j3 < 20; j3++)
@@ -154,7 +154,7 @@ public class ChunkDecoratorOverworldHell
             int k6 = x + rand.nextInt(16);
             int l9 = minY + rand.nextInt(rangeY / 2);
             int k12 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreIron.variantMap, 8)).place(world, rand, k6, l9, k12);
+            (new WorldFeatureOre(BlockLogicOreIron.variantMap, 8)).place(world, rand, k6, l9, k12);
         }
 
         for(int k3 = 0; k3 < 2; k3++)
@@ -162,7 +162,7 @@ public class ChunkDecoratorOverworldHell
             int l6 = x + rand.nextInt(16);
             int i10 = minY + rand.nextInt(rangeY / 4);
             int l12 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreGold.variantMap, 8)).place(world, rand, l6, i10, l12);
+            (new WorldFeatureOre(BlockLogicOreGold.variantMap, 8)).place(world, rand, l6, i10, l12);
         }
 
         for(int l3 = 0; l3 < 8; l3++)
@@ -170,7 +170,7 @@ public class ChunkDecoratorOverworldHell
             int i7 = x + rand.nextInt(16);
             int j10 = minY + rand.nextInt(rangeY / 8);
             int i13 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreRedstone.variantMap, 7)).place(world, rand, i7, j10, i13);
+            (new WorldFeatureOre(BlockLogicOreRedstone.variantMap, 7)).place(world, rand, i7, j10, i13);
         }
 
         for(int i4 = 0; i4 < 1; i4++)
@@ -178,7 +178,7 @@ public class ChunkDecoratorOverworldHell
             int j7 = x + rand.nextInt(16);
             int k10 = minY + rand.nextInt(rangeY / 8);
             int j13 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreDiamond.variantMap, 7)).place(world, rand, j7, k10, j13);
+            (new WorldFeatureOre(BlockLogicOreDiamond.variantMap, 7)).place(world, rand, j7, k10, j13);
         }
 
         for(int j4 = 0; j4 < 1; j4++)
@@ -186,7 +186,7 @@ public class ChunkDecoratorOverworldHell
             int k7 = x + rand.nextInt(16);
             int l10 = minY + rand.nextInt(rangeY / 8) + rand.nextInt(rangeY / 8);
             int k13 = z + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreLapis.variantMap, 6)).place(world, rand, k7, l10, k13);
+            (new WorldFeatureOre(BlockLogicOreLapis.variantMap, 6)).place(world, rand, k7, l10, k13);
         }
 
         double d = 0.5D;
@@ -204,10 +204,10 @@ public class ChunkDecoratorOverworldHell
             WorldFeature wf;
             if(rand.nextInt(10) == 0)
             {
-                wf = new WorldFeatureTreeFancy(hasLeaves ? Blocks.LEAVES_OAK.id : 0, Blocks.LOG_OAK.id);
+                wf = new WorldFeatureTreeFancy(hasLeaves ? Blocks.LEAVES_OAK.id() : 0, Blocks.LOG_OAK.id());
             } else
             {
-                wf = new WorldFeatureTree(hasLeaves ? Blocks.LEAVES_OAK.id : 0, Blocks.LOG_OAK.id, 4);
+                wf = new WorldFeatureTree(hasLeaves ? Blocks.LEAVES_OAK.id() : 0, Blocks.LOG_OAK.id(), 4);
             }
             wf.init(1.0D, 1.0D, 1.0D);
             wf.place(world, rand, l13, world.getHeightValue(l13, j14), j14);
@@ -219,7 +219,7 @@ public class ChunkDecoratorOverworldHell
             int i17 = x + rand.nextInt(16) + 8;
             int i20 = minY + rand.nextInt(rangeY);
             int l22 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureDeadBush(Blocks.DEADBUSH.id)).place(world, rand, i17, i20, l22);
+            (new WorldFeatureDeadBush(Blocks.DEADBUSH.id())).place(world, rand, i17, i20, l22);
         }
 
         for(int l18 = 0; l18 < 5; l18++)
@@ -227,7 +227,7 @@ public class ChunkDecoratorOverworldHell
             int l21 = x + rand.nextInt(16) + 8;
             int k23 = minY + rand.nextInt(rand.nextInt(rangeY - 8) + 8);
             int l24 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id)).place(world, rand, l21, k23, l24);
+            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id())).place(world, rand, l21, k23, l24);
         }
 
         for(int i19 = 0; i19 < 20; i19++)
@@ -235,7 +235,7 @@ public class ChunkDecoratorOverworldHell
             int i22 = x + rand.nextInt(16) + 8;
             int l23 = minY + rand.nextInt(rand.nextInt(rand.nextInt(rangeY - rangeY / 8) + 8) + 8);
             int i25 = z + rand.nextInt(16) + 8;
-            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id)).place(world, rand, i22, l23, i25);
+            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id())).place(world, rand, i22, l23, i25);
         }
 
         if (world.getBlockId(x, minY + world.getWorldType().getOceanY() - 1, z) == world.getWorldType().getOceanBlockId())
@@ -243,7 +243,7 @@ public class ChunkDecoratorOverworldHell
             world.setBlockWithNotify(x, minY + world.getWorldType().getOceanY() - 1, z, world.getWorldType().getOceanBlockId());
         }
 
-        BlockSand.fallInstantly = false;
+        BlockLogicSand.fallInstantly = false;
 
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
index 59f9cb22b..b10498dcc 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
@@ -1,12 +1,12 @@
 package net.minecraft.core.world.generate.chunk.perlin.overworld.retro;
 
-import net.minecraft.core.block.BlockSand;
+import net.minecraft.core.block.BlockLogicOreCoal;
+import net.minecraft.core.block.BlockLogicOreDiamond;
+import net.minecraft.core.block.BlockLogicOreGold;
+import net.minecraft.core.block.BlockLogicOreIron;
+import net.minecraft.core.block.BlockLogicOreRedstone;
+import net.minecraft.core.block.BlockLogicSand;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockOreCoal;
-import net.minecraft.core.block.BlockOreDiamond;
-import net.minecraft.core.block.BlockOreGold;
-import net.minecraft.core.block.BlockOreIron;
-import net.minecraft.core.block.BlockOreRedstone;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
@@ -46,7 +46,7 @@ public class ChunkDecoratorOverworldRetro
         int maxY = world.getWorldType().getMaxY();
         int rangeY = (maxY + 1) - minY;
 
-        BlockSand.fallInstantly = true;
+        BlockLogicSand.fallInstantly = true;
         int k = chunkX * 16;
         int l = chunkZ * 16;
         Random rand = new Random(world.getRandomSeed());
@@ -58,7 +58,7 @@ public class ChunkDecoratorOverworldRetro
             int i4 = k + rand.nextInt(16) + 8;
             int j6 = minY + rand.nextInt(rangeY);
             int i11 = l + rand.nextInt(16) + 8;
-            (new WorldFeatureDungeon(Blocks.COBBLE_STONE.id, Blocks.COBBLE_STONE_MOSSY.id, null)).place(world, rand, i4, j6, i11);
+            (new WorldFeatureDungeon(Blocks.COBBLE_STONE.id(), Blocks.COBBLE_STONE_MOSSY.id(), null)).place(world, rand, i4, j6, i11);
         }
 
         for (int j1 = 0; j1 < 10; j1++)
@@ -74,7 +74,7 @@ public class ChunkDecoratorOverworldRetro
             int k4 = k + rand.nextInt(16);
             int l6 = minY + rand.nextInt(rangeY);
             int k11 = l + rand.nextInt(16);
-            (new WorldFeatureOre(Blocks.DIRT.id, 32)).place(world, rand, k4, l6, k11);
+            (new WorldFeatureOre(Blocks.DIRT.id(), 32)).place(world, rand, k4, l6, k11);
         }
 
         for (int i2 = 0; i2 < 10; i2++)
@@ -82,7 +82,7 @@ public class ChunkDecoratorOverworldRetro
             int l4 = k + rand.nextInt(16);
             int i7 = minY + rand.nextInt(rangeY);
             int l11 = l + rand.nextInt(16);
-            (new WorldFeatureOre(Blocks.GRAVEL.id, 32)).place(world, rand, l4, i7, l11);
+            (new WorldFeatureOre(Blocks.GRAVEL.id(), 32)).place(world, rand, l4, i7, l11);
         }
 
         for (int j2 = 0; j2 < 20; j2++)
@@ -90,7 +90,7 @@ public class ChunkDecoratorOverworldRetro
             int i5 = k + rand.nextInt(16);
             int j7 = minY + rand.nextInt(rangeY);
             int i12 = l + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreCoal.variantMap, 16)).place(world, rand, i5, j7, i12);
+            (new WorldFeatureOre(BlockLogicOreCoal.variantMap, 16)).place(world, rand, i5, j7, i12);
         }
 
         for (int k2 = 0; k2 < 20; k2++)
@@ -98,7 +98,7 @@ public class ChunkDecoratorOverworldRetro
             int j5 = k + rand.nextInt(16);
             int k7 = minY + rand.nextInt(rangeY / 2);
             int j12 = l + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreIron.variantMap, 8)).place(world, rand, j5, k7, j12);
+            (new WorldFeatureOre(BlockLogicOreIron.variantMap, 8)).place(world, rand, j5, k7, j12);
         }
 
         for (int i3 = 0; i3 < 2; i3++)
@@ -106,7 +106,7 @@ public class ChunkDecoratorOverworldRetro
             int k5 = k + rand.nextInt(16);
             int l7 = minY + rand.nextInt(rangeY / 4);
             int k12 = l + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreGold.variantMap, 8)).place(world, rand, k5, l7, k12);
+            (new WorldFeatureOre(BlockLogicOreGold.variantMap, 8)).place(world, rand, k5, l7, k12);
         }
 
         for (int j3 = 0; j3 < 8; j3++)
@@ -114,7 +114,7 @@ public class ChunkDecoratorOverworldRetro
             int l5 = k + rand.nextInt(16);
             int i8 = minY + rand.nextInt(rangeY / 8);
             int l12 = l + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreRedstone.variantMap, 7)).place(world, rand, l5, i8, l12);
+            (new WorldFeatureOre(BlockLogicOreRedstone.variantMap, 7)).place(world, rand, l5, i8, l12);
         }
 
         for (int k3 = 0; k3 < 1; k3++)
@@ -122,7 +122,7 @@ public class ChunkDecoratorOverworldRetro
             int i6 = k + rand.nextInt(16);
             int j8 = minY + rand.nextInt(rangeY / 8);
             int i13 = l + rand.nextInt(16);
-            (new WorldFeatureOre(BlockOreDiamond.variantMap, 7)).place(world, rand, i6, j8, i13);
+            (new WorldFeatureOre(BlockLogicOreDiamond.variantMap, 7)).place(world, rand, i6, j8, i13);
         }
 
         double d = 0.5D;
@@ -135,17 +135,17 @@ public class ChunkDecoratorOverworldRetro
         {
             l3++;
         }
-        Object obj = new WorldFeatureTree(Blocks.LEAVES_OAK_RETRO.id, Blocks.LOG_OAK.id, 4);
+        WorldFeature tree = new WorldFeatureTree(Blocks.LEAVES_OAK_RETRO.id(), Blocks.LOG_OAK.id(), 4);
         if (rand.nextInt(10) == 0)
         {
-            obj = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK_RETRO.id, Blocks.LOG_OAK.id);
+            tree = new WorldFeatureTreeFancy(Blocks.LEAVES_OAK_RETRO.id(), Blocks.LOG_OAK.id());
         }
         for (int k8 = 0; k8 < l3; k8++)
         {
             int j13 = k + rand.nextInt(16) + 8;
             int l15 = l + rand.nextInt(16) + 8;
-            ((WorldFeature)(obj)).init(1.0D, 1.0D, 1.0D);
-            ((WorldFeature)(obj)).place(world, rand, j13, world.getHeightValue(j13, l15), l15);
+            tree.init(1.0D, 1.0D, 1.0D);
+            tree.place(world, rand, j13, world.getHeightValue(j13, l15), l15);
         }
 
         for (int l8 = 0; l8 < 2; l8++)
@@ -153,7 +153,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, 64, false)).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)
@@ -161,21 +161,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, 64, false)).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, 64, false)).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, 64, false)).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++)
         {
@@ -198,7 +198,7 @@ public class ChunkDecoratorOverworldRetro
             int i15 = k + rand.nextInt(16) + 8;
             int k17 = minY + rand.nextInt(rand.nextInt(rangeY - 8) + 8);
             int i19 = l + rand.nextInt(16) + 8;
-            (new WorldFeatureLiquid(Blocks.FLUID_WATER_FLOWING.id)).place(world, rand, i15, k17, i19);
+            (new WorldFeatureLiquid(Blocks.FLUID_WATER_FLOWING.id())).place(world, rand, i15, k17, i19);
         }
 
         for (int k10 = 0; k10 < 20; k10++)
@@ -206,27 +206,27 @@ public class ChunkDecoratorOverworldRetro
             int j15 = k + rand.nextInt(16) + 8;
             int l17 = minY + rand.nextInt(rand.nextInt(rand.nextInt(rangeY / 2 - rangeY / 8) + 8) + 8);
             int j19 = l + rand.nextInt(16) + 8;
-            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id)).place(world, rand, j15, l17, j19);
+            (new WorldFeatureLiquid(Blocks.FLUID_LAVA_FLOWING.id())).place(world, rand, j15, l17, j19);
         }
 
-        for (int l10 = k + 8 + 0; l10 < k + 8 + 16; l10++)
+        for (int l10 = k + 8; l10 < k + 8 + 16; l10++)
         {
-            for (int k15 = l + 8 + 0; k15 < l + 8 + 16; k15++)
+            for (int k15 = l + 8; k15 < l + 8 + 16; k15++)
             {
                 int i18 = world.findTopSolidBlock(l10, k15);
                 if (snowCovered && i18 > minY && i18 <= maxY && world.getBlockId(l10, i18, k15) == 0 && world.getBlockMaterial(l10, i18 - 1, k15).blocksMotion() && world.getBlockMaterial(l10, i18 - 1, k15) != Material.ice)
                 {
-                    world.setBlockWithNotify(l10, i18, k15, Blocks.LAYER_SNOW.id);
+                    world.setBlockWithNotify(l10, i18, k15, Blocks.LAYER_SNOW.id());
                 }
                 if (snowCovered && world.getBlockMaterial(l10, world.getWorldType().getOceanY() - 1, k15) == Material.water)
                 {
-                    world.setBlockWithNotify(l10, world.getWorldType().getOceanY() - 1, k15, Blocks.ICE.id);
+                    world.setBlockWithNotify(l10, world.getWorldType().getOceanY() - 1, k15, Blocks.ICE.id());
                 }
             }
 
         }
 
-        BlockSand.fallInstantly = false;
+        BlockLogicSand.fallInstantly = false;
         world.scheduledUpdatesAreImmediate = false;
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblock.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblock.java
index b2994f9ea..8ff58e0fb 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblock.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblock.java
@@ -17,10 +17,10 @@ public class ChunkDecoratorSkyblock
     public void decorate(Chunk chunk) {
         // Starting island
         if (contains(chunk, -1, 1)) {
-            new WorldFeatureTree(Blocks.LEAVES_OAK.id, Blocks.LOG_OAK.id, 6).place(chunk.world, new Random(0), -1, 67, 1);
+            new WorldFeatureTree(Blocks.LEAVES_OAK.id(), Blocks.LOG_OAK.id(), 6).place(chunk.world, new Random(0), -1, 67, 1);
         }
         if (contains(chunk, 4, -3)) {
-            chunk.setBlockIDWithMetadata(4 & (Chunk.CHUNK_SIZE_X - 1), 67, -3 & (Chunk.CHUNK_SIZE_Z - 1), Blocks.CHEST_PLANKS_OAK.id, 3);
+            chunk.setBlockIDWithMetadata(4 & (Chunk.CHUNK_SIZE_X - 1), 67, -3 & (Chunk.CHUNK_SIZE_Z - 1), Blocks.CHEST_PLANKS_OAK.id(), 3);
             TileEntity tileEntity = chunk.getBlockEntity(4 & (Chunk.CHUNK_SIZE_X - 1), 67, -3 & (Chunk.CHUNK_SIZE_Z - 1));
             if (tileEntity instanceof TileEntityChest) {
                 TileEntityChest chestEntity = (TileEntityChest) tileEntity;
@@ -31,7 +31,7 @@ public class ChunkDecoratorSkyblock
 
         // Desert island
         if (contains(chunk, -67, 0)) {
-            chunk.setBlockIDWithMetadata(-67 & (Chunk.CHUNK_SIZE_X - 1), 67, 0 & (Chunk.CHUNK_SIZE_Z - 1), Blocks.CHEST_PLANKS_OAK.id, 1);
+            chunk.setBlockIDWithMetadata(-67 & (Chunk.CHUNK_SIZE_X - 1), 67, 0 & (Chunk.CHUNK_SIZE_Z - 1), Blocks.CHEST_PLANKS_OAK.id(), 1);
             TileEntity tileEntity = chunk.getBlockEntity(-67 & (Chunk.CHUNK_SIZE_X - 1), 67, 0 & (Chunk.CHUNK_SIZE_Z - 1));
             if (tileEntity instanceof TileEntityChest) {
                 TileEntityChest chestEntity = (TileEntityChest) tileEntity;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblockNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblockNether.java
index 7d792f205..a457e4a81 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblockNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkDecoratorSkyblockNether.java
@@ -23,7 +23,7 @@ public class ChunkDecoratorSkyblockNether
 
         // Chest
         if (contains(chunk, 1, -1)) {
-            chunk.setBlockIDWithMetadata(1 & (Chunk.CHUNK_SIZE_X - 1), 66, -1 & (Chunk.CHUNK_SIZE_Z - 1), Blocks.CHEST_PLANKS_OAK.id, 3);
+            chunk.setBlockIDWithMetadata(1 & (Chunk.CHUNK_SIZE_X - 1), 66, -1 & (Chunk.CHUNK_SIZE_Z - 1), Blocks.CHEST_PLANKS_OAK.id(), 3);
             TileEntity tileEntity = chunk.getBlockEntity(1 & (Chunk.CHUNK_SIZE_X - 1), 66, -1 & (Chunk.CHUNK_SIZE_Z - 1));
             if (tileEntity != null) {
                 TileEntityChest tileEntityChest = (TileEntityChest) tileEntity;
@@ -34,8 +34,8 @@ public class ChunkDecoratorSkyblockNether
         }
 
         // Mushrooms
-        tryPlace(chunk, 1, 66, 0, Blocks.MUSHROOM_BROWN.id);
-        tryPlace(chunk, -1, 66, 1, Blocks.MUSHROOM_RED.id);
+        tryPlace(chunk, 1, 66, 0, Blocks.MUSHROOM_BROWN.id());
+        tryPlace(chunk, -1, 66, 1, Blocks.MUSHROOM_RED.id());
     }
 
     private boolean contains(Chunk chunk, int xBlock, int zBlock) {
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblock.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblock.java
index b5566f80a..553869805 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblock.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblock.java
@@ -20,36 +20,36 @@ public class ChunkGeneratorSkyblock
         // Starting island
         for (int x = -1; x <= 1; x++) {
             for (int z = -1; z <= 1; z++) {
-                tryPlace(chunk, result, x, 64, z, Blocks.DIRT.id);
-                tryPlace(chunk, result, x, 65, z, Blocks.DIRT.id);
-                tryPlace(chunk, result, x, 66, z, Blocks.GRASS.id);
+                tryPlace(chunk, result, x, 64, z, Blocks.DIRT.id());
+                tryPlace(chunk, result, x, 65, z, Blocks.DIRT.id());
+                tryPlace(chunk, result, x, 66, z, Blocks.GRASS.id());
             }
         }
         for (int x = -1; x <= 1; x++) {
             for (int z = -4; z <= -2; z++) {
-                tryPlace(chunk, result, x, 64, z, Blocks.DIRT.id);
-                tryPlace(chunk, result, x, 65, z, Blocks.DIRT.id);
-                tryPlace(chunk, result, x, 66, z, Blocks.GRASS.id);
+                tryPlace(chunk, result, x, 64, z, Blocks.DIRT.id());
+                tryPlace(chunk, result, x, 65, z, Blocks.DIRT.id());
+                tryPlace(chunk, result, x, 66, z, Blocks.GRASS.id());
             }
         }
         for (int x = 2; x <= 4; x++) {
             for (int z = -4; z <= -2; z++) {
-                tryPlace(chunk, result, x, 64, z, Blocks.DIRT.id);
-                tryPlace(chunk, result, x, 65, z, Blocks.DIRT.id);
-                tryPlace(chunk, result, x, 66, z, Blocks.GRASS.id);
+                tryPlace(chunk, result, x, 64, z, Blocks.DIRT.id());
+                tryPlace(chunk, result, x, 65, z, Blocks.DIRT.id());
+                tryPlace(chunk, result, x, 66, z, Blocks.GRASS.id());
             }
         }
-        tryPlace(chunk, result, 0, 64, -3, Blocks.BEDROCK.id);
+        tryPlace(chunk, result, 0, 64, -3, Blocks.BEDROCK.id());
 
         // Desert island
         for (int x = -68; x <= -66; x++) {
             for (int z = -1; z <= 1; z++) {
-                tryPlace(chunk, result, x, 64, z, Blocks.SAND.id);
-                tryPlace(chunk, result, x, 65, z, Blocks.SAND.id);
-                tryPlace(chunk, result, x, 66, z, Blocks.SAND.id);
+                tryPlace(chunk, result, x, 64, z, Blocks.SAND.id());
+                tryPlace(chunk, result, x, 65, z, Blocks.SAND.id());
+                tryPlace(chunk, result, x, 66, z, Blocks.SAND.id());
             }
         }
-        tryPlace(chunk, result, -68, 67, 1, Blocks.CACTUS.id);
+        tryPlace(chunk, result, -68, 67, 1, Blocks.CACTUS.id());
 
         return result;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblockNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblockNether.java
index 348b4ef84..3fe19c1dd 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblockNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/skyblock/ChunkGeneratorSkyblockNether.java
@@ -20,25 +20,25 @@ public class ChunkGeneratorSkyblockNether
         // Main island
         for (int x = -1; x <= 1; x++) {
             for (int z = -1; z <= 1; z++) {
-                tryPlace(chunk, result, x, 63, z, Blocks.GLOWSTONE.id);
-                tryPlace(chunk, result, x, 64, z, Blocks.GLOWSTONE.id);
-                tryPlace(chunk, result, x, 65, z, Blocks.GLOWSTONE.id);
+                tryPlace(chunk, result, x, 63, z, Blocks.GLOWSTONE.id());
+                tryPlace(chunk, result, x, 64, z, Blocks.GLOWSTONE.id());
+                tryPlace(chunk, result, x, 65, z, Blocks.GLOWSTONE.id());
             }
         }
         // Portal
         for (int z = -1; z <= 2; z++) {
             if (z == -1 || z == 2) {
-                tryPlace(chunk, result, 2, 65, z, Blocks.OBSIDIAN.id);
-                tryPlace(chunk, result, 2, 66, z, Blocks.OBSIDIAN.id);
-                tryPlace(chunk, result, 2, 67, z, Blocks.OBSIDIAN.id);
-                tryPlace(chunk, result, 2, 68, z, Blocks.OBSIDIAN.id);
-                tryPlace(chunk, result, 2, 69, z, Blocks.OBSIDIAN.id);
+                tryPlace(chunk, result, 2, 65, z, Blocks.OBSIDIAN.id());
+                tryPlace(chunk, result, 2, 66, z, Blocks.OBSIDIAN.id());
+                tryPlace(chunk, result, 2, 67, z, Blocks.OBSIDIAN.id());
+                tryPlace(chunk, result, 2, 68, z, Blocks.OBSIDIAN.id());
+                tryPlace(chunk, result, 2, 69, z, Blocks.OBSIDIAN.id());
             } else {
-                tryPlace(chunk, result, 2, 65, z, Blocks.OBSIDIAN.id);
-                tryPlace(chunk, result, 2, 66, z, Blocks.PORTAL_NETHER.id);
-                tryPlace(chunk, result, 2, 67, z, Blocks.PORTAL_NETHER.id);
-                tryPlace(chunk, result, 2, 68, z, Blocks.PORTAL_NETHER.id);
-                tryPlace(chunk, result, 2, 69, z, Blocks.OBSIDIAN.id);
+                tryPlace(chunk, result, 2, 65, z, Blocks.OBSIDIAN.id());
+                tryPlace(chunk, result, 2, 66, z, Blocks.PORTAL_NETHER.id());
+                tryPlace(chunk, result, 2, 67, z, Blocks.PORTAL_NETHER.id());
+                tryPlace(chunk, result, 2, 68, z, Blocks.PORTAL_NETHER.id());
+                tryPlace(chunk, result, 2, 69, z, Blocks.OBSIDIAN.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureAlgae.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureAlgae.java
index 5f9af8da6..678b53444 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureAlgae.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureAlgae.java
@@ -17,10 +17,10 @@ public class WorldFeatureAlgae extends WorldFeature
             int i1 = (x + random.nextInt(8)) - random.nextInt(8);
             int j1 = (y);
             int k1 = (z + random.nextInt(8)) - random.nextInt(8);
-            if((world.getBlockId(i1, j1, k1) == Blocks.FLUID_WATER_STILL.id) &&
+            if((world.getBlockId(i1, j1, k1) == Blocks.FLUID_WATER_STILL.id()) &&
                     world.getBlockMaterial(i1, j1+1, k1) == Material.air)
             {
-                world.setBlock(i1, j1+1, k1, Blocks.ALGAE.id);
+                world.setBlock(i1, j1+1, k1, Blocks.ALGAE.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureCactus.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureCactus.java
index 12d59dc55..bf456c757 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureCactus.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureCactus.java
@@ -29,7 +29,7 @@ public class WorldFeatureCactus extends WorldFeature
             {
                 if(Blocks.CACTUS.canBlockStay(world, i1, j1 + i2, k1))
                 {
-                    world.setBlock(i1, j1 + i2, k1, Blocks.CACTUS.id);
+                    world.setBlock(i1, j1 + i2, k1, Blocks.CACTUS.id());
                 }
             }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureClay.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureClay.java
index 69fdb2ff3..16486fda5 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureClay.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureClay.java
@@ -18,11 +18,11 @@ public class WorldFeatureClay extends WorldFeature
 	}
 
     @MethodParametersAnnotation(names = {"numberOfBlocks", "block"})
-    public WorldFeatureClay(int numberOfBlocks, Block block)
+    public WorldFeatureClay(int numberOfBlocks, Block<?> block)
     {
-        clayBlockId = Blocks.BLOCK_CLAY.id;
+        clayBlockId = Blocks.BLOCK_CLAY.id();
         this.numberOfBlocks = numberOfBlocks;
-        this.generateInId = block.id;
+        this.generateInId = block.id();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDeadBush.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDeadBush.java
index 06485a40d..dde55c3c2 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDeadBush.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDeadBush.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.generate.feature;
 
-import net.minecraft.core.block.BlockLeavesBase;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -19,7 +19,7 @@ public class WorldFeatureDeadBush extends WorldFeature
     @Override
 	public boolean place(World world, Random random, int x, int y, int z)
     {
-        for(int l; ((l = world.getBlockId(x, y, z)) == 0 || Blocks.blocksList[l] instanceof BlockLeavesBase) && y > 0; y--) { }
+        for(int l; ((l = world.getBlockId(x, y, z)) == 0 || Block.hasLogicClass(Blocks.blocksList[l], BlockLogicLeavesBase.class)) && y > 0; y--) { }
         for(int i1 = 0; i1 < 4; i1++)
         {
             int j1 = (x + random.nextInt(8)) - random.nextInt(8);
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDungeon.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDungeon.java
index 56f6880bd..9f665a455 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDungeon.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureDungeon.java
@@ -2,7 +2,7 @@ package net.minecraft.core.world.generate.feature;
 
 import net.minecraft.core.WeightedRandomBag;
 import net.minecraft.core.WeightedRandomLootObject;
-import net.minecraft.core.block.BlockChest;
+import net.minecraft.core.block.BlockLogicChest;
 import net.minecraft.core.block.entity.TileEntityChest;
 import net.minecraft.core.block.entity.TileEntityMobSpawner;
 import net.minecraft.core.item.Item;
@@ -11,6 +11,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.material.Material;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -18,12 +19,12 @@ public class WorldFeatureDungeon extends WorldFeature
 {
 	public int blockIdWalls;
 	public int blockIdFloor;
-	public String mobOverride;
+	public @Nullable String mobOverride;
     public WeightedRandomBag<WeightedRandomLootObject> chestLoot;
     public WeightedRandomBag<String> spawnerMonsters;
 
     @MethodParametersAnnotation(names = {"blockIdWalls", "blockIdFloor", "mobOverrideDispatcherId"})
-    public WorldFeatureDungeon(int blockIdWalls, int blockIdFloor, String mobOverride)
+    public WorldFeatureDungeon(int blockIdWalls, int blockIdFloor, @Nullable String mobOverride)
     {
     	this.blockIdWalls = blockIdWalls;
     	this.blockIdFloor = blockIdFloor;
@@ -154,8 +155,8 @@ public class WorldFeatureDungeon extends WorldFeature
                 {
                     continue;
                 }
-                world.setBlockWithNotify(k3, l3, i4, Blocks.CHEST_PLANKS_OAK.id);
-                BlockChest.setDefaultDirection(world, k3, l3, i4);
+                world.setBlockWithNotify(k3, l3, i4, Blocks.CHEST_PLANKS_OAK.id());
+                BlockLogicChest.setDefaultDirection(world, k3, l3, i4);
                 TileEntityChest tileentitychest = (TileEntityChest)world.getBlockEntity(k3, l3, i4);
                 int k4 = 0;
                 do
@@ -175,7 +176,7 @@ public class WorldFeatureDungeon extends WorldFeature
 
         }
 
-        world.setBlockWithNotify(x, y, z, Blocks.MOBSPAWNER.id);
+        world.setBlockWithNotify(x, y, z, Blocks.MOBSPAWNER.id());
         TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner)world.getBlockEntity(x, y, z);
         tileentitymobspawner.setMobId(pickMobSpawner(random));
         return true;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFire.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFire.java
index eb05c08d8..f2506450d 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFire.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFire.java
@@ -20,9 +20,9 @@ public class WorldFeatureFire extends WorldFeature
             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) && world.getBlockId(i1, j1 - 1, k1) == Blocks.COBBLE_NETHERRACK.id)
+            if(world.isAirBlock(i1, j1, k1) && world.getBlockId(i1, j1 - 1, k1) == Blocks.COBBLE_NETHERRACK.id())
             {
-                world.setBlockWithNotify(i1, j1, k1, Blocks.FIRE.id);
+                world.setBlockWithNotify(i1, j1, k1, Blocks.FIRE.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java
index 438e8196f..1fec14e6e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureFlowers.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.generate.feature;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFlowerStackable;
+import net.minecraft.core.block.BlockLogicFlowerStackable;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -32,7 +32,7 @@ public class WorldFeatureFlowers extends WorldFeature
             if(world.isAirBlock(i1, j1, k1) && Blocks.blocksList[plantBlockId].canBlockStay(world, i1, j1, k1))
             {
                 final int metadata;
-                if (Blocks.getBlock(plantBlockId) instanceof BlockFlowerStackable) {
+                if (Block.hasLogicClass(Blocks.getBlock(plantBlockId), BlockLogicFlowerStackable.class)) {
                     final int stackSize;
                     if (varyStackSize) {
                         stackSize = getStackSize(random);
@@ -40,7 +40,7 @@ public class WorldFeatureFlowers extends WorldFeature
                         stackSize = 0;
                     }
 
-                    metadata = BlockFlowerStackable.setStackCount(0, stackSize);
+                    metadata = BlockLogicFlowerStackable.setStackCount(0, stackSize);
                 } else {
                     metadata = 0;
                 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneA.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneA.java
index 559d5976f..12160f7f5 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneA.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneA.java
@@ -19,11 +19,11 @@ public class WorldFeatureGlowstoneA extends WorldFeature
         {
             return false;
         }
-        if(world.getBlockId(x, y + 1, z) != Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x, y + 1, z) != Blocks.COBBLE_NETHERRACK.id())
         {
             return false;
         }
-        world.setBlockWithNotify(x, y, z, Blocks.GLOWSTONE.id);
+        world.setBlockWithNotify(x, y, z, Blocks.GLOWSTONE.id());
         for(int l = 0; l < 1500; l++)
         {
             int i1 = (x + random.nextInt(8)) - random.nextInt(8);
@@ -61,7 +61,7 @@ public class WorldFeatureGlowstoneA extends WorldFeature
                 {
                     j2 = world.getBlockId(i1, j1, k1 + 1);
                 }
-                if(j2 == Blocks.GLOWSTONE.id)
+                if(j2 == Blocks.GLOWSTONE.id())
                 {
                     l1++;
                 }
@@ -69,7 +69,7 @@ public class WorldFeatureGlowstoneA extends WorldFeature
 
             if(l1 == 1)
             {
-                world.setBlockWithNotify(i1, j1, k1, Blocks.GLOWSTONE.id);
+                world.setBlockWithNotify(i1, j1, k1, Blocks.GLOWSTONE.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneB.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneB.java
index 17420a09f..9439efc5c 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneB.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGlowstoneB.java
@@ -19,11 +19,11 @@ public class WorldFeatureGlowstoneB extends WorldFeature
         {
             return false;
         }
-        if(world.getBlockId(x, y + 1, z) != Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x, y + 1, z) != Blocks.COBBLE_NETHERRACK.id())
         {
             return false;
         }
-        world.setBlockWithNotify(x, y, z, Blocks.GLOWSTONE.id);
+        world.setBlockWithNotify(x, y, z, Blocks.GLOWSTONE.id());
         for(int l = 0; l < 1500; l++)
         {
             int i1 = (x + random.nextInt(8)) - random.nextInt(8);
@@ -61,7 +61,7 @@ public class WorldFeatureGlowstoneB extends WorldFeature
                 {
                     j2 = world.getBlockId(i1, j1, k1 + 1);
                 }
-                if(j2 == Blocks.GLOWSTONE.id)
+                if(j2 == Blocks.GLOWSTONE.id())
                 {
                     l1++;
                 }
@@ -69,7 +69,7 @@ public class WorldFeatureGlowstoneB extends WorldFeature
 
             if(l1 == 1)
             {
-                world.setBlockWithNotify(i1, j1, k1, Blocks.GLOWSTONE.id);
+                world.setBlockWithNotify(i1, j1, k1, Blocks.GLOWSTONE.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGrassPatch.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGrassPatch.java
index 5b85c4b63..4ae08760a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGrassPatch.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureGrassPatch.java
@@ -58,7 +58,7 @@ public class WorldFeatureGrassPatch extends WorldFeature
                         double d14 = (((double)i3 + 0.5D) - d8) / (d10 / 2D);
                         if(d12 * d12 + d13 * d13 + d14 * d14 < 1.0D)
                         {
-                            if(world.getBlockId(k2, l2, i3) == Blocks.DIRT.id || world.getBlockId(k2, l2, i3) == Blocks.GRASS.id)
+                            if(world.getBlockId(k2, l2, i3) == Blocks.DIRT.id() || world.getBlockId(k2, l2, i3) == Blocks.GRASS.id())
                                 world.setBlockAndMetadata(k2, l2, i3, blockToPlace, 0);
                         }
                     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java
index 7d08f4f10..7fedd3a98 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLabyrinth.java
@@ -2,8 +2,8 @@ package net.minecraft.core.world.generate.feature;
 
 import net.minecraft.core.WeightedRandomBag;
 import net.minecraft.core.WeightedRandomLootObject;
-import net.minecraft.core.block.BlockChest;
-import net.minecraft.core.block.BlockRotatable;
+import net.minecraft.core.block.BlockLogicChest;
+import net.minecraft.core.block.BlockLogicRotatable;
 import net.minecraft.core.block.entity.TileEntityChest;
 import net.minecraft.core.block.entity.TileEntityDispenser;
 import net.minecraft.core.block.entity.TileEntityMobSpawner;
@@ -30,11 +30,11 @@ public class WorldFeatureLabyrinth extends WorldFeature
     boolean treasureGenerated = false;
     boolean libraryGenerated = false;
     boolean isCold = false;
-    int wallBlockA = Blocks.COBBLE_STONE.id;
-    int wallBlockB = Blocks.COBBLE_STONE_MOSSY.id;
-    int brickBlockA = Blocks.BRICK_STONE_POLISHED.id;
-    int brickBlockB = Blocks.BRICK_STONE_POLISHED_MOSSY.id;
-    int slabBlock = Blocks.SLAB_STONE_POLISHED.id;
+    int wallBlockA = Blocks.COBBLE_STONE.id();
+    int wallBlockB = Blocks.COBBLE_STONE_MOSSY.id();
+    int brickBlockA = Blocks.BRICK_STONE_POLISHED.id();
+    int brickBlockB = Blocks.BRICK_STONE_POLISHED_MOSSY.id();
+    int slabBlock = Blocks.SLAB_STONE_POLISHED.id();
     public ItemStack treasureItem;
     public WeightedRandomBag<WeightedRandomLootObject> chestLoot;
     public WeightedRandomBag<WeightedRandomLootObject> dispenserLoot;
@@ -46,18 +46,18 @@ public class WorldFeatureLabyrinth extends WorldFeature
 
         if (biome == Biomes.OVERWORLD_DESERT || biome == Biomes.OVERWORLD_OUTBACK)
         {
-            wallBlockA = Blocks.SANDSTONE.id;
-            wallBlockB = Blocks.SANDSTONE.id;
-            brickBlockA = Blocks.BRICK_SANDSTONE.id;
-            brickBlockB = Blocks.BRICK_SANDSTONE.id;
-            slabBlock = Blocks.SLAB_SANDSTONE.id;
+            wallBlockA = Blocks.SANDSTONE.id();
+            wallBlockB = Blocks.SANDSTONE.id();
+            brickBlockA = Blocks.BRICK_SANDSTONE.id();
+            brickBlockB = Blocks.BRICK_SANDSTONE.id();
+            slabBlock = Blocks.SLAB_SANDSTONE.id();
         }
         if (biome == Biomes.OVERWORLD_TAIGA || biome == Biomes.OVERWORLD_TUNDRA || biome == Biomes.OVERWORLD_GLACIER)
         {
-            wallBlockA = Blocks.PERMAFROST.id;
-            wallBlockB = Blocks.COBBLE_PERMAFROST.id;
-            brickBlockA = Blocks.BRICK_PERMAFROST.id;
-            brickBlockB = Blocks.BRICK_PERMAFROST.id;
+            wallBlockA = Blocks.PERMAFROST.id();
+            wallBlockB = Blocks.COBBLE_PERMAFROST.id();
+            brickBlockA = Blocks.BRICK_PERMAFROST.id();
+            brickBlockB = Blocks.BRICK_PERMAFROST.id();
             isCold = true;
         }
 
@@ -142,10 +142,10 @@ public class WorldFeatureLabyrinth extends WorldFeature
                         //generate traps
                         if (!generateTrapOnWall && (xWallCheck || zWallCheck)) {
                             if ((x == blockZ || z == blockZ) && y == blockY) {
-                                world.setBlockWithNotify(x, y, z, Blocks.MOTION_SENSOR_IDLE.id);
-                                BlockRotatable.setDefaultDirection(world, x, y, z);
-                                world.setBlockWithNotify(x, y - 1, z, Blocks.DISPENSER_COBBLE_STONE.id);
-                                BlockRotatable.setDefaultDirection(world, x, y - 1, z);
+                                world.setBlockWithNotify(x, y, z, Blocks.MOTION_SENSOR_IDLE.id());
+                                BlockLogicRotatable.setDefaultDirection(world, x, y, z);
+                                world.setBlockWithNotify(x, y - 1, z, Blocks.DISPENSER_COBBLE_STONE.id());
+                                BlockLogicRotatable.setDefaultDirection(world, x, y - 1, z);
                                 TileEntityDispenser tileEntityDispenser = (TileEntityDispenser) world.getBlockEntity(x, blockY - 1, z);
                                 int k4 = 0;
                                 while (k4 < 3) {
@@ -189,7 +189,7 @@ public class WorldFeatureLabyrinth extends WorldFeature
                         if (yWallCheck) {
                             world.setBlockWithNotify(x, y, z, wallBlockB);
                             if(dungeonSize >= 10)
-                                world.setBlockWithNotify(x, y+1, z, Blocks.SPIKES.id);
+                                world.setBlockWithNotify(x, y+1, z, Blocks.SPIKES.id());
                         }
                         else if (x != blockX && z != blockZ && random.nextInt(20) == 0 && world.getBlockId(x, y + 1, z) != slabBlock)
                         {
@@ -215,9 +215,9 @@ public class WorldFeatureLabyrinth extends WorldFeature
     private boolean canReplace(World world, int x, int y, int z){
         if(y <= 11)
             return false;
-        if(world.getBlockId(x, y, z) == (brickBlockA) || world.getBlockId(x, y, z) == Blocks.PLANKS_OAK.id || world.getBlockId(x, y, z) == Blocks.COBWEB.id || world.getBlockId(x, y, z) == Blocks.BOOKSHELF_PLANKS_OAK.id || world.getBlockId(x, y, z) == Blocks.MOBSPAWNER.id || world.getBlockId(x, y, z) == brickBlockB )
+        if(world.getBlockId(x, y, z) == (brickBlockA) || world.getBlockId(x, y, z) == Blocks.PLANKS_OAK.id() || world.getBlockId(x, y, z) == Blocks.COBWEB.id() || world.getBlockId(x, y, z) == Blocks.BOOKSHELF_PLANKS_OAK.id() || world.getBlockId(x, y, z) == Blocks.MOBSPAWNER.id() || world.getBlockId(x, y, z) == brickBlockB )
             return false;
-        if(world.getBlockId(x, y, z) == Blocks.MOTION_SENSOR_IDLE.id || world.getBlockId(x, y, z) == Blocks.DISPENSER_COBBLE_STONE.id || world.getBlockId(x, y, z) == Blocks.MOTION_SENSOR_ACTIVE.id) {
+        if(world.getBlockId(x, y, z) == Blocks.MOTION_SENSOR_IDLE.id() || world.getBlockId(x, y, z) == Blocks.DISPENSER_COBBLE_STONE.id() || world.getBlockId(x, y, z) == Blocks.MOTION_SENSOR_ACTIVE.id()) {
             world.removeBlockTileEntity(x, y, z);
             world.setBlockWithNotify(x, y, z, 0);
             return true;
@@ -303,7 +303,7 @@ public class WorldFeatureLabyrinth extends WorldFeature
                             else world.setBlockWithNotify(x, y, z, 0);
                         }
                         if(y == blockY + (height - 1) && !zWallCheck && !xWallCheck && random.nextInt(20)==0)
-                            world.setBlockWithNotify(x, y, z, Blocks.COBWEB.id);
+                            world.setBlockWithNotify(x, y, z, Blocks.COBWEB.id());
                     }
                 }
             }
@@ -373,8 +373,8 @@ public class WorldFeatureLabyrinth extends WorldFeature
         int chestX = blockX + random.nextInt(size-1) - (size-1);
         int chestZ = blockZ + random.nextInt(size-1) - (size-1);
         if(canReplace(world, chestX, blockY-2, chestZ)) {
-            world.setBlockWithNotify(chestX, blockY - 1, chestZ, Blocks.CHEST_PLANKS_OAK.id);
-            BlockChest.setDefaultDirection(world, chestX, blockY - 1, chestZ);
+            world.setBlockWithNotify(chestX, blockY - 1, chestZ, Blocks.CHEST_PLANKS_OAK.id());
+            BlockLogicChest.setDefaultDirection(world, chestX, blockY - 1, chestZ);
             TileEntityChest tileentitychest = (TileEntityChest) world.getBlockEntity(chestX, blockY - 1, chestZ);
             int k4 = 0;
             while (k4 < 10) {
@@ -387,7 +387,7 @@ public class WorldFeatureLabyrinth extends WorldFeature
         }
         if (doSpawner)
         {
-            world.setBlockWithNotify(blockX, blockY-1, blockZ, Blocks.MOBSPAWNER.id);
+            world.setBlockWithNotify(blockX, blockY-1, blockZ, Blocks.MOBSPAWNER.id());
             TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner)world.getBlockEntity(blockX, blockY-1, blockZ);
             if(tileentitymobspawner != null)
                 tileentitymobspawner.setMobId(pickMobSpawner(random));
@@ -420,7 +420,7 @@ public class WorldFeatureLabyrinth extends WorldFeature
                         }
                         else if (yWallCheck) {
                             if((x > blockX-2 && x < blockX+2) || (z > blockZ-2 && z < blockZ+2))
-                                world.setBlockWithNotify(x, y, z, Blocks.PLANKS_OAK.id);
+                                world.setBlockWithNotify(x, y, z, Blocks.PLANKS_OAK.id());
                             else if (random.nextInt(5) == 0)
                                 world.setBlockWithNotify(x, y, z, wallBlockB);
                             else
@@ -440,12 +440,12 @@ public class WorldFeatureLabyrinth extends WorldFeature
                                     && (z <= blockZ - 1 || z >= blockZ + 1)
                                     && y < blockY + 2) {
                                 if(xRoom % 2 == 0)
-                                    world.setBlockWithNotify(x, y, z, Blocks.BOOKSHELF_PLANKS_OAK.id);
+                                    world.setBlockWithNotify(x, y, z, Blocks.BOOKSHELF_PLANKS_OAK.id());
                                 else
                                     if (random.nextInt(5) == 0)
-                                        world.setBlockWithNotify(x, y, z, Blocks.LOG_OAK_MOSSY.id);
+                                        world.setBlockWithNotify(x, y, z, Blocks.LOG_OAK_MOSSY.id());
                                     else
-                                        world.setBlockWithNotify(x, y, z, Blocks.LOG_OAK.id);
+                                        world.setBlockWithNotify(x, y, z, Blocks.LOG_OAK.id());
                             }
                             else
                                 world.setBlockWithNotify(x, y, z, 0);
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLake.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLake.java
index 746ed8185..85462cd05 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLake.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLake.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate.feature;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.block.material.Material;
@@ -77,7 +76,7 @@ public class WorldFeatureLake extends WorldFeature
                     {
                         return false;
                     }
-                    if (world.getBlockId(x + dx, y + dy, z + dz) == Blocks.ICE.id)
+                    if (world.getBlockId(x + dx, y + dy, z + dz) == Blocks.ICE.id())
                     {
                     	return false;
                     }
@@ -93,7 +92,7 @@ public class WorldFeatureLake extends WorldFeature
             {
                 for(int dy = 0; dy < 8; dy++)
                 {
-                    if(shouldPlaceLiquid[(dx * 16 + dz) * 8 + dy] && world.getBlockId(x + dx, y + dy, z + dz) != Blocks.BEDROCK.id)
+                    if(shouldPlaceLiquid[(dx * 16 + dz) * 8 + dy] && world.getBlockId(x + dx, y + dy, z + dz) != Blocks.BEDROCK.id())
                     {
                         world.setBlockWithNotify(x + dx, y + dy, z + dz, dy < 4 ? liquidId : 0);
                     }
@@ -109,9 +108,9 @@ public class WorldFeatureLake extends WorldFeature
             {
                 for(int dy = 4; dy < 8; dy++)
                 {
-                    if(shouldPlaceLiquid[(dx * 16 + dz) * 8 + dy] && world.getBlockId(x + dx, y + dy - 1, z + dz) != Blocks.BEDROCK.id && world.getBlockId(x + dx, (y + dy) - 1, z + dz) == Blocks.DIRT.id && world.getSavedLightValue(LightLayer.Sky, x + dx, y + dy, z + dz) > 0)
+                    if(shouldPlaceLiquid[(dx * 16 + dz) * 8 + dy] && world.getBlockId(x + dx, y + dy - 1, z + dz) != Blocks.BEDROCK.id() && world.getBlockId(x + dx, (y + dy) - 1, z + dz) == Blocks.DIRT.id() && world.getSavedLightValue(LightLayer.Sky, x + dx, y + dy, z + dz) > 0)
                     {
-                        world.setBlock(x + dx, (y + dy) - 1, z + dz, Blocks.GRASS.id);
+                        world.setBlock(x + dx, (y + dy) - 1, z + dz, Blocks.GRASS.id());
                     }
                 }
 
@@ -119,7 +118,7 @@ public class WorldFeatureLake extends WorldFeature
 
         }
 
-        if(Blocks.blocksList[liquidId].blockMaterial == Material.lava)
+        if(Blocks.blocksList[liquidId].getMaterial() == Material.lava)
         {
             for(int dx = 0; dx < 16; dx++)
             {
@@ -128,7 +127,7 @@ public class WorldFeatureLake extends WorldFeature
                     for(int dy = 0; dy < 8; dy++)
                     {
                         boolean flag1 = !shouldPlaceLiquid[(dx * 16 + dz) * 8 + dy] && (dx < 15 && shouldPlaceLiquid[((dx + 1) * 16 + dz) * 8 + dy] || dx > 0 && shouldPlaceLiquid[((dx - 1) * 16 + dz) * 8 + dy] || dz < 15 && shouldPlaceLiquid[(dx * 16 + (dz + 1)) * 8 + dy] || dz > 0 && shouldPlaceLiquid[(dx * 16 + (dz - 1)) * 8 + dy] || dy < 7 && shouldPlaceLiquid[(dx * 16 + dz) * 8 + (dy + 1)] || dy > 0 && shouldPlaceLiquid[(dx * 16 + dz) * 8 + (dy - 1)]);
-                        if(flag1 && (dy < 4 || random.nextInt(2) != 0) && world.getBlockId(x + dx, y + dy, z + dz) != Blocks.BEDROCK.id && world.getBlockMaterial(x + dx, y + dy, z + dz).isSolid())
+                        if(flag1 && (dy < 4 || random.nextInt(2) != 0) && world.getBlockId(x + dx, y + dy, z + dz) != Blocks.BEDROCK.id() && world.getBlockMaterial(x + dx, y + dy, z + dz).isSolid())
                         {
                             world.setBlock(x + dx, y + dy, z + dz, world.getWorldType().getFillerBlockId());
                         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLiquid.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLiquid.java
index a19c45dfe..8dfb139ab 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLiquid.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureLiquid.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate.feature;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -17,32 +16,32 @@ public class WorldFeatureLiquid extends WorldFeature
     @Override
 	public boolean place(World world, Random random, int x, int y, int z)
     {
-        if(world.getBlockId(x, y + 1, z) != Blocks.STONE.id)
+        if(world.getBlockId(x, y + 1, z) != Blocks.STONE.id())
         {
             return false;
         }
-        if(world.getBlockId(x, y - 1, z) != Blocks.STONE.id)
+        if(world.getBlockId(x, y - 1, z) != Blocks.STONE.id())
         {
             return false;
         }
-        if(world.getBlockId(x, y, z) != 0 && world.getBlockId(x, y, z) != Blocks.STONE.id)
+        if(world.getBlockId(x, y, z) != 0 && world.getBlockId(x, y, z) != Blocks.STONE.id())
         {
             return false;
         }
         int l = 0;
-        if(world.getBlockId(x - 1, y, z) == Blocks.STONE.id)
+        if(world.getBlockId(x - 1, y, z) == Blocks.STONE.id())
         {
             l++;
         }
-        if(world.getBlockId(x + 1, y, z) == Blocks.STONE.id)
+        if(world.getBlockId(x + 1, y, z) == Blocks.STONE.id())
         {
             l++;
         }
-        if(world.getBlockId(x, y, z - 1) == Blocks.STONE.id)
+        if(world.getBlockId(x, y, z - 1) == Blocks.STONE.id())
         {
             l++;
         }
-        if(world.getBlockId(x, y, z + 1) == Blocks.STONE.id)
+        if(world.getBlockId(x, y, z + 1) == Blocks.STONE.id())
         {
             l++;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java
index dc8d1fe4f..685f6b906 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMeadow.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.world.generate.feature;
 
-import net.minecraft.core.block.BlockLeavesBase;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockFlowerStackable;
+import net.minecraft.core.block.BlockLogicFlowerStackable;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -19,7 +19,7 @@ public class WorldFeatureMeadow extends WorldFeature
     @Override
     public boolean place(World world, Random random, int x, int y, int z)
     {
-        for(int l; ((l = world.getBlockId(x, y, z)) == 0 || Blocks.blocksList[l] instanceof BlockLeavesBase) && y > 0; y--) { }
+        for(int l; ((l = world.getBlockId(x, y, z)) == 0 || Block.hasLogicClass(Blocks.blocksList[l], BlockLogicLeavesBase.class)) && y > 0; y--) { }
         for(int i1 = 0; i1 < 128; i1++)
         {
             int j1 = (x + random.nextInt(8)) - random.nextInt(8);
@@ -32,7 +32,7 @@ public class WorldFeatureMeadow extends WorldFeature
 
             if(world.isAirBlock(j1, k1, l1) && Blocks.blocksList[flowerId].canBlockStay(world, j1, k1, l1))
             {
-                final int meta = BlockFlowerStackable.setStackCount(0, WorldFeatureFlowers.getStackSize(random));
+                final int meta = BlockLogicFlowerStackable.setStackCount(0, WorldFeatureFlowers.getStackSize(random));
                 world.setBlockAndMetadata(j1, k1, l1, flowerId, meta);
             }
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMudPatch.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMudPatch.java
index 3a26d960d..99a477556 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMudPatch.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureMudPatch.java
@@ -22,9 +22,9 @@ public class WorldFeatureMudPatch extends WorldFeature
                 float offset = (float) noise.getValue(chunkX / 30D, yPos / 30D, chunkZ / 30D) * 0.75f;
                 if(offset >= 0.125F) {
                     for(int i = 0; i < 5; i++) {
-                        if (world.getBlockId(chunkX, yPos - i, chunkZ) == Blocks.GRASS.id ||
-                                world.getBlockId(chunkX, yPos - i, chunkZ) == Blocks.DIRT.id) {
-                            world.setBlock(chunkX, yPos - i, chunkZ, Blocks.MUD.id);
+                        if (world.getBlockId(chunkX, yPos - i, chunkZ) == Blocks.GRASS.id() ||
+                                world.getBlockId(chunkX, yPos - i, chunkZ) == Blocks.DIRT.id()) {
+                            world.setBlock(chunkX, yPos - i, chunkZ, Blocks.MUD.id());
                         }
                     }
                 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherLava.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherLava.java
index cca2f0297..565b7a070 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherLava.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherLava.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate.feature;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -18,32 +17,32 @@ public class WorldFeatureNetherLava extends WorldFeature
     @Override
 	public boolean place(World world, Random random, int x, int y, int z)
     {
-        if(world.getBlockId(x, y + 1, z) != Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x, y + 1, z) != Blocks.COBBLE_NETHERRACK.id())
         {
             return false;
         }
-        if(world.getBlockId(x, y, z) != 0 && world.getBlockId(x, y, z) != Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x, y, z) != 0 && world.getBlockId(x, y, z) != Blocks.COBBLE_NETHERRACK.id())
         {
             return false;
         }
         int l = 0;
-        if(world.getBlockId(x - 1, y, z) == Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x - 1, y, z) == Blocks.COBBLE_NETHERRACK.id())
         {
             l++;
         }
-        if(world.getBlockId(x + 1, y, z) == Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x + 1, y, z) == Blocks.COBBLE_NETHERRACK.id())
         {
             l++;
         }
-        if(world.getBlockId(x, y, z - 1) == Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x, y, z - 1) == Blocks.COBBLE_NETHERRACK.id())
         {
             l++;
         }
-        if(world.getBlockId(x, y, z + 1) == Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x, y, z + 1) == Blocks.COBBLE_NETHERRACK.id())
         {
             l++;
         }
-        if(world.getBlockId(x, y - 1, z) == Blocks.COBBLE_NETHERRACK.id)
+        if(world.getBlockId(x, y - 1, z) == Blocks.COBBLE_NETHERRACK.id())
         {
             l++;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureOre.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureOre.java
index 72679bd27..da6e2bc97 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureOre.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureOre.java
@@ -81,9 +81,9 @@ public class WorldFeatureOre extends WorldFeature
                         	else
                         	{
                         		int id = world.getBlockId(x, y, z);
-                        		if (id == Blocks.STONE.id || id == Blocks.COBBLE_NETHERRACK.id ||
-                        				id == Blocks.BASALT.id || id == Blocks.LIMESTONE.id ||
-                        				id == Blocks.GRANITE.id)
+                        		if (id == Blocks.STONE.id() || id == Blocks.COBBLE_NETHERRACK.id() ||
+                        				id == Blocks.BASALT.id() || id == Blocks.LIMESTONE.id() ||
+                        				id == Blocks.GRANITE.id())
                         		{
                         			world.setBlock(x, y, z, minableBlockId);
                         		}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePermaice.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePermaice.java
index 2e7aa4355..4e2040184 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePermaice.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePermaice.java
@@ -13,11 +13,11 @@ public class WorldFeaturePermaice extends WorldFeature{
     private int generateInId;
 
     @MethodParametersAnnotation(names = {"numberOfBlocks", "block"})
-    public WorldFeaturePermaice(int numberOfBlocks, Block block)
+    public WorldFeaturePermaice(int numberOfBlocks, Block<?> block)
     {
-        blockId = Blocks.PERMAICE.id;
+        blockId = Blocks.PERMAICE.id();
         this.numberOfBlocks = numberOfBlocks;
-        this.generateInId = block.id;
+        this.generateInId = block.id();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumice.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumice.java
index 41c0c9f24..759a6fc2c 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumice.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumice.java
@@ -17,10 +17,10 @@ public class WorldFeaturePumice extends WorldFeature{
     }
 
     @MethodParametersAnnotation(names = {"numberOfBlocks", "block"})
-    public WorldFeaturePumice(int numberOfBlocks, Block block)
+    public WorldFeaturePumice(int numberOfBlocks, Block<?> block)
     {
         this.numberOfBlocks = numberOfBlocks;
-        this.generateInId = block.id;
+        this.generateInId = block.id();
     }
 
     @Override
@@ -72,7 +72,7 @@ public class WorldFeaturePumice extends WorldFeature{
                         {
                             if(world.getBlockId(k2, l2, i3) == generateInId)
                             {
-                                world.setBlock(k2, l2, i3, Blocks.PUMICE_WET.id);
+                                world.setBlock(k2, l2, i3, Blocks.PUMICE_WET.id());
                             }
                         }
                     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumpkin.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumpkin.java
index 10c97ea1d..d5fa52042 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumpkin.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeaturePumpkin.java
@@ -20,11 +20,11 @@ public class WorldFeaturePumpkin extends WorldFeature
             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) && world.getBlockId(i1, j1 - 1, k1) == Blocks.GRASS.id && Blocks.PUMPKIN.canPlaceBlockAt(world, i1, j1, k1))
+            if(world.isAirBlock(i1, j1, k1) && world.getBlockId(i1, j1 - 1, k1) == Blocks.GRASS.id() && Blocks.PUMPKIN.canPlaceBlockAt(world, i1, j1, k1))
             {
                 if(random.nextInt(50)== 0)
-                    world.setBlockAndMetadata(i1, j1, k1, Blocks.PUMPKIN_CARVED_IDLE.id, random.nextInt(4));
-                else    world.setBlockWithNotify(i1, j1, k1, Blocks.PUMPKIN.id);
+                    world.setBlockAndMetadata(i1, j1, k1, Blocks.PUMPKIN_CARVED_IDLE.id(), random.nextInt(4));
+                else    world.setBlockWithNotify(i1, j1, k1, Blocks.PUMPKIN.id());
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureRichScorchedDirt.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureRichScorchedDirt.java
index d4a65e992..40bb29f19 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureRichScorchedDirt.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureRichScorchedDirt.java
@@ -21,8 +21,8 @@ public class WorldFeatureRichScorchedDirt extends WorldFeature
             for(int y1 = y - 2; y1 <= y+2; y1++ ) {
                 for(int z1 = z - numberOfBlocks; z1 < z + numberOfBlocks; z1++ ) {
                     if(random.nextInt(8) == 0){
-                        if(world.getBlockId(x1, y1, z1) == Blocks.DIRT_SCORCHED.id)
-                            world.setBlock(x1, y1, z1, Blocks.DIRT_SCORCHED_RICH.id);
+                        if(world.getBlockId(x1, y1, z1) == Blocks.DIRT_SCORCHED.id())
+                            world.setBlock(x1, y1, z1, Blocks.DIRT_SCORCHED_RICH.id());
                     }
                 }
             }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSpinifexPatch.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSpinifexPatch.java
index 7cfb9f89d..c362c5857 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSpinifexPatch.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSpinifexPatch.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.generate.feature;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLeavesBase;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -12,7 +12,7 @@ public class WorldFeatureSpinifexPatch extends WorldFeature
     @Override
     public boolean place(World world, Random random, int x, int y, int z)
     {
-        for(int l; ((l = world.getBlockId(x, y, z)) == 0 || Blocks.blocksList[l] instanceof BlockLeavesBase) && y > 0; y--) { }
+        for(int l; ((l = world.getBlockId(x, y, z)) == 0 || Block.hasLogicClass(Blocks.blocksList[l], BlockLogicLeavesBase.class)) && y > 0; y--) { }
         for(int i1 = 0; i1 < 64; i1++)
         {
             int j1 = (x + random.nextInt(4)) - random.nextInt(4);
@@ -23,7 +23,7 @@ public class WorldFeatureSpinifexPatch extends WorldFeature
 
             if(world.isAirBlock(j1, k1, l1) && Blocks.SPINIFEX.canBlockStay(world, j1, k1, l1))
             {
-                world.setBlockAndMetadata(j1, k1, l1, Blocks.SPINIFEX.id, meta);
+                world.setBlockAndMetadata(j1, k1, l1, Blocks.SPINIFEX.id(), meta);
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSponge.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSponge.java
index a6bafd3ab..5ab9f583f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSponge.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSponge.java
@@ -11,20 +11,20 @@ public class WorldFeatureSponge extends WorldFeature
     @Override
 	public boolean place(World world, Random random, int x, int y, int z)
     {
-        if (world.getBlockId(x, y - 1, z) != Blocks.FLUID_WATER_STILL.id)
+        if (world.getBlockId(x, y - 1, z) != Blocks.FLUID_WATER_STILL.id())
             return false;
         for(int l = 0; l < 16; l++) {
             int i1 = (x + random.nextInt(8)) - random.nextInt(8);
             int k1 = (z + random.nextInt(8)) - random.nextInt(8);
 
-            for (; world.getBlockId(i1, y - 1, k1) == Blocks.FLUID_WATER_STILL.id; y--);
+            for (; world.getBlockId(i1, y - 1, k1) == Blocks.FLUID_WATER_STILL.id(); y--);
 
-            if(world.getBlockId(i1, y-1, k1) != Blocks.SAND.id && world.getBlockId(i1, y-1, k1) != Blocks.DIRT.id)
+            if(world.getBlockId(i1, y-1, k1) != Blocks.SAND.id() && world.getBlockId(i1, y-1, k1) != Blocks.DIRT.id())
                 continue;
             if(world.getBlockId(i1, y+1, k1) == 0)
                 continue;
 
-            world.setBlockRaw(i1, y, k1, Blocks.SPONGE_WET.id);
+            world.setBlockRaw(i1, y, k1, Blocks.SPONGE_WET.id());
         }
         return true;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCane.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCane.java
index b9bd3a0b2..26491dc96 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCane.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCane.java
@@ -30,7 +30,7 @@ public class WorldFeatureSugarCane extends WorldFeature
             {
                 if(Blocks.SUGARCANE.canBlockStay(world, i1, j1 + i2, k1))
                 {
-                    world.setBlock(i1, j1 + i2, k1, Blocks.SUGARCANE.id);
+                    world.setBlock(i1, j1 + i2, k1, Blocks.SUGARCANE.id());
                 }
             }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCaneTall.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCaneTall.java
index 50907c4ba..ad169f975 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCaneTall.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSugarCaneTall.java
@@ -30,7 +30,7 @@ public class WorldFeatureSugarCaneTall extends WorldFeature
             {
                 if(Blocks.SUGARCANE.canBlockStay(world, i1, j1 + i2, k1))
                 {
-                    world.setBlock(i1, j1 + i2, k1, Blocks.SUGARCANE.id);
+                    world.setBlock(i1, j1 + i2, k1, Blocks.SUGARCANE.id());
                 }
             }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureTallGrass.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureTallGrass.java
index f7295c918..1f4de8cf7 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureTallGrass.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureTallGrass.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.generate.feature;
 
-import net.minecraft.core.block.BlockLeavesBase;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicLeavesBase;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
@@ -20,7 +20,7 @@ public class WorldFeatureTallGrass extends WorldFeature
 	public boolean place(World world, Random random, int x, int y, int z)
     {
         int l;
-        while (((l = world.getBlockId(x, y, z)) == 0 || Blocks.blocksList[l] instanceof BlockLeavesBase) && y > 0) {
+        while (((l = world.getBlockId(x, y, z)) == 0 ||  Block.hasLogicClass(Blocks.blocksList[l], BlockLogicLeavesBase.class)) && y > 0) {
             y--;
         }
         for(int i1 = 0; i1 < 128; i1++)
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTree.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTree.java
index b232adf65..15a757d7c 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTree.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTree.java
@@ -58,7 +58,7 @@ public class WorldFeatureTree extends WorldFeature
             return false;
         }
         int idBelow = world.getBlockId(x, y - 1, z);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - treeHeight - 1)
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - treeHeight - 1)
         {
             return false;
         }
@@ -105,25 +105,25 @@ public class WorldFeatureTree extends WorldFeature
      * Replace grass blocks below the tree with dirt 
      */
     public static void onTreeGrown(World world, int x, int y, int z) {
-        Block dirt = WorldFeatureTree.getDirtForGrass(world.getBlockId(x, y - 1, z));
+        Block<?> dirt = WorldFeatureTree.getDirtForGrass(world.getBlockId(x, y - 1, z));
         if(dirt != null) {
-        	world.setBlockWithNotify(x, y - 1, z, dirt.id);
+        	world.setBlockWithNotify(x, y - 1, z, dirt.id());
         }
     }
     
-    public static Block getDirtForGrass(int id) {
+    public static Block<?> getDirtForGrass(int id) {
     	// TODO make this not hardcoded
-    	if(id == Blocks.GRASS.id || id == Blocks.GRASS_RETRO.id) {
+    	if(id == Blocks.GRASS.id() || id == Blocks.GRASS_RETRO.id()) {
     		return Blocks.DIRT;
     	}
-    	if(id == Blocks.GRASS_SCORCHED.id) {
+    	if(id == Blocks.GRASS_SCORCHED.id()) {
     		return Blocks.DIRT_SCORCHED;
     	}
     	return null;
     }
 
     public static boolean canLeavesReplace(World world, int x, int y, int z) {
-        Block b = world.getBlock(x, y, z);
+        Block<?> b = world.getBlock(x, y, z);
         return b == null || b.hasTag(BlockTags.PLACE_OVERWRITES);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCaatinga.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCaatinga.java
index c80615e7f..4dd261b95 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCaatinga.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCaatinga.java
@@ -119,7 +119,7 @@ public class WorldFeatureTreeCaatinga extends WorldFeature
             return false;
         }
         int idBelow = world.getBlockId(x, y - 1, z);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - l - 1)
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - l - 1)
         {
             return false;
         }
@@ -174,24 +174,24 @@ public class WorldFeatureTreeCaatinga extends WorldFeature
      * Replace grass blocks below the tree with dirt
      */
     public static void onTreeGrown(World world, int x, int y, int z) {
-        Block dirt = WorldFeatureTree.getDirtForGrass(world.getBlockId(x, y - 1, z));
+        Block<?> dirt = WorldFeatureTree.getDirtForGrass(world.getBlockId(x, y - 1, z));
         if(dirt != null) {
-            world.setBlockWithNotify(x, y - 1, z, dirt.id);
+            world.setBlockWithNotify(x, y - 1, z, dirt.id());
         }
     }
 
-    public static Block getDirtForGrass(int id) {
+    public static Block<?> getDirtForGrass(int id) {
         // TODO make this not hardcoded
-        if(id == Blocks.GRASS.id || id == Blocks.GRASS_RETRO.id) {
+        if(id == Blocks.GRASS.id() || id == Blocks.GRASS_RETRO.id()) {
             return Blocks.DIRT;
         }
-        if(id == Blocks.GRASS_SCORCHED.id) {
+        if(id == Blocks.GRASS_SCORCHED.id()) {
             return Blocks.DIRT_SCORCHED;
         }
         return null;
     }
 
-    static final byte dimensionLookup[] = {
+    static final byte[] dimensionLookup = {
             2, 0, 0, 1, 2, 1
     };
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCherry.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCherry.java
index 3f595d0d2..143898213 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCherry.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeCherry.java
@@ -16,14 +16,14 @@ public class WorldFeatureTreeCherry extends WorldFeatureTree {
 	@Override
 	public void placeLeaves(World world, int x, int y, int z, Random rand) {
 		if(rand.nextInt(5) == 0) {
-			world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id, 0);
+			world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id(), 0);
 		}else {
-			world.setBlockWithNotify(x, y, z, Blocks.LEAVES_CHERRY.id);
+			world.setBlockWithNotify(x, y, z, Blocks.LEAVES_CHERRY.id());
 		}
 	}
 	
 	@Override
 	public boolean isLeaf(int id) {
-		return id == Blocks.LEAVES_CHERRY_FLOWERING.id || id == Blocks.LEAVES_CHERRY.id;
+		return id == Blocks.LEAVES_CHERRY_FLOWERING.id() || id == Blocks.LEAVES_CHERRY.id();
 	}
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeEucalyptus.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeEucalyptus.java
index 2a3ed91ff..c70680c36 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeEucalyptus.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeEucalyptus.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
@@ -385,7 +385,7 @@ public class WorldFeatureTreeEucalyptus extends WorldFeature
                 origin[0], (origin[1] + height) - 1, origin[2]
         };
         int idBelow = world.getBlockId(origin[0], origin[1] - 1, origin[2]);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES))
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES))
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancy.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancy.java
index ff113af0e..29c4d4d84 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancy.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancy.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
@@ -367,7 +367,7 @@ public class WorldFeatureTreeFancy extends WorldFeature
         int[] bottomPos = { origin[0], origin[1], origin[2] };
         int[] topPos = { origin[0], (origin[1] + height) - 1, origin[2] };
         int blockIdUnderneath = world.getBlockId(origin[0], origin[1] - 1, origin[2]);
-        if(!Block.hasTag(blockIdUnderneath, BlockTags.GROWS_TREES))
+        if(!Blocks.hasTag(blockIdUnderneath, BlockTags.GROWS_TREES))
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancyRainforest.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancyRainforest.java
index d4399a950..45e01da9f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancyRainforest.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeFancyRainforest.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
@@ -412,7 +412,7 @@ public class WorldFeatureTreeFancyRainforest extends WorldFeature
             basePos[0], (basePos[1] + field_878_e) - 1, basePos[2]
         };
         int idBelow = worldObj.getBlockId(basePos[0], basePos[1] - 1, basePos[2]);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES))
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES))
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreePalm.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreePalm.java
index c19e11a01..4794f7030 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreePalm.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreePalm.java
@@ -1,10 +1,10 @@
 package net.minecraft.core.world.generate.feature.tree;
 
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLeavesBase;
+import net.minecraft.core.block.BlockLogicFlower;
+import net.minecraft.core.block.BlockLogicLeavesBase;
+import net.minecraft.core.block.BlockLogicLog;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockFlower;
-import net.minecraft.core.block.BlockLog;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.MathHelper;
@@ -24,8 +24,8 @@ public class WorldFeatureTreePalm extends WorldFeature {
 	protected World world;
 	protected Random random;
 	
-	protected Block log;
-	protected Block leaves;
+	protected Block<?> log;
+	protected Block<?> leaves;
 	protected boolean big;
 	
 	protected boolean update;
@@ -55,7 +55,7 @@ public class WorldFeatureTreePalm extends WorldFeature {
 	protected Set<Integer> intSet = new HashSet<>();
 	protected List<Integer> intList = new ArrayList<>();
 	@MethodParametersAnnotation(names = {"log", "leaves", "big", "update"})
-	public WorldFeatureTreePalm(Block log, Block leaves, boolean big, boolean update, boolean checkForWater) {
+	public WorldFeatureTreePalm(Block<?> log, Block<?> leaves, boolean big, boolean update, boolean checkForWater) {
 		this.log = log;
 		this.leaves = leaves;
 		this.update = update;
@@ -176,20 +176,11 @@ public class WorldFeatureTreePalm extends WorldFeature {
 		if(id == 0) {
 			return true;
 		}
-		Block block = Blocks.getBlock(id);
+		Block<?> block = Blocks.getBlock(id);
 		
 		// TODO Create BlockTag and apply to all trees
-		if(block instanceof BlockLog) {
-			return true;
-		}
-		if(block instanceof BlockLeavesBase) {
-			return true;
-		}
-		if(block instanceof BlockFlower) {
-			return true;
-		}
-		return false;
-	}
+        return Block.hasLogicClass(block, BlockLogicLog.class) || Block.hasLogicClass(block, BlockLogicLeavesBase.class) || Block.hasLogicClass(block, BlockLogicFlower.class);
+    }
 	
 	public boolean isClearRange(int x, int y, int z, int w, int h, int d) {
 		for(int i = -w; i <= w; i++) {
@@ -316,7 +307,7 @@ public class WorldFeatureTreePalm extends WorldFeature {
 		int distance = 1;
 		for(int xi = x - distance; xi <= x + distance; xi++){
 			for(int zi = z - distance; zi <= z + distance; zi++){
-				Block blockAtRange = world.getBlock(xi, y-1, zi);
+				Block<?> blockAtRange = world.getBlock(xi, y-1, zi);
 				if(blockAtRange != null && blockAtRange.hasTag(BlockTags.IS_WATER)){
 					return true;
 				}
@@ -325,19 +316,19 @@ public class WorldFeatureTreePalm extends WorldFeature {
 		return false;
 	}
 	
-	public void generateBlock(int x, int y, int z, Block block) {
+	public void generateBlock(int x, int y, int z, Block<?> block) {
 		if(update) {
-			world.setBlockWithNotify(x, y, z, block.id);
+			world.setBlockWithNotify(x, y, z, block.id());
 		}else {
-			world.setBlock(x, y, z, block.id);
+			world.setBlock(x, y, z, block.id());
 		}	
 	}
 	
 	public boolean canGrowOnThisBlock(int id, int x, int y, int z) {
-		if(Block.hasTag(id, BlockTags.GROWS_TREES)) {
+		if(Blocks.hasTag(id, BlockTags.GROWS_TREES)) {
 			return true;
 		}
-		if(id == Blocks.SAND.id) {
+		if(id == Blocks.SAND.id()) {
 			if(checkForWater && !waterNearby(x, y, z)) {
 				return false;
 			}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShapeSwamp.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShapeSwamp.java
index c4c6070ff..283fd33d2 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShapeSwamp.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShapeSwamp.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
@@ -70,7 +69,7 @@ public class WorldFeatureTreeShapeSwamp extends WorldFeature
             return false;
         }
         int sinkToFloor = 0;
-        for(; world.getBlockId(x, (y -sinkToFloor)-1, z)==Blocks.FLUID_WATER_STILL.id; sinkToFloor++) {
+        for(; world.getBlockId(x, (y -sinkToFloor)-1, z)==Blocks.FLUID_WATER_STILL.id(); sinkToFloor++) {
 
             if (sinkToFloor > 3)
                 return false;
@@ -78,12 +77,12 @@ public class WorldFeatureTreeShapeSwamp extends WorldFeature
         int oldY = y;
         y = y -sinkToFloor;
         int idBelow = world.getBlockId(x, y - 1, z);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - trunkLength + sinkToFloor - 1)
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - trunkLength + sinkToFloor - 1)
         {
             return false;
         }
         WorldFeatureTree.onTreeGrown(world, x, y, z);
-        world.setBlockWithNotify(x, y - 1, z, Blocks.DIRT.id);
+        world.setBlockWithNotify(x, y - 1, z, Blocks.DIRT.id());
         for(int k1 = (y - 3) + trunkLength + sinkToFloor; k1 <= y + trunkLength + sinkToFloor; k1++)
         {
             int j2 = k1 - (y + trunkLength + sinkToFloor);
@@ -118,7 +117,7 @@ public class WorldFeatureTreeShapeSwamp extends WorldFeature
         for(int l1 = 0; l1 < trunkLength + sinkToFloor; l1++)
         {
             int k2 = world.getBlockId(x, y + l1, z);
-            if(k2 == 0 || k2 == leavesID || k2 == Blocks.FLUID_WATER_STILL.id || k2 == Blocks.FLUID_WATER_FLOWING.id)
+            if(k2 == 0 || k2 == leavesID || k2 == Blocks.FLUID_WATER_STILL.id() || k2 == Blocks.FLUID_WATER_FLOWING.id())
             {
                 world.setBlockWithNotify(x, y + l1, z, logID);
             }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShrub.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShrub.java
index 106b96860..4255c2b18 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShrub.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeShrub.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.feature.MethodParametersAnnotation;
@@ -60,7 +60,7 @@ public class WorldFeatureTreeShrub extends WorldFeature
             return false;
         }
         int idBelow = world.getBlockId(x, y - 1, z);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - maxHeight - 1)
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - maxHeight - 1)
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaBushy.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaBushy.java
index f69bc5d11..e6064cc1e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaBushy.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaBushy.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.feature.MethodParametersAnnotation;
@@ -69,7 +69,7 @@ public class WorldFeatureTreeTaigaBushy extends WorldFeature
             return false;
         }
         int idBelow = world.getBlockId(x, y - 1, z);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - l - 1)
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - l - 1)
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaTall.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaTall.java
index 74f5ecd1f..a91a9b666 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaTall.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTaigaTall.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.feature.MethodParametersAnnotation;
@@ -67,7 +67,7 @@ public class WorldFeatureTreeTaigaTall extends WorldFeature
             return false;
         }
         int idBelow = world.getBlockId(x, y - 1, z);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - l - 1)
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES) || y >= world.getHeightBlocks() - l - 1)
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTall.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTall.java
index 4c631f893..3e0ed8af6 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTall.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureTreeTall.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate.feature.tree;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
@@ -67,7 +66,7 @@ public class WorldFeatureTreeTall extends WorldFeature
             return false;
         }
         int idBelow = world.getBlockId(x, y - 1, z);
-        if(!Block.hasTag(idBelow, BlockTags.GROWS_TREES)|| y >= world.getHeightBlocks() - trunkHeight - 1)
+        if(!Blocks.hasTag(idBelow, BlockTags.GROWS_TREES)|| y >= world.getHeightBlocks() - trunkHeight - 1)
         {
             return false;
         }
@@ -133,7 +132,7 @@ public class WorldFeatureTreeTall extends WorldFeature
                     world.setBlockAndMetadataWithNotify(x + xOffset, y + yOffset, z + zOffset, logID, onXAxis? 2 : 1);
                     if(random.nextInt(10)==0){
                         if(world.getBlockId(x + xOffset, y + yOffset+1, z + zOffset)==0)
-                            world.setBlockWithNotify(x + xOffset, y + yOffset+1, z + zOffset, Blocks.MUSHROOM_BROWN.id);
+                            world.setBlockWithNotify(x + xOffset, y + yOffset+1, z + zOffset, Blocks.MUSHROOM_BROWN.id());
                     }
             }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/spooner/WorldFeatureSpoonerTree.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/spooner/WorldFeatureSpoonerTree.java
index 248b36af7..bc326c589 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/spooner/WorldFeatureSpoonerTree.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/spooner/WorldFeatureSpoonerTree.java
@@ -1,6 +1,5 @@
 package net.minecraft.core.world.generate.feature.tree.spooner;
 
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.world.World;
@@ -82,7 +81,7 @@ public abstract class WorldFeatureSpoonerTree
     private boolean canGenerateTree(World world)
     {
         int blockIdUnderneath = world.getBlockId(pos[0], pos[1] - 1, pos[2]);
-        if(!Block.hasTag(blockIdUnderneath, BlockTags.GROWS_TREES))
+        if(!Blocks.hasTag(blockIdUnderneath, BlockTags.GROWS_TREES))
         {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java b/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java
index fb8d14baf..85c6092f5 100644
--- a/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java
+++ b/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.world.pathfinder;
 
-import net.minecraft.core.block.BlockDoor;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicDoor;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.Entity;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.collection.IntHashMap;
 import net.minecraft.core.util.helper.MathHelper;
@@ -41,8 +41,7 @@ public class PathFinder
         Node pathpoint = getNode(MathHelper.floor(entity.bb.minX), MathHelper.floor(entity.bb.minY), MathHelper.floor(entity.bb.minZ));
         Node pathpoint1 = getNode(MathHelper.floor(xt - (double)(entity.bbWidth / 2.0F)), MathHelper.floor(yt), MathHelper.floor(zt - (double)(entity.bbWidth / 2.0F)));
         Node pathpoint2 = new Node(MathHelper.floor_float(entity.bbWidth + 1.0F), MathHelper.floor_float(entity.bbHeight + 1.0F), MathHelper.floor_float(entity.bbWidth + 1.0F));
-        Path pathentity = findPath(entity, pathpoint, pathpoint1, pathpoint2, distance);
-        return pathentity;
+        return findPath(entity, pathpoint, pathpoint1, pathpoint2, distance);
     }
 
     private Path findPath(Entity entity, Node pathpoint, Node pathpoint1, Node pathpoint2, float f)
@@ -192,16 +191,16 @@ public class PathFinder
                     {
                         continue;
                     }
-                    if(Blocks.blocksList[k1] instanceof BlockDoor)
+                    if(Block.hasLogicClass(Blocks.blocksList[k1], BlockLogicDoor.class))
                     {
                         int l1 = worldSource.getBlockMetadata(x1, y1, z1);
-                        if(!BlockDoor.isOpen(l1))
+                        if(!BlockLogicDoor.isOpen(l1))
                         {
                             return 0;
                         }
                         continue;
                     }
-                    Material material = Blocks.blocksList[k1].blockMaterial;
+                    Material material = Blocks.blocksList[k1].getMaterial();
                     if(material.blocksMotion())
                     {
                         return 0;
diff --git a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
index b849176cf..a32faab15 100644
--- a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
+++ b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
@@ -116,7 +116,7 @@ public class ItemMapSavedData extends SavedData
 
         for(MapWaypoint mapWaypoint : mapWaypoints){
             if(player.distanceToSqr(mapWaypoint.xPos, mapWaypoint.yPos, mapWaypoint.zPos) <= 256D) {
-               if(player.world.getBlockId(mapWaypoint.xPos, mapWaypoint.yPos, mapWaypoint.zPos)!= Blocks.FLAG.id)
+               if(player.world.getBlockId(mapWaypoint.xPos, mapWaypoint.yPos, mapWaypoint.zPos)!= Blocks.FLAG.id())
                 {
                     mapWaypoints.remove(mapWaypoint);
                     break;
diff --git a/game/core/src/main/java/net/minecraft/core/world/type/WorldType.java b/game/core/src/main/java/net/minecraft/core/world/type/WorldType.java
index 6f3add051..9190e849a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/type/WorldType.java
+++ b/game/core/src/main/java/net/minecraft/core/world/type/WorldType.java
@@ -52,8 +52,8 @@ public abstract class WorldType {
             this.maxPortalY = this.maxY;
         }
         this.oceanY = properties.oceanY;
-        this.oceanBlockId = properties.oceanBlock == null ? 0 : properties.oceanBlock.id;
-        this.fillerBlockId = properties.fillerBlock == null ? 0 : properties.fillerBlock.id;
+        this.oceanBlockId = properties.oceanBlock == null ? 0 : properties.oceanBlock.id();
+        this.fillerBlockId = properties.fillerBlock == null ? 0 : properties.fillerBlock.id();
         this.dayNightCycleTicks = properties.dayNightCycleTicks;
         this.mayRespawn = properties.mayRespawn;
     }
@@ -244,8 +244,8 @@ public abstract class WorldType {
         private int maxY = 255;
         private Integer maxPortalY = null;
         private int oceanY = 128;
-        private Block oceanBlock = null;
-        private Block fillerBlock = null;
+        private Block<?> oceanBlock = null;
+        private Block<?> fillerBlock = null;
         private int dayNightCycleTicks = Global.DAY_LENGTH_TICKS;
         private boolean mayRespawn = false;
 
@@ -318,12 +318,12 @@ public abstract class WorldType {
             return this;
         }
 
-        public Properties oceanBlock(Block oceanBlock) {
+        public Properties oceanBlock(Block<?> oceanBlock) {
             this.oceanBlock = oceanBlock;
             return this;
         }
 
-        public Properties fillerBlock(Block fillerBlock) {
+        public Properties fillerBlock(Block<?> fillerBlock) {
             this.fillerBlock = fillerBlock;
             return this;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeFlat.java b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeFlat.java
index d9e5b0b8c..00f21012b 100644
--- a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeFlat.java
+++ b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeFlat.java
@@ -26,7 +26,7 @@ public class WorldTypeFlat
 
     @Override
     public boolean isValidSpawn(World world, int x, int y, int z) {
-        return world.getBlockId(x, y, z) == Blocks.GRASS.id;
+        return world.getBlockId(x, y, z) == Blocks.GRASS.id();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworld.java b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworld.java
index 97e93d52a..02e75163f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworld.java
@@ -63,7 +63,7 @@ public class WorldTypeOverworld
 
     @Override
     public boolean isValidSpawn(World world, int x, int y, int z) {
-        return world.getBlockId(x, y, z) == Blocks.SAND.id;
+        return world.getBlockId(x, y, z) == Blocks.SAND.id();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldFloating.java b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldFloating.java
index c269a8122..5eb54d04f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldFloating.java
+++ b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldFloating.java
@@ -29,7 +29,7 @@ public class WorldTypeOverworldFloating
 
     @Override
     public boolean isValidSpawn(World world, int x, int y, int z) {
-        Block block = world.getBlock(x, y, z);
+        Block<?> block = world.getBlock(x, y, z);
         return world.getHeightValue(x, z) > 0 && block != null && block.isSolidRender();
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldIndev.java b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldIndev.java
index 99834d2de..cd0b6da88 100644
--- a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldIndev.java
+++ b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldIndev.java
@@ -21,14 +21,14 @@ public class WorldTypeOverworldIndev
 
     @Override
     public boolean isValidSpawn(World world, int x, int y, int z) {
-        return world.getBlockId(x, y, z) == Blocks.GRASS.id || world.getBlockId(x, y, z) == Blocks.SAND.id || world.getBlockId(x, y, z) == Blocks.GRASS_RETRO.id;
+        return world.getBlockId(x, y, z) == Blocks.GRASS.id() || world.getBlockId(x, y, z) == Blocks.SAND.id() || world.getBlockId(x, y, z) == Blocks.GRASS_RETRO.id();
     }
 
     @Override
     public void getInitialSpawnLocation(World world) {
-        int x = 0;
-        int y = 0;
-        int z = 0;
+        int x;
+        int y;
+        int z;
         Random random = new Random(world.getRandomSeed());
         spawnLoop:
         while (true) {
diff --git a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldInland.java b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldInland.java
index 5bb0326c0..7af4c8a83 100644
--- a/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldInland.java
+++ b/game/core/src/main/java/net/minecraft/core/world/type/overworld/WorldTypeOverworldInland.java
@@ -11,6 +11,6 @@ public class WorldTypeOverworldInland
 
     @Override
     public boolean isValidSpawn(World world, int x, int y, int z) {
-        return world.getBlockId(x, y, z) == Blocks.GRASS.id;
+        return world.getBlockId(x, y, z) == Blocks.GRASS.id();
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java b/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java
index e900858ba..47ce15638 100644
--- a/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java
+++ b/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java
@@ -102,7 +102,7 @@ public abstract class Weather
 
 			if (world.getBlockBiome(x, y, z).hasSurfaceSnow())
 			{
-				if (blockId == Blocks.LAYER_SNOW.id)
+				if (blockId == Blocks.LAYER_SNOW.id())
 				{
 					int meta = world.getBlockMetadata(x, y, z);
 					if (meta != 0)
@@ -114,7 +114,7 @@ public abstract class Weather
 			}
 			else
 			{
-				if (blockId == Blocks.LAYER_SNOW.id)
+				if (blockId == Blocks.LAYER_SNOW.id())
 				{
 					int meta = world.getBlockMetadata(x, y, z);
 					if (meta != 0)
@@ -127,9 +127,9 @@ public abstract class Weather
 						world.setBlockWithNotify(x, y, z, 0);
 					}
 				}
-				else if (blockIdBelow == Blocks.ICE.id)
+				else if (blockIdBelow == Blocks.ICE.id())
 				{
-					world.setBlockWithNotify(x, y - 1, z, Blocks.FLUID_WATER_STILL.id);
+					world.setBlockWithNotify(x, y - 1, z, Blocks.FLUID_WATER_STILL.id());
 				}
 			}
 		}
@@ -151,20 +151,20 @@ public abstract class Weather
 
 				if (world.getBlockBiome(chunk.xPosition * 16 + x, y, chunk.zPosition * 16 + z).hasSurfaceSnow())
 				{
-					if (blockId == Blocks.LAYER_SNOW.id)
+					if (blockId == Blocks.LAYER_SNOW.id())
 					{
 						chunk.setBlockMetadata(x, y, z, 0);
 					}
 				}
 				else
 				{
-					if (blockId == Blocks.LAYER_SNOW.id)
+					if (blockId == Blocks.LAYER_SNOW.id())
 					{
 						chunk.setBlockID(x, y, z, 0);
 					}
-					else if (blockIdBelow == Blocks.ICE.id)
+					else if (blockIdBelow == Blocks.ICE.id())
 					{
-						chunk.setBlockID(x, y - 1, z, Blocks.FLUID_WATER_STILL.id);
+						chunk.setBlockID(x, y - 1, z, Blocks.FLUID_WATER_STILL.id());
 					}
 				}
 			}
diff --git a/game/core/src/main/java/net/minecraft/core/world/weather/WeatherSnow.java b/game/core/src/main/java/net/minecraft/core/world/weather/WeatherSnow.java
index 117107415..6b5597651 100644
--- a/game/core/src/main/java/net/minecraft/core/world/weather/WeatherSnow.java
+++ b/game/core/src/main/java/net/minecraft/core/world/weather/WeatherSnow.java
@@ -4,7 +4,6 @@ import java.util.Random;
 
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.BlockLayerSnow;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
@@ -56,14 +55,14 @@ zLoop:		for (int z = 0; z < 16; z++)
 
 				if (y >= 0 && y < world.getHeightBlocks() && chunk.getBrightness(LightLayer.Block, x, y, z) < 10)
 				{
-					if (blockId == 0 && Blocks.LAYER_SNOW.canPlaceBlockAt(world, worldX, y, worldZ) && blockIdBelow != Blocks.ICE.id)
+					if (blockId == 0 && Blocks.LAYER_SNOW.canPlaceBlockAt(world, worldX, y, worldZ) && blockIdBelow != Blocks.ICE.id())
 					{
-						chunk.setBlockIDWithMetadataRaw(x, y, z, Blocks.LAYER_SNOW.id, chunk.getBlockMetadata(x, y, z));
+						chunk.setBlockIDWithMetadataRaw(x, y, z, Blocks.LAYER_SNOW.id(), chunk.getBlockMetadata(x, y, z));
 					}
-					else if (blockIdBelow == Blocks.FLUID_WATER_STILL.id && chunk.getBlockMetadata(x, y - 1, z) == 0) {
-						chunk.setBlockIDWithMetadataRaw(x, y - 1, z, Blocks.ICE.id, chunk.getBlockMetadata(x, y - 1, z));
-						if (chunk.getBlockID(x, y - 2, z) == Blocks.FLUID_WATER_STILL.id){
-							chunk.setBlockIDWithMetadataRaw(x, y - 2, z, Blocks.FLUID_WATER_FLOWING.id, chunk.getBlockMetadata(x, y - 2, z));
+					else if (blockIdBelow == Blocks.FLUID_WATER_STILL.id() && chunk.getBlockMetadata(x, y - 1, z) == 0) {
+						chunk.setBlockIDWithMetadataRaw(x, y - 1, z, Blocks.ICE.id(), chunk.getBlockMetadata(x, y - 1, z));
+						if (chunk.getBlockID(x, y - 2, z) == Blocks.FLUID_WATER_STILL.id()){
+							chunk.setBlockIDWithMetadataRaw(x, y - 2, z, Blocks.FLUID_WATER_FLOWING.id(), chunk.getBlockMetadata(x, y - 2, z));
 						}
 					}
 				}
@@ -95,30 +94,30 @@ zLoop:		for (int z = 0; z < 16; z++)
 		
 		if (world.weatherManager.getWeatherPower() > 0.6f && y >= 0 && y < world.getHeightBlocks() && world.getSavedLightValue(LightLayer.Block, x, y, z) < 10)
 		{
-			if (blockId == 0 && blockIdBelow != 0 && Blocks.LAYER_SNOW.canPlaceBlockAt(world, x, y, z) && blockIdBelow != Blocks.ICE.id)
+			if (blockId == 0 && blockIdBelow != 0 && Blocks.LAYER_SNOW.canPlaceBlockAt(world, x, y, z) && blockIdBelow != Blocks.ICE.id())
 			{
 				if(snow)
 				{
-					world.setBlockWithNotify(x, y, z, Blocks.LAYER_SNOW.id);
+					world.setBlockWithNotify(x, y, z, Blocks.LAYER_SNOW.id());
 				}
 			}
-			else if (world.weatherManager.getWeatherPower() > 0.5f && blockId == Blocks.LAYER_SNOW.id && world.getSeasonManager().getCurrentSeason() != null && (world.getSeasonManager().getCurrentSeason().hasDeeperSnow || biome == Biomes.OVERWORLD_GLACIER))
+			else if (world.weatherManager.getWeatherPower() > 0.5f && blockId == Blocks.LAYER_SNOW.id() && world.getSeasonManager().getCurrentSeason() != null && (world.getSeasonManager().getCurrentSeason().hasDeeperSnow || biome == Biomes.OVERWORLD_GLACIER))
 			{
 				if(snow) {
-					((BlockLayerSnow)Blocks.LAYER_SNOW).accumulate(world, x, y, z);
+					Blocks.LAYER_SNOW.getLogic().accumulate(world, x, y, z);
 				}
 			}
-			else if (blockIdBelow == Blocks.FLUID_WATER_STILL.id && world.getBlockMetadata(x, y - 1, z) == 0)
+			else if (blockIdBelow == Blocks.FLUID_WATER_STILL.id() && world.getBlockMetadata(x, y - 1, z) == 0)
 			{
 				if(rand.nextFloat() < world.weatherManager.getWeatherPower() * world.weatherManager.getWeatherIntensity())
 				{
 					for(int i=0; i < 4; i++)
 					{
 						Direction direction = Direction.horizontalDirections[i];
-						Block block = world.getBlock(x + direction.getOffsetX(), y - 1, z + direction.getOffsetZ());
+						Block<?> block = world.getBlock(x + direction.getOffsetX(), y - 1, z + direction.getOffsetZ());
 						if(block == Blocks.ICE || block != null && block.isSolidRender())
 						{
-							world.setBlockWithNotify(x, y - 1, z, Blocks.ICE.id);
+							world.setBlockWithNotify(x, y - 1, z, Blocks.ICE.id());
 							break;
 						}
 					}	
diff --git a/game/core/src/main/java/net/minecraft/core/world/weather/WeatherStorm.java b/game/core/src/main/java/net/minecraft/core/world/weather/WeatherStorm.java
index 4daebdace..f714ff933 100644
--- a/game/core/src/main/java/net/minecraft/core/world/weather/WeatherStorm.java
+++ b/game/core/src/main/java/net/minecraft/core/world/weather/WeatherStorm.java
@@ -1,7 +1,6 @@
 package net.minecraft.core.world.weather;
 
 import net.minecraft.core.block.material.Material;
-import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityLightning;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.util.helper.MathHelper;
@@ -70,7 +69,7 @@ public class WeatherStorm extends WeatherRain
 		weight += checkY;
 		weight += material.getConductivity();
 
-		List<Entity> entityList = world.getEntitiesWithinAABB(Mob.class, AABB.getTemporaryBB(checkX, checkY, checkZ, checkX + 1, checkY + 1, checkZ + 1));
+		List<Mob> entityList = world.getEntitiesWithinAABB(Mob.class, AABB.getTemporaryBB(checkX, checkY, checkZ, checkX + 1, checkY + 1, checkZ + 1));
 		if (!entityList.isEmpty()){
 			weight += 4; // :)
 		}
diff --git a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
index 85cd53ee9..aefb04f7f 100644
--- a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
+++ b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
@@ -1,8 +1,7 @@
 package net.minecraft.server.entity.player;
 
 import net.minecraft.core.achievement.stat.Stat;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockPortal;
+import net.minecraft.core.block.BlockLogicPortal;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.*;
 import net.minecraft.core.crafting.ContainerListener;
@@ -50,8 +49,8 @@ public class PlayerServer extends Player implements ContainerListener {
     public PlayerServer(MinecraftServer minecraftserver, World world, String username, UUID uuid, ServerPlayerController serverPlayerController)
     {
         super(world);
-        loadedChunks = new LinkedList();
-        field_420_ah = new HashSet();
+        loadedChunks = new LinkedList<>();
+        field_420_ah = new HashSet<>();
         lastHealth = 0xfa0a1f01;
         lastScore = 0xfa0a1f01;
         ticksOfInvuln = 60;
@@ -302,10 +301,10 @@ public class PlayerServer extends Player implements ContainerListener {
 
         if (inPortal)
         {
-            int targetDim = ((BlockPortal) Blocks.blocksList[portalID]).targetDimension;
+            Dimension targetDim = ((BlockLogicPortal) Blocks.blocksList[portalID].getLogic()).targetDimension;
             boolean netherAllowed = mcServer.propertyManager.getBooleanProperty("allow-nether", true);
             boolean paradiseAllowed = mcServer.propertyManager.getBooleanProperty("allow-paradise", false);
-            if ((netherAllowed && targetDim == Dimension.NETHER.id) || (paradiseAllowed && targetDim == Dimension.PARADISE.id) || (targetDim != Dimension.NETHER.id && targetDim != Dimension.PARADISE.id))
+            if ((netherAllowed && targetDim == Dimension.NETHER) || (paradiseAllowed && targetDim == Dimension.PARADISE) || (targetDim != Dimension.NETHER && targetDim != Dimension.PARADISE))
             {
                 if (craftingInventory != inventorySlots)
                 {
@@ -322,13 +321,13 @@ public class PlayerServer extends Player implements ContainerListener {
                     {
                         timeInPortal = 1.0F;
                         timeUntilPortal = 10;
-                        if (dimension == targetDim)
+                        if (dimension == targetDim.id)
                         {
                             mcServer.playerList.sendPlayerToOtherDimension(this, 0, portalColor, true);
                         }
                         else
                         {
-                            mcServer.playerList.sendPlayerToOtherDimension(this, targetDim, portalColor, true);
+                            mcServer.playerList.sendPlayerToOtherDimension(this, targetDim.id, portalColor, true);
                         }
                     }
                 }
@@ -374,10 +373,10 @@ public class PlayerServer extends Player implements ContainerListener {
                     WorldServer worldserver = mcServer.getDimensionWorld(dimension);
                     loadedChunks.remove(chunkCoord);
                     playerNetServerHandler.sendPacket(new PacketBlockRegionUpdate(chunkCoord.x * Chunk.CHUNK_SIZE_X, 0, chunkCoord.z * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, Chunk.CHUNK_SIZE_Z, worldserver));
-                    List list = worldserver.getBlockEntitiesWithinBounds(chunkCoord.x * Chunk.CHUNK_SIZE_X, 0, chunkCoord.z * Chunk.CHUNK_SIZE_Z, chunkCoord.x * Chunk.CHUNK_SIZE_X + Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, chunkCoord.z * Chunk.CHUNK_SIZE_Z + Chunk.CHUNK_SIZE_Z);
+                    List<TileEntity> list = worldserver.getBlockEntitiesWithinBounds(chunkCoord.x * Chunk.CHUNK_SIZE_X, 0, chunkCoord.z * Chunk.CHUNK_SIZE_Z, chunkCoord.x * Chunk.CHUNK_SIZE_X + Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, chunkCoord.z * Chunk.CHUNK_SIZE_Z + Chunk.CHUNK_SIZE_Z);
                     for (int j = 0; j < list.size(); j++)
                     {
-                        getTileEntityInfo((TileEntity) list.get(j));
+                        getTileEntityInfo(list.get(j));
                     }
                 }
             }
@@ -538,7 +537,7 @@ public class PlayerServer extends Player implements ContainerListener {
 	public void displayFurnaceScreen(TileEntityFurnace blockEntity)
     {
         getNextWindowId();
-        if (blockEntity instanceof TileEntityFurnaceBlastFurnace)
+        if (blockEntity instanceof TileEntityFurnaceBlast)
         {
             playerNetServerHandler.sendPacket(new PacketContainerOpen(currentWindowId, PacketContainerOpen.TYPE_BLAST_FURNACE, blockEntity.getName(), blockEntity.getContainerSize()));
         }
diff --git a/game/server/src/main/java/net/minecraft/server/world/ServerPlayerController.java b/game/server/src/main/java/net/minecraft/server/world/ServerPlayerController.java
index 588a3a41f..f4fca8d05 100644
--- a/game/server/src/main/java/net/minecraft/server/world/ServerPlayerController.java
+++ b/game/server/src/main/java/net/minecraft/server/world/ServerPlayerController.java
@@ -31,7 +31,7 @@ public class ServerPlayerController
             int j = thisWorld.getBlockId(destroyX, destroyY, destroyZ);
             if(j != 0)
             {
-                Block block = Blocks.blocksList[j];
+                Block<?> block = Blocks.blocksList[j];
                 float f = block.blockStrength(thisWorld, destroyX, destroyY, destroyZ, destroySide, player) * (float)(i + 1);
                 if(f >= 1.0F)
                 {
@@ -51,7 +51,7 @@ public class ServerPlayerController
 			return;
 		}
 		blockHitTicks = ticksRan;
-		Block block = thisWorld.getBlock(x, y, z);
+        Block<?> block = thisWorld.getBlock(x, y, z);
 		if(block != null && block.blockStrength(thisWorld, x, y, z, side, player) >= 1.0F) {
 			mineBlock(x, y, z, side);
 		} else {
@@ -63,7 +63,7 @@ public class ServerPlayerController
     
 	public void hitBlock(int x, int y, int z, Side side, double xHit, double yHit) {
 		thisWorld.onBlockHit(player, x, y, z, side);
-		Block block = thisWorld.getBlock(x, y, z);
+        Block<?> block = thisWorld.getBlock(x, y, z);
 		if(block != null) {
 			block.onBlockLeftClicked(thisWorld, x, y, z, player, side, xHit, yHit);
 		}
@@ -77,7 +77,7 @@ public class ServerPlayerController
             int i1 = thisWorld.getBlockId(x, y, z);
             if(i1 != 0)
             {
-                Block block = Blocks.blocksList[i1];
+                Block<?> block = Blocks.blocksList[i1];
                 float f = block.blockStrength(thisWorld, x, y, z, side, player) * (float)(l + 1);
                 if(f >= 0.7F)
                 {
@@ -99,8 +99,8 @@ public class ServerPlayerController
 
     public boolean removeBlock(int x, int y, int z)
     {
-        Block block = Blocks.blocksList[thisWorld.getBlockId(x, y, z)];
-        int l = thisWorld.getBlockMetadata(x, y, z);
+//        Block<?> block = Blocks.blocksList[thisWorld.getBlockId(x, y, z)];
+//        int l = thisWorld.getBlockMetadata(x, y, z);
         return thisWorld.setBlockWithNotify(x, y, z, 0);
     }
 
@@ -116,7 +116,7 @@ public class ServerPlayerController
     			return false;
     		}
     	}
-        Block block = Blocks.getBlock(id);
+        Block<?> block = Blocks.getBlock(id);
         TileEntity tileEntity = thisWorld.getBlockEntity(x, y, z);
         thisWorld.playBlockEvent(player, LevelListener.EVENT_BLOCK_BREAK, x, y, z, id);
         boolean flag = removeBlock(x, y, z);
