1+ package dev.slne.surf.surfapi.bukkit.server.inventory.framework
2+
3+ import net.bytebuddy.ByteBuddy
4+ import net.bytebuddy.asm.AsmVisitorWrapper
5+ import net.bytebuddy.description.field.FieldDescription
6+ import net.bytebuddy.description.field.FieldList
7+ import net.bytebuddy.description.method.MethodList
8+ import net.bytebuddy.description.type.TypeDescription
9+ import net.bytebuddy.dynamic.ClassFileLocator
10+ import net.bytebuddy.dynamic.loading.ClassLoadingStrategy
11+ import net.bytebuddy.implementation.Implementation
12+ import net.bytebuddy.jar.asm.ClassVisitor
13+ import net.bytebuddy.jar.asm.MethodVisitor
14+ import net.bytebuddy.jar.asm.Opcodes
15+ import net.bytebuddy.pool.TypePool
16+ import net.bytebuddy.utility.OpenedClassReader
17+ import org.bukkit.inventory.InventoryView
18+
19+ object InventoryViewRemapper {
20+ private const val INVENTORY_VIEW_INTERNAL = " org/bukkit/inventory/InventoryView"
21+ private const val INVENTORY_UPDATE_INTERNAL =
22+ " dev/slne/surf/surfapi/libs/devnatan/inventoryframework/runtime/thirdparty/InventoryUpdate"
23+
24+ fun isRemapNecessary (): Boolean {
25+ return try {
26+ InventoryView ::class .java.isInterface
27+ } catch (_: Throwable ) {
28+ false
29+ }
30+ }
31+
32+ fun remap () {
33+ if (! isRemapNecessary()) return
34+
35+ val locator = ClassFileLocator .ForClassLoader .of(javaClass.classLoader)
36+ val typePool = TypePool .Default .of(locator)
37+ val typeDescription = typePool.describe(INVENTORY_UPDATE_INTERNAL .replace(" /" , " ." )).resolve()
38+
39+ ByteBuddy ()
40+ .redefine<Any >(typeDescription, locator)
41+ .visit(InventoryViewClassVisitorWrapper ())
42+ .make()
43+ .load(javaClass.classLoader, ClassLoadingStrategy .Default .INJECTION )
44+ }
45+
46+ private class InventoryViewClassVisitorWrapper : AsmVisitorWrapper {
47+ override fun mergeWriter (flags : Int ): Int = flags
48+ override fun mergeReader (flags : Int ): Int = flags
49+
50+ override fun wrap (
51+ instrumentedType : TypeDescription ,
52+ classVisitor : ClassVisitor ,
53+ implementationContext : Implementation .Context ,
54+ typePool : TypePool ,
55+ fields : FieldList <FieldDescription .InDefinedShape ?>,
56+ methods : MethodList <* >,
57+ writerFlags : Int ,
58+ readerFlags : Int
59+ ): ClassVisitor {
60+ return InventoryViewClassVisitor (classVisitor)
61+ }
62+ }
63+
64+ private class InventoryViewClassVisitor (
65+ visitor : ClassVisitor
66+ ) : ClassVisitor(OpenedClassReader .ASM_API , visitor) {
67+
68+ override fun visitMethod (
69+ access : Int ,
70+ name : String ,
71+ descriptor : String ,
72+ signature : String? ,
73+ exceptions : Array <String >?
74+ ): MethodVisitor {
75+ val mv = super .visitMethod(access, name, descriptor, signature, exceptions)
76+ return InventoryViewMethodVisitor (mv)
77+ }
78+ }
79+
80+ private class InventoryViewMethodVisitor (
81+ visitor : MethodVisitor
82+ ) : MethodVisitor(OpenedClassReader .ASM_API , visitor) {
83+
84+ override fun visitMethodInsn (
85+ opcode : Int ,
86+ owner : String ,
87+ name : String ,
88+ descriptor : String ,
89+ isInterface : Boolean
90+ ) {
91+ if (opcode == Opcodes .INVOKEVIRTUAL && owner == INVENTORY_VIEW_INTERNAL ) {
92+ super .visitMethodInsn(
93+ Opcodes .INVOKEINTERFACE ,
94+ owner,
95+ name,
96+ descriptor,
97+ true
98+ )
99+ } else {
100+ super .visitMethodInsn(opcode, owner, name, descriptor, isInterface)
101+ }
102+ }
103+ }
104+ }
0 commit comments