[WIP] Add mod api
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.mixins;
|
||||||
|
|
||||||
|
import moe.nea.firmament.apis.ingame.FirmamentCustomPayload;
|
||||||
|
import moe.nea.firmament.events.FirmamentCustomPayloadEvent;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.network.packet.CustomPayload;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
|
public class CustomPayloadEventDispatcher {
|
||||||
|
@Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void handleFirmamentParsedPayload(CustomPayload payload, CallbackInfo ci) {
|
||||||
|
if (payload instanceof FirmamentCustomPayload customPayload) {
|
||||||
|
FirmamentCustomPayloadEvent.Companion.publish(new FirmamentCustomPayloadEvent(customPayload));
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.mixins;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
|
import moe.nea.firmament.apis.ingame.InGameCodecWrapper;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.network.codec.PacketCodec;
|
||||||
|
import net.minecraft.network.packet.CustomPayload;
|
||||||
|
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(priority = 1001, value = CustomPayloadC2SPacket.class)
|
||||||
|
public class WrapCustomPayloadC2SPacketCodec {
|
||||||
|
|
||||||
|
@WrapOperation(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/CustomPayload;createCodec(Lnet/minecraft/network/packet/CustomPayload$CodecFactory;Ljava/util/List;)Lnet/minecraft/network/codec/PacketCodec;"))
|
||||||
|
private static PacketCodec<PacketByteBuf, CustomPayload> wrapFactory(
|
||||||
|
CustomPayload.CodecFactory<PacketByteBuf> unknownCodecFactory,
|
||||||
|
List<CustomPayload.Type<PacketByteBuf, ?>> types,
|
||||||
|
Operation<PacketCodec<PacketByteBuf, CustomPayload>> original) {
|
||||||
|
|
||||||
|
var originalCodec = original.call(unknownCodecFactory, types);
|
||||||
|
|
||||||
|
return new InGameCodecWrapper(originalCodec, InGameCodecWrapper.Direction.C2S);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.mixins;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
|
import moe.nea.firmament.apis.ingame.InGameCodecWrapper;
|
||||||
|
import moe.nea.firmament.apis.ingame.JoinedCustomPayload;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.network.codec.PacketCodec;
|
||||||
|
import net.minecraft.network.listener.ClientCommonPacketListener;
|
||||||
|
import net.minecraft.network.packet.CustomPayload;
|
||||||
|
import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(priority = 1001, value = CustomPayloadS2CPacket.class)
|
||||||
|
public abstract class WrapCustomPayloadS2CPacketCodec {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
public abstract CustomPayload payload();
|
||||||
|
|
||||||
|
@WrapOperation(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/CustomPayload;createCodec(Lnet/minecraft/network/packet/CustomPayload$CodecFactory;Ljava/util/List;)Lnet/minecraft/network/codec/PacketCodec;"))
|
||||||
|
private static PacketCodec<PacketByteBuf, CustomPayload> wrapFactory(
|
||||||
|
CustomPayload.CodecFactory<PacketByteBuf> unknownCodecFactory,
|
||||||
|
List<CustomPayload.Type<PacketByteBuf, ?>> types,
|
||||||
|
Operation<PacketCodec<PacketByteBuf, CustomPayload>> original) {
|
||||||
|
|
||||||
|
var originalCodec = original.call(unknownCodecFactory, types);
|
||||||
|
|
||||||
|
return new InGameCodecWrapper(originalCodec, InGameCodecWrapper.Direction.S2C);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: move to own class
|
||||||
|
@Inject(method = "apply(Lnet/minecraft/network/listener/ClientCommonPacketListener;)V", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void onApply(ClientCommonPacketListener clientCommonPacketListener, CallbackInfo ci) {
|
||||||
|
if (payload() instanceof JoinedCustomPayload joinedCustomPayload) {
|
||||||
|
new CustomPayloadS2CPacket(joinedCustomPayload.getOriginal()).apply(clientCommonPacketListener);
|
||||||
|
new CustomPayloadS2CPacket(joinedCustomPayload.getSmuggled()).apply(clientCommonPacketListener);
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.mixins.devenv;
|
||||||
|
|
||||||
|
import moe.nea.firmament.Firmament;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.network.packet.UnknownCustomPayload;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(UnknownCustomPayload.class)
|
||||||
|
public class WarnForUnknownCustomPayloadSends {
|
||||||
|
@Inject(method = "method_56493", at = @At("HEAD"))
|
||||||
|
private static void warn(UnknownCustomPayload value, PacketByteBuf buf, CallbackInfo ci) {
|
||||||
|
Firmament.INSTANCE.getLogger().warn("Unknown custom payload is being sent: {}", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.apis.ingame
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf
|
||||||
|
import net.minecraft.network.codec.PacketCodec
|
||||||
|
import net.minecraft.network.packet.CustomPayload
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
|
||||||
|
interface FirmamentCustomPayload : CustomPayload {
|
||||||
|
|
||||||
|
class Unhandled private constructor(val identifier: Identifier) : FirmamentCustomPayload {
|
||||||
|
override fun getId(): CustomPayload.Id<out CustomPayload> {
|
||||||
|
return CustomPayload.id(identifier.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun <B : ByteBuf> createCodec(identifier: Identifier): PacketCodec<B, Unhandled> {
|
||||||
|
return object : PacketCodec<B, Unhandled> {
|
||||||
|
override fun decode(buf: B): Unhandled {
|
||||||
|
return Unhandled(identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun encode(buf: B, value: Unhandled) {
|
||||||
|
// we will never send an unhandled packet stealthy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.apis.ingame
|
||||||
|
|
||||||
|
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.apis.ingame.packets.PartyInfoRequest
|
||||||
|
import moe.nea.firmament.apis.ingame.packets.PartyInfoResponse
|
||||||
|
import moe.nea.firmament.commands.thenExecute
|
||||||
|
import moe.nea.firmament.events.CommandEvent
|
||||||
|
import moe.nea.firmament.events.FirmamentCustomPayloadEvent
|
||||||
|
import moe.nea.firmament.events.subscription.SubscriptionOwner
|
||||||
|
import moe.nea.firmament.features.FirmamentFeature
|
||||||
|
import moe.nea.firmament.features.debug.DeveloperFeatures
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
|
||||||
|
|
||||||
|
object HypixelModAPI : SubscriptionOwner {
|
||||||
|
init {
|
||||||
|
InGameCodecWrapper.Direction.C2S.customCodec =
|
||||||
|
InGameCodecWrapper.createStealthyCodec(
|
||||||
|
PartyInfoRequest.intoType()
|
||||||
|
)
|
||||||
|
InGameCodecWrapper.Direction.S2C.customCodec =
|
||||||
|
InGameCodecWrapper.createStealthyCodec(
|
||||||
|
PartyInfoResponse.intoType()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun sendRequest(packet: FirmamentCustomPayload) {
|
||||||
|
MC.networkHandler?.sendPacket(CustomPayloadC2SPacket(packet))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun testCommand(event: CommandEvent.SubCommand) {
|
||||||
|
event.subcommand("sendpartyrequest") {
|
||||||
|
thenExecute {
|
||||||
|
sendRequest(PartyInfoRequest(1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun logEvents(event: FirmamentCustomPayloadEvent) {
|
||||||
|
MC.sendChat(Text.stringifiedTranslatable("firmament.modapi.event", event.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
override val delegateFeature: FirmamentFeature
|
||||||
|
get() = DeveloperFeatures
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.apis.ingame
|
||||||
|
|
||||||
|
import net.minecraft.network.PacketByteBuf
|
||||||
|
import net.minecraft.network.codec.PacketCodec
|
||||||
|
import net.minecraft.network.packet.CustomPayload
|
||||||
|
|
||||||
|
class InGameCodecWrapper(
|
||||||
|
val wrapped: PacketCodec<PacketByteBuf, CustomPayload>,
|
||||||
|
val direction: Direction,
|
||||||
|
) : PacketCodec<PacketByteBuf, CustomPayload> {
|
||||||
|
enum class Direction {
|
||||||
|
S2C,
|
||||||
|
C2S,
|
||||||
|
;
|
||||||
|
|
||||||
|
var customCodec: PacketCodec<PacketByteBuf, FirmamentCustomPayload> = createStealthyCodec()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun createStealthyCodec(vararg codecs: CustomPayload.Type<PacketByteBuf, out FirmamentCustomPayload>): PacketCodec<PacketByteBuf, FirmamentCustomPayload> {
|
||||||
|
return CustomPayload.createCodec(
|
||||||
|
{ FirmamentCustomPayload.Unhandled.createCodec(it) },
|
||||||
|
codecs.toList()
|
||||||
|
) as PacketCodec<PacketByteBuf, FirmamentCustomPayload>
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun decode(buf: PacketByteBuf): CustomPayload {
|
||||||
|
val duplicateBuffer = PacketByteBuf(buf.slice())
|
||||||
|
val original = wrapped.decode(buf)
|
||||||
|
val duplicate = direction.customCodec.decode(duplicateBuffer)
|
||||||
|
if (duplicate is FirmamentCustomPayload.Unhandled)
|
||||||
|
return original
|
||||||
|
return JoinedCustomPayload(original, duplicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun encode(buf: PacketByteBuf, value: CustomPayload) {
|
||||||
|
if (value is FirmamentCustomPayload) {
|
||||||
|
direction.customCodec.encode(buf, value)
|
||||||
|
} else {
|
||||||
|
wrapped.encode(buf, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.apis.ingame
|
||||||
|
|
||||||
|
import net.minecraft.network.packet.CustomPayload
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to smuggle two parsed instances of the same custom payload packet.
|
||||||
|
*/
|
||||||
|
class JoinedCustomPayload(
|
||||||
|
val original: CustomPayload,
|
||||||
|
val smuggled: FirmamentCustomPayload
|
||||||
|
) : CustomPayload {
|
||||||
|
companion object {
|
||||||
|
val joinedId = CustomPayload.id<JoinedCustomPayload>("firmament:joined")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getId(): CustomPayload.Id<out JoinedCustomPayload> {
|
||||||
|
return joinedId
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.events
|
||||||
|
|
||||||
|
import moe.nea.firmament.apis.ingame.FirmamentCustomPayload
|
||||||
|
|
||||||
|
data class FirmamentCustomPayloadEvent(
|
||||||
|
val payload: FirmamentCustomPayload
|
||||||
|
) : FirmamentEvent() {
|
||||||
|
companion object : FirmamentEventBus<FirmamentCustomPayloadEvent>()
|
||||||
|
}
|
||||||
@@ -153,6 +153,7 @@
|
|||||||
"firmament.config.fixes.player-skins": "Fix unsigned Player Skins",
|
"firmament.config.fixes.player-skins": "Fix unsigned Player Skins",
|
||||||
"firmament.config.power-user.show-item-id": "Show SkyBlock Ids",
|
"firmament.config.power-user.show-item-id": "Show SkyBlock Ids",
|
||||||
"firmament.config.power-user.copy-item-id": "Copy SkyBlock Id",
|
"firmament.config.power-user.copy-item-id": "Copy SkyBlock Id",
|
||||||
|
"firmament.modapi.event": "Received mod API event: %s",
|
||||||
"firmament.config.power-user.copy-texture-pack-id": "Copy Texture Pack Id",
|
"firmament.config.power-user.copy-texture-pack-id": "Copy Texture Pack Id",
|
||||||
"firmament.config.power-user.copy-skull-texture": "Copy Placed Skull Id",
|
"firmament.config.power-user.copy-skull-texture": "Copy Placed Skull Id",
|
||||||
"firmament.config.power-user.copy-nbt-data": "Copy NBT data",
|
"firmament.config.power-user.copy-nbt-data": "Copy NBT data",
|
||||||
|
|||||||
Reference in New Issue
Block a user