-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added @ModuleInstance annotation. Annotate a static field inside your…
… module class to have it populated with its instance, allowing for easy singleton patterns. This is opt in
- Loading branch information
1 parent
832410e
commit 1b5a03c
Showing
4 changed files
with
237 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
src/main/java/org/violetmoon/zeta/event/bus/wip/ForgeZetaBus.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package org.violetmoon.zeta.event.bus.wip; | ||
|
||
import net.minecraftforge.common.MinecraftForge; | ||
import net.minecraftforge.eventbus.api.Event; | ||
import net.minecraftforge.eventbus.api.IEventBus; | ||
import org.apache.logging.log4j.Logger; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
import org.violetmoon.zeta.Zeta; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.reflect.Method; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.function.Consumer; | ||
import java.util.function.Function; | ||
|
||
public class ForgeZetaBus<E> extends ZetaBus<E> { | ||
|
||
private final Map<Class<? extends E>, Function<? extends Event, ? extends E>> forgeToZetaMap = new HashMap<>(); | ||
private final Map<Class<? extends Event>, Function<? extends E, ? extends Event>> zetaToForgeMap = new HashMap<>(); | ||
//ForgeZAddReloadListener.class, (Function<AddReloadListenerEvent, IZetaLoadEvent>) ForgeZAddReloadListener::new | ||
|
||
private final IEventBus forgeBus; | ||
|
||
/** | ||
* @param subscriberAnnotation The annotation that subscribe()/unsubscribe() will pay attention to. | ||
* @param eventRoot The superinterface of all events fired on this bus. | ||
*/ | ||
public ForgeZetaBus(Zeta z, Class<? extends Annotation> subscriberAnnotation, Class<E> eventRoot, @Nullable Logger logSpam) { | ||
super(z, subscriberAnnotation, eventRoot, logSpam); | ||
this.forgeBus = MinecraftForge.EVENT_BUS; | ||
} | ||
|
||
public void registerEventMappings(Class<? extends E> zetaEvent, | ||
Function<? extends Event, ? extends E> forgeToZeta, | ||
Class<? extends Event> forgeEvent, | ||
Function<? extends E, ? extends Event> zetaToForge) { | ||
forgeToZetaMap.put(zetaEvent, forgeToZeta); | ||
zetaToForgeMap.put(forgeEvent, zetaToForge); | ||
} | ||
|
||
// takes a method that takes a zeta event and turns into one that takes a forge event | ||
private Consumer<? extends Event> remapMethod(MethodHandle zetaEventConsumer, Class<? extends E> zetaEventClass) { | ||
Function<? extends Event, ? extends E> forgeToZetaFunc = forgeToZetaMap.get(zetaEventClass); | ||
return createForgeConsumer(zetaEventConsumer, forgeToZetaFunc); | ||
} | ||
|
||
private <Z extends E, F extends Event> Consumer<F> createForgeConsumer(MethodHandle zetaEventConsumer, Function<F, Z> forgeToZetaFunc) { | ||
return event -> { | ||
try { | ||
zetaEventConsumer.invoke(forgeToZetaFunc.apply(event)); | ||
} catch (Throwable e) { | ||
throw new RuntimeException(e); | ||
} | ||
}; | ||
} | ||
|
||
@Override | ||
protected void addListener(Method method, Object receiver, Class<?> owningClazz) { | ||
if (method.getParameterCount() != 1) | ||
throw arityERR(method); | ||
|
||
Class<?> eventType = method.getParameterTypes()[0]; | ||
if (!eventRoot.isAssignableFrom(eventType)) | ||
throw typeERR(method); | ||
|
||
MethodHandle handle; | ||
try { | ||
handle = MethodHandles.publicLookup().unreflect(method); | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
|
||
//fill in the "this" parameter | ||
if (receiver != null) | ||
handle = handle.bindTo(receiver); | ||
|
||
forgeBus.addListener(remapMethod(handle, (Class<? extends E>) eventType)); | ||
} | ||
|
||
@Override | ||
protected void removeListener(Method m, Object receiver, Class<?> owningClazz) { | ||
|
||
} | ||
|
||
|
||
@Override | ||
public <T extends E> T fire(@NotNull T event) { | ||
forgeBus.post(remapEvent(event)); | ||
return event; | ||
} | ||
|
||
private <T extends E> Event remapEvent(@NotNull T event) { | ||
Function<? extends E, ? extends Event> zetaToForgeFunc = zetaToForgeMap.get(event.getClass()); | ||
return createForgeEvent(event, zetaToForgeFunc); | ||
} | ||
|
||
private <T extends E> Event createForgeEvent(@NotNull E event, Function<T, ? extends Event> function) { | ||
return function.apply((T) event); | ||
} | ||
|
||
@Override | ||
public <T extends E> T fire(@NotNull T event, Class<? extends T> firedAs) { | ||
return null; | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
src/main/java/org/violetmoon/zeta/event/bus/wip/ZetaBus.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package org.violetmoon.zeta.event.bus.wip; | ||
|
||
import com.google.common.base.Preconditions; | ||
import org.apache.logging.log4j.Logger; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
import org.violetmoon.zeta.Zeta; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Method; | ||
import java.lang.reflect.Modifier; | ||
import java.util.Arrays; | ||
import java.util.stream.Stream; | ||
|
||
public abstract class ZetaBus<E> { | ||
|
||
protected final Class<? extends Annotation> subscriberAnnotation; | ||
protected final Class<E> eventRoot; | ||
protected final Zeta z; | ||
protected final @Nullable Logger logSpam; | ||
|
||
/** | ||
* @param subscriberAnnotation The annotation that subscribe()/unsubscribe() will pay attention to. | ||
* @param eventRoot The superinterface of all events fired on this bus. | ||
*/ | ||
public ZetaBus(Zeta z, Class<? extends Annotation> subscriberAnnotation, Class<E> eventRoot, @Nullable Logger logSpam) { | ||
Preconditions.checkArgument(eventRoot.isInterface(), "Event roots should be an interface"); | ||
|
||
this.z = z; | ||
this.subscriberAnnotation = subscriberAnnotation; | ||
this.eventRoot = eventRoot; | ||
this.logSpam = logSpam; | ||
} | ||
|
||
/** | ||
* If the parameter is a Class: subscribes all static methods from it (and its superclasses) to the event bus. | ||
* Otherwise, subscribes all non-static methods on that object (and its superclasses) to the event bus. | ||
* (Note that the event bus will hold a reference to this object.) | ||
*/ | ||
public ZetaBus<E> subscribe(@NotNull Object target) { | ||
Preconditions.checkNotNull(target, "null passed to subscribe"); | ||
|
||
Object receiver; | ||
Class<?> owningClazz; | ||
if (target instanceof Class<?> clazz) { | ||
receiver = null; | ||
owningClazz = clazz; | ||
} else { | ||
receiver = target; | ||
owningClazz = target.getClass(); | ||
} | ||
|
||
streamAnnotatedMethods(owningClazz, receiver == null) | ||
.forEach(m -> addListener(m, receiver, owningClazz)); | ||
return this; | ||
} | ||
|
||
protected abstract void addListener(Method m, Object receiver, Class<?> owningClazz); | ||
|
||
/** | ||
* If the parameter is a Class: unsubscribes all static methods from it (and its superclasses) from the event bus. | ||
* Otherwise, unsubscribes all non-static methods on that object (and its superclasses) from the event bus. | ||
*/ | ||
public ZetaBus<E> unsubscribe(@NotNull Object target) { | ||
Preconditions.checkNotNull(target, "null passed to unsubscribe"); | ||
|
||
Object receiver; | ||
Class<?> owningClazz; | ||
if (target instanceof Class<?> clazz) { | ||
receiver = null; | ||
owningClazz = clazz; | ||
} else { | ||
receiver = target; | ||
owningClazz = target.getClass(); | ||
} | ||
|
||
streamAnnotatedMethods(owningClazz, receiver == null) | ||
.forEach(m -> removeListener(m, receiver, owningClazz)); | ||
return this; | ||
} | ||
|
||
protected abstract void removeListener(Method m, Object receiver, Class<?> owningClazz); | ||
|
||
/** | ||
* Fires an event on the event bus. Each subscriber will be visited in order. | ||
*/ | ||
public abstract <T extends E> T fire(@NotNull T event); | ||
|
||
/** | ||
* Fires an event on the event bus. Each subscriber will be visited in order. | ||
* Listeners for "firedAs" will be invoked, instead of listeners for the event's own class. | ||
* <p> | ||
* (The generic should be Class<? super T & ? extends E>, but unfortunately, javac.) | ||
*/ | ||
public abstract <T extends E> T fire(@NotNull T event, Class<? extends T> firedAs); | ||
|
||
/** | ||
* Grabs methods from this class (and its superclasses, recursively) that are annotated with this bus's | ||
* annotation; and of the requested staticness. | ||
*/ | ||
private Stream<Method> streamAnnotatedMethods(Class<?> owningClazz, boolean wantStatic) { | ||
return Arrays.stream(owningClazz.getMethods()) | ||
.filter(m -> m.isAnnotationPresent(subscriberAnnotation) && ((m.getModifiers() & Modifier.STATIC) != 0) == wantStatic); | ||
} | ||
|
||
protected RuntimeException arityERR(Method method) { | ||
return methodProblem("Method annotated with @" + subscriberAnnotation.getSimpleName() + | ||
" should take 1 parameter.", method, null); | ||
} | ||
|
||
protected RuntimeException typeERR(Method method) { | ||
return methodProblem("Method annotated with @" + subscriberAnnotation.getSimpleName() + | ||
" should take an implementor of " + eventRoot.getSimpleName() + ".", method, null); | ||
} | ||
|
||
protected RuntimeException unreflectERR(Method method, Throwable cause) { | ||
return methodProblem("Exception unreflecting a @" + subscriberAnnotation.getSimpleName() + | ||
" method, is it public?", method, cause); | ||
} | ||
|
||
protected static RuntimeException methodProblem(String problem, Method method, @Nullable Throwable cause) { | ||
return new RuntimeException("%s%nMethod class: %s%nMethod name: %s".formatted( | ||
problem, method.getDeclaringClass().getName(), method.getName()), cause); | ||
} | ||
} |
42 changes: 0 additions & 42 deletions
42
src/main/java/org/violetmoon/zetaimplforge/event/load/Test.java
This file was deleted.
Oops, something went wrong.