From 5e98afe66a39c92b2acd353cf40394d653b5e5f6 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 21 Mar 2019 00:46:54 +0100 Subject: [PATCH] Created event framework It uses a similar system to Bukkit's Hopefully it works --- VirtualComputer/dependency-reduced-pom.xml | 6 ++ .../java/sznp/virtualcomputer/Commands.java | 1 - .../{events => }/Computer.java | 16 +++--- .../MouseLockerPlayerListener.java | 10 ++-- .../java/sznp/virtualcomputer/PluginMain.java | 5 +- .../events/EventHandlerBase.java | 56 +++++++++++++++++++ .../events/MachineEventHandler.java | 42 +++++++------- .../events/VBoxEventHandler.java | 27 ++++----- .../java/sznp/virtualcomputer/util/Utils.java | 23 +++++++- 9 files changed, 137 insertions(+), 49 deletions(-) rename VirtualComputer/src/main/java/sznp/virtualcomputer/{events => }/Computer.java (94%) create mode 100644 VirtualComputer/src/main/java/sznp/virtualcomputer/events/EventHandlerBase.java diff --git a/VirtualComputer/dependency-reduced-pom.xml b/VirtualComputer/dependency-reduced-pom.xml index 715dcf2..77d2b69 100644 --- a/VirtualComputer/dependency-reduced-pom.xml +++ b/VirtualComputer/dependency-reduced-pom.xml @@ -75,6 +75,12 @@ + + org.bukkit + craftbukkit + 1.12.2-R0.1-SNAPSHOT + provided + diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java index 744036d..0fcba5d 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java @@ -5,7 +5,6 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import sznp.virtualcomputer.events.Computer; public class Commands implements CommandExecutor { diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/Computer.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java similarity index 94% rename from VirtualComputer/src/main/java/sznp/virtualcomputer/events/Computer.java rename to VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java index 8e57b4a..394cf33 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/Computer.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java @@ -1,4 +1,4 @@ -package sznp.virtualcomputer.events; +package sznp.virtualcomputer; import com.google.common.collect.Lists; import lombok.Getter; @@ -7,10 +7,10 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.virtualbox_6_0.*; -import sznp.virtualcomputer.PluginMain; +import sznp.virtualcomputer.events.MachineEventHandler; +import sznp.virtualcomputer.events.VBoxEventHandler; import sznp.virtualcomputer.renderer.MCFrameBuffer; import sznp.virtualcomputer.util.Scancode; -import sznp.virtualcomputer.util.Utils; import javax.annotation.Nullable; import java.util.Arrays; @@ -25,10 +25,12 @@ public final class Computer { private IMachine machine; @java.beans.ConstructorProperties({"plugin"}) - public Computer(PluginMain plugin) { + public Computer(PluginMain plugin, ISession session, IVirtualBox vbox) { this.plugin = plugin; + this.session = session; + this.vbox = vbox; if(instance!=null) throw new IllegalStateException("A computer already exists!"); - instance=this; //TODO: Move some init stuff here + instance = this; } public void Start(CommandSender sender, int index) {// TODO: Add touchscreen support (#2) @@ -73,9 +75,9 @@ public final class Computer { machine = session.getMachine(); // This is the Machine object we can work with final IConsole console = session.getConsole(); val handler = new MachineEventHandler(Computer.this); - Utils.registerListener(console.getEventSource(), handler, VBoxEventType.MachineEvent); + handler.registerTo(console.getEventSource()); IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2 - Utils.registerListener(progress.getEventSource(), handler, VBoxEventType.OnProgressTaskCompleted); //TODO: Show progress bar some way? + handler.registerTo(progress.getEventSource()); //TODO: Show progress bar some way? console.getDisplay().attachFramebuffer(0L, new IFramebuffer(new MCFrameBuffer(console.getDisplay(), true))); sendMessage(sender, "§eComputer started."); diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/MouseLockerPlayerListener.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/MouseLockerPlayerListener.java index e619c40..07785fd 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/MouseLockerPlayerListener.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/MouseLockerPlayerListener.java @@ -1,13 +1,13 @@ package sznp.virtualcomputer; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + public class MouseLockerPlayerListener implements Runnable { public static Map LockedPlayers = new HashMap<>(); public static float LockedSpeed = 5; @@ -22,7 +22,7 @@ public class MouseLockerPlayerListener implements Runnable { if (yaw2 - yaw1 == 0 || pitch2 - pitch1 == 0) return; - PluginMain.Instance.UpdateMouse(null, (int) ((yaw2 - yaw1) * LockedSpeed), + Computer.getInstance().UpdateMouse(null, (int) ((yaw2 - yaw1) * LockedSpeed), (int) ((pitch2 - pitch1) * LockedSpeed), 0, 0, ""); entry.getKey().teleport(entry.getValue(), TeleportCause.PLUGIN); diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/PluginMain.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/PluginMain.java index b04db1d..37e86ce 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/PluginMain.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/PluginMain.java @@ -70,8 +70,9 @@ public class PluginMain extends JavaPlugin { VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom"); vbl.RTR3InitExe(0, "", 0); vbox = manager.getVBox(); - Utils.registerListener(vbox.getEventSource(), new VBoxEventHandler(), VBoxEventType.OnMachineStateChanged); - session = manager.getSessionObject(); // TODO: Events + new VBoxEventHandler().registerTo(vbox.getEventSource()); + session = manager.getSessionObject(); + new Computer(this, session, vbox); //Saves itself ccs.sendMessage("§bLoading Screen..."); try { //throw new NoClassDefFoundError("Test error pls ignore"); diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/EventHandlerBase.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/EventHandlerBase.java new file mode 100644 index 0000000..475aa23 --- /dev/null +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/EventHandlerBase.java @@ -0,0 +1,56 @@ +package sznp.virtualcomputer.events; + +import lombok.val; +import org.bukkit.Bukkit; +import org.mozilla.interfaces.IEvent; +import org.mozilla.interfaces.IEventListener; +import org.virtualbox_6_0.IEventSource; +import org.virtualbox_6_0.VBoxEventType; +import sznp.virtualcomputer.util.COMObjectBase; +import sznp.virtualcomputer.util.Utils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Map; + +/** + * A Bukkit-like event system which calls the appropriate methods on an event. + */ +public abstract class EventHandlerBase extends COMObjectBase implements IEventListener { + /** + * The events to listen for. It will only look for these handlers. + */ + private final Map> eventMap; + + protected EventHandlerBase(Map> eventMap) { + //this.eventMap = eventMap.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().value(), Map.Entry::getValue)); + this.eventMap = eventMap; + } + + @Override + public final void handleEvent(IEvent iEvent) { + //val cl=eventMap.get((int)iEvent.getType()); - We can afford to search through the events for this handler + val kv = eventMap.entrySet().stream().filter(e -> e.getKey().value() == iEvent.getType()).findAny(); + if (!kv.isPresent()) return; //Event not supported + val cl = kv.get().getValue(); + for (Method method : getClass().getMethods()) { + if (method.isAnnotationPresent(org.bukkit.event.EventHandler.class) + && method.getParameterCount() == 1 && method.getParameterTypes()[0] == cl) { + try { + method.invoke(this, Utils.getEvent(iEvent, cl)); + return; + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + Bukkit.getLogger().warning("Error while handling VirtualBox event!"); + e.getCause().printStackTrace(); + } + } + } + } + + public void registerTo(IEventSource source) { + Utils.registerListener(source, this, new ArrayList<>(eventMap.keySet())); + } +} diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java index 4b90bfb..322ebb4 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java @@ -1,27 +1,31 @@ package sznp.virtualcomputer.events; -import lombok.RequiredArgsConstructor; -import lombok.val; -import org.mozilla.interfaces.IEvent; -import org.mozilla.interfaces.IEventListener; +import com.google.common.collect.ImmutableMap; +import org.bukkit.event.EventHandler; +import org.virtualbox_6_0.IMachineStateChangedEvent; +import org.virtualbox_6_0.IProgressTaskCompletedEvent; import org.virtualbox_6_0.IStateChangedEvent; -import sznp.virtualcomputer.util.COMObjectBase; +import org.virtualbox_6_0.VBoxEventType; +import sznp.virtualcomputer.Computer; -@RequiredArgsConstructor -public class MachineEventHandler extends COMObjectBase implements IEventListener { +public class MachineEventHandler extends EventHandlerBase { private final Computer computer; - @Override - public void handleEvent(IEvent iEvent) { - if(iEvent instanceof IStateChangedEvent) { - val event=(IStateChangedEvent) iEvent; //https://www.virtualbox.org/sdkref/_virtual_box_8idl.html#a80b08f71210afe16038e904a656ed9eb - switch (event.getState()) { - case Stuck: - computer.Stop(null); - break; - case PoweredOff: - case Saved: - computer.stopRendering(); - } + + public MachineEventHandler(Computer computer) { + super(ImmutableMap.of(VBoxEventType.OnMachineStateChanged, IMachineStateChangedEvent.class, + VBoxEventType.OnProgressTaskCompleted, IProgressTaskCompletedEvent.class)); + this.computer = computer; + } + + @EventHandler + public void handleStateChange(IStateChangedEvent event) { //https://www.virtualbox.org/sdkref/_virtual_box_8idl.html#a80b08f71210afe16038e904a656ed9eb + switch (event.getState()) { + case Stuck: + computer.Stop(null); + break; + case PoweredOff: + case Saved: + computer.stopRendering(); } } } diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/VBoxEventHandler.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/VBoxEventHandler.java index 5a7ce86..cf2991a 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/VBoxEventHandler.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/VBoxEventHandler.java @@ -1,16 +1,17 @@ package sznp.virtualcomputer.events; +import com.google.common.collect.ImmutableMap; import lombok.Getter; -import lombok.val; import org.bukkit.command.CommandSender; -import org.mozilla.interfaces.IEvent; -import org.mozilla.interfaces.IEventListener; +import org.bukkit.event.EventHandler; import org.virtualbox_6_0.ISessionStateChangedEvent; import org.virtualbox_6_0.SessionState; -import sznp.virtualcomputer.util.COMObjectBase; +import org.virtualbox_6_0.VBoxEventType; +import sznp.virtualcomputer.Computer; -public class VBoxEventHandler extends COMObjectBase implements IEventListener { +public class VBoxEventHandler extends EventHandlerBase { public VBoxEventHandler() { + super(ImmutableMap.of(VBoxEventType.OnSessionStateChanged, ISessionStateChangedEvent.class)); instance = this; } @@ -19,14 +20,14 @@ public class VBoxEventHandler extends COMObjectBase implements IEventListener { private String machineID; private CommandSender sender; - @Override - public void handleEvent(IEvent iEvent) { - if (iEvent instanceof ISessionStateChangedEvent) { - val event = ((ISessionStateChangedEvent) iEvent); - if (!event.getMachineId().equals(machineID)) return; - if (event.getState() == SessionState.Locked) //Need to check here, because we can't access the console yet - Computer.getInstance().onLock(sender); - } + @EventHandler + public void onSessionStateChange(ISessionStateChangedEvent event) { + System.out.println("Session change event: " + event); + System.out.println("ID1: " + event.getMachineId() + " - ID2: " + machineID); + if (!event.getMachineId().equals(machineID)) return; + System.out.println("State: " + event.getState()); + if (event.getState() == SessionState.Locked) //Need to check here, because we can't access the console yet + Computer.getInstance().onLock(sender); } public void setup(String machineID, CommandSender sender) { diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Utils.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Utils.java index 4b046e6..4269fec 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Utils.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Utils.java @@ -1,11 +1,16 @@ package sznp.virtualcomputer.util; +import lombok.val; import org.mozilla.interfaces.IEventListener; +import org.virtualbox_6_0.IEvent; import org.virtualbox_6_0.IEventSource; import org.virtualbox_6_0.VBoxEventType; +import org.virtualbox_6_0.xpcom.IUnknown; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; +import java.util.List; public class Utils { /** @@ -34,7 +39,21 @@ public class Utils { usrPathsField.set(null, newPaths); } - public static void registerListener(IEventSource source, IEventListener listener, VBoxEventType... types) { - source.registerListener(new org.virtualbox_6_0.IEventListener(listener), Arrays.asList(types), true); + //public static void registerListener(IEventSource source, IEventListener listener, VBoxEventType... types) { + public static void registerListener(IEventSource source, IEventListener listener, List types) { + source.registerListener(new org.virtualbox_6_0.IEventListener(listener), types, true); + } + + @SuppressWarnings("unchecked") + public static T getEvent(org.mozilla.interfaces.IEvent event, Class cl) { + //if (event.getType() != type.value()) return null; + //return (T) T.queryInterface(new IEvent(event)); - Probably won't work + try { + val method = cl.getMethod("queryInterface", IUnknown.class); + return (T) method.invoke(null, new IEvent(event)); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + return null; + } } }