aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/apis/ingame/packets/PartyInfoRequest.kt
blob: 2b3d234934f827736288880c963819ca02b68dc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

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.Uuids
import moe.nea.firmament.apis.ingame.FirmamentCustomPayload

interface FirmamentCustomPayloadMeta<T : FirmamentCustomPayload> {
    val ID: CustomPayload.Id<T>
    val CODEC: PacketCodec<PacketByteBuf, T>

    fun intoType(): CustomPayload.Type<PacketByteBuf, T> {
        return CustomPayload.Type(ID, CODEC)
    }
}

data class PartyInfoRequest(val version: Int) : FirmamentCustomPayload {
    companion object : FirmamentCustomPayloadMeta<PartyInfoRequest> {
        override val ID = CustomPayload.id<PartyInfoRequest>("hypixel:party_info")
        override val CODEC =
            PacketCodecs.VAR_INT.cast<PacketByteBuf>()
                .xmap(::PartyInfoRequest, PartyInfoRequest::version)
    }

    override fun getId(): CustomPayload.Id<out CustomPayload> {
        return ID
    }
}

sealed interface PartyInfoResponseV
sealed interface HypixelVersionedPacketData<out T>
data class HypixelSuccessfulResponse<T>(val data: T) : HypixelVersionedPacketData<T>
data class HypixelUnknownVersion(val version: Int) : HypixelVersionedPacketData<Nothing>
data class HypixelApiError(val label: String, val errorId: Int) : HypixelVersionedPacketData<Nothing> {
    companion object {
        fun <B : ByteBuf> createCodec(label: String): PacketCodec<B, HypixelApiError> {
            return PacketCodecs.VAR_INT
                .cast<B>()
                .xmap({ HypixelApiError(label, it) }, HypixelApiError::errorId)
        }
    }
}

object CodecUtils {
    fun <B : PacketByteBuf, T> dispatchVersioned(
        versions: Map<Int, PacketCodec<B, out T>>,
        errorCodec: PacketCodec<B, HypixelApiError>
    ): PacketCodec<B, HypixelVersionedPacketData<T>> {
        return object : PacketCodec<B, HypixelVersionedPacketData<T>> {
            override fun decode(buf: B): HypixelVersionedPacketData<T> {
                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<T>?) {
                error("Cannot encode a hypixel packet")
            }
        }
    }

    fun <B : PacketByteBuf, T> dispatchS2CBoolean(
        ifTrue: PacketCodec<B, out T>,
        ifFalse: PacketCodec<B, out T>
    ): PacketCodec<B, T> {
        return object : PacketCodec<B, T> {
            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<UUID>,
) : PartyInfoResponseV {
    data object PartyMember
    companion object {
        val CODEC: PacketCodec<PacketByteBuf, PartyInfoResponseV1> =
            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<PartyInfoResponseV>) : FirmamentCustomPayload {
    companion object : FirmamentCustomPayloadMeta<PartyInfoResponse> {
        override val ID: CustomPayload.Id<PartyInfoResponse> = CustomPayload.id("hypixel:party_info")
        override val CODEC =
            CodecUtils
                .dispatchVersioned<PacketByteBuf, PartyInfoResponseV>(
                    mapOf(
                        1 to PartyInfoResponseV1.CODEC,
                    ),
                    HypixelApiError.createCodec("PartyInfoResponse"))
                .xmap(::PartyInfoResponse, PartyInfoResponse::data)

    }

    override fun getId(): CustomPayload.Id<out CustomPayload> {
        return ID
    }
}