warning dialog for unsupported groove.exe versions at start and before the first apply of a session (nothing blocked)

This commit is contained in:
MineTec committed 2026-11-07 18:32:42 +01:00
1 parent ff6673af66
commit 932ccf5fc8
6 files changed
+123 -2

No files matched your search

+2 -1
View File
@@ -4,7 +4,8 @@
- **English game version supported.** All exe mods (boot to level, cheats, intro skip, practice
tools, free camera) and the base patch now also work with the English groove.exe of
2000-10-17; other unknown versions still stop with a clear message.
2000-10-17. With any other version LlamaMod warns at start and before the first Apply (nothing
is blocked); mods that change groove.exe then stop with a clear message.
- **Display diagnostics option renamed and explained.** The cheats option is now called
"Troubleshooting: write display diagnostics" and warns that the game switches through every
screen mode of every monitor at start (screens go black for a while). It stays off by default.
+2 -1
View File
@@ -104,7 +104,8 @@ after an update, **Settings → Clear cache** throws it away; active mods are re
**Which versions of the game work?**
The German CD (`groove.exe` of 2001-02-12) and the English first release (2000-10-17) are
supported, including every mod. With another version the level mods still work, but the mods
supported, including every mod. With another version LlamaMod shows a warning at start and before
the first Apply (nothing is blocked); the level mods still work, but the mods
marked *modifies groove.exe* stop with "unknown program version" – the first lines of
`logs/apply.log` name the version LlamaMod found. Please report it together with that
`groove.exe`, then it can be added.
@@ -62,6 +62,7 @@ final class MainFrame extends JFrame {
private boolean crashReported;
private boolean oldWineAccepted;
private final RecoveryNotice recoveryNotice = new RecoveryNotice();
final UnsupportedExeWarning exeWarning = new UnsupportedExeWarning();
private boolean recoveryRunning;
MainFrame(AppState state) {
@@ -223,6 +224,9 @@ final class MainFrame extends JFrame {
showRecovery(state.recovery);
state.recovery = ModManager.Recovery.NONE;
}
if (inst) {
SwingUtilities.invokeLater(() -> exeWarning.atStart(this, state));
}
}
/** Tells the user once that an interrupted apply was repaired; BUSY is retried later. */
@@ -677,6 +677,7 @@ final class ModsPanel extends JPanel {
}
List<Mod> mods = selected();
ModManager mm = frame.state.modManager;
frame.exeWarning.beforeApply(frame, frame.state);
if (!AntivirusDialogs.notice(frame, mm.exeMods(mods), true)) {
return;
}
@@ -0,0 +1,86 @@
package com.eliasmueller.llamamod.ui;
import com.eliasmueller.llamamod.exe.GameExe;
import com.eliasmueller.llamamod.platform.FileOps;
import com.eliasmueller.llamamod.platform.Integrity;
import java.awt.Component;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.stream.Collectors;
import javax.swing.JOptionPane;
/**
* Warns (never blocks) when the installed groove.exe is not one of the supported builds: once at
* start and once before the first Apply of a session.
*/
final class UnsupportedExeWarning {
private boolean shownAtStart;
private boolean shownAtApply;
private String checkedSha;
private boolean unsupported;
/** The warning text, or null if the build is supported or unknown because nothing is installed. */
static String message(String sha256) {
if (sha256 == null || sha256.isEmpty()) {
return null;
}
for (GameExe.Build b : GameExe.Build.values()) {
if (b.sha256.equalsIgnoreCase(sha256)) {
return null;
}
}
return "You are running an unsupported version of the game. Mods, especially mods that modify"
+ " groove.exe, probably won't work.\n\nSupported are: "
+ Arrays.stream(GameExe.Build.values())
.map(GameExe.Build::toString)
.collect(Collectors.joining(", "))
+ ".";
}
/** SHA-256 of the set-up original groove.exe ("" if not installed or unreadable). */
static String installedSha(AppState state) {
if (!state.cfg.installed()) {
return "";
}
if (!state.cfg.exeSha256.isEmpty()) {
return state.cfg.exeSha256;
}
try {
Path hd = state.paths.originalHd();
Path exe = Files.isDirectory(hd) ? Integrity.find(hd, "groove.exe") : null;
return exe != null && Files.isRegularFile(exe) ? FileOps.sha256(exe) : "";
} catch (IOException e) {
return "";
}
}
private String current(AppState state) {
String sha = installedSha(state);
if (!sha.equals(checkedSha)) {
checkedSha = sha;
unsupported = message(sha) != null;
shownAtStart = false;
shownAtApply = false;
}
return unsupported ? message(sha) : null;
}
void atStart(Component parent, AppState state) {
String m = current(state);
if (m != null && !shownAtStart) {
shownAtStart = true;
JOptionPane.showMessageDialog(parent, m, "Unsupported game version", JOptionPane.WARNING_MESSAGE);
}
}
/** Shows the warning before the first Apply of a session; Apply always continues afterwards. */
void beforeApply(Component parent, AppState state) {
String m = current(state);
if (m != null && !shownAtApply) {
shownAtApply = true;
JOptionPane.showMessageDialog(parent, m, "Unsupported game version", JOptionPane.WARNING_MESSAGE);
}
}
}
@@ -0,0 +1,28 @@
package com.eliasmueller.llamamod.ui;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.eliasmueller.llamamod.exe.GameExe;
import org.junit.jupiter.api.Test;
class UnsupportedExeWarningTest {
@Test
void supportedBuildsAndMissingInstallGiveNoWarning() {
for (GameExe.Build b : GameExe.Build.values()) {
assertNull(UnsupportedExeWarning.message(b.sha256));
assertNull(UnsupportedExeWarning.message(b.sha256.toUpperCase()));
}
assertNull(UnsupportedExeWarning.message(""));
assertNull(UnsupportedExeWarning.message(null));
}
@Test
void otherBuildsAreWarnedAboutAndTheSupportedOnesListed() {
String m = UnsupportedExeWarning.message("00".repeat(32));
assertNotNull(m);
assertTrue(m.startsWith("You are running an unsupported version of the game."), m);
assertTrue(m.contains("German version of 2001-02-12") && m.contains("English version of 2000-10-17"), m);
}
}