Screen fixes, improved update method
Fixed updates stopping, but not the cursor NotifyUpdate handling is in a separate thread to avoid slowing the machine and it will only perform one update at a time that reflects the current state
This commit is contained in:
parent
32cea5c384
commit
586ab05033
3 changed files with 86 additions and 38 deletions
|
@ -67,9 +67,16 @@ 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":
|
||||||
Computer.getInstance().FixScreen(sender);
|
Boolean seamless;
|
||||||
|
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":
|
||||||
|
|
|
@ -100,6 +100,7 @@ public final class Computer {
|
||||||
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?
|
||||||
val fb = new MCFrameBuffer(console.getDisplay());
|
val fb = new MCFrameBuffer(console.getDisplay());
|
||||||
|
fb.start();
|
||||||
String fbid = console.getDisplay().attachFramebuffer(0L,
|
String fbid = console.getDisplay().attachFramebuffer(0L,
|
||||||
COMUtils.gimmeAFramebuffer(fb));
|
COMUtils.gimmeAFramebuffer(fb));
|
||||||
fb.setId(fbid);
|
fb.setId(fbid);
|
||||||
|
@ -153,7 +154,16 @@ public final class Computer {
|
||||||
sendMessage(sender, "§eComputer reset.");
|
sendMessage(sender, "§eComputer reset.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FixScreen(CommandSender sender) {
|
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))
|
if (checkMachineNotRunning(sender))
|
||||||
return;
|
return;
|
||||||
if (framebuffer == null) {
|
if (framebuffer == null) {
|
||||||
|
@ -166,15 +176,20 @@ public final class Computer {
|
||||||
sendMessage(sender, "§eFixing screen...");
|
sendMessage(sender, "§eFixing screen...");
|
||||||
try {
|
try {
|
||||||
synchronized (session) {
|
synchronized (session) {
|
||||||
session.getConsole().getDisplay().setSeamlessMode(false);
|
if (seamless == null)
|
||||||
session.getConsole().getDisplay().detachFramebuffer(0L, framebuffer.getId());
|
session.getConsole().getDisplay().setVideoModeHint(0L, true, false, 0, 0, 640L, 480L, 32L, false);
|
||||||
session.getConsole().getDisplay().setVideoModeHint(0L, true, false, 0, 0, 640L, 480L, 32L, true);
|
} //Last param: notify - send PnP notification - stops updates but not changes for some reason
|
||||||
framebuffer.setId(session.getConsole().getDisplay().attachFramebuffer(0L, COMUtils.gimmeAFramebuffer(framebuffer)));
|
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) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
sendMessage(sender, "§eScreen fixed.");
|
|
||||||
status = session.getConsole().getGuest().getFacilityStatus(AdditionsFacilityType.Seamless, lastUpdated);
|
status = session.getConsole().getGuest().getFacilityStatus(AdditionsFacilityType.Seamless, lastUpdated);
|
||||||
sendMessage(sender, "Seamless status: " + status);
|
sendMessage(sender, "Seamless status: " + status);
|
||||||
}
|
}
|
||||||
|
@ -258,6 +273,7 @@ public final class Computer {
|
||||||
GPURenderer.update(new byte[1], 0, 0, 0, 0, 640, 480); //Black screen
|
GPURenderer.update(new byte[1], 0, 0, 0, 0, 640, 480); //Black screen
|
||||||
stopEvents();
|
stopEvents();
|
||||||
MouseLockerPlayerListener.computerStop();
|
MouseLockerPlayerListener.computerStop();
|
||||||
|
framebuffer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopEvents() {
|
public void stopEvents() {
|
||||||
|
@ -270,6 +286,7 @@ public final class Computer {
|
||||||
|
|
||||||
public void pluginDisable(CommandSender ccs) {
|
public void pluginDisable(CommandSender ccs) {
|
||||||
stopEvents();
|
stopEvents();
|
||||||
|
framebuffer.stop();
|
||||||
if (session.getState() == SessionState.Locked) {
|
if (session.getState() == SessionState.Locked) {
|
||||||
if (session.getMachine().getState().equals(MachineState.Running)) {
|
if (session.getMachine().getState().equals(MachineState.Running)) {
|
||||||
ccs.sendMessage("§aSaving machine state...");
|
ccs.sendMessage("§aSaving machine state...");
|
||||||
|
|
|
@ -15,6 +15,8 @@ import sznp.virtualcomputer.util.COMUtils;
|
||||||
import sznp.virtualcomputer.util.IMCFrameBuffer;
|
import sznp.virtualcomputer.util.IMCFrameBuffer;
|
||||||
import sznp.virtualcomputer.util.Timing;
|
import sznp.virtualcomputer.util.Timing;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class MCFrameBuffer implements IMCFrameBuffer {
|
public class MCFrameBuffer implements IMCFrameBuffer {
|
||||||
private final IDisplay display;
|
private final IDisplay display;
|
||||||
|
@ -23,10 +25,11 @@ 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
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private String id;
|
private String id;
|
||||||
|
private final AtomicBoolean shouldUpdate = new AtomicBoolean();
|
||||||
|
private boolean running;
|
||||||
|
|
||||||
@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) {
|
||||||
|
@ -35,7 +38,7 @@ public class MCFrameBuffer implements IMCFrameBuffer {
|
||||||
tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||||
synchronized (this) { //If a change occurs twice, then wait for it
|
synchronized (this) { //If a change occurs twice, then wait for it
|
||||||
try {
|
try {
|
||||||
System.out.println("Change: " + xOrigin + " " + yOrigin + " - " + width + " " + height);
|
//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);
|
||||||
|
@ -43,8 +46,9 @@ 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)
|
//System.out.println("Actual sizes: " + this.width + " " + this.height);
|
||||||
return;
|
/*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);
|
||||||
|
@ -61,43 +65,63 @@ public class MCFrameBuffer implements IMCFrameBuffer {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
} finally {
|
} /*finally {
|
||||||
System.out.println("Change finished");
|
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)
|
/*if (this.width > 1024 || this.height > 768)
|
||||||
return;
|
return;*/
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
if(shouldUpdate.get())
|
||||||
synchronized (this) {
|
return; //Don't wait for lock, ignore update since we're updating everything anyway - TODO: Not always
|
||||||
if (updating) {
|
synchronized (this) {
|
||||||
System.out.println("Ignoring update");
|
shouldUpdate.set(true);
|
||||||
return;
|
notifyAll();
|
||||||
}
|
}
|
||||||
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();
|
|
||||||
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");
|
|
||||||
else
|
|
||||||
System.out.println("Update finished");
|
|
||||||
updating = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyUpdateImage(long x, long y, long width, long height, byte[] image) {
|
public void notifyUpdateImage(long x, long y, long width, long height, byte[] image) {
|
||||||
System.out.println("Update 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue