Use lambda metadata factory for events

stonks
This commit is contained in:
RednedEpic 2022-01-16 22:52:27 -06:00
parent ac134b84f2
commit 5abf989139
7 changed files with 146 additions and 44 deletions

View File

@ -28,8 +28,6 @@ package org.geysermc.geyser.api.event;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.extension.Extension;
import java.util.function.Consumer;
/** /**
* Represents a subscribed listener to a {@link Event}. Wraps around * Represents a subscribed listener to a {@link Event}. Wraps around
* the event and is capable of unsubscribing from the event or give * the event and is capable of unsubscribing from the event or give
@ -47,15 +45,6 @@ public interface EventSubscription<T extends Event> {
@NonNull @NonNull
Class<T> eventClass(); Class<T> eventClass();
/**
* Gets the consumer responsible for handling
* this event.
*
* @return the consumer responsible for this event
*/
@NonNull
Consumer<? super T> eventConsumer();
/** /**
* Gets the {@link Extension} that owns this * Gets the {@link Extension} that owns this
* event subscription. * event subscription.

View File

@ -30,24 +30,20 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import net.kyori.event.EventSubscriber; import net.kyori.event.EventSubscriber;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.event.Event; import org.geysermc.geyser.api.event.Event;
import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.event.EventBus;
import org.geysermc.geyser.api.event.EventSubscription; import org.geysermc.geyser.api.event.EventSubscription;
import org.geysermc.geyser.api.event.Subscribe; import org.geysermc.geyser.api.event.Subscribe;
import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.extension.Extension;
import java.util.function.Consumer;
@Getter @Getter
@Accessors(fluent = true) @Accessors(fluent = true)
@RequiredArgsConstructor @RequiredArgsConstructor
public class GeyserEventSubscription<T extends Event> implements EventSubscription<T>, EventSubscriber<T> { public abstract class AbstractEventSubscription<T extends Event> implements EventSubscription<T>, EventSubscriber<T> {
private final EventBus eventBus; protected final EventBus eventBus;
private final Class<T> eventClass; protected final Class<T> eventClass;
private final Consumer<? super T> eventConsumer; protected final Extension owner;
private final Extension owner; protected final Subscribe.PostOrder order;
private final Subscribe.PostOrder order;
@Getter(AccessLevel.NONE) private boolean active; @Getter(AccessLevel.NONE) private boolean active;
@Override @Override
@ -65,16 +61,6 @@ public class GeyserEventSubscription<T extends Event> implements EventSubscripti
this.eventBus.unsubscribe(this); this.eventBus.unsubscribe(this);
} }
@Override
public void invoke(@NonNull T event) throws Throwable {
try {
this.eventConsumer.accept(event);
} catch (Throwable ex) {
this.owner.logger().warning("Unable to fire event " + event.getClass().getSimpleName() + " with subscription " + this.eventConsumer.getClass().getSimpleName());
ex.printStackTrace();
}
}
@Override @Override
public int postOrder() { public int postOrder() {
return this.order.postOrder(); return this.order.postOrder();

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.event;
import lombok.Getter;
import lombok.experimental.Accessors;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.event.Event;
import org.geysermc.geyser.api.event.EventBus;
import org.geysermc.geyser.api.event.Subscribe;
import org.geysermc.geyser.api.extension.Extension;
import java.util.function.Consumer;
@Getter
@Accessors(fluent = true)
public class BaseEventSubscription<T extends Event> extends AbstractEventSubscription<T> {
private final Consumer<? super T> eventConsumer;
public BaseEventSubscription(EventBus eventBus, Class<T> eventClass, Extension owner, Subscribe.PostOrder order, Consumer<? super T> eventConsumer) {
super(eventBus, eventClass, owner, order);
this.eventConsumer = eventConsumer;
}
@Override
public void invoke(@NonNull T event) throws Throwable {
try {
this.eventConsumer.accept(event);
} catch (Throwable ex) {
this.owner.logger().warning("Unable to fire event " + event.getClass().getSimpleName() + " with subscription " + this.eventConsumer.getClass().getSimpleName());
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.event;
import lombok.Getter;
import lombok.experimental.Accessors;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.event.Event;
import org.geysermc.geyser.api.event.EventBus;
import org.geysermc.geyser.api.event.Subscribe;
import org.geysermc.geyser.api.extension.Extension;
import java.util.function.BiConsumer;
@Getter
@Accessors(fluent = true)
public class GeneratedEventSubscription<T extends Event> extends AbstractEventSubscription<T> {
private final Object eventHolder;
private final BiConsumer<Object, ? super T> eventConsumer;
public GeneratedEventSubscription(EventBus eventBus, Class<T> eventClass, Extension owner, Subscribe.PostOrder order, Object eventHolder, BiConsumer<Object, ? super T> eventConsumer) {
super(eventBus, eventClass, owner, order);
this.eventHolder = eventHolder;
this.eventConsumer = eventConsumer;
}
@Override
public void invoke(@NonNull T event) throws Throwable {
try {
this.eventConsumer.accept(this.eventHolder, event);
} catch (Throwable ex) {
this.owner.logger().warning("Unable to fire event " + event.getClass().getSimpleName() + " with subscription " + this.eventConsumer.getClass().getSimpleName());
ex.printStackTrace();
}
}
}

View File

@ -33,15 +33,19 @@ import org.geysermc.geyser.api.event.EventBus;
import org.geysermc.geyser.api.event.EventSubscription; import org.geysermc.geyser.api.event.EventSubscription;
import org.geysermc.geyser.api.event.Subscribe; import org.geysermc.geyser.api.event.Subscribe;
import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.extension.Extension;
import org.lanternpowered.lmbda.LambdaFactory;
import java.lang.reflect.InvocationTargetException; import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class GeyserEventBus implements EventBus { public class GeyserEventBus implements EventBus {
private static final MethodHandles.Lookup CALLER = MethodHandles.lookup();
private final SimpleEventBus<Event> bus = new SimpleEventBus<>(Event.class); private final SimpleEventBus<Event> bus = new SimpleEventBus<>(Event.class);
@NonNull @NonNull
@ -52,7 +56,7 @@ public class GeyserEventBus implements EventBus {
@Override @Override
public <T extends Event> void unsubscribe(@NonNull EventSubscription<T> subscription) { public <T extends Event> void unsubscribe(@NonNull EventSubscription<T> subscription) {
this.bus.unregister((GeyserEventSubscription<T>) subscription); this.bus.unregister((AbstractEventSubscription<T>) subscription);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -72,19 +76,19 @@ public class GeyserEventBus implements EventBus {
} }
Subscribe subscribe = method.getAnnotation(Subscribe.class); Subscribe subscribe = method.getAnnotation(Subscribe.class);
this.subscribe((Class<? extends Event>) method.getParameters()[0].getType(), (event) -> {
try { try {
method.invoke(eventHolder, event); Class<? extends Event> type = (Class<? extends Event>) method.getParameters()[0].getType();
} catch (IllegalAccessException | InvocationTargetException ex) { this.subscribe(type, eventHolder, LambdaFactory.createBiConsumer(CALLER.unreflect(method)), extension, subscribe.postOrder());
ex.printStackTrace(); } catch (IllegalAccessException ex) {
} ex.printStackTrace();
}, extension, subscribe.postOrder()); }
} }
} }
@Override @Override
public void unregisterAll(@NonNull Extension extension) { public void unregisterAll(@NonNull Extension extension) {
this.bus.unregister((Predicate<EventSubscriber<?>>) subscriber -> extension.equals(((GeyserEventSubscription<?>) subscriber).owner())); this.bus.unregister((Predicate<EventSubscriber<?>>) subscriber -> extension.equals(((AbstractEventSubscription<?>) subscriber).owner()));
} }
@Override @Override
@ -104,7 +108,13 @@ public class GeyserEventBus implements EventBus {
} }
private <T extends Event> EventSubscription<T> subscribe(Class<T> eventClass, Consumer<? super T> handler, Extension extension, Subscribe.PostOrder postOrder) { private <T extends Event> EventSubscription<T> subscribe(Class<T> eventClass, Consumer<? super T> handler, Extension extension, Subscribe.PostOrder postOrder) {
GeyserEventSubscription<T> eventSubscription = new GeyserEventSubscription<>(this, eventClass, handler, extension, postOrder); BaseEventSubscription<T> eventSubscription = new BaseEventSubscription<>(this, eventClass, extension, postOrder, handler);
this.bus.register(eventClass, eventSubscription);
return eventSubscription;
}
private <T extends Event> EventSubscription<T> subscribe(Class<T> eventClass, Object eventHolder, BiConsumer<Object, ? super T> handler, Extension extension, Subscribe.PostOrder postOrder) {
GeneratedEventSubscription<T> eventSubscription = new GeneratedEventSubscription<>(this, eventClass, extension, postOrder, eventHolder, handler);
this.bus.register(eventClass, eventSubscription); this.bus.register(eventClass, eventSubscription);
return eventSubscription; return eventSubscription;
} }

View File

@ -35,7 +35,6 @@ import java.net.URLClassLoader;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class GeyserExtensionClassLoader extends URLClassLoader { public class GeyserExtensionClassLoader extends URLClassLoader {
private final GeyserExtensionLoader loader; private final GeyserExtensionLoader loader;

View File

@ -110,14 +110,14 @@ public class GeyserExtensionLoader extends ExtensionLoader {
public Class<?> classByName(final String name) throws ClassNotFoundException{ public Class<?> classByName(final String name) throws ClassNotFoundException{
Class<?> clazz = this.classes.get(name); Class<?> clazz = this.classes.get(name);
try { try {
for(GeyserExtensionClassLoader loader : this.classLoaders.values()) { for (GeyserExtensionClassLoader loader : this.classLoaders.values()) {
try { try {
clazz = loader.findClass(name,false); clazz = loader.findClass(name,false);
} catch(NullPointerException ignored) { } catch(NullPointerException ignored) {
} }
} }
return clazz; return clazz;
} catch(NullPointerException s) { } catch (NullPointerException s) {
return null; return null;
} }
} }