Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
04053f9b13 | |||
0a6fa7a9a1 |
92 changed files with 1100 additions and 1622 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,5 +1,4 @@
|
||||||
libpxc.so
|
libpxc.so
|
||||||
dependency-reduced-pom.xml
|
|
||||||
|
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
|
@ -3,12 +3,12 @@ A working modern computer in Minecraft made using VirtualBox and Java. No client
|
||||||
|
|
||||||
## Video
|
## Video
|
||||||
|
|
||||||
[![Original video](https://img.youtube.com/vi/VxSyDfxPd3s/0.jpg)](https://www.youtube.com/watch?v=VxSyDfxPd3s)
|
[![Video](https://img.youtube.com/vi/K4t98YUIm4M/0.jpg)](https://www.youtube.com/watch?v=K4t98YUIm4M)
|
||||||
|
|
||||||
## Installation requirements
|
## Installation requirements
|
||||||
*Note: only the server host has to meet these requirements.*
|
*Note: only the server host has to meet these requirements.*
|
||||||
|
|
||||||
* A non-Windows OS
|
* A non-Windows OS supported by VirtualBox
|
||||||
* Root (sudo) privileges
|
* Root (sudo) privileges
|
||||||
* Enough resources to run another OS
|
* Enough resources to run another OS
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ A working modern computer in Minecraft made using VirtualBox and Java. No client
|
||||||
*Please give appropriate credit and link to this page if you use this machine in one of your videos/creations/etc.*
|
*Please give appropriate credit and link to this page if you use this machine in one of your videos/creations/etc.*
|
||||||
|
|
||||||
### Display
|
### Display
|
||||||
*Note:* You can create as many displays as you want, but all of them will show the same currently.
|
*Note: You can create as many displays as you want, but all of them will show the same currently.*
|
||||||
|
|
||||||
To create a display, make a 5 wide 4 high wall of item frames, then put the maps 0-19 on them starting from the top left and going downwards. You can give the maps with this command:
|
To create a display, make a 5 wide 4 high wall of item frames, then put the maps 0-19 on them starting from the top left and going downwards. You can give the maps with this command:
|
||||||
|
|
||||||
|
|
|
@ -1,298 +0,0 @@
|
||||||
package sznp.virtualcomputer;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.val;
|
|
||||||
import lombok.var;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.virtualbox_6_1.*;
|
|
||||||
import sznp.virtualcomputer.events.MachineEventHandler;
|
|
||||||
import sznp.virtualcomputer.events.VBoxEventHandler;
|
|
||||||
import sznp.virtualcomputer.renderer.GPURenderer;
|
|
||||||
import sznp.virtualcomputer.renderer.MCFrameBuffer;
|
|
||||||
import sznp.virtualcomputer.util.COMUtils;
|
|
||||||
import sznp.virtualcomputer.util.Scancode;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public final class Computer {
|
|
||||||
@Getter
|
|
||||||
private static Computer instance;
|
|
||||||
|
|
||||||
private final PluginMain plugin;
|
|
||||||
private ISession session;
|
|
||||||
private IVirtualBox vbox;
|
|
||||||
private IMachine machine;
|
|
||||||
private MachineEventHandler handler;
|
|
||||||
private IEventListener listener;
|
|
||||||
private VirtualBoxManager manager;
|
|
||||||
private MCFrameBuffer framebuffer;
|
|
||||||
|
|
||||||
@java.beans.ConstructorProperties({"plugin"})
|
|
||||||
public Computer(PluginMain plugin, VirtualBoxManager manager, IVirtualBox vbox) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
this.manager = manager;
|
|
||||||
session = manager.getSessionObject();
|
|
||||||
this.vbox = vbox;
|
|
||||||
if (instance != null) throw new IllegalStateException("A computer already exists!");
|
|
||||||
instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start(CommandSender sender, int index) {// TODO: Add touchscreen support (#2)
|
|
||||||
if (session.getState() == SessionState.Locked) {
|
|
||||||
sender.sendMessage("§cThe machine is already running!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
|
||||||
if (index < 0 || vbox.getMachines().size() <= index) {
|
|
||||||
sendMessage(sender, "§cMachine not found!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
sendMessage(sender, "§eStarting computer...");
|
|
||||||
machine = vbox.getMachines().get(index);
|
|
||||||
session.setName("minecraft");
|
|
||||||
// machine.launchVMProcess(session, "headless", "").waitForCompletion(10000); - This creates a *process*, we don't want that anymore
|
|
||||||
synchronized (session) {
|
|
||||||
machine.lockMachine(session, LockType.VM); // We want the machine inside *our* process <-- Need the VM type to have console access
|
|
||||||
}
|
|
||||||
VBoxEventHandler.getInstance().setup(machine.getId(), sender); //TODO: Sometimes null
|
|
||||||
} catch (VBoxException e) {
|
|
||||||
if (e.getResultCode() == 0x80070005) { //lockMachine: "The object functionality is limited"
|
|
||||||
sendMessage(sender, "§6Cannot start computer, the machine may be inaccessible");
|
|
||||||
sendMessage(sender, "§6Make sure that the server is running as root (sudo)");
|
|
||||||
//TODO: If we have VirtualBox open, it won't close the server's port
|
|
||||||
//TODO: "The object in question already exists." on second start
|
|
||||||
//machine.launchVMProcess(session, "headless", "").waitForCompletion(10000); //No privileges, start the 'old' way
|
|
||||||
//session.getConsole().getDisplay().attachFramebuffer(0L, new IFramebuffer(new COMFrameBuffer(session.getConsole().getDisplay(), false)));
|
|
||||||
//sendMessage(sender, "§6Computer started with slower screen. Run as root to use a faster method.");
|
|
||||||
} else {
|
|
||||||
sendMessage(sender, "§cFailed to start computer: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void List(CommandSender sender) {
|
|
||||||
val machines = vbox.getMachines();
|
|
||||||
for (int i = 0; i < machines.size(); i++) {
|
|
||||||
val m = machines.get(i);
|
|
||||||
sender.sendMessage("[" + i + "] " + m.getName() + " - " + m.getState());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets called when the machine is locked after {@link #Start(CommandSender, int)}
|
|
||||||
*
|
|
||||||
* @param sender The sender which started the machine
|
|
||||||
*/
|
|
||||||
public void onLock(CommandSender sender) {
|
|
||||||
machine = session.getMachine(); // This is the Machine object we can work with
|
|
||||||
final IConsole console = session.getConsole();
|
|
||||||
if (handler != null)
|
|
||||||
handler.disable();
|
|
||||||
handler = new MachineEventHandler(Computer.this, sender);
|
|
||||||
listener = handler.registerTo(console.getEventSource());
|
|
||||||
IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2
|
|
||||||
handler.setProgress(progress);
|
|
||||||
handler.registerTo(progress.getEventSource()); //TODO: Show progress bar some way?
|
|
||||||
val fb = new MCFrameBuffer(console.getDisplay());
|
|
||||||
fb.start();
|
|
||||||
String fbid = console.getDisplay().attachFramebuffer(0L, COMUtils.gimmeAFramebuffer(fb));
|
|
||||||
fb.setId(fbid);
|
|
||||||
framebuffer = fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendMessage(@Nullable CommandSender sender, String message) {
|
|
||||||
if (sender != null)
|
|
||||||
sender.sendMessage(message);
|
|
||||||
plugin.getLogger().warning((sender == null ? "" : sender.getName() + ": ") + ChatColor.stripColor(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop(CommandSender sender) {
|
|
||||||
if (checkMachineNotRunning(sender)) {
|
|
||||||
if (session.getState().equals(SessionState.Locked)) {
|
|
||||||
onMachineStop(sender); //Needed for session reset
|
|
||||||
sendMessage(sender, "§eComputer was already off, released it.");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sendMessage(sender, "§eStopping computer...");
|
|
||||||
synchronized (session) {
|
|
||||||
session.getConsole().powerDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PowerButton(CommandSender sender, int index) {
|
|
||||||
sendMessage(sender, "§ePressing powerbutton...");
|
|
||||||
Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (session.getState() != SessionState.Locked || session.getMachine() == null) {
|
|
||||||
Start(sender, index);
|
|
||||||
} else {
|
|
||||||
synchronized (session) {
|
|
||||||
session.getConsole().powerButton();
|
|
||||||
}
|
|
||||||
sendMessage(sender, "§ePowerbutton pressed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset(CommandSender sender) {
|
|
||||||
if (checkMachineNotRunning(sender))
|
|
||||||
return;
|
|
||||||
sendMessage(sender, "§eResetting computer...");
|
|
||||||
synchronized (session) {
|
|
||||||
session.getConsole().reset();
|
|
||||||
}
|
|
||||||
sendMessage(sender, "§eComputer reset.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveState(CommandSender sender) {
|
|
||||||
if (checkMachineNotRunning(sender))
|
|
||||||
return;
|
|
||||||
sendMessage(sender, "§eSaving computer state...");
|
|
||||||
synchronized (session) {
|
|
||||||
session.getMachine().saveState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FixScreen(CommandSender sender, Boolean seamless) {
|
|
||||||
if (checkMachineNotRunning(sender))
|
|
||||||
return;
|
|
||||||
if (framebuffer == null) {
|
|
||||||
sender.sendMessage("§cFramebuffer is null...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
val lastUpdated = new Holder<Long>();
|
|
||||||
sendMessage(sender, "§eFixing screen...");
|
|
||||||
try {
|
|
||||||
synchronized (session) {
|
|
||||||
if (seamless == null)
|
|
||||||
session.getConsole().getDisplay().setVideoModeHint(0L,
|
|
||||||
true, false,
|
|
||||||
0, 0, 640L, 480L,
|
|
||||||
32L, false);
|
|
||||||
} //Last param: notify - send PnP notification - stops updates but not changes for some reason
|
|
||||||
Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, () -> {
|
|
||||||
synchronized (session) {
|
|
||||||
sendMessage(sender, "Needs host cursor: " + session.getConsole().getMouse().getNeedsHostCursor());
|
|
||||||
session.getConsole().getMouse().putMouseEventAbsolute(-1, -1, 0, 0, 0);
|
|
||||||
session.getConsole().getMouse().putMouseEvent(0, 0, 0, 0, 0); //Switch to relative mode
|
|
||||||
sendMessage(sender, "§eScreen fixed.");
|
|
||||||
}
|
|
||||||
}, 20);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkMachineNotRunning(@Nullable CommandSender sender) {
|
|
||||||
if (session.getState() != SessionState.Locked || machine.getState() != MachineState.Running) {
|
|
||||||
if (sender != null)
|
|
||||||
sender.sendMessage("§cMachine isn't running.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PressKey(CommandSender sender, String key, String stateorduration) {
|
|
||||||
if (checkMachineNotRunning(sender))
|
|
||||||
return;
|
|
||||||
int durationorstate;
|
|
||||||
if (stateorduration.length() == 0)
|
|
||||||
durationorstate = 0;
|
|
||||||
else if (stateorduration.equalsIgnoreCase("down"))
|
|
||||||
durationorstate = -1;
|
|
||||||
else if (stateorduration.equalsIgnoreCase("up"))
|
|
||||||
durationorstate = -2;
|
|
||||||
else
|
|
||||||
durationorstate = Short.parseShort(stateorduration);
|
|
||||||
int code = Scancode.getCode("sc_" + key.toLowerCase());
|
|
||||||
if (code == -1) {
|
|
||||||
sender.sendMessage("§cUnknown key: " + key);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Release key scan code concept taken from VirtualBox source code (KeyboardImpl.cpp:putCAD())
|
|
||||||
// +128
|
|
||||||
synchronized (session) {
|
|
||||||
if (durationorstate != -2)
|
|
||||||
session.getConsole().getKeyboard().putScancode(code);
|
|
||||||
Runnable sendrelease = () -> session.getConsole().getKeyboard().putScancodes(Lists.newArrayList(code + 128,
|
|
||||||
Scancode.sc_controlLeft.Code + 128, Scancode.sc_shiftLeft.Code + 128, Scancode.sc_altLeft.Code + 128));
|
|
||||||
if (durationorstate == 0 || durationorstate == -2)
|
|
||||||
sendrelease.run();
|
|
||||||
if (durationorstate > 0) {
|
|
||||||
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, sendrelease, durationorstate * 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs, boolean down) throws Exception {
|
|
||||||
if (checkMachineNotRunning(sender))
|
|
||||||
return;
|
|
||||||
int state = 0;
|
|
||||||
if (mbs.length() > 0 && down)
|
|
||||||
state = Arrays.stream(MouseButtonState.values()).filter(mousebs -> mousebs.name().equalsIgnoreCase(mbs))
|
|
||||||
.findAny().orElseThrow(() -> new Exception("Unknown mouse button")).value();
|
|
||||||
synchronized (session) {
|
|
||||||
session.getConsole().getMouse().putMouseEvent(x, y, z, w, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs) throws Exception {
|
|
||||||
if (checkMachineNotRunning(sender))
|
|
||||||
return;
|
|
||||||
UpdateMouse(sender, x, y, z, w, mbs, true);
|
|
||||||
UpdateMouse(sender, x, y, z, w, mbs, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMachineStart(CommandSender sender) {
|
|
||||||
sendMessage(sender, "§eComputer started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMachineStop(CommandSender sender) {
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
|
||||||
if (session.getState() == SessionState.Locked) {
|
|
||||||
synchronized (session) {
|
|
||||||
session.unlockMachine(); //Needs to be outside of the event handler
|
|
||||||
}
|
|
||||||
handler = null;
|
|
||||||
machine = null;
|
|
||||||
session = manager.getSessionObject();
|
|
||||||
sendMessage(sender, "§eComputer powered off."); //This block runs later
|
|
||||||
}
|
|
||||||
});
|
|
||||||
GPURenderer.update(new byte[1], 0, 0, 0, 0, 640, 480); //Black screen
|
|
||||||
stopEvents();
|
|
||||||
MouseLockerPlayerListener.computerStop();
|
|
||||||
if (framebuffer != null)
|
|
||||||
framebuffer.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopEvents() {
|
|
||||||
/*if(session!=null && listener!=null)
|
|
||||||
session.getConsole().getEventSource().unregisterListener(listener);*/
|
|
||||||
if (listener != null)
|
|
||||||
handler.disable();
|
|
||||||
listener = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pluginDisable(CommandSender ccs) {
|
|
||||||
stopEvents();
|
|
||||||
if (framebuffer != null)
|
|
||||||
framebuffer.stop();
|
|
||||||
if (session.getState() == SessionState.Locked) {
|
|
||||||
if (session.getMachine().getState().equals(MachineState.Running)) {
|
|
||||||
ccs.sendMessage("§aSaving machine state...");
|
|
||||||
session.getMachine().saveState().waitForCompletion(10000);
|
|
||||||
}
|
|
||||||
session.unlockMachine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
package sznp.virtualcomputer.renderer;
|
|
||||||
|
|
||||||
import com.sun.jna.Pointer;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
import org.virtualbox_6_1.Holder;
|
|
||||||
import org.virtualbox_6_1.IDisplay;
|
|
||||||
import org.virtualbox_6_1.IDisplaySourceBitmap;
|
|
||||||
import org.virtualbox_6_1.VBoxException;
|
|
||||||
import sznp.virtualcomputer.PluginMain;
|
|
||||||
import sznp.virtualcomputer.util.COMUtils;
|
|
||||||
import sznp.virtualcomputer.util.IMCFrameBuffer;
|
|
||||||
import sznp.virtualcomputer.util.Timing;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class MCFrameBuffer implements IMCFrameBuffer {
|
|
||||||
private final IDisplay display;
|
|
||||||
private final Holder<IDisplaySourceBitmap> holder = new Holder<>();
|
|
||||||
private BukkitTask tt;
|
|
||||||
private Pointer pointer;
|
|
||||||
private int width;
|
|
||||||
private int height;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private String id;
|
|
||||||
private final AtomicBoolean shouldUpdate = new AtomicBoolean();
|
|
||||||
private boolean running;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) {
|
|
||||||
if (tt != null)
|
|
||||||
tt.cancel();
|
|
||||||
tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
|
||||||
synchronized (this) { //If a change occurs twice, then wait for it
|
|
||||||
try {
|
|
||||||
//System.out.println("Change: " + xOrigin + " " + yOrigin + " - " + width + " " + height);
|
|
||||||
COMUtils.querySourceBitmap(display, holder);
|
|
||||||
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];
|
|
||||||
COMUtils.queryBitmapInfo(holder.value, ptr, w, h, bpp, bpl, pf);
|
|
||||||
if (PluginMain.direct) {
|
|
||||||
pointer = new Pointer(ptr[0]);
|
|
||||||
this.width = (int) w[0];
|
|
||||||
this.height = (int) h[0];
|
|
||||||
//System.out.println("Actual sizes: " + this.width + " " + this.height);
|
|
||||||
/*if (this.width > 1024 || this.height > 768)
|
|
||||||
return;*/
|
|
||||||
GPURenderer.update(pointer.getByteArray(0L, (int) (w[0] * h[0] * 4)), (int) w[0], (int) h[0], 0, 0, this.width, this.height);
|
|
||||||
} else {
|
|
||||||
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
|
|
||||||
if (width * height > 640 * 480)
|
|
||||||
PluginMain.allpixels.limit(640 * 480 * 4);
|
|
||||||
else
|
|
||||||
PluginMain.allpixels.limit((int) (width * height * 4));
|
|
||||||
}
|
|
||||||
} 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();
|
|
||||||
} /*finally {
|
|
||||||
System.out.println("Change finished");
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyUpdate(long x, long y, long width, long height) {
|
|
||||||
/*if (this.width > 1024 || this.height > 768)
|
|
||||||
return;*/
|
|
||||||
if(shouldUpdate.get())
|
|
||||||
return; //Don't wait for lock, ignore update since we're updating everything anyway - TODO: Not always
|
|
||||||
synchronized (this) {
|
|
||||||
shouldUpdate.set(true);
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyUpdateImage(long x, long y, long width, long height, byte[] image) {
|
|
||||||
System.out.println("Update image!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
running = true;
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
|
||||||
try {
|
|
||||||
while (running) {
|
|
||||||
synchronized (this) {
|
|
||||||
while (!shouldUpdate.get())
|
|
||||||
wait(1000);
|
|
||||||
if (pointer == null) {
|
|
||||||
System.out.println("Screen pointer is null");
|
|
||||||
shouldUpdate.set(false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!running) return;
|
|
||||||
//System.out.println("Update: " + x + " " + y + " - " + width + " " + height);
|
|
||||||
Timing t = new Timing(); //TODO: Add support for only sending changed fragments
|
|
||||||
GPURenderer.update(pointer.getByteArray(0L, this.width * this.height * 4), this.width, this.height, (int) 0, (int) 0, (int) width, (int) height);
|
|
||||||
if (t.elapsedMS() > 60) //Typically 1ms max
|
|
||||||
System.out.println("Update took " + t.elapsedMS() + "ms");
|
|
||||||
shouldUpdate.set(false);
|
|
||||||
/*else
|
|
||||||
System.out.println("Update finished");*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
synchronized (this) {
|
|
||||||
running = false;
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
package sznp.virtualcomputer.util;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.invoke.VarHandle;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class Utils {
|
|
||||||
/**
|
|
||||||
* Adds the specified path to the java library path
|
|
||||||
*
|
|
||||||
* @param pathToAdd the path to add
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static void addLibraryPath(String pathToAdd) throws Exception {
|
|
||||||
try {
|
|
||||||
addLibraryPathOld(pathToAdd);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
addLibraryPathNew(pathToAdd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addLibraryPathOld(String pathToAdd) throws Exception {
|
|
||||||
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
|
|
||||||
usrPathsField.setAccessible(true);
|
|
||||||
|
|
||||||
// get array of paths
|
|
||||||
final String[] paths = (String[]) usrPathsField.get(null);
|
|
||||||
|
|
||||||
// check if the path to add is already present
|
|
||||||
for (String path : paths) {
|
|
||||||
if (path.equals(pathToAdd)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the new path
|
|
||||||
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
|
|
||||||
newPaths[newPaths.length - 1] = pathToAdd;
|
|
||||||
usrPathsField.set(null, newPaths);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addLibraryPathNew(String pathToAdd) throws Exception {
|
|
||||||
MethodHandles.Lookup cl = MethodHandles.privateLookupIn(ClassLoader.class, MethodHandles.lookup());
|
|
||||||
VarHandle sys_paths = cl.findStaticVarHandle(ClassLoader.class, "sys_paths", String[].class);
|
|
||||||
final String[] paths = (String[]) sys_paths.get();
|
|
||||||
|
|
||||||
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
|
|
||||||
newPaths[newPaths.length - 1] = pathToAdd;
|
|
||||||
sys_paths.set((Object) newPaths);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
computer {
|
|
||||||
start {
|
|
||||||
index brigadier:integer;
|
|
||||||
}
|
|
||||||
on {
|
|
||||||
index brigadier:integer;
|
|
||||||
}
|
|
||||||
list;
|
|
||||||
stop;
|
|
||||||
off;
|
|
||||||
shutdown;
|
|
||||||
kill;
|
|
||||||
powerbutton;
|
|
||||||
reset;
|
|
||||||
restart;
|
|
||||||
fix;
|
|
||||||
fixscreen;
|
|
||||||
key {
|
|
||||||
key brigadier:string single_word;
|
|
||||||
}
|
|
||||||
press {
|
|
||||||
key brigadier:string single_word;
|
|
||||||
}
|
|
||||||
mouse {
|
|
||||||
button brigadier:string single_word;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
key;
|
|
||||||
mouse;
|
|
||||||
}
|
|
||||||
show {
|
|
||||||
key;
|
|
||||||
mouse;
|
|
||||||
}
|
|
||||||
}
|
|
20
VirtualComputer/.classpath
Normal file
20
VirtualComputer/.classpath
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
|
</classpath>
|
23
VirtualComputer/.project
Normal file
23
VirtualComputer/.project
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>VirtualComputer</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
13
VirtualComputer/.settings/org.eclipse.jdt.core.prefs
Normal file
13
VirtualComputer/.settings/org.eclipse.jdt.core.prefs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
|
org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
|
144
VirtualComputer/dependency-reduced-pom.xml
Normal file
144
VirtualComputer/dependency-reduced-pom.xml
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>io.github.NorbiPeti</groupId>
|
||||||
|
<artifactId>VirtualComputer</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-g</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.4.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration />
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</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>
|
||||||
|
<repository>
|
||||||
|
<id>spigot-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>repo</id>
|
||||||
|
<url>file://${basedir}/repo</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.12-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>bungeecord-chat</artifactId>
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.virtualbox</groupId>
|
||||||
|
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||||
|
<version>6.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>craftbukkit</artifactId>
|
||||||
|
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>VirtualComputer-Core</artifactId>
|
|
||||||
<version>2.1-SNAPSHOT</version>
|
|
||||||
<parent>
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
<groupId>io.github.NorbiPeti</groupId>
|
||||||
<artifactId>VirtualComputer</artifactId>
|
<artifactId>VirtualComputer</artifactId>
|
||||||
<version>2.1-SNAPSHOT</version>
|
<version>2.0-SNAPSHOT</version>
|
||||||
</parent>
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>VirtualComputer</finalName>
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
@ -25,7 +20,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.2.4</version>
|
<version>2.4.2</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
|
@ -39,36 +34,65 @@
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spigot-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>repo</id>
|
||||||
|
<url>file://${basedir}/repo</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency> <!-- This has the least additional (platform-dependent) code -->
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.12-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.virtualbox</groupId>
|
||||||
|
<artifactId>VirtualBox</artifactId>
|
||||||
|
<version>6.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
<groupId>org.virtualbox</groupId>
|
<groupId>org.virtualbox</groupId>
|
||||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||||
<version>6.1</version>
|
<version>6.0</version>
|
||||||
|
</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 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.java.dev.jna</groupId>
|
||||||
|
<artifactId>jna</artifactId>
|
||||||
|
<version>4.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-ffi -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.jnr</groupId>
|
||||||
|
<artifactId>jnr-ffi</artifactId>
|
||||||
|
<version>2.1.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.aparapi</groupId>
|
<groupId>com.aparapi</groupId>
|
||||||
<artifactId>aparapi</artifactId>
|
<artifactId>aparapi</artifactId>
|
||||||
<version>1.10.0</version>
|
<version>1.10.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- <dependency>
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
|
||||||
<artifactId>VirtualComputer-XPCOM</artifactId>
|
|
||||||
<version>2.1-SNAPSHOT</version>
|
|
||||||
</dependency> -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>VirtualComputer-MSCOM</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>2.1-SNAPSHOT</version>
|
<version>1.16.16</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- <dependency>
|
<dependency> <!-- javax.annotations.Nullable -->
|
||||||
<groupId>me.lucko</groupId>
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
<artifactId>commodore</artifactId>
|
<artifactId>jsr305</artifactId>
|
||||||
<version>1.8</version>
|
<version>3.0.0</version>
|
||||||
</dependency> -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.PandacubeFr</groupId>
|
|
||||||
<artifactId>commodore</artifactId>
|
|
||||||
<version>patch-custom-suggests-SNAPSHOT</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<profiles>
|
<profiles>
|
||||||
|
@ -88,26 +112,8 @@
|
||||||
<artifactSet>
|
<artifactSet>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>org.virtualbox:VirtualBox-MSCOM</exclude>
|
<exclude>org.virtualbox:VirtualBox-MSCOM</exclude>
|
||||||
<exclude>io.github.NorbiPeti:VirtualComputer-MSCOM</exclude>
|
|
||||||
</excludes>
|
</excludes>
|
||||||
</artifactSet>
|
</artifactSet>
|
||||||
<!-- <minimizeJar>true</minimizeJar> -->
|
|
||||||
<filters>
|
|
||||||
<filter>
|
|
||||||
<artifact>io.github.NorbiPeti:VirtualComputer-XPCOM</artifact>
|
|
||||||
<includes>
|
|
||||||
<include>**
|
|
||||||
</include> <!-- Don't delete org.mozilla.interfaces.internal when minimizing -->
|
|
||||||
</includes>
|
|
||||||
</filter>
|
|
||||||
<filter>
|
|
||||||
<artifact>com.github.jnr:jnr-ffi</artifact>
|
|
||||||
<includes>
|
|
||||||
<include>**
|
|
||||||
</include> <!-- Don't delete org.mozilla.interfaces.internal when minimizing -->
|
|
||||||
</includes>
|
|
||||||
</filter>
|
|
||||||
</filters>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
@ -131,7 +137,6 @@
|
||||||
<artifactSet>
|
<artifactSet>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>org.virtualbox:VirtualBox</exclude>
|
<exclude>org.virtualbox:VirtualBox</exclude>
|
||||||
<exclude>io.github.NorbiPeti:VirtualComputer-XPCOM</exclude>
|
|
||||||
</excludes>
|
</excludes>
|
||||||
</artifactSet>
|
</artifactSet>
|
||||||
</configuration>
|
</configuration>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<metadata>
|
||||||
|
<groupId>org.virtualbox</groupId>
|
||||||
|
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||||
|
<versioning>
|
||||||
|
<release>6.0</release>
|
||||||
|
<versions>
|
||||||
|
<version>6.0</version>
|
||||||
|
</versions>
|
||||||
|
<lastUpdated>20190405225845</lastUpdated>
|
||||||
|
</versioning>
|
||||||
|
</metadata>
|
Binary file not shown.
Binary file not shown.
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.virtualbox</groupId>
|
<groupId>org.virtualbox</groupId>
|
||||||
<artifactId>VirtualBox</artifactId>
|
<artifactId>VirtualBox</artifactId>
|
||||||
<version>6.1</version>
|
<version>5.1</version>
|
||||||
<description>POM was created from install:install-file</description>
|
<description>POM was created from install:install-file</description>
|
||||||
</project>
|
</project>
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.virtualbox</groupId>
|
<groupId>org.virtualbox</groupId>
|
||||||
<artifactId>VirtualBox-JWS</artifactId>
|
<artifactId>VirtualBox</artifactId>
|
||||||
<version>6.1</version>
|
<version>5.2</version>
|
||||||
<description>POM was created from install:install-file</description>
|
<description>POM was created from install:install-file</description>
|
||||||
</project>
|
</project>
|
|
@ -3,13 +3,12 @@
|
||||||
<groupId>org.virtualbox</groupId>
|
<groupId>org.virtualbox</groupId>
|
||||||
<artifactId>VirtualBox</artifactId>
|
<artifactId>VirtualBox</artifactId>
|
||||||
<versioning>
|
<versioning>
|
||||||
<release>6.1</release>
|
<release>6.0</release>
|
||||||
<versions>
|
<versions>
|
||||||
<version>5.1</version>
|
<version>5.1</version>
|
||||||
<version>5.2</version>
|
<version>5.2</version>
|
||||||
<version>6.0</version>
|
<version>6.0</version>
|
||||||
<version>6.1</version>
|
|
||||||
</versions>
|
</versions>
|
||||||
<lastUpdated>20200811171440</lastUpdated>
|
<lastUpdated>20181221211412</lastUpdated>
|
||||||
</versioning>
|
</versioning>
|
||||||
</metadata>
|
</metadata>
|
|
@ -1,31 +1,13 @@
|
||||||
package sznp.virtualcomputer;
|
package sznp.virtualcomputer;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
|
||||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
|
||||||
import com.mojang.brigadier.tree.CommandNode;
|
|
||||||
import lombok.val;
|
|
||||||
import me.lucko.commodore.Commodore;
|
|
||||||
import me.lucko.commodore.CommodoreProvider;
|
|
||||||
import me.lucko.commodore.file.CommodoreFileFormat;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.TabCompleter;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.virtualbox_6_1.MouseButtonState;
|
import org.virtualbox_6_0.VBoxException;
|
||||||
import org.virtualbox_6_1.VBoxException;
|
|
||||||
import sznp.virtualcomputer.util.Scancode;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
public class Commands implements CommandExecutor {
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Commands implements CommandExecutor, TabCompleter {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||||
|
@ -43,9 +25,6 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||||
}
|
}
|
||||||
Computer.getInstance().Start(sender, c);
|
Computer.getInstance().Start(sender, c);
|
||||||
break;
|
break;
|
||||||
case "list":
|
|
||||||
Computer.getInstance().List(sender);
|
|
||||||
break;
|
|
||||||
case "stop":
|
case "stop":
|
||||||
case "poweroff":
|
case "poweroff":
|
||||||
case "off":
|
case "off":
|
||||||
|
@ -67,16 +46,9 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||||
case "restart":
|
case "restart":
|
||||||
Computer.getInstance().Reset(sender);
|
Computer.getInstance().Reset(sender);
|
||||||
break;
|
break;
|
||||||
case "save":
|
|
||||||
case "savestate":
|
|
||||||
Computer.getInstance().SaveState(sender);
|
|
||||||
break;
|
|
||||||
case "fix":
|
case "fix":
|
||||||
case "fixscreen":
|
case "fixscreen":
|
||||||
Boolean seamless;
|
Computer.getInstance().FixScreen(sender);
|
||||||
if (args.length < 2) seamless = null;
|
|
||||||
else seamless = args[1].equalsIgnoreCase("true");
|
|
||||||
Computer.getInstance().FixScreen(sender, seamless);
|
|
||||||
break;
|
break;
|
||||||
case "key":
|
case "key":
|
||||||
case "press":
|
case "press":
|
||||||
|
@ -110,9 +82,11 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||||
showusage = false;
|
showusage = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (VBoxException e) {
|
}
|
||||||
|
catch (VBoxException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (Exception ignored) { //It will show the usage here
|
}
|
||||||
|
catch (Exception ignored) { //It will show the usage here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (showusage) {
|
if (showusage) {
|
||||||
|
@ -157,7 +131,7 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
MouseLockerPlayerListener.LockedSpeed = Float.parseFloat(args[2]);
|
MouseLockerPlayerListener.LockedSpeed = Float.parseFloat(args[2]);
|
||||||
} catch (NumberFormatException e) {
|
} catch(NumberFormatException e) {
|
||||||
sender.sendMessage("§cThe speed must be a number.");
|
sender.sendMessage("§cThe speed must be a number.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -169,49 +143,6 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean tabSetup = true;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
|
||||||
if (CommodoreProvider.isSupported() && tabSetup) {
|
|
||||||
tabSetup = false;
|
|
||||||
new Object() {
|
|
||||||
private void setup(Command command) {
|
|
||||||
val com = CommodoreProvider.getCommodore(PluginMain.Instance);
|
|
||||||
try {
|
|
||||||
val node = CommodoreFileFormat.parse(PluginMain.Instance.getResource("computer.commodore"));
|
|
||||||
CommandNode<Object> arg = RequiredArgumentBuilder.argument("index", IntegerArgumentType.integer()).build();
|
|
||||||
replaceChildren(node.getChild("start"), arg);
|
|
||||||
replaceChildren(node.getChild("on"), arg);
|
|
||||||
arg = RequiredArgumentBuilder.argument("key", StringArgumentType.word())
|
|
||||||
.suggests((context, builder) -> {
|
|
||||||
Arrays.stream(Scancode.values()).map(Scancode::name)
|
|
||||||
.map(name -> name.replace("sc_", "")).forEach(builder::suggest);
|
|
||||||
return builder.buildFuture();
|
|
||||||
}).build();
|
|
||||||
replaceChildren(node.getChild("key"), arg);
|
|
||||||
replaceChildren(node.getChild("press"), arg);
|
|
||||||
arg = RequiredArgumentBuilder.argument("button", StringArgumentType.word())
|
|
||||||
.suggests((context, builder) -> {
|
|
||||||
Arrays.stream(MouseButtonState.values()).map(MouseButtonState::name).forEach(builder::suggest);
|
|
||||||
return builder.buildFuture();
|
|
||||||
}).build();
|
|
||||||
replaceChildren(node.getChild("mouse"), arg);
|
|
||||||
com.register(command, node);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void replaceChildren(CommandNode<Object> target, CommandNode<Object> node) {
|
|
||||||
target.getChildren().clear();
|
|
||||||
target.addChild(node);
|
|
||||||
}
|
|
||||||
}.setup(command);
|
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the 2nd parameter
|
* Checks the 2nd parameter
|
||||||
*
|
*
|
235
VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java
Normal file
235
VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
package sznp.virtualcomputer;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.virtualbox_6_0.*;
|
||||||
|
import sznp.virtualcomputer.events.MachineEventHandler;
|
||||||
|
import sznp.virtualcomputer.events.VBoxEventHandler;
|
||||||
|
import sznp.virtualcomputer.renderer.GPURenderer;
|
||||||
|
import sznp.virtualcomputer.renderer.MCFrameBuffer;
|
||||||
|
import sznp.virtualcomputer.util.Scancode;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public final class Computer {
|
||||||
|
@Getter
|
||||||
|
private static Computer instance;
|
||||||
|
|
||||||
|
private final PluginMain plugin;
|
||||||
|
private ISession session;
|
||||||
|
private IVirtualBox vbox;
|
||||||
|
private IMachine machine;
|
||||||
|
private MachineEventHandler handler;
|
||||||
|
private IEventListener listener;
|
||||||
|
private VirtualBoxManager manager;
|
||||||
|
|
||||||
|
@java.beans.ConstructorProperties({"plugin"})
|
||||||
|
public Computer(PluginMain plugin, VirtualBoxManager manager, IVirtualBox vbox) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.manager = manager;
|
||||||
|
session = manager.getSessionObject();
|
||||||
|
this.vbox = vbox;
|
||||||
|
if (instance != null) throw new IllegalStateException("A computer already exists!");
|
||||||
|
instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start(CommandSender sender, int index) {// TODO: Add touchscreen support (#2)
|
||||||
|
if (session.getState() == SessionState.Locked) {
|
||||||
|
sender.sendMessage("§cThe machine is already running!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
|
if (vbox.getMachines().size() <= index) {
|
||||||
|
sendMessage(sender, "§cMachine not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
sendMessage(sender, "§eStarting computer...");
|
||||||
|
machine = vbox.getMachines().get(index);
|
||||||
|
session.setName("minecraft");
|
||||||
|
// machine.launchVMProcess(session, "headless", "").waitForCompletion(10000); - This creates a *process*, we don't want that anymore
|
||||||
|
machine.lockMachine(session, LockType.VM); // We want the machine inside *our* process <-- Need the VM type to have console access
|
||||||
|
VBoxEventHandler.getInstance().setup(machine.getId(), sender); //TODO: Sometimes null
|
||||||
|
} catch (VBoxException e) {
|
||||||
|
if (e.getResultCode() == 0x80070005) { //lockMachine: "The object functionality is limited"
|
||||||
|
sendMessage(sender, "§6Cannot start computer, the machine may be inaccessible");
|
||||||
|
sendMessage(sender, "§6Make sure that the server is running as root (sudo)");
|
||||||
|
//TODO: If we have VirtualBox open, it won't close the server's port
|
||||||
|
//TODO: "The object in question already exists." on second start
|
||||||
|
//machine.launchVMProcess(session, "headless", "").waitForCompletion(10000); //No privileges, start the 'old' way
|
||||||
|
//session.getConsole().getDisplay().attachFramebuffer(0L, new IFramebuffer(new MCFrameBuffer(session.getConsole().getDisplay(), false)));
|
||||||
|
//sendMessage(sender, "§6Computer started with slower screen. Run as root to use a faster method.");
|
||||||
|
} else {
|
||||||
|
sendMessage(sender, "§cFailed to start computer: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets called when the machine is locked after {@link #Start(CommandSender, int)}
|
||||||
|
*
|
||||||
|
* @param sender The sender which started the machine
|
||||||
|
*/
|
||||||
|
public void onLock(CommandSender sender) {
|
||||||
|
machine = session.getMachine(); // This is the Machine object we can work with
|
||||||
|
final IConsole console = session.getConsole();
|
||||||
|
if (handler != null)
|
||||||
|
handler.disable();
|
||||||
|
handler = new MachineEventHandler(Computer.this, sender);
|
||||||
|
listener = handler.registerTo(console.getEventSource());
|
||||||
|
IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2
|
||||||
|
handler.setProgress(progress);
|
||||||
|
handler.registerTo(progress.getEventSource()); //TODO: Show progress bar some way?
|
||||||
|
console.getDisplay().attachFramebuffer(0L,
|
||||||
|
new IFramebuffer(new MCFrameBuffer(console.getDisplay(), true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMessage(@Nullable CommandSender sender, String message) {
|
||||||
|
if (sender != null)
|
||||||
|
sender.sendMessage(message);
|
||||||
|
plugin.getLogger().warning((sender == null ? "" : sender.getName() + ": ") + ChatColor.stripColor(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop(CommandSender sender) {
|
||||||
|
if (checkMachineNotRunning(sender)) {
|
||||||
|
if (session.getState().equals(SessionState.Locked)) {
|
||||||
|
onMachineStop(sender); //Needed for session reset
|
||||||
|
sendMessage(sender, "§eComputer was already off, released it.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendMessage(sender, "§eStopping computer...");
|
||||||
|
session.getConsole().powerDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PowerButton(CommandSender sender, int index) {
|
||||||
|
sendMessage(sender, "§ePressing powerbutton...");
|
||||||
|
Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (session.getState() != SessionState.Locked || session.getMachine() == null) {
|
||||||
|
Start(sender, index);
|
||||||
|
} else {
|
||||||
|
session.getConsole().powerButton();
|
||||||
|
sendMessage(sender, "§ePowerbutton pressed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset(CommandSender sender) {
|
||||||
|
if (checkMachineNotRunning(sender))
|
||||||
|
return;
|
||||||
|
sendMessage(sender, "§eResetting computer...");
|
||||||
|
session.getConsole().reset();
|
||||||
|
sendMessage(sender, "§eComputer reset.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FixScreen(CommandSender sender) {
|
||||||
|
if (checkMachineNotRunning(sender))
|
||||||
|
return;
|
||||||
|
sendMessage(sender, "§eFixing screen...");
|
||||||
|
session.getConsole().getDisplay().setSeamlessMode(false);
|
||||||
|
session.getConsole().getDisplay().setVideoModeHint(0L, true, false, 0, 0, 640L, 480L, 32L);
|
||||||
|
sendMessage(sender, "§eScreen fixed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkMachineNotRunning(@Nullable CommandSender sender) {
|
||||||
|
if (session.getState() != SessionState.Locked || machine.getState() != MachineState.Running) {
|
||||||
|
if (sender != null)
|
||||||
|
sender.sendMessage("§cMachine isn't running.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PressKey(CommandSender sender, String key, String stateorduration) {
|
||||||
|
if (checkMachineNotRunning(sender))
|
||||||
|
return;
|
||||||
|
int durationorstate;
|
||||||
|
if (stateorduration.length() == 0)
|
||||||
|
durationorstate = 0;
|
||||||
|
else if (stateorduration.equalsIgnoreCase("down"))
|
||||||
|
durationorstate = -1;
|
||||||
|
else if (stateorduration.equalsIgnoreCase("up"))
|
||||||
|
durationorstate = -2;
|
||||||
|
else
|
||||||
|
durationorstate = Short.parseShort(stateorduration);
|
||||||
|
int code = Scancode.getCode("sc_" + key.toLowerCase());
|
||||||
|
if (code == -1) {
|
||||||
|
sender.sendMessage("§cUnknown key: " + key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Release key scan code concept taken from VirtualBox source code (KeyboardImpl.cpp:putCAD())
|
||||||
|
// +128
|
||||||
|
if (durationorstate != -2)
|
||||||
|
session.getConsole().getKeyboard().putScancode(code);
|
||||||
|
Runnable sendrelease = () -> session.getConsole().getKeyboard().putScancodes(Lists.newArrayList(code + 128,
|
||||||
|
Scancode.sc_controlLeft.Code + 128, Scancode.sc_shiftLeft.Code + 128, Scancode.sc_altLeft.Code + 128));
|
||||||
|
if (durationorstate == 0 || durationorstate == -2)
|
||||||
|
sendrelease.run();
|
||||||
|
if (durationorstate > 0) {
|
||||||
|
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, sendrelease, durationorstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs, boolean down) throws Exception {
|
||||||
|
if (checkMachineNotRunning(sender))
|
||||||
|
return;
|
||||||
|
int state = 0;
|
||||||
|
if (mbs.length() > 0 && down)
|
||||||
|
state = Arrays.stream(MouseButtonState.values()).filter(mousebs -> mousebs.name().equalsIgnoreCase(mbs))
|
||||||
|
.findAny().orElseThrow(() -> new Exception("Unknown mouse button")).value();
|
||||||
|
session.getConsole().getMouse().putMouseEvent(x, y, z, w, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs) throws Exception {
|
||||||
|
if (checkMachineNotRunning(sender))
|
||||||
|
return;
|
||||||
|
UpdateMouse(sender, x, y, z, w, mbs, true);
|
||||||
|
UpdateMouse(sender, x, y, z, w, mbs, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onMachineStart(CommandSender sender) {
|
||||||
|
sendMessage(sender, "§eComputer started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onMachineStop(CommandSender sender) {
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
|
if (session.getState() == SessionState.Locked) {
|
||||||
|
session.unlockMachine(); //Needs to be outside of the event handler
|
||||||
|
handler = null;
|
||||||
|
machine = null;
|
||||||
|
session = manager.getSessionObject();
|
||||||
|
sendMessage(sender, "§eComputer powered off."); //This block runs later
|
||||||
|
}
|
||||||
|
});
|
||||||
|
GPURenderer.update(new byte[1], 0, 0, 0, 0, 640, 480); //Black screen
|
||||||
|
stopEvents();
|
||||||
|
MouseLockerPlayerListener.computerStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopEvents() {
|
||||||
|
/*if(session!=null && listener!=null)
|
||||||
|
session.getConsole().getEventSource().unregisterListener(listener);*/
|
||||||
|
if (listener != null)
|
||||||
|
handler.disable();
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pluginDisable(CommandSender ccs) {
|
||||||
|
stopEvents();
|
||||||
|
if (session.getState() == SessionState.Locked) {
|
||||||
|
if (session.getMachine().getState().equals(MachineState.Running)) {
|
||||||
|
ccs.sendMessage("§aSaving machine state...");
|
||||||
|
session.getMachine().saveState().waitForCompletion(10000);
|
||||||
|
}
|
||||||
|
session.unlockMachine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,13 @@ package sznp.virtualcomputer;
|
||||||
|
|
||||||
import jnr.ffi.LibraryLoader;
|
import jnr.ffi.LibraryLoader;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import net.sf.jni4net.Bridge;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
import org.virtualbox_6_1.IVirtualBox;
|
import org.virtualbox_6_0.IEventListener;
|
||||||
import org.virtualbox_6_1.VirtualBoxManager;
|
import org.virtualbox_6_0.IVirtualBox;
|
||||||
|
import org.virtualbox_6_0.VirtualBoxManager;
|
||||||
import sznp.virtualcomputer.events.VBoxEventHandler;
|
import sznp.virtualcomputer.events.VBoxEventHandler;
|
||||||
import sznp.virtualcomputer.renderer.BukkitRenderer;
|
import sznp.virtualcomputer.renderer.BukkitRenderer;
|
||||||
import sznp.virtualcomputer.renderer.GPURenderer;
|
import sznp.virtualcomputer.renderer.GPURenderer;
|
||||||
|
@ -26,7 +26,7 @@ public class PluginMain extends JavaPlugin {
|
||||||
private static final int MCX = 5;
|
private static final int MCX = 5;
|
||||||
private static final int MCY = 4;
|
private static final int MCY = 4;
|
||||||
private BukkitTask mousetask;
|
private BukkitTask mousetask;
|
||||||
private VBoxEventHandler listener;
|
private IEventListener listener;
|
||||||
|
|
||||||
public static PluginMain Instance;
|
public static PluginMain Instance;
|
||||||
//public static ByteBuffer allpixels = ByteBuffer.allocate(640 * 480 * 4); // It's set on each change
|
//public static ByteBuffer allpixels = ByteBuffer.allocate(640 * 480 * 4); // It's set on each change
|
||||||
|
@ -34,7 +34,7 @@ public class PluginMain extends JavaPlugin {
|
||||||
* Only used if {@link #direct} is false.
|
* Only used if {@link #direct} is false.
|
||||||
*/
|
*/
|
||||||
public static ByteBuffer allpixels; // It's set on each change
|
public static ByteBuffer allpixels; // It's set on each change
|
||||||
private static final ArrayList<IRenderer> renderers = new ArrayList<>();
|
private static ArrayList<IRenderer> renderers = new ArrayList<>();
|
||||||
/*
|
/*
|
||||||
* Only used if {@link #direct} is true.
|
* Only used if {@link #direct} is true.
|
||||||
*/
|
*/
|
||||||
|
@ -51,23 +51,14 @@ public class PluginMain extends JavaPlugin {
|
||||||
this.getCommand("computer").setExecutor(new Commands());
|
this.getCommand("computer").setExecutor(new Commands());
|
||||||
sendAll = getConfig().getBoolean("sendAll", true);
|
sendAll = getConfig().getBoolean("sendAll", true);
|
||||||
ccs.sendMessage("§bInitializing VirtualBox...");
|
ccs.sendMessage("§bInitializing VirtualBox...");
|
||||||
String osname = System.getProperty("os.name").toLowerCase();
|
String vbpath = System.getProperty("os.name").toLowerCase().contains("mac")
|
||||||
final boolean windows;
|
|
||||||
String vbpath;
|
|
||||||
{
|
|
||||||
boolean win = false;
|
|
||||||
vbpath = osname.contains("mac")
|
|
||||||
? "/Applications/VirtualBox.app/Contents/MacOS"
|
? "/Applications/VirtualBox.app/Contents/MacOS"
|
||||||
: (win = osname.contains("windows"))
|
|
||||||
? "C:\\Program Files\\Oracle\\VirtualBox"
|
|
||||||
: "/opt/virtualbox";
|
: "/opt/virtualbox";
|
||||||
windows = win;
|
|
||||||
}
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
Predicate<File> notGoodDir = ff -> !ff.isDirectory() || (!windows && Arrays.stream(ff.list()).noneMatch(s -> s.contains("xpcom")));
|
Predicate<File> notGoodDir= ff->!ff.isDirectory() || Arrays.stream(ff.list()).noneMatch(s -> s.contains("xpcom"));
|
||||||
if (notGoodDir.test(new File(vbpath)))
|
if (notGoodDir.test(new File(vbpath)))
|
||||||
vbpath = "/usr/lib/virtualbox";
|
vbpath = "/usr/lib/virtualbox";
|
||||||
if (notGoodDir.test(new File(vbpath)))
|
if(notGoodDir.test(new File(vbpath)))
|
||||||
error("Could not find VirtualBox! Download from https://www.virtualbox.org/wiki/Downloads");
|
error("Could not find VirtualBox! Download from https://www.virtualbox.org/wiki/Downloads");
|
||||||
if (System.getProperty("vbox.home") == null || System.getProperty("vbox.home").isEmpty())
|
if (System.getProperty("vbox.home") == null || System.getProperty("vbox.home").isEmpty())
|
||||||
System.setProperty("vbox.home", vbpath);
|
System.setProperty("vbox.home", vbpath);
|
||||||
|
@ -77,32 +68,11 @@ public class PluginMain extends JavaPlugin {
|
||||||
if (System.getProperty("java.library.path") == null || System.getProperty("java.library.path").isEmpty())
|
if (System.getProperty("java.library.path") == null || System.getProperty("java.library.path").isEmpty())
|
||||||
System.setProperty("java.library.path", vbpath);
|
System.setProperty("java.library.path", vbpath);
|
||||||
Utils.addLibraryPath(vbpath);
|
Utils.addLibraryPath(vbpath);
|
||||||
if (windows) {
|
|
||||||
ccs.sendMessage("§bExtracting Windows-specific libraries...");
|
|
||||||
final File[] libs = new File[]{
|
|
||||||
new File(getDataFolder(), "jni4net.n-0.8.9.0.dll"),
|
|
||||||
new File(getDataFolder(), "jni4net.n.w64.v40-0.8.9.0.dll"),
|
|
||||||
new File(getDataFolder(), "VirtualComputerWindows.j4n.dll"),
|
|
||||||
new File(getDataFolder(), "VirtualComputerWindows.dll"),
|
|
||||||
new File(getDataFolder(), "Interop.VirtualBox.dll")
|
|
||||||
};
|
|
||||||
|
|
||||||
for (final File lib : libs) {
|
|
||||||
if (!lib.exists()) {
|
|
||||||
JarUtils.extractFromJar(lib.getName(), lib.getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ccs.sendMessage("§bInitializing bridge...");
|
|
||||||
Bridge.init(getDataFolder().getAbsoluteFile());
|
|
||||||
Bridge.LoadAndRegisterAssemblyFrom(new File(getDataFolder(), "VirtualComputerWindows.j4n.dll"));
|
|
||||||
}
|
|
||||||
final VirtualBoxManager manager = VirtualBoxManager.createInstance(getDataFolder().getAbsolutePath());
|
final VirtualBoxManager manager = VirtualBoxManager.createInstance(getDataFolder().getAbsolutePath());
|
||||||
if (!windows) {
|
VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom"); //TODO: Test for MSCOM
|
||||||
VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom");
|
|
||||||
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());
|
||||||
new Computer(this, manager, vbox); //Saves itself
|
new Computer(this, manager, vbox); //Saves itself
|
||||||
ccs.sendMessage("§bLoading Screen...");
|
ccs.sendMessage("§bLoading Screen...");
|
||||||
try {
|
try {
|
||||||
|
@ -111,12 +81,12 @@ public class PluginMain extends JavaPlugin {
|
||||||
for (short j = 0; j < MCY; j++)
|
for (short j = 0; j < MCY; j++)
|
||||||
renderers.add(new GPURenderer((short) (j * 5 + i), Bukkit.getWorlds().get(0), i, j));
|
renderers.add(new GPURenderer((short) (j * 5 + i), Bukkit.getWorlds().get(0), i, j));
|
||||||
//pxc = LibraryLoader.create(PXCLib.class).search(getDataFolder().getAbsolutePath()).load("pxc");
|
//pxc = LibraryLoader.create(PXCLib.class).search(getDataFolder().getAbsolutePath()).load("pxc");
|
||||||
direct = true;
|
direct=true;
|
||||||
ccs.sendMessage("§bUsing Direct Renderer, all good");
|
ccs.sendMessage("§bUsing Direct Renderer, all good");
|
||||||
} catch (NoClassDefFoundError | Exception e) {
|
} catch (NoClassDefFoundError | Exception e) {
|
||||||
for (short i = 0; i < 20; i++)
|
for (short i = 0; i < 20; i++)
|
||||||
renderers.add(new BukkitRenderer(i, Bukkit.getWorlds().get(0), i * 128 * 128 * 4));
|
renderers.add(new BukkitRenderer(i, Bukkit.getWorlds().get(0), i * 128 * 128 * 4));
|
||||||
direct = false;
|
direct=false;
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
ccs.sendMessage("§6Compatibility error, using slower renderer");
|
ccs.sendMessage("§6Compatibility error, using slower renderer");
|
||||||
}
|
}
|
||||||
|
@ -134,9 +104,7 @@ public class PluginMain extends JavaPlugin {
|
||||||
private void error(String message) {
|
private void error(String message) {
|
||||||
getLogger().severe("A fatal error occured, disabling plugin!");
|
getLogger().severe("A fatal error occured, disabling plugin!");
|
||||||
Bukkit.getPluginManager().disablePlugin(this);
|
Bukkit.getPluginManager().disablePlugin(this);
|
||||||
val ex = new RuntimeException(message);
|
throw new RuntimeException(message);
|
||||||
ex.setStackTrace(new StackTraceElement[0]);
|
|
||||||
throw ex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fired when plugin is disabled
|
// Fired when plugin is disabled
|
||||||
|
@ -151,7 +119,7 @@ public class PluginMain extends JavaPlugin {
|
||||||
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)
|
||||||
}*/
|
}*/
|
||||||
if (listener != null)
|
if (listener != null)
|
||||||
listener.disable(); //The save progress wait locks with the event
|
((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.");
|
|
@ -2,11 +2,12 @@ package sznp.virtualcomputer.events;
|
||||||
|
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.virtualbox_6_1.IEvent;
|
import org.mozilla.interfaces.IEvent;
|
||||||
import org.virtualbox_6_1.IEventSource;
|
import org.mozilla.interfaces.IEventListener;
|
||||||
import org.virtualbox_6_1.VBoxEventType;
|
import org.virtualbox_6_0.IEventSource;
|
||||||
import sznp.virtualcomputer.util.COMUtils;
|
import org.virtualbox_6_0.VBoxEventType;
|
||||||
import sznp.virtualcomputer.util.IEventHandler;
|
import sznp.virtualcomputer.util.COMObjectBase;
|
||||||
|
import sznp.virtualcomputer.util.Utils;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -16,29 +17,31 @@ import java.util.Map;
|
||||||
/**
|
/**
|
||||||
* A Bukkit-like event system which calls the appropriate methods on an event.
|
* A Bukkit-like event system which calls the appropriate methods on an event.
|
||||||
*/
|
*/
|
||||||
public abstract class EventHandlerBase implements IEventHandler {
|
public abstract class EventHandlerBase extends COMObjectBase implements IEventListener {
|
||||||
/**
|
/**
|
||||||
* The events to listen for. It will only look for these handlers.
|
* The events to listen for. It will only look for these handlers.
|
||||||
*/
|
*/
|
||||||
private final Map<VBoxEventType, Class<? extends org.virtualbox_6_1.IEvent>> eventMap;
|
private final Map<VBoxEventType, Class<? extends org.virtualbox_6_0.IEvent>> eventMap;
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
|
|
||||||
protected EventHandlerBase(Map<VBoxEventType, Class<? extends org.virtualbox_6_1.IEvent>> eventMap) {
|
protected EventHandlerBase(Map<VBoxEventType, Class<? extends org.virtualbox_6_0.IEvent>> eventMap) {
|
||||||
|
//this.eventMap = eventMap.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().value(), Map.Entry::getValue));
|
||||||
this.eventMap = eventMap;
|
this.eventMap = eventMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void handleEvent(IEvent iEvent) {
|
public final void handleEvent(IEvent iEvent) {
|
||||||
|
//val cl=eventMap.get((int)iEvent.getType()); - We can afford to search through the events for this handler
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
val kv = eventMap.entrySet().stream().filter(e -> e.getKey().value() == iEvent.getType().value()).findAny();
|
val kv = eventMap.entrySet().stream().filter(e -> e.getKey().value() == iEvent.getType()).findAny();
|
||||||
if (!kv.isPresent()) return; //Event not supported
|
if (!kv.isPresent()) return; //Event not supported
|
||||||
val cl = kv.get().getValue();
|
val cl = kv.get().getValue();
|
||||||
for (Method method : getClass().getMethods()) {
|
for (Method method : getClass().getMethods()) {
|
||||||
if (method.isAnnotationPresent(org.bukkit.event.EventHandler.class)
|
if (method.isAnnotationPresent(org.bukkit.event.EventHandler.class)
|
||||||
&& method.getParameterCount() == 1 && method.getParameterTypes()[0] == cl) {
|
&& method.getParameterCount() == 1 && method.getParameterTypes()[0] == cl) {
|
||||||
try {
|
try {
|
||||||
method.invoke(this, COMUtils.getEvent(iEvent, cl));
|
method.invoke(this, Utils.getEvent(iEvent, cl));
|
||||||
return;
|
return;
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -50,8 +53,8 @@ public abstract class EventHandlerBase implements IEventHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends EventHandlerBase> org.virtualbox_6_1.IEventListener registerTo(IEventSource source) {
|
public <T extends EventHandlerBase> org.virtualbox_6_0.IEventListener registerTo(IEventSource source) {
|
||||||
return COMUtils.registerListener(source, this, new ArrayList<>(eventMap.keySet()));
|
return Utils.registerListener(source, this, new ArrayList<>(eventMap.keySet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disable() {
|
public void disable() {
|
|
@ -6,12 +6,11 @@ import lombok.experimental.var;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.virtualbox_6_1.IProgress;
|
import org.virtualbox_6_0.IProgress;
|
||||||
import org.virtualbox_6_1.IStateChangedEvent;
|
import org.virtualbox_6_0.IStateChangedEvent;
|
||||||
import org.virtualbox_6_1.VBoxEventType;
|
import org.virtualbox_6_0.VBoxEventType;
|
||||||
import sznp.virtualcomputer.Computer;
|
import sznp.virtualcomputer.Computer;
|
||||||
import sznp.virtualcomputer.PluginMain;
|
import sznp.virtualcomputer.PluginMain;
|
||||||
import sznp.virtualcomputer.util.COMUtils;
|
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -48,13 +47,8 @@ public class MachineEventHandler extends EventHandlerBase {
|
||||||
l.warning("Result code: " + Integer.toHexString(progress.getResultCode()));
|
l.warning("Result code: " + Integer.toHexString(progress.getResultCode()));
|
||||||
for (var info = progress.getErrorInfo(); info != null; info = info.getNext()) {
|
for (var info = progress.getErrorInfo(); info != null; info = info.getNext()) {
|
||||||
l.warning("----------------");
|
l.warning("----------------");
|
||||||
if (info.getResultCode() == 0x80004005 && info.getResultDetail() == 0xFFFFF88B)
|
|
||||||
l.warning("The server cannot access the VirtualBox driver, run it with sudo. Make sure to only run plugins you trust.");
|
|
||||||
else {
|
|
||||||
l.warning("VBox: " + info.getText());
|
l.warning("VBox: " + info.getText());
|
||||||
l.warning("Component: " + info.getComponent());
|
l.warning("Component: " + info.getComponent());
|
||||||
l.warning("Error codes: " + Integer.toHexString(info.getResultCode()) + " " + Integer.toHexString(info.getResultDetail()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
|
@ -4,9 +4,9 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.virtualbox_6_1.ISessionStateChangedEvent;
|
import org.virtualbox_6_0.ISessionStateChangedEvent;
|
||||||
import org.virtualbox_6_1.SessionState;
|
import org.virtualbox_6_0.SessionState;
|
||||||
import org.virtualbox_6_1.VBoxEventType;
|
import org.virtualbox_6_0.VBoxEventType;
|
||||||
import sznp.virtualcomputer.Computer;
|
import sznp.virtualcomputer.Computer;
|
||||||
|
|
||||||
public class VBoxEventHandler extends EventHandlerBase {
|
public class VBoxEventHandler extends EventHandlerBase {
|
|
@ -1,6 +1,6 @@
|
||||||
package sznp.virtualcomputer.renderer;
|
package sznp.virtualcomputer.renderer;
|
||||||
|
|
||||||
import lombok.val;
|
import net.minecraft.server.v1_12_R1.WorldMap;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.map.MapCanvas;
|
import org.bukkit.map.MapCanvas;
|
||||||
|
@ -12,20 +12,17 @@ import sznp.virtualcomputer.util.Timing;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
public class GPURenderer extends MapRenderer implements IRenderer {
|
public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
private byte[] buffer;
|
private byte[] buffer;
|
||||||
private final GPURendererInternal kernel;
|
private final GPURendererInternal kernel;
|
||||||
|
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 int changedX = 0, changedY = 0, changedWidth = 640, changedHeight = 480;
|
private int changedX = 0, changedY = 0, changedWidth = 640, changedHeight = 480;
|
||||||
private BiConsumer<Integer, Integer> flagDirty; //This way it's version independent, as long as it's named the same
|
|
||||||
private static ArrayList<GPURenderer> renderers = new ArrayList<>();
|
private static ArrayList<GPURenderer> renderers = new ArrayList<>();
|
||||||
private static Method flagDirtyMethod;
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -47,16 +44,7 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
this.mapy = mapy;
|
this.mapy = mapy;
|
||||||
Field field = map.getClass().getDeclaredField("worldMap");
|
Field field = map.getClass().getDeclaredField("worldMap");
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
val wmap = field.get(map);
|
wmap = (WorldMap) field.get(map);
|
||||||
if (flagDirtyMethod == null)
|
|
||||||
flagDirtyMethod = wmap.getClass().getMethod("flagDirty", int.class, int.class);
|
|
||||||
flagDirty = (x, y) -> {
|
|
||||||
try {
|
|
||||||
flagDirtyMethod.invoke(wmap, x, y);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
kernel = new GPURendererInternal(mapx, mapy, colors_);
|
kernel = new GPURendererInternal(mapx, mapy, colors_);
|
||||||
renderers.add(this);
|
renderers.add(this);
|
||||||
|
|
||||||
|
@ -91,16 +79,16 @@ public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
int yy = y + changedHeight >= 128 ? 127 : y + changedHeight;
|
int yy = y + changedHeight >= 128 ? 127 : y + changedHeight;
|
||||||
//System.out.println("local: ("+x+", "+y+") "+w+"x"+h);
|
//System.out.println("local: ("+x+", "+y+") "+w+"x"+h);
|
||||||
kernel.render(buffer);
|
kernel.render(buffer);
|
||||||
flagDirty.accept(x, y);
|
wmap.flagDirty(x, y);
|
||||||
flagDirty.accept(xx, yy); // Send the changes only
|
wmap.flagDirty(xx, yy); // Send the changes only
|
||||||
changedX = Integer.MAX_VALUE; //Finished rendering
|
changedX = Integer.MAX_VALUE; //Finished rendering
|
||||||
changedY = Integer.MAX_VALUE; //TODO: Render as soon as we receive new image
|
changedY = Integer.MAX_VALUE; //TODO: Render as soon as we receive new image
|
||||||
changedWidth = -1; //Finished rendering
|
changedWidth = -1; //Finished rendering
|
||||||
changedHeight = -1;
|
changedHeight = -1;
|
||||||
} else {
|
} else {
|
||||||
kernel.render(buffer);
|
kernel.render(buffer);
|
||||||
flagDirty.accept(0, 0);
|
wmap.flagDirty(0, 0);
|
||||||
flagDirty.accept(127, 127); // Send everything
|
wmap.flagDirty(127, 127); // Send everything
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
|
@ -0,0 +1,154 @@
|
||||||
|
package sznp.virtualcomputer.renderer;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
import org.mozilla.interfaces.IFramebuffer;
|
||||||
|
import org.mozilla.interfaces.IFramebufferOverlay;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class MCFrameBuffer implements IFramebuffer {
|
||||||
|
private IDisplay display;
|
||||||
|
private Holder<IDisplaySourceBitmap> holder = new Holder<>();
|
||||||
|
|
||||||
|
public MCFrameBuffer(IDisplay display, boolean VBoxDirect) { //TODO: Implement param
|
||||||
|
this.display = display;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public nsISupports queryInterface(String id) {
|
||||||
|
return Mozilla.queryInterface(this, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getBitsPerPixel() {
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getBytesPerLine() {
|
||||||
|
return 640L;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long[] getCapabilities(long[] arg0) {
|
||||||
|
try {
|
||||||
|
System.out.println("Capabilities queried");
|
||||||
|
System.out.println("Capabilities: " + Arrays.toString(arg0));
|
||||||
|
return new long[]{FramebufferCapabilities.UpdateImage.value()};
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new long[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getHeight() {
|
||||||
|
return 480;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getHeightReduction() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IFramebufferOverlay getOverlay() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPixelFormat() {
|
||||||
|
return BitmapFormat.BGRA.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getVisibleRegion(byte arg0, long arg1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getWidth() {
|
||||||
|
return 640;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getWinId() {
|
||||||
|
return 0; // Zero means no win id
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notify3DEvent(long arg0, byte[] arg1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private BukkitTask tt;
|
||||||
|
private Pointer pointer;
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) {
|
||||||
|
if (tt != null)
|
||||||
|
tt.cancel();
|
||||||
|
tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||||
|
try {
|
||||||
|
display.querySourceBitmap(0L, holder);
|
||||||
|
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);
|
||||||
|
if (PluginMain.direct) {
|
||||||
|
pointer = new Pointer(ptr[0]);
|
||||||
|
this.width = (int) w[0];
|
||||||
|
this.height = (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 {
|
||||||
|
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
|
||||||
|
if (width * height > 640 * 480)
|
||||||
|
PluginMain.allpixels.limit(640 * 480 * 4);
|
||||||
|
else
|
||||||
|
PluginMain.allpixels.limit((int) (width * height * 4));
|
||||||
|
}
|
||||||
|
} 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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyUpdate(long x, long y, long width, long height) {
|
||||||
|
Timing t = new Timing();
|
||||||
|
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
|
||||||
|
System.out.println("Update took " + t.elapsedMS() + "ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyUpdateImage(long arg0, long arg1, long arg2, long arg3, byte[] arg4) {
|
||||||
|
System.out.println("Update image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisibleRegion(byte arg0, long arg1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processVHWACommand(byte b, int i, boolean b1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean videoModeSupported(long arg0, long arg1, long arg2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
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 {
|
||||||
|
/**
|
||||||
|
* Adds the specified path to the java library path
|
||||||
|
*
|
||||||
|
* @param pathToAdd the path to add
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static void addLibraryPath(String pathToAdd) throws Exception {
|
||||||
|
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
|
||||||
|
usrPathsField.setAccessible(true);
|
||||||
|
|
||||||
|
// get array of paths
|
||||||
|
final String[] paths = (String[]) usrPathsField.get(null);
|
||||||
|
|
||||||
|
// check if the path to add is already present
|
||||||
|
for (String path : paths) {
|
||||||
|
if (path.equals(pathToAdd)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the new path
|
||||||
|
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
|
||||||
|
newPaths[newPaths.length - 1] = pathToAdd;
|
||||||
|
usrPathsField.set(null, newPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
//public static void registerListener(IEventSource source, IEventListener listener, VBoxEventType... types) {
|
||||||
|
public static org.virtualbox_6_0.IEventListener registerListener(IEventSource source, IEventListener listener, List<VBoxEventType> types) {
|
||||||
|
val ret = new org.virtualbox_6_0.IEventListener(listener);
|
||||||
|
source.registerListener(ret, types, true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T extends IEvent> T getEvent(org.mozilla.interfaces.IEvent event, Class<T> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
name: VirtualComputer
|
name: VirtualComputer
|
||||||
main: sznp.virtualcomputer.PluginMain
|
main: sznp.virtualcomputer.PluginMain
|
||||||
version: '2.1'
|
version: 2.0
|
||||||
commands:
|
commands:
|
||||||
computer:
|
computer:
|
||||||
usage: Use /computer start|stop|reset|key|mouse|input|fix
|
usage: Use /computer start|stop|reset|key|mouse|input|fix
|
||||||
aliases: c
|
aliases: c
|
||||||
api-version: '1.13'
|
|
|
@ -1,73 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>VirtualComputer-MSCOM</artifactId>
|
|
||||||
<version>2.1-SNAPSHOT</version>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
|
||||||
<artifactId>VirtualComputer</artifactId>
|
|
||||||
<version>2.1-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<!-- <dependency>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
|
||||||
<version>6.1</version>
|
|
||||||
<optional>true
|
|
||||||
</optional> <!- https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html ->
|
|
||||||
</dependency> -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.sf.jni4net</groupId>
|
|
||||||
<artifactId>clr</artifactId>
|
|
||||||
<version>0.8.9.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
|
||||||
<artifactId>VirtualComputer-Windows</artifactId>
|
|
||||||
<version>3.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox-JWS</artifactId>
|
|
||||||
<version>6.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.18.20</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>3.2.4</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<artifactSet>
|
|
||||||
<includes>
|
|
||||||
<include>net.sf.jni4net:clr</include>
|
|
||||||
<include>io.github.NorbiPeti:VirtualComputer-Windows</include>
|
|
||||||
</includes>
|
|
||||||
</artifactSet>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,90 +0,0 @@
|
||||||
package sznp.virtualcomputer;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
|
|
||||||
public class JarUtils {
|
|
||||||
|
|
||||||
public static boolean extractFromJar(final String fileName,
|
|
||||||
final String dest) throws IOException {
|
|
||||||
if (getRunningJar() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final File file = new File(dest);
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
file.mkdir();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!file.exists()) {
|
|
||||||
file.getParentFile().mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
final JarFile jar = getRunningJar();
|
|
||||||
final Enumeration<JarEntry> e = jar.entries();
|
|
||||||
while (e.hasMoreElements()) {
|
|
||||||
final JarEntry je = e.nextElement();
|
|
||||||
if (!je.getName().contains(fileName)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final InputStream in = new BufferedInputStream(
|
|
||||||
jar.getInputStream(je));
|
|
||||||
final OutputStream out = new BufferedOutputStream(
|
|
||||||
new FileOutputStream(file));
|
|
||||||
copyInputStream(in, out);
|
|
||||||
jar.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
jar.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void copyInputStream(final InputStream in,
|
|
||||||
final OutputStream out) throws IOException {
|
|
||||||
try {
|
|
||||||
final byte[] buff = new byte[4096];
|
|
||||||
int n;
|
|
||||||
while ((n = in.read(buff)) > 0) {
|
|
||||||
out.write(buff, 0, n);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static URL getJarUrl(final File file) throws IOException {
|
|
||||||
return new URL("jar:" + file.toURI().toURL().toExternalForm() + "!/");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JarFile getRunningJar() throws IOException {
|
|
||||||
if (!RUNNING_FROM_JAR) {
|
|
||||||
return null; // null if not running from jar
|
|
||||||
}
|
|
||||||
String path = new File(JarUtils.class.getProtectionDomain()
|
|
||||||
.getCodeSource().getLocation().getPath()).getAbsolutePath();
|
|
||||||
path = URLDecoder.decode(path, "UTF-8");
|
|
||||||
return new JarFile(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean RUNNING_FROM_JAR = false;
|
|
||||||
|
|
||||||
static {
|
|
||||||
final URL resource = JarUtils.class.getClassLoader().getResource(
|
|
||||||
"plugin.yml");
|
|
||||||
if (resource != null) {
|
|
||||||
RUNNING_FROM_JAR = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package sznp.virtualcomputer.util;
|
|
||||||
|
|
||||||
import com.jacob.com.COMConverter;
|
|
||||||
import com.jacob.com.Dispatch;
|
|
||||||
import com.jacob.com.Variant;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.val;
|
|
||||||
import lombok.var;
|
|
||||||
import org.virtualbox_6_1.*;
|
|
||||||
import virtualcomputerwindows.Exports;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class COMUtils {
|
|
||||||
private COMUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEventListener registerListener(IEventSource source, IEventHandler listener, List<VBoxEventType> types) {
|
|
||||||
source.registerListener(, types, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public static <T extends IEvent> T getEvent(IEvent event, Class<T> cl) {
|
|
||||||
return cl.getConstructor(Dispatch.class).newInstance(event.getTypedWrapped());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IFramebuffer gimmeAFramebuffer(IMCFrameBuffer frameBuffer) {
|
|
||||||
var variant = new Variant();
|
|
||||||
COMConverter.SetVariantAddress(variant, Exports.GetFrameBuffer(frameBuffer, COMConverter.GetVariantAddress(variant)));
|
|
||||||
return new IFramebuffer(variant.toDispatch()); //Object variant
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void queryBitmapInfo(IDisplaySourceBitmap bitmap, long[] ptr, long[] w, long[] h, long[] bpp, long[] bpl, long[] pf) {
|
|
||||||
/*Out<Integer> wo = new Out<>(), ho = new Out<>(), bppo = new Out<>(), bplo = new Out<>();
|
|
||||||
val pfo = new Out<org.virtualbox_6_1_FixIt.BitmapFormat>();
|
|
||||||
val ptro = new Out<Long>();
|
|
||||||
bitmap.queryBitmapInfo(ptro, wo, ho, bppo, bplo, pfo);
|
|
||||||
ptr[0] = ptro.getValue();
|
|
||||||
w[0] = wo.getValue();
|
|
||||||
h[0] = ho.getValue();
|
|
||||||
bpp[0] = bppo.getValue();
|
|
||||||
bpl[0] = bplo.getValue();
|
|
||||||
pf[0] = Exports.convertEnum(pfo.getValue());*/
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void querySourceBitmap(IDisplay display, Holder<IDisplaySourceBitmap> holder) {
|
|
||||||
display.querySourceBitmap(0L, holder);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package sznp.virtualcomputer.util;
|
|
||||||
|
|
||||||
import lombok.var;
|
|
||||||
import org.virtualbox_6_1.IEvent;
|
|
||||||
|
|
||||||
public interface IEventHandler {
|
|
||||||
void handleEvent(IEvent iEvent);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default void handleEvent(long l) {
|
|
||||||
var dp = new Dispatch();
|
|
||||||
dp.m_pDispatch = l;
|
|
||||||
handleEvent(new IEvent(dp));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package sznp.virtualcomputer.util;
|
|
||||||
|
|
||||||
public interface IMCFrameBuffer extends virtualcomputerwindows.IMCFrameBuffer {
|
|
||||||
void notifyUpdate(long x, long y, long width, long height);
|
|
||||||
|
|
||||||
void notifyUpdateImage(long x, long y, long width, long height, byte[] image);
|
|
||||||
|
|
||||||
void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height);
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26403.7
|
VisualStudioVersion = 15.0.26403.7
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualComputerWindows", "VirtualComputerWindows\VirtualComputerWindows.csproj", "{FA1D1EAA-1984-4CC9-9656-98357FDD1A61}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualComputerWindows", "VirtualComputerWindows\VirtualComputerWindows.csproj", "{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -15,8 +15,18 @@ Global
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{FA1D1EAA-1984-4CC9-9656-98357FDD1A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{FA1D1EAA-1984-4CC9-9656-98357FDD1A61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x64.Build.0 = Release|x64
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x86.Build.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
using System;
|
|
||||||
using VirtualBox;
|
|
||||||
|
|
||||||
namespace VirtualComputerWindows
|
|
||||||
{
|
|
||||||
public static class Class1
|
|
||||||
{
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Starting VirtualBox...");
|
|
||||||
var vbox = new VirtualBoxClass();
|
|
||||||
var machines = vbox.Machines.As<IMachine>();
|
|
||||||
var session = new SessionClass();
|
|
||||||
//machines[0].LockMachine(session, LockType.LockType_VM);
|
|
||||||
//var prog = session.Console.PowerUp(); - Unknown error initializing kernel driver (VERR_SUPDRV_NOT_BUDDING_VM_PROCESS_1)
|
|
||||||
var prog = machines[0].LaunchVMProcess(session, "headless", Array.Empty<string>());
|
|
||||||
prog.WaitForCompletion(-1);
|
|
||||||
Console.WriteLine("Error: " + prog.ErrorInfo?.Text);
|
|
||||||
session.Console.Display.AttachFramebuffer(0, new MCFramebuffer());
|
|
||||||
Console.WriteLine("All set up");
|
|
||||||
Console.ReadLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T[] As<T>(this Array array) => (T[]) array;
|
|
||||||
}
|
|
||||||
}
|
|
59
VirtualComputerWindows/VirtualComputerWindows/Exports.cs
Normal file
59
VirtualComputerWindows/VirtualComputerWindows/Exports.cs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VirtualBox;
|
||||||
|
|
||||||
|
namespace VirtualComputerWindows
|
||||||
|
{
|
||||||
|
public static class Exports
|
||||||
|
{
|
||||||
|
[DllImport(@"C:\Program Files\Oracle\VirtualBox\VBoxRT.dll", CallingConvention = CallingConvention.StdCall)]
|
||||||
|
private static extern void RTR3InitExe(int argc, string argv, int zeroflags);
|
||||||
|
/*[DllImport(@"C:\Program Files\Oracle\VirtualBox\VBoxVMM.dll", CallingConvention = CallingConvention.StdCall)]
|
||||||
|
private static extern int VMMDoHmTest(IntPtr vmstruct);*/
|
||||||
|
|
||||||
|
private static VirtualBoxClient vbc;
|
||||||
|
|
||||||
|
public static async Task<IVirtualBox> Init() => await Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//Environment.SetEnvironmentVariable("VBOX_HOME", @"C:\Program Files\Oracle\VirtualBox\");
|
||||||
|
//TODO: Only finds the VBoxVMM.dll when placed in the VirtualBox dir (regardless of working dir)
|
||||||
|
//Even then there are hardening issues: VERR_SUPDRV_NOT_BUDDING_VM_PROCESS_1
|
||||||
|
//https://www.virtualbox.org/svn/vbox/trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
|
||||||
|
vbc = new VirtualBoxClientClass();
|
||||||
|
var vbox = vbc.VirtualBox;
|
||||||
|
RTR3InitExe(0, "", 0);
|
||||||
|
var ses = vbc.Session;
|
||||||
|
var machine = vbox.Machines.GetValue(0) as IMachine;
|
||||||
|
ses.Name = "minecraft";
|
||||||
|
machine.LockMachine(ses, LockType.LockType_VM);
|
||||||
|
Console.WriteLine("Locking...");
|
||||||
|
while (ses.State != SessionState.SessionState_Locked) ;
|
||||||
|
Console.WriteLine("Locked");
|
||||||
|
machine = ses.Machine;
|
||||||
|
Console.WriteLine("Powering up...");
|
||||||
|
ses.Console.PowerUp().WaitForCompletion(10000);
|
||||||
|
Console.WriteLine("Framebuffer attach");
|
||||||
|
ses.Console.Display.AttachFramebuffer(0, new VBFB(ses.Console.Display));
|
||||||
|
return vbox;
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
Console.ReadLine();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,56 +0,0 @@
|
||||||
using System;
|
|
||||||
using VirtualBox;
|
|
||||||
|
|
||||||
namespace VirtualComputerWindows
|
|
||||||
{
|
|
||||||
public class MCFramebuffer : IFramebuffer
|
|
||||||
{
|
|
||||||
public void NotifyUpdate(uint aX, uint aY, uint aWidth, uint aHeight)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"Unexpected NotifyUpdate: {aX} {aY} {aWidth} {aHeight}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void NotifyUpdateImage(uint aX, uint aY, uint aWidth, uint aHeight, Array aImage)
|
|
||||||
{
|
|
||||||
Console.WriteLine("NotifyUpdateImage");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void NotifyChange(uint aScreenId, uint aXOrigin, uint aYOrigin, uint aWidth, uint aHeight)
|
|
||||||
{
|
|
||||||
Console.WriteLine("NotifyChange");
|
|
||||||
}
|
|
||||||
|
|
||||||
public int VideoModeSupported(uint aWidth, uint aHeight, uint aBpp)
|
|
||||||
{
|
|
||||||
Console.WriteLine("VideoModeSupported");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetVisibleRegion(ref byte aRectangles, uint aCount)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetVisibleRegion(ref byte aRectangles, uint aCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ProcessVHWACommand(ref byte aCommand, int aEnmCmd, int aFromGuest)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Notify3DEvent(uint aType, Array aData)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Width { get; } = 640;
|
|
||||||
public uint Height { get; } = 480;
|
|
||||||
public uint BitsPerPixel { get; } = 32;
|
|
||||||
public uint BytesPerLine { get; } = 640 * 4;
|
|
||||||
public BitmapFormat PixelFormat { get; } = BitmapFormat.BitmapFormat_BGRA;
|
|
||||||
public uint HeightReduction { get; } = 0;
|
|
||||||
public IFramebufferOverlay Overlay { get; }
|
|
||||||
public long WinId { get; } = 0;
|
|
||||||
public Array Capabilities { get; } = new[] {FramebufferCapabilities.FramebufferCapabilities_UpdateImage};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("VirtualComputerWindows")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("VirtualComputerWindows")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("5e734f17-ff74-4187-a6e4-b7e1dab272f8")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
75
VirtualComputerWindows/VirtualComputerWindows/VBFB.cs
Normal file
75
VirtualComputerWindows/VirtualComputerWindows/VBFB.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using VirtualBox;
|
||||||
|
|
||||||
|
namespace VirtualComputerWindows
|
||||||
|
{
|
||||||
|
internal class VBFB : IFramebuffer
|
||||||
|
{
|
||||||
|
private IDisplay display;
|
||||||
|
|
||||||
|
public VBFB(IDisplay display)
|
||||||
|
{
|
||||||
|
this.display = display;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NotifyUpdate(uint aX, uint aY, uint aWidth, uint aHeight)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Update: " + aX + " " + aY + " " + aWidth + " " + aHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NotifyUpdateImage(uint aX, uint aY, uint aWidth, uint aHeight, Array aImage)
|
||||||
|
{
|
||||||
|
Console.WriteLine("UpdateImage: " + aX + " " + aY + " " + aWidth + " " + aHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NotifyChange(uint aScreenId, uint aXOrigin, uint aYOrigin, uint aWidth, uint aHeight)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Change: " + aXOrigin + " " + aYOrigin + " " + aWidth + " " + aHeight);
|
||||||
|
display.QuerySourceBitmap(0, out var isd);
|
||||||
|
var addr = new IntPtr();
|
||||||
|
isd.QueryBitmapInfo(addr, out var w, out var h, out var bpp, out var bpl, out var bf);
|
||||||
|
Console.WriteLine("Bitmap info: " + addr + " " + w + " " + h + " " + bpp + " " + bpl + " " + bf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int VideoModeSupported(uint aWidth, uint aHeight, uint aBpp)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint GetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||||
|
{
|
||||||
|
return aCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProcessVHWACommand(ref byte aCommand, int aEnmCmd, int aFromGuest)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Notify3DEvent(uint aType, Array aData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Width => 640;
|
||||||
|
|
||||||
|
public uint Height => 480;
|
||||||
|
|
||||||
|
public uint BitsPerPixel => 32;
|
||||||
|
|
||||||
|
public uint BytesPerLine => 640 * 4;
|
||||||
|
|
||||||
|
public BitmapFormat PixelFormat => BitmapFormat.BitmapFormat_BGRA;
|
||||||
|
|
||||||
|
public uint HeightReduction => 0;
|
||||||
|
|
||||||
|
public IFramebufferOverlay Overlay => null;
|
||||||
|
|
||||||
|
public long WinId => 0;
|
||||||
|
|
||||||
|
//public Array Capabilities => new[] { FramebufferCapabilities.FramebufferCapabilities_UpdateImage };
|
||||||
|
public Array Capabilities => new FramebufferCapabilities[] { };
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,104 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>VirtualComputerWindows</RootNamespace>
|
||||||
|
<AssemblyName>VirtualComputerWindows</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
<DllExportNamespace>VirtualComputerWindows</DllExportNamespace>
|
||||||
|
<DllExportDDNSCecil>true</DllExportDDNSCecil>
|
||||||
|
<DllExportSkipOnAnyCpu>false</DllExportSkipOnAnyCpu>
|
||||||
|
<DllExportOrdinalsBase>1</DllExportOrdinalsBase>
|
||||||
|
<DllExportGenExpLib>false</DllExportGenExpLib>
|
||||||
|
<DllExportOurILAsm>false</DllExportOurILAsm>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
|
<OutputPath>bin\x64\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||||
|
<OutputPath>bin\x86\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<StartupObject />
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.ComponentModel.Composition" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Exports.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="VBFB.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<COMReference Include="VirtualBox">
|
<COMReference Include="VirtualBox">
|
||||||
<Guid>{D7569351-1750-46F0-936E-BD127D5BC264}</Guid>
|
<Guid>{D7569351-1750-46F0-936E-BD127D5BC264}</Guid>
|
||||||
|
@ -16,5 +110,6 @@
|
||||||
<EmbedInteropTypes>False</EmbedInteropTypes>
|
<EmbedInteropTypes>False</EmbedInteropTypes>
|
||||||
</COMReference>
|
</COMReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Import Project="../packages/DllExport.1.5.2/tools/net.r_eg.DllExport.targets" Condition="Exists('../packages/DllExport.1.5.2/tools/net.r_eg.DllExport.targets')" />
|
||||||
</Project>
|
</Project>
|
15
VirtualComputerWindows/VirtualComputerWindows/app.config
Normal file
15
VirtualComputerWindows/VirtualComputerWindows/app.config
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net462" />
|
||||||
|
</packages>
|
|
@ -1,45 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<parent>
|
|
||||||
<artifactId>VirtualComputer</artifactId>
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
|
||||||
<version>2.1-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>VirtualComputer-XPCOM</artifactId>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox</artifactId>
|
|
||||||
<version>6.1</version>
|
|
||||||
<optional>true
|
|
||||||
</optional> <!-- https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html -->
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<artifactSet>
|
|
||||||
<includes>
|
|
||||||
<include>org.virtualbox:VirtualBox</include>
|
|
||||||
</includes>
|
|
||||||
</artifactSet>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
|
@ -1,122 +0,0 @@
|
||||||
package sznp.virtualcomputer;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.mozilla.interfaces.IFramebuffer;
|
|
||||||
import org.mozilla.interfaces.IFramebufferOverlay;
|
|
||||||
import org.mozilla.interfaces.nsISupports;
|
|
||||||
import org.mozilla.xpcom.Mozilla;
|
|
||||||
import org.virtualbox_6_1.BitmapFormat;
|
|
||||||
import org.virtualbox_6_1.FramebufferCapabilities;
|
|
||||||
import sznp.virtualcomputer.util.IMCFrameBuffer;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class COMFrameBuffer implements IFramebuffer {
|
|
||||||
private final IMCFrameBuffer frameBuffer;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public nsISupports queryInterface(String id) {
|
|
||||||
return Mozilla.queryInterface(this, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getBitsPerPixel() {
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getBytesPerLine() {
|
|
||||||
return 640L;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long[] getCapabilities(long[] arg0) {
|
|
||||||
try {
|
|
||||||
System.out.println("Capabilities queried");
|
|
||||||
System.out.println("Capabilities: " + Arrays.toString(arg0));
|
|
||||||
return new long[]{FramebufferCapabilities.UpdateImage.value()};
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return new long[]{};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getHeight() {
|
|
||||||
return 480;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getHeightReduction() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IFramebufferOverlay getOverlay() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getPixelFormat() {
|
|
||||||
return BitmapFormat.BGRA.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getVisibleRegion(byte arg0, long arg1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getWidth() {
|
|
||||||
return 640;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getWinId() {
|
|
||||||
return 0; // Zero means no win id
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notify3DEvent(long type, byte[] data) {
|
|
||||||
System.out.println("3D event! " + type + " - " + Arrays.toString(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) {
|
|
||||||
frameBuffer.notifyChange(screenId, xOrigin, yOrigin, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyUpdate(long x, long y, long width, long height) {
|
|
||||||
frameBuffer.notifyUpdate(x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyUpdateImage(long arg0, long arg1, long arg2, long arg3, byte[] arg4) {
|
|
||||||
frameBuffer.notifyUpdateImage(arg0, arg1, arg2, arg3, arg4);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVisibleRegion(byte arg0, long arg1) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Posts a Video HW Acceleration Command to the frame buffer for processing.<br />
|
|
||||||
* <br />
|
|
||||||
* The commands used for 2D video acceleration (DDraw surface creation/destroying, blitting, scaling, color conversion, overlaying, etc.) are posted from quest to the host to be processed by the host hardware.
|
|
||||||
*
|
|
||||||
* @param command Pointer to VBOXVHWACMD containing the command to execute.
|
|
||||||
* @param enmCmd The validated VBOXVHWACMD::enmCmd value from the command.
|
|
||||||
* @param fromGuest Set when the command origins from the guest, clear if host.
|
|
||||||
*/ //https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp#L4645
|
|
||||||
@Override
|
|
||||||
public void processVHWACommand(byte command, int enmCmd, boolean fromGuest) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean videoModeSupported(long arg0, long arg1, long arg2) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package sznp.virtualcomputer;
|
|
||||||
|
|
||||||
import org.mozilla.interfaces.IEvent;
|
|
||||||
import org.mozilla.interfaces.IEventListener;
|
|
||||||
import sznp.virtualcomputer.util.COMObjectBase;
|
|
||||||
import sznp.virtualcomputer.util.IEventHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Bukkit-like event system which calls the appropriate methods on an event.
|
|
||||||
*/
|
|
||||||
public final class EventHandler extends COMObjectBase implements IEventListener {
|
|
||||||
private final IEventHandler handler;
|
|
||||||
private boolean enabled = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New XPCOM event handler.
|
|
||||||
*
|
|
||||||
* @param handler The handle method that handles what needs to be handled
|
|
||||||
*/
|
|
||||||
public EventHandler(IEventHandler handler) {
|
|
||||||
this.handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void handleEvent(IEvent iEvent) {
|
|
||||||
if (!enabled)
|
|
||||||
return;
|
|
||||||
handler.handleEvent(new org.virtualbox_6_1.IEvent(iEvent));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disable() {
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package sznp.virtualcomputer.util;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import org.virtualbox_6_1.*;
|
|
||||||
import org.virtualbox_6_1.xpcom.IUnknown;
|
|
||||||
import sznp.virtualcomputer.COMFrameBuffer;
|
|
||||||
import sznp.virtualcomputer.EventHandler;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class COMUtils {
|
|
||||||
private COMUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
//public static void registerListener(IEventSource source, IEventListener listener, VBoxEventType... types) {
|
|
||||||
public static org.virtualbox_6_1.IEventListener registerListener(IEventSource source, IEventHandler listener, List<VBoxEventType> types) {
|
|
||||||
val ret = new org.virtualbox_6_1.IEventListener(new EventHandler(listener));
|
|
||||||
source.registerListener(ret, types, true);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T extends IEvent> T getEvent(IEvent event, Class<T> cl) {
|
|
||||||
try {
|
|
||||||
val method = cl.getMethod("queryInterface", IUnknown.class);
|
|
||||||
return (T) method.invoke(null, event);
|
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IFramebuffer gimmeAFramebuffer(IMCFrameBuffer frameBuffer) {
|
|
||||||
return new IFramebuffer(new COMFrameBuffer(frameBuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void queryBitmapInfo(IDisplaySourceBitmap bitmap, long[] ptr, long[] w, long[] h, long[] bpp, long[] bpl, long[] pf) {
|
|
||||||
bitmap.getTypedWrapped().queryBitmapInfo(ptr, w, h, bpp, bpl, pf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void querySourceBitmap(IDisplay display, Holder<IDisplaySourceBitmap> holder) {
|
|
||||||
display.querySourceBitmap(0L, holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean convertToBool(boolean bool) {
|
|
||||||
return bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean convertFromBool(boolean bool) {
|
|
||||||
return bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long convertFromLong(long l) {
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package sznp.virtualcomputer.util;
|
|
||||||
|
|
||||||
import org.virtualbox_6_1.IEvent;
|
|
||||||
|
|
||||||
public interface IEventHandler {
|
|
||||||
void handleEvent(IEvent iEvent);
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package sznp.virtualcomputer.util;
|
|
||||||
|
|
||||||
public interface IMCFrameBuffer {
|
|
||||||
void notifyUpdate(long x, long y, long width, long height);
|
|
||||||
|
|
||||||
void notifyUpdateImage(long x, long y, long width, long height, byte[] image);
|
|
||||||
|
|
||||||
void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height);
|
|
||||||
}
|
|
154
pom.xml
154
pom.xml
|
@ -1,154 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
|
||||||
<artifactId>VirtualComputer</artifactId>
|
|
||||||
<version>2.1-SNAPSHOT</version>
|
|
||||||
<modules>
|
|
||||||
<module>VirtualComputerMSCOM</module>
|
|
||||||
<module>VirtualComputer-Core</module>
|
|
||||||
</modules>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<name>VirtualComputer</name>
|
|
||||||
<url>https://github.com/NorbiPeti/VirtualComputer</url>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>repo</id>
|
|
||||||
<url>file://${basedir}/../repo</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>spigot-repo</id>
|
|
||||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>jitpack</id>
|
|
||||||
<url>https://jitpack.io/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.11</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.18.12</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.java.dev.jna</groupId>
|
|
||||||
<artifactId>jna</artifactId>
|
|
||||||
<version>4.4.0</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-ffi -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.jnr</groupId>
|
|
||||||
<artifactId>jnr-ffi</artifactId>
|
|
||||||
<version>2.1.16</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency> <!-- javax.annotations.Nullable -->
|
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
|
||||||
<artifactId>jsr305</artifactId>
|
|
||||||
<version>3.0.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot-api</artifactId>
|
|
||||||
<version>1.12-R0.1-SNAPSHOT</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- <dependency> !- Not using anything from here directly so we're not that dependent on versions -
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot</artifactId>
|
|
||||||
<version>1.16.1-R0.1-SNAPSHOT</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency> -->
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
|
|
||||||
<plugins>
|
|
||||||
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-clean-plugin</artifactId>
|
|
||||||
<version>3.1.0</version>
|
|
||||||
</plugin>
|
|
||||||
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
|
||||||
<version>3.0.2</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.8.0</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>2.22.1</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>3.0.2</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-install-plugin</artifactId>
|
|
||||||
<version>2.5.2</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
|
||||||
<version>2.8.2</version>
|
|
||||||
</plugin>
|
|
||||||
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-site-plugin</artifactId>
|
|
||||||
<version>3.7.1</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
|
||||||
<version>3.0.0</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
</build>
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>XPCOM</id>
|
|
||||||
<modules>
|
|
||||||
<module>VirtualComputerXPCOM</module>
|
|
||||||
</modules>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>MSCOM</id>
|
|
||||||
<modules>
|
|
||||||
<module>VirtualComputerMSCOM</module>
|
|
||||||
</modules>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>intellij-idea-only</id>
|
|
||||||
<activation>
|
|
||||||
<property>
|
|
||||||
<name>idea.maven.embedder.version</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<modules>
|
|
||||||
<module>VirtualComputerMSCOM</module>
|
|
||||||
</modules>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
</project>
|
|
Binary file not shown.
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
|
||||||
<artifactId>VirtualComputer-Windows</artifactId>
|
|
||||||
<version>3.0</version>
|
|
||||||
<description>POM was created from install:install-file</description>
|
|
||||||
</project>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>io.github.NorbiPeti</groupId>
|
|
||||||
<artifactId>VirtualComputer-Windows</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<release>3.0</release>
|
|
||||||
<versions>
|
|
||||||
<version>3.0</version>
|
|
||||||
</versions>
|
|
||||||
<lastUpdated>20201121164706</lastUpdated>
|
|
||||||
</versioning>
|
|
||||||
</metadata>
|
|
Binary file not shown.
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>net.sf.jni4net</groupId>
|
|
||||||
<artifactId>clr</artifactId>
|
|
||||||
<version>0.8.8.0</version>
|
|
||||||
<description>POM was created from install:install-file</description>
|
|
||||||
</project>
|
|
Binary file not shown.
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>net.sf.jni4net</groupId>
|
|
||||||
<artifactId>clr</artifactId>
|
|
||||||
<version>0.8.9.0</version>
|
|
||||||
<description>POM was created from install:install-file</description>
|
|
||||||
</project>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>net.sf.jni4net</groupId>
|
|
||||||
<artifactId>clr</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<release>0.8.8.0</release>
|
|
||||||
<versions>
|
|
||||||
<version>0.8.9.0</version>
|
|
||||||
<version>0.8.8.0</version>
|
|
||||||
</versions>
|
|
||||||
<lastUpdated>20201122015638</lastUpdated>
|
|
||||||
</versioning>
|
|
||||||
</metadata>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox-JWS</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<release>6.1</release>
|
|
||||||
<versions>
|
|
||||||
<version>6.1</version>
|
|
||||||
</versions>
|
|
||||||
<lastUpdated>20210603224925</lastUpdated>
|
|
||||||
</versioning>
|
|
||||||
</metadata>
|
|
Binary file not shown.
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
|
||||||
<version>6.1</version>
|
|
||||||
<description>POM was created from install:install-file</description>
|
|
||||||
</project>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<release>6.1</release>
|
|
||||||
<versions>
|
|
||||||
<version>6.0</version>
|
|
||||||
<version>6.1</version>
|
|
||||||
</versions>
|
|
||||||
<lastUpdated>20201016165020</lastUpdated>
|
|
||||||
</versioning>
|
|
||||||
</metadata>
|
|
Binary file not shown.
|
@ -1,10 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox</artifactId>
|
|
||||||
<version>5.1</version>
|
|
||||||
<description>POM was created from install:install-file</description>
|
|
||||||
</project>
|
|
|
@ -1,10 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>org.virtualbox</groupId>
|
|
||||||
<artifactId>VirtualBox</artifactId>
|
|
||||||
<version>5.2</version>
|
|
||||||
<description>POM was created from install:install-file</description>
|
|
||||||
</project>
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue