diff --git a/build.gradle.kts b/build.gradle.kts index 82b0aaf9e..44287ca7e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -56,7 +56,7 @@ dependencies { // Networking api("io.ktor:ktor-server-netty:3.1.2") - api("io.github.dockyardmc:tide:3.1") + api("io.github.dockyardmc:tide:3.7") api("io.github.dockyardmc:bytesocks-client-java:1.0-SNAPSHOT") { exclude(module = "slf4j-api") } diff --git a/custom_codec_definitions.json b/custom_codec_definitions.json index 2d771c706..095ab0da5 100644 --- a/custom_codec_definitions.json +++ b/custom_codec_definitions.json @@ -1,8 +1,10 @@ { "codec": { - "Component": "ComponentCodecs.STRING" + "Component": "ComponentCodecs.STRING", + "PotionEffect": "RegistryCodec.codec(PotionEffectRegistry)" }, "stream_codec": { - "Component": "ComponentCodecs.STREAM" + "Component": "ComponentCodecs.STREAM", + "PotionEffect": "RegistryCodec.stream(PotionEffectRegistry)" } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/codec/DurationCodec.kt b/src/main/kotlin/io/github/dockyardmc/codec/DurationCodec.kt new file mode 100644 index 000000000..0496296fd --- /dev/null +++ b/src/main/kotlin/io/github/dockyardmc/codec/DurationCodec.kt @@ -0,0 +1,38 @@ +package io.github.dockyardmc.codec + +import io.github.dockyardmc.extentions.readVarInt +import io.github.dockyardmc.extentions.writeVarInt +import io.github.dockyardmc.scheduler.runnables.inWholeMinecraftTicks +import io.github.dockyardmc.scheduler.runnables.ticks +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.stream.StreamCodec +import io.github.dockyardmc.tide.transcoder.Transcoder +import io.netty.buffer.ByteBuf +import kotlin.time.Duration + +object DurationCodec { + + val STREAM_CODEC_INT_TICKS = object : StreamCodec { + + override fun write(buffer: ByteBuf, value: Duration) { + buffer.writeVarInt(value.inWholeMinecraftTicks) + } + + override fun read(buffer: ByteBuf): Duration { + return buffer.readVarInt().ticks + } + } + + val CODEC_INT_TICKS = object : Codec { + + override fun encode(transcoder: Transcoder, value: Duration): D { + return transcoder.encodeInt(value.inWholeMinecraftTicks) + } + + override fun decode(transcoder: Transcoder, value: D): Duration { + return transcoder.decodeInt(value).ticks + + } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/codec/LocationCodecs.kt b/src/main/kotlin/io/github/dockyardmc/codec/LocationCodecs.kt new file mode 100644 index 000000000..10923b34a --- /dev/null +++ b/src/main/kotlin/io/github/dockyardmc/codec/LocationCodecs.kt @@ -0,0 +1,22 @@ +package io.github.dockyardmc.codec + +import io.github.dockyardmc.maths.vectors.Vector3 +import io.github.dockyardmc.tide.stream.StreamCodec + +object LocationCodecs { + + val BLOCK_POSITION = StreamCodec.LONG.transform( + { from -> + val blockX = from.x.toLong() + val blockY = from.y.toLong() + val blockZ = from.z.toLong() + (blockX and 0x3FFFFFF shl 38) or ((blockZ and 0x3FFFFFF) shl 12) or (blockY and 0xFFF) + }, + { to -> + val x = (to shr 38).toInt() + val y = (to shl 52 shr 52).toInt() + val z = (to shl 26 shr 38).toInt() + Vector3(x, y, z) + }) + +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/codec/transcoder/BinaryTagTranscoder.kt b/src/main/kotlin/io/github/dockyardmc/codec/transcoder/BinaryTagTranscoder.kt index cdaaae1c9..f22d2f414 100644 --- a/src/main/kotlin/io/github/dockyardmc/codec/transcoder/BinaryTagTranscoder.kt +++ b/src/main/kotlin/io/github/dockyardmc/codec/transcoder/BinaryTagTranscoder.kt @@ -125,7 +125,7 @@ object BinaryTagTranscoder : Transcoder { } override fun put(key: String, value: BinaryTag): Transcoder.VirtualMapBuilder { - compound.put(key, value) + if (value !is EndBinaryTag) compound.put(key, value) return this } } diff --git a/src/main/kotlin/io/github/dockyardmc/codec/transcoder/CRC32CTranscoder.kt b/src/main/kotlin/io/github/dockyardmc/codec/transcoder/CRC32CTranscoder.kt new file mode 100644 index 000000000..2e9afb52e --- /dev/null +++ b/src/main/kotlin/io/github/dockyardmc/codec/transcoder/CRC32CTranscoder.kt @@ -0,0 +1,146 @@ +package io.github.dockyardmc.codec.transcoder + +import io.github.dockyardmc.data.CRC32CHasher +import io.github.dockyardmc.data.CRC32CHasher.EMPTY +import io.github.dockyardmc.data.Hasher +import io.github.dockyardmc.tide.transcoder.Transcoder + +object CRC32CTranscoder : Transcoder { + + override fun encodeBoolean(value: Boolean): Int { + return if (value) CRC32CHasher.TRUE else CRC32CHasher.FALSE + } + + override fun encodeByte(value: Byte): Int { + return CRC32CHasher.ofByte(value) + } + + override fun encodeDouble(value: Double): Int { + return CRC32CHasher.ofDouble(value) + } + + override fun encodeFloat(value: Float): Int { + return CRC32CHasher.ofFloat(value) + } + + override fun encodeInt(value: Int): Int { + return CRC32CHasher.ofInt(value) + } + + override fun encodeList(size: Int): Transcoder.ListBuilder { + val hasher = Hasher().putByte(CRC32CHasher.TAG_LIST_START) + return object : Transcoder.ListBuilder { + + override fun add(value: Int): Transcoder.ListBuilder { + hasher.putIntBytes(value) + return this + } + + override fun build(): Int { + return hasher.putByte(CRC32CHasher.TAG_LIST_END).hash() + } + + } + } + + override fun encodeLong(value: Long): Int { + return CRC32CHasher.ofLong(value) + } + + override fun encodeMap(): Transcoder.VirtualMapBuilder { + val map = mutableMapOf() + return object : Transcoder.VirtualMapBuilder { + + override fun put(key: Int, value: Int): Transcoder.VirtualMapBuilder { + if (value != EMPTY) { + map[key] = value + } + return this + } + + override fun build(): Int { + if (map.isEmpty()) return CRC32CHasher.EMPTY_MAP + val hasher = Hasher().putByte(CRC32CHasher.TAG_MAP_START) + + map.entries.stream().sorted(CRC32CHasher.MAP_COMPARATOR).forEach { entry -> + hasher.putIntBytes(entry.key) + hasher.putIntBytes(entry.value) + } + + return hasher.putByte(CRC32CHasher.TAG_MAP_END).hash() + + } + + override fun put(key: String, value: Int): Transcoder.VirtualMapBuilder { + return put(encodeString(key), value) + } + + } + } + + override fun encodeNull(): Int { + return EMPTY + } + + override fun encodeShort(value: Short): Int { + return CRC32CHasher.ofShort(value) + } + + override fun encodeString(value: String): Int { + return CRC32CHasher.ofString(value) + } + + override fun encodeByteArray(value: ByteArray): Int { + return CRC32CHasher.ofByteArray(value) + } + + override fun encodeIntArray(value: IntArray): Int { + return CRC32CHasher.ofIntArray(value) + } + + override fun encodeLongArray(value: LongArray): Int { + return CRC32CHasher.ofLongArray(value) + } + + // only encode, fuck the decoding + + override fun decodeBoolean(value: Int): Boolean { + throw UnsupportedOperationException() + } + + override fun decodeByte(value: Int): Byte { + throw UnsupportedOperationException() + } + + override fun decodeDouble(value: Int): Double { + throw UnsupportedOperationException() + } + + override fun decodeFloat(value: Int): Float { + throw UnsupportedOperationException() + } + + override fun decodeInt(value: Int): Int { + throw UnsupportedOperationException() + } + + override fun decodeList(value: Int): List { + throw UnsupportedOperationException() + } + + override fun decodeLong(value: Int): Long { + throw UnsupportedOperationException() + } + + override fun decodeMap(value: Int): Transcoder.VirtualMap { + throw UnsupportedOperationException() + } + + override fun decodeShort(value: Int): Short { + throw UnsupportedOperationException() + } + + override fun decodeString(value: Int): String { + throw UnsupportedOperationException() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/data/CRC32CHasher.kt b/src/main/kotlin/io/github/dockyardmc/data/CRC32CHasher.kt index 96f246d9c..a9ea7e77f 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/CRC32CHasher.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/CRC32CHasher.kt @@ -12,9 +12,9 @@ object CRC32CHasher { // should have 0 probability to appear as CRC32C hash due to odd parity, we can use it as marker for inline values in maps const val INLINE: Int = 0x00000001 - private val KEY_COMPARATOR: Comparator> = java.util.Map.Entry.comparingByKey(Comparator.comparingLong { x: Int -> Integer.toUnsignedLong(x) }) - private val VALUE_COMPARATOR: Comparator> = java.util.Map.Entry.comparingByValue(Comparator.comparingLong { x: Int -> Integer.toUnsignedLong(x) }) - private val MAP_COMPARATOR: Comparator> = KEY_COMPARATOR.thenComparing(VALUE_COMPARATOR) + val KEY_COMPARATOR: Comparator> = java.util.Map.Entry.comparingByKey(Comparator.comparingLong { x: Int -> Integer.toUnsignedLong(x) }) + val VALUE_COMPARATOR: Comparator> = java.util.Map.Entry.comparingByValue(Comparator.comparingLong { x: Int -> Integer.toUnsignedLong(x) }) + val MAP_COMPARATOR: Comparator> = KEY_COMPARATOR.thenComparing(VALUE_COMPARATOR) const val TAG_EMPTY: Byte = 1 const val TAG_MAP_START: Byte = 2 diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/ArmorTrimComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/ArmorTrimComponent.kt index 03d5e2f73..1e6f98153 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/ArmorTrimComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/ArmorTrimComponent.kt @@ -1,37 +1,44 @@ package io.github.dockyardmc.data.components -import io.github.dockyardmc.data.CRC32CHasher +import io.github.dockyardmc.codec.RegistryCodec +import io.github.dockyardmc.codec.transcoder.CRC32CTranscoder import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.HashHolder -import io.github.dockyardmc.extentions.readRegistryEntry -import io.github.dockyardmc.extentions.writeRegistryEntry +import io.github.dockyardmc.data.StaticHash import io.github.dockyardmc.protocol.NetworkReadable import io.github.dockyardmc.registry.registries.TrimMaterial import io.github.dockyardmc.registry.registries.TrimMaterialRegistry import io.github.dockyardmc.registry.registries.TrimPattern import io.github.dockyardmc.registry.registries.TrimPatternRegistry +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import io.netty.buffer.ByteBuf -class ArmorTrimComponent(val material: TrimMaterial, val pattern: TrimPattern) : DataComponent() { +data class ArmorTrimComponent(val material: TrimMaterial, val pattern: TrimPattern) : DataComponent() { override fun write(buffer: ByteBuf) { - buffer.writeRegistryEntry(material) - buffer.writeRegistryEntry(pattern) + STREAM_CODEC.write(buffer, this) } override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - static("material", CRC32CHasher.ofRegistryEntry(material)) - static("pattern", CRC32CHasher.ofRegistryEntry(pattern)) - } + return StaticHash(CODEC.encode(CRC32CTranscoder, this)) } companion object : NetworkReadable { + val CODEC = StructCodec.of( + "material", RegistryCodec.codec(TrimMaterialRegistry), ArmorTrimComponent::material, + "pattern", RegistryCodec.codec(TrimPatternRegistry), ArmorTrimComponent::pattern, + ::ArmorTrimComponent + ) + + val STREAM_CODEC = StreamCodec.of( + RegistryCodec.stream(TrimMaterialRegistry), ArmorTrimComponent::material, + RegistryCodec.stream(TrimPatternRegistry), ArmorTrimComponent::pattern, + ::ArmorTrimComponent + ) + override fun read(buffer: ByteBuf): ArmorTrimComponent { - return ArmorTrimComponent( - buffer.readRegistryEntry(TrimMaterialRegistry), - buffer.readRegistryEntry(TrimPatternRegistry), - ) + return STREAM_CODEC.read(buffer) } } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/BlockEntityDataComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/BlockEntityDataComponent.kt index 292381549..7e9dedc27 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/BlockEntityDataComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/BlockEntityDataComponent.kt @@ -2,7 +2,6 @@ package io.github.dockyardmc.data.components import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.HashHolder -import io.github.dockyardmc.extentions.readNBT import io.github.dockyardmc.extentions.readNBTCompound import io.github.dockyardmc.extentions.writeNBT import io.github.dockyardmc.protocol.NetworkReadable @@ -16,7 +15,7 @@ class BlockEntityDataComponent(val nbt: CompoundBinaryTag) : DataComponent() { } override fun hashStruct(): HashHolder { - return unsupported(this::class) + return unsupported(this) } companion object : NetworkReadable { diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/BlocksAttacksComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/BlocksAttacksComponent.kt index ee64bfce4..56cc64366 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/BlocksAttacksComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/BlocksAttacksComponent.kt @@ -1,130 +1,153 @@ package io.github.dockyardmc.data.components +import io.github.dockyardmc.codec.RegistryCodec +import io.github.dockyardmc.codec.transcoder.CRC32CTranscoder import io.github.dockyardmc.data.CRC32CHasher import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.HashHolder -import io.github.dockyardmc.extentions.readVarInt -import io.github.dockyardmc.extentions.toSoundEvent -import io.github.dockyardmc.extentions.writeVarInt -import io.github.dockyardmc.protocol.* -import io.github.dockyardmc.protocol.types.readList -import io.github.dockyardmc.protocol.types.writeList +import io.github.dockyardmc.data.StaticHash +import io.github.dockyardmc.protocol.DataComponentHashable +import io.github.dockyardmc.protocol.NetworkReadable +import io.github.dockyardmc.protocol.NetworkWritable +import io.github.dockyardmc.registry.registries.DamageType +import io.github.dockyardmc.registry.registries.DamageTypeRegistry import io.github.dockyardmc.registry.registries.EntityType import io.github.dockyardmc.registry.registries.EntityTypeRegistry -import io.github.dockyardmc.sounds.CustomSoundEvent import io.github.dockyardmc.sounds.SoundEvent +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import io.netty.buffer.ByteBuf -class BlocksAttacksComponent( +data class BlocksAttacksComponent( val blocksDelaySeconds: Float, val disableCooldownScale: Float, val damageReductions: List, val itemDamageFunction: ItemDamageFunction, - val bypassedBy: List?, - val blockSound: String?, - val disableSound: String? + val bypassedBy: DamageType?, + val blockSound: SoundEvent?, + val disableSound: SoundEvent? ) : DataComponent() { companion object : NetworkReadable { - const val BLOCKS_DELAY_SECONDS_DEFAULT = 0f - const val DISABLE_COOLDOWN_SCALE_DEFAULT = 1f + + val CODEC = StructCodec.of( + "blocks_delay_seconds", Codec.FLOAT.default(0f), BlocksAttacksComponent::blocksDelaySeconds, + "disable_cooldown_scale", Codec.FLOAT.default(1f), BlocksAttacksComponent::disableCooldownScale, + "damage_reductions", DamageReduction.CODEC.list().default(listOf(DamageReduction.DEFAULT)), BlocksAttacksComponent::damageReductions, + "item_damage", ItemDamageFunction.CODEC.default(ItemDamageFunction.DEFAULT), BlocksAttacksComponent::itemDamageFunction, + "bypassed_by", RegistryCodec.codec(DamageTypeRegistry).optional(), BlocksAttacksComponent::bypassedBy, + "block_sound", SoundEvent.CODEC.optional(), BlocksAttacksComponent::blockSound, + "disabled_sound", SoundEvent.CODEC.optional(), BlocksAttacksComponent::disableSound, + ::BlocksAttacksComponent + ) + + val STREAM_CODEC = StreamCodec.of( + StreamCodec.FLOAT, BlocksAttacksComponent::blocksDelaySeconds, + StreamCodec.FLOAT, BlocksAttacksComponent::disableCooldownScale, + DamageReduction.STREAM_CODEC.list(), BlocksAttacksComponent::damageReductions, + ItemDamageFunction.STREAM_CODEC, BlocksAttacksComponent::itemDamageFunction, + RegistryCodec.stream(DamageTypeRegistry).optional(), BlocksAttacksComponent::bypassedBy, + SoundEvent.STREAM_CODEC.optional(), BlocksAttacksComponent::blockSound, + SoundEvent.STREAM_CODEC.optional(), BlocksAttacksComponent::disableSound, + ::BlocksAttacksComponent + ) override fun read(buffer: ByteBuf): BlocksAttacksComponent { - return BlocksAttacksComponent( - buffer.readFloat(), - buffer.readFloat(), - buffer.readList(DamageReduction::read), - ItemDamageFunction.read(buffer), - buffer.readOptional { b -> b.readList(ByteBuf::readVarInt).map { int -> EntityTypeRegistry.getByProtocolId(int) } }, - SoundEvent.read(buffer).identifier, - SoundEvent.read(buffer).identifier, - ) + return STREAM_CODEC.read(buffer) } } override fun write(buffer: ByteBuf) { - buffer.writeFloat(blocksDelaySeconds) - buffer.writeFloat(disableCooldownScale) - buffer.writeList(damageReductions, DamageReduction::write) - itemDamageFunction.write(buffer) - buffer.writeOptionalList(bypassedBy?.map { type -> type.getProtocolId() }, ByteBuf::writeVarInt) - buffer.writeOptional(blockSound?.toSoundEvent(), CustomSoundEvent::write) - buffer.writeOptional(disableSound?.toSoundEvent(), CustomSoundEvent::write) + STREAM_CODEC.write(buffer, this) } override fun hashStruct(): HashHolder { - return unsupported(this::class) -// return CRC32CHasher.of { -// default("block_delay_seconds", BLOCKS_DELAY_SECONDS_DEFAULT, blocksDelaySeconds, CRC32CHasher::ofFloat) -// default("disable_cooldown_scale", DISABLE_COOLDOWN_SCALE_DEFAULT, disableCooldownScale, CRC32CHasher::ofFloat) -// defaultStructList("damage_reductions", listOf(DamageReduction.DEFAULT), damageReductions, DamageReduction::hashStruct) -// defaultStruct("item_damage", ItemDamageFunction.DEFAULT, itemDamageFunction, ItemDamageFunction::hashStruct) -// optionalList("bypassed_by", bypassedBy?.map { type -> type.getEntryIdentifier() }, CRC32CHasher::ofString) -// optional("block_sound") + return StaticHash(CODEC.encode(CRC32CTranscoder, this)) } -} + data class ItemDamageFunction(val threshold: Float, val base: Float, val factor: Float) : NetworkWritable, DataComponentHashable { -data class ItemDamageFunction(val threshold: Float, val base: Float, val factor: Float) : NetworkWritable, DataComponentHashable { + companion object : NetworkReadable { - override fun write(buffer: ByteBuf) { - buffer.writeFloat(threshold) - buffer.writeFloat(base) - buffer.writeFloat(factor) - } + val DEFAULT = ItemDamageFunction(1f, 0f, 1f) - companion object : NetworkReadable { + val STREAM_CODEC = StreamCodec.of( + StreamCodec.FLOAT, ItemDamageFunction::threshold, + StreamCodec.FLOAT, ItemDamageFunction::base, + StreamCodec.FLOAT, ItemDamageFunction::factor, + ::ItemDamageFunction + ) - val DEFAULT = ItemDamageFunction(1f, 0f, 1f) + val CODEC = StructCodec.of( + "threshold", Codec.FLOAT, ItemDamageFunction::threshold, + "base", Codec.FLOAT, ItemDamageFunction::base, + "factor", Codec.FLOAT, ItemDamageFunction::factor, + ::ItemDamageFunction + ) - override fun read(buffer: ByteBuf): ItemDamageFunction { - return ItemDamageFunction(buffer.readFloat(), buffer.readFloat(), buffer.readFloat()) + override fun read(buffer: ByteBuf): ItemDamageFunction { + return STREAM_CODEC.read(buffer) + } } - } - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - static("threshold", CRC32CHasher.ofFloat(threshold)) - static("base", CRC32CHasher.ofFloat(base)) - static("factor", CRC32CHasher.ofFloat(factor)) + override fun write(buffer: ByteBuf) { + STREAM_CODEC.write(buffer, this) } - } -} -data class DamageReduction( - val horizontalBlockingAngle: Float, - val type: List?, - val base: Float, - val factor: Float -) : NetworkWritable, DataComponentHashable { - override fun write(buffer: ByteBuf) { - buffer.writeFloat(horizontalBlockingAngle) - buffer.writeOptionalList(type?.map { entityType -> entityType.getProtocolId() }, ByteBuf::writeVarInt) - buffer.writeFloat(base) - buffer.writeFloat(factor) + override fun hashStruct(): HashHolder { + return CRC32CHasher.of { + static("threshold", CRC32CHasher.ofFloat(threshold)) + static("base", CRC32CHasher.ofFloat(base)) + static("factor", CRC32CHasher.ofFloat(factor)) + } + } } - companion object : NetworkReadable { + data class DamageReduction( + val horizontalBlockingAngle: Float, + val type: EntityType?, + val base: Float, + val factor: Float + ) : NetworkWritable, DataComponentHashable { + + override fun write(buffer: ByteBuf) { + STREAM_CODEC.write(buffer, this) + } - val DEFAULT = DamageReduction(90.0f, null, 0.0f, 1.0f) + companion object : NetworkReadable { - override fun read(buffer: ByteBuf): DamageReduction { - return DamageReduction( - buffer.readFloat(), - buffer.readOptional { b -> b.readList(ByteBuf::readVarInt).map { int -> EntityTypeRegistry.getByProtocolId(int) } }, - buffer.readFloat(), - buffer.readFloat() + val DEFAULT = DamageReduction(90.0f, null, 0.0f, 1.0f) + + val CODEC = StructCodec.of( + "horizontal_blocking_angle", Codec.FLOAT.default(DEFAULT.horizontalBlockingAngle), DamageReduction::horizontalBlockingAngle, + "type", RegistryCodec.codec(EntityTypeRegistry).optional(), DamageReduction::type, + "base", Codec.FLOAT, DamageReduction::base, + "factor", Codec.FLOAT, DamageReduction::factor, + ::DamageReduction ) + + val STREAM_CODEC = StreamCodec.of( + StreamCodec.FLOAT, DamageReduction::horizontalBlockingAngle, + RegistryCodec.stream(EntityTypeRegistry).optional(), DamageReduction::type, + StreamCodec.FLOAT, DamageReduction::base, + StreamCodec.FLOAT, DamageReduction::factor, + ::DamageReduction + ) + + override fun read(buffer: ByteBuf): DamageReduction { + return STREAM_CODEC.read(buffer) + } } - } - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - default("horizontal_blocking_angle", DEFAULT.horizontalBlockingAngle, horizontalBlockingAngle, CRC32CHasher::ofFloat) - optionalList("type", type?.map { entityType -> entityType.getEntryIdentifier() }, CRC32CHasher::ofString) - static("base", CRC32CHasher.ofFloat(base)) - static("factor", CRC32CHasher.ofFloat(factor)) + override fun hashStruct(): HashHolder { + return CRC32CHasher.of { + default("horizontal_blocking_angle", DEFAULT.horizontalBlockingAngle, horizontalBlockingAngle, CRC32CHasher::ofFloat) + optional("type", type?.identifier, CRC32CHasher::ofString) + static("base", CRC32CHasher.ofFloat(base)) + static("factor", CRC32CHasher.ofFloat(factor)) + } } } -} +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/BreakSoundComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/BreakSoundComponent.kt index f9e4f05bd..6e0c1c4a3 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/BreakSoundComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/BreakSoundComponent.kt @@ -4,23 +4,25 @@ import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.HashHolder import io.github.dockyardmc.data.StaticHash import io.github.dockyardmc.protocol.NetworkReadable -import io.github.dockyardmc.sounds.BuiltinSoundEvent import io.github.dockyardmc.sounds.SoundEvent import io.netty.buffer.ByteBuf -data class BreakSoundComponent(val sound: String) : DataComponent() { +data class BreakSoundComponent(val sound: SoundEvent) : DataComponent() { - override fun write(buffer: ByteBuf) { - BuiltinSoundEvent.of(sound).write(buffer) + companion object : NetworkReadable { + val CODEC = SoundEvent.CODEC + val STREAM_CODEC = SoundEvent.STREAM_CODEC + + override fun read(buffer: ByteBuf): BreakSoundComponent { + return BreakSoundComponent(STREAM_CODEC.read(buffer)) + } } - override fun hashStruct(): HashHolder { - return StaticHash(BuiltinSoundEvent.of(sound).hashStruct().getHashed()) + override fun write(buffer: ByteBuf) { + STREAM_CODEC.write(buffer, sound) } - companion object : NetworkReadable { - override fun read(buffer: ByteBuf): BreakSoundComponent { - return BreakSoundComponent(SoundEvent.read(buffer).identifier) - } + override fun hashStruct(): HashHolder { + return StaticHash(sound.hashStruct().getHashed()) } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/ConsumableComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/ConsumableComponent.kt index 462cd3133..7e68d7aca 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/ConsumableComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/ConsumableComponent.kt @@ -1,62 +1,67 @@ package io.github.dockyardmc.data.components -import io.github.dockyardmc.data.CRC32CHasher +import io.github.dockyardmc.codec.transcoder.CRC32CTranscoder import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.HashHolder -import io.github.dockyardmc.extentions.readEnum -import io.github.dockyardmc.extentions.writeEnum +import io.github.dockyardmc.data.StaticHash import io.github.dockyardmc.protocol.NetworkReadable import io.github.dockyardmc.protocol.types.ConsumeEffect -import io.github.dockyardmc.protocol.types.readList -import io.github.dockyardmc.protocol.types.writeList import io.github.dockyardmc.registry.Sounds import io.github.dockyardmc.sounds.BuiltinSoundEvent -import io.github.dockyardmc.sounds.CustomSoundEvent import io.github.dockyardmc.sounds.SoundEvent +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import io.netty.buffer.ByteBuf -class ConsumableComponent( +data class ConsumableComponent( val consumeSeconds: Float, val animation: Animation, - val sound: String, + val sound: SoundEvent, val hasParticles: Boolean, val effects: List ) : DataComponent() { - override fun write(buffer: ByteBuf) { - buffer.writeFloat(consumeSeconds) - buffer.writeEnum(animation) - CustomSoundEvent(sound).write(buffer) - buffer.writeBoolean(hasParticles) - buffer.writeList(effects, ConsumeEffect::write) - } - - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - default("consume_seconds", CONSUME_SECONDS_DEFAULT, consumeSeconds, CRC32CHasher::ofFloat) - default("animation", Animation.EAT, animation, CRC32CHasher::ofEnum) - defaultStruct("sound", BuiltinSoundEvent.of(Sounds.ENTITY_GENERIC_EAT), CustomSoundEvent(sound), SoundEvent::hashStruct) - default("has_consume_particles", HAS_CONSUME_PARTICLES_DEFAULT, hasParticles, CRC32CHasher::ofBoolean) - defaultStructList("on_consume_effects", listOf(), effects, ConsumeEffect::hashStruct) - } - } - companion object : NetworkReadable { const val CONSUME_SECONDS_DEFAULT = 1.6f const val HAS_CONSUME_PARTICLES_DEFAULT = true + val ANIMATION_DEFAULT = Animation.EAT + val SOUND_DEFAULT = BuiltinSoundEvent(Sounds.ENTITY_GENERIC_EAT) + val CONSUME_EFFECTS_DEFAULT = listOf() + + val CODEC = StructCodec.of( + "consume_seconds", Codec.FLOAT.default(CONSUME_SECONDS_DEFAULT), ConsumableComponent::consumeSeconds, + "animation", Codec.enum().default(ANIMATION_DEFAULT), ConsumableComponent::animation, + "sound", SoundEvent.CODEC.default(SOUND_DEFAULT), ConsumableComponent::sound, + "has_consume_particles", Codec.BOOLEAN.default(HAS_CONSUME_PARTICLES_DEFAULT), ConsumableComponent::hasParticles, + "on_consume_effects", ConsumeEffect.CODEC.list().default(CONSUME_EFFECTS_DEFAULT), ConsumableComponent::effects, + ::ConsumableComponent + ) + + val STREAM_CODEC = StreamCodec.of( + StreamCodec.FLOAT, ConsumableComponent::consumeSeconds, + StreamCodec.enum(), ConsumableComponent::animation, + SoundEvent.STREAM_CODEC, ConsumableComponent::sound, + StreamCodec.BOOLEAN, ConsumableComponent::hasParticles, + ConsumeEffect.STREAM_CODEC.list(), ConsumableComponent::effects, + ::ConsumableComponent + ) override fun read(buffer: ByteBuf): ConsumableComponent { - return ConsumableComponent( - buffer.readFloat(), - buffer.readEnum(), - SoundEvent.read(buffer).identifier, - buffer.readBoolean(), - buffer.readList(ConsumeEffect::read) - ) + return STREAM_CODEC.read(buffer) } } + override fun hashStruct(): HashHolder { + return StaticHash(CODEC.encode(CRC32CTranscoder, this)) + } + + override fun write(buffer: ByteBuf) { + STREAM_CODEC.write(buffer, this) + } + + enum class Animation(val decreasesAmount: Boolean) { NONE(false), EAT(true), diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/DeathProtectionComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/DeathProtectionComponent.kt index 9672bd68d..41a132552 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/DeathProtectionComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/DeathProtectionComponent.kt @@ -1,30 +1,42 @@ package io.github.dockyardmc.data.components +import io.github.dockyardmc.codec.transcoder.CRC32CTranscoder import io.github.dockyardmc.data.CRC32CHasher import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.HashHolder +import io.github.dockyardmc.data.StaticHash import io.github.dockyardmc.protocol.NetworkReadable import io.github.dockyardmc.protocol.types.ConsumeEffect -import io.github.dockyardmc.protocol.types.readList -import io.github.dockyardmc.protocol.types.writeList +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import io.netty.buffer.ByteBuf -class DeathProtectionComponent(val deathEffects: List) : DataComponent() { +data class DeathProtectionComponent(val deathEffects: List) : DataComponent() { + + companion object : NetworkReadable { + + val CODEC = StructCodec.of( + "death_effects", ConsumeEffect.CODEC.list().default(listOf()), DeathProtectionComponent::deathEffects, + ::DeathProtectionComponent + ) + + val STREAM_CODEC = StreamCodec.of( + ConsumeEffect.STREAM_CODEC.list(), DeathProtectionComponent::deathEffects, + ::DeathProtectionComponent + ) + + override fun read(buffer: ByteBuf): DeathProtectionComponent { + return STREAM_CODEC.read(buffer) + } + } override fun write(buffer: ByteBuf) { - buffer.writeList(deathEffects, ConsumeEffect::write) + STREAM_CODEC.write(buffer, this) } override fun hashStruct(): HashHolder { return CRC32CHasher.of { - structList("on_consume_effects", deathEffects, ConsumeEffect::hashStruct) - } - } - - companion object : NetworkReadable { - override fun read(buffer: ByteBuf): DeathProtectionComponent { - return DeathProtectionComponent(buffer.readList(ConsumeEffect::read)) -// return DeathProtectionComponent(emptyList()) + return StaticHash(CODEC.encode(CRC32CTranscoder, this@DeathProtectionComponent)) } } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/EquippableComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/EquippableComponent.kt index fe103efd5..d8ec117ab 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/EquippableComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/EquippableComponent.kt @@ -27,12 +27,12 @@ class EquippableComponent( val damageOnHurt: Boolean, val equipOnInteract: Boolean, val canBeSheared: Boolean, - val shearingSounds: SoundEvent + val shearingSound: SoundEvent ) : DataComponent() { override fun write(buffer: ByteBuf) { buffer.writeEnum(equipmentSlot) - equipSound.write(buffer) + SoundEvent.STREAM_CODEC.write(buffer, equipSound) buffer.writeOptional(assetId, ByteBuf::writeString) buffer.writeOptional(cameraOverlay, ByteBuf::writeString) buffer.writeOptionalList(allowedEntities?.map { type -> type.getProtocolId() }, ByteBuf::writeVarInt) @@ -41,13 +41,13 @@ class EquippableComponent( buffer.writeBoolean(damageOnHurt) buffer.writeBoolean(equipOnInteract) buffer.writeBoolean(canBeSheared) - shearingSounds.write(buffer) + SoundEvent.STREAM_CODEC.write(buffer, shearingSound) } override fun hashStruct(): HashHolder { return CRC32CHasher.of { static("slot", CRC32CHasher.ofEnum(equipmentSlot)) - defaultStruct("equip_sound", BuiltinSoundEvent.of(Sounds.ITEM_ARMOR_EQUIP_GENERIC), equipSound, SoundEvent::hashStruct) + defaultStruct("equip_sound", BuiltinSoundEvent(Sounds.ITEM_ARMOR_EQUIP_GENERIC), equipSound, SoundEvent::hashStruct) optional("asset_id", assetId, CRC32CHasher::ofString) optional("camera_overlay", cameraOverlay, CRC32CHasher::ofString) optionalList("allowed_entities", allowedEntities, CRC32CHasher::ofRegistryEntry) @@ -56,18 +56,18 @@ class EquippableComponent( default("damage_on_hurt", true, damageOnHurt, CRC32CHasher::ofBoolean) default("equip_on_interact", false, equipOnInteract, CRC32CHasher::ofBoolean) default("can_be_sheared", false, canBeSheared, CRC32CHasher::ofBoolean) - defaultStruct("shearing_sound", DEFAULT_SHEARING_SOUND, shearingSounds, SoundEvent::hashStruct) + defaultStruct("shearing_sound", DEFAULT_SHEARING_SOUND, shearingSound, SoundEvent::hashStruct) } } companion object : NetworkReadable { - val DEFAULT_SHEARING_SOUND = BuiltinSoundEvent.of(Sounds.ITEM_SHEARS_SNIP) + val DEFAULT_SHEARING_SOUND = BuiltinSoundEvent(Sounds.ITEM_SHEARS_SNIP) override fun read(buffer: ByteBuf): EquippableComponent { return EquippableComponent( buffer.readEnum(), - SoundEvent.read(buffer), + SoundEvent.STREAM_CODEC.read(buffer), buffer.readOptional(ByteBuf::readString), buffer.readOptional(ByteBuf::readString), buffer.readOptional { b -> b.readList(ByteBuf::readVarInt).map { int -> EntityTypeRegistry.getByProtocolId(int) } }, @@ -76,7 +76,7 @@ class EquippableComponent( buffer.readBoolean(), buffer.readBoolean(), buffer.readBoolean(), - SoundEvent.read(buffer) + SoundEvent.STREAM_CODEC.read(buffer) ) } } diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/PotionContentsComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/PotionContentsComponent.kt index ea01030b8..b182bee53 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/PotionContentsComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/PotionContentsComponent.kt @@ -7,7 +7,6 @@ import io.github.dockyardmc.effects.AppliedPotionEffect import io.github.dockyardmc.extentions.* import io.github.dockyardmc.protocol.NetworkReadable import io.github.dockyardmc.protocol.readOptional -import io.github.dockyardmc.protocol.types.writeList import io.github.dockyardmc.protocol.writeOptional import io.github.dockyardmc.registry.registries.PotionType import io.github.dockyardmc.registry.registries.PotionTypeRegistry @@ -33,7 +32,7 @@ class PotionContentsComponent( override fun write(buffer: ByteBuf) { buffer.writeOptional(potion?.getProtocolId(), ByteBuf::writeVarInt) buffer.writeOptional(customColor, CustomColor::writePackedInt) - buffer.writeList(effects, AppliedPotionEffect::write) + AppliedPotionEffect.STREAM_CODEC.list().write(buffer, effects) buffer.writeOptional(customName, ByteBuf::writeString) } @@ -42,7 +41,7 @@ class PotionContentsComponent( return PotionContentsComponent( buffer.readOptional(ByteBuf::readVarInt)?.let { PotionTypeRegistry.getByProtocolId(it) }, buffer.readOptional(ByteBuf::readInt)?.let { CustomColor.fromRGBInt(it) }, - buffer.readList(AppliedPotionEffect::read), + AppliedPotionEffect.STREAM_CODEC.list().read(buffer), buffer.readOptional(ByteBuf::readString) ) } diff --git a/src/main/kotlin/io/github/dockyardmc/data/components/UseCooldownComponent.kt b/src/main/kotlin/io/github/dockyardmc/data/components/UseCooldownComponent.kt index 05989c513..5044d1feb 100644 --- a/src/main/kotlin/io/github/dockyardmc/data/components/UseCooldownComponent.kt +++ b/src/main/kotlin/io/github/dockyardmc/data/components/UseCooldownComponent.kt @@ -3,18 +3,35 @@ package io.github.dockyardmc.data.components import io.github.dockyardmc.data.CRC32CHasher import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.HashHolder -import io.github.dockyardmc.extentions.readString -import io.github.dockyardmc.extentions.writeString import io.github.dockyardmc.protocol.NetworkReadable -import io.github.dockyardmc.protocol.readOptional -import io.github.dockyardmc.protocol.writeOptional +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import io.netty.buffer.ByteBuf -class UseCooldownComponent(val seconds: Float, val cooldownGroup: String? = null) : DataComponent() { +data class UseCooldownComponent(val seconds: Float, val cooldownGroup: String? = null) : DataComponent() { + + companion object : NetworkReadable { + + val STREAM_CODEC = StreamCodec.of( + StreamCodec.FLOAT, UseCooldownComponent::seconds, + StreamCodec.STRING.optional(), UseCooldownComponent::cooldownGroup, + ::UseCooldownComponent + ) + + val CODEC = StructCodec.of( + "seconds", Codec.FLOAT, UseCooldownComponent::seconds, + "cooldown_group", Codec.STRING.optional(), UseCooldownComponent::cooldownGroup, + ::UseCooldownComponent + ) + + override fun read(buffer: ByteBuf): UseCooldownComponent { + return STREAM_CODEC.read(buffer) + } + } override fun write(buffer: ByteBuf) { - buffer.writeFloat(seconds) - buffer.writeOptional(cooldownGroup, ByteBuf::writeString) + STREAM_CODEC.write(buffer, this) } override fun hashStruct(): HashHolder { @@ -23,13 +40,4 @@ class UseCooldownComponent(val seconds: Float, val cooldownGroup: String? = null optional("cooldown_group", cooldownGroup, CRC32CHasher::ofString) } } - - companion object : NetworkReadable { - override fun read(buffer: ByteBuf): UseCooldownComponent { - return UseCooldownComponent( - buffer.readFloat(), - buffer.readOptional(ByteBuf::readString) - ) - } - } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/effects/AppliedPotionEffect.kt b/src/main/kotlin/io/github/dockyardmc/effects/AppliedPotionEffect.kt index 45bfd0619..598b34c6d 100644 --- a/src/main/kotlin/io/github/dockyardmc/effects/AppliedPotionEffect.kt +++ b/src/main/kotlin/io/github/dockyardmc/effects/AppliedPotionEffect.kt @@ -1,89 +1,92 @@ package io.github.dockyardmc.effects +import io.github.dockyardmc.codec.DurationCodec +import io.github.dockyardmc.codec.RegistryCodec import io.github.dockyardmc.data.CRC32CHasher import io.github.dockyardmc.data.HashHolder -import io.github.dockyardmc.extentions.readRegistryEntry -import io.github.dockyardmc.extentions.readVarInt -import io.github.dockyardmc.extentions.writeVarInt import io.github.dockyardmc.protocol.DataComponentHashable -import io.github.dockyardmc.protocol.NetworkReadable -import io.github.dockyardmc.protocol.NetworkWritable -import io.github.dockyardmc.protocol.writeOptional import io.github.dockyardmc.registry.registries.PotionEffect import io.github.dockyardmc.registry.registries.PotionEffectRegistry import io.github.dockyardmc.scheduler.runnables.inWholeMinecraftTicks import io.github.dockyardmc.scheduler.runnables.ticks -import io.netty.buffer.ByteBuf +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import kotlin.time.Duration data class AppliedPotionEffect( var effect: PotionEffect, - val settings: AppliedPotionEffectSettings, + val settings: Settings, var startTime: Long? = null, -) : DataComponentHashable, NetworkWritable { +) : DataComponentHashable { - override fun write(buffer: ByteBuf) { - effect.write(buffer) - settings.write(buffer) - } + companion object { - companion object : NetworkReadable { - override fun read(buffer: ByteBuf): AppliedPotionEffect { - return AppliedPotionEffect(buffer.readRegistryEntry(PotionEffectRegistry), AppliedPotionEffectSettings.read(buffer)) - } - } + val STREAM_CODEC = StreamCodec.of( + RegistryCodec.stream(PotionEffectRegistry), AppliedPotionEffect::effect, + Settings.STREAM_CODEC, AppliedPotionEffect::settings, + ::AppliedPotionEffect + ) - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - static("id", CRC32CHasher.ofRegistryEntry(effect)) - inline(settings, AppliedPotionEffectSettings::hashStruct) - //start field is only for server-side use - } + val CODEC = StructCodec.of( + "id", RegistryCodec.codec(PotionEffectRegistry), AppliedPotionEffect::effect, + StructCodec.INLINE, Settings.CODEC, AppliedPotionEffect::settings, + ::AppliedPotionEffect + ) } -} -data class AppliedPotionEffectSettings( - val amplifier: Int, - val duration: Duration, - val isAmbient: Boolean, - val showParticles: Boolean, - val showIcon: Boolean, - val hiddenEffect: AppliedPotionEffectSettings? = null -) : DataComponentHashable { - companion object { + data class Settings( + val amplifier: Int, + val duration: Duration, + val isAmbient: Boolean, + val showParticles: Boolean, + val showIcon: Boolean, + val hiddenEffect: Settings? = null + ) : DataComponentHashable { + companion object { - fun read(buffer: ByteBuf): AppliedPotionEffectSettings { - val amplifier: Int = buffer.readVarInt() - val duration: Int = buffer.readVarInt() - val isAmbient: Boolean = buffer.readBoolean() - val showParticles: Boolean = buffer.readBoolean() - val showIcon: Boolean = buffer.readBoolean() - var hiddenEffect: AppliedPotionEffectSettings? = null + val STREAM_CODEC = StreamCodec.recursive { self -> + StreamCodec.of( + StreamCodec.VAR_INT, Settings::amplifier, + DurationCodec.STREAM_CODEC_INT_TICKS, Settings::duration, + StreamCodec.BOOLEAN, Settings::isAmbient, + StreamCodec.BOOLEAN, Settings::showParticles, + StreamCodec.BOOLEAN, Settings::showIcon, + self.optional(), Settings::hiddenEffect, + ::Settings + ) + } - if (buffer.readBoolean()) { - hiddenEffect = read(buffer) + val CODEC = Codec.recursive { self -> + StructCodec.of( + "amplifier", Codec.BYTE.transform({ from -> from.toInt() }, { to -> to.toByte() }).default(0), Settings::amplifier, + "duration", DurationCodec.CODEC_INT_TICKS.default(0.ticks), Settings::duration, + "ambient", Codec.BOOLEAN.default(false), Settings::isAmbient, + "show_particles", Codec.BOOLEAN.default(true), Settings::showParticles, + "show_icon", Codec.BOOLEAN, Settings::showIcon, + "hidden_effect", self.optional(), Settings::hiddenEffect, + ::Settings + ) + } + } + + override fun hashStruct(): HashHolder { + return CRC32CHasher.of { + default("amplifier", 0, amplifier.toByte(), CRC32CHasher::ofByte) + default("duration", 0, duration.inWholeMinecraftTicks, CRC32CHasher::ofInt) + default("ambient", false, isAmbient, CRC32CHasher::ofBoolean) + default("show_particles", true, showParticles, CRC32CHasher::ofBoolean) + static("show_icon", CRC32CHasher.ofBoolean(showIcon)) + optionalStruct("hidden_effect", hiddenEffect, Settings::hashStruct) } - return AppliedPotionEffectSettings(amplifier, duration.ticks(), isAmbient, showParticles, showIcon, hiddenEffect) } } override fun hashStruct(): HashHolder { return CRC32CHasher.of { - default("amplifier", 0, amplifier.toByte(), CRC32CHasher::ofByte) - default("duration", 0, duration.inWholeMinecraftTicks, CRC32CHasher::ofInt) - default("ambient", false, isAmbient, CRC32CHasher::ofBoolean) - default("show_particles", true, showParticles, CRC32CHasher::ofBoolean) - static("show_icon", CRC32CHasher.ofBoolean(showIcon)) - optionalStruct("hidden_effect", hiddenEffect, AppliedPotionEffectSettings::hashStruct) + static("id", CRC32CHasher.ofRegistryEntry(effect)) + inline(settings, Settings::hashStruct) } } +} - fun write(buffer: ByteBuf) { - buffer.writeVarInt(amplifier) - buffer.writeVarInt(duration.inWholeMinecraftTicks) - buffer.writeBoolean(isAmbient) - buffer.writeBoolean(showIcon) - buffer.writeBoolean(showIcon) - buffer.writeOptional(hiddenEffect, AppliedPotionEffectSettings::write) - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/entity/Entity.kt b/src/main/kotlin/io/github/dockyardmc/entity/Entity.kt index 341914002..9ecebc427 100644 --- a/src/main/kotlin/io/github/dockyardmc/entity/Entity.kt +++ b/src/main/kotlin/io/github/dockyardmc/entity/Entity.kt @@ -6,7 +6,6 @@ import cz.lukynka.bindables.BindableMap import cz.lukynka.bindables.BindablePool import io.github.dockyardmc.config.ConfigManager import io.github.dockyardmc.effects.AppliedPotionEffect -import io.github.dockyardmc.effects.AppliedPotionEffectSettings import io.github.dockyardmc.entity.EntityManager.despawnEntity import io.github.dockyardmc.entity.handlers.* import io.github.dockyardmc.entity.metadata.EntityMetadata @@ -337,7 +336,7 @@ abstract class Entity(open var location: Location, open var world: World) : Disp showBlueBorder: Boolean = false, showIconOnHud: Boolean = false, ) { - val potionEffect = AppliedPotionEffect(effect, AppliedPotionEffectSettings(amplifier, duration, showBlueBorder, showParticles, showIconOnHud)) + val potionEffect = AppliedPotionEffect(effect, AppliedPotionEffect.Settings(amplifier, duration, showBlueBorder, showParticles, showIconOnHud)) this.potionEffects[effect] = potionEffect } diff --git a/src/main/kotlin/io/github/dockyardmc/item/ItemStack.kt b/src/main/kotlin/io/github/dockyardmc/item/ItemStack.kt index ecb6f76a3..4ac390f6d 100644 --- a/src/main/kotlin/io/github/dockyardmc/item/ItemStack.kt +++ b/src/main/kotlin/io/github/dockyardmc/item/ItemStack.kt @@ -1,6 +1,5 @@ package io.github.dockyardmc.item -import cz.lukynka.prettylog.log import io.github.dockyardmc.attributes.AttributeModifier import io.github.dockyardmc.data.DataComponent import io.github.dockyardmc.data.DataComponentPatch @@ -22,6 +21,7 @@ import io.github.dockyardmc.scroll.Component import io.github.dockyardmc.scroll.CustomColor import io.github.dockyardmc.scroll.extensions.stripComponentTags import io.github.dockyardmc.scroll.extensions.toComponent +import io.github.dockyardmc.sounds.BuiltinSoundEvent import io.github.dockyardmc.utils.CustomDataHolder import io.netty.buffer.ByteBuf import net.kyori.adventure.nbt.* @@ -99,7 +99,7 @@ data class ItemStack( hasParticles: Boolean = true, consumeEffects: List = listOf() ): ItemStack { - return ItemStackMeta.fromItemStack(this).apply { withConsumable(consumeTimeSeconds, animation, sound, hasParticles, consumeEffects) }.toItemStack() + return ItemStackMeta.fromItemStack(this).apply { this.withConsumable(consumeTimeSeconds, animation, BuiltinSoundEvent(sound), hasParticles, consumeEffects) }.toItemStack() } fun withRarity(rarity: ItemRarity): ItemStack { diff --git a/src/main/kotlin/io/github/dockyardmc/item/ItemStackMeta.kt b/src/main/kotlin/io/github/dockyardmc/item/ItemStackMeta.kt index c30b717b9..4ba6286ac 100644 --- a/src/main/kotlin/io/github/dockyardmc/item/ItemStackMeta.kt +++ b/src/main/kotlin/io/github/dockyardmc/item/ItemStackMeta.kt @@ -12,6 +12,8 @@ import io.github.dockyardmc.registry.Sounds import io.github.dockyardmc.registry.registries.Item import io.github.dockyardmc.scroll.CustomColor import io.github.dockyardmc.scroll.extensions.toComponent +import io.github.dockyardmc.sounds.BuiltinSoundEvent +import io.github.dockyardmc.sounds.SoundEvent import java.util.* class ItemStackMeta { @@ -91,7 +93,7 @@ class ItemStackMeta { fun withConsumable( consumeTimeSeconds: Float, animation: ConsumableComponent.Animation = ConsumableComponent.Animation.EAT, - sound: String = Sounds.ENTITY_GENERIC_EAT, + sound: SoundEvent = BuiltinSoundEvent(Sounds.ENTITY_GENERIC_EAT), hasParticles: Boolean = true, consumeEffects: List = listOf() ) { diff --git a/src/main/kotlin/io/github/dockyardmc/maths/vectors/Vector3.kt b/src/main/kotlin/io/github/dockyardmc/maths/vectors/Vector3.kt index 29feda458..28ef770a8 100644 --- a/src/main/kotlin/io/github/dockyardmc/maths/vectors/Vector3.kt +++ b/src/main/kotlin/io/github/dockyardmc/maths/vectors/Vector3.kt @@ -1,9 +1,11 @@ package io.github.dockyardmc.maths.vectors +import io.github.dockyardmc.extentions.toVector3 import io.github.dockyardmc.extentions.writeVarInt import io.github.dockyardmc.location.Location import io.github.dockyardmc.protocol.NetworkReadable import io.github.dockyardmc.protocol.NetworkWritable +import io.github.dockyardmc.tide.codec.Codec import io.github.dockyardmc.tide.stream.StreamCodec import io.github.dockyardmc.world.World import io.netty.buffer.ByteBuf @@ -135,8 +137,14 @@ data class Vector3( buffer.writeShort(this.z) } + fun toIntArray(): IntArray { + return intArrayOf(x, y, z) + } + companion object : NetworkReadable { + val CODEC = Codec.INT_ARRAY.transform({ from -> from.toVector3() }, { to -> to.toIntArray() }) + val STREAM_CODEC = StreamCodec.of( StreamCodec.VAR_INT, Vector3::x, StreamCodec.VAR_INT, Vector3::y, diff --git a/src/main/kotlin/io/github/dockyardmc/player/systems/FoodEatingSystem.kt b/src/main/kotlin/io/github/dockyardmc/player/systems/FoodEatingSystem.kt index 477546cf5..059e9e062 100644 --- a/src/main/kotlin/io/github/dockyardmc/player/systems/FoodEatingSystem.kt +++ b/src/main/kotlin/io/github/dockyardmc/player/systems/FoodEatingSystem.kt @@ -3,7 +3,6 @@ package io.github.dockyardmc.player.systems import io.github.dockyardmc.data.components.ConsumableComponent import io.github.dockyardmc.data.components.FoodComponent import io.github.dockyardmc.events.* -import io.github.dockyardmc.extentions.broadcastMessage import io.github.dockyardmc.item.ItemStack import io.github.dockyardmc.maths.randomFloat import io.github.dockyardmc.maths.vectors.Vector3f @@ -49,7 +48,7 @@ class FoodEatingSystem(val player: Player) : TickablePlayerSystem { // Eating if ((world.worldAge % 5) == 0L && consumableComponent.animation == ConsumableComponent.Animation.EAT) { val players = world.players.filter { it != player } - players.playSound(consumableComponent.sound, location, 1f, Random.randomFloat(0.9f, 1.3f)) + players.playSound(consumableComponent.sound.identifier, location, 1f, Random.randomFloat(0.9f, 1.3f)) if (consumableComponent.hasParticles) { players.spawnParticle( location = location.clone().apply { y += 1.5 }, diff --git a/src/main/kotlin/io/github/dockyardmc/protocol/DataComponentHashable.kt b/src/main/kotlin/io/github/dockyardmc/protocol/DataComponentHashable.kt index f449534dd..6966b1a67 100644 --- a/src/main/kotlin/io/github/dockyardmc/protocol/DataComponentHashable.kt +++ b/src/main/kotlin/io/github/dockyardmc/protocol/DataComponentHashable.kt @@ -4,6 +4,8 @@ import io.github.dockyardmc.data.HashHolder import kotlin.reflect.KClass interface DataComponentHashable { + + @Deprecated("Please use CODEC and CRC32CTranscoder", replaceWith = ReplaceWith("CRC32Transcoder")) fun hashStruct(): HashHolder { return unsupported(this) } diff --git a/src/main/kotlin/io/github/dockyardmc/protocol/types/ConsumeEffect.kt b/src/main/kotlin/io/github/dockyardmc/protocol/types/ConsumeEffect.kt index dee1e53c9..a01e294a0 100644 --- a/src/main/kotlin/io/github/dockyardmc/protocol/types/ConsumeEffect.kt +++ b/src/main/kotlin/io/github/dockyardmc/protocol/types/ConsumeEffect.kt @@ -1,162 +1,164 @@ package io.github.dockyardmc.protocol.types -import io.github.dockyardmc.data.CRC32CHasher +import io.github.dockyardmc.codec.RegistryCodec +import io.github.dockyardmc.codec.transcoder.CRC32CTranscoder import io.github.dockyardmc.data.HashHolder import io.github.dockyardmc.data.StaticHash import io.github.dockyardmc.effects.AppliedPotionEffect -import io.github.dockyardmc.extentions.read -import io.github.dockyardmc.extentions.readVarInt -import io.github.dockyardmc.extentions.writeVarInt import io.github.dockyardmc.protocol.DataComponentHashable import io.github.dockyardmc.protocol.NetworkReadable -import io.github.dockyardmc.protocol.NetworkWritable -import io.github.dockyardmc.registry.RegistryEntry import io.github.dockyardmc.registry.registries.PotionEffect import io.github.dockyardmc.registry.registries.PotionEffectRegistry -import io.github.dockyardmc.sounds.CustomSoundEvent import io.github.dockyardmc.sounds.SoundEvent -import io.github.dockyardmc.utils.MutableBiMap +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import io.netty.buffer.ByteBuf -import java.util.concurrent.atomic.AtomicInteger -import kotlin.reflect.KClass -interface ConsumeEffect : NetworkWritable, DataComponentHashable { +sealed interface ConsumeEffect : DataComponentHashable { - companion object : NetworkReadable { - val effects = MutableBiMap>() - private val protocolIdCounter = AtomicInteger() + enum class Type(val key: String) { + APPLY_EFFECTS("minecraft:apply_effects"), + REMOVE_EFFECTS("minecraft:remove_effects"), + CLEAR_ALL_EFFECTS("minecraft:clear_all_effects"), + TELEPORT_RANDOMLY("minecraft:teleport_randomly"), + PLAY_SOUND("minecraft:play_sound"); - init { - register(ApplyEffects::class) - register(RemoveEffects::class) - register(ClearAllEffects::class) - register(TeleportRandomly::class) - register(PlaySound::class) + companion object { + val CODEC = Codec.STRING.transform({ from -> Type.entries.first { it.key == from } }, { to -> to.key }) } + } - override fun read(buffer: ByteBuf): ConsumeEffect { - val id = buffer.readVarInt() - val kclass = effects.getByKey(id) - return kclass.read(buffer) - } + override fun hashStruct(): HashHolder { + return StaticHash(CODEC.encode(CRC32CTranscoder, this)) + } + + companion object : NetworkReadable { + + val STREAM_CODEC = StreamCodec.enum().union( + { type -> + when (type) { + Type.APPLY_EFFECTS -> ApplyEffects.STREAM_CODEC + Type.REMOVE_EFFECTS -> RemoveEffects.STREAM_CODEC + Type.CLEAR_ALL_EFFECTS -> ClearAllEffects.STREAM_CODEC + Type.TELEPORT_RANDOMLY -> TeleportRandomly.STREAM_CODEC + Type.PLAY_SOUND -> PlaySound.STREAM_CODEC + } + }, + { effect -> + when (effect) { + is ApplyEffects -> Type.APPLY_EFFECTS + is ClearAllEffects -> Type.CLEAR_ALL_EFFECTS + is PlaySound -> Type.PLAY_SOUND + is RemoveEffects -> Type.REMOVE_EFFECTS + is TeleportRandomly -> Type.TELEPORT_RANDOMLY + } + } + ) + + val CODEC = Type.CODEC.union( + { type -> + when (type) { + Type.APPLY_EFFECTS -> ApplyEffects.CODEC + Type.REMOVE_EFFECTS -> RemoveEffects.CODEC + Type.CLEAR_ALL_EFFECTS -> ClearAllEffects.CODEC + Type.TELEPORT_RANDOMLY -> TeleportRandomly.CODEC + Type.PLAY_SOUND -> PlaySound.CODEC + } + }, + { effect -> + when (effect) { + is ApplyEffects -> Type.APPLY_EFFECTS + is ClearAllEffects -> Type.CLEAR_ALL_EFFECTS + is PlaySound -> Type.PLAY_SOUND + is RemoveEffects -> Type.REMOVE_EFFECTS + is TeleportRandomly -> Type.TELEPORT_RANDOMLY + } + } + ) - private fun register(kclass: KClass) { - effects.put(protocolIdCounter.getAndIncrement(), kclass) + override fun read(buffer: ByteBuf): ConsumeEffect { + return STREAM_CODEC.read(buffer) } } - data class ApplyEffects(val effects: List, val probability: Float) : ConsumeEffect { + data class ApplyEffects(val effects: List, val probability: Float = 1f) : ConsumeEffect { init { require(probability in 0f..1f) { "Probability must be between 0f and 1f" } } - override fun write(buffer: ByteBuf) { - buffer.writeVarInt(ConsumeEffect.effects.getByValue(this::class)) - buffer.writeList(effects, AppliedPotionEffect::write) - buffer.writeFloat(probability) - } - - companion object : NetworkReadable { - const val ID = 0 + companion object { + const val DEFAULT_PROBABILITY = 1f - override fun read(buffer: ByteBuf): ApplyEffects { - return ApplyEffects(buffer.readList(AppliedPotionEffect::read), buffer.readFloat()) - } - } + val STREAM_CODEC = StreamCodec.of( + AppliedPotionEffect.STREAM_CODEC.list(), ApplyEffects::effects, + StreamCodec.FLOAT, ApplyEffects::probability, + ::ApplyEffects + ) - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - structList("effects", effects, AppliedPotionEffect::hashStruct) - default("probability", 1f, probability, CRC32CHasher::ofFloat) - } + val CODEC = StructCodec.of( + "effects", AppliedPotionEffect.CODEC.list(), ApplyEffects::effects, + "probability", Codec.FLOAT.default(DEFAULT_PROBABILITY), ApplyEffects::probability, + ::ApplyEffects + ) } - } data class RemoveEffects(val effects: List) : ConsumeEffect { - override fun write(buffer: ByteBuf) { - buffer.writeVarInt(ConsumeEffect.effects.getByValue(this::class)) - buffer.writeList(effects, RegistryEntry::write) - } - - companion object : NetworkReadable { - const val ID = 1 - - override fun read(buffer: ByteBuf): RemoveEffects { - return RemoveEffects(buffer.readList { b -> RegistryEntry.read(b, PotionEffectRegistry) }) - } - } + companion object { + val STREAM_CODEC = StreamCodec.of( + RegistryCodec.stream(PotionEffectRegistry).list(), RemoveEffects::effects, + ::RemoveEffects + ) - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - list("effects", effects, CRC32CHasher::ofRegistryEntry) - } + val CODEC = StructCodec.of( + "effects", RegistryCodec.codec(PotionEffectRegistry).list(), RemoveEffects::effects, + ::RemoveEffects + ) } } class ClearAllEffects : ConsumeEffect { - override fun write(buffer: ByteBuf) { - buffer.writeVarInt(effects.getByValue(this::class)) - } - - companion object : NetworkReadable { - const val ID = 3 + companion object { +// private val INSTANCE get() = ClearAllEffects() - override fun read(buffer: ByteBuf): ClearAllEffects { - return ClearAllEffects() - } - } - - override fun hashStruct(): HashHolder { - return StaticHash(CRC32CHasher.EMPTY_MAP) + val CODEC = StructCodec.of(::ClearAllEffects) + val STREAM_CODEC = StreamCodec.of(::ClearAllEffects) } } data class TeleportRandomly(val diameter: Float = DEFAULT_DIAMETER) : ConsumeEffect { - override fun write(buffer: ByteBuf) { - buffer.writeVarInt(effects.getByValue(this::class)) - buffer.writeFloat(diameter) - } - - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - default("diameter", DEFAULT_DIAMETER, diameter, CRC32CHasher::ofFloat) - } - } - - companion object : NetworkReadable { + companion object { const val DEFAULT_DIAMETER = 16.0f - const val ID = 3 - - override fun read(buffer: ByteBuf): TeleportRandomly { - return TeleportRandomly(buffer.readFloat()) - } - } - } - data class PlaySound(val sound: String) : ConsumeEffect { + val STREAM_CODEC = StreamCodec.of( + StreamCodec.FLOAT, TeleportRandomly::diameter, + ::TeleportRandomly + ) - override fun write(buffer: ByteBuf) { - buffer.writeVarInt(effects.getByValue(this::class)) - CustomSoundEvent(sound).write(buffer) + val CODEC = StructCodec.of( + "diameter", Codec.FLOAT.default(DEFAULT_DIAMETER), TeleportRandomly::diameter, + ::TeleportRandomly + ) } + } - companion object : NetworkReadable { - const val ID = 4 + data class PlaySound(val sound: SoundEvent) : ConsumeEffect { - override fun read(buffer: ByteBuf): PlaySound { - return PlaySound(SoundEvent.read(buffer).identifier) - } - } + companion object { + val CODEC = StructCodec.of( + "sound", SoundEvent.CODEC, PlaySound::sound, + ::PlaySound + ) - override fun hashStruct(): HashHolder { - return CRC32CHasher.of { - static("sound", CustomSoundEvent(sound).hashStruct().getHashed()) - } + val STREAM_CODEC = StreamCodec.of( + SoundEvent.STREAM_CODEC, PlaySound::sound, + ::PlaySound + ) } } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/protocol/types/WorldPosition.kt b/src/main/kotlin/io/github/dockyardmc/protocol/types/WorldPosition.kt index f53626d57..56fcadcc6 100644 --- a/src/main/kotlin/io/github/dockyardmc/protocol/types/WorldPosition.kt +++ b/src/main/kotlin/io/github/dockyardmc/protocol/types/WorldPosition.kt @@ -1,19 +1,38 @@ package io.github.dockyardmc.protocol.types +import io.github.dockyardmc.codec.LocationCodecs import io.github.dockyardmc.data.CRC32CHasher import io.github.dockyardmc.data.HashHolder -import io.github.dockyardmc.extentions.readString -import io.github.dockyardmc.extentions.writeString -import io.github.dockyardmc.location.readBlockPosition -import io.github.dockyardmc.location.writeBlockPosition import io.github.dockyardmc.maths.vectors.Vector3 import io.github.dockyardmc.protocol.DataComponentHashable import io.github.dockyardmc.protocol.NetworkReadable import io.github.dockyardmc.protocol.NetworkWritable +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec import io.netty.buffer.ByteBuf data class WorldPosition(val dimension: String, val blockPosition: Vector3) : NetworkWritable, DataComponentHashable { + companion object : NetworkReadable { + + val STREAM_CODEC = StreamCodec.of( + StreamCodec.STRING, WorldPosition::dimension, + LocationCodecs.BLOCK_POSITION, WorldPosition::blockPosition, + ::WorldPosition + ) + + val CODEC = StructCodec.of( + "dimension", Codec.STRING, WorldPosition::dimension, + "pos", Vector3.CODEC, WorldPosition::blockPosition, + ::WorldPosition + ) + + override fun read(buffer: ByteBuf): WorldPosition { + return STREAM_CODEC.read(buffer) + } + } + override fun hashStruct(): HashHolder { return CRC32CHasher.of { static("dimension", CRC32CHasher.ofString(dimension)) @@ -22,17 +41,7 @@ data class WorldPosition(val dimension: String, val blockPosition: Vector3) : Ne } override fun write(buffer: ByteBuf) { - buffer.writeString(dimension) - buffer.writeBlockPosition(blockPosition) - } - - companion object : NetworkReadable { - override fun read(buffer: ByteBuf): WorldPosition { - val name = buffer.readString() - val blockPos = buffer.readBlockPosition() - - return WorldPosition(name, blockPos) - } + STREAM_CODEC.write(buffer, this) } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/registry/dummy/DummyInstrument.kt b/src/main/kotlin/io/github/dockyardmc/registry/dummy/DummyInstrument.kt index 6bf14b6e5..3f4940b92 100644 --- a/src/main/kotlin/io/github/dockyardmc/registry/dummy/DummyInstrument.kt +++ b/src/main/kotlin/io/github/dockyardmc/registry/dummy/DummyInstrument.kt @@ -11,7 +11,7 @@ import io.netty.buffer.ByteBuf data class DummyInstrument(val soundEvent: SoundEvent, val useDuration: Float, val range: Float, val description: Component) : NetworkWritable { override fun write(buffer: ByteBuf) { - soundEvent.write(buffer) + SoundEvent.STREAM_CODEC.write(buffer, soundEvent) buffer.writeFloat(useDuration) buffer.writeFloat(range) buffer.writeTextComponent(description) @@ -20,7 +20,7 @@ data class DummyInstrument(val soundEvent: SoundEvent, val useDuration: Float, v companion object : NetworkReadable { override fun read(buffer: ByteBuf): DummyInstrument { return DummyInstrument( - SoundEvent.read(buffer), + SoundEvent.STREAM_CODEC.read(buffer), buffer.readFloat(), buffer.readFloat(), buffer.readTextComponent() diff --git a/src/main/kotlin/io/github/dockyardmc/registry/registries/BiomeRegistry.kt b/src/main/kotlin/io/github/dockyardmc/registry/registries/BiomeRegistry.kt index 3d99078f5..539605fbc 100644 --- a/src/main/kotlin/io/github/dockyardmc/registry/registries/BiomeRegistry.kt +++ b/src/main/kotlin/io/github/dockyardmc/registry/registries/BiomeRegistry.kt @@ -1,5 +1,6 @@ package io.github.dockyardmc.registry.registries +import io.github.dockyardmc.codec.transcoder.BinaryTagTranscoder import io.github.dockyardmc.nbt.nbt import io.github.dockyardmc.protocol.NbtWritable import io.github.dockyardmc.registry.DataDrivenRegistry @@ -39,7 +40,7 @@ data class BackgroundMusic( ) { fun toNBT(): CompoundBinaryTag { return nbt { - withCompound("sound", CustomSoundEvent(sound, null).getNbt()) + withCompound("sound", CustomSoundEvent.CODEC.encode(BinaryTagTranscoder, CustomSoundEvent(sound, null)) as CompoundBinaryTag) withInt("max_delay", maxDelay) withInt("min_delay", minDelay) withBoolean("replace_current_music", replaceCurrentMusic) diff --git a/src/main/kotlin/io/github/dockyardmc/resourcepack/ResourcepackManager.kt b/src/main/kotlin/io/github/dockyardmc/resourcepack/ResourcepackManager.kt index fcf9f4f28..e4cf302d3 100644 --- a/src/main/kotlin/io/github/dockyardmc/resourcepack/ResourcepackManager.kt +++ b/src/main/kotlin/io/github/dockyardmc/resourcepack/ResourcepackManager.kt @@ -1,7 +1,5 @@ package io.github.dockyardmc.resourcepack -import cz.lukynka.prettylog.LogType -import cz.lukynka.prettylog.log import io.github.dockyardmc.player.Player import io.github.dockyardmc.protocol.packets.ProtocolState import io.github.dockyardmc.protocol.packets.configurations.ClientboundConfigurationAddResourcePackPacket diff --git a/src/main/kotlin/io/github/dockyardmc/resourcepack/ResourcepackOLD.kt b/src/main/kotlin/io/github/dockyardmc/resourcepack/ResourcepackOLD.kt deleted file mode 100644 index e1dca39db..000000000 --- a/src/main/kotlin/io/github/dockyardmc/resourcepack/ResourcepackOLD.kt +++ /dev/null @@ -1,84 +0,0 @@ -//package io.github.dockyardmc.resourcepack -// -//import io.github.dockyardmc.player.Player -//import io.github.dockyardmc.protocol.packets.play.clientbound.ClientboundAddResourcepackPacket -//import io.github.dockyardmc.protocol.packets.play.clientbound.ClientboundRemoveResourcepackPacket -//import java.util.UUID -// -//object ResourcepackManager { -// val pending: MutableList = mutableListOf() -//} -// -//class ResourcepackOLD { -// var onFail: ((ResourcepackResponseEvent) -> Unit)? = null -// var onSuccess: ((ResourcepackResponseEvent) -> Unit)? = null -// var url: String = "" -// var required: Boolean = false -// var promptMessage: String? = null -// -// var player: Player? = null -// var uuid: UUID = UUID.randomUUID() -// var name: String = uuid.toString() -// -// fun withPromptMessage(message: String) { -// this.promptMessage = message -// } -// -// fun setForced(forced: Boolean) { -// this.required = forced -// } -// -// fun withUrl(url: String) { -// this.url = url -// } -// -// fun onFail(unit: (ResourcepackResponseEvent) -> Unit) { -// onFail = unit -// } -// -// fun onSuccess(unit: (ResourcepackResponseEvent) -> Unit) { -// onSuccess = unit -// } -// -//} -// -//data class ResourcepackResponseEvent( -// val resourcepack: ResourcepackOLD, -// val player: Player, -// val status: ResourcepackStatus -//) -// -//inline fun Player.addResourcepack(name: String, resourcepack: ResourcepackOLD.() -> Unit) { -// addResourcepack( -// name, -// ResourcepackOLD().apply(resourcepack) -// ) -//} -// -//fun Player.addResourcepack(name: String, pack: ResourcepackOLD) { -// pack.name = name -// pack.player = this -// -// ResourcepackManager.pending.add(pack) -// this.sendPacket(ClientboundAddResourcepackPacket(pack)) -//} -// -//fun Player.removeResourcepack(name: String) { -// val pack = this.resourcepacks[name] ?: return -// this.sendPacket(ClientboundRemoveResourcepackPacket(pack.uuid)) -//} -// -//inline fun Collection.addResourcepack(name: String, resourcepack: ResourcepackOLD.() -> Unit) { -// this.forEach { it.addResourcepack(name, resourcepack) } -//} -// -//enum class ResourcepackStatus { -// SUCCESSFULLY_LOADED, -// DECLINED, -// FAILED_TO_DOWNLOAD, -// ACCEPTED, -// DOWNLOADED, -// INVALID_URL, -// FAILED_TO_RELOAD, -// DISCARDED -//} \ No newline at end of file diff --git a/src/main/kotlin/io/github/dockyardmc/schematics/Schematic.kt b/src/main/kotlin/io/github/dockyardmc/schematics/Schematic.kt index 6e03ff993..2e46fb517 100644 --- a/src/main/kotlin/io/github/dockyardmc/schematics/Schematic.kt +++ b/src/main/kotlin/io/github/dockyardmc/schematics/Schematic.kt @@ -2,23 +2,12 @@ package io.github.dockyardmc.schematics -import cz.lukynka.prettylog.LogType -import cz.lukynka.prettylog.log -import io.github.dockyardmc.extentions.getOrThrow -import io.github.dockyardmc.extentions.readVarInt -import io.github.dockyardmc.extentions.reversed -import io.github.dockyardmc.extentions.toByteBuf import io.github.dockyardmc.location.Location import io.github.dockyardmc.maths.vectors.Vector3 import io.github.dockyardmc.registry.Blocks -import io.github.dockyardmc.world.World import io.github.dockyardmc.world.block.Block -import io.github.dockyardmc.world.chunk.Chunk -import io.github.dockyardmc.world.chunk.ChunkPos import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.kyori.adventure.nbt.CompoundBinaryTag -import java.util.concurrent.CompletableFuture data class Schematic( var size: Vector3, diff --git a/src/main/kotlin/io/github/dockyardmc/sounds/SoundEvent.kt b/src/main/kotlin/io/github/dockyardmc/sounds/SoundEvent.kt index 75424a993..b698824d1 100644 --- a/src/main/kotlin/io/github/dockyardmc/sounds/SoundEvent.kt +++ b/src/main/kotlin/io/github/dockyardmc/sounds/SoundEvent.kt @@ -7,68 +7,89 @@ import io.github.dockyardmc.extentions.readString import io.github.dockyardmc.extentions.readVarInt import io.github.dockyardmc.extentions.writeString import io.github.dockyardmc.extentions.writeVarInt -import io.github.dockyardmc.nbt.nbt -import io.github.dockyardmc.protocol.* +import io.github.dockyardmc.protocol.DataComponentHashable +import io.github.dockyardmc.protocol.readOptional +import io.github.dockyardmc.protocol.writeOptional import io.github.dockyardmc.registry.registries.SoundRegistry +import io.github.dockyardmc.tide.codec.Codec +import io.github.dockyardmc.tide.codec.StructCodec +import io.github.dockyardmc.tide.stream.StreamCodec +import io.github.dockyardmc.tide.transcoder.Transcoder import io.netty.buffer.ByteBuf -import net.kyori.adventure.nbt.BinaryTag -import net.kyori.adventure.nbt.CompoundBinaryTag -import net.kyori.adventure.nbt.StringBinaryTag -interface SoundEvent : NetworkWritable, NbtWritable, DataComponentHashable { +sealed interface SoundEvent : DataComponentHashable { + + val identifier: String + companion object { - fun read(buffer: ByteBuf): SoundEvent { - val id = buffer.readVarInt() - 1 - if (id != -1) { - val sound = SoundRegistry.getByProtocolId(id) - return BuiltinSoundEvent(sound, id) + val STREAM_CODEC = object : StreamCodec { + + @Suppress("UNCHECKED_CAST") + override fun write(buffer: ByteBuf, value: SoundEvent) { + when (value) { + is BuiltinSoundEvent -> buffer.writeVarInt(value.protocolId + 1) + is CustomSoundEvent -> { + buffer.writeVarInt(0) + buffer.writeString(value.identifier) + buffer.writeOptional(value.range, ByteBuf::writeFloat) + } + } } - val identifier = buffer.readString() - val range = buffer.readOptional(ByteBuf::readFloat) - return CustomSoundEvent(identifier, range) + override fun read(buffer: ByteBuf): SoundEvent { + val id = buffer.readVarInt() - 1 + if (id != -1) return BuiltinSoundEvent(id) + + return CustomSoundEvent(buffer.readString(), buffer.readOptional(ByteBuf::readFloat)) + } } - } - val identifier: String -} + val CODEC = object : Codec { -data class BuiltinSoundEvent(override val identifier: String, val id: Int) : SoundEvent { + override fun encode(transcoder: Transcoder, value: SoundEvent): D { + return when (value) { + is BuiltinSoundEvent -> transcoder.encodeString(value.identifier) + is CustomSoundEvent -> CustomSoundEvent.CODEC.encode(transcoder, value) + } + } - override fun write(buffer: ByteBuf) { - buffer.writeVarInt(id + 1) - } + override fun decode(transcoder: Transcoder, value: D): SoundEvent { + val result = runCatching { transcoder.decodeString(value) } + if (result.isSuccess) return BuiltinSoundEvent(result.getOrThrow()) - override fun getNbt(): BinaryTag { - return StringBinaryTag.stringBinaryTag(identifier) + return CustomSoundEvent.CODEC.decode(transcoder, value) + } + } } +} + +data class BuiltinSoundEvent(override val identifier: String) : SoundEvent { + + constructor(id: Int) : this(SoundRegistry.getByProtocolId(id)) + + val protocolId = SoundRegistry[identifier] override fun hashStruct(): HashHolder { return StaticHash(CRC32CHasher.ofString(identifier)) } - - companion object { - fun of(identifier: String): BuiltinSoundEvent { - val id = SoundRegistry[identifier] - return BuiltinSoundEvent(identifier, id) - } - } } data class CustomSoundEvent(override val identifier: String, val range: Float? = null) : SoundEvent { - override fun write(buffer: ByteBuf) { - buffer.writeVarInt(0) - buffer.writeString(identifier) - buffer.writeOptional(range, ByteBuf::writeFloat) + companion object { + val CODEC = StructCodec.of( + "sound_id", Codec.STRING, CustomSoundEvent::identifier, + "range", Codec.FLOAT.optional(), CustomSoundEvent::range, + ::CustomSoundEvent + ) } - override fun getNbt(): CompoundBinaryTag { - return nbt { - withString("sound_id", identifier) - if (range != null) withFloat("range", range) - } - } +// override fun write(buffer: ByteBuf) { +// buffer.writeVarInt(0) +// buffer.writeString(identifier) +// buffer.writeOptional(range, ByteBuf::writeFloat) +// } + override fun hashStruct(): HashHolder { return CRC32CHasher.of { diff --git a/src/test/kotlin/io/github/dockyard/tests/hashing/HashTest.kt b/src/test/kotlin/io/github/dockyard/tests/hashing/HashTest.kt index a2e2d80cb..0209e256b 100644 --- a/src/test/kotlin/io/github/dockyard/tests/hashing/HashTest.kt +++ b/src/test/kotlin/io/github/dockyard/tests/hashing/HashTest.kt @@ -1,5 +1,6 @@ package io.github.dockyard.tests.hashing +import cz.lukynka.prettylog.log import io.github.dockyard.tests.TestServer import io.github.dockyardmc.attributes.AttributeModifier import io.github.dockyardmc.attributes.AttributeOperation @@ -8,7 +9,6 @@ import io.github.dockyardmc.attributes.Modifier import io.github.dockyardmc.data.CRC32CHasher import io.github.dockyardmc.data.components.* import io.github.dockyardmc.effects.AppliedPotionEffect -import io.github.dockyardmc.effects.AppliedPotionEffectSettings import io.github.dockyardmc.maths.vectors.Vector3 import io.github.dockyardmc.protocol.DataComponentHashable import io.github.dockyardmc.protocol.types.ConsumeEffect @@ -16,7 +16,6 @@ import io.github.dockyardmc.protocol.types.EquipmentSlot import io.github.dockyardmc.protocol.types.WorldPosition import io.github.dockyardmc.registry.* import io.github.dockyardmc.registry.registries.PotionTypeRegistry -import io.github.dockyardmc.registry.registries.SoundRegistry import io.github.dockyardmc.scroll.CustomColor import io.github.dockyardmc.sounds.BuiltinSoundEvent import io.github.dockyardmc.sounds.CustomSoundEvent @@ -66,18 +65,18 @@ class HashTest { AttributeModifiersComponent(listOf(Modifier(Attributes.ATTACK_SPEED, AttributeModifier("minecraft:test", 6.9, AttributeOperation.ADD_VALUE), EquipmentSlotGroup.ANY, Modifier.Display.Default.INSTANCE))) to 168186938, AttributeModifiersComponent(listOf()) to -1978007022, CustomSoundEvent(Sounds.BLOCK_NOTE_BLOCK_BANJO, null) to 2036171673, - BuiltinSoundEvent(Sounds.BLOCK_NOTE_BLOCK_BANJO, SoundRegistry[Sounds.BLOCK_NOTE_BLOCK_BANJO]) to 952047800, - ConsumableComponent(1.6f, ConsumableComponent.Animation.EAT, Sounds.ITEM_GOAT_HORN_SOUND_0, true, listOf()) to -102904843, - ConsumableComponent(0.3f, ConsumableComponent.Animation.BLOCK, Sounds.ITEM_BOOK_PUT, false, listOf()) to -1085734156, - AppliedPotionEffect(PotionEffects.LUCK, AppliedPotionEffectSettings(1, 5.seconds, true, false, true, null)) to -1904986478, - ConsumeEffect.ApplyEffects(listOf(AppliedPotionEffect(PotionEffects.LUCK, AppliedPotionEffectSettings(1, 5.seconds, true, false, true, null))), 1.0f) to -181115074, - ConsumeEffect.RemoveEffects(listOf(PotionEffects.LUCK, PotionEffects.HASTE)) to -1438921926, + BuiltinSoundEvent(Sounds.BLOCK_NOTE_BLOCK_BANJO) to 952047800, + ConsumeEffect.ApplyEffects(listOf(), 1.0f) to 2028610984, + ConsumeEffect.RemoveEffects(listOf(PotionEffects.LUCK, PotionEffects.HASTE)) to 497533033, ConsumeEffect.ClearAllEffects() to -982207288, - ConsumeEffect.PlaySound(Sounds.ITEM_GOAT_HORN_SOUND_0) to -102904843, - ConsumeEffect.TeleportRandomly() to -982207288, - ConsumeEffect.TeleportRandomly(5.0f) to 984729518, + ConsumeEffect.PlaySound(BuiltinSoundEvent(Sounds.ITEM_GOAT_HORN_SOUND_0)) to 257203246, + ConsumeEffect.TeleportRandomly() to 813409391, + ConsumeEffect.TeleportRandomly(5.0f) to -1764715223, + ConsumableComponent(1.6f, ConsumableComponent.Animation.EAT, BuiltinSoundEvent(Sounds.ITEM_GOAT_HORN_SOUND_0), true, listOf()) to 1795682327, + ConsumableComponent(0.3f, ConsumableComponent.Animation.BLOCK, BuiltinSoundEvent(Sounds.ITEM_BOOK_PUT), false, listOf()) to -349184012, + AppliedPotionEffect(PotionEffects.LUCK, AppliedPotionEffect.Settings(1, 5.seconds, true, false, true, null)) to -1904986478, CustomModelDataComponent(listOf(1f, 2f), listOf(true, false), listOf("gay", "month"), listOf(CustomColor(1, 1, 1))) to 766388248, - EquippableComponent(EquipmentSlot.CHESTPLATE, BuiltinSoundEvent.of(Sounds.ITEM_GOAT_HORN_SOUND_0), null, null, null, true, true, true, true, false, BuiltinSoundEvent.of(Sounds.ITEM_GOAT_HORN_SOUND_0)) to 1213362121, + EquippableComponent(EquipmentSlot.CHESTPLATE, BuiltinSoundEvent(Sounds.ITEM_GOAT_HORN_SOUND_0), null, null, null, true, true, true, true, false, BuiltinSoundEvent(Sounds.ITEM_GOAT_HORN_SOUND_0)) to 1213362121, FoodComponent(2, 1.3f, true) to 474066665, ItemBlockStateComponent(mapOf("month?" to "gay!")) to 725075553, LodestoneTrackerComponent(WorldPosition("minecraft:main", Vector3(1, 2, 3)), true) to 728072173, @@ -95,6 +94,7 @@ class HashTest { expectedHashes.forEach { (hashable, hash) -> assertEquals(-340533995, CRC32CHasher.ofColor(CustomColor(1, 1, 1))) + log("Testing: ${hashable::class.simpleName}") assertEquals(hash, hashable.hashStruct().getHashed()) } } diff --git a/src/test/kotlin/io/github/dockyard/tests/hashing/TranscoderTest.kt b/src/test/kotlin/io/github/dockyard/tests/hashing/TranscoderTest.kt new file mode 100644 index 000000000..ecf6d6f8b --- /dev/null +++ b/src/test/kotlin/io/github/dockyard/tests/hashing/TranscoderTest.kt @@ -0,0 +1,26 @@ +package io.github.dockyard.tests.hashing + +import io.github.dockyardmc.codec.transcoder.CRC32CTranscoder +import io.github.dockyardmc.data.DataComponent +import io.github.dockyardmc.data.components.UseCooldownComponent +import io.github.dockyardmc.tide.codec.Codec +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class TranscoderTest { + + data class TestHash(val component: DataComponent, val codec: Codec, val expectedHash: Int) + + val expectedHashes = listOf( + TestHash(UseCooldownComponent(1.6f, "minecraft:test"), UseCooldownComponent.CODEC, 493336604), + ) + + @Suppress("UNCHECKED_CAST") + @Test + fun test() { + expectedHashes.forEach { testHash -> + val codec = testHash.codec as Codec + assertEquals(testHash.expectedHash, codec.encode(CRC32CTranscoder, testHash.component)) + } + } +} \ No newline at end of file