Attempts to fix screen on Ubuntu after /c fix

It stops sending updates after running the fix command
This commit is contained in:
Norbi Peti 2020-08-03 02:43:31 +02:00
parent 3ce2da7f7f
commit 32cea5c384
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
2 changed files with 115 additions and 46 deletions

View file

@ -3,6 +3,7 @@ package sznp.virtualcomputer;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.Getter; import lombok.Getter;
import lombok.val; import lombok.val;
import lombok.var;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -28,6 +29,7 @@ public final class Computer {
private MachineEventHandler handler; private MachineEventHandler handler;
private IEventListener listener; private IEventListener listener;
private VirtualBoxManager manager; private VirtualBoxManager manager;
private MCFrameBuffer framebuffer;
@java.beans.ConstructorProperties({"plugin"}) @java.beans.ConstructorProperties({"plugin"})
public Computer(PluginMain plugin, VirtualBoxManager manager, IVirtualBox vbox) { public Computer(PluginMain plugin, VirtualBoxManager manager, IVirtualBox vbox) {
@ -45,7 +47,7 @@ public final class Computer {
return; return;
} }
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
if (vbox.getMachines().size() <= index) { if (index < 0 || vbox.getMachines().size() <= index) {
sendMessage(sender, "§cMachine not found!"); sendMessage(sender, "§cMachine not found!");
return; return;
} }
@ -54,7 +56,9 @@ public final class Computer {
machine = vbox.getMachines().get(index); machine = vbox.getMachines().get(index);
session.setName("minecraft"); session.setName("minecraft");
// machine.launchVMProcess(session, "headless", "").waitForCompletion(10000); - This creates a *process*, we don't want that anymore // 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 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 VBoxEventHandler.getInstance().setup(machine.getId(), sender); //TODO: Sometimes null
} catch (VBoxException e) { } catch (VBoxException e) {
if (e.getResultCode() == 0x80070005) { //lockMachine: "The object functionality is limited" if (e.getResultCode() == 0x80070005) { //lockMachine: "The object functionality is limited"
@ -95,8 +99,11 @@ public final class Computer {
IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2 IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2
handler.setProgress(progress); handler.setProgress(progress);
handler.registerTo(progress.getEventSource()); //TODO: Show progress bar some way? handler.registerTo(progress.getEventSource()); //TODO: Show progress bar some way?
console.getDisplay().attachFramebuffer(0L, val fb = new MCFrameBuffer(console.getDisplay());
COMUtils.gimmeAFramebuffer(new MCFrameBuffer(console.getDisplay()))); String fbid = console.getDisplay().attachFramebuffer(0L,
COMUtils.gimmeAFramebuffer(fb));
fb.setId(fbid);
framebuffer = fb;
} }
private void sendMessage(@Nullable CommandSender sender, String message) { private void sendMessage(@Nullable CommandSender sender, String message) {
@ -114,8 +121,10 @@ public final class Computer {
return; return;
} }
sendMessage(sender, "§eStopping computer..."); sendMessage(sender, "§eStopping computer...");
synchronized (session) {
session.getConsole().powerDown(); session.getConsole().powerDown();
} }
}
public void PowerButton(CommandSender sender, int index) { public void PowerButton(CommandSender sender, int index) {
sendMessage(sender, "§ePressing powerbutton..."); sendMessage(sender, "§ePressing powerbutton...");
@ -125,7 +134,9 @@ public final class Computer {
if (session.getState() != SessionState.Locked || session.getMachine() == null) { if (session.getState() != SessionState.Locked || session.getMachine() == null) {
Start(sender, index); Start(sender, index);
} else { } else {
synchronized (session) {
session.getConsole().powerButton(); session.getConsole().powerButton();
}
sendMessage(sender, "§ePowerbutton pressed."); sendMessage(sender, "§ePowerbutton pressed.");
} }
} }
@ -136,17 +147,36 @@ public final class Computer {
if (checkMachineNotRunning(sender)) if (checkMachineNotRunning(sender))
return; return;
sendMessage(sender, "§eResetting computer..."); sendMessage(sender, "§eResetting computer...");
synchronized (session) {
session.getConsole().reset(); session.getConsole().reset();
}
sendMessage(sender, "§eComputer reset."); sendMessage(sender, "§eComputer reset.");
} }
public void FixScreen(CommandSender sender) { public void FixScreen(CommandSender sender) {
if (checkMachineNotRunning(sender)) if (checkMachineNotRunning(sender))
return; return;
if (framebuffer == null) {
sender.sendMessage("§cFramebuffer is null...");
return;
}
val lastUpdated = new Holder<Long>();
var status = session.getConsole().getGuest().getFacilityStatus(AdditionsFacilityType.Seamless, lastUpdated);
sendMessage(sender, "Seamless status: " + status);
sendMessage(sender, "§eFixing screen..."); sendMessage(sender, "§eFixing screen...");
try {
synchronized (session) {
session.getConsole().getDisplay().setSeamlessMode(false); session.getConsole().getDisplay().setSeamlessMode(false);
session.getConsole().getDisplay().detachFramebuffer(0L, framebuffer.getId());
session.getConsole().getDisplay().setVideoModeHint(0L, true, false, 0, 0, 640L, 480L, 32L, true); session.getConsole().getDisplay().setVideoModeHint(0L, true, false, 0, 0, 640L, 480L, 32L, true);
framebuffer.setId(session.getConsole().getDisplay().attachFramebuffer(0L, COMUtils.gimmeAFramebuffer(framebuffer)));
}
} catch (Exception e) {
e.printStackTrace();
}
sendMessage(sender, "§eScreen fixed."); sendMessage(sender, "§eScreen fixed.");
status = session.getConsole().getGuest().getFacilityStatus(AdditionsFacilityType.Seamless, lastUpdated);
sendMessage(sender, "Seamless status: " + status);
} }
public boolean checkMachineNotRunning(@Nullable CommandSender sender) { public boolean checkMachineNotRunning(@Nullable CommandSender sender) {
@ -177,6 +207,7 @@ public final class Computer {
} }
// Release key scan code concept taken from VirtualBox source code (KeyboardImpl.cpp:putCAD()) // Release key scan code concept taken from VirtualBox source code (KeyboardImpl.cpp:putCAD())
// +128 // +128
synchronized (session) {
if (durationorstate != -2) if (durationorstate != -2)
session.getConsole().getKeyboard().putScancode(code); session.getConsole().getKeyboard().putScancode(code);
Runnable sendrelease = () -> session.getConsole().getKeyboard().putScancodes(Lists.newArrayList(code + 128, Runnable sendrelease = () -> session.getConsole().getKeyboard().putScancodes(Lists.newArrayList(code + 128,
@ -184,7 +215,8 @@ public final class Computer {
if (durationorstate == 0 || durationorstate == -2) if (durationorstate == 0 || durationorstate == -2)
sendrelease.run(); sendrelease.run();
if (durationorstate > 0) { if (durationorstate > 0) {
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, sendrelease, durationorstate); Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, sendrelease, durationorstate * 20);
}
} }
} }
@ -195,8 +227,10 @@ public final class Computer {
if (mbs.length() > 0 && down) if (mbs.length() > 0 && down)
state = Arrays.stream(MouseButtonState.values()).filter(mousebs -> mousebs.name().equalsIgnoreCase(mbs)) state = Arrays.stream(MouseButtonState.values()).filter(mousebs -> mousebs.name().equalsIgnoreCase(mbs))
.findAny().orElseThrow(() -> new Exception("Unknown mouse button")).value(); .findAny().orElseThrow(() -> new Exception("Unknown mouse button")).value();
synchronized (session) {
session.getConsole().getMouse().putMouseEvent(x, y, z, w, state); 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 { public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs) throws Exception {
if (checkMachineNotRunning(sender)) if (checkMachineNotRunning(sender))
@ -212,7 +246,9 @@ public final class Computer {
public void onMachineStop(CommandSender sender) { public void onMachineStop(CommandSender sender) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
if (session.getState() == SessionState.Locked) { if (session.getState() == SessionState.Locked) {
synchronized (session) {
session.unlockMachine(); //Needs to be outside of the event handler session.unlockMachine(); //Needs to be outside of the event handler
}
handler = null; handler = null;
machine = null; machine = null;
session = manager.getSessionObject(); session = manager.getSessionObject();

View file

@ -1,7 +1,9 @@
package sznp.virtualcomputer.renderer; package sznp.virtualcomputer.renderer;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import org.virtualbox_6_1.Holder; import org.virtualbox_6_1.Holder;
@ -21,13 +23,19 @@ public class MCFrameBuffer implements IMCFrameBuffer {
private Pointer pointer; private Pointer pointer;
private int width; private int width;
private int height; private int height;
private boolean updating = false;
@Getter
@Setter
private String id;
@Override @Override
public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) { public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) {
if (tt != null) if (tt != null)
tt.cancel(); tt.cancel();
tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> { tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
synchronized (this) { //If a change occurs twice, then wait for it
try { try {
System.out.println("Change: " + xOrigin + " " + yOrigin + " - " + width + " " + height);
display.querySourceBitmap(0L, holder); 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]; 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); COMUtils.queryBitmapInfo(holder.value, ptr, w, h, bpp, bpl, pf);
@ -35,6 +43,8 @@ public class MCFrameBuffer implements IMCFrameBuffer {
pointer = new Pointer(ptr[0]); pointer = new Pointer(ptr[0]);
this.width = (int) w[0]; this.width = (int) w[0];
this.height = (int) h[0]; this.height = (int) h[0];
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); GPURenderer.update(pointer.getByteArray(0L, (int) (w[0] * h[0] * 4)), (int) w[0], (int) h[0], 0, 0, this.width, this.height);
} else { } else {
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4); PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
@ -51,16 +61,39 @@ public class MCFrameBuffer implements IMCFrameBuffer {
e.printStackTrace(); e.printStackTrace();
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace(); t.printStackTrace();
} finally {
System.out.println("Change finished");
}
} }
}); });
} }
@Override @Override
public void notifyUpdate(long x, long y, long width, long height) { public void notifyUpdate(long x, long y, long width, long height) {
if (this.width > 1024 || this.height > 768)
return;
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
synchronized (this) {
if (updating) {
System.out.println("Ignoring update");
return;
}
updating = true;
if (pointer == null) {
System.out.println("Screen pointer is null");
updating = false;
return;
}
System.out.println("Update: " + x + " " + y + " - " + width + " " + height);
Timing t = new Timing(); 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); GPURenderer.update(pointer.getByteArray(0L, this.width * this.height * 4), this.width, this.height, (int) x, (int) y, (int) width, (int) height);
if (t.elapsedMS() > 60) //Typically 1ms max if (t.elapsedMS() > 60) //Typically 1ms max
System.out.println("Update took " + t.elapsedMS() + "ms"); System.out.println("Update took " + t.elapsedMS() + "ms");
else
System.out.println("Update finished");
updating = false;
}
});
} }
@Override @Override