Directly using VirtualBox from Java #5
6 changed files with 84 additions and 29 deletions
|
@ -57,11 +57,16 @@
|
||||||
<version>6.0</version>
|
<version>6.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bukkit</groupId>
|
<groupId>org.virtualbox</groupId>
|
||||||
<artifactId>craftbukkit</artifactId>
|
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
<version>6.0</version>
|
||||||
<scope>provided</scope>
|
</dependency>
|
||||||
</dependency>
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>craftbukkit</artifactId>
|
||||||
|
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
|
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.java.dev.jna</groupId>
|
<groupId>net.java.dev.jna</groupId>
|
||||||
|
@ -90,26 +95,56 @@
|
||||||
<version>3.0.0</version>
|
<version>3.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<!-- <profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>XPCOM</id>
|
<id>XPCOM</id>
|
||||||
<dependencies>
|
<build>
|
||||||
<dependency>
|
<plugins>
|
||||||
<groupId>org.virtualbox</groupId>
|
<plugin>
|
||||||
<artifactId>VirtualBox</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>6.0</version>
|
<executions>
|
||||||
</dependency>
|
<execution>
|
||||||
</dependencies>
|
<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>
|
||||||
<profile>
|
<profile>
|
||||||
<id>MSCOM</id>
|
<id>MSCOM</id>
|
||||||
<dependencies>
|
<build>
|
||||||
<dependency>
|
<plugins>
|
||||||
<groupId>org.virtualbox</groupId>
|
<plugin>
|
||||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>6.0</version>
|
<executions>
|
||||||
</dependency>
|
<execution>
|
||||||
</dependencies>
|
<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>
|
</profile>
|
||||||
</profiles> -->
|
</profiles>
|
||||||
</project>
|
</project>
|
|
@ -8,6 +8,7 @@ import org.bukkit.command.CommandSender;
|
||||||
import org.virtualbox_6_0.*;
|
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.GPURendererInternal;
|
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;
|
||||||
|
@ -207,7 +208,7 @@ public final class Computer {
|
||||||
sendMessage(sender, "§eComputer powered off."); //This block runs later
|
sendMessage(sender, "§eComputer powered off."); //This block runs later
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
GPURendererInternal.setPixels(new byte[1], 0, 0); //Black screen
|
GPURenderer.update(new byte[1], 0, 0, 0, 0, 640, 480); //Black screen
|
||||||
stopEvents();
|
stopEvents();
|
||||||
MouseLockerPlayerListener.computerStop();
|
MouseLockerPlayerListener.computerStop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class PluginMain extends JavaPlugin {
|
||||||
System.setProperty("java.library.path", vbpath);
|
System.setProperty("java.library.path", vbpath);
|
||||||
Utils.addLibraryPath(vbpath);
|
Utils.addLibraryPath(vbpath);
|
||||||
final VirtualBoxManager manager = VirtualBoxManager.createInstance(getDataFolder().getAbsolutePath());
|
final VirtualBoxManager manager = VirtualBoxManager.createInstance(getDataFolder().getAbsolutePath());
|
||||||
VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom");
|
VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom"); //TODO: Test for MSCOM
|
||||||
vbl.RTR3InitExe(0, "", 0);
|
vbl.RTR3InitExe(0, "", 0);
|
||||||
IVirtualBox vbox = manager.getVBox();
|
IVirtualBox vbox = manager.getVBox();
|
||||||
listener = new VBoxEventHandler().registerTo(vbox.getEventSource());
|
listener = new VBoxEventHandler().registerTo(vbox.getEventSource());
|
||||||
|
|
|
@ -16,8 +16,10 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
private byte[] buffer;
|
private byte[] buffer;
|
||||||
private GPURendererInternal kernel;
|
private GPURendererInternal kernel;
|
||||||
private WorldMap wmap;
|
private WorldMap wmap;
|
||||||
|
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;
|
||||||
|
|
||||||
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);
|
||||||
|
@ -32,6 +34,8 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
colors_[i] = cs[i].getRGB();
|
colors_[i] = cs[i].getRGB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.mapx = mapx;
|
||||||
|
this.mapy = mapy;
|
||||||
Field field = map.getClass().getDeclaredField("worldMap");
|
Field field = map.getClass().getDeclaredField("worldMap");
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
wmap = (WorldMap) field.get(map);
|
wmap = (WorldMap) field.get(map);
|
||||||
|
@ -46,19 +50,34 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
public void render(MapView map, MapCanvas canvas, Player player) {
|
public void render(MapView map, MapCanvas canvas, Player player) {
|
||||||
Timing t = new Timing();
|
Timing t = new Timing();
|
||||||
try {
|
try {
|
||||||
if (kernel.isRendered()) return; //TODO: Stop rendering after computer is stopped
|
if (kernel.isRendered()) return;
|
||||||
if (buffer == null) { //The buffer remains the same, as the canvas remains the same
|
if (buffer == null) { //The buffer remains the same, as the canvas remains the same
|
||||||
Field field = canvas.getClass().getDeclaredField("buffer");
|
Field field = canvas.getClass().getDeclaredField("buffer");
|
||||||
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
|
||||||
|
|| changedX + changedWidth < mapx * 128 || changedY + changedHeight < mapy * 128)
|
||||||
|
return; //No change for this map - TODO: Test
|
||||||
|
int x = changedX % 128;
|
||||||
|
int y = changedY % 128;
|
||||||
|
int w = x + changedWidth >= 128 ? 128 - x - 1 : changedWidth;
|
||||||
|
int h = y + changedHeight >= 128 ? 128 - y - 1 : changedHeight;
|
||||||
kernel.render(buffer);
|
kernel.render(buffer);
|
||||||
wmap.flagDirty(0, 0);
|
wmap.flagDirty(x, y);
|
||||||
wmap.flagDirty(127, 127); // Send the whole image - TODO: Only send changes
|
wmap.flagDirty(x + w, y + h); // Send the changes only
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
if (t.elapsedMS() > 60)
|
if (t.elapsedMS() > 60)
|
||||||
System.out.println("Map rendering took " + t.elapsedMS() + "ms");
|
System.out.println("Map rendering took " + t.elapsedMS() + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void update(byte[] pixels, int width, int height, int changedX, int changedY, int changedWidth, int changedHeight) {
|
||||||
|
GPURenderer.changedX = changedX;
|
||||||
|
GPURenderer.changedY = changedY;
|
||||||
|
GPURenderer.changedWidth = changedWidth;
|
||||||
|
GPURenderer.changedHeight = changedHeight;
|
||||||
|
GPURendererInternal.setPixels(pixels, width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class GPURendererInternal extends Kernel {
|
||||||
private static final int BLUE = 0;
|
private static final int BLUE = 0;
|
||||||
|
|
||||||
@SuppressWarnings("Convert2Lambda") //Aparapi fails with lambdas
|
@SuppressWarnings("Convert2Lambda") //Aparapi fails with lambdas
|
||||||
public static void setPixels(byte[] pixels, int width, int height) {
|
static void setPixels(byte[] pixels, int width, int height) {
|
||||||
renderers.forEach(new Consumer<GPURendererInternal>() {
|
renderers.forEach(new Consumer<GPURendererInternal>() {
|
||||||
@Override //IT'S THE LAMBDAS (exception)
|
@Override //IT'S THE LAMBDAS (exception)
|
||||||
public void accept(GPURendererInternal r) {
|
public void accept(GPURendererInternal r) {
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class MCFrameBuffer implements IFramebuffer {
|
||||||
pointer = new Pointer(ptr[0]);
|
pointer = new Pointer(ptr[0]);
|
||||||
this.width = (int) w[0];
|
this.width = (int) w[0];
|
||||||
this.height = (int) h[0];
|
this.height = (int) h[0];
|
||||||
GPURendererInternal.setPixels(pointer.getByteArray(0L, (int) (w[0] * h[0] * 4)), (int) w[0], (int) h[0]);
|
GPURenderer.update(pointer.getByteArray(0L, (int) (w[0] * h[0] * 4)), (int) w[0], (int) h[0], 0, 0, this.width, this.height);
|
||||||
} else {
|
} else {
|
||||||
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
|
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
|
||||||
if (width * height > 640 * 480)
|
if (width * height > 640 * 480)
|
||||||
|
@ -129,7 +129,7 @@ public class MCFrameBuffer implements IFramebuffer {
|
||||||
@Override
|
@Override
|
||||||
public void notifyUpdate(long x, long y, long width, long height) {
|
public void notifyUpdate(long x, long y, long width, long height) {
|
||||||
Timing t = new Timing();
|
Timing t = new Timing();
|
||||||
GPURendererInternal.setPixels(pointer.getByteArray(0L, (this.width * this.height * 4)), this.width, this.height); //TODO: Only copy changed part
|
GPURenderer.update(pointer.getByteArray(0L, this.width * this.height * 4), this.width, this.height, (int) x, (int) y, (int) width, (int) height);
|
||||||
if (t.elapsedMS() > 60) //Typically 1ms max
|
if (t.elapsedMS() > 60) //Typically 1ms max
|
||||||
System.out.println("Update took " + t.elapsedMS() + "ms");
|
System.out.println("Update took " + t.elapsedMS() + "ms");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue