mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-07-06 19:44:55 +02:00
Generate actual classes for LP events at runtime instead of using proxies + InvocationHandlers
This commit is contained in:
parent
b65639cd76
commit
c3128dec0d
|
@ -55,6 +55,7 @@ shadowJar {
|
|||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
|
|
|
@ -41,6 +41,7 @@ shadowJar {
|
|||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
|
|
|
@ -21,6 +21,7 @@ dependencies {
|
|||
compile 'com.github.ben-manes.caffeine:caffeine:2.8.0'
|
||||
compile 'com.squareup.okhttp3:okhttp:3.14.4'
|
||||
compile 'com.squareup.okio:okio:1.17.4'
|
||||
compile 'net.bytebuddy:byte-buddy:1.10.9'
|
||||
compile('me.lucko.configurate:configurate-core:3.5') {
|
||||
exclude(module: 'guava')
|
||||
}
|
||||
|
|
|
@ -127,6 +127,13 @@ public enum Dependency {
|
|||
Relocation.of(RelocationHelper.OKHTTP3_STRING, RelocationHelper.OKHTTP3_STRING),
|
||||
Relocation.of(RelocationHelper.OKIO_STRING, RelocationHelper.OKIO_STRING)
|
||||
),
|
||||
BYTEBUDDY(
|
||||
"net{}bytebuddy",
|
||||
"byte-buddy",
|
||||
"1.10.9",
|
||||
"B7nKbi+XDLA/SyVlHfHy/OJx1JG0TgQJgniHeG9pLU0=",
|
||||
Relocation.of("bytebuddy", "net{}bytebuddy")
|
||||
),
|
||||
COMMODORE(
|
||||
"me{}lucko",
|
||||
"commodore",
|
||||
|
|
|
@ -32,7 +32,7 @@ import me.lucko.luckperms.common.api.implementation.ApiPermissionHolder;
|
|||
import me.lucko.luckperms.common.api.implementation.ApiUser;
|
||||
import me.lucko.luckperms.common.cacheddata.GroupCachedDataManager;
|
||||
import me.lucko.luckperms.common.cacheddata.UserCachedDataManager;
|
||||
import me.lucko.luckperms.common.event.gen.GeneratedEventSpec;
|
||||
import me.lucko.luckperms.common.event.gen.GeneratedEventClass;
|
||||
import me.lucko.luckperms.common.event.model.EntitySourceImpl;
|
||||
import me.lucko.luckperms.common.event.model.SenderPlatformEntity;
|
||||
import me.lucko.luckperms.common.event.model.UnknownSource;
|
||||
|
@ -132,7 +132,11 @@ public final class EventDispatcher {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends LuckPermsEvent> T generate(Class<T> eventClass, Object... params) {
|
||||
return (T) GeneratedEventSpec.lookup(eventClass).newInstance(this.eventBus.getApiProvider(), params);
|
||||
try {
|
||||
return (T) GeneratedEventClass.generate(eventClass).newInstance(this.eventBus.getApiProvider(), params);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Exception occurred whilst generating event instance", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchExtensionLoad(Extension extension) {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.event.gen;
|
||||
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.event.LuckPermsEvent;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link LuckPermsEvent}.
|
||||
*/
|
||||
public abstract class AbstractEvent implements LuckPermsEvent {
|
||||
private final LuckPerms api;
|
||||
|
||||
protected AbstractEvent(LuckPerms api) {
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull LuckPerms getLuckPerms() {
|
||||
return this.api;
|
||||
}
|
||||
|
||||
// Overridden by the subclass. Used by GeneratedEventClass to get setter method handles.
|
||||
public MethodHandles.Lookup mhl() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.event.gen;
|
||||
|
||||
import me.lucko.luckperms.common.cache.LoadingMap;
|
||||
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.ClassFileVersion;
|
||||
import net.bytebuddy.description.NamedElement;
|
||||
import net.bytebuddy.description.modifier.Visibility;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.FixedValue;
|
||||
import net.bytebuddy.implementation.MethodCall;
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.event.LuckPermsEvent;
|
||||
import net.luckperms.api.event.util.Param;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.returns;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
|
||||
/**
|
||||
* Holds the generated event class for a given type of {@link LuckPermsEvent}.
|
||||
*/
|
||||
public class GeneratedEventClass {
|
||||
|
||||
/** The MethodHandles.lookup() method */
|
||||
private static final Method METHOD_HANDLES_LOOKUP;
|
||||
static {
|
||||
try {
|
||||
METHOD_HANDLES_LOOKUP = MethodHandles.class.getMethod("lookup");
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A loading cache of event types to {@link GeneratedEventClass}es.
|
||||
*/
|
||||
private static final Map<Class<? extends LuckPermsEvent>, GeneratedEventClass> CACHE = LoadingMap.of(clazz -> {
|
||||
try {
|
||||
return new GeneratedEventClass(clazz);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Generate a {@link GeneratedEventClass} for the given {@code event} type.
|
||||
*
|
||||
* @param event the event type
|
||||
* @return the generated class
|
||||
*/
|
||||
public static GeneratedEventClass generate(Class<? extends LuckPermsEvent> event) {
|
||||
return CACHE.get(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor used to create instances of the generated class
|
||||
*/
|
||||
private final Constructor<? extends AbstractEvent> constructor;
|
||||
|
||||
/**
|
||||
* An array of {@link MethodHandle}s, which can set values for each of the properties in the event class.
|
||||
*/
|
||||
private final MethodHandle[] setters;
|
||||
|
||||
private GeneratedEventClass(Class<? extends LuckPermsEvent> eventClass) throws ReflectiveOperationException {
|
||||
|
||||
// get a TypeDescription for the event class
|
||||
TypeDescription eventClassType = new TypeDescription.ForLoadedType(eventClass);
|
||||
|
||||
// determine a generated class name of the event
|
||||
String eventClassSuffix = eventClass.getName().substring(LuckPermsEvent.class.getPackage().getName().length());
|
||||
String generatedClassName = GeneratedEventClass.class.getPackage().getName() + eventClassSuffix;
|
||||
|
||||
DynamicType.Builder<AbstractEvent> builder = new ByteBuddy(ClassFileVersion.JAVA_V8)
|
||||
// create a subclass of AbstractEvent
|
||||
.subclass(AbstractEvent.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
|
||||
// using the predetermined generated class name
|
||||
.name(generatedClassName)
|
||||
// implement the event interface
|
||||
.implement(eventClassType)
|
||||
// implement all methods annotated with Param by simply returning the value from the corresponding field with the same name
|
||||
.method(isAnnotatedWith(Param.class))
|
||||
.intercept(FieldAccessor.of(NamedElement.WithRuntimeName::getInternalName))
|
||||
// implement LuckPermsEvent#getEventType by returning the event class type
|
||||
.method(named("getEventType").and(returns(Class.class)).and(takesArguments(0)))
|
||||
.intercept(FixedValue.value(eventClassType))
|
||||
// implement AbstractEvent#mh by calling & returning the value of MethodHandles.lookup()
|
||||
.method(named("mhl").and(returns(MethodHandles.Lookup.class)).and(takesArguments(0)))
|
||||
.intercept(MethodCall.invoke(METHOD_HANDLES_LOOKUP))
|
||||
// implement a toString method
|
||||
.withToString();
|
||||
|
||||
// get a sorted array of all methods on the event interface annotated with @Param
|
||||
Method[] properties = Arrays.stream(eventClass.getMethods())
|
||||
.filter(m -> m.isAnnotationPresent(Param.class))
|
||||
.sorted(Comparator.comparingInt(o -> o.getAnnotation(Param.class).value()))
|
||||
.toArray(Method[]::new);
|
||||
|
||||
// for each method on the event interface annotated with @Param
|
||||
for (Method method : properties) {
|
||||
if (!method.isAnnotationPresent(Param.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// define a field on the generated class to hold the value
|
||||
builder = builder.defineField(method.getName(), method.getReturnType(), Visibility.PRIVATE);
|
||||
}
|
||||
|
||||
// finish building, load the class, get a constructor
|
||||
Class<? extends AbstractEvent> generatedClass = builder.make().load(GeneratedEventClass.class.getClassLoader()).getLoaded();
|
||||
this.constructor = generatedClass.getDeclaredConstructor(LuckPerms.class);
|
||||
|
||||
// create a dummy instance of the generated class & get the method handle lookup instance
|
||||
MethodHandles.Lookup lookup = this.constructor.newInstance(new Object[]{null}).mhl();
|
||||
|
||||
// get 'setter' MethodHandles
|
||||
this.setters = new MethodHandle[properties.length];
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
Method method = properties[i];
|
||||
|
||||
// obtain a setter MethodHandle for the property
|
||||
this.setters[i] = lookup.findSetter(generatedClass, method.getName(), method.getReturnType())
|
||||
.asType(MethodType.methodType(void.class, new Class[]{AbstractEvent.class, Object.class}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the event class.
|
||||
*
|
||||
* @param api an instance of the LuckPerms API
|
||||
* @param properties the event properties
|
||||
* @return the event instance
|
||||
* @throws Throwable if something goes wrong
|
||||
*/
|
||||
public LuckPermsEvent newInstance(LuckPerms api, Object... properties) throws Throwable {
|
||||
if (properties.length != this.setters.length) {
|
||||
throw new IllegalStateException("Unexpected number of properties. given: " + properties.length + ", expected: " + this.setters.length);
|
||||
}
|
||||
|
||||
// create a new instance of the event
|
||||
final AbstractEvent event = this.constructor.newInstance(api);
|
||||
|
||||
// set the properties onto the event instance
|
||||
for (int i = 0; i < this.setters.length; i++) {
|
||||
MethodHandle setter = this.setters[i];
|
||||
Object value = properties[i];
|
||||
setter.invokeExact(event, value);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.event.gen;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.common.cache.LoadingMap;
|
||||
import me.lucko.luckperms.common.util.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.util.PrivateMethodHandles;
|
||||
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.event.LuckPermsEvent;
|
||||
import net.luckperms.api.event.util.Param;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents the generated specification for an instance of a given {@link LuckPermsEvent}.
|
||||
*/
|
||||
public class GeneratedEventSpec {
|
||||
|
||||
private static final Method TO_STRING_METHOD;
|
||||
private static final Method EQUALS_METHOD;
|
||||
private static final Method HASHCODE_METHOD;
|
||||
private static final Method GET_LUCKPERMS_METHOD;
|
||||
private static final Method GET_EVENT_TYPE_METHOD;
|
||||
static {
|
||||
try {
|
||||
TO_STRING_METHOD = Object.class.getMethod("toString");
|
||||
EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
|
||||
HASHCODE_METHOD = Object.class.getMethod("hashCode");
|
||||
GET_LUCKPERMS_METHOD = LuckPermsEvent.class.getMethod("getLuckPerms");
|
||||
GET_EVENT_TYPE_METHOD = LuckPermsEvent.class.getMethod("getEventType");
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Class<? extends LuckPermsEvent>, GeneratedEventSpec> CACHE = LoadingMap.of(GeneratedEventSpec::new);
|
||||
|
||||
public static GeneratedEventSpec lookup(Class<? extends LuckPermsEvent> event) {
|
||||
return CACHE.get(event);
|
||||
}
|
||||
|
||||
private final Class<? extends LuckPermsEvent> eventClass;
|
||||
private final List<Method> methods;
|
||||
private final List<Class<?>> returnTypes;
|
||||
|
||||
private GeneratedEventSpec(Class<? extends LuckPermsEvent> eventClass) {
|
||||
this.eventClass = eventClass;
|
||||
|
||||
List<Method> methods = new ArrayList<>();
|
||||
for (Method method : eventClass.getMethods()) {
|
||||
if (method.isDefault()) {
|
||||
continue;
|
||||
}
|
||||
if (GET_LUCKPERMS_METHOD.equals(method) || GET_EVENT_TYPE_METHOD.equals(method)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
methods.add(method);
|
||||
}
|
||||
methods.sort(Comparator.comparingInt(o -> o.isAnnotationPresent(Param.class) ? o.getAnnotation(Param.class).value() : 0));
|
||||
this.methods = ImmutableList.copyOf(methods);
|
||||
|
||||
this.returnTypes = this.methods.stream()
|
||||
.map(Method::getReturnType)
|
||||
.collect(ImmutableCollectors.toList());
|
||||
}
|
||||
|
||||
public LuckPermsEvent newInstance(LuckPerms api, Object... params) {
|
||||
if (params.length != this.methods.size()) {
|
||||
throw new IllegalStateException("param length differs from number of methods. expected " + this.methods.size() + " - " + this.methods);
|
||||
}
|
||||
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
Object param = params[i];
|
||||
Class<?> expectedType = this.returnTypes.get(i);
|
||||
if (!expectedType.isInstance(param)) {
|
||||
throw new IllegalArgumentException("Parameter at index " + i + " cannot be assigned to " + expectedType);
|
||||
}
|
||||
}
|
||||
|
||||
EventInvocationHandler eventInvocationHandler = new EventInvocationHandler(api, params);
|
||||
return (LuckPermsEvent) Proxy.newProxyInstance(GeneratedEventSpec.class.getClassLoader(), new Class[]{this.eventClass}, eventInvocationHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* An invocation handler bound to a set of parameters, used to implement the event as a proxy.
|
||||
*/
|
||||
private final class EventInvocationHandler implements InvocationHandler {
|
||||
private final LuckPerms api;
|
||||
private final Object[] fields;
|
||||
|
||||
EventInvocationHandler(LuckPerms api, Object[] fields) {
|
||||
this.api = api;
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (TO_STRING_METHOD.equals(method)) {
|
||||
return "GeneratedEvent(" +
|
||||
"proxy=" + proxy.getClass().getName() + "@" + Integer.toHexString(proxy.hashCode()) + ", " +
|
||||
"class=" + GeneratedEventSpec.this.eventClass.getName() + ", " +
|
||||
"fields=" + Arrays.toString(this.fields) + ")";
|
||||
}
|
||||
if (EQUALS_METHOD.equals(method)) {
|
||||
return proxy == args[0];
|
||||
}
|
||||
if (HASHCODE_METHOD.equals(method)) {
|
||||
return System.identityHashCode(proxy);
|
||||
}
|
||||
if (GET_LUCKPERMS_METHOD.equals(method)) {
|
||||
return this.api;
|
||||
}
|
||||
if (GET_EVENT_TYPE_METHOD.equals(method)) {
|
||||
return GeneratedEventSpec.this.eventClass;
|
||||
}
|
||||
|
||||
if (method.getDeclaringClass() == Object.class || method.isDefault()) {
|
||||
return PrivateMethodHandles.privateLookup(method.getDeclaringClass())
|
||||
.unreflectSpecial(method, method.getDeclaringClass())
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
}
|
||||
|
||||
int methodIndex = GeneratedEventSpec.this.methods.indexOf(method);
|
||||
if (methodIndex == -1) {
|
||||
throw new UnsupportedOperationException("Method not supported: " + method);
|
||||
}
|
||||
|
||||
return this.fields[methodIndex];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -250,6 +250,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||
Dependency.CAFFEINE,
|
||||
Dependency.OKIO,
|
||||
Dependency.OKHTTP,
|
||||
Dependency.BYTEBUDDY,
|
||||
Dependency.EVENT
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class PrivateMethodHandles {
|
||||
private PrivateMethodHandles() {}
|
||||
|
||||
private static final Constructor<MethodHandles.Lookup> LOOKUP_CONSTRUCTOR;
|
||||
static {
|
||||
try {
|
||||
LOOKUP_CONSTRUCTOR = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
|
||||
LOOKUP_CONSTRUCTOR.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
// MethodHandles.Lookup.PUBLIC | MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED | MethodHandles.Lookup.PACKAGE
|
||||
private static final int TRUSTED_FLAG = -1;
|
||||
|
||||
/**
|
||||
* Returns a {@link MethodHandles.Lookup lookup object} with full capabilities to emulate all
|
||||
* supported bytecode behaviors, including private access, on a target class.
|
||||
*
|
||||
* @param targetClass the target class
|
||||
* @return a lookup object for the target class, with private access
|
||||
*/
|
||||
public static MethodHandles.Lookup privateLookup(Class<?> targetClass) {
|
||||
try {
|
||||
return LOOKUP_CONSTRUCTOR.newInstance(targetClass, TRUSTED_FLAG);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@ shadowJar {
|
|||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
|
|
|
@ -46,6 +46,7 @@ shadowJar {
|
|||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
|
|
|
@ -32,6 +32,7 @@ shadowJar {
|
|||
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
|
||||
relocate 'okio', 'me.lucko.luckperms.lib.okio'
|
||||
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
|
||||
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
|
||||
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
|
||||
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
|
||||
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
|
||||
|
|
Loading…
Reference in New Issue
Block a user