From c8ea7187874349c302762e75c396e53e13b5ba3c Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 22 Mar 2019 02:29:39 +0100 Subject: [PATCH] Fixes, events - Unlocking machine on power off - Removed change debug messages - Fixed missing break in command handling - Added timing (updates seem to be 1ms max, changes 66ms) -- Screen rendering for the first time takes long, as expected - Handling errors such as powering off while getting bitmap - Added support for any case key names - Fixed typo for 'period' key - Fixed state event (probably) --- .../java/sznp/virtualcomputer/Commands.java | 1 + .../java/sznp/virtualcomputer/Computer.java | 11 ++++---- .../events/MachineEventHandler.java | 5 ++-- .../virtualcomputer/renderer/GPURenderer.java | 4 +++ .../renderer/MCFrameBuffer.java | 25 ++++++++++++++----- .../sznp/virtualcomputer/util/Scancode.java | 25 +++++++++++++++++-- .../sznp/virtualcomputer/util/Timing.java | 9 +++++++ 7 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 VirtualComputer/src/main/java/sznp/virtualcomputer/util/Timing.java diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java index 0fcba5d..68b911a 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java @@ -111,6 +111,7 @@ public class Commands implements CommandExecutor { + " [\"\",{\"text\":\" [Z]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Z\"}},{\"text\":\" [X]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key X\"}},{\"text\":\" [C]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key C\"}},{\"text\":\" [V]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key V\"}},{\"text\":\" [B]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key B\"}},{\"text\":\" [N]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key N\"}},{\"text\":\" [M]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key M\"}}]"); Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName() + " [\"\",{\"text\":\" [Ctrl]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key ControlLeft\"}},{\"text\":\" [Alt]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key AltLeft\"}},{\"text\":\" [Space]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Space\"}},{\"text\":\" [AltGr]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key AltRight\"}},{\"text\":\" [Ctrl]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key ControlRight\"}}]"); + break; case "mouse": if (!MouseLockerPlayerListener.LockedPlayers.containsKey(sender)) { MouseLockerPlayerListener.LockedPlayers.put((Player) sender, ((Player) sender).getLocation()); diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java index 394cf33..73bbd7d 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java @@ -156,10 +156,8 @@ public final class Computer { durationorstate = -2; else durationorstate = Short.parseShort(stateorduration); - int code; - try { - code = Scancode.valueOf("sc_" + key.toLowerCase()).Code; - } catch (IllegalArgumentException e) { + int code = Scancode.getCode("sc_" + key.toLowerCase()); + if (code == -1) { sender.sendMessage("§cUnknown key: " + key); return; } @@ -193,7 +191,8 @@ public final class Computer { UpdateMouse(sender, x, y, z, w, mbs, false); } - public void stopRendering() { - //TODO + public void onMachineStop() { + session.unlockMachine(); + plugin.getLogger().info("Computer powered off."); } } diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java index 322ebb4..131dcd9 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/events/MachineEventHandler.java @@ -2,7 +2,6 @@ package sznp.virtualcomputer.events; 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 org.virtualbox_6_0.VBoxEventType; @@ -12,7 +11,7 @@ public class MachineEventHandler extends EventHandlerBase { private final Computer computer; public MachineEventHandler(Computer computer) { - super(ImmutableMap.of(VBoxEventType.OnMachineStateChanged, IMachineStateChangedEvent.class, + super(ImmutableMap.of(VBoxEventType.OnStateChanged, IStateChangedEvent.class, VBoxEventType.OnProgressTaskCompleted, IProgressTaskCompletedEvent.class)); this.computer = computer; } @@ -25,7 +24,7 @@ public class MachineEventHandler extends EventHandlerBase { break; case PoweredOff: case Saved: - computer.stopRendering(); + computer.onMachineStop(); } } } diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/GPURenderer.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/GPURenderer.java index 3356976..4606246 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/GPURenderer.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/GPURenderer.java @@ -10,6 +10,7 @@ import org.bukkit.map.MapCanvas; import org.bukkit.map.MapPalette; import org.bukkit.map.MapRenderer; import org.bukkit.map.MapView; +import sznp.virtualcomputer.util.Timing; import java.awt.*; import java.lang.reflect.Field; @@ -53,6 +54,7 @@ public class GPURenderer extends MapRenderer implements IRenderer { @Override public void render(MapView map, MapCanvas canvas, Player player) { + Timing t = new Timing(); try { if (kernel.isRendered()) return; //TODO: Stop rendering after computer is stopped Field field = canvas.getClass().getDeclaredField("buffer"); @@ -67,5 +69,7 @@ public class GPURenderer extends MapRenderer implements IRenderer { } catch (Exception e) { e.printStackTrace(); } + if (t.elapsedMS() > 60) + System.out.println("Map rendering took " + t.elapsedMS() + "ms"); } } diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/MCFrameBuffer.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/MCFrameBuffer.java index 66d5c13..8d10fe3 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/MCFrameBuffer.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/renderer/MCFrameBuffer.java @@ -9,6 +9,7 @@ import org.mozilla.interfaces.nsISupports; import org.mozilla.xpcom.Mozilla; import org.virtualbox_6_0.*; import sznp.virtualcomputer.PluginMain; +import sznp.virtualcomputer.util.Timing; import java.util.Arrays; @@ -93,21 +94,22 @@ public class MCFrameBuffer implements IFramebuffer { @Override public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) { - System.out.println("Change - " + width + "x" + height); + //Timing ti=new Timing(); + //System.out.println("Change - " + width + "x" + height); if (tt != null) tt.cancel(); /* * if (width > 640 || height > 480) { tt = Bukkit.getScheduler().runTaskTimerAsynchronously(PluginMain.Instance, () -> display.setVideoModeHint(0L, true, false, 0, 0, 640L, 480L, 32L), 5, 5); * return; // Don't even try to render too large resolutions } */ - tt = Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, () -> { + tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> { try { display.querySourceBitmap(0L, holder); //byte[] arr = PluginMain.allpixels.array(); long[] ptr = new long[1], w = new long[1], h = new long[1], bpp = new long[1], bpl = new long[1], pf = new long[1]; holder.value.getTypedWrapped().queryBitmapInfo(ptr, w, h, bpp, bpl, pf); - System.out.println("Arr0:" + ptr[0]); - System.out.println("whbppbplpf: " + w[0] + " " + h[0] + " " + bpp[0] + " " + bpl[0] + " " + pf[0]); + //System.out.println("Arr0:" + ptr[0]); + //System.out.println("whbppbplpf: " + w[0] + " " + h[0] + " " + bpp[0] + " " + bpl[0] + " " + pf[0]); if (PluginMain.direct) { //PluginMain.pxc.setSource(ptr[0], (int)w[0], (int)h[0], PluginMain.MCX, PluginMain.MCY); pointer = new Pointer(ptr[0]); @@ -121,11 +123,19 @@ public class MCFrameBuffer implements IFramebuffer { else PluginMain.allpixels.limit((int) (width * height * 4)); } - System.out.println("Change!"); + //System.out.println("Change!"); + //System.out.println("Change task took "+ti.elapsedMS()+"ms"); + } catch (VBoxException e) { + if (e.getResultCode() == 0x80070005) + return; // Machine is being powered down + if (e.getResultCode() == 0x80004005) //The function "querySourceBitmap" returned an error condition: "Operation failed (NS_ERROR_FAILURE)" + System.out.println("I don't know why this happens, but stopping the computer helps."); + e.printStackTrace(); } catch (Throwable t) { t.printStackTrace(); } - }, 5); // Wait 1/4th of a second + }); // Wait 1/4th of a second - Don't + //System.out.println("Change took "+ti.elapsedMS()+"ms"); } @Override @@ -138,7 +148,10 @@ public class MCFrameBuffer implements IFramebuffer { ((DirectRenderer) r).render(PluginMain.allpixels, x, y, width, height); System.out.println("Update!"); - The render is done each tick }, 5);*/ + Timing t = new Timing(); GPURendererInternal.setPixels(pointer.getByteArray(0L, (this.width * this.height * 4)), this.width, this.height); //TODO: Only copy changed part + if (t.elapsedMS() > 60) //Typically 1ms max + System.out.println("Update took " + t.elapsedMS() + "ms"); } @Override diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Scancode.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Scancode.java index daa0a18..a9cae96 100644 --- a/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Scancode.java +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Scancode.java @@ -8,6 +8,8 @@ The scancode values come from: - reading win32 WM_INPUT keyboard messages. */ +import java.util.HashMap; + @SuppressWarnings("unused") public enum Scancode { // https://handmade.network/forums/t/2011-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names @@ -21,7 +23,7 @@ public enum Scancode { // https://handmade.network/forums/t/2011-keyboard_inputs 0x29), sc_shiftLeft(0x2A), sc_backslash(0x2B), sc_z( 0x2C), sc_x(0x2D), sc_c(0x2E), sc_v(0x2F), sc_b( 0x30), sc_n(0x31), sc_m(0x32), sc_comma( - 0x33), sc_preiod(0x34), sc_slash( + 0x33), sc_period(0x34), sc_slash( 0x35), sc_shiftRight( 0x36), sc_numpad_multiply( 0x37), sc_altLeft( @@ -107,9 +109,28 @@ public enum Scancode { // https://handmade.network/forums/t/2011-keyboard_inputs * some times you get keyup messages too. - when pressed at the same time as one or both control keys, generates a 0xE046 (sc_cancel) and the string for that scancode is "break". */ + private static final HashMap scanCodes = new HashMap<>(); + + static { + for (Scancode sc : values()) + scanCodes.put(sc.toString().toLowerCase(), sc.Code); + } + + /** + * Gets the scancode from a lowercased string (O(1)) + * + * @param keyLowerCased The key name, lowercased (sc_...) + * @return The code or -1 if not found + */ + public static int getCode(String keyLowerCased) { + Integer code = scanCodes.get(keyLowerCased); + if (code == null) return -1; + return code; + } + public int Code; Scancode(int code) { Code = code; } -} \ No newline at end of file +} diff --git a/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Timing.java b/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Timing.java new file mode 100644 index 0000000..eb68ba2 --- /dev/null +++ b/VirtualComputer/src/main/java/sznp/virtualcomputer/util/Timing.java @@ -0,0 +1,9 @@ +package sznp.virtualcomputer.util; + +public class Timing { + private long start = System.nanoTime(); + + public long elapsedMS() { + return (System.nanoTime() - start) / 1000000L; + } +}