Weiter am Voxel kram gebastelt

This commit is contained in:
2026-08-06 22:48:54 +02:00
parent 0329390d31
commit 8feaf24490
39 changed files with 359 additions and 140 deletions

View File

@@ -62,6 +62,15 @@ public class BlightGame extends SimpleApplication {
private long startTimeMs = 0;
private long lastFullscreenFix = 0;
private long pendingFullscreenFixAt = Long.MAX_VALUE;
// Cinnamons Display-Daemon interpretiert den glfwSetWindowMonitor()-Toggle in
// fixFullscreenMonitor() offenbar als Monitor-Neukonfiguration und setzt dabei
// "scaling-factor" (org.cinnamon.desktop.interface) auf 0 (=Auto) zurück, auch wenn
// der Nutzer explizit 100% (Wert 1) eingestellt hatte das bleibt dann auch nach dem
// Spielende so stehen. Wir sichern den Wert vor dem Fix und schreiben ihn zeitversetzt
// zurück (Cinnamon braucht etwas, bis es reagiert sofortiges Zurückschreiben würde
// von Cinnamons eigenem Reset kurz danach wieder überschrieben).
private String savedScalingFactor = null;
private long pendingScalingRestoreAt = Long.MAX_VALUE;
private boolean firstLaunch = true; // false nach dem ersten simpleInitApp()
private boolean initialFixDone = false; // Initial-Fix bei 0.5s bereits gelaufen
private boolean pendingMenuRebuild = false; // nur true nach explizitem app.restart()
@@ -202,6 +211,7 @@ public class BlightGame extends SimpleApplication {
audioSettings = AudioSettingsStore.load();
de.blight.game.state.ModelLodControl.debugLod2 = graphicsSettings.debugLod2;
captureScalingFactor();
startTimeMs = System.currentTimeMillis();
initialFixDone = false;
@@ -226,6 +236,16 @@ public class BlightGame extends SimpleApplication {
// Fullscreen-Zustand war (wie beim 5s-Watchdog). Aus dem Hidden-Zustand behandelt
// Cinnamon den nächsten Fullscreen-Übergang als Neuerstplatzierung und ignoriert
// den Ziel-Monitor zugunsten des aktiven Workspaces (Editor-Monitor).
//
// mainMenuState wird weiter unten in dieser Methode gebaut mit der JETZT
// aktuellen (noch nicht fullscreen-korrigierten) Kamera-Größe. Der Vollbild-Fix
// läuft aber erst ~200ms später in simpleUpdate() und löst dann reshape() aus.
// Ohne pendingMenuRebuild würde rebuildScreenDependentStates() dabei NUR HUD/
// Hotbar/LoadingScreen neu aufbauen (siehe dortige Kommentare: das ist normalerweise
// extra vor app.restart() gesetzt) das Menü bliebe dauerhaft auf der falschen,
// zu kleinen Ausgangsgröße stehen und würde nur einen Bildschirm-Ausschnitt
// (unten links) füllen, obwohl das Fenster längst auf volle Auflösung steht.
pendingMenuRebuild = true;
}
// Restart nach Einstellungsänderung: pendingFullscreenFixAt (scheduleFullscreenFix)
// bleibt gesetzt und übernimmt den Fix nach 1 s.
@@ -493,6 +513,11 @@ public class BlightGame extends SimpleApplication {
fixFullscreenMonitor();
}
if (now >= pendingScalingRestoreAt) {
pendingScalingRestoreAt = Long.MAX_VALUE;
restoreScalingFactor();
}
// Watchdog: Vollbild-Verlust durch GNOME/WM (erkennbar an Auflösungs-Mismatch).
if (graphicsSettings != null && graphicsSettings.fullscreen) {
if (now - startTimeMs > 5_000
@@ -798,8 +823,56 @@ public class BlightGame extends SimpleApplication {
glfwSleep(200);
GLFW.glfwFocusWindow(win);
// scaling-factor zeitversetzt zurückschreiben, siehe Feld-Kommentar oben bei
// savedScalingFactor Cinnamon reagiert erst mit etwas Verzögerung auf den
// Monitor-Toggle, ein sofortiger Restore würde von Cinnamons eigenem Reset
// wieder überschrieben.
pendingScalingRestoreAt = System.currentTimeMillis() + 2_000;
} catch (Throwable e) {
log.warn("[Grafik] Vollbild-Fix fehlgeschlagen: {}", e.getMessage(), e);
}
}
/** Liest den aktuellen Cinnamon-Skalierungsfaktor, um ihn nach dem Vollbild-Fix
* wiederherzustellen (siehe Feld-Kommentar bei savedScalingFactor). */
private void captureScalingFactor() {
try {
Process p = new ProcessBuilder(
"gsettings", "get", "org.cinnamon.desktop.interface", "scaling-factor")
.redirectErrorStream(true).start();
String out = new String(p.getInputStream().readAllBytes()).trim();
p.waitFor();
// Format ist z.B. "uint32 1" letztes Token ist der Wert. Nicht per
// replaceAll("[^0-9]","") Ziffern rausfiltern: "uint32" enthält selbst
// die Ziffern 3 und 2, das hängt sie vor den echten Wert (1 -> "321",
// 321 -> "32321", ...) und schaukelt sich exponentiell hoch.
String[] parts = out.split("\\s+");
String value = parts[parts.length - 1];
savedScalingFactor = value.matches("[0-9]+") ? value : null;
log.info("[Grafik] scaling-factor gesichert: {}", savedScalingFactor);
} catch (Exception e) {
log.debug("[Grafik] scaling-factor konnte nicht gelesen werden (evtl. kein Cinnamon): {}", e.getMessage());
savedScalingFactor = null;
}
}
/** Schreibt den zuvor gesicherten Cinnamon-Skalierungsfaktor zurück. */
private void restoreScalingFactor() {
if (savedScalingFactor == null) return;
try {
new ProcessBuilder(
"gsettings", "set", "org.cinnamon.desktop.interface", "scaling-factor", savedScalingFactor)
.start().waitFor();
log.info("[Grafik] scaling-factor wiederhergestellt: {}", savedScalingFactor);
} catch (Exception e) {
log.warn("[Grafik] scaling-factor konnte nicht wiederhergestellt werden: {}", e.getMessage());
}
}
@Override
public void stop() {
restoreScalingFactor();
super.stop();
}
}

View File

@@ -373,7 +373,7 @@ public class WorldScene extends BaseAppState {
dayNight.getDayTime().setTimeOfDay(0.5f);
} else if (envCamFrames == 30) {
log.info("[WorldScene] Starte LightProbe-Backen bei Mittag (Frame {})...", envCamFrames);
final float restoreTime = 0.25f;
final float restoreTime = 0.5f; // Spielstart-Uhrzeit, siehe DayTime-Default
LightProbeFactory.updateProbe(probe, envCam, rootNode,
new JobProgressAdapter<LightProbe>() {
@Override public void done(LightProbe result) {

View File

@@ -87,7 +87,7 @@ public class DayNightState extends BaseAppState implements TimeListener {
// ── Konstruktoren ─────────────────────────────────────────────────────────
/** Game-Modus: Schatten aktiv, 5-Minuten-Tag. */
/** Game-Modus: Schatten aktiv, 96-Minuten-Tag (siehe DayTime.DEFAULT_DAY_DURATION). */
public DayNightState() {
this(new DayTime(), true);
}