package moe.nea.firmament.apis.ingame.packets import io.netty.buffer.ByteBuf import java.util.UUID import net.minecraft.network.PacketByteBuf import net.minecraft.network.codec.PacketCodec import net.minecraft.network.codec.PacketCodecs import net.minecraft.network.packet.CustomPayload import net.minecraft.util.Identifier import net.minecraft.util.Uuids import moe.nea.firmament.apis.ingame.FirmamentCustomPayload interface FirmamentCustomPayloadMeta { val ID: CustomPayload.Id val CODEC: PacketCodec fun id(name: String): CustomPayload.Id { return CustomPayload.Id(Identifier.of(name)) } fun intoType(): CustomPayload.Type { return CustomPayload.Type(ID, CODEC) } } data class PartyInfoRequest(val version: Int) : FirmamentCustomPayload { companion object : FirmamentCustomPayloadMeta { override val ID = id("hypixel:party_info") override val CODEC = PacketCodecs.VAR_INT.cast() .xmap(::PartyInfoRequest, PartyInfoRequest::version) } override fun getId(): CustomPayload.Id { return ID } } sealed interface PartyInfoResponseV sealed interface HypixelVersionedPacketData data class HypixelSuccessfulResponse(val data: T) : HypixelVersionedPacketData data class HypixelUnknownVersion(val version: Int) : HypixelVersionedPacketData data class HypixelApiError(val label: String, val errorId: Int) : HypixelVersionedPacketData { companion object { fun createCodec(label: String): PacketCodec { return PacketCodecs.VAR_INT .cast() .xmap({ HypixelApiError(label, it) }, HypixelApiError::errorId) } } } object CodecUtils { fun dispatchVersioned( versions: Map>, errorCodec: PacketCodec ): PacketCodec> { return object : PacketCodec> { override fun decode(buf: B): HypixelVersionedPacketData { if (!buf.readBoolean()) { return errorCodec.decode(buf) } val version = buf.readVarInt() val versionCodec = versions[version] ?: return HypixelUnknownVersion(version) return HypixelSuccessfulResponse(versionCodec.decode(buf)) } override fun encode(buf: B, value: HypixelVersionedPacketData?) { error("Cannot encode a hypixel packet") } } } fun dispatchS2CBoolean( ifTrue: PacketCodec, ifFalse: PacketCodec ): PacketCodec { return object : PacketCodec { override fun decode(buf: B): T { return if (buf.readBoolean()) { ifTrue.decode(buf) } else { ifFalse.decode(buf) } } override fun encode(buf: B, value: T) { error("Cannot reverse dispatch boolean") } } } } data object PartyInfoResponseVUnknown : PartyInfoResponseV data class PartyInfoResponseV1( val leader: UUID?, val members: Set, ) : PartyInfoResponseV { data object PartyMember companion object { val CODEC: PacketCodec = CodecUtils.dispatchS2CBoolean( PacketCodec.tuple( Uuids.PACKET_CODEC, PartyInfoResponseV1::leader, Uuids.PACKET_CODEC.collect(PacketCodecs.toCollection(::HashSet)), PartyInfoResponseV1::members, ::PartyInfoResponseV1 ), PacketCodec.unit(PartyInfoResponseV1(null, setOf()))) } } data class PartyInfoResponse(val data: HypixelVersionedPacketData) : FirmamentCustomPayload { companion object : FirmamentCustomPayloadMeta { override val ID = id("hypixel:party_info") override val CODEC = CodecUtils .dispatchVersioned( mapOf( 1 to PartyInfoResponseV1.CODEC, ), HypixelApiError.createCodec("PartyInfoResponse")) .xmap(::PartyInfoResponse, PartyInfoResponse::data) } override fun getId(): CustomPayload.Id { return ID } }