Directly using VirtualBox from Java #5
6 changed files with 132 additions and 41 deletions
|
@ -32,6 +32,58 @@
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>XPCOM</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactSet>
|
||||||
|
<excludes>
|
||||||
|
<exclude>org.virtualbox:VirtualBox-MSCOM</exclude>
|
||||||
|
</excludes>
|
||||||
|
</artifactSet>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>MSCOM</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactSet>
|
||||||
|
<excludes>
|
||||||
|
<exclude>org.virtualbox:VirtualBox</exclude>
|
||||||
|
</excludes>
|
||||||
|
</artifactSet>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spigot-repo</id>
|
<id>spigot-repo</id>
|
||||||
|
@ -75,6 +127,12 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.virtualbox</groupId>
|
||||||
|
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||||
|
<version>6.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bukkit</groupId>
|
<groupId>org.bukkit</groupId>
|
||||||
<artifactId>craftbukkit</artifactId>
|
<artifactId>craftbukkit</artifactId>
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.virtualbox_6_0.*;
|
||||||
import sznp.virtualcomputer.events.MachineEventHandler;
|
import sznp.virtualcomputer.events.MachineEventHandler;
|
||||||
import sznp.virtualcomputer.events.VBoxEventHandler;
|
import sznp.virtualcomputer.events.VBoxEventHandler;
|
||||||
import sznp.virtualcomputer.renderer.GPURenderer;
|
import sznp.virtualcomputer.renderer.GPURenderer;
|
||||||
import sznp.virtualcomputer.renderer.GPURendererInternal;
|
|
||||||
import sznp.virtualcomputer.renderer.MCFrameBuffer;
|
import sznp.virtualcomputer.renderer.MCFrameBuffer;
|
||||||
import sznp.virtualcomputer.util.Scancode;
|
import sznp.virtualcomputer.util.Scancode;
|
||||||
|
|
||||||
|
@ -79,6 +78,8 @@ public final class Computer {
|
||||||
public void onLock(CommandSender sender) {
|
public void onLock(CommandSender sender) {
|
||||||
machine = session.getMachine(); // This is the Machine object we can work with
|
machine = session.getMachine(); // This is the Machine object we can work with
|
||||||
final IConsole console = session.getConsole();
|
final IConsole console = session.getConsole();
|
||||||
|
if (handler != null)
|
||||||
|
handler.disable();
|
||||||
handler = new MachineEventHandler(Computer.this, sender);
|
handler = new MachineEventHandler(Computer.this, sender);
|
||||||
listener = handler.registerTo(console.getEventSource());
|
listener = handler.registerTo(console.getEventSource());
|
||||||
IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2
|
IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2
|
||||||
|
@ -222,6 +223,7 @@ public final class Computer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pluginDisable(CommandSender ccs) {
|
public void pluginDisable(CommandSender ccs) {
|
||||||
|
stopEvents();
|
||||||
if (session.getState() == SessionState.Locked) {
|
if (session.getState() == SessionState.Locked) {
|
||||||
if (session.getMachine().getState().equals(MachineState.Running)) {
|
if (session.getMachine().getState().equals(MachineState.Running)) {
|
||||||
ccs.sendMessage("§aSaving machine state...");
|
ccs.sendMessage("§aSaving machine state...");
|
||||||
|
|
|
@ -40,6 +40,7 @@ public class PluginMain extends JavaPlugin {
|
||||||
*/
|
*/
|
||||||
//public static PXCLib pxc;
|
//public static PXCLib pxc;
|
||||||
public static boolean direct;
|
public static boolean direct;
|
||||||
|
public static boolean sendAll;
|
||||||
|
|
||||||
// Fired when plugin is first enabled
|
// Fired when plugin is first enabled
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,6 +49,7 @@ public class PluginMain extends JavaPlugin {
|
||||||
try {
|
try {
|
||||||
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
||||||
this.getCommand("computer").setExecutor(new Commands());
|
this.getCommand("computer").setExecutor(new Commands());
|
||||||
|
sendAll = getConfig().getBoolean("sendAll", true);
|
||||||
ccs.sendMessage("§bInitializing VirtualBox...");
|
ccs.sendMessage("§bInitializing VirtualBox...");
|
||||||
String vbpath = System.getProperty("os.name").toLowerCase().contains("mac")
|
String vbpath = System.getProperty("os.name").toLowerCase().contains("mac")
|
||||||
? "/Applications/VirtualBox.app/Contents/MacOS"
|
? "/Applications/VirtualBox.app/Contents/MacOS"
|
||||||
|
@ -109,13 +111,15 @@ public class PluginMain extends JavaPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
||||||
mousetask.cancel();
|
if (mousetask != null)
|
||||||
|
mousetask.cancel();
|
||||||
/*try {
|
/*try {
|
||||||
source.unregisterListener(listener);
|
source.unregisterListener(listener);
|
||||||
} catch (VBoxException e) { //"Listener was never registered"
|
} catch (VBoxException e) { //"Listener was never registered"
|
||||||
e.printStackTrace(); - VBox claims the listener was never registered (can double register as well)
|
e.printStackTrace(); - VBox claims the listener was never registered (can double register as well)
|
||||||
}*/
|
}*/
|
||||||
((VBoxEventHandler) listener.getTypedWrapped()).disable(); //The save progress wait locks with the event
|
if (listener != null)
|
||||||
|
((VBoxEventHandler) listener.getTypedWrapped()).disable(); //The save progress wait locks with the event
|
||||||
if (Computer.getInstance() != null)
|
if (Computer.getInstance() != null)
|
||||||
Computer.getInstance().pluginDisable(ccs);
|
Computer.getInstance().pluginDisable(ccs);
|
||||||
ccs.sendMessage("§aHuh.");
|
ccs.sendMessage("§aHuh.");
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class MachineEventHandler extends EventHandlerBase {
|
||||||
case PoweredOff:
|
case PoweredOff:
|
||||||
case Saved:
|
case Saved:
|
||||||
if (starting) {
|
if (starting) {
|
||||||
sender.sendMessage("§cFailed to start computer! See the VM's log for more details.");
|
sender.sendMessage("§cFailed to start computer! See the console for more details.");
|
||||||
sender.sendMessage("§cMake sure that 2D and 3D acceleration is disabled.");
|
sender.sendMessage("§cMake sure that 2D and 3D acceleration is disabled.");
|
||||||
starting = false;
|
starting = false;
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||||
|
|
|
@ -7,23 +7,29 @@ import org.bukkit.map.MapCanvas;
|
||||||
import org.bukkit.map.MapPalette;
|
import org.bukkit.map.MapPalette;
|
||||||
import org.bukkit.map.MapRenderer;
|
import org.bukkit.map.MapRenderer;
|
||||||
import org.bukkit.map.MapView;
|
import org.bukkit.map.MapView;
|
||||||
|
import sznp.virtualcomputer.PluginMain;
|
||||||
import sznp.virtualcomputer.util.Timing;
|
import sznp.virtualcomputer.util.Timing;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class GPURenderer extends MapRenderer implements IRenderer {
|
public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
private byte[] buffer;
|
private byte[] buffer;
|
||||||
private GPURendererInternal kernel;
|
private final GPURendererInternal kernel;
|
||||||
private WorldMap wmap;
|
private WorldMap wmap;
|
||||||
private int mapx, mapy;
|
private int mapx, mapy;
|
||||||
//Store at central location after conversion
|
//Store at central location after conversion
|
||||||
private static int[] colors_;
|
private static int[] colors_;
|
||||||
private static int changedX, changedY, changedWidth, changedHeight;
|
private int changedX = 0, changedY = 0, changedWidth = 640, changedHeight = 480;
|
||||||
|
private static ArrayList<GPURenderer> renderers = new ArrayList<>();
|
||||||
|
|
||||||
public GPURenderer(short id, World world, int mapx, int mapy) throws Exception {
|
public GPURenderer(short id, World world, int mapx, int mapy) throws Exception {
|
||||||
MapView map = IRenderer.prepare(id, world);
|
MapView map = IRenderer.prepare(id, world);
|
||||||
if (map == null) return; //Testing
|
if (map == null) {
|
||||||
|
kernel = null;
|
||||||
|
return; //Testing
|
||||||
|
}
|
||||||
|
|
||||||
if (colors_ == null) {
|
if (colors_ == null) {
|
||||||
Field field = MapPalette.class.getDeclaredField("colors");
|
Field field = MapPalette.class.getDeclaredField("colors");
|
||||||
|
@ -40,8 +46,7 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
wmap = (WorldMap) field.get(map);
|
wmap = (WorldMap) field.get(map);
|
||||||
kernel = new GPURendererInternal(mapx, mapy, colors_);
|
kernel = new GPURendererInternal(mapx, mapy, colors_);
|
||||||
|
renderers.add(this);
|
||||||
//System.setProperty("com.codegen.config.enable.NEW", "true");
|
|
||||||
|
|
||||||
map.addRenderer(this);
|
map.addRenderer(this);
|
||||||
}
|
}
|
||||||
|
@ -56,16 +61,35 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
buffer = (byte[]) field.get(canvas);
|
buffer = (byte[]) field.get(canvas);
|
||||||
}
|
}
|
||||||
if (changedX >= (mapx + 1) * 128 || changedY >= (mapy + 1) * 128
|
if (!PluginMain.sendAll) {
|
||||||
|| changedX + changedWidth < mapx * 128 || changedY + changedHeight < mapy * 128)
|
synchronized (kernel) {
|
||||||
return; //No change for this map - TODO: Test
|
if (changedX >= (mapx + 1) * 128 || changedY >= (mapy + 1) * 128
|
||||||
int x = changedX % 128;
|
|| changedX + changedWidth < mapx * 128 || changedY + changedHeight < mapy * 128) {
|
||||||
int y = changedY % 128;
|
kernel.ignoreChange();
|
||||||
int w = x + changedWidth >= 128 ? 128 - x - 1 : changedWidth;
|
return; //No change for this map
|
||||||
int h = y + changedHeight >= 128 ? 128 - y - 1 : changedHeight;
|
}
|
||||||
kernel.render(buffer);
|
}
|
||||||
wmap.flagDirty(x, y);
|
//System.out.println("changed: (" + changedX + ", " + changedY + ") " + changedWidth + "x" + changedHeight);
|
||||||
wmap.flagDirty(x + w, y + h); // Send the changes only
|
//System.out.println("map: (" + mapx + ", " + mapy + ")");
|
||||||
|
int x = changedX - mapx * 128;
|
||||||
|
int y = changedY - mapy * 128;
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (y < 0) y = 0;
|
||||||
|
int xx = x + changedWidth >= 128 ? 127 : x + changedWidth;
|
||||||
|
int yy = y + changedHeight >= 128 ? 127 : y + changedHeight;
|
||||||
|
//System.out.println("local: ("+x+", "+y+") "+w+"x"+h);
|
||||||
|
kernel.render(buffer);
|
||||||
|
wmap.flagDirty(x, y);
|
||||||
|
wmap.flagDirty(xx, yy); // Send the changes only
|
||||||
|
changedX = Integer.MAX_VALUE; //Finished rendering
|
||||||
|
changedY = Integer.MAX_VALUE; //TODO: Render as soon as we receive new image
|
||||||
|
changedWidth = -1; //Finished rendering
|
||||||
|
changedHeight = -1;
|
||||||
|
} else {
|
||||||
|
kernel.render(buffer);
|
||||||
|
wmap.flagDirty(0, 0);
|
||||||
|
wmap.flagDirty(127, 127); // Send everything
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -74,10 +98,20 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void update(byte[] pixels, int width, int height, int changedX, int changedY, int changedWidth, int changedHeight) {
|
public static void update(byte[] pixels, int width, int height, int changedX, int changedY, int changedWidth, int changedHeight) {
|
||||||
GPURenderer.changedX = changedX;
|
for (GPURenderer r : renderers) {
|
||||||
GPURenderer.changedY = changedY;
|
synchronized (r.kernel) {
|
||||||
GPURenderer.changedWidth = changedWidth;
|
if (!PluginMain.sendAll) {
|
||||||
GPURenderer.changedHeight = changedHeight;
|
if (changedX < r.changedX)
|
||||||
GPURendererInternal.setPixels(pixels, width, height);
|
r.changedX = changedX;
|
||||||
|
if (changedY < r.changedY)
|
||||||
|
r.changedY = changedY;
|
||||||
|
if (changedWidth > r.changedWidth)
|
||||||
|
r.changedWidth = changedWidth;
|
||||||
|
if (changedHeight > r.changedHeight)
|
||||||
|
r.changedHeight = changedHeight;
|
||||||
|
}
|
||||||
|
r.kernel.setPixels(pixels, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,6 @@ import com.aparapi.Kernel;
|
||||||
import com.aparapi.Range;
|
import com.aparapi.Range;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
//Accessing the GPURenderer results in ArrayIndexOutOfBoundsExceptions - IT'S THE LAMBDAS
|
//Accessing the GPURenderer results in ArrayIndexOutOfBoundsExceptions - IT'S THE LAMBDAS
|
||||||
public class GPURendererInternal extends Kernel {
|
public class GPURendererInternal extends Kernel {
|
||||||
private int mapx;
|
private int mapx;
|
||||||
|
@ -21,7 +18,6 @@ public class GPURendererInternal extends Kernel {
|
||||||
private Range range;
|
private Range range;
|
||||||
@Getter
|
@Getter
|
||||||
private boolean rendered;
|
private boolean rendered;
|
||||||
private static ArrayList<GPURendererInternal> renderers = new ArrayList<>();
|
|
||||||
|
|
||||||
//public static byte[] test=new byte[1]; - LAMBDAS
|
//public static byte[] test=new byte[1]; - LAMBDAS
|
||||||
public GPURendererInternal(int mapx, int mapy, int[] colors) {
|
public GPURendererInternal(int mapx, int mapy, int[] colors) {
|
||||||
|
@ -34,8 +30,6 @@ public class GPURendererInternal extends Kernel {
|
||||||
pixels = new byte[1];
|
pixels = new byte[1];
|
||||||
width = height = 0;
|
width = height = 0;
|
||||||
rendered = false;
|
rendered = false;
|
||||||
|
|
||||||
renderers.add(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -94,17 +88,12 @@ public class GPURendererInternal extends Kernel {
|
||||||
private static final int GREEN = 1;
|
private static final int GREEN = 1;
|
||||||
private static final int BLUE = 0;
|
private static final int BLUE = 0;
|
||||||
|
|
||||||
@SuppressWarnings("Convert2Lambda") //Aparapi fails with lambdas
|
//Aparapi fails with lambdas
|
||||||
static void setPixels(byte[] pixels, int width, int height) {
|
void setPixels(byte[] pixels, int width, int height) {
|
||||||
renderers.forEach(new Consumer<GPURendererInternal>() {
|
this.pixels = pixels;
|
||||||
@Override //IT'S THE LAMBDAS (exception)
|
this.width = width;
|
||||||
public void accept(GPURendererInternal r) {
|
this.height = height;
|
||||||
r.pixels = pixels;
|
rendered = false;
|
||||||
r.width = width;
|
|
||||||
r.height = height;
|
|
||||||
r.rendered = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(byte[] buffer) {
|
void render(byte[] buffer) {
|
||||||
|
@ -113,4 +102,8 @@ public class GPURendererInternal extends Kernel {
|
||||||
put(buffer).put(pixels).execute(range).get(buffer);
|
put(buffer).put(pixels).execute(range).get(buffer);
|
||||||
rendered = true;
|
rendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ignoreChange() {
|
||||||
|
rendered = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue