Skip to content

Instantly share code, notes, and snippets.

@derkalaender
Created April 7, 2020 22:45
Show Gist options
  • Save derkalaender/d71cb31c69b5e972152ecf8a9728d65f to your computer and use it in GitHub Desktop.
Save derkalaender/d71cb31c69b5e972152ecf8a9728d65f to your computer and use it in GitHub Desktop.
Minecraft/Forge NBT DSL
abstract class ItemNBTHolder(val stack: ItemStack, val compound: CompoundNBT) {
protected fun byte(defaultValue: Byte) = SimpleNBTDelegate(defaultValue, CompoundNBT::getByte, CompoundNBT::putByte)
protected fun short(defaultValue: Short) = SimpleNBTDelegate(defaultValue, CompoundNBT::getShort, CompoundNBT::putShort)
protected fun int(defaultValue: Int) = SimpleNBTDelegate(defaultValue, CompoundNBT::getInt, CompoundNBT::putInt)
protected fun long(defaultValue: Long) = SimpleNBTDelegate(defaultValue, CompoundNBT::getLong, CompoundNBT::putLong)
protected fun float(defaultValue: Float) = SimpleNBTDelegate(defaultValue, CompoundNBT::getFloat, CompoundNBT::putFloat)
protected fun double(defaultValue: Double) = SimpleNBTDelegate(defaultValue, CompoundNBT::getDouble, CompoundNBT::putDouble)
protected fun string(defaultValue: String) = SimpleNBTDelegate(defaultValue, CompoundNBT::getString, CompoundNBT::putString)
protected fun byteArray(defaultValue: ByteArray = ByteArray(0)) = SimpleNBTDelegate(defaultValue, CompoundNBT::getByteArray, CompoundNBT::putByteArray)
protected fun intArray(defaultValue: IntArray = IntArray(0)) = SimpleNBTDelegate(defaultValue, CompoundNBT::getIntArray, CompoundNBT::putIntArray)
protected fun longArray(defaultValue: LongArray = LongArray(0)) = SimpleNBTDelegate(defaultValue, CompoundNBT::getLongArray, CompoundNBT::putLongArray)
protected fun boolean(defaultValue: Boolean) = SimpleNBTDelegate(defaultValue, CompoundNBT::getBoolean, CompoundNBT::putBoolean)
protected fun uuid() = object : MutableNBTDelegate<UUID?>() {
override fun getValue(stack: ItemStack, compound: CompoundNBT, tag: String): UUID? {
return if (isTagExisting(stack, tag + "Most") && isTagExisting(stack, tag + "Least")) {
compound.getUniqueId(tag)
} else {
null
}
}
override fun setValue(stack: ItemStack, compound: CompoundNBT, tag: String, value: UUID?) {
if (value != null) {
compound.putUniqueId(tag, value)
}
}
}
protected fun <R : ItemNBTHolder> compound(nested: (ItemStack, CompoundNBT) -> R) = object : NBTDelegate<CompoundHelper<R>>() {
override fun getValue(stack: ItemStack, compound: CompoundNBT, tag: String): CompoundHelper<R> {
return if (isTagExisting(stack, tag)) {
val newCompound = compound.getCompound(tag)
CompoundHelper(nested(stack, compound.getCompound(tag)), { compound.put(tag, newCompound) })
} else {
val newCompound = CompoundNBT()
CompoundHelper(nested(stack, newCompound), { compound.put(tag, newCompound) })
}
}
}
}
class CompoundHelper<T : ItemNBTHolder>(private val holder: T, private val callback: () -> Unit) {
operator fun <R> invoke(func: T.() -> R): R {
val result = func(holder)
callback()
return result
}
}
abstract class NBTDelegate<R> : ReadOnlyProperty<ItemNBTHolder, R> {
protected fun isTagExisting(stack: ItemStack, tag: String) = !stack.isEmpty && stack.orCreateTag.contains(tag)
abstract fun getValue(stack: ItemStack, compound: CompoundNBT, tag: String): R
override fun getValue(thisRef: ItemNBTHolder, property: KProperty<*>) = getValue(thisRef.stack, thisRef.compound, property.name)
}
abstract class MutableNBTDelegate<R> : NBTDelegate<R>(), ReadWriteProperty<ItemNBTHolder, R> {
abstract fun setValue(stack: ItemStack, compound: CompoundNBT, tag: String, value: R)
override fun setValue(thisRef: ItemNBTHolder, property: KProperty<*>, value: R) = setValue(thisRef.stack, thisRef.compound, property.name, value)
}
class SimpleNBTDelegate<R : Any>(private val defaultValue: R, private val getter: CompoundNBT.(String) -> R, private val setter: CompoundNBT.(String, R) -> Unit) : MutableNBTDelegate<R>() {
override fun getValue(stack: ItemStack, compound: CompoundNBT, tag: String): R {
return if (isTagExisting(stack, tag)) {
getter(compound, tag)
} else {
defaultValue
}
}
override fun setValue(stack: ItemStack, compound: CompoundNBT, tag: String, value: R) {
setter(compound, tag, value)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment