[ALL] Add Prepatcher Warning

This commit is contained in:
Ben C 2023-05-13 18:55:59 -04:00
parent 19dfbb800a
commit 606f366d78
No known key found for this signature in database
GPG Key ID: 556064B755159BBC
9 changed files with 80 additions and 25 deletions

View File

@ -1,2 +1,4 @@
[alias]
xtask = "run --package xtask --"
xtask = "run --package xtask --"
lint = "clippy --all-targets -- -D warnings"

View File

@ -306,12 +306,21 @@ async fn run_from_cli(cli: BaseCli) -> Result<()> {
Commands::Enable { unique_name } | Commands::Disable { unique_name } => {
let db = LocalDatabase::fetch(&config.owml_path)?;
let enable = matches!(cli.command, Commands::Enable { unique_name: _ });
let mut show_warnings_for: Vec<String> = vec![];
if unique_name == "*" || unique_name == "all" {
for local_mod in db.valid() {
toggle_mod(&local_mod.manifest.unique_name, &db, enable, false)?;
show_warnings_for.extend(toggle_mod(
&local_mod.manifest.unique_name,
&db,
enable,
false,
)?);
}
} else {
toggle_mod(unique_name, &db, enable, r)?;
show_warnings_for = toggle_mod(unique_name, &db, enable, r)?;
}
for mod_name in show_warnings_for {
warn!("========\n{mod_name} possibly modified game files.\nIn order to disable it completely, use the \"verify game files\" option in Steam / Epic.\nCheck {mod_name}'s readme for more information.\n========")
}
}
Commands::LogServer { port } => {

View File

@ -17,6 +17,12 @@ pub struct LocalMod {
pub manifest: ModManifest,
}
impl LocalMod {
pub fn uses_pre_patcher(&self) -> bool {
self.manifest.patcher.is_some()
}
}
/// Represents a mod that completely failed to load
#[typeshare]
#[derive(Serialize, Clone)]
@ -157,6 +163,7 @@ pub struct ModManifest {
pub conflicts: Option<Vec<String>>,
pub paths_to_preserve: Option<Vec<String>>,
pub warning: Option<ModWarning>,
pub patcher: Option<String>,
}
/// Represents a warning a mod wants to show to the user on start

View File

@ -56,6 +56,11 @@ pub fn get_mod_enabled(mod_path: &Path) -> Result<bool> {
/// Toggle a mod to a given enabled value.
/// Also support applying this action recursively.
///
///
/// ## Returns
///
/// A list of mod names that were disabled and use pre patchers, and therefore **should alert the user to check the mod's README for instructions on how to fully disable it**.
///
/// ## Errors
///
/// If we can't read/save to the config files of the mod or (if recursive is true) any of it's dependents.
@ -65,19 +70,27 @@ pub fn toggle_mod(
local_db: &LocalDatabase,
enabled: bool,
recursive: bool,
) -> Result<()> {
) -> Result<Vec<String>> {
let mut show_warnings_for: Vec<String> = vec![];
let local_mod = local_db
.get_mod(unique_name)
.ok_or_else(|| anyhow!("Mod {} not found", unique_name))?;
let config_path = PathBuf::from(&local_mod.mod_path).join("config.json");
if !enabled && local_mod.uses_pre_patcher() {
show_warnings_for.push(local_mod.manifest.name.clone());
}
if config_path.is_file() {
let mut config = read_config(&config_path)?;
config.enabled = enabled;
write_config(&config, &config_path)?;
} else {
generate_config(&config_path)?;
toggle_mod(unique_name, local_db, enabled, recursive)?;
show_warnings_for.extend(toggle_mod(unique_name, local_db, enabled, recursive)?);
}
if recursive {
if let Some(deps) = local_mod.manifest.dependencies.as_ref() {
for dep in deps.iter() {
@ -98,12 +111,12 @@ pub fn toggle_mod(
}
}
if flag {
toggle_mod(
show_warnings_for.extend(toggle_mod(
&dep_mod.manifest.unique_name,
local_db,
enabled,
recursive,
)?;
)?);
}
}
} else {
@ -112,7 +125,7 @@ pub fn toggle_mod(
}
}
}
Ok(())
Ok(show_warnings_for)
}
#[cfg(test)]

View File

@ -208,24 +208,25 @@ pub async fn toggle_mod(
unique_name: &str,
enabled: bool,
state: tauri::State<'_, State>,
) -> Result {
) -> Result<Vec<String>> {
let db = state.local_db.read().await;
owmods_core::toggle::toggle_mod(unique_name, &db, enabled, false)?;
Ok(())
let show_warnings_for = owmods_core::toggle::toggle_mod(unique_name, &db, enabled, false)?;
Ok(show_warnings_for)
}
#[tauri::command]
pub async fn toggle_all(enabled: bool, state: tauri::State<'_, State>) -> Result {
pub async fn toggle_all(enabled: bool, state: tauri::State<'_, State>) -> Result<Vec<String>> {
let local_db = state.local_db.read().await;
let mut show_warnings_for: Vec<String> = vec![];
for local_mod in local_db.valid() {
owmods_core::toggle::toggle_mod(
show_warnings_for.extend(owmods_core::toggle::toggle_mod(
&local_mod.manifest.unique_name,
&local_db,
enabled,
false,
)?;
)?);
}
Ok(())
Ok(show_warnings_for)
}
#[tauri::command]

View File

@ -77,6 +77,8 @@
"Outdated": "This mod is outdated, consider updating (latest version is v$payload$)",
"PLATFORM": "Platform: $platform$",
"PRERELEASE_WARNING": "Prereleases are experimental versions of mods that may not work correctly. Are you sure you want to install?",
"PREPATCHER_WARNING": "$name$ possibly modified game files. In order to disable it completely, use the \"verify game files\" option in Steam / Epic. Check $name$'s readme for more information.",
"PREPATCHER_WARNING_TITLE": "Warning for $name$",
"Pink": "Pink",
"Purple": "Purple",
"RAINBOW": "Rainbow Mode",

View File

@ -37,8 +37,8 @@ const commandInfo = {
getLocalMod: $<ModCommand<UnsafeLocalMod>>("get_local_mod"),
getRemoteMod: $<ModCommand<RemoteMod>>("get_remote_mod"),
getLogLine: $<CommandInfo<{ port: number; line: number }, GameMessage>>("get_game_message"),
toggleMod: $<ActionCommand<{ uniqueName: string; enabled: boolean }>>("toggle_mod"),
toggleAll: $<ActionCommand<{ enabled: boolean }>>("toggle_all"),
toggleMod: $<CommandInfo<{ uniqueName: string; enabled: boolean }, string[]>>("toggle_mod"),
toggleAll: $<CommandInfo<{ enabled: boolean }, string[]>>("toggle_all"),
openModFolder: $<ModAction>("open_mod_folder"),
openModReadme: $<ModAction>("open_mod_readme"),
uninstallMod: $<ModAction>("uninstall_mod"),

View File

@ -7,6 +7,7 @@ import ModValidationModal, {
import { useGetTranslation } from "@hooks";
import { memo, useCallback, useEffect, useRef, useState } from "react";
import UnsafeModRow from "./UnsafeModRow";
import { dialog } from "@tauri-apps/api";
const LocalMods = memo(function LocalMods() {
const validationModalRef = useRef<ModValidationModalHandle>();
@ -20,12 +21,23 @@ const LocalMods = memo(function LocalMods() {
commands.refreshLocalDb();
}, []);
const onToggleAll = useCallback((enabled: boolean) => {
commands
.toggleAll({ enabled })
.then(() => commands.refreshLocalDb())
.catch(console.warn);
}, []);
const onToggleAll = useCallback(
(enabled: boolean) => {
commands
.toggleAll({ enabled })
.then((warnings) => {
commands.refreshLocalDb();
for (const modName of warnings) {
dialog.message(getTranslation("PREPATCHER_WARNING", { name: modName }), {
type: "warning",
title: getTranslation("PREPATCHER_WARNING_TITLE", { name: modName })
});
}
})
.catch(console.warn);
},
[getTranslation]
);
const onSearch = (newFilter: string) => {
if (activeTimeout !== null) {

View File

@ -5,6 +5,7 @@ import { confirm } from "@tauri-apps/api/dialog";
import { LocalMod, ModValidationError } from "@types";
import { memo, useCallback } from "react";
import LocalModRow from "./LocalModRow";
import { dialog } from "@tauri-apps/api";
interface LocalModRowProps {
mod: LocalMod;
@ -45,9 +46,17 @@ const ValidModRow = memo(function ValidModRow({ mod, onValidationClick }: LocalM
uniqueName: mod.manifest.uniqueName,
enabled: newVal
})
.then(() => commands.refreshLocalDb());
.then((warnings) => {
commands.refreshLocalDb();
for (const modName of warnings) {
dialog.message(getTranslation("PREPATCHER_WARNING", { name: modName }), {
type: "warning",
title: getTranslation("PREPATCHER_WARNING_TITLE", { name: modName })
});
}
});
},
[mod.manifest.uniqueName]
[mod.manifest.uniqueName, getTranslation]
);
const onOpen = useCallback(() => {