diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/Pixel.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/Pixel.java
deleted file mode 100644
index 76488c5..0000000
--- a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/Pixel.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package eu.mhsl.minecraft.pixelblocks.pixelblock;
-
-import eu.mhsl.minecraft.pixelblocks.Main;
-import org.bukkit.Location;
-import org.bukkit.NamespacedKey;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.entity.BlockDisplay;
-import org.bukkit.entity.EntityType;
-import org.bukkit.persistence.PersistentDataType;
-import org.bukkit.util.Transformation;
-import org.bukkit.util.Vector;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-public class Pixel {
-    private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin, "pixel_of");
-
-    private final @NotNull PixelBlock parentBlock;
-    private final @NotNull BlockDisplay entity;
-
-    private final Location location;
-
-    public static List<Pixel> fromExisting(PixelBlock parentBlock) {
-        return parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(BlockDisplay.class, 1)
-            .stream()
-            .filter(blockDisplay -> blockDisplay.getPersistentDataContainer().has(pixelOfTag))
-            .filter(blockDisplay -> Objects.equals(
-                blockDisplay.getPersistentDataContainer().get(pixelOfTag, PersistentDataType.STRING),
-                parentBlock.getBlockUUID().toString()
-            ))
-            .map(blockDisplay -> new Pixel(parentBlock, blockDisplay))
-            .collect(Collectors.toList());
-    }
-    private Pixel(@NotNull PixelBlock parentBlock, @NotNull BlockDisplay entity) {
-        this.parentBlock = parentBlock;
-        this.entity = entity;
-        this.location = entity.getLocation();
-    }
-
-    public static Pixel newPixel(PixelBlock parentBlock, Vector relativePosition, BlockData blockData, double scale) {
-        return new Pixel(parentBlock, relativePosition, blockData, scale);
-    }
-    private Pixel(@NotNull PixelBlock parentBlock, @NotNull Vector relativePosition, @NotNull BlockData blockData, double scale) {
-        this.parentBlock = parentBlock;
-        this.location = parentBlock.getPixelBlockLocation().add(relativePosition.multiply(scale));
-        this.entity = (BlockDisplay) this.location.getWorld().spawnEntity(this.location, EntityType.BLOCK_DISPLAY);
-
-        this.entity.setBlock(blockData);
-        Transformation transform = this.entity.getTransformation();
-        transform.getScale().set(scale);
-        this.entity.setTransformation(transform);
-        this.entity.getPersistentDataContainer().set(pixelOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
-    }
-
-    public void destroy() {
-        this.entity.remove();
-    }
-
-    public Location getLocation() {
-        return location.clone();
-    }
-}
diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java
index 38111a3..dafc3be 100644
--- a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java
+++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java
@@ -7,26 +7,21 @@ import eu.mhsl.minecraft.pixelblocks.utils.Direction;
 import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.format.NamedTextColor;
 import org.bukkit.*;
-import org.bukkit.block.data.BlockData;
 import org.bukkit.entity.*;
 import org.bukkit.util.Vector;
 import org.jetbrains.annotations.NotNull;
 
 import javax.annotation.Nullable;
-import java.io.File;
 import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 
 public class PixelBlock {
     private boolean exists = true;
     private PixelBlockWorld pixelWorld;
 
-    private final int pixelsPerBlock = Main.configuration.pixelsPerBlock();
-
     private final Location pixelBlockLocation;
     private final Direction facingDirection;
-    private List<Pixel> pixels = new ArrayList<>();
+    private Pixels pixels;
+    private List<PixelBlockWorld.PixelData> pixelData;
 
     private PixelBlockHitbox hitbox;
     private PixelBlockPlaceholder placeholder;
@@ -35,12 +30,6 @@ public class PixelBlock {
     private final UUID ownerUUID;
     private final UUID blockUUID;
 
-    public static final int maxPixelsPerBlock = 2000;
-
-    public static @NotNull String getWorldName(@NotNull PixelBlock pixelBlock) {
-        return Main.plugin.getDataFolder().getPath() + File.separator + pixelBlock.blockUUID;
-    }
-
     public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) {
         return Main.pixelBlocks.stream()
                 .filter(block -> block.blockUUID.equals(getUUIDFromWorld(world)))
@@ -79,14 +68,14 @@ public class PixelBlock {
         this.facingDirection = direction;
         this.lastEntryLocation = lastEntryLocation;
 
-        this.ensureChunksLoaded();
         try {
             this.pixelWorld = new PixelBlockWorld(this);
-            this.pixels = Pixel.fromExisting(this);
-            this.placeholder = PixelBlockPlaceholder.fromExisting(this);
-            this.hitbox = PixelBlockHitbox.fromExisting(this);
+            this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
+            this.pixels = new Pixels(this);
+            this.placeholder = new PixelBlockPlaceholder(this);
+            this.hitbox = new PixelBlockHitbox(this);
 
-            Main.plugin.getLogger().info(String.format("Loaded existing pixelblock '%s' with %d pixels", this.blockUUID, this.pixels.size()));
+            Main.plugin.getLogger().info(String.format("Loaded existing pixelblock '%s'", this.blockUUID));
         } catch(Exception e) {
             Main.plugin.getLogger().info(String.format("Failed initializing existing pixelblock '%s': %s", this.blockUUID, e.getMessage()));
         }
@@ -109,8 +98,10 @@ public class PixelBlock {
         this.getBlockTaskChain()
             .sync(() -> {
                 this.pixelWorld = new PixelBlockWorld(this);
-                this.placeholder = PixelBlockPlaceholder.newPlaceholder(this);
-                this.hitbox = PixelBlockHitbox.newHitbox(this);
+                this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
+                this.pixels = new Pixels(this);
+                this.placeholder = new PixelBlockPlaceholder(this);
+                this.hitbox = new PixelBlockHitbox(this);
             })
             .execute();
 
@@ -128,15 +119,6 @@ public class PixelBlock {
         return Main.sharedChain(this.blockUUID.toString());
     }
 
-    private void ensureChunksLoaded() {
-        Chunk chunk = this.pixelBlockLocation.getChunk();
-        if(!chunk.isLoaded() || !chunk.isEntitiesLoaded()) {
-            Main.plugin.getLogger().info(String.format("Loading chunk '%d, %d' for pixelblock '%s'", chunk.getX(), chunk.getZ(), this.blockUUID));
-            chunk.load(true);
-            chunk.getEntities();
-        }
-    }
-
     public void enterBlock(@NotNull Player player) {
         if(Main.configuration.onlyEditableByOwner() && !player.getUniqueId().equals(ownerUUID)) {
             player.sendMessage(Component.text("Dieser Pixelblock gehört nicht dir!", NamedTextColor.RED));
@@ -161,68 +143,22 @@ public class PixelBlock {
         this.getBlockTaskChain()
             .sync(() -> player.teleport(this.lastEntryLocation != null ? this.lastEntryLocation : this.pixelBlockLocation))
             .current(() -> Main.plugin.getLogger().info(String.format("%s exited PixelBlock", player.getName())))
+            .sync(() -> this.pixelData = this.pixelWorld.getPixels(this.facingDirection))
             .execute();
 
         this.scheduleEntityUpdate();
     }
 
     private void scheduleEntityUpdate() {
-        record PixelData(PixelBlock parent, Vector relativeLocation, BlockData block, double scale) {
-            Pixel create() {
-                return Pixel.newPixel(this.parent, this.relativeLocation, this.block, this.scale);
-            }
-        }
-        List<PixelData> pixelData = new ArrayList<>();
-
-        this.scheduleEntityRemove();
         this.getBlockTaskChain()
-            .async(() -> {
-                for (int x = 0; x < pixelsPerBlock; x++) {
-                    for (int y = 0; y < pixelsPerBlock; y++) {
-                        for (int z = 0; z < pixelsPerBlock; z++) {
-                            World world = pixelBlockLocation.getWorld();
-                            Location relativeLocation = new Location(world, x, y, z);
-
-                            Location blockLocation = this.pixelWorld.getBuildOrigin();
-                            switch (this.facingDirection) {
-                                case south -> blockLocation.add(relativeLocation.x(), relativeLocation.y(), relativeLocation.z());
-                                case north -> blockLocation.add((pixelsPerBlock-1)-relativeLocation.x(), relativeLocation.y(), (pixelsPerBlock-1)-relativeLocation.z());
-                                case east -> blockLocation.add((pixelsPerBlock-1)-relativeLocation.z(), relativeLocation.y(), relativeLocation.x());
-                                case west -> blockLocation.add(relativeLocation.z(), relativeLocation.y(), (pixelsPerBlock-1)-relativeLocation.x());
-                            }
-                            BlockData block = blockLocation.getBlock().getBlockData();
-
-                            if(!block.getMaterial().isEmpty()) {
-                                pixelData.add(new PixelData(this, relativeLocation.toVector(), block, (double) 1 / pixelsPerBlock));
-                            }
-                        }
-                    }
-                }
+            .sync(this::removeEntities)
+            .async(() -> Collections.shuffle(this.pixelData))
+            .delay(1)
+            .syncLast((pixelData) -> {
+                this.pixels.spawn();
+                this.hitbox.spawn();
+                this.placeholder.spawn();
             })
-            .async(() -> Collections.shuffle(pixelData))
-            .asyncFirst(() -> {
-                int spawnSpreadInTicks = 10;
-                int chunkSize = (int) Math.ceil((double) pixelData.size() / spawnSpreadInTicks);
-
-                TaskChain<Object> spawnTask = this.getBlockTaskChain();
-                IntStream.range(0, spawnSpreadInTicks)
-                    .mapToObj(i -> pixelData.stream()
-                        .skip((long) i * chunkSize)
-                        .limit(chunkSize)
-                        .collect(Collectors.toList()))
-                    .forEach(pixels -> spawnTask
-                        .delay(1)
-                        .sync(() -> pixels.forEach(pixel -> this.pixels.add(pixel.create()))));
-
-                return spawnTask;
-            })
-            .syncLast((chain) -> chain
-                .sync(() -> {
-                    this.hitbox = PixelBlockHitbox.newHitbox(this);
-                    this.placeholder = PixelBlockPlaceholder.newPlaceholder(this);
-                    Main.plugin.getLogger().info(String.format("Placed %d entities for PixelBlock '%s'", this.pixels.size(), this.blockUUID));
-                })
-                .execute())
             .execute();
     }
 
@@ -261,9 +197,9 @@ public class PixelBlock {
             .filter(entity -> entity instanceof Item)
             .forEach(entity -> entity.teleport(this.lastEntryLocation));
 
-        this.scheduleEntityRemove();
         this.getBlockTaskChain()
             .sync(() -> {
+                this.removeEntities();
                 World world = this.pixelBlockLocation.getWorld();
                 world.playSound(this.pixelBlockLocation, Sound.BLOCK_COPPER_BULB_BREAK, 1.0F, 30);
                 world.dropItem(this.pixelBlockLocation.add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this));
@@ -275,25 +211,10 @@ public class PixelBlock {
             .execute();
     }
 
-    private void scheduleEntityRemove() {
-        this.getBlockTaskChain()
-            .current(() -> Main.plugin.getLogger()
-                .info(String.format("Removing %d pixels in PixelBlock '%s'", this.pixels.size(), this.blockUUID)))
-            .sync(this::ensureChunksLoaded)
-            .delay(1)
-            .sync(() -> {
-                List<Entity> entitiesBefore = this.pixelBlockLocation.getWorld().getEntities();
-                this.pixels.forEach(Pixel::destroy);
-                List<Entity> entitiesAfter = this.pixelBlockLocation.getWorld().getEntities();
-
-                Main.plugin.getLogger().info("Entities im Chunk vor dem Entfernen: " + entitiesBefore.size());
-                Main.plugin.getLogger().info("Entities im Chunk nach dem Entfernen: " + entitiesAfter.size());
-
-                this.pixels.clear();
-                this.placeholder.destroy();
-                this.hitbox.destroy();
-            })
-            .execute();
+    private void removeEntities() {
+        this.pixels.destroy();
+        this.placeholder.destroy();
+        this.hitbox.destroy();
     }
 
     public @NotNull PixelBlockWorld getPixelWorld() {
@@ -312,8 +233,8 @@ public class PixelBlock {
         return this.lastEntryLocation != null;
     }
 
-    public List<Pixel> getPixels() {
-        return pixels;
+    public List<PixelBlockWorld.PixelData> getPixelData() {
+        return pixelData;
     }
 
     public Location getLastEntryLocation() {
diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockHitbox.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockHitbox.java
index cd42909..95989d4 100644
--- a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockHitbox.java
+++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockHitbox.java
@@ -1,24 +1,94 @@
 package eu.mhsl.minecraft.pixelblocks.pixelblock;
 
 import eu.mhsl.minecraft.pixelblocks.Main;
-import eu.mhsl.minecraft.pixelblocks.utils.MinMaxUtil;
 import org.bukkit.Location;
 import org.bukkit.NamespacedKey;
+import org.bukkit.entity.Entity;
 import org.bukkit.entity.EntityType;
 import org.bukkit.entity.Interaction;
 import org.bukkit.persistence.PersistentDataType;
 
 import java.util.List;
 import java.util.Objects;
-import java.util.UUID;
 
 public class PixelBlockHitbox {
     private static final NamespacedKey hitboxOfTag = new NamespacedKey(Main.plugin, "hitbox_of");
 
-    private final Interaction interaction;
+    private final PixelBlock parentBlock;
 
-    public static PixelBlockHitbox fromExisting(PixelBlock parentBlock) {
-        Interaction hitBox = parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(Interaction.class, 1)
+    public PixelBlockHitbox(PixelBlock parentBlock) {
+        this.parentBlock = parentBlock;
+    }
+
+    public void spawn() {
+        Location pixelBlockLocation = this.parentBlock.getPixelBlockLocation();
+        List<PixelBlockWorld.PixelData> pixels = this.parentBlock.getPixelData();
+        double scale = pixels.getFirst().scale();
+
+        float offset = (float) Main.configuration.hitboxOffset();
+        int pixelsPerBlock = Main.configuration.pixelsPerBlock();
+
+        Interaction interaction;
+        if(true) {
+            interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
+                pixelBlockLocation.clone().add(0.5, -offset, 0.5),
+                EntityType.INTERACTION
+            );
+            interaction.setInteractionHeight(1 + 2*offset);
+            interaction.setInteractionWidth(1 + 2*offset);
+        } else {
+//            double startingX = this.parentBlock.getPixelBlockLocation().x() + MinMaxUtil.getMinProperty(pixels, pixel -> pixel.relativeLocation().getX()) * scale;
+//            double startingY = this.parentBlock.getPixelBlockLocation().y() + MinMaxUtil.getMinProperty(pixels, pixel -> pixel.relativeLocation().getY()) * scale;
+//            double startingZ = this.parentBlock.getPixelBlockLocation().z() + MinMaxUtil.getMinProperty(pixels, pixel -> pixel.relativeLocation().getZ()) * scale;
+//
+//            double endingX = this.parentBlock.getPixelBlockLocation().x() + MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.relativeLocation().getX()) * scale;
+//            double endingY = this.parentBlock.getPixelBlockLocation().y() + MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.relativeLocation().getY()) * scale;
+//            double endingZ = this.parentBlock.getPixelBlockLocation().z() + MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.relativeLocation().getZ()) * scale;
+//
+//            Location spawnLocation = pixelBlockLocation.clone().add(
+//                ((startingX+endingX+1)/2)/pixelsPerBlock,
+//                (startingY/pixelsPerBlock)-offset,
+//                ((startingZ+endingZ+1)/2)/pixelsPerBlock
+//            );
+//
+//            float height = (float) (endingY-startingY+1)/pixelsPerBlock + 2*offset;
+//
+//            float width;
+//            if((endingX-startingX) > (endingZ-startingZ)) {
+//                width = (float) (endingX-startingX+1)/pixelsPerBlock + 2*offset;
+//            } else {
+//                width = (float) (endingZ-startingZ+1)/pixelsPerBlock + 2*offset;
+//            }
+//
+//            if(spawnLocation.getX()+width/2 > pixelBlockLocation.getX()+1) {
+//                spawnLocation.subtract((spawnLocation.getX()+width/2)-(pixelBlockLocation.getX()+1), 0, 0);
+//            }
+//            if(spawnLocation.getX()-width/2 < pixelBlockLocation.getX()) {
+//                spawnLocation.add(pixelBlockLocation.getX()-(spawnLocation.getX()-width/2), 0, 0);
+//            }
+//
+//            if(spawnLocation.getZ()+width/2 > pixelBlockLocation.getZ()+1) {
+//                spawnLocation.subtract(0, 0, (spawnLocation.getZ()+width/2)-(pixelBlockLocation.getZ()+1));
+//            }
+//            if(spawnLocation.getZ()-width/2 < pixelBlockLocation.getZ()) {
+//                spawnLocation.add(0, 0, pixelBlockLocation.getZ()-(spawnLocation.getZ()-width/2));
+//            }
+//
+//            interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
+//                spawnLocation,
+//                EntityType.INTERACTION
+//            );
+//
+//            interaction.setInteractionHeight(height);
+//            interaction.setInteractionWidth(width);
+        }
+
+        interaction.getPersistentDataContainer()
+            .set(hitboxOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
+    }
+
+    public void destroy() {
+        this.parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(Interaction.class, 1)
             .stream()
             .filter(interaction -> interaction.getPersistentDataContainer().has(hitboxOfTag))
             .filter(interaction -> Objects.equals(
@@ -28,81 +98,6 @@ public class PixelBlockHitbox {
             .reduce((a, b) -> {
                 throw new IllegalStateException(String.format("Mehrere hitboxen für PixelBlock '%s' gefunden!", parentBlock.getBlockUUID()));
             })
-            .orElseThrow();
-
-        Main.plugin.getLogger().info(String.format("Found existing hitbox '%s' for block '%s'", hitBox.getUniqueId(), parentBlock.getBlockUUID()));
-        return new PixelBlockHitbox(hitBox);
-    }
-    private PixelBlockHitbox(Interaction interaction) {
-        this.interaction = interaction;
-    }
-
-    public static PixelBlockHitbox newHitbox(PixelBlock parentBlock) {
-        return new PixelBlockHitbox(parentBlock.getPixelBlockLocation(), parentBlock.getPixels(), parentBlock.getBlockUUID());
-    }
-    private PixelBlockHitbox(Location pixelBlockLocation, List<Pixel> pixels, UUID parentBlockUUID) {
-        float offset = (float) Main.configuration.hitboxOffset();
-        int pixelsPerBlock = Main.configuration.pixelsPerBlock();
-
-        if(pixels.size() > 5 || true) {
-            interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
-                pixelBlockLocation.clone().add(0.5, -offset, 0.5),
-                EntityType.INTERACTION
-            );
-            interaction.setInteractionHeight(1 + 2*offset);
-            interaction.setInteractionWidth(1 + 2*offset);
-        } else {
-            double startingX = MinMaxUtil.getMinProperty(pixels, pixel -> pixel.getLocation().getX());
-            double startingY = MinMaxUtil.getMinProperty(pixels, pixel -> pixel.getLocation().getY());
-            double startingZ = MinMaxUtil.getMinProperty(pixels, pixel -> pixel.getLocation().getZ());
-
-            double endingX = MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.getLocation().getX());
-            double endingY = MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.getLocation().getY());
-            double endingZ = MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.getLocation().getZ());
-
-            Location spawnLocation = pixelBlockLocation.clone().add(
-                ((startingX+endingX+1)/2)/pixelsPerBlock,
-                (startingY/pixelsPerBlock)-offset,
-                ((startingZ+endingZ+1)/2)/pixelsPerBlock
-            );
-
-            float height = (float) (endingY-startingY+1)/pixelsPerBlock + 2*offset;
-
-            float width;
-            if((endingX-startingX) > (endingZ-startingZ)) {
-                width = (float) (endingX-startingX+1)/pixelsPerBlock + 2*offset;
-            } else {
-                width = (float) (endingZ-startingZ+1)/pixelsPerBlock + 2*offset;
-            }
-
-            if(spawnLocation.getX()+width/2 > pixelBlockLocation.getX()+1) {
-                spawnLocation.subtract((spawnLocation.getX()+width/2)-(pixelBlockLocation.getX()+1), 0, 0);
-            }
-            if(spawnLocation.getX()-width/2 < pixelBlockLocation.getX()) {
-                spawnLocation.add(pixelBlockLocation.getX()-(spawnLocation.getX()-width/2), 0, 0);
-            }
-
-            if(spawnLocation.getZ()+width/2 > pixelBlockLocation.getZ()+1) {
-                spawnLocation.subtract(0, 0, (spawnLocation.getZ()+width/2)-(pixelBlockLocation.getZ()+1));
-            }
-            if(spawnLocation.getZ()-width/2 < pixelBlockLocation.getZ()) {
-                spawnLocation.add(0, 0, pixelBlockLocation.getZ()-(spawnLocation.getZ()-width/2));
-            }
-
-            interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
-                spawnLocation,
-                EntityType.INTERACTION
-            );
-
-            interaction.setInteractionHeight(height);
-            interaction.setInteractionWidth(width);
-        }
-
-        this.interaction.getPersistentDataContainer()
-            .set(hitboxOfTag, PersistentDataType.STRING, parentBlockUUID.toString());
-    }
-
-    public void destroy() {
-        this.interaction.remove();
+            .ifPresent(Entity::remove);
     }
 }
diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockPlaceholder.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockPlaceholder.java
index f7ed9d8..4272eea 100644
--- a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockPlaceholder.java
+++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockPlaceholder.java
@@ -18,32 +18,16 @@ import java.util.*;
 public class PixelBlockPlaceholder {
     private static final NamespacedKey placeholderOfTag = new NamespacedKey(Main.plugin, "placeholder_of");
 
-    List<ItemDisplay> placeholders = new ArrayList<>();
+    private final PixelBlock parentBlock;
 
-    public static PixelBlockPlaceholder fromExisting(PixelBlock parentBlock) {
-        List<ItemDisplay> placeholders = parentBlock.getPixelBlockLocation()
-            .getNearbyEntitiesByType(ItemDisplay.class, 1)
-            .stream()
-            .filter(itemDisplay -> itemDisplay.getPersistentDataContainer().has(placeholderOfTag))
-            .filter(itemDisplay -> Objects.equals(
-                itemDisplay.getPersistentDataContainer().get(placeholderOfTag, PersistentDataType.STRING),
-                parentBlock.getBlockUUID().toString()
-            ))
-            .toList();
-
-        Main.plugin.getLogger().info(String.format("Found %d existing placeholders for block '%s'", placeholders.size(), parentBlock.getBlockUUID()));
-        return new PixelBlockPlaceholder(placeholders);
-    }
-    private PixelBlockPlaceholder(List<ItemDisplay> itemDisplays) {
-        this.placeholders = itemDisplays;
+    public PixelBlockPlaceholder(PixelBlock parentBlock) {
+        this.parentBlock = parentBlock;
     }
 
-    public static PixelBlockPlaceholder newPlaceholder(PixelBlock parentBlock) {
-        return new PixelBlockPlaceholder(parentBlock);
-    }
-    private PixelBlockPlaceholder(PixelBlock parentBlock) {
-        if(parentBlock.getPixels().size() > 5) return;
+    public void spawn() {
+        if(parentBlock.getPixelData().size() > 5) return;
 
+        List<ItemDisplay> placeholders = new ArrayList<>();
         Location pixelBlockLocation = parentBlock.getPixelBlockLocation();
         UUID parentBlockUUID = parentBlock.getBlockUUID();
 
@@ -56,7 +40,7 @@ public class PixelBlockPlaceholder {
                 EntityType.ITEM_DISPLAY
             );
             verticalCore.setRotation(i, 0);
-            this.placeholders.add(verticalCore);
+            placeholders.add(verticalCore);
         }
 
         ItemDisplay horizontalCore = (ItemDisplay) pixelBlockWorld.spawnEntity(
@@ -64,9 +48,9 @@ public class PixelBlockPlaceholder {
             EntityType.ITEM_DISPLAY
         );
         horizontalCore.setRotation(0, 90);
-        this.placeholders.add(horizontalCore);
+        placeholders.add(horizontalCore);
 
-        this.placeholders.forEach(coreDisplay -> {
+        placeholders.forEach(coreDisplay -> {
             coreDisplay.setItemStack(ItemStack.of(Material.END_CRYSTAL));
             Transformation transform = coreDisplay.getTransformation();
             transform.getScale().set(0.5);
@@ -78,18 +62,22 @@ public class PixelBlockPlaceholder {
             EntityType.ITEM_DISPLAY
         );
         displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS));
-        this.placeholders.add(displayContainer);
+        placeholders.add(displayContainer);
 
-        this.setDataTags(parentBlockUUID);
-    }
-
-    private void setDataTags(UUID parentBlockUUID) {
-        this.placeholders.stream()
+        placeholders.stream()
             .map(PersistentDataHolder::getPersistentDataContainer)
             .forEach(container -> container.set(placeholderOfTag, PersistentDataType.STRING, parentBlockUUID.toString()));
     }
 
     public void destroy() {
-        this.placeholders.forEach(Entity::remove);
+        this.parentBlock.getPixelBlockLocation()
+            .getNearbyEntitiesByType(ItemDisplay.class, 1)
+            .stream()
+            .filter(itemDisplay -> itemDisplay.getPersistentDataContainer().has(placeholderOfTag))
+            .filter(itemDisplay -> Objects.equals(
+                itemDisplay.getPersistentDataContainer().get(placeholderOfTag, PersistentDataType.STRING),
+                parentBlock.getBlockUUID().toString()
+            ))
+            .forEach(Entity::remove);
     }
 }
diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockWorld.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockWorld.java
index 330bc22..09c3225 100644
--- a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockWorld.java
+++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlockWorld.java
@@ -1,14 +1,18 @@
 package eu.mhsl.minecraft.pixelblocks.pixelblock;
 
 import eu.mhsl.minecraft.pixelblocks.Main;
+import eu.mhsl.minecraft.pixelblocks.utils.Direction;
 import eu.mhsl.minecraft.pixelblocks.utils.LocationUtil;
 import org.bukkit.*;
+import org.bukkit.block.data.BlockData;
 import org.bukkit.entity.Entity;
 import org.bukkit.entity.Player;
 import org.bukkit.generator.ChunkGenerator;
+import org.bukkit.util.Vector;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
@@ -17,7 +21,7 @@ import static eu.mhsl.minecraft.pixelblocks.Main.plugin;
 
 public class PixelBlockWorld {
     private final PixelBlock parentPixelBlock;
-    private World world;
+    private final World world;
 
     int worldGrassBorderWidth = 10;
     int pixelsPerBlock = Main.configuration.pixelsPerBlock();
@@ -88,6 +92,34 @@ public class PixelBlockWorld {
         return getBorderOrigin().add(worldGrassBorderWidth + pixelsPerBlock, 0, worldGrassBorderWidth + pixelsPerBlock);
     }
 
+    public record PixelData(Vector relativeLocation, BlockData block, double scale) {}
+    public List<PixelData> getPixels(Direction direction) {
+        List<PixelData> pixelData = new ArrayList<>();
+
+        for (int x = 0; x < pixelsPerBlock; x++) {
+            for (int y = 0; y < pixelsPerBlock; y++) {
+                for (int z = 0; z < pixelsPerBlock; z++) {
+                    Location relativeLocation = new Location(world, x, y, z);
+
+                    Location blockLocation = this.getBuildOrigin();
+                    switch (direction) {
+                        case south -> blockLocation.add(relativeLocation.x(), relativeLocation.y(), relativeLocation.z());
+                        case north -> blockLocation.add((pixelsPerBlock-1)-relativeLocation.x(), relativeLocation.y(), (pixelsPerBlock-1)-relativeLocation.z());
+                        case east -> blockLocation.add((pixelsPerBlock-1)-relativeLocation.z(), relativeLocation.y(), relativeLocation.x());
+                        case west -> blockLocation.add(relativeLocation.z(), relativeLocation.y(), (pixelsPerBlock-1)-relativeLocation.x());
+                    }
+                    BlockData block = blockLocation.getBlock().getBlockData();
+
+                    if(!block.getMaterial().isEmpty()) {
+                        pixelData.add(new PixelData(relativeLocation.toVector(), block, (double) 1 / pixelsPerBlock));
+                    }
+                }
+            }
+        }
+
+        return pixelData;
+    }
+
     private World loadOrCreatePixelWorld() {
         final WorldCreator worldCreator = new WorldCreator(getWorldPathName());
 
diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/Pixels.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/Pixels.java
new file mode 100644
index 0000000..7e2346b
--- /dev/null
+++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/Pixels.java
@@ -0,0 +1,62 @@
+package eu.mhsl.minecraft.pixelblocks.pixelblock;
+
+import eu.mhsl.minecraft.pixelblocks.Main;
+import eu.mhsl.minecraft.pixelblocks.utils.ListUtil;
+import org.bukkit.Location;
+import org.bukkit.NamespacedKey;
+import org.bukkit.entity.BlockDisplay;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.persistence.PersistentDataType;
+import org.bukkit.util.Transformation;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Objects;
+
+public class Pixels {
+    private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin, "pixel_of");
+
+    private final @NotNull PixelBlock parentBlock;
+
+    public Pixels(@NotNull PixelBlock parentBlock) {
+        this.parentBlock = parentBlock;
+    }
+
+    public void spawn() {
+        ListUtil.splitListInParts(10, this.parentBlock.getPixelData())
+            .forEach(pixels -> parentBlock.getBlockTaskChain()
+                .delay(1)
+                .sync(() -> pixels.forEach(this::spawnPixel))
+                .execute());
+    }
+
+    private void spawnPixel(PixelBlockWorld.PixelData pixelData) {
+        Location pixelBlockLocation = this.parentBlock.getPixelBlockLocation();
+        Location pixelLocation = pixelBlockLocation.add(pixelData.relativeLocation().multiply(pixelData.scale()));
+        BlockDisplay entity = (BlockDisplay) pixelBlockLocation.getWorld().spawnEntity(pixelLocation, EntityType.BLOCK_DISPLAY);
+
+        entity.setBlock(pixelData.block());
+        Transformation transform = entity.getTransformation();
+        transform.getScale().set(pixelData.scale());
+        entity.setTransformation(transform);
+        entity.getPersistentDataContainer().set(pixelOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
+    }
+
+    public void destroy() {
+        List<BlockDisplay> entities = parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(BlockDisplay.class, 1)
+            .stream()
+            .filter(blockDisplay -> blockDisplay.getPersistentDataContainer().has(pixelOfTag))
+            .filter(blockDisplay -> Objects.equals(
+                blockDisplay.getPersistentDataContainer().get(pixelOfTag, PersistentDataType.STRING),
+                parentBlock.getBlockUUID().toString()
+            ))
+            .toList();
+
+        ListUtil.splitListInParts(10, entities)
+            .forEach(pixels -> parentBlock.getBlockTaskChain()
+                .delay(1)
+                .sync(() -> pixels.forEach(Entity::remove))
+                .execute());
+    }
+}
diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/utils/ListUtil.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/utils/ListUtil.java
new file mode 100644
index 0000000..d51b49d
--- /dev/null
+++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/utils/ListUtil.java
@@ -0,0 +1,19 @@
+package eu.mhsl.minecraft.pixelblocks.utils;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class ListUtil {
+    public static <T> List<List<T>> splitListInParts(int parts, List<T> list) {
+        int actualParts = Math.min(parts, list.size());
+        int chunkSize = (int) Math.ceil((double) list.size() / actualParts);
+        return IntStream.range(0, actualParts)
+            .mapToObj(i -> list.stream()
+                .skip((long) i * chunkSize)
+                .limit(chunkSize)
+                .collect(Collectors.toList()))
+            .toList();
+    }
+
+}