Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.1.2 #139

Merged
merged 3 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions assets/localization/FR/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<LanguageData id="Français" name="Français" subtitle_extension="fr" supported_iso="fr,fra,fr-fr,fr-be,fr-ca,fr-ch" under_development="false">
<strings>
<!-- BUTRLauncherModuleVM -->
<string id="kfMQEOFS" text="Le module est installé dans le dossier /Modules du jeu et sur le Steam Workshop !{NL}La version /Modules sera utilisée !"/>
<string id="aAYdk1zd" text="Le DLL est obfusqué !{NL}Il n'y a aucune garantie que le code est sûr !{NL}L'équipe de BUTR met en garde contre les conséquences possibles de l'exécution de code obfusqué !"/>

<!-- BUTRLauncherOptionsVM -->
<string id="z9WqFewN" text="DÉSACTIVÉ !"/>
<string id="44qrhQ6g" text="Redémarrage requis !"/>

<string id="zHo3tzQT" text="Débloquer les fichiers au démarrage"/>
<string id="sOInYH9V" text="Débloque automatiquement les fichiers .dll au démarrage"/>
<string id="LXlsSS8t" text="Corriger les problèmes courants"/>
<string id="J9VbkLW4" text="Corrige des problèmes tels que la présence de 0Harmony.dll dans le dossier /bin"/>
<string id="vUAqDj9H" text="Liste compacte des modules"/>
<string id="Qn1aPNQM" text="Réduit la taille du contenu de l'onglet Mods"/>
<string id="GUWbD65T" text="Désactiver la vérification de compatibilité binaire"/>
<string id="lmpQeQBS" text="Désactive la vérification de compatibilité des mods par le Launcher"/>
<string id="iD27wEq7" text="Masquer l'image aléatoire"/>
<string id="LaPvZjwC" text="Cacher l'image du Cavalier pour que le Launcher soit plus compact"/>
<string id="JT7QnJJA" text="Débloquer les fichiers"/>
<string id="VMIp4503" text="Débloque tous les fichiers .dll dans le dossier /Modules"/>
<string id="RDLKkiVk" text="Débloquer"/>
<string id="QJSBiZdJ" text="Tri expérimental"/>
<string id="HVhaqeb4" text="Utilise le nouvel algorithme de tri après la v1.12.x. Désactiver pour utiliser l'ancien algorithme"/>
<string id="1zt99vTt" text="Mode agrandi"/>
<string id="XUSDSpvf" text="Augmente la hauteur du Launcher"/>
<string id="IsR2rbnG" text="Restaurer la sauvegarde des options de jeu"/>
<string id="uKUsA3Sp" text="LauncherEx fait toujours une sauvegarde avant d'enregistrer pour la première fois. Cela restaurera les fichiers d'origine"/>
<string id="TLDgPay9" text="Restaurer"/>
<string id="5XzSM7RN" text="Restaurer la sauvegarde des options du moteur"/>
<string id="JusnHy6S" text="Active le redimensionnement DPI de Windows pour éliminer le flou des éléments de l'interface utilisateur"/>

<!-- BUTRLauncherSavesVM -->
<string id="JtelOsIW" text="Nom"/>
<string id="14WBFIS1" text="Version"/>
<string id="OJsGrGVi" text="Personnage"/>
<string id="JxpEEQdF" text="Niveau"/>
<string id="qkkTPycE" text="Jours"/>
<string id="aYWWDkKX" text="Créé le"/>

<!-- LauncherConfirmStartVMMixin -->
<string id="DzJmcvsP" text="Annuler"/>
<string id="epTxGUqT" text="Confirmer"/>

<!-- LauncherModsVMMixin -->
<string id="pZVVdI5d" text="L'ordre de chargement a été réorganisé avec l'algorithme par défaut !{NL}Raisons :{NL}{REASONS}"/>
<string id="sP1a61KE" text="Impossible de placer le module à la position souhaitée ! Placement au plus proche disponible !{NL}Raison :{NL}{REASONS}"/>
<string id="sLf3eIpH" text="Échec du tri de la liste des modules !"/>

<!-- LauncherVMMixin -->
<string id="yS5hbWCL" text="Options"/>
<string id="V66qoU6n" text="Launcher"/>
<string id="ro4RMgyt" text="Jeu"/>
<string id="q4rQuTgG" text="Moteur"/>
<string id="d5OjKcGE" text="Sauvegardes"/>
<string id="Aws9irMU" text="Importer l'ordre de chargement"/>
<string id="4wKr76gx" text="Importer l'ordre de chargement de la sauvegarde"/>
<string id="XdZGqnFW" text="Exporter l'ordre de charge actuel"/>
<string id="G55IdM6M" text="Exporter l'ordre de chargement de la sauvegarde"/>
<string id="MlYQ0uX7" text="Des instabilités pourraient survenir."/>
<string id="qvzptzrE" text="Souhaitez-vous continuer à charger la sauvegarde ?"/>
<string id="dDprK7Mz" text="ATTENTION"/>

<string id="Hk7FBBSa" text="Solo"/>
<string id="UOGhdUWE" text="Multijoueur"/>
<string id="VDTcZpPr" text="Compagnon Digital"/>
<string id="Tg0If68v" text="Actualités"/>
<string id="YGU9eXM0" text="Mods"/>
<string id="xYv4iv7C" text="JOUER"/>
<string id="6B3iZLqR" text="CONTINUER"/>
<string id="eUt6GKkQ" text="LANCER"/>

<!-- LauncherVMMixin -->
<string id="WJnTxf3v" text="Importation annulée !"/>
<string id="BjtJ4Lxw" text="Exportation annulée"/>
<string id="eohqbvHU" text="Liste importée avec succès !"/>
<string id="VwFQTk5z" text="Liste exportée avec succès !"/>

<!-- Issues -->
<string id="kxqLbSqe" text="(ID inconnu)"/>

<string id="izSm5f85" text="IDs des modules en double :{NL}{MODULEIDS}"/>
<string id="vCwH9226" text="Noms des modules en double :{NL}{MODULENAMES}"/>
<string id="GtDRbC3m" text="Modules manquants :{NL}{MODULES}"/>
<string id="BuMom4Jt" text="Versions de modules incompatibles :{NL}{MODULEVERSIONS}"/>

<string id="nYVWoomO" text="{MODULEID}. Requis {REQUIREDVERSION}. Installé {ACTUALVERSION}"/>
<string id="sd6M4KRd" text="Ordre de chargement :{NL}{LOADORDER}"/>
<string id="HvvA78sZ" text="Problèmes d'ordre de chargement :{NL}{LOADORDERISSUES}"/>

<string id="B64DbmWp" text="Fichier de sauvegarde introuvable !"/>
<string id="epU06HID" text="Échec de la lecture du fichier de sauvegarde !"/>

<string id="DKRNkst2" text="Ouvrir un fichier avec un ordre de chargement"/>
<string id="XSxlKweM" text="Enregistrer la liste de modules de Bannerlord"/>

<string id="hgew15HH" text="Continuer l'importation ?"/>

<string id="tqjPGPtP" text="LauncherEx a détecté 0Harmony.dll dans le dossier racine /bin du jeu !{NL}Cela pourrait causer des problèmes, souhaitez-vous le supprimer ?"/>

<string id="J3Uh6MV4" text="'{ID}' {VERSION} manquant dans la liste des modules"/>
<string id="3eQSr6wt" text="'{ID}' {VERSION} manquant"/>
<string id="U858vdQX" text="'{ID}' a une ou plusieurs dépendances manquantes !"/>
<string id="1LS8Z5DU" text="'{ID}' a des problèmes non résolus !"/>
<string id="Vjz9HQ41" text="Mauvaise version de '{ID}' &lt;= {VERSION}"/>
<string id="ZvnlL7VE" text="Mauvaise version de '{ID}' &lt;= [{VERSION}]"/>
<string id="EfNuH2bG" text="Mauvaise version de '{ID}' &gt;= [{VERSION}]"/>
<string id="zXDidmpQ" text="'{ID}' est incompatible avec ce module"/>
<string id="4KFwqKgG" text="Le module '{ID}' est à la fois requis et marqué comme incompatible"/>
<string id="9DRB6yXv" text="Le module '{ID}' est à la fois requis en tant que LoadBefore et LoadAfter"/>
<string id="RC1V9BbP" text="Dépendances circulaires. '{TARGETID}' et '{SOURCEID}' dépendent l'un de l'autre"/>
<string id="s3xbuejE" text="'{SOURCEID}' doit être chargé avant '{TARGETID}'"/>
<string id="2ALJB7z2" text="'{SOURCEID}' doit être chargé après '{TARGETID}'"/>

<!-- Dependency Constructor -->
<string id="8ldMJPhQ" text=" (optionnel)"/>
<string id="f9hYP7mk" text="Dépend de :"/>
<string id="eGJ387f7" text="Incompatible avec :"/>
<string id="eW76jyd7" text="Doit être chargé avant :"/>


<string id="HdnFwgVA" text="Basé sur les analyses de BUTR :{NL}{NL}Mise à jour non requise.{NL}Score de compatibilité {SCORE}%{NL}{NL}{CURRENTVERSION} est l'une des meilleures versions pour le jeu {GAMEVERSION}"/>
<string id="HdnFwgVB" text="Basé sur les analyses de BUTR :{NL}{NL}Score de compatibilité {SCORE}%{NL}{NL}Suggère de mettre à jour vers {RECOMMENDEDVERSION}.{NL}Score de compatibilité {RECOMMENDEDSCORE}%{NL}{NL}{RECOMMENDEDVERSION} a une meilleure compatibilité pour le jeu {GAMEVERSION} plutôt que {CURRENTVERSION} !"/>

<string id="q5quVWMI" text="Basculer tous les modules"/>
<string id="H5nMY4WU" text="Actualiser les modules"/>
<string id="zXWdahH9" text="Obtenir des recommandations de mise à jour{NL}Cliquer sur ce bouton enverra votre liste de modules au serveur de BUTR pour obtenir les scores de compatibilité et les versions recommandées.{NL}Ils sont basés sur les rapports de crash de ButterLib.{NL}{NL}(Nécessite une connexion Internet)"/>
</strings>
</LanguageData>
4 changes: 4 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
---------------------------------------------------------------------------------------------------
Version: 1.1.2
* Collection Load Order Tab was not updated correctly on Load Order Page changes
* Added French localization
---------------------------------------------------------------------------------------------------
Version: 1.1.1
* Fixed collection creation
---------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "game-mount-and-blade-ii-bannerlord-butr",
"version": "1.1.1",
"version": "1.1.2",
"description": "A Vortex extension for Mount and Blade II: Bannerlord mod management.",
"author": "BUTR Team & Nexus Mods",
"license": "GPL-3.0+",
Expand Down
8 changes: 5 additions & 3 deletions src/blse/events.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { actions, types } from 'vortex-api';
import { findBLSEMod } from './utils';
import { hasSettingsInterfacePrimaryTool } from '../vortex';
import { hasPersistentBannerlordMods, hasSettingsInterfacePrimaryTool } from '../vortex';
import { GAME_ID } from '../common';

export const didDeployBLSE = (api: types.IExtensionApi): Promise<void> => {
Expand All @@ -12,7 +12,8 @@ export const didDeployBLSE = (api: types.IExtensionApi): Promise<void> => {

const primaryTool = state.settings.interface.primaryTool.mountandblade2bannerlord;

const blseMod = findBLSEMod(state);
const mods = hasPersistentBannerlordMods(state.persistent) ? state.persistent.mods.mountandblade2bannerlord : {};
const blseMod = findBLSEMod(mods);
if (blseMod && primaryTool === undefined) {
api.store?.dispatch(actions.setPrimaryTool(GAME_ID, 'blse-cli'));
}
Expand All @@ -38,7 +39,8 @@ export const didPurgeBLSE = (api: types.IExtensionApi): Promise<void> => {
return Promise.resolve();
}

const blseMod = findBLSEMod(state);
const mods = hasPersistentBannerlordMods(state.persistent) ? state.persistent.mods.mountandblade2bannerlord : {};
const blseMod = findBLSEMod(mods);
if (blseMod) {
api.store?.dispatch(actions.setPrimaryTool(GAME_ID, undefined!));
}
Expand Down
7 changes: 2 additions & 5 deletions src/blse/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { IFileInfo } from '@nexusmods/nexus-api/lib';
import { BLSE_MOD_ID, BLSE_URL, GAME_ID } from '../common';
import { hasPersistentBannerlordMods } from '../vortex';
import { LocalizationManager } from '../localization';
import { IBannerlordMod } from '../types';
import { IBannerlordMod, IBannerlordModStorage } from '../types';

export const isModActive = (profile: types.IProfile, mod: IBannerlordMod): boolean => {
return profile.modState[mod.id]?.enabled ?? false;
Expand All @@ -13,10 +13,7 @@ const isModBLSE = (mod: IBannerlordMod): boolean => {
return mod.type === `bannerlord-blse` || (mod.attributes?.modId === 1 && mod.attributes?.source === `nexus`);
};

export const findBLSEMod = (state: types.IState): IBannerlordMod | undefined => {
if (!hasPersistentBannerlordMods(state.persistent)) return undefined;

const mods = state.persistent.mods.mountandblade2bannerlord ?? {};
export const findBLSEMod = (mods: IBannerlordModStorage): IBannerlordMod | undefined => {
const blseMods: IBannerlordMod[] = Object.values(mods).filter((mod: IBannerlordMod) => isModBLSE(mod));

if (blseMods.length === 0) return undefined;
Expand Down
7 changes: 5 additions & 2 deletions src/blse/vortex.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { actions, selectors, types } from 'vortex-api';
import { deployBLSE, downloadBLSE, findBLSEDownload, findBLSEMod, isModActive } from './utils';
import { LocalizationManager } from '../localization';
import { hasPersistentBannerlordMods } from '../vortex';

const sendNotification = (
api: types.IExtensionApi,
Expand Down Expand Up @@ -31,7 +32,8 @@ export const recommendBLSE = (api: types.IExtensionApi): void => {

const profile: types.IProfile | undefined = selectors.activeProfile(state);

const blseMod = findBLSEMod(state);
const mods = hasPersistentBannerlordMods(state.persistent) ? state.persistent.mods.mountandblade2bannerlord : {};
const blseMod = findBLSEMod(mods);
if (blseMod) {
// Found but not enabled
const blseIsActive = isModActive(profile, blseMod);
Expand Down Expand Up @@ -84,7 +86,8 @@ export const forceInstallBLSE = async (api: types.IExtensionApi): Promise<void>

const profile: types.IProfile | undefined = selectors.activeProfile(state);

const blseMod = findBLSEMod(state);
const mods = hasPersistentBannerlordMods(state.persistent) ? state.persistent.mods.mountandblade2bannerlord : {};
const blseMod = findBLSEMod(mods);
if (blseMod) {
// Found but not enabled
const blseIsActive = isModActive(profile, blseMod);
Expand Down
7 changes: 3 additions & 4 deletions src/butr/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { types } from 'vortex-api';
import { IModAnalyzerRequestModule, IModAnalyzerRequestQuery, IModuleCompatibilityInfoCache } from './types';
import { ModAnalyzerProxy } from './modAnalyzerProxy';
import { versionToString, VortexLauncherManager } from '../launcher';

export const getCompatibilityScores = async (api: types.IExtensionApi): Promise<IModuleCompatibilityInfoCache> => {
const launcherManager = VortexLauncherManager.getInstance(api);

export const getCompatibilityScores = async (
launcherManager: VortexLauncherManager
): Promise<IModuleCompatibilityInfoCache> => {
const allModules = launcherManager.getAllModules();
const gameVersion = launcherManager.getGameVersionVortex();

Expand Down
19 changes: 7 additions & 12 deletions src/collections/generalData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { selectors, types } from 'vortex-api';
import { profile } from 'node:console';
import { ICollectionData, ICollectionDataWithGeneralData, ICollectionGeneralData } from './types';
import { genCollectionGeneralLoadOrder, parseCollectionGeneralLoadOrder } from './loadOrder';
import { CollectionParseError } from './errors';
Expand All @@ -7,25 +8,19 @@ import { hasPersistentBannerlordMods, hasPersistentLoadOrder } from '../vortex';
import { findBLSEMod, forceInstallBLSE, isModActive } from '../blse';
import { vortexToPersistence } from '../loadOrder';
import { VortexLauncherManager } from '../launcher';
import { IBannerlordMod, IBannerlordModStorage, VortexLoadOrderStorage } from '../types';

/**
* Assumes that the correct Game ID is active and that the profile is set up correctly.
*/
export const genCollectionGeneralData = (
api: types.IExtensionApi,
includedModIds: string[]
profile: types.IProfile,
loadOrder: VortexLoadOrderStorage,
includedMods: IBannerlordModStorage
): Promise<ICollectionGeneralData> => {
const state = api.getState();

const profile: types.IProfile | undefined = selectors.activeProfile(state);

const loadOrder = hasPersistentLoadOrder(state.persistent) ? state.persistent.loadOrder[profile.id] ?? [] : [];
const mods = hasPersistentBannerlordMods(state.persistent) ? state.persistent.mods.mountandblade2bannerlord : {};

const includedMods = Object.values(mods).filter((mod) => includedModIds.includes(mod.id));
const collectionLoadOrder = genCollectionGeneralLoadOrder(loadOrder, includedMods);
const collectionLoadOrder = genCollectionGeneralLoadOrder(loadOrder, Object.values(includedMods));

const blseMod = findBLSEMod(state);
const blseMod = findBLSEMod(includedMods);
const hasBLSE = blseMod !== undefined && isModActive(profile, blseMod);

return Promise.resolve({
Expand Down
29 changes: 25 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
SettingsProps,
} from './views';
import { BannerlordGame } from './game';
import { IAddedFiles } from './types';
import { IAddedFiles, IBannerlordModStorage } from './types';
import { reducer } from './react';
import { actionsSettings } from './settings';
import {
Expand All @@ -32,7 +32,13 @@ import { didDeployLoadOrder, gamemodeActivatedLoadOrder, LoadOrderManager } from
import { didDeployBLSE, didPurgeBLSE, getInstallPathBLSE, installBLSE, isModTypeBLSE, testBLSE } from './blse';
import { VortexLauncherManager } from './launcher';
import { gamemodeActivatedSave } from './save';
import { addedFilesEvent, getInstallPathModule, isModTypeModule } from './vortex';
import {
addedFilesEvent,
getInstallPathModule,
hasPersistentBannerlordMods,
hasPersistentLoadOrder,
isModTypeModule,
} from './vortex';
import { version } from '../package.json';

// TODO: Better dialogs with settings
Expand Down Expand Up @@ -64,11 +70,26 @@ const main = (context: types.IExtensionContext): boolean => {
if (hasContextWithCollectionFeature(context)) {
context.optional.registerCollectionFeature(
/*id:*/ `${GAME_ID}_load_order`,
/*generate:*/ async (gameId: string, includedMods: string[], _mod: types.IMod) => {
/*generate:*/ async (gameId: string, includedModIds: string[], _mod: types.IMod) => {
if (GAME_ID !== gameId) {
return {};
}
return await genCollectionGeneralData(context.api, includedMods);

const state = context.api.getState();
const profile: types.IProfile | undefined = selectors.activeProfile(state);
const loadOrder = hasPersistentLoadOrder(state.persistent) ? state.persistent.loadOrder[profile?.id] ?? [] : [];
const mods = hasPersistentBannerlordMods(state.persistent)
? state.persistent.mods.mountandblade2bannerlord
: {};

const includedMods = Object.values(mods)
.filter((mod) => includedModIds.includes(mod.id))
.reduce<IBannerlordModStorage>((map, obj) => {
map[obj.id] = obj;
return map;
}, {});

return await genCollectionGeneralData(profile, loadOrder, includedMods);
},
/*parse:*/ async (gameId: string, collection: ICollectionData, _mod: types.IMod) => {
if (GAME_ID !== gameId) {
Expand Down
14 changes: 9 additions & 5 deletions src/views/CollectionGeneralData/pages/GeneralDataPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { getCompatibilityScores, IModuleCompatibilityInfoCache } from '../../../
import { genCollectionGeneralData } from '../../../collections';
import { useLocalization } from '../../../localization';
import { hasPersistentBannerlordMods, hasPersistentLoadOrder } from '../../../vortex';
import { useLauncher } from '../../../launcher';

interface IFromState {
profile: types.IProfile | undefined;
loadOrder: VortexLoadOrderStorage;
mods: IBannerlordModStorage;
}
Expand All @@ -22,23 +24,24 @@ export const BannerlordGeneralDataPage = (props: BannerlordGeneralDataPageProps)
const [hasBLSE, setHasBLSE] = useState<boolean>(false);
const [persistentLoadOrder, setPersistentLoadOrder] = useState<PersistenceLoadOrderStorage>([]);

const { loadOrder, mods } = useSelector(mapState);
const { profile, loadOrder, mods } = useSelector(mapState);

const context = useContext(MainContext);
const launcherManager = useLauncher();

useEffect(() => {
async function setData(): Promise<void> {
const data = await genCollectionGeneralData(context.api, Object.keys(mods));
if (!profile) return;
const data = await genCollectionGeneralData(profile, loadOrder, mods);
setHasBLSE(data.hasBLSE);
setPersistentLoadOrder(data.suggestedLoadOrder);
}
setData().catch(() => {});
}, [context.api, mods]);
}, [profile, loadOrder, mods]);

const { localize: t } = useLocalization();

const refreshCompatibilityScores = (): void => {
getCompatibilityScores(context.api)
getCompatibilityScores(launcherManager)
.then((cache) => {
setCompatibilityInfoCache(cache);
})
Expand Down Expand Up @@ -90,6 +93,7 @@ const mapState = (state: types.IState): IFromState => {
const loadOrder = hasPersistentLoadOrder(state.persistent) ? state.persistent.loadOrder[profile?.id] ?? [] : [];
const mods = hasPersistentBannerlordMods(state.persistent) ? state.persistent.mods.mountandblade2bannerlord : {};
return {
profile,
loadOrder,
mods,
};
Expand Down
2 changes: 1 addition & 1 deletion src/views/Saves/components/RadioView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ export const RadioView = (props: RadioViewProps): JSX.Element => {
onChange={() => onChange(save)}
/>
) : (
<div />
<></>
);
};
Loading
Loading