Skip to content
This repository has been archived by the owner on Jun 3, 2024. It is now read-only.

Commit

Permalink
Use protocollib's built in converters where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
0ffz committed Mar 14, 2024
1 parent 0dc0752 commit 932d364
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 52 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ allprojects {
repositories {
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://repo.dmulloy2.net/nexus/repository/public/")//ProtocolLib
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://repo.papermc.io/repository/maven-public/")
}

val libs = rootProject.idofrontLibs
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version=0.9
version=0.10
group=com.mineinabyss
idofrontVersion=0.22.3
publishComponentName=java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.mineinabyss.protocolburrito

import com.comphenix.protocol.events.PacketContainer

object FieldHelpers {
inline fun <reified T : Any> getField(forObject: Any, index: Int): T =
getField(T::class.java, forObject, index)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.comphenix.protocol.PacketType
import com.comphenix.protocol.injector.packet.PacketRegistry

interface WrappedCompanion {
val type: PacketType
val packetType: PacketType

fun wrap(any: Any): Any
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package com.mineinabyss.protocolburrito

interface WrappedPacket
import com.comphenix.protocol.events.PacketContainer

interface WrappedPacket {
val container: PacketContainer
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ProtocolManagerBurrito(
crossinline onSend: PacketEvent.(wrapped: T) -> Unit
) {
val companion = T::class.companionObjectInstance as WrappedCompanion
onSend(companion.type, priority = priority) { onSend(companion.wrap(packet.handle) as T) }
onSend(companion.packetType, priority = priority) { onSend(companion.wrap(packet.handle) as T) }
}

inline fun onSend(
Expand All @@ -48,7 +48,7 @@ class ProtocolManagerBurrito(
crossinline onReceive: PacketEvent.(wrapped: T) -> Unit
) {
val companion = T::class.companionObjectInstance as WrappedCompanion
onReceive(companion.type, priority = priority) { onReceive(companion.wrap(packet.handle) as T) }
onReceive(companion.packetType, priority = priority) { onReceive(companion.wrap(packet.handle) as T) }
}

inline fun onReceive(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mineinabyss.protocolburrito.generation

import com.comphenix.protocol.PacketType
import com.comphenix.protocol.events.PacketContainer
import com.comphenix.protocol.injector.packet.PacketRegistry
import com.mineinabyss.protocolburrito.FieldHelpers
import com.mineinabyss.protocolburrito.WrappedCompanion
Expand All @@ -11,36 +12,59 @@ import org.reflections.Reflections
import org.reflections.scanners.SubTypesScanner
import java.io.File
import java.util.concurrent.atomic.AtomicInteger
import kotlin.reflect.KType
import kotlin.reflect.KClass
import kotlin.reflect.KVisibility
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.jvmErasure

val OUTPUT_DIR = File("build/generated/burrito/main/")

@OptIn(ExperimentalStdlibApi::class)
fun generateProtocolExtensions() {
val reflections = Reflections("net.minecraft.network.protocol.game", SubTypesScanner(false))
reflections.getSubTypesOf(Packet::class.java)
.map { it.kotlin }
.filter { !it.isAbstract }
.forEach { packetClass ->
val indices = mutableMapOf<KType, AtomicInteger>()
val indices = mutableMapOf<KClass<*>, AtomicInteger>()
val props = packetClass.declaredMemberProperties.mapNotNull { field ->

val type = field.returnType
if (field.visibility == KVisibility.PUBLIC) return@mapNotNull null
if (field.returnType.jvmErasure.visibility != KVisibility.PUBLIC) return@mapNotNull null
if (field.returnType.arguments.any { it.type?.jvmErasure?.visibility != KVisibility.PUBLIC }) return@mapNotNull null
val index = indices.getOrPut(type) { AtomicInteger(0) }
PropertySpec.builder(field.name, type.asTypeName().copy(annotations = listOf())) //.let {
val typeInfo = TypeMap.getStructureModifier(type) ?: run {
println("Creating ${packetClass.simpleName}")
println("Failed to find structure modifier on (name=${field.name}, type=$type, erased=${type.jvmErasure})")
if (field.returnType.jvmErasure.visibility != KVisibility.PUBLIC) return@mapNotNull null
if (field.returnType.arguments.any { it.type?.jvmErasure?.visibility != KVisibility.PUBLIC }) return@mapNotNull null
null
}
val useType = typeInfo?.type ?: type.asTypeName()
val index = indices.getOrPut(type.jvmErasure) { AtomicInteger(0) }
PropertySpec.builder(field.name, useType.copy(annotations = listOf()))
.getter(
FunSpec.getterBuilder()
.addStatement("return %T.getField(handle, ${index.toInt()})", FieldHelpers::class)
FunSpec.getterBuilder().run {
if (typeInfo != null)
addStatement(
"return container.%N().read(${index.toInt()})",
typeInfo.structureModifierMember
)
else
addStatement("return %T.getField(handle, ${index.toInt()})", FieldHelpers::class)
}
.build()
)
.setter(
FunSpec.setterBuilder()
.addParameter(ParameterSpec.builder("value", type.asTypeName()).build())
.addCode("%T.setField(handle, ${index.toInt()}, value)", FieldHelpers::class)
.run {
if (typeInfo != null)
addCode(
"container.%N().write(${index.toInt()}, value)",
typeInfo.structureModifierMember
)
else
addCode("%T.setField(handle, ${index.toInt()}, value)", FieldHelpers::class)
}
.build()
)
.mutable(true)
Expand All @@ -62,13 +86,18 @@ fun generateProtocolExtensions() {
PropertySpec.builder("handle", Any::class/*packetClass*/).build()
)
// .addProperty("handle", packetClass)
.addProperty(
PropertySpec.builder("container", PacketContainer::class, KModifier.OVERRIDE)
.initializer("PacketContainer(packetType, handle)")
.build()
)
.addProperties(props)
.addType(
TypeSpec
.companionObjectBuilder()
.addSuperinterface(WrappedCompanion::class)
.addProperty(
PropertySpec.builder("type", PacketType::class)
PropertySpec.builder("packetType", PacketType::class)
.addModifiers(KModifier.OVERRIDE)
.getter(
FunSpec.getterBuilder()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,140 @@
package com.mineinabyss.protocolburrito.generation

import com.comphenix.protocol.events.PacketContainer
import com.comphenix.protocol.reflect.StructureModifier
import org.bukkit.entity.Entity
import kotlin.reflect.KClass
import kotlin.reflect.KFunction1
import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.MemberName.Companion.member
import it.unimi.dsi.fastutil.objects.Object2IntMap
import net.minecraft.stats.Stat
import java.util.*
import kotlin.reflect.*
import kotlin.reflect.full.withNullability

object TypeMap {
class TypeInfo<T : Any>(
val kClass: KClass<T>,
val structureModified: KFunction1<PacketContainer, StructureModifier<T>>
class TypeInfo(
val type: TypeName,
val structureModifierMember: MemberName
// val structureModifier: KFunction1<PacketContainer, StructureModifier<T>>
)

inline fun <reified T : Any> get(function: KFunction1<PacketContainer, StructureModifier<T>>): TypeInfo<T> {
return TypeInfo(T::class, function)
// inline fun <reified T : Any> get(function: KFunction1<PacketContainer, StructureModifier<T>>): TypeInfo<T> {
// return TypeInfo(T::class, function)
// }
//
// val types = mapOf<String, TypeInfo>(
// // Arrays
// //TODO doesnt work because Array<String> gets type erased
//// "java.lang.String[]" to get<Array<String>>(PacketContainer::getStringArrays),
// "byte[]" to get<ByteArray>(PacketContainer::getByteArrays),
// "int[]" to get<IntArray>(PacketContainer::getIntegerArrays),
// "short[]" to get<ShortArray>(PacketContainer::getShortArrays),
// "net.minecraft.world.entity.EntityType<?>" to get(PacketContainer::getEntityTypeModifier),
// "net.minecraft.core.BlockPos" to get(PacketContainer::getBlockPositionModifier),
// //TODO UNSURE
// "net.minecraft.network.chat.Component" to get(PacketContainer::getChatComponents),
// //TODO figure something out with this modifier, requires world parameter pass
//// "net.minecraft.world.entity.Entity" to get(PacketContainer::getEntityModifier),
// )

@OptIn(ExperimentalStdlibApi::class)
fun getStructureModifier(type: KType): TypeInfo? {
// val type = type.withNullability(false)
// val singleArgument = type.arguments.singleOrNull()?.type?.withNullability(false)
// if(singleArgument != null) {
// val outerType = outerModifier[type.jvmErasure]
// println("Working on $type with args ${type.arguments}, and erased ${type.jvmErasure}")
// if (outerType != null) {
// println(FunSpec.builder("test").addStatement("val test = %N", outerType).build())
// }
//
// leafModifier[singleArgument]
//
// println("Got type $outerType")
// }
val modifier = mappedLeafModifiers[type.javaType] ?: return null
val structureModifierName = modifier.name
val fieldType = modifier.returnType.arguments.single().type!!.asTypeName()

return TypeInfo(fieldType, packetContainer.member(structureModifierName))
}

val types = mapOf<String, TypeInfo<*>>(
"byte" to get(PacketContainer::getBytes),
"boolean" to get(PacketContainer::getBooleans),
"short" to get(PacketContainer::getShorts),
"int" to get(PacketContainer::getIntegers),
"long" to get(PacketContainer::getLongs),
"float" to get(PacketContainer::getFloat),
"double" to get(PacketContainer::getDoubles),
"java.lang.String" to get(PacketContainer::getStrings),
"java.util.UUID" to get(PacketContainer::getUUIDs),
//TODO doesnt work because Array<String> gets type erased
// "java.lang.String[]" to get<Array<String>>(PacketContainer::getStringArrays),
"byte[]" to get<ByteArray>(PacketContainer::getByteArrays),
"int[]" to get<IntArray>(PacketContainer::getIntegerArrays),
"short[]" to get<ShortArray>(PacketContainer::getShortArrays),
// "" to get(PacketContainer::getItemModifier),
// "" to get(PacketContainer::getItemArrayModifier),
// "" to get(PacketContainer::getItemListModifier),
// "" to get(PacketContainer::getStatisticMaps),
// "" to get(PacketContainer::getWorldTypeModifier),
// "" to get(PacketContainer::getDataWatcherModifier),
"net.minecraft.world.entity.EntityType" to get(PacketContainer::getEntityTypeModifier),
"net.minecraft.core.BlockPos" to get(PacketContainer::getBlockPositionModifier),
//TODO UNSURE
"net.minecraft.network.chat.Component" to get(PacketContainer::getChatComponents),
//TODO figure something out with this modifier, requires world parameter pass
// "net.minecraft.world.entity.Entity" to get(PacketContainer::getEntityModifier),
val packetContainer = PacketContainer::class.asClassName()

val outerModifier = mapOf<KClass<*>, MemberName>(
List::class to packetContainer.member("lists"),
// Optional::class to PacketContainer::getOptionals,
)

private val leafModifier = mapOf<KType, KFunction<*>>(
// Primitives
typeOf<Byte>() to PacketContainer::getIntegers,
typeOf<Boolean>() to PacketContainer::getBooleans,
typeOf<Short>() to PacketContainer::getShorts,
typeOf<Int>() to PacketContainer::getIntegers,
typeOf<Long>() to PacketContainer::getLongs,
typeOf<Float>() to PacketContainer::getFloat,
typeOf<Double>() to PacketContainer::getDoubles,
typeOf<String>() to PacketContainer::getStrings,
typeOf<UUID>() to PacketContainer::getUUIDs,
typeOf<Array<String>>() to PacketContainer::getStringArrays,
typeOf<ByteArray>() to PacketContainer::getByteArrays,
typeOf<IntArray>() to PacketContainer::getIntegerArrays,
typeOf<ShortArray>() to PacketContainer::getShortArrays,
typeOf<net.minecraft.world.item.ItemStack>() to PacketContainer::getItemModifier,
typeOf<Array<net.minecraft.world.item.ItemStack>>() to PacketContainer::getItemArrayModifier,
typeOf<List<net.minecraft.world.item.ItemStack>>() to PacketContainer::getItemListModifier,
typeOf<Object2IntMap<Stat<*>>>() to PacketContainer::getStatisticMaps,
// typeOf<net.minecraft.world.level.GameType>() to PacketContainer::getWorldTypeModifier,
typeOf<net.minecraft.network.syncher.SynchedEntityData>() to PacketContainer::getDataWatcherModifier,
typeOf<net.minecraft.world.entity.EntityType<*>>() to PacketContainer::getEntityTypeModifier,
typeOf<net.minecraft.core.BlockPos>() to PacketContainer::getBlockPositionModifier,
typeOf<net.minecraft.world.level.block.entity.BlockEntityType<*>>() to PacketContainer::getBlockEntityTypeModifier,
// TODO getChunkCoordIntPairs
typeOf<net.minecraft.nbt.CompoundTag>() to PacketContainer::getNbtModifier,
typeOf<List<net.minecraft.nbt.CompoundTag>>() to PacketContainer::getListNbtModifier,
typeOf<net.minecraft.world.phys.Vec3>() to PacketContainer::getVectors,
typeOf<List<net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket.AttributeSnapshot>>() to PacketContainer::getAttributeCollectionModifier,
typeOf<List<net.minecraft.core.BlockPos>>() to PacketContainer::getBlockPositionCollectionModifier,
typeOf<List<net.minecraft.network.syncher.SynchedEntityData.DataItem<*>>>() to PacketContainer::getWatchableCollectionModifier,
typeOf<List<net.minecraft.network.syncher.SynchedEntityData.DataValue<*>>>() to PacketContainer::getDataValueCollectionModifier,
// blocks
typeOf<net.minecraft.world.level.block.Block>() to PacketContainer::getBlocks,
typeOf<net.minecraft.world.level.block.state.BlockState>() to PacketContainer::getBlockData,
typeOf<Array<net.minecraft.world.level.block.state.BlockState>>() to PacketContainer::getBlockDataArrays,
//getMultiBlockChangeInfoArrays
typeOf<net.minecraft.network.chat.Component>() to PacketContainer::getChatComponents,
typeOf<Array<net.minecraft.network.chat.Component>>() to PacketContainer::getChatComponentArrays,
// getServerPings
// getPlayerInfoDataLists
// getProtocols
// getClientCommands
// getChatVisibilities
typeOf<net.minecraft.world.Difficulty>() to PacketContainer::getDifficulties,
// getEntityUseActions
// getEnumEntityUseActions
// getGameModes
// getResourcePackStatus
// getPlayerInfoAction
// getPlayerInfoActions
// getTitleActions
// getWorldBorderActions
// getCombatEvents
// getPlayerDigTypes
// getPlayerActions
// getScoreboardActions
// getParticles
// getNewParticles
// getEffectTypes
// getSoundCategories
// ...
typeOf<net.minecraft.world.InteractionHand>() to PacketContainer::getHands,
typeOf<net.minecraft.core.Direction>() to PacketContainer::getDirections,
typeOf<net.minecraft.network.chat.ChatType.BoundNetwork>() to PacketContainer::getChatTypes,
typeOf<net.minecraft.resources.ResourceLocation>() to PacketContainer::getMinecraftKeys,
// getDimensions
typeOf<net.minecraft.world.level.dimension.DimensionType>() to PacketContainer::getDimensionTypes,
// getMerchantRecipeLists
// ...
)
@OptIn(ExperimentalStdlibApi::class)
private val mappedLeafModifiers = leafModifier.mapKeys { it.key.javaType }
}
8 changes: 8 additions & 0 deletions protocolburrito-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ dependencies {
compileOnly(idofrontLibs.bundles.idofront.core)
implementation(project(":"))
}


configurations {
runtimeClasspath {
val protocolLib = idofrontLibs.minecraft.plugin.protocollib.get()
exclude(protocolLib.group, protocolLib.name)
}
}
1 change: 1 addition & 0 deletions protocolburrito-plugin/src/main/resources/paper-plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ dependencies:
ProtocolLib:
required: true
load: BEFORE
join-classpath: true
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencyResolutionManagement {
}

include(
"protocolburrito-generator-obfuscated",
"protocolburrito-generator",
"protocolburrito-api",
"protocolburrito-plugin"
Expand Down

0 comments on commit 932d364

Please sign in to comment.