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":
|
||||
Computer.getInstance().Reset(sender);
|
||||
break;
|
||||
case "save":
|
||||
case "savestate":
|
||||
Computer.getInstance().SaveState(sender);
|
||||
break;
|
||||
case "fix":
|
||||
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;
|
||||
case "key":
|
||||
case "press":
|
||||
|
|
|
@ -100,6 +100,7 @@ public final class Computer {
|
|||
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);
|
||||
|
@ -153,7 +154,16 @@ public final class Computer {
|
|||
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))
|
||||
return;
|
||||
if (framebuffer == null) {
|
||||
|
@ -166,15 +176,20 @@ public final class Computer {
|
|||
sendMessage(sender, "§eFixing screen...");
|
||||
try {
|
||||
synchronized (session) {
|
||||
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);
|
||||
framebuffer.setId(session.getConsole().getDisplay().attachFramebuffer(0L, COMUtils.gimmeAFramebuffer(framebuffer)));
|
||||
}
|
||||
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();
|
||||
}
|
||||
sendMessage(sender, "§eScreen fixed.");
|
||||
status = session.getConsole().getGuest().getFacilityStatus(AdditionsFacilityType.Seamless, lastUpdated);
|
||||
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
|
||||
stopEvents();
|
||||
MouseLockerPlayerListener.computerStop();
|
||||
framebuffer.stop();
|
||||
}
|
||||
|
||||
public void stopEvents() {
|
||||
|
@ -270,6 +286,7 @@ public final class Computer {
|
|||
|
||||
public void pluginDisable(CommandSender ccs) {
|
||||
stopEvents();
|
||||
framebuffer.stop();
|
||||
if (session.getState() == SessionState.Locked) {
|
||||
if (session.getMachine().getState().equals(MachineState.Running)) {
|
||||
ccs.sendMessage("§aSaving machine state...");
|
||||
|
|
|
@ -15,6 +15,8 @@ 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;
|
||||
|
@ -23,10 +25,11 @@ public class MCFrameBuffer implements IMCFrameBuffer {
|
|||
private Pointer pointer;
|
||||
private int width;
|
||||
private int height;
|
||||
private boolean updating = false;
|
||||
@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) {
|
||||
|
@ -35,7 +38,7 @@ public class MCFrameBuffer implements IMCFrameBuffer {
|
|||
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);
|
||||
//System.out.println("Change: " + xOrigin + " " + yOrigin + " - " + width + " " + height);
|
||||
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];
|
||||
COMUtils.queryBitmapInfo(holder.value, ptr, w, h, bpp, bpl, pf);
|
||||
|
@ -43,8 +46,9 @@ public class MCFrameBuffer implements IMCFrameBuffer {
|
|||
pointer = new Pointer(ptr[0]);
|
||||
this.width = (int) w[0];
|
||||
this.height = (int) h[0];
|
||||
if (this.width > 1024 || this.height > 768)
|
||||
return;
|
||||
//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);
|
||||
|
@ -61,43 +65,63 @@ public class MCFrameBuffer implements IMCFrameBuffer {
|
|||
e.printStackTrace();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
} finally {
|
||||
} /*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;
|
||||
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();
|
||||
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;
|
||||
}
|
||||
});
|
||||
/*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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue