diff --git a/build.gradle.kts b/build.gradle.kts
index be88092..0b5d66e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -18,7 +18,6 @@ repositories {
 
     maven(url = "https://jitpack.io")
     maven(url = "https://repo.spongepowered.org/maven")
-    maven(url = "https://repo.minestom.com/repository/maven-public/")
     maven(url = "https://repo.velocitypowered.com/snapshots/")
 }
 
@@ -33,10 +32,10 @@ dependencies {
     compileOnly(kotlin("reflect"))
 
     // Compile Minestom into project
-    compileOnly("com.github.LeoDog896", "Minestom", "fc441737f4")
+    compileOnly("com.github.Minestom", "Minestom", "7867313290")
 
     // Get KStom
-    compileOnly("com.github.Project-Cepi:KStom:f962764331")
+    compileOnly("com.github.Project-Cepi:KStom:82f7000079")
 
     // Use MobExtension
     compileOnly("com.github.Project-Cepi:MobExtension:4eb377e311")
@@ -45,10 +44,13 @@ dependencies {
     compileOnly("com.github.Project-Cepi.Particable:common:ad9ec542a8")
 
     // import kotlinx serialization
-    compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1")
+    compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")
 
     // Add Kepi
     compileOnly("com.github.Project-Cepi:Kepi:991a24276e")
+
+    // Add MiniMessage
+    implementation("net.kyori:adventure-text-minimessage:4.10.1")
 }
 
 tasks.withType<Test> {
diff --git a/src/main/kotlin/world/cepi/region/api/Region.kt b/src/main/kotlin/world/cepi/region/api/Region.kt
index 751a3b9..327ec43 100644
--- a/src/main/kotlin/world/cepi/region/api/Region.kt
+++ b/src/main/kotlin/world/cepi/region/api/Region.kt
@@ -17,9 +17,6 @@ import org.jglrxavpok.hephaistos.nbt.NBTCompound
 import org.jglrxavpok.hephaistos.nbt.NBTCompoundLike
 import world.cepi.kstom.Manager
 import world.cepi.kstom.event.listenOnly
-import world.cepi.kstom.item.get
-import world.cepi.kstom.item.set
-import world.cepi.kstom.serializer.BossBarSerializer
 import world.cepi.kstom.serializer.ComponentSerializer
 import world.cepi.kstom.serializer.NBTSerializer
 import world.cepi.region.Selection
@@ -50,8 +47,10 @@ data class Region(
     var displayName: Component? = null,
 
     /** If this region's name is hidden */
-    var hidden: Boolean = false
-) : TagHandler {
+    var hidden: Boolean = false,
+
+    val states: MutableList<RegionState> = mutableListOf()
+) : TagHandler by TagHandler.newHandler() {
 
     /**
      * True, if this region contains at least one block.
@@ -60,18 +59,13 @@ data class Region(
     val defined: Boolean
         get() = selections.isEmpty()
 
-    @Serializable(with = NBTSerializer::class)
-    private val nbtCompound = NBTCompound()
-
-    val snapshots: MutableList<RegionSnapshot> = mutableListOf()
-
     /**
      * The volume of this region in cubic meters.
      */
     val volume: Int
         get() = selections
             .filter { selections.none { sel -> sel.containsAll(it) } }
-            .map { it.xRange.size * it.yRange.size * it.zRange.size }.sum()
+            .sumOf { it.xRange.size * it.yRange.size * it.zRange.size }
 
     /**
      * Checks if the given block position is inside of this
@@ -182,26 +176,6 @@ data class Region(
             }
         }
     }
-
-    override fun <T : Any?> getTag(tag: Tag<T>): T? {
-        return tag.read(nbtCompound)
-    }
-
-    override fun <T : Any?> setTag(tag: Tag<T>, value: T?) {
-        tag.write(nbtCompound.toMutableCompound(), value)
-    }
-
-    override fun readableCopy(): TagReadable {
-        TODO("Not yet implemented")
-    }
-
-    override fun updateContent(compound: NBTCompoundLike) {
-        TODO("Not yet implemented")
-    }
-
-    override fun asCompound(): NBTCompound {
-        TODO("Not yet implemented")
-    }
 }
 
 var Player.region: Region?
diff --git a/src/main/kotlin/world/cepi/region/api/RegionSnapshot.kt b/src/main/kotlin/world/cepi/region/api/RegionSnapshot.kt
deleted file mode 100644
index b5723f7..0000000
--- a/src/main/kotlin/world/cepi/region/api/RegionSnapshot.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package world.cepi.region.api
-
-import kotlinx.serialization.Serializable
-import world.cepi.region.size
-import java.time.LocalTime
-
-@Serializable
-data class RegionSnapshot(val blockStates: List<Short>) {
-    val time: Long = System.currentTimeMillis()
-
-    companion object {
-        fun from(region: Region) = region.selections.map { selection ->
-            selection.xRange.map { x ->
-                selection.yRange.map { y ->
-                    selection.zRange.map { z ->
-                        region.instance.getBlock(x, y, z).id()
-                    }
-                }.flatten()
-            }.flatten()
-        }.flatten()
-    }
-
-}
\ No newline at end of file
diff --git a/src/main/kotlin/world/cepi/region/api/RegionState.kt b/src/main/kotlin/world/cepi/region/api/RegionState.kt
new file mode 100644
index 0000000..186bdc7
--- /dev/null
+++ b/src/main/kotlin/world/cepi/region/api/RegionState.kt
@@ -0,0 +1,24 @@
+package world.cepi.region.api
+
+import kotlinx.serialization.Serializable
+import net.minestom.server.instance.block.Block
+import world.cepi.kstom.serializer.BlockSerializer
+
+@Serializable
+data class RegionState(val blockStates: List<@Serializable(with = BlockSerializer::class) Block>) {
+    companion object {
+        fun from(region: Region) = RegionState(region.selections.map { selection ->
+            selection.xRange.map { x ->
+                selection.yRange.map { y ->
+                    selection.zRange.map { z ->
+                        region.instance.getBlock(x, y, z)
+                    }
+                }.flatten()
+            }.flatten()
+        }.flatten())
+    }
+
+    fun put(region: Region) {
+        
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/world/cepi/region/command/RegionArguments.kt b/src/main/kotlin/world/cepi/region/command/RegionArguments.kt
index 3bde37b..9524ab6 100644
--- a/src/main/kotlin/world/cepi/region/command/RegionArguments.kt
+++ b/src/main/kotlin/world/cepi/region/command/RegionArguments.kt
@@ -17,7 +17,7 @@ object RegionArguments {
     }
 
     val existingRegion = ArgumentType.Word("region").map { name ->
-        RegionProvider[name]?: throw ArgumentSyntaxException("Invalid region", name, 1)
+        RegionProvider[name] ?: throw ArgumentSyntaxException("Invalid region", name, 1)
     }.suggest {
         RegionProvider.regions.values
             .map { it.name }
diff --git a/src/main/kotlin/world/cepi/region/command/RegionCommand.kt b/src/main/kotlin/world/cepi/region/command/RegionCommand.kt
index c601c4a..e36c103 100644
--- a/src/main/kotlin/world/cepi/region/command/RegionCommand.kt
+++ b/src/main/kotlin/world/cepi/region/command/RegionCommand.kt
@@ -54,15 +54,15 @@ object RegionCommand : Kommand({
         sender.sendFormattedTranslatableMessage("common", "world.none")
     }
 
-    syntax(spawn, existingRegion, amount).onlyPlayers {
-        if (!MobUtils.hasMobEgg(sender)) return@onlyPlayers
+    syntax(spawn, existingRegion, amount) {
+        if (!MobUtils.hasMobEgg(sender)) return@syntax
 
-        val mob = player.mobEgg ?: return@onlyPlayers
+        val mob = player.mobEgg ?: return@syntax
 
         repeat(!amount) {
             mob.spawnMob(player.instance!!, (!existingRegion).selections.random().random())
         }
-    }
+    }.onlyPlayers()
 
     syntax(create, regionName, world) {
         val instance = if (sender is Player) {
@@ -115,6 +115,6 @@ object RegionCommand : Kommand({
          """.trimIndent()
     }
 
-    addSubcommands(SelectionsSubcommand, MetaSubcommand)
+    addSubcommands(SelectionsSubcommand, MetaSubcommand, StateSubcommand)
 
 }, "region")
\ No newline at end of file
diff --git a/src/main/kotlin/world/cepi/region/command/subcommand/SelectionsSubcommand.kt b/src/main/kotlin/world/cepi/region/command/subcommand/SelectionsSubcommand.kt
index f6606e7..602e4b1 100644
--- a/src/main/kotlin/world/cepi/region/command/subcommand/SelectionsSubcommand.kt
+++ b/src/main/kotlin/world/cepi/region/command/subcommand/SelectionsSubcommand.kt
@@ -29,7 +29,7 @@ object SelectionsSubcommand : Kommand({
     val pos1 by literal
     val pos2 by literal
 
-    onlyPlayers
+    onlyPlayers()
 
     playerCallbackFailMessage = { sender ->
         sender.sendFormattedTranslatableMessage("common", "command.only_players")
diff --git a/src/main/kotlin/world/cepi/region/command/subcommand/StateSubcommand.kt b/src/main/kotlin/world/cepi/region/command/subcommand/StateSubcommand.kt
new file mode 100644
index 0000000..f667934
--- /dev/null
+++ b/src/main/kotlin/world/cepi/region/command/subcommand/StateSubcommand.kt
@@ -0,0 +1,15 @@
+package world.cepi.region.command.subcommand
+
+import world.cepi.kstom.command.arguments.literal
+import world.cepi.kstom.command.kommand.Kommand
+import world.cepi.region.api.RegionState
+import world.cepi.region.command.RegionArguments
+
+object StateSubcommand : Kommand({
+    val add by literal
+
+    syntax(RegionArguments.existingRegion, add) {
+        val region = (!RegionArguments.existingRegion)
+        region.states.add(RegionState.from(region))
+    }
+}, "state")
\ No newline at end of file
diff --git a/src/main/kotlin/world/cepi/region/serialization/InstanceSerializer.kt b/src/main/kotlin/world/cepi/region/serialization/InstanceSerializer.kt
index fba3f8c..787fe19 100644
--- a/src/main/kotlin/world/cepi/region/serialization/InstanceSerializer.kt
+++ b/src/main/kotlin/world/cepi/region/serialization/InstanceSerializer.kt
@@ -1,17 +1,12 @@
 package world.cepi.region.serialization
 
 import kotlinx.serialization.KSerializer
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
 import kotlinx.serialization.builtins.serializer
 import kotlinx.serialization.descriptors.SerialDescriptor
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
 import net.minestom.server.instance.Instance
 import world.cepi.kstom.Manager
-import world.cepi.region.Selection
-import world.cepi.region.api.Region
-import world.cepi.region.api.RegionSnapshot
 
 object InstanceSerializer : KSerializer<Instance> {
     override val descriptor: SerialDescriptor = String.serializer().descriptor