Skip to content
This repository has been archived by the owner on Jul 23, 2023. It is now read-only.

Commit

Permalink
Show error and prevent crash when mod manifest is broken
Browse files Browse the repository at this point in the history
  • Loading branch information
Raicuparta committed May 13, 2021
1 parent 49a6220 commit e8c39d8
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 40 deletions.
11 changes: 10 additions & 1 deletion app/components/Mods/ModActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
toggleEnabled,
getLocalMods,
installPrerelease,
isBroken,
} from '../../services';
import { localModList, settingsState } from '../../store';
import { useLoading } from '../../store/loading-state';
Expand Down Expand Up @@ -77,13 +78,16 @@ const ModActions: React.FunctionComponent<Props> = ({ mod }) => {
setAnchorEl(null);
};

const isModBroken = isBroken(mod);
const isModInstalled = mod !== undefined && isInstalled(mod);
const isModOutdated = isOutdated(mod);
const isModInstallable = mod.downloadUrl !== undefined;
const isModDownloadable =
!isLoading && (isModInstalled ? isModOutdated : isModInstallable);
const isInstallHighlighted =
!isLoading && (isModOutdated || (mod.isRequired && !isModInstalled));
!isLoading &&
!isModBroken &&
(isModOutdated || (mod.isRequired && !isModInstalled));

const handleActionError = (actionName: string, error: string) => {
debugConsole.error('error in action', actionName, error);
Expand Down Expand Up @@ -139,6 +143,11 @@ const ModActions: React.FunctionComponent<Props> = ({ mod }) => {
if (isLoading) {
return modsText.actions.loading;
}
if (isModBroken) {
return mod.remoteVersion
? modsText.actions.reinstall
: modsText.actions.cantReinstall;
}
if (isModOutdated && mod.remoteVersion) {
return modsText.actions.update(mod.remoteVersion);
}
Expand Down
12 changes: 8 additions & 4 deletions app/components/Mods/ModTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,14 @@ const useStyles = makeStyles((theme) => ({
const ModTableRow: React.FunctionComponent<Props> = ({ mod }) => {
const styles = useStyles();
const missingDependencyNames = useRecoilValue(missingDependencyIdsState(mod));
const isModBroken = isBroken(mod);
const isModOutdated = isOutdated(mod);

const getVersionColor = () => {
if (isOutdated(mod)) {
if (isModBroken) {
return 'default';
}
if (isModOutdated) {
return 'secondary';
}
if (isInstalled(mod)) {
Expand All @@ -101,7 +105,7 @@ const ModTableRow: React.FunctionComponent<Props> = ({ mod }) => {

const getClassName = () => {
let className = styles.tableRow;
if (isBroken(mod)) {
if (isModBroken) {
className += ` ${styles.brokenRow}`;
} else if (missingDependencyNames.length > 0) {
className += ` ${styles.missingDependencyRow}`;
Expand All @@ -110,7 +114,7 @@ const ModTableRow: React.FunctionComponent<Props> = ({ mod }) => {
};

const getRowTooltip = () => {
if (isBroken(mod)) {
if (isModBroken) {
return modsText.modLoadError(mod.errors);
}
if (missingDependencyNames.length > 0) {
Expand Down Expand Up @@ -153,7 +157,7 @@ const ModTableRow: React.FunctionComponent<Props> = ({ mod }) => {
label={getVersion()}
className={styles.versionChip}
/>
{isModOutdated && (
{!isModBroken && isModOutdated && (
<div className={styles.outdatedChip}>{modsText.outdated}</div>
)}
</TableCell>
Expand Down
6 changes: 5 additions & 1 deletion app/helpers/static-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ export const modsText = {
disable: 'Disable',
enable: 'Enable',
loading: 'Loading...',
reinstall: 'Reinstall',
cantReinstall: 'Could not find mod in database',
update: (version: string) => `Update to ${version}`,
alreadyInstalled: 'Already installed',
alreadyInstalled: 'Installed and up to date',
install: 'Install',
more: 'More...',
openDirectory: 'Show in explorer',
Expand Down Expand Up @@ -91,6 +93,8 @@ export const modsText = {
`Error executing mod ${action}: ${error}`,
duplicateModError: (modUniqueName: string) =>
`Found multiple mods with the same uniqueName (${modUniqueName}). Open the mods directory and make sure you only have one copy of each mod.`,
brokenManifestError: (directoryName: string) =>
`Failed to read manifest.json in mod directory "${directoryName}". Reinstall the mod or contact the mod author to fix this issue.`,
};

export const settingsText = {
Expand Down
86 changes: 52 additions & 34 deletions app/services/get-local-mods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,47 +43,65 @@ export function getLocalMods(owmlPath: string) {
const localMods: Mod[] = [getOwml(owmlPath)];

manifestPaths.forEach((manifestPath) => {
const { manifest, missingAttributes } = manifestPartialToFull(
fs.readJsonSync(manifestPath)
);
const modPath = path.dirname(manifestPath);
try {
const { manifest, missingAttributes } = manifestPartialToFull(
fs.readJsonSync(manifestPath)
);

const modWithSameId = localMods.find(
(localMod) => localMod.uniqueName === manifest.uniqueName
);
if (modWithSameId) {
modWithSameId.errors.push(
modsText.duplicateModError(manifest.uniqueName)
const modWithSameId = localMods.find(
(localMod) => localMod.uniqueName === manifest.uniqueName
);
return;
}
if (modWithSameId) {
modWithSameId.errors.push(
modsText.duplicateModError(manifest.uniqueName)
);
return;
}

const mod: Mod = {
name: manifest.name,
author: manifest.author,
uniqueName: manifest.uniqueName,
localVersion: coerce(manifest.version)?.version ?? manifest.version,
modPath: path.dirname(manifestPath),
errors: [],
dependencies: manifest.dependencies ?? [],
requireVR: manifest.requireVR,
description: manifest.description,
warning: manifest.warning,
};
const mod: Mod = {
name: manifest.name,
author: manifest.author,
uniqueName: manifest.uniqueName,
localVersion: coerce(manifest.version)?.version ?? manifest.version,
modPath,
errors: [],
dependencies: manifest.dependencies ?? [],
requireVR: manifest.requireVR,
description: manifest.description,
warning: manifest.warning,
};

if (missingAttributes.length > 0) {
mod.errors.push(
modsText.missingManifestAttributesError(manifestPath, missingAttributes)
);
}
if (missingAttributes.length > 0) {
mod.errors.push(
modsText.missingManifestAttributesError(
manifestPath,
missingAttributes
)
);
}

try {
mod.isEnabled = isEnabled(mod);
try {
mod.isEnabled = isEnabled(mod);
} catch (error) {
mod.isEnabled = true;
debugConsole.error(error);
}

localMods.push(mod);
} catch (error) {
mod.isEnabled = true;
debugConsole.error(error);
const modDirectoryName = path.basename(modPath);
localMods.push({
author: modDirectoryName,
dependencies: [],
description: error.message,
errors: [modsText.brokenManifestError(modDirectoryName)],
modPath,
name: modDirectoryName,
uniqueName: modDirectoryName,
localVersion: '-',
});
}

localMods.push(mod);
});

return [...localMods].filter((mod) => mod);
Expand Down

0 comments on commit e8c39d8

Please sign in to comment.