Upload via GUI (324 Dateien)
This commit is contained in:
+59
-3
@@ -222,6 +222,45 @@ let letzterUpdateCheck = { checking: true };
|
||||
// Hauptfenster hat seine Empfänger registriert – erst dann den Update-Hinweis schicken
|
||||
const hauptfensterBereit = new Promise((resolve) => ipcMain.once('renderer:ready', resolve));
|
||||
|
||||
/*
|
||||
* Update und laufendes Spiel
|
||||
* --------------------------
|
||||
* Ein Update beendet den Launcher (und der Installer ersetzt dessen Dateien). Das darf nie
|
||||
* passieren, solange Minecraft läuft: Das Update wird erst installiert, wenn kein Spiel mehr
|
||||
* läuft. Damit es trotzdem nicht untergeht, bekommt der Spieler im Spiel eine Einblendung
|
||||
* (wie bei den Freunde-Hinweisen), und nach dem letzten Spielende öffnet sich der Update-Dialog.
|
||||
*/
|
||||
const spielLaeuft = () => laufendeInstanzen.size > 0;
|
||||
const SPIEL_LAEUFT_TEXT = 'Minecraft läuft noch – das Update wird erst installiert, wenn kein Spiel mehr läuft. Bitte zuerst das Spiel beenden.';
|
||||
let updateWartetAufSpielende = false; // Hinweis kam im Spiel -> nach Spielende den Dialog zeigen
|
||||
let angekuendigteVersion = null; // Dialog schon gezeigt, nicht bei jeder Prüfung wieder
|
||||
const updateImSpielGemeldet = new Set(); // pid des Spiels, das den Hinweis schon bekam
|
||||
|
||||
// Einblendung auf dem Minecraft-Fenster, einmal je Spielstart
|
||||
async function meldeUpdateImSpiel() {
|
||||
const info = pendingUpdateInfo;
|
||||
if (!info || !info.available || !spielLaeuft()) return;
|
||||
for (const pid of [...laufendePid.values()]) {
|
||||
if (updateImSpielGemeldet.has(pid)) continue;
|
||||
// false, solange das Spielfenster noch nicht da ist – dann beim nächsten Durchlauf erneut
|
||||
const gezeigt = await zeigeIngameOverlay('AeroMC-Update', [
|
||||
`AeroMC ${info.latestVersion || 'Update'} ist verfügbar.`,
|
||||
'Bitte nach dem Spiel installieren.',
|
||||
], pid, 10000).catch(() => false);
|
||||
// nur vermerken, wenn dieses Spiel noch läuft – sonst bliebe nach seinem Ende ein falscher Zustand zurück
|
||||
if (gezeigt && spielLaeuft() && [...laufendePid.values()].includes(pid)) { updateImSpielGemeldet.add(pid); updateWartetAufSpielende = true; }
|
||||
}
|
||||
}
|
||||
|
||||
// Dialog zeigen – aber nie, während ein Spiel läuft (er würde dem Spiel den Fokus nehmen)
|
||||
function kuendigeUpdateAn(info) {
|
||||
if (!info || !info.available) return;
|
||||
if (spielLaeuft()) { updateWartetAufSpielende = true; meldeUpdateImSpiel().catch(() => {}); return; }
|
||||
if (info.latestVersion && info.latestVersion === angekuendigteVersion) return;
|
||||
angekuendigteVersion = info.latestVersion || true;
|
||||
broadcast('update:available', info);
|
||||
}
|
||||
|
||||
async function pruefeAufUpdates() {
|
||||
letzterUpdateCheck = { checking: true };
|
||||
broadcast('update:checked', letzterUpdateCheck);
|
||||
@@ -357,7 +396,15 @@ ipcMain.handle('recording:getServer', (_e, id) => letzteQuickPlayServer.get(id)
|
||||
const laufendePid = new Map(); // instanceId -> pid des zuletzt gestarteten Minecraft-Prozesses
|
||||
// Instanzen, deren Spiel gerade läuft (für den pulsierenden Rand der Karte)
|
||||
const laufendeInstanzen = new Set();
|
||||
function meldeLaufende() { broadcast('game:laufend', [...laufendeInstanzen]); }
|
||||
function meldeLaufende() {
|
||||
broadcast('game:laufend', [...laufendeInstanzen]);
|
||||
// letztes Spiel beendet und ein Update wartet -> jetzt den Update-Dialog zeigen
|
||||
if (!spielLaeuft() && updateWartetAufSpielende) {
|
||||
updateWartetAufSpielende = false;
|
||||
updateImSpielGemeldet.clear();
|
||||
kuendigeUpdateAn(pendingUpdateInfo);
|
||||
}
|
||||
}
|
||||
ipcMain.handle('game:laufend', () => [...laufendeInstanzen]);
|
||||
const kontoPid = new Map(); // kontoId -> pid, für den Ingame-Toast: der muss auf DEM Fenster
|
||||
// des prüfenden Kontos erscheinen, nicht auf irgendeinem laufenden Minecraft-Fenster
|
||||
@@ -1169,8 +1216,13 @@ app.whenReady().then(() => {
|
||||
pruefeAufUpdates().then(async (info) => {
|
||||
if (!info.available) return;
|
||||
await hauptfensterBereit;
|
||||
broadcast('update:available', info);
|
||||
kuendigeUpdateAn(info);
|
||||
}).catch(() => {});
|
||||
// Der Launcher bleibt oft tagelang offen: alle 3 Stunden erneut prüfen. Läuft ein Spiel,
|
||||
// gibt es nur die Einblendung im Spiel, den Dialog erst nach Spielende.
|
||||
setInterval(() => { pruefeAufUpdates().then(kuendigeUpdateAn).catch(() => {}); }, 3 * 60 * 60 * 1000);
|
||||
// Hinweis im Spiel, sobald das Spielfenster da ist (auch für ein später gestartetes Spiel)
|
||||
setInterval(() => { meldeUpdateImSpiel().catch(() => {}); }, 30000);
|
||||
|
||||
// Anmelde-Dienste automatisch überwachen (sofort + alle 2 Minuten)
|
||||
setTimeout(() => checkAuthServices(), 2500);
|
||||
@@ -1230,7 +1282,7 @@ ipcMain.handle('settings:save', (_e, patch) => {
|
||||
// Beta-Teilnahme umgeschaltet -> gleich neu nach Updates suchen
|
||||
if (patch && Object.prototype.hasOwnProperty.call(patch, 'betaTeilnahme') && !!patch.betaTeilnahme !== betaStand) {
|
||||
betaStand = !!patch.betaTeilnahme;
|
||||
pruefeAufUpdates().then((info) => { if (info.available) broadcast('update:available', info); }).catch(() => {});
|
||||
pruefeAufUpdates().then((info) => { if (info.available) { angekuendigteVersion = null; kuendigeUpdateAn(info); } }).catch(() => {});
|
||||
}
|
||||
if (patch && Object.prototype.hasOwnProperty.call(patch, 'friendsEnabled')) {
|
||||
aktualisiereFreundeTastenkuerzel();
|
||||
@@ -5575,11 +5627,15 @@ ipcMain.handle('update:lastCheck', () => letzterUpdateCheck);
|
||||
// beliebige Datei als "Update" ausführen lassen.
|
||||
ipcMain.handle('update:install', async () => {
|
||||
try {
|
||||
// Nie während Minecraft läuft: Der Launcher beendet sich für das Update
|
||||
if (spielLaeuft()) { updateWartetAufSpielende = true; return { ok: false, spielLaeuft: true, message: SPIEL_LAEUFT_TEXT }; }
|
||||
const asset = pendingUpdateInfo && pendingUpdateInfo.available ? pendingUpdateInfo.asset : null;
|
||||
if (!asset) throw new Error('Kein geprüftes Update vorhanden – bitte erneut nach Updates suchen.');
|
||||
const file = await updater.downloadAndInstall(asset, (p) => {
|
||||
broadcast('update:progress', p);
|
||||
});
|
||||
// Während des Downloads kann ein Spiel gestartet worden sein – die Datei bleibt liegen
|
||||
if (spielLaeuft()) { updateWartetAufSpielende = true; return { ok: false, spielLaeuft: true, message: SPIEL_LAEUFT_TEXT }; }
|
||||
const res = await updater.applyUpdate(file);
|
||||
// Portable: der Tausch klappt erst, wenn der Launcher die EXE freigibt
|
||||
setTimeout(() => app.quit(), 1200);
|
||||
|
||||
@@ -1711,7 +1711,24 @@ function showUpdateDialog(info) {
|
||||
: (channel
|
||||
? `Für den Kanal ${channel} liegt in diesem Release keine passende Datei bereit. Bitte im Release nachsehen und von Hand aktualisieren.`
|
||||
: 'Die Paketart dieses Launchers lässt sich nicht sicher bestimmen. Bitte das Update von Hand aus dem Release laden.');
|
||||
updHintNormal = el('upd-hint').textContent;
|
||||
show('modal-update');
|
||||
aktualisiereUpdateKnopf();
|
||||
}
|
||||
|
||||
// Solange Minecraft läuft, wird nicht installiert: Der Launcher beendet sich für das Update
|
||||
let updHintNormal = '';
|
||||
let updInstalliertGerade = false;
|
||||
async function aktualisiereUpdateKnopf() {
|
||||
if (!pendingUpdate || !pendingUpdate.asset || updInstalliertGerade) return;
|
||||
let laeuft = false;
|
||||
try { laeuft = ((await window.api.laufendeInstanzen()) || []).length > 0; } catch { /* dann nicht sperren */ }
|
||||
const btn = el('upd-install');
|
||||
btn.disabled = laeuft;
|
||||
btn.textContent = laeuft ? 'Minecraft läuft noch' : 'Installieren';
|
||||
el('upd-hint').textContent = laeuft
|
||||
? 'Das Update wird erst installiert, wenn kein Minecraft mehr läuft. Beende das Spiel – danach kannst du hier auf „Installieren“ klicken.'
|
||||
: updHintNormal;
|
||||
}
|
||||
|
||||
// Links in den Update-Hinweisen im Browser öffnen, nie im Launcher-Fenster
|
||||
@@ -1731,10 +1748,19 @@ async function startUpdate() {
|
||||
const btn = el('upd-install');
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Wird installiert …';
|
||||
updInstalliertGerade = true;
|
||||
el('upd-progress').classList.remove('hidden');
|
||||
el('upd-status').textContent = 'Wird heruntergeladen …';
|
||||
|
||||
const res = await window.api.updateInstall();
|
||||
if (!res.ok) updInstalliertGerade = false;
|
||||
if (!res.ok && res.spielLaeuft) {
|
||||
// Spiel lief schon oder ist während des Downloads gestartet worden
|
||||
el('upd-progress').classList.add('hidden');
|
||||
el('upd-status').textContent = '';
|
||||
aktualisiereUpdateKnopf();
|
||||
return;
|
||||
}
|
||||
if (res.ok) {
|
||||
el('upd-status').textContent = res.kind === 'portable'
|
||||
? 'Launcher schließt sich, wird ersetzt und startet automatisch neu.'
|
||||
@@ -7849,6 +7875,8 @@ window.addEventListener('DOMContentLoaded', async () => {
|
||||
}
|
||||
el('upd-notes').addEventListener('click', updateLinkKlick);
|
||||
window.api.onLaufendeInstanzen(setzeLaufende);
|
||||
// Update-Dialog offen: Knopf freigeben, sobald das letzte Spiel beendet ist (bzw. sperren, wenn eins startet)
|
||||
window.api.onLaufendeInstanzen(() => { if (!el('modal-update').classList.contains('hidden')) aktualisiereUpdateKnopf(); });
|
||||
window.api.laufendeInstanzen().then(setzeLaufende).catch(() => {});
|
||||
el('grid').addEventListener('mousemove', kippeZurMaus);
|
||||
baueLichtpunkte();
|
||||
|
||||
Reference in New Issue
Block a user