diff --git a/pom.xml b/pom.xml
index fc494f7..e9111aa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,18 @@
             <artifactId>jline-reader</artifactId>
             <version>3.20.0</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.10.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>31.1-jre</version>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/src/main/java/cz/jzitnik/game/Dependencies.java b/src/main/java/cz/jzitnik/game/Dependencies.java
new file mode 100644
index 0000000..62e6837
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/Dependencies.java
@@ -0,0 +1,7 @@
+package cz.jzitnik.game;
+
+import cz.jzitnik.game.handlers.place.PlaceHandler;
+
+public class Dependencies {
+    public PlaceHandler placeHandler = new PlaceHandler();
+}
diff --git a/src/main/java/cz/jzitnik/game/Game.java b/src/main/java/cz/jzitnik/game/Game.java
index 364c4c2..5b3675c 100644
--- a/src/main/java/cz/jzitnik/game/Game.java
+++ b/src/main/java/cz/jzitnik/game/Game.java
@@ -1,14 +1,16 @@
 package cz.jzitnik.game;
 
+import cz.jzitnik.game.generation.Generation;
 import cz.jzitnik.game.items.Item;
 import cz.jzitnik.game.items.ItemType;
+import cz.jzitnik.game.handlers.place.CustomPlaceHandler;
 import cz.jzitnik.game.sprites.Breaking;
 import cz.jzitnik.game.sprites.Steve;
 import cz.jzitnik.game.ui.Chest;
 import cz.jzitnik.game.ui.Furnace;
 import cz.jzitnik.game.ui.Window;
 import cz.jzitnik.game.ui.Inventory;
-import cz.jzitnik.tui.RightClickHandler;
+import cz.jzitnik.game.handlers.rightclick.RightClickHandler;
 import cz.jzitnik.tui.ScreenMovingCalculationProvider;
 import cz.jzitnik.tui.ScreenRenderer;
 import lombok.Getter;
@@ -20,11 +22,9 @@ import java.util.List;
 
 @Getter
 public class Game {
-    private List<Block>[][] world = new ArrayList[256][512];
-    @Setter
-    private Block player;
-    @Setter
-    private Block player2;
+    @SuppressWarnings("unchecked")
+    private final List<Block>[][] world = (List<Block>[][]) new ArrayList[256][512];
+    private final Player player = new Player();
     private boolean mining = false;
     @Setter
     private Window window = Window.WORLD;
@@ -61,10 +61,10 @@ public class Game {
             return;
         }
 
-        world[cords[1]][cords[0] + 1].add(player2);
-        world[cords[1]][cords[0]].remove(player2);
-        world[cords[1]-1][cords[0] + 1].add(player);
-        world[cords[1]-1][cords[0]].remove(player);
+        world[cords[1]][cords[0] + 1].add(player.getPlayerBlock2());
+        world[cords[1]][cords[0]].remove(player.getPlayerBlock2());
+        world[cords[1]-1][cords[0] + 1].add(player.getPlayerBlock1());
+        world[cords[1]-1][cords[0]].remove(player.getPlayerBlock1());
         screenRenderer.render(this);
 
         update(screenRenderer);
@@ -80,10 +80,10 @@ public class Game {
             return;
         }
 
-        world[cords[1]][cords[0] - 1].add(player2);
-        world[cords[1]][cords[0]].remove(player2);
-        world[cords[1]-1][cords[0] - 1].add(player);
-        world[cords[1]-1][cords[0]].remove(player);
+        world[cords[1]][cords[0] - 1].add(player.getPlayerBlock2());
+        world[cords[1]][cords[0]].remove(player.getPlayerBlock2());
+        world[cords[1]-1][cords[0] - 1].add(player.getPlayerBlock1());
+        world[cords[1]-1][cords[0]].remove(player.getPlayerBlock1());
         screenRenderer.render(this);
 
         update(screenRenderer);
@@ -95,14 +95,14 @@ public class Game {
         }
         int[] cords = getPlayerCords();
 
-        if (world[cords[1] - 2][cords[0]].stream().anyMatch(block -> !block.isGhost()) || world[cords[1] + 1][cords[0]].stream().anyMatch(Block::isGhost)) {
+        if (world[cords[1] - 2][cords[0]].stream().anyMatch(block -> !block.isGhost()) || world[cords[1] + 1][cords[0]].stream().allMatch(Block::isGhost)) {
             return;
         }
 
-        world[cords[1] - 1][cords[0]].remove(player);
-        world[cords[1] - 1][cords[0]].add(player2);
-        world[cords[1] - 2][cords[0]].add(player);
-        world[cords[1]][cords[0]].remove(player2);
+        world[cords[1] - 1][cords[0]].remove(player.getPlayerBlock1());
+        world[cords[1] - 1][cords[0]].add(player.getPlayerBlock2());
+        world[cords[1] - 2][cords[0]].add(player.getPlayerBlock1());
+        world[cords[1]][cords[0]].remove(player.getPlayerBlock2());
 
         new Thread(() -> {
             try {
@@ -113,10 +113,10 @@ public class Game {
             int[] cords2 = getPlayerCords();
 
             if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) {
-                world[cords2[1] - 1][cords2[0]].remove(player);
-                world[cords2[1]][cords2[0]].add(player);
-                world[cords2[1] + 1][cords2[0]].add(player2);
-                world[cords2[1]][cords2[0]].remove(player2);
+                world[cords2[1] - 1][cords2[0]].remove(player.getPlayerBlock1());
+                world[cords2[1]][cords2[0]].add(player.getPlayerBlock1());
+                world[cords2[1] + 1][cords2[0]].add(player.getPlayerBlock2());
+                world[cords2[1]][cords2[0]].remove(player.getPlayerBlock2());
 
                 screenRenderer.render(this);
             }
@@ -132,7 +132,7 @@ public class Game {
         world[y][x].add(breakingBlock);
         screenRenderer.render(this);
 
-        double hardness = world[y][x].stream().filter(block -> !block.isGhost()).toList().get(0).calculateHardness(inventory);
+        double hardness = world[y][x].stream().filter(block -> !block.isGhost()).toList().getFirst().calculateHardness(inventory);
 
         this.mining = true;
 
@@ -187,9 +187,10 @@ public class Game {
                 }
             }
 
-            blocks.clear();
-            blocks.add(new Block("air", SpriteLoader.SPRITES.AIR, true, false));
+            CustomPlaceHandler customPlaceHandler = gameStates.dependencies.placeHandler.get(blocks.stream().filter(Block::isMineable).toList().getFirst().getBlockId());
+            customPlaceHandler.mine(this, x, y);
             inventory.getItemInHand().ifPresent(Item::use);
+
             screenRenderer.render(this);
 
             update(screenRenderer);
@@ -233,10 +234,10 @@ public class Game {
             int[] cords2 = getPlayerCords();
 
             if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) {
-                world[cords2[1] - 1][cords2[0]].remove(player);
-                world[cords2[1]][cords2[0]].add(player);
-                world[cords2[1] + 1][cords2[0]].add(player2);
-                world[cords2[1]][cords2[0]].remove(player2);
+                world[cords2[1] - 1][cords2[0]].remove(player.getPlayerBlock1());
+                world[cords2[1]][cords2[0]].add(player.getPlayerBlock1());
+                world[cords2[1] + 1][cords2[0]].add(player.getPlayerBlock2());
+                world[cords2[1]][cords2[0]].remove(player.getPlayerBlock2());
 
                 screenRenderer.render(this);
             } else {
@@ -264,7 +265,7 @@ public class Game {
         }
 
         if (!blocks.stream().allMatch(block -> block.getBlockId().equals("air"))) {
-            RightClickHandler.handle(x, y, this);
+            RightClickHandler.handle(x, y, this, screenRenderer);
             screenRenderer.render(this);
             return;
         }
@@ -273,12 +274,13 @@ public class Game {
             return;
         }
 
-        blocks.removeAll(blocks.stream().filter(block -> block.getBlockId().equals("air")).toList());
-        blocks.add(inventory.getItemInHand().get().getBlock().get());
+        Item item = inventory.getItemInHand().get();
 
-        inventory.decreaseItemInHand();
+        CustomPlaceHandler placeHandler = gameStates.dependencies.placeHandler.get(item.getId());
 
-        screenRenderer.render(this);
+        if (placeHandler.place(this, x, y)) {
+            screenRenderer.render(this);
+        }
     }
 
     public void changeSlot(int slot, ScreenRenderer screenRenderer) {
diff --git a/src/main/java/cz/jzitnik/game/GameStates.java b/src/main/java/cz/jzitnik/game/GameStates.java
index c4fa272..b10d2b1 100644
--- a/src/main/java/cz/jzitnik/game/GameStates.java
+++ b/src/main/java/cz/jzitnik/game/GameStates.java
@@ -4,10 +4,12 @@ import cz.jzitnik.game.ui.CraftingTable;
 
 public class GameStates {
     public CraftingTable craftingTable;
+    public Dependencies dependencies;
     public int clickX = -1;
     public int clickY = -1;
 
     public GameStates(Game game) {
         craftingTable = new CraftingTable(game);
+        dependencies = new Dependencies();
     }
 }
diff --git a/src/main/java/cz/jzitnik/game/Player.java b/src/main/java/cz/jzitnik/game/Player.java
new file mode 100644
index 0000000..e496c28
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/Player.java
@@ -0,0 +1,13 @@
+package cz.jzitnik.game;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Player {
+    private int health = 10;
+    private int hunger = 6;
+    private Block playerBlock1;
+    private Block playerBlock2;
+}
diff --git a/src/main/java/cz/jzitnik/game/SpriteLoader.java b/src/main/java/cz/jzitnik/game/SpriteLoader.java
index 06d41ff..f653adb 100644
--- a/src/main/java/cz/jzitnik/game/SpriteLoader.java
+++ b/src/main/java/cz/jzitnik/game/SpriteLoader.java
@@ -21,10 +21,12 @@ public class SpriteLoader {
 
         CHEST,
         CRAFTING_TABLE,
+        COAL_ORE,
 
         OAK_LOG,
         OAK_LEAF,
         OAK_PLANKS,
+        OAK_DOOR,
 
         WOODEN_PICKAXE,
         STONE_PICKAXE,
@@ -41,9 +43,13 @@ public class SpriteLoader {
         ITEM_COBBLESTONE,
         ITEM_STONE,
         ITEM_FURNACE,
+        ITEM_OAK_DOOR,
 
         ITEM_CRAFTING_TABLE,
-        ITEM_CHEST
+        ITEM_CHEST,
+
+        HEART,
+        HUNGER
     }
 
     public static final HashMap<SPRITES, Sprite> SPRITES_MAP = new HashMap<>();
@@ -63,6 +69,8 @@ public class SpriteLoader {
         SPRITES_MAP.put(SPRITES.CHEST, new SimpleSprite("chest.ans"));
         SPRITES_MAP.put(SPRITES.COBBLESTONE, new SimpleSprite("cobblestone.ans"));
         SPRITES_MAP.put(SPRITES.FURNACE, new Furnace());
+        SPRITES_MAP.put(SPRITES.COAL_ORE, new SimpleSprite("coal_ore.ans"));
+        SPRITES_MAP.put(SPRITES.OAK_DOOR, new OakDoor());
 
         SPRITES_MAP.put(SPRITES.WOODEN_PICKAXE, new SimpleSprite("items/wooden_pickaxe.ans"));
         SPRITES_MAP.put(SPRITES.STONE_PICKAXE, new SimpleSprite("items/stone_pickaxe.ans"));
@@ -79,6 +87,10 @@ public class SpriteLoader {
         SPRITES_MAP.put(SPRITES.ITEM_STONE, new SimpleSprite("items/stone.ans"));
         SPRITES_MAP.put(SPRITES.ITEM_CHEST, new SimpleSprite("items/chest.ans"));
         SPRITES_MAP.put(SPRITES.ITEM_FURNACE, new SimpleSprite("items/furnace.ans"));
+        SPRITES_MAP.put(SPRITES.ITEM_OAK_DOOR, new SimpleSprite("oak_door/items/oak_door.ans"));
+
+        SPRITES_MAP.put(SPRITES.HEART, new Heart());
+        SPRITES_MAP.put(SPRITES.HUNGER, new Hunger());
     }
 
     public static SpriteList<SPRITES> load() {
diff --git a/src/main/java/cz/jzitnik/game/annotations/RegisterPlaceHandler.java b/src/main/java/cz/jzitnik/game/annotations/RegisterPlaceHandler.java
new file mode 100644
index 0000000..d9cc272
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/annotations/RegisterPlaceHandler.java
@@ -0,0 +1,12 @@
+package cz.jzitnik.game.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface RegisterPlaceHandler {
+    String value();
+}
diff --git a/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java b/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java
index 9b3c867..f03a109 100644
--- a/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java
+++ b/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java
@@ -94,6 +94,18 @@ public class CraftingRecipeList {
                 {"cobblestone", null, "cobblestone"},
                 {"cobblestone", "cobblestone", "cobblestone"}
         }, () -> new InventoryItem(1, ItemBlockSupplier.Items.furnace())));
+
+        recipes.add(new CraftingRecipe(new String[][]{
+                {"oak_planks", "oak_planks", null},
+                {"oak_planks", "oak_planks", null},
+                {"oak_planks", "oak_planks", null}
+        }, () -> new InventoryItem(1, ItemBlockSupplier.Items.oakDoor())));
+
+        recipes.add(new CraftingRecipe(new String[][]{
+                {"dirt", null, null},
+                {null, null, null},
+                {null, null, null}
+        }, () -> new InventoryItem(1, ItemBlockSupplier.Items.oakDoor())));
     }
 
     public static Optional<CraftingRecipe> getRecipe(String[] r) {
diff --git a/src/main/java/cz/jzitnik/game/generation/CaveGenerator.java b/src/main/java/cz/jzitnik/game/generation/CaveGenerator.java
new file mode 100644
index 0000000..a27c98f
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/generation/CaveGenerator.java
@@ -0,0 +1,12 @@
+package cz.jzitnik.game.generation;
+
+import cz.jzitnik.game.Block;
+import java.util.List;
+
+public class CaveGenerator {
+    private static final int WIDTH = 512;
+    private static final int HEIGHT = 256;
+
+    public static void generateCaves(List<Block>[][] world, int[] terrainHeight) {
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/Generation.java b/src/main/java/cz/jzitnik/game/generation/Generation.java
similarity index 91%
rename from src/main/java/cz/jzitnik/game/Generation.java
rename to src/main/java/cz/jzitnik/game/generation/Generation.java
index 9e9b50c..7798e79 100644
--- a/src/main/java/cz/jzitnik/game/Generation.java
+++ b/src/main/java/cz/jzitnik/game/generation/Generation.java
@@ -1,5 +1,8 @@
-package cz.jzitnik.game;
+package cz.jzitnik.game.generation;
 
+import cz.jzitnik.game.Block;
+import cz.jzitnik.game.Game;
+import cz.jzitnik.game.SpriteLoader;
 import cz.jzitnik.game.items.ItemBlockSupplier;
 import cz.jzitnik.game.items.ItemType;
 import cz.jzitnik.game.sprites.Steve;
@@ -18,8 +21,8 @@ public class Generation {
         Block steveBlock2 = new Block("steve", SpriteLoader.SPRITES.STEVE);
         steveBlock2.setSpriteState(Steve.SteveState.SECOND);
 
-        game.setPlayer(steveBlock);
-        game.setPlayer2(steveBlock2);
+        game.getPlayer().setPlayerBlock1(steveBlock);
+        game.getPlayer().setPlayerBlock2(steveBlock2);
 
         int[] terrainHeight = generateTerrain();
         populateWorld(world, terrainHeight);
@@ -77,9 +80,7 @@ public class Generation {
 
         for (List<Block>[] lists : world) {
             for (List<Block> list : lists) {
-                if (list.isEmpty()) {
-                    list.add(new Block("air", SpriteLoader.SPRITES.AIR, true, false));
-                }
+                list.addFirst(new Block("air", SpriteLoader.SPRITES.AIR, true, false));
             }
         }
     }
diff --git a/src/main/java/cz/jzitnik/game/handlers/place/CustomPlaceHandler.java b/src/main/java/cz/jzitnik/game/handlers/place/CustomPlaceHandler.java
new file mode 100644
index 0000000..f0c1645
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/handlers/place/CustomPlaceHandler.java
@@ -0,0 +1,8 @@
+package cz.jzitnik.game.handlers.place;
+
+import cz.jzitnik.game.Game;
+
+public interface CustomPlaceHandler {
+    boolean place(Game game, int x, int y);
+    void mine(Game game, int x, int y);
+}
diff --git a/src/main/java/cz/jzitnik/game/handlers/place/DefaultPlaceHandler.java b/src/main/java/cz/jzitnik/game/handlers/place/DefaultPlaceHandler.java
new file mode 100644
index 0000000..2d8681a
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/handlers/place/DefaultPlaceHandler.java
@@ -0,0 +1,24 @@
+package cz.jzitnik.game.handlers.place;
+
+import cz.jzitnik.game.Game;
+
+public class DefaultPlaceHandler implements CustomPlaceHandler {
+    @Override
+    public boolean place(Game game, int x, int y) {
+        var blocks = game.getWorld()[y][x];
+        var inventory = game.getInventory();
+
+        blocks.add(inventory.getItemInHand().get().getBlock().get());
+
+        inventory.decreaseItemInHand();
+
+        return true;
+    }
+
+    @Override
+    public void mine(Game game, int x, int y) {
+        var blocks = game.getWorld()[y][x];
+
+        blocks.removeAll(blocks.stream().filter(i -> !i.getBlockId().equals("air")).toList());
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java b/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java
new file mode 100644
index 0000000..6c5d650
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java
@@ -0,0 +1,45 @@
+package cz.jzitnik.game.handlers.place;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import cz.jzitnik.game.annotations.RegisterPlaceHandler;
+import org.reflections.Reflections;
+
+public class PlaceHandler {
+    private final HashMap<String, CustomPlaceHandler> placeHandlerList = new HashMap<>();
+    private final CustomPlaceHandler defaultPlaceHandler = new DefaultPlaceHandler();
+
+    public boolean contains(String itemId) {
+        return placeHandlerList.containsKey(itemId);
+    }
+
+    public CustomPlaceHandler get(String itemId) {
+        if (!contains(itemId)) {
+            return defaultPlaceHandler;
+        }
+
+        return placeHandlerList.get(itemId);
+    }
+
+    public PlaceHandler() {
+        registerHandlers();
+    }
+
+    private void registerHandlers() {
+        Reflections reflections = new Reflections("cz.jzitnik.game.handlers.place.handlers");
+        Set<Class<?>> handlerClasses = reflections.getTypesAnnotatedWith(RegisterPlaceHandler.class);
+
+        for (Class<?> clazz : handlerClasses) {
+            if (CustomPlaceHandler.class.isAssignableFrom(clazz)) {
+                try {
+                    CustomPlaceHandler handlerInstance = (CustomPlaceHandler) clazz.getDeclaredConstructor().newInstance();
+                    RegisterPlaceHandler annotation = clazz.getAnnotation(RegisterPlaceHandler.class);
+                    placeHandlerList.put(annotation.value(), handlerInstance);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/handlers/place/handlers/DoorPlaceHandler.java b/src/main/java/cz/jzitnik/game/handlers/place/handlers/DoorPlaceHandler.java
new file mode 100644
index 0000000..cd1672a
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/handlers/place/handlers/DoorPlaceHandler.java
@@ -0,0 +1,93 @@
+package cz.jzitnik.game.handlers.place.handlers;
+
+import cz.jzitnik.game.Block;
+import cz.jzitnik.game.Game;
+import cz.jzitnik.game.annotations.RegisterPlaceHandler;
+import cz.jzitnik.game.handlers.place.CustomPlaceHandler;
+import cz.jzitnik.game.items.ItemBlockSupplier;
+import cz.jzitnik.game.sprites.OakDoor;
+import cz.jzitnik.tui.ScreenRenderer;
+
+@RegisterPlaceHandler("oak_door")
+public class DoorPlaceHandler implements CustomPlaceHandler {
+    public static void rightClick(Game game, int x, int y, ScreenRenderer screenRenderer) {
+        var blocks = game.getWorld()[y][x];
+        var door = blocks.stream().filter(block -> block.getBlockId().equals("oak_door")).toList().getFirst();
+
+
+        switch (door.getSpriteState().get()) {
+            case OakDoor.OakDoorState.TOP, OakDoor.OakDoorState.TOPCLOSED -> {
+                var blocks2 = game.getWorld()[y+1][x];
+                var door2 = blocks2.stream().filter(block -> block.getBlockId().equals("oak_door")).toList().getFirst();
+                change(door2);
+            }
+            case OakDoor.OakDoorState.BOTTOM, OakDoor.OakDoorState.BOTTOMCLOSED -> {
+                var blocks2 = game.getWorld()[y-1][x];
+                var door2 = blocks2.stream().filter(block -> block.getBlockId().equals("oak_door")).toList().getFirst();
+                change(door2);
+            }
+            default -> throw new IllegalStateException("Unexpected value: " + door.getSpriteState().get());
+        }
+
+        change(door);
+        game.update(screenRenderer);
+    }
+
+    private static void change(Block door) {
+        door.setSpriteState(switch (door.getSpriteState().get()) {
+            case OakDoor.OakDoorState.TOP -> OakDoor.OakDoorState.TOPCLOSED;
+            case OakDoor.OakDoorState.BOTTOM -> OakDoor.OakDoorState.BOTTOMCLOSED;
+            case OakDoor.OakDoorState.TOPCLOSED -> OakDoor.OakDoorState.TOP;
+            case OakDoor.OakDoorState.BOTTOMCLOSED -> OakDoor.OakDoorState.BOTTOM;
+            default -> throw new IllegalStateException("Unexpected value: " + door.getSpriteState().get());
+        });
+
+        door.setGhost(switch (door.getSpriteState().get()) {
+            case OakDoor.OakDoorState.TOP, OakDoor.OakDoorState.BOTTOM -> true;
+            case OakDoor.OakDoorState.TOPCLOSED, OakDoor.OakDoorState.BOTTOMCLOSED -> false;
+            default -> throw new IllegalStateException("Unexpected value: " + door.getSpriteState().get());
+        });
+    }
+
+    @Override
+    public boolean place(Game game, int x, int y) {
+        var blocks = game.getWorld()[y][x];
+        var blocksTop = game.getWorld()[y-1][x];
+
+        if (!blocksTop.stream().allMatch(Block::isGhost)) {
+            return false;
+        }
+
+        var inventory = game.getInventory();
+
+        Block block = inventory.getItemInHand().get().getBlock().get();
+        block.setSpriteState(OakDoor.OakDoorState.BOTTOMCLOSED);
+        blocks.add(block);
+
+        Block block2 = ItemBlockSupplier.Blocks.oakDoor();
+        block2.setSpriteState(OakDoor.OakDoorState.TOPCLOSED);
+        blocksTop.add(block2);
+
+        inventory.decreaseItemInHand();
+
+        return true;
+    }
+
+    @Override
+    public void mine(Game game, int x, int y) {
+        var blocks = game.getWorld()[y][x];
+        Block block = blocks.stream().filter(b -> b.getBlockId().equals("oak_door")).toList().getFirst();
+
+        if (block.getSpriteState().get() == OakDoor.OakDoorState.BOTTOM || block.getSpriteState().get() == OakDoor.OakDoorState.BOTTOMCLOSED) {
+            var blocks2 = game.getWorld()[y-1][x];
+            blocks2.removeAll(blocks2.stream().filter(i -> !i.getBlockId().equals("air")).toList());
+        }
+
+        if (block.getSpriteState().get() == OakDoor.OakDoorState.TOP || block.getSpriteState().get() == OakDoor.OakDoorState.TOPCLOSED) {
+            var blocks2 = game.getWorld()[y+1][x];
+            blocks2.removeAll(blocks2.stream().filter(i -> !i.getBlockId().equals("air")).toList());
+        }
+
+        blocks.removeAll(blocks.stream().filter(i -> !i.getBlockId().equals("air")).toList());
+    }
+}
diff --git a/src/main/java/cz/jzitnik/tui/RightClickHandler.java b/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandler.java
similarity index 74%
rename from src/main/java/cz/jzitnik/tui/RightClickHandler.java
rename to src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandler.java
index 1e24353..557f722 100644
--- a/src/main/java/cz/jzitnik/tui/RightClickHandler.java
+++ b/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandler.java
@@ -1,8 +1,10 @@
-package cz.jzitnik.tui;
+package cz.jzitnik.game.handlers.rightclick;
 
 import cz.jzitnik.game.Block;
 import cz.jzitnik.game.Game;
+import cz.jzitnik.game.handlers.place.handlers.DoorPlaceHandler;
 import cz.jzitnik.game.ui.Window;
+import cz.jzitnik.tui.ScreenRenderer;
 
 import java.util.HashMap;
 
@@ -12,7 +14,7 @@ public class RightClickHandler {
         void apply(T t, U u);
     }
 
-    public static void handle(int x, int y, Game game) {
+    public static void handle(int x, int y, Game game, ScreenRenderer screenRenderer) {
         if (game.isMining()) {
             return;
         }
@@ -21,6 +23,7 @@ public class RightClickHandler {
         functionMap.put("crafting_table", game.getGameStates().craftingTable::render);
         functionMap.put("chest", (Integer ignored, Integer ignored2) -> game.setWindow(Window.CHEST));
         functionMap.put("furnace", (Integer ignored, Integer ignored2) -> game.setWindow(Window.FURNACE));
+        functionMap.put("oak_door", (Integer xx, Integer xy) -> DoorPlaceHandler.rightClick(game, xx, xy, screenRenderer));
 
         game.getGameStates().clickX = x;
         game.getGameStates().clickY = y;
diff --git a/src/main/java/cz/jzitnik/game/items/ItemBlockSupplier.java b/src/main/java/cz/jzitnik/game/items/ItemBlockSupplier.java
index bc6ef14..b03aa33 100644
--- a/src/main/java/cz/jzitnik/game/items/ItemBlockSupplier.java
+++ b/src/main/java/cz/jzitnik/game/items/ItemBlockSupplier.java
@@ -36,6 +36,9 @@ public class ItemBlockSupplier {
         public static Item furnace(Block ref) {
             return new Item("furnace", "Furnace", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_FURNACE, ref);
         }
+        public static Item oakDoor(Block ref) {
+            return new Item("oak_door", "Oak door", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_OAK_DOOR, ref);
+        }
     }
 
     public static class Blocks {
@@ -85,6 +88,14 @@ public class ItemBlockSupplier {
             block.setDrops(List.of(Helper.furnace(block)));
             return block;
         }
+        public static Block coalOre() {
+            return new Block("coal_ore", SpriteLoader.SPRITES.COAL_ORE);
+        }
+        public static Block oakDoor() {
+            var block = new Block("oak_door", SpriteLoader.SPRITES.OAK_DOOR, 3, ItemType.AXE, new ArrayList<>());
+            block.setDrops(List.of(Helper.oakDoor(block)));
+            return block;
+        }
     }
 
     // I hate this but whatever
@@ -131,5 +142,8 @@ public class ItemBlockSupplier {
         public static Item furnace() {
             return Helper.furnace(Blocks.furnace());
         }
+        public static Item oakDoor() {
+            return Helper.oakDoor(Blocks.oakDoor());
+        }
     }
 }
diff --git a/src/main/java/cz/jzitnik/game/sprites/Heart.java b/src/main/java/cz/jzitnik/game/sprites/Heart.java
new file mode 100644
index 0000000..5b3ca49
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/sprites/Heart.java
@@ -0,0 +1,25 @@
+package cz.jzitnik.game.sprites;
+
+import cz.jzitnik.tui.ResourceLoader;
+import cz.jzitnik.tui.Sprite;
+
+public class Heart extends Sprite {
+    public enum HeartState {
+        OFF,
+        ON,
+    }
+
+    public String getSprite() {
+        throw new RuntimeException("Idk");
+    }
+
+    public String getSprite(Enum e) {
+        return ResourceLoader.loadResource(
+                switch (e) {
+                    case HeartState.OFF -> "gui/heartempty.ans";
+                    case HeartState.ON -> "gui/heartfull.ans";
+                    default -> throw new IllegalStateException("Unexpected value: " + e);
+                }
+        );
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/sprites/Hunger.java b/src/main/java/cz/jzitnik/game/sprites/Hunger.java
new file mode 100644
index 0000000..979e6c2
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/sprites/Hunger.java
@@ -0,0 +1,25 @@
+package cz.jzitnik.game.sprites;
+
+import cz.jzitnik.tui.ResourceLoader;
+import cz.jzitnik.tui.Sprite;
+
+public class Hunger extends Sprite {
+    public enum HungerState {
+        OFF,
+        ON,
+    }
+
+    public String getSprite() {
+        throw new RuntimeException("Idk");
+    }
+
+    public String getSprite(Enum e) {
+        return ResourceLoader.loadResource(
+                switch (e) {
+                    case HungerState.OFF -> "gui/hungerempty.ans";
+                    case HungerState.ON -> "gui/hungerfull.ans";
+                    default -> throw new IllegalStateException("Unexpected value: " + e);
+                }
+        );
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/sprites/OakDoor.java b/src/main/java/cz/jzitnik/game/sprites/OakDoor.java
new file mode 100644
index 0000000..aa948a5
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/sprites/OakDoor.java
@@ -0,0 +1,29 @@
+package cz.jzitnik.game.sprites;
+
+import cz.jzitnik.tui.ResourceLoader;
+import cz.jzitnik.tui.Sprite;
+
+public class OakDoor extends Sprite {
+    public enum OakDoorState {
+        TOP,
+        BOTTOM,
+        TOPCLOSED,
+        BOTTOMCLOSED
+    }
+
+    public String getSprite() {
+        return ResourceLoader.loadResource("oak_door/bottomclosed.ans");
+    }
+
+    public String getSprite(Enum e) {
+        return ResourceLoader.loadResource(
+                switch (e) {
+                    case OakDoorState.TOP -> "oak_door/top.ans";
+                    case OakDoorState.BOTTOM -> "oak_door/bottom.ans";
+                    case OakDoorState.TOPCLOSED -> "oak_door/topclosed.ans";
+                    case OakDoorState.BOTTOMCLOSED -> "oak_door/bottomclosed.ans";
+                    default -> throw new IllegalStateException("Unexpected value: " + e);
+                }
+        );
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/ui/Healthbar.java b/src/main/java/cz/jzitnik/game/ui/Healthbar.java
new file mode 100644
index 0000000..dcd8105
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/ui/Healthbar.java
@@ -0,0 +1,49 @@
+package cz.jzitnik.game.ui;
+
+import cz.jzitnik.game.Game;
+import cz.jzitnik.game.SpriteLoader;
+import cz.jzitnik.game.sprites.Heart;
+import cz.jzitnik.game.sprites.Hunger;
+import cz.jzitnik.tui.SpriteList;
+import org.jline.terminal.Terminal;
+
+import static cz.jzitnik.game.ui.Inventory.INVENTORY_SIZE_PX;
+
+public class Healthbar {
+    public static void render(StringBuilder buffer, SpriteList spriteList, Terminal terminal, Game game) {
+        int termWidth = terminal.getWidth();
+        int startLeft = (termWidth / 2) - (INVENTORY_SIZE_PX / 2);
+
+        int heartSize = 9 * 20;
+        int moveLeft = INVENTORY_SIZE_PX - (heartSize * 2);
+
+        String[] spriteOn = spriteList.getSprite(SpriteLoader.SPRITES.HEART).getSprite(Heart.HeartState.ON).split("\n");
+        String[] spriteOff = spriteList.getSprite(SpriteLoader.SPRITES.HEART).getSprite(Heart.HeartState.OFF).split("\n");
+
+        String[] hungerSpriteOn = spriteList.getSprite(SpriteLoader.SPRITES.HUNGER).getSprite(Hunger.HungerState.ON).split("\n");
+        String[] hungerSpriteOff = spriteList.getSprite(SpriteLoader.SPRITES.HUNGER).getSprite(Hunger.HungerState.OFF).split("\n");
+
+        for (int i = 0; i < 9; i++) {
+            buffer.append(" ".repeat(startLeft));
+            for (int j = 0; j < 10; j++) {
+                if (j < game.getPlayer().getHealth()) {
+                    buffer.append(spriteOn[i]);
+                } else {
+                    buffer.append(spriteOff[i]);
+                }
+            }
+
+            buffer.append("\033[0m").append(" ".repeat(moveLeft));
+            for (int j = 0; j < 10; j++) {
+                if ((10 - j) <= game.getPlayer().getHunger()) {
+                    buffer.append(hungerSpriteOn[i]);
+                } else {
+                    buffer.append(hungerSpriteOff[i]);
+                }
+            }
+
+            buffer.append("\n");
+        }
+        buffer.append("\n\n");
+    }
+}
diff --git a/src/main/java/cz/jzitnik/tui/ScreenMovingCalculationProvider.java b/src/main/java/cz/jzitnik/tui/ScreenMovingCalculationProvider.java
index 4e8f636..446976a 100644
--- a/src/main/java/cz/jzitnik/tui/ScreenMovingCalculationProvider.java
+++ b/src/main/java/cz/jzitnik/tui/ScreenMovingCalculationProvider.java
@@ -6,7 +6,7 @@ public class ScreenMovingCalculationProvider {
         int spriteHeight = 25;
 
         int viewXRadius = (terminalWidth / 2) / spriteWidth;
-        int viewYRadius = ((terminalHeight - 30) / 2) / spriteHeight;
+        int viewYRadius = ((terminalHeight - 30 - 9) / 2) / spriteHeight;
 
         // Ensure at least one sprite is visible
         viewXRadius = Math.max(viewXRadius, 1);
diff --git a/src/main/java/cz/jzitnik/tui/ScreenRenderer.java b/src/main/java/cz/jzitnik/tui/ScreenRenderer.java
index 6bdde91..7ed0015 100644
--- a/src/main/java/cz/jzitnik/tui/ScreenRenderer.java
+++ b/src/main/java/cz/jzitnik/tui/ScreenRenderer.java
@@ -5,6 +5,7 @@ import cz.jzitnik.game.Game;
 import cz.jzitnik.game.sprites.Steve;
 import cz.jzitnik.game.ui.Chest;
 import cz.jzitnik.game.ui.Furnace;
+import cz.jzitnik.game.ui.Healthbar;
 import cz.jzitnik.tui.utils.SpriteCombiner;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
@@ -141,6 +142,8 @@ public class ScreenRenderer {
                 // Empty space between world and hotbar
                 main.append("\n\n\n");
 
+                Healthbar.render(main, spriteList, terminal, game);
+
                 game.getInventory().renderHotbar(main, spriteList, terminal, false);
             }
         }
diff --git a/src/main/java/cz/jzitnik/tui/SpriteList.java b/src/main/java/cz/jzitnik/tui/SpriteList.java
index c482847..f788bdb 100644
--- a/src/main/java/cz/jzitnik/tui/SpriteList.java
+++ b/src/main/java/cz/jzitnik/tui/SpriteList.java
@@ -23,11 +23,4 @@ public class SpriteList<E extends Enum<E>> {
     public Sprite getSprite(E key) {
         return sprites.get(key);
     }
-
-    public void setSprite(E key, Sprite value) {
-        if (!sprites.containsKey(key)) {
-            throw new IllegalArgumentException("Invalid key: " + key);
-        }
-        sprites.put(key, value);
-    }
 }
diff --git a/src/main/resources/textures/coal_ore.ans b/src/main/resources/textures/coal_ore.ans
new file mode 100644
index 0000000..a1e1db3
--- /dev/null
+++ b/src/main/resources/textures/coal_ore.ans
@@ -0,0 +1,25 @@
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
diff --git a/src/main/resources/textures/gui/heartempty.ans b/src/main/resources/textures/gui/heartempty.ans
new file mode 100644
index 0000000..5233123
--- /dev/null
+++ b/src/main/resources/textures/gui/heartempty.ans
@@ -0,0 +1,9 @@
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
diff --git a/src/main/resources/textures/gui/heartfull.ans b/src/main/resources/textures/gui/heartfull.ans
new file mode 100644
index 0000000..6f4b7bd
--- /dev/null
+++ b/src/main/resources/textures/gui/heartfull.ans
@@ -0,0 +1,9 @@
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
diff --git a/src/main/resources/textures/gui/hungerempty.ans b/src/main/resources/textures/gui/hungerempty.ans
new file mode 100644
index 0000000..e1707ce
--- /dev/null
+++ b/src/main/resources/textures/gui/hungerempty.ans
@@ -0,0 +1,9 @@
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
diff --git a/src/main/resources/textures/gui/hungerfull.ans b/src/main/resources/textures/gui/hungerfull.ans
new file mode 100644
index 0000000..3d1e651
--- /dev/null
+++ b/src/main/resources/textures/gui/hungerfull.ans
@@ -0,0 +1,9 @@
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
+                  
diff --git a/src/main/resources/textures/items/wooden_axe.ans b/src/main/resources/textures/items/wooden_axe.ans
index ba5932a..7a1cbf6 100644
--- a/src/main/resources/textures/items/wooden_axe.ans
+++ b/src/main/resources/textures/items/wooden_axe.ans
@@ -1,26 +1,25 @@
-                                                  
-                                                  
-                            ▒                     
-                         ░░░░      ░░░            
-                            ░░░░░░░               
-                         ░░░░░░░░░░               
-                         ░░░░░░░░░░               
-                      ░░░░░░░░░░░░░   ░░░         
-                      ░░░░░░░░░░░░░░░░            
-                      ░░░░░░░░░░░░░░░░            
-                                ░░░░░░░░░         
-                            ░░░░   ░░░░░░         
-                            ░░░░   ░░░░░░         
-                         ░░░   ▒                  
-                   ▓▓▓░░░    ░░░   ░░░░░░         
-                      ░░░   ░                     
-                   ░░░                            
-                   ░░░                            
-                ░░░                               
-             ░░░                                  
-             ░░░                                  
-      ░   ░░░                                     
-      ░                                           
-      ░                                           
-                                                  
-
\ No newline at end of file
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
diff --git a/src/main/resources/textures/oak_door/bottom.ans b/src/main/resources/textures/oak_door/bottom.ans
new file mode 100644
index 0000000..e0f9573
--- /dev/null
+++ b/src/main/resources/textures/oak_door/bottom.ans
@@ -0,0 +1,25 @@
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
diff --git a/src/main/resources/textures/oak_door/bottomclosed.ans b/src/main/resources/textures/oak_door/bottomclosed.ans
new file mode 100644
index 0000000..1de16c8
--- /dev/null
+++ b/src/main/resources/textures/oak_door/bottomclosed.ans
@@ -0,0 +1,25 @@
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
diff --git a/src/main/resources/textures/oak_door/items/oak_door.ans b/src/main/resources/textures/oak_door/items/oak_door.ans
new file mode 100644
index 0000000..46d42cd
--- /dev/null
+++ b/src/main/resources/textures/oak_door/items/oak_door.ans
@@ -0,0 +1,25 @@
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
diff --git a/src/main/resources/textures/oak_door/top.ans b/src/main/resources/textures/oak_door/top.ans
new file mode 100644
index 0000000..b960535
--- /dev/null
+++ b/src/main/resources/textures/oak_door/top.ans
@@ -0,0 +1,25 @@
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
diff --git a/src/main/resources/textures/oak_door/topclosed.ans b/src/main/resources/textures/oak_door/topclosed.ans
new file mode 100644
index 0000000..02966ff
--- /dev/null
+++ b/src/main/resources/textures/oak_door/topclosed.ans
@@ -0,0 +1,25 @@
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+                                                  
+