forked from SteamWar/SteamWar
Allow @Linked on fields
The value of a @Linked field of a linked class is linked like a linked class itself, e.g. registered as listener, and unlinked again on unlink. The field has to be initialised when linking. HullHiderCommand and TPSSystem use it instead of registering their listeners by hand.
This commit is contained in:
+1
-1
@@ -57,10 +57,10 @@ public class HullHiderCommand extends SWCommand implements Listener {
|
||||
public HullHiderCommand() {
|
||||
super("hullhider");
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(hullHider, BauSystem.getInstance());
|
||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), this::onTick, 1, 1);
|
||||
}
|
||||
|
||||
@Linked
|
||||
private final HullHider<Region> hullHider = new HullHider<>();
|
||||
// Read on netty threads by the BauTechHider
|
||||
private final Map<Region, HiddenHull> hulls = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -50,6 +50,9 @@ import java.util.Arrays;
|
||||
@Linked
|
||||
public class TPSSystem implements Listener {
|
||||
|
||||
@Linked
|
||||
private final TickManager tickManager = TickManager.impl;
|
||||
|
||||
public TPSSystem() {
|
||||
if (TickManager.impl.canFreeze()) {
|
||||
new TPSFreezeCommand();
|
||||
@@ -68,7 +71,6 @@ public class TPSSystem implements Listener {
|
||||
new TickDefaultCommand();
|
||||
new TPSBaseCommand();
|
||||
new TickBaseCommand();
|
||||
Bukkit.getPluginManager().registerEvents(TickManager.impl, BauSystem.getInstance());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -38,6 +39,7 @@ public abstract class AbstractLinker<T> {
|
||||
|
||||
protected final T plugin;
|
||||
private Map<Class<?>, Object> instances = new HashMap<>();
|
||||
private final List<Object> fieldInstances = new ArrayList<>();
|
||||
|
||||
protected AbstractLinker(@NonNull T plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -90,6 +92,7 @@ public abstract class AbstractLinker<T> {
|
||||
((Enable) any).enable();
|
||||
}
|
||||
linkObject(any);
|
||||
linkFields(any);
|
||||
});
|
||||
} catch (SecurityException e) {
|
||||
Throwable cause = e.getCause();
|
||||
@@ -119,6 +122,31 @@ public abstract class AbstractLinker<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private void linkFields(Object any) {
|
||||
for (Field field : any.getClass().getDeclaredFields()) {
|
||||
if (field.getAnnotation(Linked.class) == null) continue;
|
||||
|
||||
Object value;
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
value = field.get(Modifier.isStatic(field.getModifiers()) ? null : any);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SecurityException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
String message = "Linked field " + any.getClass().getName() + "." + field.getName() + " is not initialised";
|
||||
throw new SecurityException(message, new IllegalStateException(message));
|
||||
}
|
||||
|
||||
fieldInstances.add(value);
|
||||
if (value instanceof Enable) {
|
||||
((Enable) value).enable();
|
||||
}
|
||||
linkObject(value);
|
||||
}
|
||||
}
|
||||
|
||||
public final void unlink() {
|
||||
instances.forEach((aClass, any) -> {
|
||||
unlinkObject(any);
|
||||
@@ -126,6 +154,12 @@ public abstract class AbstractLinker<T> {
|
||||
((Disable) any).disable();
|
||||
}
|
||||
});
|
||||
fieldInstances.forEach(any -> {
|
||||
unlinkObject(any);
|
||||
if (any instanceof Disable) {
|
||||
((Disable) any).disable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public final void addLinkableInstance(@NonNull Object instance) {
|
||||
|
||||
@@ -26,8 +26,12 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* On a class: the class is instantiated and linked.
|
||||
* On a field of a linked class: the (already initialised) value of the field is linked as well, e.g. registered as listener.
|
||||
*/
|
||||
@IndexAnnotated
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
public @interface Linked {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user