Skip to content

Commit

Permalink
Replace method handle usages with access widener
Browse files Browse the repository at this point in the history
  • Loading branch information
NichtStudioCode committed Sep 21, 2024
1 parent 036f928 commit 05622a1
Show file tree
Hide file tree
Showing 21 changed files with 174 additions and 681 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
package xyz.xenondevs.nova.network

import io.netty.buffer.Unpooled
import net.kyori.adventure.text.Component
import net.minecraft.core.Holder
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.ComponentSerialization
import net.minecraft.network.protocol.game.ClientboundBossEventPacket
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket
import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket.AttributeSnapshot
import net.minecraft.network.protocol.game.ServerboundInteractPacket
import net.minecraft.network.protocol.game.ServerboundPlaceRecipePacket
import net.minecraft.resources.ResourceLocation
import net.minecraft.sounds.SoundEvent
import net.minecraft.sounds.SoundSource
import xyz.xenondevs.nova.network.event.clientbound.ServerboundInteractPacketEvent
import net.minecraft.world.BossEvent
import xyz.xenondevs.nova.util.RegistryFriendlyByteBuf
import xyz.xenondevs.nova.util.bossbar.operation.BossBarOperation
import java.lang.invoke.MethodHandles
import java.lang.invoke.MethodType
import java.util.*
import xyz.xenondevs.nova.util.component.adventure.toNMSComponent

fun ClientboundSetPassengersPacket(vehicle: Int, passengers: IntArray): ClientboundSetPassengersPacket {
val buffer = FriendlyByteBuf(Unpooled.buffer())
Expand All @@ -27,13 +23,29 @@ fun ClientboundSetPassengersPacket(vehicle: Int, passengers: IntArray): Clientbo
return ClientboundSetPassengersPacket.STREAM_CODEC.decode(buffer)
}

private val BOSS_BAR_OPERATION_CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundBossEventPacket\$Operation")
private val CLIENTBOUND_BOSS_EVENT_PACKET_CONSTRUCTOR = MethodHandles
.privateLookupIn(ClientboundBossEventPacket::class.java, MethodHandles.lookup())
.findConstructor(ClientboundBossEventPacket::class.java, MethodType.methodType(Void.TYPE, UUID::class.java, BOSS_BAR_OPERATION_CLASS))

fun ClientboundBossEventPacket(id: UUID, operation: BossBarOperation): ClientboundBossEventPacket {
return CLIENTBOUND_BOSS_EVENT_PACKET_CONSTRUCTOR.invoke(id, operation.toNMS()) as ClientboundBossEventPacket
internal fun AddOperation(
name: Component,
progress: Float,
color: BossEvent.BossBarColor,
overlay: BossEvent.BossBarOverlay,
darkenScreen: Boolean,
playMusic: Boolean,
createWorldFog: Boolean
): ClientboundBossEventPacket.AddOperation {
val buf = RegistryFriendlyByteBuf()
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buf, name.toNMSComponent())
buf.writeFloat(progress)
buf.writeEnum(color)
buf.writeEnum(overlay)
var result = 0
if (darkenScreen)
result = result or 1
if (playMusic)
result = result or 2
if (createWorldFog)
result = result or 4
buf.writeByte(result)
return ClientboundBossEventPacket.AddOperation(buf)
}

fun ClientboundSoundEntityPacket(sound: Holder<SoundEvent>, source: SoundSource, entityId: Int, volume: Float, pitch: Float, seed: Long): ClientboundSoundEntityPacket {
Expand All @@ -48,45 +60,10 @@ fun ClientboundSoundEntityPacket(sound: Holder<SoundEvent>, source: SoundSource,
return ClientboundSoundEntityPacket.STREAM_CODEC.decode(buf)
}

private val CLIENTBOUND_UPDATE_ATTRIBUTES_PACKET_CONSTRUCTOR = MethodHandles
.privateLookupIn(ClientboundUpdateAttributesPacket::class.java, MethodHandles.lookup())
.findConstructor(ClientboundUpdateAttributesPacket::class.java, MethodType.methodType(Void.TYPE, Int::class.java, List::class.java))

fun ClientboundUpdateAttributesPacket(entityId: Int, values: List<AttributeSnapshot>): ClientboundUpdateAttributesPacket {
return CLIENTBOUND_UPDATE_ATTRIBUTES_PACKET_CONSTRUCTOR.invoke(entityId, values) as ClientboundUpdateAttributesPacket
}

fun ServerboundPlaceRecipePacket(containerId: Int, recipe: ResourceLocation, shiftDown: Boolean): ServerboundPlaceRecipePacket {
val buf = FriendlyByteBuf(Unpooled.buffer())
buf.writeByte(containerId)
buf.writeResourceLocation(recipe)
buf.writeBoolean(shiftDown)
return ServerboundPlaceRecipePacket.STREAM_CODEC.decode(buf)
}

fun ServerboundInteractPacket(entityId: Int, action: ServerboundInteractPacketEvent.Action, isUsingSecondaryAction: Boolean): ServerboundInteractPacket {
val buf = FriendlyByteBuf(Unpooled.buffer())

buf.writeVarInt(entityId)
when (action) {
is ServerboundInteractPacketEvent.Action.Interact -> {
buf.writeVarInt(0)
buf.writeVarInt(action.hand.ordinal)
}

is ServerboundInteractPacketEvent.Action.InteractAtLocation -> {
buf.writeVarInt(2)
buf.writeFloat(action.location.x.toFloat())
buf.writeFloat(action.location.y.toFloat())
buf.writeFloat(action.location.z.toFloat())
buf.writeVarInt(action.hand.ordinal)
}

is ServerboundInteractPacketEvent.Action.Attack -> {
buf.writeVarInt(1)
}
}
buf.writeBoolean(isUsingSecondaryAction)

return ServerboundInteractPacket.STREAM_CODEC.decode(buf)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package xyz.xenondevs.nova.network

import io.netty.buffer.ByteBuf
import it.unimi.dsi.fastutil.objects.Object2IntMap
import net.minecraft.network.PacketListener
import net.minecraft.network.ProtocolInfo
Expand All @@ -15,11 +16,6 @@ import net.minecraft.network.protocol.game.GamePacketTypes
import net.minecraft.network.protocol.game.GameProtocols
import net.minecraft.network.protocol.ping.PingPacketTypes
import xyz.xenondevs.nova.util.REGISTRY_ACCESS
import java.lang.invoke.MethodHandles

private val ID_DISPATCH_CODEC_TO_ID = MethodHandles
.privateLookupIn(IdDispatchCodec::class.java, MethodHandles.lookup())
.findGetter(IdDispatchCodec::class.java, "toId", Object2IntMap::class.java)

internal object PacketIdRegistry {

Expand Down Expand Up @@ -213,8 +209,9 @@ internal object PacketIdRegistry {
private fun <L : PacketListener, P : Packet<in L>> getPacketIdMap(
template: ProtocolInfo.Unbound<L, RegistryFriendlyByteBuf>
): Object2IntMap<PacketType<P>> {
val codec = template.bind(RegistryFriendlyByteBuf.decorator(REGISTRY_ACCESS)).codec()
return ID_DISPATCH_CODEC_TO_ID.invoke(codec) as Object2IntMap<PacketType<P>>
val codec = template.bind(RegistryFriendlyByteBuf.decorator(REGISTRY_ACCESS)).codec()
as IdDispatchCodec<ByteBuf, Packet<in L>, PacketType<P>>
return codec.toId
}

}
21 changes: 3 additions & 18 deletions nova/src/main/kotlin/xyz/xenondevs/nova/network/PacketManager.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package xyz.xenondevs.nova.network

import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInboundHandlerAdapter
import io.netty.channel.ChannelInitializer
import net.kyori.adventure.text.Component
import net.minecraft.network.Connection
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.server.network.ServerCommonPacketListenerImpl
import net.minecraft.server.network.ServerConnectionListener
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
Expand All @@ -25,16 +21,8 @@ import xyz.xenondevs.nova.initialize.InternalInitStage
import xyz.xenondevs.nova.util.MINECRAFT_SERVER
import xyz.xenondevs.nova.util.registerEvents
import xyz.xenondevs.nova.util.serverPlayer
import java.lang.invoke.MethodHandles
import net.minecraft.world.entity.player.Player as MojangPlayer

private val SERVER_CONNECTION_LISTENER_CHANNELS_GETTER = MethodHandles
.privateLookupIn(ServerConnectionListener::class.java, MethodHandles.lookup())
.findGetter(ServerConnectionListener::class.java, "channels", List::class.java)
private val SERVER_COMMON_PACKET_LISTENER_IMPL_CONNECTION_GETTER = MethodHandles
.privateLookupIn(ServerCommonPacketListenerImpl::class.java, MethodHandles.lookup())
.findGetter(ServerCommonPacketListenerImpl::class.java, "connection", Connection::class.java)

val Player.packetHandler: PacketHandler?
get() = PacketManager.playerHandlers[name]

Expand Down Expand Up @@ -79,8 +67,7 @@ internal object PacketManager : Listener {

@Suppress("UNCHECKED_CAST")
private fun registerHandlers() {
val channels = SERVER_CONNECTION_LISTENER_CHANNELS_GETTER.invoke(MINECRAFT_SERVER.connection) as List<ChannelFuture>
serverChannel = channels.first().channel()
serverChannel = MINECRAFT_SERVER.connection.channels.first().channel()

val pipeline = serverChannel.pipeline()
pipeline.context("nova_pipeline_adapter")?.handler()?.run(pipeline::remove)
Expand Down Expand Up @@ -141,14 +128,12 @@ internal object PacketManager : Listener {
}

private fun registerHandler(player: Player) {
val connection = SERVER_COMMON_PACKET_LISTENER_IMPL_CONNECTION_GETTER.invoke(player.serverPlayer.connection) as Connection
val channel = connection.channel
val channel = player.serverPlayer.connection.connection.channel
channel.pipeline().addBefore("packet_handler", "nova_packet_handler", PacketHandler(channel, player))
}

private fun unregisterHandler(player: Player) {
val connection = SERVER_COMMON_PACKET_LISTENER_IMPL_CONNECTION_GETTER.invoke(player.serverPlayer.connection) as Connection
val pipeline = connection.channel.pipeline()
val pipeline = player.serverPlayer.connection.connection.channel.pipeline()
pipeline.context("nova_packet_handler")?.handler()?.run(pipeline::remove)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@ package xyz.xenondevs.nova.network.event.clientbound

import net.minecraft.network.protocol.game.ClientboundBossEventPacket
import org.bukkit.entity.Player
import xyz.xenondevs.nova.network.ClientboundBossEventPacket
import xyz.xenondevs.nova.network.event.PlayerPacketEvent
import xyz.xenondevs.nova.util.MutableLazy
import xyz.xenondevs.nova.util.bossbar.operation.BossBarOperation
import java.lang.invoke.MethodHandles
import java.util.*

private val CLIENTBOUND_BOSS_EVENT_PACKET_ID_GETTER = MethodHandles
.privateLookupIn(ClientboundBossEventPacket::class.java, MethodHandles.lookup())
.findGetter(ClientboundBossEventPacket::class.java, "id", UUID::class.java)

class ClientboundBossEventPacketEvent(
player: Player,
packet: ClientboundBossEventPacket
) : PlayerPacketEvent<ClientboundBossEventPacket>(player, packet) {

var id: UUID by MutableLazy({ changed = true }) { CLIENTBOUND_BOSS_EVENT_PACKET_ID_GETTER.invoke(packet) as UUID }
var operation: BossBarOperation by MutableLazy({ changed = true }) { BossBarOperation.fromPacket(packet) }
var id = packet.id
set(value) {
field = value
changed = true
}
var operation: ClientboundBossEventPacket.Operation = packet.operation
set(value) {
field = value
changed = true
}

override fun buildChangedPacket(): ClientboundBossEventPacket {
return ClientboundBossEventPacket(id, operation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package xyz.xenondevs.nova.network.event.clientbound
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket.AttributeSnapshot
import org.bukkit.entity.Player
import xyz.xenondevs.nova.network.ClientboundUpdateAttributesPacket
import xyz.xenondevs.nova.network.event.PlayerPacketEvent

class ClientboundUpdateAttributesPacketEvent(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,21 @@
package xyz.xenondevs.nova.network.event.clientbound

import net.minecraft.network.protocol.game.ServerboundInteractPacket
import net.minecraft.world.InteractionHand
import net.minecraft.world.phys.Vec3
import org.bukkit.entity.Player
import xyz.xenondevs.nova.network.event.PlayerPacketEvent
import java.lang.invoke.MethodHandles

private val ACTION =
Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket\$Action")
private val INTERACTION_ACTION =
Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket\$InteractionAction")
private val INTERACTION_AT_LOCATION_ACTION =
Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket\$InteractionAtLocationAction")

private val SERVERBOUND_INTERACT_PACKET_LOOKUP = MethodHandles
.privateLookupIn(ServerboundInteractPacket::class.java, MethodHandles.lookup())
private val INTERACTION_ACTION_LOOKUP = MethodHandles
.privateLookupIn(INTERACTION_ACTION, MethodHandles.lookup())
private val INTERACTION_AT_LOCATION_ACTION_LOOKUP = MethodHandles
.privateLookupIn(INTERACTION_AT_LOCATION_ACTION, MethodHandles.lookup())
private val SERVERBOUND_INTERACT_PACKET_ENTITY_ID_GETTER = SERVERBOUND_INTERACT_PACKET_LOOKUP
.findGetter(ServerboundInteractPacket::class.java, "entityId", Int::class.java)
private val SERVERBOUND_INTERACT_PACKET_ACTION_GETTER = SERVERBOUND_INTERACT_PACKET_LOOKUP
.findGetter(ServerboundInteractPacket::class.java, "action", ACTION)
private val INTERACTION_ACTION_HAND_GETTER = INTERACTION_ACTION_LOOKUP
.findGetter(INTERACTION_ACTION, "hand", InteractionHand::class.java)
private val INTERACTION_AT_LOCATION_ACTION_HAND_GETTER = INTERACTION_AT_LOCATION_ACTION_LOOKUP
.findGetter(INTERACTION_AT_LOCATION_ACTION, "hand", InteractionHand::class.java)
private val INTERACTION_AT_LOCATION_ACTION_LOCATION_GETTER = INTERACTION_AT_LOCATION_ACTION_LOOKUP
.findGetter(INTERACTION_AT_LOCATION_ACTION, "location", Vec3::class.java)

class ServerboundInteractPacketEvent(
player: Player,
packet: ServerboundInteractPacket
) : PlayerPacketEvent<ServerboundInteractPacket>(player, packet) {

var entityId = SERVERBOUND_INTERACT_PACKET_ENTITY_ID_GETTER.invoke(packet) as Int
var entityId = packet.entityId
set(value) {
field = value
changed = true
}

var action = Action.of(SERVERBOUND_INTERACT_PACKET_ACTION_GETTER.invoke(packet))
var action = packet.action
set(value) {
field = value
changed = true
Expand All @@ -55,34 +28,6 @@ class ServerboundInteractPacketEvent(
}

override fun buildChangedPacket(): ServerboundInteractPacket =
xyz.xenondevs.nova.network.ServerboundInteractPacket(entityId, action, isUsingSecondaryAction)

sealed interface Action {

data class Interact(val hand: InteractionHand) : Action

data class InteractAtLocation(val hand: InteractionHand, val location: Vec3) : Action

data object Attack : Action

companion object {

internal fun of(nmsAction: Any): Action = when (nmsAction.javaClass) {
ACTION -> Interact(
INTERACTION_ACTION_HAND_GETTER.invoke(nmsAction) as InteractionHand
)

INTERACTION_AT_LOCATION_ACTION -> InteractAtLocation(
INTERACTION_AT_LOCATION_ACTION_HAND_GETTER.invoke(nmsAction) as InteractionHand,
INTERACTION_AT_LOCATION_ACTION_LOCATION_GETTER.invoke(nmsAction) as Vec3
)

// ServerboundInteractPacket.ATTACK anonymous class
else -> Attack
}

}

}
ServerboundInteractPacket(entityId, isUsingSecondaryAction, action)

}
Loading

0 comments on commit 05622a1

Please sign in to comment.