diff --git a/pom.xml b/pom.xml
index e9111aa..58aeff5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,12 @@
             <artifactId>guava</artifactId>
             <version>31.1-jre</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.18.2</version>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/src/main/java/cz/jzitnik/Main.java b/src/main/java/cz/jzitnik/Main.java
index b0e4f23..e933c7c 100644
--- a/src/main/java/cz/jzitnik/Main.java
+++ b/src/main/java/cz/jzitnik/Main.java
@@ -1,6 +1,7 @@
 package cz.jzitnik;
 
 import cz.jzitnik.game.Game;
+import cz.jzitnik.game.mobs.EntityLogicProvider;
 import cz.jzitnik.game.threads.HealthRegenerationThread;
 import cz.jzitnik.game.threads.HungerDrainThread;
 import cz.jzitnik.game.threads.InputHandlerThread;
@@ -33,16 +34,18 @@ public class Main {
             Thread inputHandlerThread = new InputHandlerThread(game, terminal, screenRenderer, isRunning);
             Thread healingThread = new HealthRegenerationThread(game.getPlayer());
             Thread hungerDrainThread = new HungerDrainThread(game.getPlayer());
+            EntityLogicProvider entityLogicProvider = new EntityLogicProvider();
 
+            // Start all threads
             healingThread.start();
             hungerDrainThread.start();
             inputHandlerThread.start();
 
-
             while (isRunning[0]) {
                 if (game.getWindow() == Window.WORLD) {
                     screenRenderer.render(game);
                 }
+                entityLogicProvider.update(game);
 
                 Thread.sleep(1000);
             }
diff --git a/src/main/java/cz/jzitnik/game/Game.java b/src/main/java/cz/jzitnik/game/Game.java
index aa028d3..adc380a 100644
--- a/src/main/java/cz/jzitnik/game/Game.java
+++ b/src/main/java/cz/jzitnik/game/Game.java
@@ -1,16 +1,21 @@
 package cz.jzitnik.game;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import cz.jzitnik.game.entities.Block;
+import cz.jzitnik.game.entities.GameStates;
+import cz.jzitnik.game.entities.Player;
 import cz.jzitnik.game.generation.Generation;
-import cz.jzitnik.game.items.Item;
-import cz.jzitnik.game.items.ItemType;
+import cz.jzitnik.game.entities.items.Item;
+import cz.jzitnik.game.entities.items.ItemType;
 import cz.jzitnik.game.handlers.place.CustomPlaceHandler;
+import cz.jzitnik.game.mobs.EntitySpawnProvider;
 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.blocks.Chest;
+import cz.jzitnik.game.blocks.Furnace;
 import cz.jzitnik.game.ui.Window;
 import cz.jzitnik.game.ui.Inventory;
-import cz.jzitnik.game.handlers.rightclick.RightClickHandler;
+import cz.jzitnik.game.handlers.rightclick.RightClickHandlerProvider;
 import cz.jzitnik.tui.ScreenMovingCalculationProvider;
 import cz.jzitnik.tui.ScreenRenderer;
 import lombok.Getter;
@@ -28,12 +33,14 @@ public class Game {
     private boolean mining = false;
     @Setter
     private Window window = Window.WORLD;
-
-    //jsonignore
-    private final GameStates gameStates = new GameStates(this);
-
     private final Inventory inventory = new Inventory();
 
+    @JsonIgnore
+    private final EntitySpawnProvider entitySpawnProvider = new EntitySpawnProvider();
+
+    @JsonIgnore
+    private final GameStates gameStates = new GameStates(this);
+
     public Game() {
         Generation.generateWorld(this);
     }
@@ -51,13 +58,13 @@ public class Game {
         return null;
     }
 
-    public void movePlayerRight(ScreenRenderer screenRenderer) {
+    public void movePlayerRight(ScreenRenderer screenRenderer, Terminal terminal) {
         if (window != Window.WORLD) {
             return;
         }
         int[] cords = getPlayerCords();
 
-        if (world[cords[1]][cords[0] + 1].stream().anyMatch(block -> !block.isGhost()) || world[cords[1] - 1][cords[0] + 1].stream().anyMatch(block -> !block.isGhost())) {
+        if (isSolid(world[cords[1]][cords[0] + 1]) || isSolid(world[cords[1] - 1][cords[0] + 1])) {
             return;
         }
 
@@ -67,16 +74,18 @@ public class Game {
         world[cords[1]-1][cords[0]].remove(player.getPlayerBlock1());
         screenRenderer.render(this);
 
+        entitySpawnProvider.update(this, terminal);
+
         update(screenRenderer);
     }
 
-    public void movePlayerLeft(ScreenRenderer screenRenderer) {
+    public void movePlayerLeft(ScreenRenderer screenRenderer, Terminal terminal) {
         if (window != Window.WORLD) {
             return;
         }
         int[] cords = getPlayerCords();
 
-        if (world[cords[1]][cords[0] - 1].stream().anyMatch(block -> !block.isGhost()) || world[cords[1] - 1][cords[0] - 1].stream().anyMatch(block -> !block.isGhost())) {
+        if (isSolid(world[cords[1]][cords[0] - 1]) || isSolid(world[cords[1] - 1][cords[0] - 1])) {
             return;
         }
 
@@ -86,6 +95,8 @@ public class Game {
         world[cords[1]-1][cords[0]].remove(player.getPlayerBlock1());
         screenRenderer.render(this);
 
+        entitySpawnProvider.update(this, terminal);
+
         update(screenRenderer);
     }
 
@@ -95,7 +106,7 @@ 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().allMatch(Block::isGhost)) {
+        if (isSolid(world[cords[1] - 2][cords[0]]) || !isSolid(world[cords[1] + 1][cords[0]])) {
             return;
         }
 
@@ -106,20 +117,12 @@ public class Game {
 
         new Thread(() -> {
             try {
-                Thread.sleep(500);
+                Thread.sleep(400);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
-            int[] cords2 = getPlayerCords();
 
-            if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) {
-                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);
-            }
+            update(screenRenderer);
         }).start();
     }
 
@@ -233,7 +236,7 @@ public class Game {
             }
             int[] cords2 = getPlayerCords();
 
-            if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) {
+            if (!isSolid(world[cords2[1] + 1][cords2[0]])) {
                 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());
@@ -268,7 +271,7 @@ public class Game {
         }
 
         if (!blocks.stream().allMatch(block -> block.getBlockId().equals("air"))) {
-            RightClickHandler.handle(x, y, this, screenRenderer);
+            RightClickHandlerProvider.handle(x, y, this, screenRenderer);
             screenRenderer.render(this);
             return;
         }
@@ -293,4 +296,8 @@ public class Game {
         inventory.setItemInhHandIndex(slot);
         screenRenderer.render(this);
     }
+
+    public boolean isSolid(List<Block> blocks) {
+        return !blocks.stream().allMatch(Block::isGhost);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/cz/jzitnik/game/annotations/RegisterPlaceHandler.java b/src/main/java/cz/jzitnik/game/annotations/EntityLogic.java
similarity index 87%
rename from src/main/java/cz/jzitnik/game/annotations/RegisterPlaceHandler.java
rename to src/main/java/cz/jzitnik/game/annotations/EntityLogic.java
index d9cc272..3775c60 100644
--- a/src/main/java/cz/jzitnik/game/annotations/RegisterPlaceHandler.java
+++ b/src/main/java/cz/jzitnik/game/annotations/EntityLogic.java
@@ -5,8 +5,8 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.lang.annotation.ElementType;
 
-@Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
-public @interface RegisterPlaceHandler {
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EntityLogic {
     String value();
 }
diff --git a/src/main/java/cz/jzitnik/game/annotations/EntitySpawn.java b/src/main/java/cz/jzitnik/game/annotations/EntitySpawn.java
new file mode 100644
index 0000000..1d9c4d6
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/annotations/EntitySpawn.java
@@ -0,0 +1,11 @@
+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;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EntitySpawn {
+}
diff --git a/src/main/java/cz/jzitnik/game/annotations/PlaceHandler.java b/src/main/java/cz/jzitnik/game/annotations/PlaceHandler.java
new file mode 100644
index 0000000..2c61b9f
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/annotations/PlaceHandler.java
@@ -0,0 +1,13 @@
+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 PlaceHandler {
+    String value();
+}
diff --git a/src/main/java/cz/jzitnik/game/annotations/RightClickLogic.java b/src/main/java/cz/jzitnik/game/annotations/RightClickLogic.java
new file mode 100644
index 0000000..22cbaac
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/annotations/RightClickLogic.java
@@ -0,0 +1,11 @@
+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;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RightClickLogic {
+}
diff --git a/src/main/java/cz/jzitnik/game/ui/Chest.java b/src/main/java/cz/jzitnik/game/blocks/Chest.java
similarity index 87%
rename from src/main/java/cz/jzitnik/game/ui/Chest.java
rename to src/main/java/cz/jzitnik/game/blocks/Chest.java
index c21e01d..dfb2d7c 100644
--- a/src/main/java/cz/jzitnik/game/ui/Chest.java
+++ b/src/main/java/cz/jzitnik/game/blocks/Chest.java
@@ -1,7 +1,11 @@
-package cz.jzitnik.game.ui;
+package cz.jzitnik.game.blocks;
 
 import cz.jzitnik.game.Game;
-import cz.jzitnik.game.items.InventoryItem;
+import cz.jzitnik.game.annotations.RightClickLogic;
+import cz.jzitnik.game.entities.items.InventoryItem;
+import cz.jzitnik.game.handlers.rightclick.RightClickHandler;
+import cz.jzitnik.game.ui.InventoryClickHandler;
+import cz.jzitnik.game.ui.Window;
 import cz.jzitnik.tui.ScreenRenderer;
 import cz.jzitnik.tui.SpriteList;
 import org.jline.terminal.MouseEvent;
@@ -10,7 +14,8 @@ import org.jline.terminal.Terminal;
 import java.util.List;
 import java.util.Optional;
 
-public class Chest {
+@RightClickLogic
+public class Chest implements RightClickHandler {
     private static final int ROW_AMOUNT = 4;
     private static final int COLUMN_AMOUNT = 6;
     private static final int CELL_WIDTH = 50;
@@ -91,4 +96,9 @@ public class Chest {
             items[i] = null;
         }
     }
+
+    @Override
+    public void onBlockRightClick(int ignored, int ignored2, Game game, ScreenRenderer ignored4) {
+        game.setWindow(Window.CHEST);
+    }
 }
diff --git a/src/main/java/cz/jzitnik/game/ui/Furnace.java b/src/main/java/cz/jzitnik/game/blocks/Furnace.java
similarity index 94%
rename from src/main/java/cz/jzitnik/game/ui/Furnace.java
rename to src/main/java/cz/jzitnik/game/blocks/Furnace.java
index b218fe5..8d941be 100644
--- a/src/main/java/cz/jzitnik/game/ui/Furnace.java
+++ b/src/main/java/cz/jzitnik/game/blocks/Furnace.java
@@ -1,10 +1,14 @@
-package cz.jzitnik.game.ui;
+package cz.jzitnik.game.blocks;
 
-import cz.jzitnik.game.Block;
+import cz.jzitnik.game.annotations.RightClickLogic;
+import cz.jzitnik.game.entities.Block;
 import cz.jzitnik.game.Game;
-import cz.jzitnik.game.items.InventoryItem;
-import cz.jzitnik.game.items.Item;
+import cz.jzitnik.game.entities.items.InventoryItem;
+import cz.jzitnik.game.entities.items.Item;
+import cz.jzitnik.game.handlers.rightclick.RightClickHandler;
 import cz.jzitnik.game.smelting.Smelting;
+import cz.jzitnik.game.ui.InventoryClickHandler;
+import cz.jzitnik.game.ui.Window;
 import cz.jzitnik.tui.ScreenRenderer;
 import cz.jzitnik.tui.SpriteList;
 import cz.jzitnik.tui.utils.Numbers;
@@ -15,7 +19,8 @@ import org.jline.terminal.Terminal;
 import java.util.List;
 import java.util.Optional;
 
-public class Furnace {
+@RightClickLogic
+public class Furnace implements RightClickHandler {
     private final Block block;
     private final InventoryItem[] items = new InventoryItem[2];
     private InventoryItem outputItem;
@@ -254,4 +259,9 @@ public class Furnace {
 
         setSmelting(false);
     }
+
+    @Override
+    public void onBlockRightClick(int ignored, int ignored2, Game game, ScreenRenderer ignored3) {
+        game.setWindow(Window.FURNACE);
+    }
 }
diff --git a/src/main/java/cz/jzitnik/game/blocks/OakDoorData.java b/src/main/java/cz/jzitnik/game/blocks/OakDoorData.java
new file mode 100644
index 0000000..d9683d5
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/blocks/OakDoorData.java
@@ -0,0 +1,51 @@
+package cz.jzitnik.game.blocks;
+
+import cz.jzitnik.game.Game;
+import cz.jzitnik.game.annotations.RightClickLogic;
+import cz.jzitnik.game.entities.Block;
+import cz.jzitnik.game.handlers.rightclick.RightClickHandler;
+import cz.jzitnik.game.sprites.OakDoor;
+
+import cz.jzitnik.tui.ScreenRenderer;
+
+@RightClickLogic
+public class OakDoorData implements RightClickHandler {
+    private 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());
+        });
+    }
+
+    public void onBlockRightClick(int x, int y, Game game, 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);
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/crafting/CraftingRecipe.java b/src/main/java/cz/jzitnik/game/crafting/CraftingRecipe.java
index f74c4ad..39d138f 100644
--- a/src/main/java/cz/jzitnik/game/crafting/CraftingRecipe.java
+++ b/src/main/java/cz/jzitnik/game/crafting/CraftingRecipe.java
@@ -1,6 +1,6 @@
 package cz.jzitnik.game.crafting;
 
-import cz.jzitnik.game.items.InventoryItem;
+import cz.jzitnik.game.entities.items.InventoryItem;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
diff --git a/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java b/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java
index f03a109..6c3c280 100644
--- a/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java
+++ b/src/main/java/cz/jzitnik/game/crafting/CraftingRecipeList.java
@@ -1,7 +1,7 @@
 package cz.jzitnik.game.crafting;
 
-import cz.jzitnik.game.items.InventoryItem;
-import cz.jzitnik.game.items.ItemBlockSupplier;
+import cz.jzitnik.game.entities.items.InventoryItem;
+import cz.jzitnik.game.entities.items.ItemBlockSupplier;
 
 import java.util.*;
 
diff --git a/src/main/java/cz/jzitnik/game/Block.java b/src/main/java/cz/jzitnik/game/entities/Block.java
similarity index 90%
rename from src/main/java/cz/jzitnik/game/Block.java
rename to src/main/java/cz/jzitnik/game/entities/Block.java
index 713f5ba..e655840 100644
--- a/src/main/java/cz/jzitnik/game/Block.java
+++ b/src/main/java/cz/jzitnik/game/entities/Block.java
@@ -1,8 +1,9 @@
-package cz.jzitnik.game;
+package cz.jzitnik.game.entities;
 
-import cz.jzitnik.game.items.Item;
-import cz.jzitnik.game.items.ItemType;
-import cz.jzitnik.game.items.ToolVariant;
+import cz.jzitnik.game.SpriteLoader;
+import cz.jzitnik.game.entities.items.Item;
+import cz.jzitnik.game.entities.items.ItemType;
+import cz.jzitnik.game.entities.items.ToolVariant;
 import cz.jzitnik.game.ui.Inventory;
 import lombok.Getter;
 import lombok.Setter;
@@ -24,6 +25,7 @@ public class Block {
     private List<ToolVariant> toolVariants = new ArrayList<>();
     private List<Item> drops = new ArrayList<>();
     private Object data = null;
+    private boolean isMob = false;
 
     public Block(String blockId, SpriteLoader.SPRITES sprite) {
         this.blockId = blockId;
diff --git a/src/main/java/cz/jzitnik/game/Dependencies.java b/src/main/java/cz/jzitnik/game/entities/Dependencies.java
similarity index 80%
rename from src/main/java/cz/jzitnik/game/Dependencies.java
rename to src/main/java/cz/jzitnik/game/entities/Dependencies.java
index 62e6837..c0a34ad 100644
--- a/src/main/java/cz/jzitnik/game/Dependencies.java
+++ b/src/main/java/cz/jzitnik/game/entities/Dependencies.java
@@ -1,4 +1,4 @@
-package cz.jzitnik.game;
+package cz.jzitnik.game.entities;
 
 import cz.jzitnik.game.handlers.place.PlaceHandler;
 
diff --git a/src/main/java/cz/jzitnik/game/GameStates.java b/src/main/java/cz/jzitnik/game/entities/GameStates.java
similarity index 84%
rename from src/main/java/cz/jzitnik/game/GameStates.java
rename to src/main/java/cz/jzitnik/game/entities/GameStates.java
index b10d2b1..c3367da 100644
--- a/src/main/java/cz/jzitnik/game/GameStates.java
+++ b/src/main/java/cz/jzitnik/game/entities/GameStates.java
@@ -1,5 +1,6 @@
-package cz.jzitnik.game;
+package cz.jzitnik.game.entities;
 
+import cz.jzitnik.game.Game;
 import cz.jzitnik.game.ui.CraftingTable;
 
 public class GameStates {
diff --git a/src/main/java/cz/jzitnik/game/Player.java b/src/main/java/cz/jzitnik/game/entities/Player.java
similarity index 95%
rename from src/main/java/cz/jzitnik/game/Player.java
rename to src/main/java/cz/jzitnik/game/entities/Player.java
index 7958b95..5a61710 100644
--- a/src/main/java/cz/jzitnik/game/Player.java
+++ b/src/main/java/cz/jzitnik/game/entities/Player.java
@@ -1,4 +1,4 @@
-package cz.jzitnik.game;
+package cz.jzitnik.game.entities;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/src/main/java/cz/jzitnik/game/items/InventoryItem.java b/src/main/java/cz/jzitnik/game/entities/items/InventoryItem.java
similarity index 95%
rename from src/main/java/cz/jzitnik/game/items/InventoryItem.java
rename to src/main/java/cz/jzitnik/game/entities/items/InventoryItem.java
index 80fe605..44d59fa 100644
--- a/src/main/java/cz/jzitnik/game/items/InventoryItem.java
+++ b/src/main/java/cz/jzitnik/game/entities/items/InventoryItem.java
@@ -1,4 +1,4 @@
-package cz.jzitnik.game.items;
+package cz.jzitnik.game.entities.items;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;
diff --git a/src/main/java/cz/jzitnik/game/items/Item.java b/src/main/java/cz/jzitnik/game/entities/items/Item.java
similarity index 95%
rename from src/main/java/cz/jzitnik/game/items/Item.java
rename to src/main/java/cz/jzitnik/game/entities/items/Item.java
index 8cb9834..9fe1f50 100644
--- a/src/main/java/cz/jzitnik/game/items/Item.java
+++ b/src/main/java/cz/jzitnik/game/entities/items/Item.java
@@ -1,6 +1,6 @@
-package cz.jzitnik.game.items;
+package cz.jzitnik.game.entities.items;
 
-import cz.jzitnik.game.Block;
+import cz.jzitnik.game.entities.Block;
 import cz.jzitnik.game.SpriteLoader;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
diff --git a/src/main/java/cz/jzitnik/game/items/ItemBlockSupplier.java b/src/main/java/cz/jzitnik/game/entities/items/ItemBlockSupplier.java
similarity index 91%
rename from src/main/java/cz/jzitnik/game/items/ItemBlockSupplier.java
rename to src/main/java/cz/jzitnik/game/entities/items/ItemBlockSupplier.java
index b03aa33..6f82d46 100644
--- a/src/main/java/cz/jzitnik/game/items/ItemBlockSupplier.java
+++ b/src/main/java/cz/jzitnik/game/entities/items/ItemBlockSupplier.java
@@ -1,9 +1,11 @@
-package cz.jzitnik.game.items;
+package cz.jzitnik.game.entities.items;
 
 import cz.jzitnik.game.SpriteLoader;
-import cz.jzitnik.game.Block;
-import cz.jzitnik.game.ui.Chest;
-import cz.jzitnik.game.ui.Furnace;
+import cz.jzitnik.game.blocks.OakDoorData;
+import cz.jzitnik.game.entities.Block;
+import cz.jzitnik.game.blocks.Chest;
+import cz.jzitnik.game.blocks.Furnace;
+import cz.jzitnik.game.mobs.services.pig.PigData;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -93,6 +95,7 @@ public class ItemBlockSupplier {
         }
         public static Block oakDoor() {
             var block = new Block("oak_door", SpriteLoader.SPRITES.OAK_DOOR, 3, ItemType.AXE, new ArrayList<>());
+            block.setData(new OakDoorData());
             block.setDrops(List.of(Helper.oakDoor(block)));
             return block;
         }
@@ -146,4 +149,16 @@ public class ItemBlockSupplier {
             return Helper.oakDoor(Blocks.oakDoor());
         }
     }
+
+    public static class Mobs {
+        public static Block pig() {
+            // Yes, pig is a block. Cry about it.
+            var block = new Block("pig", SpriteLoader.SPRITES.PIG);
+            block.setMob(true);
+            block.setGhost(true);
+            block.setMineable(false);
+            block.setData(new PigData());
+            return block;
+        }
+    }
 }
diff --git a/src/main/java/cz/jzitnik/game/items/ItemType.java b/src/main/java/cz/jzitnik/game/entities/items/ItemType.java
similarity index 71%
rename from src/main/java/cz/jzitnik/game/items/ItemType.java
rename to src/main/java/cz/jzitnik/game/entities/items/ItemType.java
index 007de75..d8cde61 100644
--- a/src/main/java/cz/jzitnik/game/items/ItemType.java
+++ b/src/main/java/cz/jzitnik/game/entities/items/ItemType.java
@@ -1,4 +1,4 @@
-package cz.jzitnik.game.items;
+package cz.jzitnik.game.entities.items;
 
 public enum ItemType {
     PICKAXE,
diff --git a/src/main/java/cz/jzitnik/game/items/ToolVariant.java b/src/main/java/cz/jzitnik/game/entities/items/ToolVariant.java
similarity index 60%
rename from src/main/java/cz/jzitnik/game/items/ToolVariant.java
rename to src/main/java/cz/jzitnik/game/entities/items/ToolVariant.java
index 8ee5c8b..6a9edf7 100644
--- a/src/main/java/cz/jzitnik/game/items/ToolVariant.java
+++ b/src/main/java/cz/jzitnik/game/entities/items/ToolVariant.java
@@ -1,4 +1,4 @@
-package cz.jzitnik.game.items;
+package cz.jzitnik.game.entities.items;
 
 public enum ToolVariant {
     WOODEN,
diff --git a/src/main/java/cz/jzitnik/game/generation/CaveGenerator.java b/src/main/java/cz/jzitnik/game/generation/CaveGenerator.java
deleted file mode 100644
index a27c98f..0000000
--- a/src/main/java/cz/jzitnik/game/generation/CaveGenerator.java
+++ /dev/null
@@ -1,12 +0,0 @@
-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/Generation.java b/src/main/java/cz/jzitnik/game/generation/Generation.java
index 7798e79..965b77a 100644
--- a/src/main/java/cz/jzitnik/game/generation/Generation.java
+++ b/src/main/java/cz/jzitnik/game/generation/Generation.java
@@ -1,10 +1,10 @@
 package cz.jzitnik.game.generation;
 
-import cz.jzitnik.game.Block;
+import cz.jzitnik.game.entities.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.entities.items.ItemBlockSupplier;
+import cz.jzitnik.game.entities.items.ItemType;
 import cz.jzitnik.game.sprites.Steve;
 
 import java.util.ArrayList;
@@ -18,13 +18,16 @@ public class Generation {
 
         Block steveBlock = new Block("steve", SpriteLoader.SPRITES.STEVE);
         steveBlock.setSpriteState(Steve.SteveState.FIRST);
+        steveBlock.setGhost(true);
         Block steveBlock2 = new Block("steve", SpriteLoader.SPRITES.STEVE);
         steveBlock2.setSpriteState(Steve.SteveState.SECOND);
+        steveBlock2.setGhost(true);
+
+        int[] terrainHeight = generateTerrain();
 
         game.getPlayer().setPlayerBlock1(steveBlock);
         game.getPlayer().setPlayerBlock2(steveBlock2);
 
-        int[] terrainHeight = generateTerrain();
         populateWorld(world, terrainHeight);
         plantTrees(world, terrainHeight);
 
diff --git a/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java b/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java
index 6c5d650..88db7d9 100644
--- a/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java
+++ b/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java
@@ -3,7 +3,6 @@ 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 {
@@ -28,13 +27,13 @@ public class PlaceHandler {
 
     private void registerHandlers() {
         Reflections reflections = new Reflections("cz.jzitnik.game.handlers.place.handlers");
-        Set<Class<?>> handlerClasses = reflections.getTypesAnnotatedWith(RegisterPlaceHandler.class);
+        Set<Class<?>> handlerClasses = reflections.getTypesAnnotatedWith(cz.jzitnik.game.annotations.PlaceHandler.class);
 
         for (Class<?> clazz : handlerClasses) {
             if (CustomPlaceHandler.class.isAssignableFrom(clazz)) {
                 try {
                     CustomPlaceHandler handlerInstance = (CustomPlaceHandler) clazz.getDeclaredConstructor().newInstance();
-                    RegisterPlaceHandler annotation = clazz.getAnnotation(RegisterPlaceHandler.class);
+                    cz.jzitnik.game.annotations.PlaceHandler annotation = clazz.getAnnotation(cz.jzitnik.game.annotations.PlaceHandler.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
index cd1672a..298ac8c 100644
--- a/src/main/java/cz/jzitnik/game/handlers/place/handlers/DoorPlaceHandler.java
+++ b/src/main/java/cz/jzitnik/game/handlers/place/handlers/DoorPlaceHandler.java
@@ -1,54 +1,14 @@
 package cz.jzitnik.game.handlers.place.handlers;
 
-import cz.jzitnik.game.Block;
+import cz.jzitnik.game.annotations.PlaceHandler;
+import cz.jzitnik.game.entities.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.entities.items.ItemBlockSupplier;
 import cz.jzitnik.game.sprites.OakDoor;
-import cz.jzitnik.tui.ScreenRenderer;
 
-@RegisterPlaceHandler("oak_door")
+@PlaceHandler("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];
diff --git a/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandler.java b/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandler.java
index 557f722..8769690 100644
--- a/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandler.java
+++ b/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandler.java
@@ -1,40 +1,8 @@
 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;
-
-public class RightClickHandler {
-    @FunctionalInterface
-    public interface Function3<T, U> {
-        void apply(T t, U u);
-    }
-
-    public static void handle(int x, int y, Game game, ScreenRenderer screenRenderer) {
-        if (game.isMining()) {
-            return;
-        }
-
-        HashMap<String, Function3<Integer, Integer>> functionMap = new HashMap<>();
-        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;
-
-        var blocks = game.getWorld()[y][x];
-        for (Block block : blocks) {
-            if (functionMap.containsKey(block.getBlockId())) {
-                functionMap.get(block.getBlockId()).apply(x, y);
-
-                return;
-            }
-        }
-    }
+public interface RightClickHandler {
+    void onBlockRightClick(int x, int y, Game game, ScreenRenderer screenRenderer);
 }
diff --git a/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandlerProvider.java b/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandlerProvider.java
new file mode 100644
index 0000000..2fe0f55
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/handlers/rightclick/RightClickHandlerProvider.java
@@ -0,0 +1,29 @@
+package cz.jzitnik.game.handlers.rightclick;
+
+import cz.jzitnik.game.annotations.RightClickLogic;
+import cz.jzitnik.game.entities.Block;
+import cz.jzitnik.game.Game;
+import cz.jzitnik.tui.ScreenRenderer;
+
+public class RightClickHandlerProvider {
+    public static void handle(int x, int y, Game game, ScreenRenderer screenRenderer) {
+        if (game.isMining()) {
+            return;
+        }
+
+        game.getGameStates().clickX = x;
+        game.getGameStates().clickY = y;
+
+        var blocks = game.getWorld()[y][x];
+        for (Block block : blocks) {
+            if (block.getBlockId().equalsIgnoreCase("crafting_table")) {
+                game.getGameStates().craftingTable.render(x, y);
+                continue;
+            }
+
+            if (block.getData() != null && block.getData().getClass().isAnnotationPresent(RightClickLogic.class) && block.getData() instanceof RightClickHandler handlerClass) {
+                handlerClass.onBlockRightClick(x, y, game, screenRenderer);
+            }
+        }
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/mobs/EntityLogicInterface.java b/src/main/java/cz/jzitnik/game/mobs/EntityLogicInterface.java
new file mode 100644
index 0000000..2ee5597
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/mobs/EntityLogicInterface.java
@@ -0,0 +1,5 @@
+package cz.jzitnik.game.mobs;
+
+public interface EntityLogicInterface {
+    void nextIteration(EntityLogicProvider.EntityLogicMobDTO entityLogicMobDTO);
+}
diff --git a/src/main/java/cz/jzitnik/game/mobs/EntityLogicProvider.java b/src/main/java/cz/jzitnik/game/mobs/EntityLogicProvider.java
new file mode 100644
index 0000000..3c334cc
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/mobs/EntityLogicProvider.java
@@ -0,0 +1,82 @@
+package cz.jzitnik.game.mobs;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import cz.jzitnik.game.Game;
+import cz.jzitnik.game.annotations.EntityLogic;
+import cz.jzitnik.game.entities.Block;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.reflections.Reflections;
+
+public class EntityLogicProvider {
+    private static final int CHUNK_SIZE = 20;
+    private final HashMap<String, EntityLogicInterface> logicList = new HashMap<>();
+
+    @AllArgsConstructor
+    @Getter
+    public static class EntityLogicMobDTO {
+        private Game game;
+        private Block mob;
+        private int x;
+        private int y;
+    }
+
+    public void update(Game game) {
+        int[] playerLocation = game.getPlayerCords();
+        int playerX = playerLocation[0];
+        int playerY = playerLocation[1];
+
+        int startX = Math.max(0, playerX - CHUNK_SIZE);
+        int startY = Math.max(0, playerY - CHUNK_SIZE);
+        int endX = Math.min(game.getWorld()[0].length, playerX + CHUNK_SIZE);
+        int endY = Math.min(game.getWorld().length, playerY + CHUNK_SIZE);
+
+        List<EntityLogicMobDTO> mobs = new ArrayList<>();
+
+        for (int y = startY; y <= endY; y++) {
+            for (int x = startX; x <= endX; x++) {
+                int finalX = x;
+                int finalY = y;
+                List<EntityLogicMobDTO> blockMobs = game.getWorld()[y][x].stream().filter(Block::isMob).map(mob -> new EntityLogicMobDTO(game, mob, finalX, finalY)).toList();
+                mobs.addAll(blockMobs);
+            }
+        }
+
+        for (EntityLogicMobDTO entityLogicMobDTO : mobs) {
+            run(entityLogicMobDTO);
+        }
+    }
+
+    private void run(EntityLogicMobDTO entityLogicMobDTO) {
+        if (!logicList.containsKey(entityLogicMobDTO.getMob().getBlockId())) {
+            return;
+        }
+
+        logicList.get(entityLogicMobDTO.getMob().getBlockId()).nextIteration(entityLogicMobDTO);
+    }
+
+    public EntityLogicProvider() {
+        registerHandlers();
+    }
+
+    private void registerHandlers() {
+        Reflections reflections = new Reflections("cz.jzitnik.game.mobs.services");
+        Set<Class<?>> handlerClasses = reflections.getTypesAnnotatedWith(EntityLogic.class);
+
+        for (Class<?> clazz : handlerClasses) {
+            if (EntityLogicInterface.class.isAssignableFrom(clazz)) {
+                try {
+                    EntityLogicInterface instance = (EntityLogicInterface) clazz.getDeclaredConstructor().newInstance();
+                    EntityLogic annotation = clazz.getAnnotation(EntityLogic.class);
+                    logicList.put(annotation.value(), instance);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/mobs/EntitySpawnInterface.java b/src/main/java/cz/jzitnik/game/mobs/EntitySpawnInterface.java
new file mode 100644
index 0000000..0b6b003
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/mobs/EntitySpawnInterface.java
@@ -0,0 +1,8 @@
+package cz.jzitnik.game.mobs;
+
+import cz.jzitnik.game.Game;
+import org.jline.terminal.Terminal;
+
+public interface EntitySpawnInterface {
+    void spawn(int playerX, int playerY, Game game, Terminal terminal);
+}
diff --git a/src/main/java/cz/jzitnik/game/mobs/EntitySpawnProvider.java b/src/main/java/cz/jzitnik/game/mobs/EntitySpawnProvider.java
new file mode 100644
index 0000000..9b00369
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/mobs/EntitySpawnProvider.java
@@ -0,0 +1,57 @@
+package cz.jzitnik.game.mobs;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import cz.jzitnik.game.Game;
+import cz.jzitnik.game.annotations.EntitySpawn;
+import cz.jzitnik.game.entities.Block;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.jline.terminal.Terminal;
+import org.reflections.Reflections;
+
+public class EntitySpawnProvider {
+    private final List<EntitySpawnInterface> spawnList = new ArrayList<>();
+
+    @AllArgsConstructor
+    @Getter
+    public static class EntityLogicMobDTO {
+        private Game game;
+        private Block mob;
+        private int x;
+        private int y;
+    }
+
+    public void update(Game game, Terminal terminal) {
+        int[] playerLocation = game.getPlayerCords();
+        int playerX = playerLocation[0];
+        int playerY = playerLocation[1];
+
+        for (EntitySpawnInterface entitySpawnInterface: spawnList) {
+
+            entitySpawnInterface.spawn(playerX, playerY, game, terminal);
+        }
+    }
+
+    public EntitySpawnProvider() {
+        registerHandlers();
+    }
+
+    private void registerHandlers() {
+        Reflections reflections = new Reflections("cz.jzitnik.game.mobs.services");
+        Set<Class<?>> handlerClasses = reflections.getTypesAnnotatedWith(EntitySpawn.class);
+
+        for (Class<?> clazz : handlerClasses) {
+            if (EntitySpawnInterface.class.isAssignableFrom(clazz)) {
+                try {
+                    EntitySpawnInterface instance = (EntitySpawnInterface) clazz.getDeclaredConstructor().newInstance();
+                    spawnList.add(instance);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/mobs/services/pig/PigData.java b/src/main/java/cz/jzitnik/game/mobs/services/pig/PigData.java
new file mode 100644
index 0000000..8f95ab7
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/mobs/services/pig/PigData.java
@@ -0,0 +1,12 @@
+package cz.jzitnik.game.mobs.services.pig;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class PigData {
+    private int lastDirection = 1; // 1 = right, -1 = left
+    private int movementCooldown = 0;
+    private int jumpAttempts = 0;
+}
diff --git a/src/main/java/cz/jzitnik/game/mobs/services/pig/PigLogic.java b/src/main/java/cz/jzitnik/game/mobs/services/pig/PigLogic.java
new file mode 100644
index 0000000..4eaf70e
--- /dev/null
+++ b/src/main/java/cz/jzitnik/game/mobs/services/pig/PigLogic.java
@@ -0,0 +1,177 @@
+package cz.jzitnik.game.mobs.services.pig;
+
+import cz.jzitnik.game.Game;
+import cz.jzitnik.game.annotations.EntityLogic;
+import cz.jzitnik.game.annotations.EntitySpawn;
+import cz.jzitnik.game.entities.Block;
+import cz.jzitnik.game.entities.items.ItemBlockSupplier;
+import cz.jzitnik.game.mobs.EntityLogicInterface;
+import cz.jzitnik.game.mobs.EntityLogicProvider;
+import cz.jzitnik.game.mobs.EntitySpawnInterface;
+import cz.jzitnik.game.sprites.Pig;
+import cz.jzitnik.tui.ScreenMovingCalculationProvider;
+import org.jline.terminal.Terminal;
+
+import java.util.*;
+
+@EntitySpawn
+@EntityLogic("pig")
+public class PigLogic implements EntityLogicInterface, EntitySpawnInterface {
+    private final Random random = new Random();
+
+    @Override
+    public void nextIteration(EntityLogicProvider.EntityLogicMobDTO entityLogicMobDTO) {
+        int pigX = entityLogicMobDTO.getX();
+        int pigY = entityLogicMobDTO.getY();
+        var game = entityLogicMobDTO.getGame();
+        var pig = entityLogicMobDTO.getMob();
+        var world = game.getWorld();
+        var pigData = (PigData) pig.getData();
+
+        boolean updated = false;
+        int newPigX = pigX;
+        int newPigY = pigY;
+
+        // Reduce movement cooldown
+        if (pigData.getMovementCooldown() > 0) {
+            pigData.setMovementCooldown(pigData.getMovementCooldown() - 1);
+            return; // Skip movement this iteration
+        }
+
+        // Determine movement direction
+        int direction = pigData.getLastDirection();
+        if (random.nextInt(10) < 3) { // 30% chance to change direction
+            direction = -direction;
+        }
+        pigData.setLastDirection(direction);
+
+        // Update sprite direction
+        if (direction == 1) {
+            pig.setSpriteState(Pig.PigState.RIGHT);
+        } else {
+            pig.setSpriteState(Pig.PigState.LEFT);
+        }
+
+        List<Block> blocksAhead = world[pigY][pigX + direction];
+        if (!game.isSolid(blocksAhead)) {
+            world[pigY][pigX].remove(pig);
+            world[pigY][pigX + direction].add(pig);
+            newPigX = pigX + direction;
+            updated = true;
+            pigData.setJumpAttempts(0); // Reset jump attempts when moving forward
+        } else {
+            List<Block> blocksAboveAhead = world[pigY - 1][pigX + direction];
+            List<Block> blocksTwoAboveAhead = world[pigY - 2][pigX + direction];
+
+            // Jump if there is only one block height obstacle and limit jump attempts
+            if (!game.isSolid(blocksAboveAhead) && game.isSolid(blocksAhead) && !game.isSolid(blocksTwoAboveAhead)) {
+                if (pigData.getJumpAttempts() < 2) { // Limit jumping attempts to prevent infinite jumping
+                    world[pigY][pigX].remove(pig);
+                    world[pigY - 1][pigX + direction].add(pig);
+                    newPigX = pigX + direction;
+                    newPigY = pigY - 1;
+                    updated = true;
+                    pigData.setJumpAttempts(pigData.getJumpAttempts() + 1);
+                }
+            }
+        }
+
+        // Falling logic (avoid long falls)
+        while (updated) {
+            if (!game.isSolid(world[newPigY + 1][newPigX])) {
+                if (newPigY - pigY < 3) { // Only fall if it's at most 2 blocks drop
+                    world[newPigY][newPigX].remove(pig);
+                    world[newPigY + 1][newPigX].add(pig);
+                    newPigY++;
+                } else {
+                    updated = false;
+                }
+            } else {
+                updated = false;
+            }
+        }
+
+        // Apply movement cooldown to slow down movement
+        pigData.setMovementCooldown(random.nextInt(3) + 1); // 1-3 iterations cooldown
+    }
+
+    @Override
+    public void spawn(int playerX, int playerY, Game game, Terminal terminal) {
+        // Cordinates where player can see
+        int[] data = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), game.getWorld()[0].length, game.getWorld().length);
+        var world = game.getWorld();
+        int startX = data[0];
+        int endX = data[1];
+
+        // Left side
+        int lstartX = startX - 20;
+        int lendX = startX - 5;
+        int lstartY = playerY - 15;
+        int lendY = playerY + 15;
+
+        if (countPrasata(lstartX, lendX, lstartY, lendY, game) < 3 && random.nextInt(100) < 2) {
+            var spawnLocations = pigCanSpawn(lstartX, lendX, playerY, game);
+            if (!spawnLocations.isEmpty()) {
+                System.out.println(spawnLocations.size());
+                for (int i = 0; i < Math.min(4, spawnLocations.size()); i++) {
+                    var randomLocation = getRandomEntry(spawnLocations);
+                    int x = randomLocation.getKey();
+                    int y = randomLocation.getValue();
+
+                    world[y][x].add(ItemBlockSupplier.Mobs.pig());
+                }
+            }
+        }
+
+        // Right side
+        int rstartX = endX + 5;
+        int rendX = endX + 20;
+        int rstartY = playerY - 15;
+        int rendY = playerY + 15;
+
+        if (countPrasata(rstartX, rendX, rstartY, rendY, game) < 3 && random.nextInt(100) < 2) {
+            var spawnLocations = pigCanSpawn(rstartX, rendX, playerY, game);
+            if (!spawnLocations.isEmpty()) {
+                System.out.println(spawnLocations.size());
+                for (int i = 0; i < Math.min(4, spawnLocations.size()); i++) {
+                    var randomLocation = getRandomEntry(spawnLocations);
+                    int x = randomLocation.getKey();
+                    int y = randomLocation.getValue();
+
+                    world[y][x].add(ItemBlockSupplier.Mobs.pig());
+                }
+            }
+        }
+    }
+
+    public static <K, V> Map.Entry<K, V> getRandomEntry(HashMap<K, V> map) {
+        List<Map.Entry<K, V>> entryList = new ArrayList<>(map.entrySet());
+        Random random = new Random();
+        return entryList.get(random.nextInt(entryList.size()));
+    }
+
+    private HashMap<Integer, Integer> pigCanSpawn(int startX, int endX, int playerY, Game game) {
+        var map = new HashMap<Integer, Integer>();
+        var world = game.getWorld();
+        for (int x = startX; x <= endX; x++) {
+            for (int y = Math.max(0, playerY - 30); y < Math.min(world.length, playerY + 30); y++) {
+                if (world[y][x].stream().anyMatch(i -> i.getBlockId().equals("grass"))) {
+                    map.put(x, y - 1);
+                }
+            }
+        }
+
+        return map;
+    }
+
+    private long countPrasata(int startX, int endX, int startY, int endY, Game game) {
+        long pigAmount = 0;
+        for (int y = startY; y <= endY; y++) {
+            for (int x = startX; x <= endX; x++) {
+                pigAmount += game.getWorld()[y][x].stream().filter(i -> i.getBlockId().equals("pig")).count();
+            }
+        }
+
+        return pigAmount;
+    }
+}
diff --git a/src/main/java/cz/jzitnik/game/smelting/Smelting.java b/src/main/java/cz/jzitnik/game/smelting/Smelting.java
index 8aac464..2f06f63 100644
--- a/src/main/java/cz/jzitnik/game/smelting/Smelting.java
+++ b/src/main/java/cz/jzitnik/game/smelting/Smelting.java
@@ -1,7 +1,7 @@
 package cz.jzitnik.game.smelting;
 
-import cz.jzitnik.game.items.Item;
-import cz.jzitnik.game.items.ItemBlockSupplier;
+import cz.jzitnik.game.entities.items.Item;
+import cz.jzitnik.game.entities.items.ItemBlockSupplier;
 
 import java.util.HashMap;
 import java.util.function.Supplier;
diff --git a/src/main/java/cz/jzitnik/game/threads/HealthRegenerationThread.java b/src/main/java/cz/jzitnik/game/threads/HealthRegenerationThread.java
index 0a9bded..451b523 100644
--- a/src/main/java/cz/jzitnik/game/threads/HealthRegenerationThread.java
+++ b/src/main/java/cz/jzitnik/game/threads/HealthRegenerationThread.java
@@ -1,6 +1,6 @@
 package cz.jzitnik.game.threads;
 
-import cz.jzitnik.game.Player;
+import cz.jzitnik.game.entities.Player;
 import lombok.AllArgsConstructor;
 
 @AllArgsConstructor
diff --git a/src/main/java/cz/jzitnik/game/threads/HungerDrainThread.java b/src/main/java/cz/jzitnik/game/threads/HungerDrainThread.java
index dc0bc11..397f44a 100644
--- a/src/main/java/cz/jzitnik/game/threads/HungerDrainThread.java
+++ b/src/main/java/cz/jzitnik/game/threads/HungerDrainThread.java
@@ -1,6 +1,6 @@
 package cz.jzitnik.game.threads;
 
-import cz.jzitnik.game.Player;
+import cz.jzitnik.game.entities.Player;
 import lombok.AllArgsConstructor;
 
 @AllArgsConstructor
diff --git a/src/main/java/cz/jzitnik/game/threads/InputHandlerThread.java b/src/main/java/cz/jzitnik/game/threads/InputHandlerThread.java
index d5f1e96..e077c83 100644
--- a/src/main/java/cz/jzitnik/game/threads/InputHandlerThread.java
+++ b/src/main/java/cz/jzitnik/game/threads/InputHandlerThread.java
@@ -1,6 +1,8 @@
 package cz.jzitnik.game.threads;
 
 import cz.jzitnik.game.Game;
+import cz.jzitnik.game.blocks.Chest;
+import cz.jzitnik.game.blocks.Furnace;
 import cz.jzitnik.game.ui.*;
 import cz.jzitnik.tui.MouseHandler;
 import cz.jzitnik.tui.ScreenRenderer;
@@ -54,11 +56,11 @@ public class InputHandlerThread extends Thread {
                 switch (key) {
                     case '1', '2', '3', '4', '5', '6', '7', '8', '9' -> game.changeSlot(key - 49, screenRenderer);
                     case 'a' -> {
-                        game.movePlayerLeft(screenRenderer);
+                        game.movePlayerLeft(screenRenderer, terminal);
                         screenRenderer.render(game);
                     }
                     case 'd' -> {
-                        game.movePlayerRight(screenRenderer);
+                        game.movePlayerRight(screenRenderer, terminal);
                         screenRenderer.render(game);
                     }
                     case ' ' -> {
diff --git a/src/main/java/cz/jzitnik/game/ui/CraftingTable.java b/src/main/java/cz/jzitnik/game/ui/CraftingTable.java
index 09e0179..ce9e6d6 100644
--- a/src/main/java/cz/jzitnik/game/ui/CraftingTable.java
+++ b/src/main/java/cz/jzitnik/game/ui/CraftingTable.java
@@ -3,7 +3,7 @@ package cz.jzitnik.game.ui;
 import cz.jzitnik.game.Game;
 import cz.jzitnik.game.crafting.CraftingRecipe;
 import cz.jzitnik.game.crafting.CraftingRecipeList;
-import cz.jzitnik.game.items.InventoryItem;
+import cz.jzitnik.game.entities.items.InventoryItem;
 import cz.jzitnik.tui.ScreenRenderer;
 import cz.jzitnik.tui.utils.SpriteCombiner;
 import cz.jzitnik.tui.SpriteList;
diff --git a/src/main/java/cz/jzitnik/game/ui/Inventory.java b/src/main/java/cz/jzitnik/game/ui/Inventory.java
index 76f7477..d33cc45 100644
--- a/src/main/java/cz/jzitnik/game/ui/Inventory.java
+++ b/src/main/java/cz/jzitnik/game/ui/Inventory.java
@@ -1,7 +1,7 @@
 package cz.jzitnik.game.ui;
 
-import cz.jzitnik.game.items.InventoryItem;
-import cz.jzitnik.game.items.Item;
+import cz.jzitnik.game.entities.items.InventoryItem;
+import cz.jzitnik.game.entities.items.Item;
 import cz.jzitnik.tui.utils.SpriteCombiner;
 import cz.jzitnik.tui.SpriteList;
 import cz.jzitnik.tui.utils.Numbers;
diff --git a/src/main/java/cz/jzitnik/game/ui/InventoryClickHandler.java b/src/main/java/cz/jzitnik/game/ui/InventoryClickHandler.java
index 65144a8..2bca08b 100644
--- a/src/main/java/cz/jzitnik/game/ui/InventoryClickHandler.java
+++ b/src/main/java/cz/jzitnik/game/ui/InventoryClickHandler.java
@@ -1,7 +1,7 @@
 package cz.jzitnik.game.ui;
 
 import cz.jzitnik.game.Game;
-import cz.jzitnik.game.items.InventoryItem;
+import cz.jzitnik.game.entities.items.InventoryItem;
 import cz.jzitnik.tui.ScreenRenderer;
 import org.jline.terminal.MouseEvent;
 import org.jline.terminal.Terminal;
diff --git a/src/main/java/cz/jzitnik/game/ui/InventoryDTO.java b/src/main/java/cz/jzitnik/game/ui/InventoryDTO.java
index ca0a335..4f82ce0 100644
--- a/src/main/java/cz/jzitnik/game/ui/InventoryDTO.java
+++ b/src/main/java/cz/jzitnik/game/ui/InventoryDTO.java
@@ -1,6 +1,6 @@
 package cz.jzitnik.game.ui;
 
-import cz.jzitnik.game.items.InventoryItem;
+import cz.jzitnik.game.entities.items.InventoryItem;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
diff --git a/src/main/java/cz/jzitnik/game/ui/SmallCraftingTable.java b/src/main/java/cz/jzitnik/game/ui/SmallCraftingTable.java
index d9d76a1..da321c6 100644
--- a/src/main/java/cz/jzitnik/game/ui/SmallCraftingTable.java
+++ b/src/main/java/cz/jzitnik/game/ui/SmallCraftingTable.java
@@ -2,7 +2,7 @@ package cz.jzitnik.game.ui;
 
 import cz.jzitnik.game.crafting.CraftingRecipe;
 import cz.jzitnik.game.crafting.CraftingRecipeList;
-import cz.jzitnik.game.items.InventoryItem;
+import cz.jzitnik.game.entities.items.InventoryItem;
 import cz.jzitnik.tui.utils.SpriteCombiner;
 import cz.jzitnik.tui.SpriteList;
 import cz.jzitnik.tui.utils.Numbers;
diff --git a/src/main/java/cz/jzitnik/tui/ScreenRenderer.java b/src/main/java/cz/jzitnik/tui/ScreenRenderer.java
index 65942ee..733d2ef 100644
--- a/src/main/java/cz/jzitnik/tui/ScreenRenderer.java
+++ b/src/main/java/cz/jzitnik/tui/ScreenRenderer.java
@@ -1,14 +1,13 @@
 package cz.jzitnik.tui;
 
-import cz.jzitnik.game.Block;
+import cz.jzitnik.game.entities.Block;
 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.blocks.Chest;
+import cz.jzitnik.game.blocks.Furnace;
 import cz.jzitnik.game.ui.Healthbar;
 import cz.jzitnik.tui.utils.SpriteCombiner;
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
 import lombok.Setter;
 import org.jline.terminal.Terminal;
 
@@ -16,10 +15,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
-@RequiredArgsConstructor
 public class ScreenRenderer {
-    private SpriteList spriteList;
-    private Terminal terminal;
+    private final SpriteList spriteList;
+    private final Terminal terminal;
 
     public ScreenRenderer(SpriteList spriteList, Terminal terminal) {
         this.spriteList = spriteList;
@@ -41,7 +39,7 @@ public class ScreenRenderer {
         return null;
     }
 
-    public void render(Game game) {
+    public synchronized void render(Game game) {
         var world = game.getWorld();
         StringBuilder main = new StringBuilder();
         main.append("\033[H\033[2J");