Skip to content

Networking

Archie's networking layer provides a type-safe, annotation-driven API for sending packets between client and server. All packets are serialized with CBOR via kotlinx.serialization, so no manual buffer reading/writing is required.


NetworkChannel

NetworkChannel is the entry point. A single channel instance can handle any number of server-bound and client-bound packet types.

// Create the channel (usually a top-level object or companion property)
val CHANNEL = NetworkChannel(Archie["network/main"])

Defining packets

Packet types must be Kotlin data classes annotated with @Serializable.

@Serializable
data class SyncEnergyPacket(val energy: Int, val pos: @Contextual BlockPos)

@Serializable
data class RequestDataPacket(val id: Int)

Registering handlers

Register handlers before calling register():

// Server receives this packet from the client
CHANNEL.serverbound(RequestDataPacket::class) { packet, ctx ->
    val player = ctx.player as ServerPlayer
    val data = fetchData(packet.id)
    CHANNEL.toPlayer(player, SyncEnergyPacket(data.energy, data.pos))
}

// Client receives this packet from the server
CHANNEL.clientbound(SyncEnergyPacket::class) { packet, ctx ->
    ClientEnergyCache.update(packet.pos, packet.energy)
}

// Called once during mod init
CHANNEL.register()

Sending packets

Method Description
toServer(packet) Client → Server
toPlayer(player, packet) Server → specific player
toPlayers(list, packet) Server → list of players
toAllPlayers(packet) Server → every connected player
toPlayersInDimension(level, packet) Server → all players in a dimension
toNearPlayers(level, exclude, x, y, z, radius, packet) Server → players within radius
toPlayersTrackingEntity(entity, self, packet) Server → players loading an entity
toPlayersTrackingChunk(level, pos, packet) Server → players loading a chunk

IPacketContext

The IPacketContext interface is passed to every packet handler and exposes:

Property Type Description
player Player The player associated with the packet
registryAccess RegistryAccess Dynamic registry access
minecraft Minecraft Client-side Minecraft instance (client handlers only)

Minecraft type serializers

For serializing Minecraft types inside packets, annotate fields with @Contextual and use the provided type aliases:

@Serializable
data class TeleportPacket(
    val destination: @Contextual BlockPos,
    val dimension: @Contextual ResourceLocation,
)

Available contextual serializers: BlockPos, ChunkPos, GlobalPos, Vec3, Vec3i, BlockHitResult, ResourceLocation, FriendlyByteBuf.