From 0f6cddec2b6137976802c32b903e27e0809df47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tibor=20Ili=C4=87?= Date: Wed, 7 Aug 2024 18:44:18 +0200 Subject: [PATCH] dynasties support, fix for mod updating ignoring tags --- .gitignore | 2 + locales/en/translation.json | 11 +- package.json | 2 +- src/appConfigFunctions.ts | 1 + src/appData.ts | 2 + src/appSlice.ts | 39 +++++ src/assets/game_icons/dynasties.png | Bin 0 -> 20326 bytes src/components/GamePathsSetup.tsx | 10 +- src/components/Main.tsx | 2 + src/components/ModDropdownOptions.tsx | 11 +- src/components/ModTagPicker.tsx | 94 ++++++++++ src/components/OptionsDrawer.tsx | 4 +- src/index.css | 4 + src/index.d.ts | 26 +++ src/index.ts | 5 +- src/initialAppState.ts | 2 + src/ipcMainListeners.ts | 25 ++- src/modFunctions.ts | 11 +- src/schema.ts | 11 ++ src/sub.ts | 46 ++++- src/supportedGames.ts | 238 +++++++++++++++++++++++++- 21 files changed, 525 insertions(+), 21 deletions(-) create mode 100644 src/assets/game_icons/dynasties.png create mode 100644 src/components/ModTagPicker.tsx diff --git a/.gitignore b/.gitignore index 5aa9223..ed02adb 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,5 @@ temp/ .yarn/cache/ dumps + +sublog.txt diff --git a/locales/en/translation.json b/locales/en/translation.json index 83c0bbe..a103dbb 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -381,5 +381,14 @@ "setFolderPathsManuallyPharaoh": "The mod manager tried to get Pharaoh folder locations from Windows Registry, but it couldn't find them! You'll have to set them manually!", "setFolderPathsManuallyOptionallyPharaoh": "The mod manager automatically found Pharaoh folder paths from the Windows Registry, but you can set them manually here.", "noMissingFilesFound": "No missing files found!", - "missingFiles": "Missing Files" + "missingFiles": "Missing Files", + "dynasties": "Pharaoh Dynasties", + "mainDynastiesFolder": "The main Dynasties folder that contains Pharaoh.exe, for example C:\\Program Files (x86)\\Steam\\steamapps\\common\\Total War PHARAOH DYNASTIES", + "dynastiesFolder": "Dynasties folder:", + "dynastiesContentFolder": "The Dynasties Steam Workshop content folder named 2951630 (which is the steam ID for Pharaoh Dynasties) that contains mods, for example C:\\Program Files (x86)\\Steam\\steamapps\\workshop\\content\\2951630", + "selectDynastiesFolder": "Select Dynasties Folder", + "setFolderPathsManuallyDynasties": "The mod manager tried to get Pharaoh Dynasties folder locations from Windows Registry, but it couldn't find them! You'll have to set them manually!", + "setFolderPathsManuallyOptionallyDynasties": "The mod manager automatically found Pharaoh Dynasties folder paths from the Windows Registry, but you can set them manually here.", + "chooseNewModTag": "Choose tag for the new mod:", + "upload": "Upload" } diff --git a/package.json b/package.json index b25f77c..72cbf3d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wh3mm", "productName": "wh3mm", - "version": "2.7.0", + "version": "2.8.0", "description": "WH3 Mod Manager", "main": ".webpack/main", "scripts": { diff --git a/src/appConfigFunctions.ts b/src/appConfigFunctions.ts index 0ac10e3..0a74996 100644 --- a/src/appConfigFunctions.ts +++ b/src/appConfigFunctions.ts @@ -61,6 +61,7 @@ const removeModDataWeDontSave = (mods: Mod[] | undefined) => { mod.isDeleted = false; mod.isMovie = false; mod.dependencyPacks = []; + mod.tags = []; } }; diff --git a/src/appData.ts b/src/appData.ts index a2cca83..5eb3348 100644 --- a/src/appData.ts +++ b/src/appData.ts @@ -98,6 +98,7 @@ for (const supportedGame of supportedGames) { attila: undefined, troy: undefined, pharaoh: undefined, + dynasties: undefined, }; (appData as AppData).gameToPresets = { wh2: [], @@ -106,6 +107,7 @@ for (const supportedGame of supportedGames) { attila: [], troy: [], pharaoh: [], + dynasties: [], }; export default appData as AppData; diff --git a/src/appSlice.ts b/src/appSlice.ts index 5bde1f9..3c22924 100644 --- a/src/appSlice.ts +++ b/src/appSlice.ts @@ -485,6 +485,7 @@ const appSlice = createSlice({ if (removedModData) { mod.isEnabled = removedModData.isEnabled; mod.loadOrder = removedModData.loadOrder; + mod.tags = removedModData.tags; // state.currentPreset.mods.splice(state.currentPreset.mods.indexOf(mod), 1); // state.currentPreset.mods.splice(removedModData.indexInMods, 0, mod); state.removedModsData = state.removedModsData.filter(({ modPath }) => modPath != mod.path); @@ -560,6 +561,7 @@ const appSlice = createSlice({ indexInMods: state.currentPreset.mods.indexOf(removedMod), loadOrder: removedMod.loadOrder, time: Date.now(), + tags: removedMod.tags, }); state.removedModsCategories[removedMod.path] = removedMod.categories ?? []; @@ -587,6 +589,16 @@ const appSlice = createSlice({ !equal(dataMod.reqModIdToName, data.reqModIdToName) ) dataMod.reqModIdToName = data.reqModIdToName; + if (data.tags) { + if (dataMod.tags.length != data.tags.length) { + // console.log("tags changed:", dataMod.name, dataMod.tags, "->", data.tags); + dataMod.tags = data.tags; + } + if (contentMod.tags.length != data.tags.length) { + // console.log("tags changed:", contentMod.name, contentMod.tags, "->", data.tags); + contentMod.tags = data.tags; + } + } } } @@ -607,6 +619,16 @@ const appSlice = createSlice({ } if (data.lastChanged && mod.lastChanged != data.lastChanged) mod.lastChanged = data.lastChanged; + if (data.tags && mod.tags.length != data.tags.length) { + // console.log("tags changed:", mod.name, mod.tags, "->", data.tags); + mod.tags = data.tags; + } + + // timeAddedToUserList we get from Steam is always 0, not sure what it's for but it's not actually time of subbing + // if (data.subscriptionTime && mod.subbedTime != data.subscriptionTime) { + // console.log("subbedTime:", mod.subbedTime, "->", data.subscriptionTime); + // mod.subbedTime = data.subscriptionTime; + // } } }, setPackHeaderData: (state: AppState, action: PayloadAction) => { @@ -1138,6 +1160,20 @@ const appSlice = createSlice({ createBisectedModListPresets: (state: AppState, action: PayloadAction) => { createBisectedModListPresetsInternal(state, action.payload); }, + setIsModTagPickerOpen: (state: AppState, action: PayloadAction) => { + state.isModTagPickerOpen = action.payload; + }, + setCurrentModToUpload: (state: AppState, action: PayloadAction) => { + state.currentModToUpload = action.payload; + }, + setTagForMod: (state: AppState, action: PayloadAction<{ mod: Mod; tag: string }>) => { + const payloadMod = action.payload.mod; + const payloadTag = action.payload.tag; + const mod = state.currentPreset.mods.find((mod) => mod.path == payloadMod.path); + if (!mod) return; + + mod.tags = ["mod", payloadTag]; + }, selectCategory: (state: AppState, action: PayloadAction) => { const { mods, category, selectOperation } = action.payload; @@ -1243,6 +1279,9 @@ export const { setCustomizableMods, createBisectedModListPresets, requestGameFolderPaths, + setCurrentModToUpload, + setIsModTagPickerOpen, + setTagForMod, } = appSlice.actions; export default appSlice.reducer; diff --git a/src/assets/game_icons/dynasties.png b/src/assets/game_icons/dynasties.png new file mode 100644 index 0000000000000000000000000000000000000000..118607da48a6d2a5da75472feb47b865047a9c94 GIT binary patch literal 20326 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 KMNUMnLSTX( attila: "mainAttilaFolder", troy: "mainTroyFolder", pharaoh: "mainPharaohFolder", + dynasties: "mainDynastiesFolder", }; const supportedGameToGameFolderLocalization: Record = { wh2: "wh2Folder", @@ -32,6 +33,7 @@ const supportedGameToGameFolderLocalization: Record = { attila: "attilaFolder", troy: "troyFolder", pharaoh: "pharaohFolder", + dynasties: "dynastiesFolder", }; const supportedGameToContentFolderLocalization: Record = { wh2: "wh2ContentFolder", @@ -40,6 +42,7 @@ const supportedGameToContentFolderLocalization: Record = attila: "attilaContentFolder", troy: "troyContentFolder", pharaoh: "pharaohContentFolder", + dynasties: "dynastiesContentFolder", }; const supportedGameToSelectFolderLocalization: Record = { wh2: "selectWH2Folder", @@ -48,6 +51,7 @@ const supportedGameToSelectFolderLocalization: Record = attila: "selectAttilaFolder", troy: "selectTroyFolder", pharaoh: "selectPharaohFolder", + dynasties: "selectDynastiesFolder", }; const supportedGameToSetFolderPathsManuallyLocalization: Record = { wh2: "setFolderPathsManuallyWH2", @@ -56,6 +60,7 @@ const supportedGameToSetFolderPathsManuallyLocalization: Record = { wh2: "setFolderPathsManuallyOptionallyWH2", @@ -64,6 +69,7 @@ const supportedGameToSetFolderPathsManuallyOptionallyLocalization: Record { @@ -78,6 +84,8 @@ const GamePathsSetup = memo(({ isOpen, setIsOpen }: GamePathsSetupProps) => { const localized: Record = useContext(localizationContext); + console.log("requestFolderPathsForGame:", requestFolderPathsForGame); + return ( <> {(isOpen || (isSetAppFolderPathsDone && isAnyPathEmpty) || requestFolderPathsForGame) && ( @@ -95,7 +103,7 @@ const GamePathsSetup = memo(({ isOpen, setIsOpen }: GamePathsSetupProps) => {
- {(isAnyPathEmpty && ( + {((isAnyPathEmpty || requestFolderPathsForGame) && (

{localized[supportedGameToSetFolderPathsManuallyLocalization[currentGame]]}

diff --git a/src/components/Main.tsx b/src/components/Main.tsx index f526406..24a22ac 100644 --- a/src/components/Main.tsx +++ b/src/components/Main.tsx @@ -3,6 +3,7 @@ import { useAppSelector } from "../hooks"; import Sidebar from "./Sidebar"; import ModRows from "./ModRows"; import Categories from "./Categories"; +import ModTagPicker from "./ModTagPicker"; const Main = () => { const currentTab = useAppSelector((state) => state.app.currentTab); @@ -16,6 +17,7 @@ const Main = () => {
+
)} diff --git a/src/components/ModDropdownOptions.tsx b/src/components/ModDropdownOptions.tsx index 1dda45e..fe40e31 100644 --- a/src/components/ModDropdownOptions.tsx +++ b/src/components/ModDropdownOptions.tsx @@ -1,6 +1,12 @@ import { Tooltip } from "flowbite-react"; import React, { memo, useCallback, useContext, useState } from "react"; -import { setModLoadOrderRelativeTo, toggleAlwaysEnabledMods, toggleAlwaysHiddenMods } from "../appSlice"; +import { + setCurrentModToUpload, + setIsModTagPickerOpen, + setModLoadOrderRelativeTo, + toggleAlwaysEnabledMods, + toggleAlwaysHiddenMods, +} from "../appSlice"; import { FaFolderOpen, FaExternalLinkAlt, @@ -100,7 +106,8 @@ const ModDropdownOptions = memo((props: ModDropdownOptionsProps) => { ); const uploadMod = useCallback( (mod: Mod) => { - window.api?.uploadMod(mod); + dispatch(setCurrentModToUpload(mod)); + dispatch(setIsModTagPickerOpen(true)); }, [allMods] ); diff --git a/src/components/ModTagPicker.tsx b/src/components/ModTagPicker.tsx new file mode 100644 index 0000000..c055606 --- /dev/null +++ b/src/components/ModTagPicker.tsx @@ -0,0 +1,94 @@ +import { Modal } from "../flowbite/components/Modal/index"; +import React, { memo, useCallback, useContext, useState } from "react"; +import { useAppDispatch, useAppSelector } from "../hooks"; +import localizationContext from "../localizationContext"; +import selectStyle from "../styles/selectStyle"; +import Select, { ActionMeta, SingleValue } from "react-select"; +import { setIsModTagPickerOpen, setTagForMod } from "../appSlice"; + +type OptionType = { + value: string; + label: string; +}; + +const options: OptionType[] = [ + "graphical", + "campaign", + "units", + "battle", + "ui", + "maps", + "overhaul", + "compilation", + "cheat", +].map((tag) => ({ value: tag, label: tag })); + +const ModTagPicker = memo(() => { + const dispatch = useAppDispatch(); + + const isModTagPickerOpen = useAppSelector((state) => state.app.isModTagPickerOpen); + const currentModToUpload = useAppSelector((state) => state.app.currentModToUpload); + + const [currentTag, setCurrentTag] = useState("graphical"); + + const onUploadMod = () => { + if (currentModToUpload) { + window.api?.uploadMod({ ...currentModToUpload, tags: ["mod", currentTag] }); + dispatch(setIsModTagPickerOpen(false)); + } + }; + + const onClose = useCallback(() => { + dispatch(setIsModTagPickerOpen(false)); + }, []); + + const onTagChange = (newValue: SingleValue, actionMeta: ActionMeta) => { + if (!newValue) return; + if (!currentModToUpload) return; + + console.log(`label: ${newValue.label}, value: ${newValue.value}, action: ${actionMeta.action}`); + if (actionMeta.action === "select-option") { + setCurrentTag(newValue.value); + dispatch(setTagForMod({ mod: currentModToUpload, tag: newValue.value })); + } + }; + + const localized: Record = useContext(localizationContext); + + return ( + <> + {currentModToUpload && isModTagPickerOpen && ( + + {localized.uploadMod} + +
+ + {localized.chooseNewModTag} + + + +
+
+
+ )} + + ); +}); +export default ModTagPicker; diff --git a/src/components/OptionsDrawer.tsx b/src/components/OptionsDrawer.tsx index be1390c..9c3731e 100644 --- a/src/components/OptionsDrawer.tsx +++ b/src/components/OptionsDrawer.tsx @@ -239,14 +239,14 @@ const OptionsDrawer = memo(() => {
diff --git a/src/index.css b/src/index.css index bdd5f31..f53192e 100644 --- a/src/index.css +++ b/src/index.css @@ -295,3 +295,7 @@ body:not(.disable-row-hover) .row:hover > div:not(.drop-ghost) { .modalDontOverflowWindowHeight { max-height: calc(100% - 2rem); } + +.modalGiveChildVisibleOverflow > :first-child { + overflow: visible; +} diff --git a/src/index.d.ts b/src/index.d.ts index da92458..61ee1c3 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -2,6 +2,7 @@ import { PackedFile, PackCollisions } from "./packFileTypes"; import { GameFolderPaths } from "./appData"; import { api } from "./preload"; import { SupportedGames } from "./supportedGames"; +import { UgcItemVisibility } from "../node_modules/@ai-zen/steamworks.js/client.d"; export {}; declare global { @@ -38,6 +39,7 @@ declare global { subbedTime?: number; isSymbolicLink: boolean; categories?: string[]; + tags: string[]; } interface ModData { @@ -47,6 +49,8 @@ declare global { lastChanged: number; author: string; isDeleted: boolean; + subscriptionTime: number; + tags: string[]; } interface PackHeaderData { @@ -128,6 +132,8 @@ declare global { customizableMods: Record; currentGame: SupportedGames; steamCollectionsToImport: Record; + isModTagPickerOpen: boolean; + currentModToUpload: Mod | undefined; } type; @@ -338,12 +344,28 @@ declare global { indexInMods: number; loadOrder?: number; time: number; + tags: string[]; } type ToastType = "success" | "warning" | "info"; type MainWindowTab = "mods" | "enabledMods" | "categories"; + export interface WorkshopItemStatisticStringified { + numSubscriptions: string; + numFavorites: string; + numFollowers: string; + numUniqueSubscriptions: string; + numUniqueFavorites: string; + numUniqueFollowers: string; + numUniqueWebsiteViews: string; + reportScore: string; + numSecondsPlayed: string; + numPlaytimeSessions: string; + numComments: string; + numSecondsPlayedDuringTimePeriod: string; + numPlaytimeSessionsDuringTimePeriod: string; + } export interface WorkshopItemStringInsteadOfBigInt { publishedFileId: string; creatorAppId?: number; @@ -355,6 +377,9 @@ declare global { timeCreated: number; /** Time updated in unix epoch seconds format */ timeUpdated: number; + /** Time when the user added the published item to their list (not always applicable), provided in Unix epoch format (time since Jan 1st, 1970). */ + timeAddedToUserList: number; + visibility: UgcItemVisibility; banned: boolean; acceptedForUse: boolean; tags: Array; @@ -364,6 +389,7 @@ declare global { numDownvotes: number; numChildren: number; previewUrl?: string; + statistics: WorkshopItemStatisticStringified; } export interface PlayerSteamIdStringInsteadOfBigInt { diff --git a/src/index.ts b/src/index.ts index d4f713c..b370cbe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import { gameToProcessName, gameToSteamId } from "./supportedGames"; import psList from "ps-list"; import { exec, fork } from "child_process"; -import { app, autoUpdater, BrowserWindow, dialog, ipcMain, shell } from "electron"; +import { app, autoUpdater, BrowserWindow, dialog, ipcMain, Menu, shell } from "electron"; import installExtension, { REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } from "electron-extension-installer"; import fetch from "electron-fetch"; import isDev from "electron-is-dev"; @@ -264,6 +264,9 @@ if (!gotTheLock) { } }); + // not using a default menu + Menu.setApplicationMenu(null); + // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. diff --git a/src/initialAppState.ts b/src/initialAppState.ts index dc0fc57..f210428 100644 --- a/src/initialAppState.ts +++ b/src/initialAppState.ts @@ -73,6 +73,8 @@ const initialState = { isHelpOpen: false, lastModThatWasRead: undefined, currentlyReadingMod: undefined, + isModTagPickerOpen: false, + currentModToUpload: undefined, } as AppState; export default initialState; diff --git a/src/ipcMainListeners.ts b/src/ipcMainListeners.ts index 123cfec..a475d18 100644 --- a/src/ipcMainListeners.ts +++ b/src/ipcMainListeners.ts @@ -52,6 +52,7 @@ import { format } from "date-fns"; import { sortByNameAndLoadOrder } from "./modSortingHelpers"; import { tryOpenFile } from "./utility/fileHelpers"; import steamCollectionScript from "./utility/steamCollectionScript"; +import fetch from "electron-fetch"; declare const VIEWER_WEBPACK_ENTRY: string; declare const VIEWER_PRELOAD_WEBPACK_ENTRY: string; @@ -89,7 +90,7 @@ export const registerIpcMainListeners = ( if (appData.gamesToGameFolderPaths[newGame].contentFolder) { appData.packsData = []; appData.saveSetupDone = false; - console.log("SETTING CURR GAME 2"); + console.log("Setting current game 1"); appData.currentGame = newGame; await getAllMods(); } @@ -100,7 +101,7 @@ export const registerIpcMainListeners = ( if (appData.gamesToGameFolderPaths[newGame].contentFolder) { contentFolder = appData.gamesToGameFolderPaths[newGame].contentFolder ?? ""; gamePath = appData.gamesToGameFolderPaths[newGame].gamePath ?? ""; - console.log("SETTING CURR GAME 1"); + console.log("Setting current game 2"); appData.currentGame = newGame; console.log("SENDING setAppFolderPaths", gamePath, contentFolder); // mainWindow?.webContents.send("setCurrentGameNaive", newGame); @@ -409,6 +410,7 @@ export const registerIpcMainListeners = ( isMovie: false, size: 0, isSymbolicLink: false, + tags: ["mod"], }; if (appData.packsData.every((iterPack) => iterPack.path != dataPackPath)) { console.log("READING DATA PACK"); @@ -664,7 +666,7 @@ export const registerIpcMainListeners = ( }; ipcMain.on("getAllModData", (event, ids: string[]) => { - if (isDev) return; + // if (isDev) return; fetchModData( ids.filter((id) => id !== ""), @@ -1419,7 +1421,7 @@ export const registerIpcMainListeners = ( startTime: Date.now(), } as Toast); } - updateMod(mod, response.workshopId, mod.name, true); + updateMod(mod, response.workshopId, mod.tags, mod.name, true); break; case "error": mainWindow?.webContents.send("addToast", { @@ -1436,6 +1438,7 @@ export const registerIpcMainListeners = ( const updateMod = async ( mod: Mod, workshopId: string, + tags: string[], modTitle?: string, openInSteamAfterUpdate = false ) => { @@ -1450,7 +1453,16 @@ export const registerIpcMainListeners = ( await fs.linkSync(mod.path, nodePath.join(uploadFolderPath, mod.name)); await fs.linkSync(mod.imgPath, nodePath.join(uploadFolderPath, nodePath.basename(mod.imgPath))); - const args = [gameToSteamId[appData.currentGame], "update", workshopId, uploadFolderPath, mod.imgPath]; + const args = [ + gameToSteamId[appData.currentGame], + "update", + workshopId, + uploadFolderPath, + mod.imgPath, + tags.join(";"), + ]; + console.log("UPDATING MOD:", modTitle, tags); + // return; if (modTitle) args.push(modTitle); const child = fork(nodePath.join(__dirname, "sub.js"), args, {}); child.on( @@ -1514,7 +1526,7 @@ export const registerIpcMainListeners = ( ); }; ipcMain.on("updateMod", async (event, mod: Mod, contentMod: Mod) => { - updateMod(mod, contentMod.workshopId); + updateMod(mod, contentMod.workshopId, contentMod.tags); }); ipcMain.on("fakeUpdatePack", async (event, mod: Mod) => { try { @@ -1890,6 +1902,7 @@ export const registerIpcMainListeners = ( isMovie: false, size: 0, isSymbolicLink: false, + tags: ["mod"], }; vanillaPacks.push(dataMod); } diff --git a/src/modFunctions.ts b/src/modFunctions.ts index c8fc282..d6b8e55 100644 --- a/src/modFunctions.ts +++ b/src/modFunctions.ts @@ -15,6 +15,7 @@ import { decodeHTML } from "entities"; const matchAuthorNameInSteamHtmlTag = /.*>(.+?)'s .*?<\/a>/; const matchBreadcrumbsInSteamPageHtml = /