Skip to content

Instantly share code, notes, and snippets.

@Unh0lyTigg
Created February 4, 2015 05:12
Show Gist options
  • Save Unh0lyTigg/90fd761ba709b24b27e5 to your computer and use it in GitHub Desktop.
Save Unh0lyTigg/90fd761ba709b24b27e5 to your computer and use it in GitHub Desktop.
package org.unh0lytigg.core.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface ASContainer {
public AutoSubscribe[] value();
}
package org.unh0lytigg.core.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(ASContainer.class)
public @interface AutoSubscribe {
public Bus busToAttach() default Bus.AUTO;
public String customBusName() default "";
public AttachPhase phase() default AttachPhase.POST_INIT;
public int numAutoAttach() default 1;
public static enum Bus {
AUTO,
FML,
FORGE,
TERRAIN_GEN,
ORE_GEN,
CUSTOM;
}
public static enum AttachPhase {
PRE_INIT,
INIT,
POST_INIT;
}
}
package org.unh0lytigg.core.background;
import static org.unh0lytigg.core.TiggCore.LOGGER;
import static org.unh0lytigg.core.asm.ASMInfo.table;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.unh0lytigg.core.EventBusAccess;
import org.unh0lytigg.core.annotations.AutoSubscribe;
import org.unh0lytigg.core.annotations.AutoSubscribe.AttachPhase;
import org.unh0lytigg.core.annotations.AutoSubscribe.Bus;
import org.unh0lytigg.core.events.EventBusMap;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class AutoSubscribeWorker {
private static Set<ASMData> data;
public static void prePhase() {
data = Sets.newHashSet();
data.addAll(table.getAll("org.unh0lytigg.core.annotations.AutoSubscribe"));
data.addAll(table.getAll("org.unh0lytigg.core.annotations.ASContainer"));
data = data.stream().filter(d -> { return d.getObjectName() != null; }).collect(Collectors.toSet());
try {
doWork(AttachPhase.PRE_INIT);
} catch (Exception e) {
Throwables.propagate(e);
}
}
public static void initPhase() {
try {
doWork(AttachPhase.INIT);
} catch (Exception e) {
Throwables.propagate(e);
}
}
public static void postPhase() {
try {
doWork(AttachPhase.POST_INIT);
} catch (Exception e) {
Throwables.propagate(e);
}
}
private static void doWork(AttachPhase phase) throws Exception {
for (ASMData d : data) {
if (d.getObjectName() == null) {
continue;
}
Class<?> c = Class.forName(d.getClassName());
Field f = c.getDeclaredField(d.getObjectName());
if ((f.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
continue;
f.setAccessible(true);
Object value = f.get(null);
AutoSubscribe[] infos = f.getAnnotationsByType(AutoSubscribe.class);
infoloop:
for (AutoSubscribe info : infos) {
if (info.phase() != phase)
continue;
Bus b = info.busToAttach();
EventBus bus = null;
switch(b) {
case FML:
bus = EventBusAccess.fml();
break;
case FORGE:
bus = EventBusAccess.forge();
break;
case TERRAIN_GEN:
bus = EventBusAccess.terrain();
break;
case ORE_GEN:
bus = EventBusAccess.ore();
break;
case CUSTOM:
bus = EventBusAccess.custom(info.customBusName());
break;
case AUTO:
autoRegister(value, info, c);
break infoloop;
default:
break;
}
if (bus != null)
bus.register(value);
}
}
}
@SuppressWarnings("unchecked")
private static void autoRegister(Object value, AutoSubscribe info, Class<?> clazz) {
List<EventBus> busses = Lists.newArrayList();
for (Method m : clazz.getDeclaredMethods()) {
if (m.isAnnotationPresent(SubscribeEvent.class)) {
if (m.getParameterTypes().length == 1 && (Event.class.isAssignableFrom(m.getParameterTypes()[0]))) {
Class<? extends Event> c = (Class<? extends Event>) m.getParameterTypes()[0]; // Should be safe, check is being done in if statement
EventBus b = EventBusMap.getBus(c);
if (b != null && !busses.contains(b))
busses.add(b);
}
}
}
if (busses.size() != info.numAutoAttach())
LOGGER.warn("AutoSubscribeWorker.autoRegister: expected " + info.numAutoAttach() + " busses for " + clazz.getTypeName() + ", got " + busses.size());
for (EventBus b : busses)
b.register(value);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment