Add block codecs
This commit is contained in:
parent
653f62447c
commit
4cc3d8f17f
10 changed files with 159 additions and 20 deletions
|
@ -20,7 +20,7 @@ val striktVersion = properties["version.strikt"].toString()
|
|||
|
||||
dependencies {
|
||||
// Kotlin
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect:1.4.10")
|
||||
api("org.jetbrains.kotlin:kotlin-reflect:1.4.10")
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutinesVersion}")
|
||||
|
||||
// JSON
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package space.blokk.util
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
data class KPropertyValuePair<V>(val property: KProperty<V>, val value: V)
|
|
@ -1,13 +0,0 @@
|
|||
// IF YOU CHANGE THIS FILE, MOVE IT FROM `generatedKotlin` TO `kotlin` OR IT WILL BE OVERWRITTEN.
|
||||
package space.blokk.world.block
|
||||
|
||||
import space.blokk.world.block.interfaces.Button
|
||||
|
||||
/**
|
||||
* A block of type [ACACIA_BUTTON][Material.ACACIA_BUTTON]
|
||||
*/
|
||||
class AcaciaButton(
|
||||
ref: BlockRef
|
||||
) : Block(ref), Button {
|
||||
override var pressed: Boolean = false
|
||||
}
|
|
@ -1,5 +1,10 @@
|
|||
package space.blokk.world.block
|
||||
|
||||
import space.blokk.util.KPropertyValuePair
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.starProjectedType
|
||||
|
||||
/**
|
||||
* @param ref The [BlockRef] referencing this block.
|
||||
*/
|
||||
|
@ -26,4 +31,52 @@ abstract class Block internal constructor(val ref: BlockRef) {
|
|||
internal fun destroy() {
|
||||
onDestroy()
|
||||
}
|
||||
|
||||
abstract class Companion {
|
||||
abstract val codec: Codec<*>
|
||||
}
|
||||
|
||||
class Codec<T : Block> private constructor(
|
||||
val blockClass: KClass<out T>,
|
||||
val id: Int,
|
||||
val firstStateID: Int,
|
||||
val states: List<Array<KPropertyValuePair<*>>>
|
||||
) {
|
||||
companion object {
|
||||
inline fun <reified T : Block> id(id: Int, firstStateID: Int) = id(T::class, id, firstStateID)
|
||||
fun <T : Block> id(blockClass: KClass<out T>, id: Int, firstStateID: Int) =
|
||||
Builder(blockClass, id, firstStateID)
|
||||
}
|
||||
|
||||
class Builder<T : Block> internal constructor(
|
||||
private val blockClass: KClass<out T>,
|
||||
private val id: Int,
|
||||
private val firstStateID: Int
|
||||
) {
|
||||
private val attributeFields = mutableListOf<KProperty<Any>>()
|
||||
|
||||
fun attribute(property: KProperty<Any>) = this.apply { attributeFields.add(property) }
|
||||
|
||||
fun build() = Codec(blockClass, id, firstStateID, generateStates(attributeFields))
|
||||
|
||||
companion object {
|
||||
fun generateStates(properties: List<KProperty<Any>>): List<Array<KPropertyValuePair<*>>> {
|
||||
if (properties.isEmpty()) return emptyList()
|
||||
|
||||
val current = properties[0]
|
||||
println(current.returnType)
|
||||
val allowedValues = when (current.returnType) {
|
||||
Boolean::class.starProjectedType -> arrayOf(true, false)
|
||||
else -> TODO()
|
||||
}
|
||||
|
||||
val rest = generateStates(properties.drop(1))
|
||||
return allowedValues.flatMap { value ->
|
||||
if (rest.isEmpty()) listOf(arrayOf(KPropertyValuePair(current, value)))
|
||||
else rest.map { arrayOf(KPropertyValuePair(current, value), *it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package space.blokk.world.block.interfaces
|
||||
package space.blokk.world.block
|
||||
|
||||
interface Button {
|
||||
var pressed: Boolean
|
28
blokk-api/src/main/kotlin/space/blokk/world/block/Hopper.kt
Normal file
28
blokk-api/src/main/kotlin/space/blokk/world/block/Hopper.kt
Normal file
|
@ -0,0 +1,28 @@
|
|||
package space.blokk.world.block
|
||||
|
||||
/**
|
||||
* Material: [HOPPER][Material.HOPPER]
|
||||
*/
|
||||
class Hopper(
|
||||
ref: BlockRef
|
||||
) : Block(ref) {
|
||||
var enabled: Boolean = false
|
||||
|
||||
var facing: Facing = Facing.DOWN
|
||||
|
||||
enum class Facing {
|
||||
DOWN,
|
||||
NORTH,
|
||||
SOUTH,
|
||||
WEST,
|
||||
EAST
|
||||
}
|
||||
|
||||
companion object : Block.Companion() {
|
||||
override val codec = Codec
|
||||
.id<Hopper>(328, 6192)
|
||||
.attribute(Hopper::enabled)
|
||||
.attribute(Hopper::facing)
|
||||
.build()
|
||||
}
|
||||
}
|
25
blokk-block-codecs/build.gradle.kts
Normal file
25
blokk-block-codecs/build.gradle.kts
Normal file
|
@ -0,0 +1,25 @@
|
|||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
group = rootProject.group
|
||||
version = rootProject.version
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
kotlinOptions.freeCompilerArgs = listOf(
|
||||
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
"-progressive"
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package space.blokk.world.block.codec
|
||||
|
||||
class AcaciaButtonCodec {
|
||||
}
|
|
@ -16,6 +16,7 @@ import space.blokk.server.Server
|
|||
import space.blokk.server.event.ServerEvent
|
||||
import space.blokk.util.EncryptionUtils
|
||||
import space.blokk.util.Ticker
|
||||
import space.blokk.world.block.Hopper
|
||||
import java.io.File
|
||||
import java.security.KeyPair
|
||||
import kotlin.system.exitProcess
|
||||
|
@ -94,6 +95,10 @@ class BlokkServer internal constructor() : Server {
|
|||
logger info "Listening on ${config.host}:${config.port}"
|
||||
|
||||
ticker.start()
|
||||
|
||||
Hopper.codec.states.forEach {
|
||||
println(it.map { it.toString() })
|
||||
}
|
||||
}
|
||||
|
||||
override fun shutdown() {
|
||||
|
|
|
@ -11,11 +11,15 @@ typealias JsonAny = com.jsoniter.any.Any
|
|||
|
||||
class FilesGenerator(private val dataDir: File, private val outputDir: File, private val sourcesDir: File) {
|
||||
companion object {
|
||||
const val IMPORT_FOR_REMOVAL_PACKAGE_NAME = "IMPORT_FOR_REMOVAL"
|
||||
const val PROPERTY_TYPE_FOR_REMOVAL_NAME = "PROPERTY_TYPE_FOR_REMOVAL"
|
||||
|
||||
const val API_PACKAGE = "space.blokk"
|
||||
const val BLOCK_PACKAGE = "space.blokk.world.block"
|
||||
val MATERIAL_TYPE = ClassName(BLOCK_PACKAGE, "Material")
|
||||
val BLOCK_TYPE = ClassName(BLOCK_PACKAGE, "Block")
|
||||
val BLOCK_REF_TYPE = ClassName(BLOCK_PACKAGE, "BlockRef")
|
||||
val BLOCK_CODEC_TYPE = BLOCK_TYPE.nestedClass("Codec")
|
||||
val K_CLASS_TYPE = ClassName("kotlin.reflect", "KClass")
|
||||
val MAP_TYPE = ClassName("kotlin.collections", "Map")
|
||||
}
|
||||
|
@ -74,11 +78,11 @@ class FilesGenerator(private val dataDir: File, private val outputDir: File, pri
|
|||
val upperUnderscoreName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, lowerUnderscoreName)
|
||||
val specificMaterialType = MATERIAL_TYPE.nestedClass(upperUnderscoreName)
|
||||
|
||||
if (sourcesDir.resolve("./${BLOCK_PACKAGE.replace(".", "/")}/$upperCamelName.kt").exists())
|
||||
continue
|
||||
val filePathRelativeToSourceRoot = "./${BLOCK_PACKAGE.replace(".", "/")}/$upperCamelName.kt"
|
||||
if (sourcesDir.resolve(filePathRelativeToSourceRoot).exists()) continue
|
||||
|
||||
val type = TypeSpec.classBuilder(upperCamelName)
|
||||
.addKdoc("A block of type [$upperUnderscoreName][%T]", specificMaterialType)
|
||||
.addKdoc("Material: [$upperUnderscoreName][%T]", specificMaterialType)
|
||||
.superclass(BLOCK_TYPE)
|
||||
.primaryConstructor(
|
||||
FunSpec.constructorBuilder()
|
||||
|
@ -86,13 +90,41 @@ class FilesGenerator(private val dataDir: File, private val outputDir: File, pri
|
|||
.build()
|
||||
)
|
||||
.addSuperclassConstructorParameter("ref")
|
||||
.addType(
|
||||
TypeSpec.companionObjectBuilder()
|
||||
.superclass(BLOCK_TYPE.nestedClass("Companion"))
|
||||
.addProperty(
|
||||
PropertySpec.builder(
|
||||
"codec",
|
||||
ClassName(IMPORT_FOR_REMOVAL_PACKAGE_NAME, PROPERTY_TYPE_FOR_REMOVAL_NAME),
|
||||
KModifier.OVERRIDE
|
||||
)
|
||||
.initializer(
|
||||
"""
|
||||
%T
|
||||
.id<${upperCamelName}>(${block.get("id").toInt()}, ${
|
||||
block.get("minStateId").toInt()
|
||||
})
|
||||
// .attribute(${upperCamelName}::PROPERTY)
|
||||
.build()
|
||||
""".trimIndent(), BLOCK_CODEC_TYPE
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
|
||||
FileSpec.builder(BLOCK_PACKAGE, upperCamelName)
|
||||
val fileContent = FileSpec.builder(BLOCK_PACKAGE, upperCamelName)
|
||||
.addComment("IF YOU CHANGE THIS FILE, MOVE IT FROM `generatedKotlin` TO `kotlin` OR IT WILL BE OVERWRITTEN.")
|
||||
.addType(type)
|
||||
.build()
|
||||
.writeTo(outputDir)
|
||||
.toString()
|
||||
.replaceFirst("\n\nimport $IMPORT_FOR_REMOVAL_PACKAGE_NAME.$PROPERTY_TYPE_FOR_REMOVAL_NAME", "")
|
||||
.replaceFirst(": $PROPERTY_TYPE_FOR_REMOVAL_NAME", "")
|
||||
.replaceFirst("Block.Codec", "Codec")
|
||||
|
||||
outputDir.resolve(filePathRelativeToSourceRoot).writeText(fileContent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue