VNC-Steuerung verbessern: Low-Latency, Maus, Tastatur, Resize
Die Steuerung ist jetzt auf Minecraft (Menü, Chat, Inventar, AFK-Farmen) optimiert. Für Mouselook/PVP bleibt VNC ungeeignet (Protokollgrenze, dokumentiert). x11vnc (serverseitig, entrypoint.sh): - -threads: parallele I/O-Threads → weniger Eingabe-Lag - -pointer_mode 4: flüssigere Mausübertragung (Default 1 ist träge) - -norepeat: verhindert doppelte Tastaturwiederholungen im Spiel - -nodpms -nofbpm -nowf -nowcr: Energiesparen/Rate-Limiting aus - Über X11VNC_EXTRA env var frei konfigurierbar noVNC-Client (VncViewer.vue): - resize=remote statt scaling: Xvfb folgt Fenstergröße (1:1-Maus-Mapung) - reconnect=1: auto-Reconnect bei Abbruch - clipboard=1: Zwischenablage Browser <-> Container - view_only=0: Eingabe explizit freigeschaltet - Klick ins Bild setzt Tastaturfokus ins iframe - Hinweis auf Mausfreigabe (Strg+Alt+Umschalt), Fokus-Button README: neuer Abschnitt "Steuerung über VNC" mit Grenzerklärung. .env.example + docker-compose.yml: X11VNC_EXTRA durchgereicht.
This commit is contained in:
parent
b8a99e6e9e
commit
af073e77ec
5 changed files with 134 additions and 19 deletions
|
|
@ -24,6 +24,13 @@ WEB_PORT=8080
|
|||
# Optionales VNC-Passwort. Leer = ohne Passwort (nur für lokales Netz gedacht).
|
||||
VNC_PASSWORD=
|
||||
|
||||
# Zusätzliche x11vnc-Flags für die Low-Latency-/Eingabe-Optimierung.
|
||||
# Defaults sind auf Minecraft (Menü, Chat, Inventar, AFK-Farmen) abgestimmt:
|
||||
# -threads -pointer_mode 4 -norepeat -nodpms -nofbpm -nowf -nowcr
|
||||
# Für langsames Netz z.B. Kompression dazuschalten:
|
||||
# -threads -pointer_mode 4 -norepeat -tight -compresslevel 6 -quality 7
|
||||
X11VNC_EXTRA=
|
||||
|
||||
# noVNC-Pfad. Leer = Dashboard startet direkt im VNC-Viewer.
|
||||
# Z.B. "vnc.html" für die standalone noVNC-Seite ohne Dashboard-Frame.
|
||||
NOVNC_PATH=
|
||||
|
|
|
|||
47
README.md
47
README.md
|
|
@ -111,6 +111,53 @@ Die konkrete Einrichtung hängt von deiner Farm ab. Typische Schritte:
|
|||
| `DISPLAY_REFRESH` | `60` | Bildwiederholrate des virtuellen Displays. |
|
||||
| `WEB_PORT` | `8080` | Browser-Port. |
|
||||
| `VNC_PASSWORD` | *(leer)* | Optional. Leer = ohne Auth (nur lokales Netz!). |
|
||||
| `X11VNC_EXTRA` | siehe `.env` | Low-Latency-/Eingabe-Flags für x11vnc. |
|
||||
|
||||
---
|
||||
|
||||
## Steuerung über VNC
|
||||
|
||||
Die Steuerung ist auf **Minecraft-Menü, Chat, Inventar und AFK-Farmen**
|
||||
optimiert. Sie ist **nicht** für aktives PVP/Mouselook gedacht — das ist eine
|
||||
grundsätzliche Grenze von VNC (siehe unten).
|
||||
|
||||
**Bedienung im Browser:**
|
||||
- **Klick ins Bild** → setzt den Tastaturfokus ins Spielfenster (Tasten gehen
|
||||
ans Spiel, nicht an den Browser).
|
||||
- **Maus freigeben** → `Strg + Alt + Umschalt` (noVNC-Standard).
|
||||
- **Vollbild** → Button in der Toolbar; für Minecraft flächendeckend.
|
||||
- **Zwischenablage** → automatisch verknüpft (Login-Codes / Server-IPs kopieren
|
||||
geht direkt zwischen Browser und Container).
|
||||
|
||||
**Was automatisch eingestellt ist:**
|
||||
- `resize=remote`: die Xvfb-Auflösung folgt der Fenstergröße (1:1-Maus-Mapung,
|
||||
keine Skalierungs-Unschärfe).
|
||||
- `reconnect=1`: bei Abbruch verbindet noVNC selbstständig neu.
|
||||
- x11vnc mit `-threads -pointer_mode 4 -norepeat`:
|
||||
- `-threads` → parallele I/O-Threads, weniger Eingabe-Lag.
|
||||
- `-pointer_mode 4` → flüssigere Mausübertragung als der Default (1).
|
||||
- `-norepeat` → verhindert doppelte Tastaturwiederholungen im Spiel.
|
||||
- `-nodpms -nofbpm -nowf -nowcr` → Energiesparen und Rate-Limiting aus, damit
|
||||
nichts nach Leerlauf ruckelt.
|
||||
|
||||
**Für langsames Netz** (z. B. Remote über Internet statt LAN) in der `.env`
|
||||
Kompression aktivieren:
|
||||
```
|
||||
X11VNC_EXTRA=-threads -pointer_mode 4 -norepeat -tight -compresslevel 6 -quality 7
|
||||
```
|
||||
|
||||
### Warum Mouselook nicht richtig geht
|
||||
|
||||
VNC überträgt **absolute** Mauskoordinaten („Cursor an Position X/Y"). Minecraft
|
||||
wie jedes FPS-artige Spiel braucht aber **relative** Mausbewegung und setzt den
|
||||
Cursor dafür jeden Frame auf die Bildmitte zurück ([noVNC Issue #1493][novnc1493]).
|
||||
Darum lässt sich die Kamera per VNC nicht sinnfrei drehen.
|
||||
|
||||
Für Menü, Buttons, Chat, Inventar und reines AFK auf einer Farm ist das ohne
|
||||
Bedeutung. Wer wirklich remote *spielen* will, braucht ein anderes Protokoll
|
||||
(Sunshine/Moonlight statt VNC) — das ist mit dieser Architektur nicht abgedeckt.
|
||||
|
||||
[novnc1493]: https://github.com/novnc/noVNC/issues/1493
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ services:
|
|||
DISPLAY_REFRESH: ${DISPLAY_REFRESH:-60}
|
||||
DISPLAY_DEPTH: ${DISPLAY_DEPTH:-24}
|
||||
VNC_PASSWORD: ${VNC_PASSWORD:-}
|
||||
X11VNC_EXTRA: ${X11VNC_EXTRA:--threads -pointer_mode 4 -norepeat -nodpms -nofbpm -nowf -nowcr}
|
||||
NOVNC_PATH: ${NOVNC_PATH:-}
|
||||
|
||||
ports:
|
||||
|
|
|
|||
|
|
@ -65,9 +65,22 @@ else
|
|||
VNC_PWFLAG="-nopw"
|
||||
fi
|
||||
|
||||
# Low-Latency-x11vnc-Optionen. Für Minecraft sind vor allem wichtig:
|
||||
# -threads parallele Eingabe-/Ausgabe-Threads → weniger Lag
|
||||
# -pointer_mode 4 flüssigere Mausübertragung (Default 1 ist träge)
|
||||
# -norepeat Server-seite Tastaturwiederholung unterdrücken (sonst
|
||||
# doppelte Auto-Repeat-Tasten im Spiel)
|
||||
# -nocursorshape / -cursor none kein Cursor-Shape-Traffic (Cursor ist eh
|
||||
# vom Spiel übermalt); -cursorX aber als sichtbarer Fallback
|
||||
# -nodpms -nofbpm Energiesparen aus (sonst ruckelt es nach Leerlauf)
|
||||
# -nowf -nowcr kein Wireframe/Rate-Limit beim Fensterziehen
|
||||
# -noxdamage-suffix stabilereDamage-Erfassung
|
||||
# Encoding/Qualität werden vom Client (noVNC) ausgehandelt, nicht hier erzwungen.
|
||||
X11VNC_EXTRA="${X11VNC_EXTRA:--threads -pointer_mode 4 -norepeat -nodpms -nofbpm -nowf -nowcr}"
|
||||
|
||||
cat > /tmp/x11vnc.conf <<EOF
|
||||
[program:x11vnc]
|
||||
command=/usr/bin/x11vnc -display :0 -forever -shared ${VNC_PWFLAG} -rfbport 5900
|
||||
command=/usr/bin/x11vnc -display :0 -forever -shared ${VNC_PWFLAG} -rfbport 5900 ${X11VNC_EXTRA}
|
||||
priority=20
|
||||
autostart=true
|
||||
autorestart=true
|
||||
|
|
|
|||
|
|
@ -16,18 +16,28 @@ const errorMsg = ref<string | null>(null)
|
|||
const iframeEl = ref<HTMLIFrameElement | null>(null)
|
||||
const iframeKey = ref(0)
|
||||
|
||||
// noVNC-URL: autoconnect=1, resize=scaling, Pfad zum websockify.
|
||||
// noVNC-URL mit auf Steuerung/Spiele optimierten Parametern:
|
||||
// resize=remote — passt die Xvfb-Auflösung an die Fenstergröße an
|
||||
// (statt nur zu skalieren). Korrekte 1:1-Maus-Mapung,
|
||||
// keine Unschärfe. Fällt auf 'scale' zurück, falls der
|
||||
// Server kein Resize unterstützt.
|
||||
// reconnect=1 — bei Verbindungsabbruch automatisch neu verbinden.
|
||||
// path=websockify — noVNC spricht den WS-Endpunkt relativ an.
|
||||
// show_dot=1 — lokalen Punkt-Cursor zeigen (Zielhilfe).
|
||||
// view_only=0 — Eingabe explizit freischalten.
|
||||
// clipboard=1 — Zwischenablage zwischen Browser und VM verknüpfen
|
||||
// (wichtig für Login-Codes / Server-IPs kopieren).
|
||||
const novncUrl = computed(() => {
|
||||
const host = window.location.hostname
|
||||
const port = window.location.port || String(window.location.port)
|
||||
const port = window.location.port
|
||||
const params = new URLSearchParams({
|
||||
autoconnect: '1',
|
||||
resize: 'scaling',
|
||||
// noVNC spricht relativ 'websockify' an → nginx mappt /websockify.
|
||||
reconnect: '1',
|
||||
resize: 'remote',
|
||||
path: 'websockify',
|
||||
// show_dot_cursor hilft beim Zielen im VNC-Fenster.
|
||||
show_dot: '1',
|
||||
// host/port für die Anzeige im noVNC-eigenen UI; iframe nutzt aber path.
|
||||
view_only: '0',
|
||||
clipboard: '1',
|
||||
host,
|
||||
port,
|
||||
})
|
||||
|
|
@ -47,6 +57,20 @@ function onIframeLoad() {
|
|||
state.value = 'connected'
|
||||
}
|
||||
|
||||
// Fokus in den iframe setzen, damit Tastatureingaben ans Spiel gehen.
|
||||
// noVNC selbst fängt die Keys im iframe ab; wir müssen nur dorthin fokussieren.
|
||||
function focusFrame() {
|
||||
const el = iframeEl.value
|
||||
if (!el) return
|
||||
// Versuch, das innere Dokument zu fokussieren (gleiche Origin → erlaubt).
|
||||
try {
|
||||
el.contentWindow?.focus()
|
||||
} catch {
|
||||
/* Cross-Origin → iframe focus als Fallback */
|
||||
el.focus()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
state.value = 'connecting'
|
||||
})
|
||||
|
|
@ -54,15 +78,17 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<div class="vnc">
|
||||
<iframe
|
||||
ref="iframeEl"
|
||||
:key="iframeKey"
|
||||
class="vnc__frame"
|
||||
:src="novncUrl"
|
||||
title="Minecraft via noVNC"
|
||||
allow="clipboard-read; clipboard-write; fullscreen"
|
||||
@load="onIframeLoad"
|
||||
></iframe>
|
||||
<div class="vnc__stage" @click="focusFrame">
|
||||
<iframe
|
||||
ref="iframeEl"
|
||||
:key="iframeKey"
|
||||
class="vnc__frame"
|
||||
:src="novncUrl"
|
||||
title="Minecraft via noVNC"
|
||||
allow="clipboard-read; clipboard-write; fullscreen"
|
||||
@load="onIframeLoad"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<div v-if="state !== 'connected'" class="vnc__overlay">
|
||||
<div class="vnc__overlay-inner">
|
||||
|
|
@ -91,9 +117,11 @@ onMounted(() => {
|
|||
}}
|
||||
</span>
|
||||
<span class="vnc__hint">
|
||||
Maus im Fenster festhalten? Im noVNC-Seitenmenge „Clip to Window“.
|
||||
Klick ins Bild für Tastatur-Fokus. Maus freigeben:
|
||||
<kbd>Strg</kbd>+<kbd>Alt</kbd>+<kbd>Umschalt</kbd>
|
||||
</span>
|
||||
<button @click="reload">Aktualisieren</button>
|
||||
<button @click="focusFrame" :disabled="state !== 'connected'">Fokus</button>
|
||||
<button @click="reload" :disabled="state === 'connecting'">Aktualisieren</button>
|
||||
<button
|
||||
@click="iframeEl?.requestFullscreen()"
|
||||
:disabled="state !== 'connected'"
|
||||
|
|
@ -113,10 +141,18 @@ onMounted(() => {
|
|||
background: #000;
|
||||
}
|
||||
|
||||
.vnc__frame {
|
||||
.vnc__stage {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vnc__frame {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
background: #000;
|
||||
}
|
||||
|
|
@ -165,6 +201,17 @@ onMounted(() => {
|
|||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.vnc__hint kbd {
|
||||
font-family: var(--mono);
|
||||
background: var(--bg-elev-2);
|
||||
border: 1px solid var(--border);
|
||||
border-bottom-width: 2px;
|
||||
border-radius: 4px;
|
||||
padding: 1px 5px;
|
||||
font-size: 10px;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.vnc__badge.connected {
|
||||
background: var(--accent);
|
||||
color: #0f1115;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue