implement Event API

This commit is contained in:
dfsek
2021-02-15 19:56:55 -07:00
parent 4131b45c6f
commit 7cfa96f925
8 changed files with 253 additions and 2 deletions

View File

@@ -0,0 +1,53 @@
package com.dfsek.terra.api.core.event;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.util.ReflectionUtil;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TerraEventManager implements EventManager {
private final Map<Class<? extends Event>, Map<EventListener, List<Method>>> listeners = new HashMap<>();
private final TerraPlugin main;
public TerraEventManager(TerraPlugin main) {
this.main = main;
}
@Override
public void callEvent(Event event) {
if(!listeners.containsKey(event.getClass())) return;
listeners.get(event.getClass()).forEach((eventListener, methods) -> methods.forEach(method -> {
try {
method.invoke(eventListener, event);
} catch(Exception e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
main.getLogger().warning("Exception occurred during event handling:");
main.getLogger().warning(writer.toString());
main.getLogger().warning("Report this to the maintainers of " + eventListener.getClass().getCanonicalName());
}
}));
}
@SuppressWarnings("unchecked")
@Override
public void registerListener(EventListener listener) {
Class<? extends EventListener> listenerClass = listener.getClass();
Method[] methods = ReflectionUtil.getMethods(listenerClass);
for(Method method : methods) {
if(method.getParameterCount() != 1) continue; // Check that parameter count is only 1.
Class<?> eventParam = method.getParameterTypes()[0];
if(!Event.class.isAssignableFrom(eventParam)) continue; // Check that parameter is an Event.
method.setAccessible(true);
listeners.computeIfAbsent((Class<? extends Event>) eventParam, e -> new HashMap<>()).computeIfAbsent(listener, l -> new ArrayList<>()).add(method);
}
}
}

View File

@@ -0,0 +1,5 @@
package com.dfsek.terra.api.core.event.annotations;
public @interface Listener {
int priority() default 0;
}

View File

@@ -28,6 +28,7 @@ import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.structures.structure.buffer.Buffer;
import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer;
import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer;
import com.dfsek.terra.registry.FunctionRegistry;
import com.dfsek.terra.registry.config.LootRegistry;
import com.dfsek.terra.registry.config.ScriptRegistry;
import com.dfsek.terra.world.generation.math.SamplerCache;
@@ -48,7 +49,7 @@ public class StructureScript {
private final TerraPlugin main;
String tempID;
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException {
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache, FunctionRegistry functionRegistry) throws ParseException {
Parser parser;
try {
parser = new Parser(IOUtils.toString(inputStream));
@@ -85,6 +86,8 @@ public class StructureScript {
.registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue())))
.registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue())));
functionRegistry.forEach(parser::registerFunction); // Register registry functions.
block = parser.parse();
this.id = parser.getID();
tempID = id;

View File

@@ -0,0 +1,28 @@
package com.dfsek.terra.api.util;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Stream;
public class ReflectionUtil {
public static Field[] getFields(@NotNull Class<?> type) {
Field[] result = type.getDeclaredFields();
Class<?> parentClass = type.getSuperclass();
if(parentClass != null) {
result = Stream.concat(Arrays.stream(result), Arrays.stream(getFields(parentClass))).toArray(Field[]::new);
}
return result;
}
public static Method[] getMethods(@NotNull Class<?> type) {
Method[] result = type.getDeclaredMethods();
Class<?> parentClass = type.getSuperclass();
if(parentClass != null) {
result = Stream.concat(Arrays.stream(result), Arrays.stream(getMethods(parentClass))).toArray(Method[]::new);
}
return result;
}
}

View File

@@ -44,6 +44,7 @@ import com.dfsek.terra.config.templates.OreTemplate;
import com.dfsek.terra.config.templates.PaletteTemplate;
import com.dfsek.terra.config.templates.StructureTemplate;
import com.dfsek.terra.config.templates.TreeTemplate;
import com.dfsek.terra.registry.FunctionRegistry;
import com.dfsek.terra.registry.TerraRegistry;
import com.dfsek.terra.registry.config.BiomeRegistry;
import com.dfsek.terra.registry.config.CarverRegistry;
@@ -95,6 +96,7 @@ public class ConfigPack implements LoaderRegistrar {
private final CarverRegistry carverRegistry = new CarverRegistry();
private final NormalizerRegistry normalizerRegistry = new NormalizerRegistry();
private final FunctionRegistry functionRegistry = new FunctionRegistry();
private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader();
private final ConfigLoader selfLoader = new ConfigLoader();
@@ -201,7 +203,7 @@ public class ConfigPack implements LoaderRegistrar {
loader.open("structures/data", ".tesf").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) {
try {
StructureScript structureScript = new StructureScript(entry.getValue(), main, scriptRegistry, lootRegistry, samplerCache);
StructureScript structureScript = new StructureScript(entry.getValue(), main, scriptRegistry, lootRegistry, samplerCache, functionRegistry);
scriptRegistry.add(structureScript.getId(), structureScript);
} catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException e) {
throw new LoadException("Unable to load script \"" + entry.getKey() + "\"", e);
@@ -300,4 +302,8 @@ public class ConfigPack implements LoaderRegistrar {
public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() {
return biomeProviderBuilder;
}
public FunctionRegistry getFunctionRegistry() {
return functionRegistry;
}
}

View File

@@ -0,0 +1,6 @@
package com.dfsek.terra.registry;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
public class FunctionRegistry extends TerraRegistry<FunctionBuilder<?>> {
}

View File

@@ -9,6 +9,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public abstract class TerraRegistry<T> implements TypeLoader<T> {
@@ -59,6 +60,10 @@ public abstract class TerraRegistry<T> implements TypeLoader<T> {
objects.forEach((id, obj) -> consumer.accept(obj));
}
public void forEach(BiConsumer<String, T> consumer) {
objects.forEach(consumer);
}
public Set<T> entries() {
return new HashSet<>(objects.values());
}