Add Tags packet and send it during join procedure
This commit is contained in:
parent
d387842f95
commit
aa4f1d89f5
14 changed files with 153 additions and 42 deletions
|
@ -42,6 +42,10 @@ dependencies {
|
|||
|
||||
kotlin {
|
||||
sourceSets["main"].kotlin.srcDir("src/main/generatedKotlin")
|
||||
|
||||
sourceSets.all {
|
||||
languageSettings.enableLanguageFeature("InlineClasses")
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
|
6
blokk-api/src/main/kotlin/space/blokk/NamespacedID.kt
Normal file
6
blokk-api/src/main/kotlin/space/blokk/NamespacedID.kt
Normal file
|
@ -0,0 +1,6 @@
|
|||
package space.blokk
|
||||
|
||||
inline class NamespacedID(val value: String) {
|
||||
val namespace get() = value.substringBefore(":")
|
||||
val id get() = value.substringAfter(":")
|
||||
}
|
6
blokk-api/src/main/kotlin/space/blokk/recipe/Recipe.kt
Normal file
6
blokk-api/src/main/kotlin/space/blokk/recipe/Recipe.kt
Normal file
|
@ -0,0 +1,6 @@
|
|||
package space.blokk.recipe
|
||||
|
||||
sealed class Recipe {
|
||||
abstract val group: String
|
||||
// TODO
|
||||
}
|
|
@ -9,6 +9,7 @@ import space.blokk.logging.LoggingOutputProvider
|
|||
import space.blokk.net.Session
|
||||
import space.blokk.player.Player
|
||||
import space.blokk.plugin.PluginManager
|
||||
import space.blokk.recipe.Recipe
|
||||
import space.blokk.server.event.ServerEvent
|
||||
import java.io.File
|
||||
|
||||
|
@ -31,6 +32,8 @@ interface Server : EventTarget<ServerEvent> {
|
|||
val minimumLogLevel: Logger.Level
|
||||
val loggingOutputProvider: LoggingOutputProvider
|
||||
|
||||
val recipes: Set<Recipe>
|
||||
|
||||
/**
|
||||
* Creates a [ReceiveChannel] which emits [Unit] every tick.
|
||||
*
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
package space.blokk.tags
|
||||
|
||||
import space.blokk.NamespacedID
|
||||
import space.blokk.world.block.Material
|
||||
|
||||
class Tag(val name: String, val type: Type, val rawValues: List<String>) {
|
||||
val values: List<String> by lazy {
|
||||
rawValues.flatMap {
|
||||
if (it.startsWith("#")) TagRegistry.tags.getValue(it.removePrefix("#")).values
|
||||
else listOf(it)
|
||||
}
|
||||
val values: List<NamespacedID> = rawValues.flatMap {
|
||||
if (it.startsWith("#")) TagRegistry.tags.getValue(it.removePrefix("#")).values
|
||||
else listOf(NamespacedID(it))
|
||||
}
|
||||
|
||||
val numericIDs: List<Int> = when (type) {
|
||||
Type.BLOCKS -> values.map { Material.byID.getValue(it).numericID }
|
||||
else -> TODO()
|
||||
}
|
||||
|
||||
enum class Type {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package space.blokk.net.packet.play
|
||||
|
||||
import io.netty.buffer.ByteBuf
|
||||
import space.blokk.net.MinecraftProtocolDataTypes.writeVarInt
|
||||
import space.blokk.net.packet.OutgoingPacketCodec
|
||||
|
||||
object DeclareRecipesPacketCodec : OutgoingPacketCodec<DeclareRecipesPacket>(0x5B, DeclareRecipesPacket::class) {
|
||||
override fun DeclareRecipesPacket.encode(dst: ByteBuf) {
|
||||
dst.writeVarInt(recipes.size)
|
||||
for (recipe in recipes) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import space.blokk.net.packet.Protocol
|
|||
object PlayProtocol : Protocol(
|
||||
"PLAY",
|
||||
ClientSettingsPacketCodec,
|
||||
DeclareRecipesPacketCodec,
|
||||
DisconnectPacketCodec,
|
||||
IncomingPluginMessagePacketCodec,
|
||||
JoinGamePacketCodec,
|
||||
|
@ -14,5 +15,6 @@ object PlayProtocol : Protocol(
|
|||
PlayerPositionAndLookPacketCodec,
|
||||
ServerDifficultyPacketCodec,
|
||||
SetSelectedHotbarSlotPacketCodec,
|
||||
TagsPacketCodec,
|
||||
UpdateViewPositionPacketCodec
|
||||
)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package space.blokk.net.packet.play
|
||||
|
||||
import io.netty.buffer.ByteBuf
|
||||
import space.blokk.net.MinecraftProtocolDataTypes.writeString
|
||||
import space.blokk.net.MinecraftProtocolDataTypes.writeVarInt
|
||||
import space.blokk.net.packet.OutgoingPacketCodec
|
||||
import space.blokk.tags.Tag
|
||||
|
||||
object TagsPacketCodec : OutgoingPacketCodec<TagsPacket>(0x5C, TagsPacket::class) {
|
||||
override fun TagsPacket.encode(dst: ByteBuf) {
|
||||
listOf(
|
||||
tags.filter { it.type == Tag.Type.BLOCKS },
|
||||
tags.filter { it.type == Tag.Type.ITEMS },
|
||||
tags.filter { it.type == Tag.Type.FLUIDS },
|
||||
tags.filter { it.type == Tag.Type.ENTITY_TYPES }
|
||||
).forEach { tags ->
|
||||
dst.writeVarInt(tags.size)
|
||||
|
||||
tags.forEach { tag ->
|
||||
dst.writeString(tag.name)
|
||||
dst.writeVarInt(tag.values.size)
|
||||
tag.numericIDs.forEach { dst.writeVarInt(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package space.blokk.net.packet.play
|
||||
|
||||
import space.blokk.net.packet.OutgoingPacket
|
||||
import space.blokk.recipe.Recipe
|
||||
|
||||
/**
|
||||
* Sent by the server while the player is joining.
|
||||
*/
|
||||
data class DeclareRecipesPacket(val recipes: Set<Recipe>) : OutgoingPacket()
|
|
@ -0,0 +1,9 @@
|
|||
package space.blokk.net.packet.play
|
||||
|
||||
import space.blokk.net.packet.OutgoingPacket
|
||||
import space.blokk.tags.Tag
|
||||
|
||||
/**
|
||||
* Sent by the server while the player is joining.
|
||||
*/
|
||||
data class TagsPacket(val tags: Iterable<Tag>) : OutgoingPacket()
|
|
@ -11,6 +11,7 @@ import space.blokk.logging.Logger
|
|||
import space.blokk.net.BlokkSocketServer
|
||||
import space.blokk.player.Player
|
||||
import space.blokk.plugin.BlokkPluginManager
|
||||
import space.blokk.recipe.Recipe
|
||||
import space.blokk.server.Server
|
||||
import space.blokk.server.event.ServerEvent
|
||||
import space.blokk.util.EncryptionUtils
|
||||
|
@ -18,6 +19,7 @@ import space.blokk.util.Ticker
|
|||
import space.blokk.util.createUnconfinedSupervisorScope
|
||||
import java.io.File
|
||||
import java.security.KeyPair
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class BlokkServer internal constructor() : Server {
|
||||
|
@ -31,6 +33,8 @@ class BlokkServer internal constructor() : Server {
|
|||
override val players = EventTargetGroup.Mutable<Player>(true)
|
||||
override val pluginManager = BlokkPluginManager(this)
|
||||
|
||||
override val recipes: Set<Recipe> = CopyOnWriteArraySet()
|
||||
|
||||
val keyPair: KeyPair
|
||||
|
||||
init {
|
||||
|
|
|
@ -172,7 +172,7 @@ class LoginAndJoinProcedure(val session: BlokkSession) {
|
|||
|
||||
session.send(SetSelectedHotbarSlotPacket(state.selectedHotbarSlot))
|
||||
|
||||
// TODO: Send Declare Recipes packet
|
||||
session.send(DeclareRecipesPacket(session.server.recipes))
|
||||
// TODO: Send Tags packet
|
||||
// TODO: Send Entity Status packet with OP permission level
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@ package space.blokk.mdsp
|
|||
|
||||
import com.google.common.base.CaseFormat
|
||||
import com.jsoniter.JsonIterator
|
||||
import com.jsoniter.ValueType
|
||||
import com.squareup.kotlinpoet.*
|
||||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||
import space.blokk.mdsp.util.ConstructorPropertiesHelper
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class BlocksAndMaterialGenerator(
|
||||
private val workingDir: File,
|
||||
|
@ -15,6 +16,7 @@ class BlocksAndMaterialGenerator(
|
|||
companion object {
|
||||
const val BLOCK_PACKAGE = "space.blokk.world.block"
|
||||
val MATERIAL_TYPE = ClassName(BLOCK_PACKAGE, "Material")
|
||||
val NAMESPACED_ID_TYPE = ClassName("space.blokk", "NamespacedID")
|
||||
val BLOCK_TYPE = ClassName(BLOCK_PACKAGE, "Block")
|
||||
val K_CLASS_TYPE = ClassName("kotlin.reflect", "KClass")
|
||||
val MAP_TYPE = ClassName("kotlin.collections", "Map")
|
||||
|
@ -111,24 +113,30 @@ class BlocksAndMaterialGenerator(
|
|||
}
|
||||
|
||||
private fun generateMaterialEnum(blocks: List<JsonAny>, collisionShapeKeyByBlockName: MutableMap<String, JsonAny>) {
|
||||
val cph = ConstructorPropertiesHelper()
|
||||
|
||||
val builder = TypeSpec.enumBuilder("Material")
|
||||
.primaryConstructor(
|
||||
FunSpec.constructorBuilder()
|
||||
.addParameter("id", String::class)
|
||||
.addParameter(
|
||||
"blockType",
|
||||
K_CLASS_TYPE.parameterizedBy(WildcardTypeName.producerOf(BLOCK_TYPE))
|
||||
.addParameters(
|
||||
listOf(
|
||||
cph.create("numericID", Int::class),
|
||||
cph.create("id", NAMESPACED_ID_TYPE),
|
||||
cph.create(
|
||||
"blockType",
|
||||
K_CLASS_TYPE.parameterizedBy(WildcardTypeName.producerOf(BLOCK_TYPE))
|
||||
),
|
||||
cph.create("hardness", Float::class),
|
||||
cph.create("transparent", Boolean::class),
|
||||
cph.create("emittedLight", Int::class),
|
||||
cph.create("filteredLight", Int::class),
|
||||
cph.create("collisionShape", ClassName(BLOCK_PACKAGE, "CollisionShape")),
|
||||
cph.create("maxStackSize", Byte::class),
|
||||
)
|
||||
)
|
||||
.addParameter("hardness", Float::class)
|
||||
.addParameter("transparent", Boolean::class)
|
||||
.addParameter("emittedLight", Byte::class)
|
||||
.addParameter("filteredLight", Byte::class)
|
||||
.addParameter("collisionShape", ClassName(BLOCK_PACKAGE, "CollisionShape"))
|
||||
.addParameter("maxStackSize", Byte::class)
|
||||
.build()
|
||||
)
|
||||
|
||||
val materialNameByBlockClassName = mutableMapOf<String, String>()
|
||||
.addProperties(cph.getProperties())
|
||||
|
||||
for (block in blocks) {
|
||||
val name = block.get("name").toString()
|
||||
|
@ -136,12 +144,11 @@ class BlocksAndMaterialGenerator(
|
|||
val materialName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, name)
|
||||
val blockClassName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name)
|
||||
|
||||
materialNameByBlockClassName[blockClassName] = materialName
|
||||
|
||||
builder.addEnumConstant(
|
||||
materialName,
|
||||
TypeSpec.anonymousClassBuilder()
|
||||
.addSuperclassConstructorParameter("%S", "minecraft:$name")
|
||||
.addSuperclassConstructorParameter("%L", block.get("id").toInt())
|
||||
.addSuperclassConstructorParameter("%T(%S)", NAMESPACED_ID_TYPE, "minecraft:$name")
|
||||
.addSuperclassConstructorParameter(
|
||||
"%T::class",
|
||||
ClassName(
|
||||
|
@ -158,11 +165,8 @@ class BlocksAndMaterialGenerator(
|
|||
ClassName(
|
||||
BLOCK_PACKAGE,
|
||||
"CollisionShape",
|
||||
try {
|
||||
collisionShapeValue.asList()[0].toString()
|
||||
} catch (e: Exception) {
|
||||
collisionShapeValue.toInt().toString()
|
||||
}
|
||||
if (collisionShapeValue.valueType() == ValueType.ARRAY) collisionShapeValue.asList()[0].toString()
|
||||
else collisionShapeValue.toInt().toString()
|
||||
)
|
||||
)
|
||||
.addSuperclassConstructorParameter("%L", block.get("stackSize").toInt())
|
||||
|
@ -170,14 +174,6 @@ class BlocksAndMaterialGenerator(
|
|||
)
|
||||
}
|
||||
|
||||
val initializerTypes = materialNameByBlockClassName.toList()
|
||||
.flatMap { (blockClassName, materialName) ->
|
||||
listOf(
|
||||
ClassName(BLOCK_PACKAGE, blockClassName),
|
||||
ClassName(BLOCK_PACKAGE, "Material", materialName)
|
||||
)
|
||||
}
|
||||
|
||||
builder.addType(
|
||||
TypeSpec.companionObjectBuilder()
|
||||
.addProperty(
|
||||
|
@ -188,14 +184,18 @@ class BlocksAndMaterialGenerator(
|
|||
MATERIAL_TYPE
|
||||
)
|
||||
)
|
||||
.initializer(
|
||||
"mapOf(\n" +
|
||||
arrayOfNulls<String>(materialNameByBlockClassName.size)
|
||||
.apply { Arrays.fill(this, "%T::class to %T") }
|
||||
.joinToString(",\n") +
|
||||
"\n)",
|
||||
*initializerTypes.toTypedArray()
|
||||
.initializer("values().map { it.blockType to it }.toMap()")
|
||||
.build()
|
||||
)
|
||||
.addProperty(
|
||||
PropertySpec.builder(
|
||||
"byID",
|
||||
MAP_TYPE.parameterizedBy(
|
||||
NAMESPACED_ID_TYPE,
|
||||
MATERIAL_TYPE
|
||||
)
|
||||
)
|
||||
.initializer("values().map { it.id to it }.toMap()")
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package space.blokk.mdsp.util
|
||||
|
||||
import com.squareup.kotlinpoet.ParameterSpec
|
||||
import com.squareup.kotlinpoet.PropertySpec
|
||||
import com.squareup.kotlinpoet.TypeName
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class ConstructorPropertiesHelper {
|
||||
private val properties = mutableListOf<PropertySpec>()
|
||||
|
||||
fun create(name: String, type: TypeName): ParameterSpec {
|
||||
properties.add(PropertySpec.builder(name, type).initializer(name).build())
|
||||
return ParameterSpec.builder(name, type).build()
|
||||
}
|
||||
|
||||
fun create(name: String, type: KClass<*>): ParameterSpec {
|
||||
properties.add(PropertySpec.builder(name, type).initializer(name).build())
|
||||
return ParameterSpec.builder(name, type).build()
|
||||
}
|
||||
|
||||
fun getProperties() = properties.toList()
|
||||
}
|
Reference in a new issue