diff --git a/gradle.properties b/gradle.properties
index 7d4b79e..3cbb336 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,7 +4,7 @@ kotlin.code.style=official
 specifyKotlinAsDependency=false
 
 projectGroup=ru.dbotthepony.kommons
-projectVersion=2.9.11
+projectVersion=2.9.12
 
 guavaDepVersion=33.0.0
 gsonDepVersion=2.8.9
diff --git a/src/main/kotlin/ru/dbotthepony/kommons/io/DelegateSyncher.kt b/src/main/kotlin/ru/dbotthepony/kommons/io/DelegateSyncher.kt
index 873c2f7..95ec089 100644
--- a/src/main/kotlin/ru/dbotthepony/kommons/io/DelegateSyncher.kt
+++ b/src/main/kotlin/ru/dbotthepony/kommons/io/DelegateSyncher.kt
@@ -24,7 +24,11 @@ import java.util.concurrent.ConcurrentLinkedQueue
 import java.util.concurrent.CopyOnWriteArrayList
 import java.util.concurrent.atomic.AtomicBoolean
 import java.util.concurrent.locks.ReentrantLock
+import java.util.function.BooleanSupplier
 import java.util.function.Consumer
+import java.util.function.DoubleSupplier
+import java.util.function.IntSupplier
+import java.util.function.LongSupplier
 import java.util.function.Supplier
 import kotlin.collections.ArrayList
 import kotlin.concurrent.withLock
@@ -139,6 +143,8 @@ class DelegateSyncher : Observer {
 	}
 
 	inner class Slot<V>(val delegate: ListenableDelegate<V>, val codec: StreamCodec<V>) : AbstractSlot(), ListenableDelegate<V> {
+		constructor(delegate: Supplier<V>, codec: StreamCodec<V>) : this(ListenableDelegate.CustomShadow(delegate, codec::compare, codec::copy), codec)
+
 		private val l = delegate.addListener(Consumer {
 			markDirty()
 			listeners.accept(it)
@@ -516,7 +522,7 @@ class DelegateSyncher : Observer {
 	}
 
 	fun <V> add(delegate: Supplier<V>, codec: StreamCodec<V>): Slot<V> {
-		return Slot(ListenableDelegate.CustomShadow(delegate, codec::compare, codec::copy), codec)
+		return computed(delegate, codec)
 	}
 
 	fun <E> add(delegate: ListenableSet<E>, codec: StreamCodec<E>): SetSlot<E> {
@@ -527,6 +533,23 @@ class DelegateSyncher : Observer {
 		return MapSlot(delegate, keyCodec, valueCodec)
 	}
 
+	fun computedByte(delegate: Supplier<Byte>) = Slot(ListenableDelegate.Shadow(delegate), ByteValueCodec)
+	fun computedShort(delegate: Supplier<Short>) = Slot(ListenableDelegate.Shadow(delegate), ShortValueCodec)
+	fun computedChar(delegate: Supplier<Char>) = Slot(ListenableDelegate.Shadow(delegate), CharValueCodec)
+	fun computedInt(delegate: Supplier<Int>) = Slot(ListenableDelegate.Shadow(delegate), VarIntValueCodec)
+	fun computedLong(delegate: Supplier<Long>) = Slot(ListenableDelegate.Shadow(delegate), VarLongValueCodec)
+	fun computedFloat(delegate: Supplier<Float>) = Slot(ListenableDelegate.Shadow(delegate), FloatValueCodec)
+	fun computedDouble(delegate: Supplier<Double>) = Slot(ListenableDelegate.Shadow(delegate), DoubleValueCodec)
+	fun computedBoolean(delegate: Supplier<Boolean>) = Slot(ListenableDelegate.Shadow(delegate), BooleanValueCodec)
+	fun computedString(delegate: Supplier<String>) = Slot(ListenableDelegate.Shadow(delegate), BinaryStringCodec)
+	fun computedUUID(delegate: Supplier<UUID>) = Slot(ListenableDelegate.Shadow(delegate), UUIDValueCodec)
+	fun <V> computed(delegate: Supplier<V>, codec: StreamCodec<V>) = Slot(ListenableDelegate.CustomShadow(delegate, codec::compare, codec::copy), codec)
+
+	fun computedInt(delegate: IntSupplier) = Slot(ListenableDelegate.Shadow(delegate::getAsInt), VarIntValueCodec)
+	fun computedLong(delegate: LongSupplier) = Slot(ListenableDelegate.Shadow(delegate::getAsLong), VarLongValueCodec)
+	fun computedDouble(delegate: DoubleSupplier) = Slot(ListenableDelegate.Shadow(delegate::getAsDouble), DoubleValueCodec)
+	fun computedBoolean(delegate: BooleanSupplier) = Slot(ListenableDelegate.Shadow(delegate::getAsBoolean), BooleanValueCodec)
+
 	@JvmName("vbyte")
 	@JvmOverloads
 	fun byte(value: Byte = 0, setter: DelegateSetter<Byte> = DelegateSetter.passthrough(), getter: DelegateGetter<Byte> = DelegateGetter.passthrough()): Slot<Byte> {