diff --git a/utils/paths.js b/utils/paths.js index 5298ed1..120b49e 100644 --- a/utils/paths.js +++ b/utils/paths.js @@ -182,33 +182,72 @@ class LuantiPaths { mapToActualGameId(directoryName) { // Map directory names to the actual game IDs that Luanti recognizes - // For most cases, the directory name IS the game ID - const gameIdMap = { - // Luanti internal alias mapping - see https://github.com/luanti-org/luanti/blob/c9d4c33174c87ede1f49c5fe5e8e49a784798eb6/src/content/subgames.cpp#L21 - 'minetest_game': 'minetest', - }; + // Luanti normalizes game IDs by removing "_game" suffix from all games + // See https://github.com/luanti-org/luanti/blob/c9d4c33174c87ede1f49c5fe5e8e49a784798eb6/src/content/subgames.cpp#L21 - return gameIdMap[directoryName] || directoryName; + // Remove "_game" suffix if present + if (directoryName.endsWith('_game')) { + return directoryName.slice(0, -5); // Remove last 5 characters ("_game") + } + + return directoryName; } mapGameIdForWorldCreation(gameId) { // When creating worlds, map game IDs that Luanti expects to use different IDs internally // This is the reverse of directory-based detection - we're setting what goes in world.mt - const worldGameIdMap = { - 'minetest_game': 'minetest', // Luanti expects 'minetest' in world.mt even for minetest_game - }; + // Luanti normalizes all game IDs by removing "_game" suffix - return worldGameIdMap[gameId] || gameId; + // Remove "_game" suffix if present + if (gameId.endsWith('_game')) { + return gameId.slice(0, -5); // Remove last 5 characters ("_game") + } + + return gameId; } - mapInternalGameIdToDirectory(internalGameId) { + async mapInternalGameIdToDirectory(internalGameId) { // Reverse mapping: convert internal game ID back to directory name for display/reference - // This helps when we read a world.mt with "minetest" but want to show "Minetest Game" - const reverseGameIdMap = { - 'minetest': 'minetest_game', // world.mt has 'minetest' but directory is 'minetest_game' - }; + // This helps when we read a world.mt with normalized game ID but want to show directory name + // Since Luanti normalizes by removing "_game" suffix, we need to check if a directory + // with "_game" suffix exists for this normalized ID - return reverseGameIdMap[internalGameId] || internalGameId; + const fs = require('fs').promises; + const path = require('path'); + + // Check both system and user games directories + const gameDirs = [this.getGamesPath()]; + if (this.getSystemGamesPath() && this.getSystemGamesPath() !== this.getGamesPath()) { + gameDirs.push(this.getSystemGamesPath()); + } + + for (const gameDir of gameDirs) { + try { + // First check if the internalGameId as-is exists as a directory + const directPath = path.join(gameDir, internalGameId); + const stat = await fs.stat(directPath); + if (stat.isDirectory()) { + return internalGameId; + } + } catch (error) { + // Directory doesn't exist, try with "_game" suffix + } + + try { + // Check if there's a directory with "_game" suffix + const gameIdWithSuffix = internalGameId + '_game'; + const suffixPath = path.join(gameDir, gameIdWithSuffix); + const stat = await fs.stat(suffixPath); + if (stat.isDirectory()) { + return gameIdWithSuffix; + } + } catch (error) { + // Directory doesn't exist either + } + } + + // Fallback: return the original ID + return internalGameId; } async getInstalledGames() {