Index: binaries/data/mods/mod/gui/modmod/modmod.js =================================================================== --- binaries/data/mods/mod/gui/modmod/modmod.js +++ binaries/data/mods/mod/gui/modmod/modmod.js @@ -1,364 +0,0 @@ -/** - * Contains JS objects defined by the mod JSON files available. - * @example - *{ - * "public": - * { - * "name": "0ad", - * "version": "0.0.16", - * "label": "0 A.D. - Empires Ascendant", - * "type": "content|functionality|mixed/mod-pack", - * "url": "http://wildfregames.com/", - * "description": "A free, open-source, historical RTS game.", - * "dependencies": [] - * }, - * "foldername2": { - * "name": "mod2", - * "label": "Mod 2", - * "version": "1.1", - * "description": "", - * "dependencies": ["0ad<=0.0.16", "rote"] - * } - *} - */ -var g_Mods = {}; - -/** - * Every mod needs to define these properties. - */ -var g_RequiredProperties = ["name", "label", "description", "dependencies", "version"]; - -/** - * Version checks in mod dependencies can use these operators. - */ -var g_CompareVersion = /(<=|>=|<|>|=)/; - -/** - * Folder names of all mods that are or can be launched. - */ -var g_ModsEnabled = []; -var g_ModsDisabled = []; - -var g_ColorNoModSelected = "255 255 100"; -var g_ColorDependenciesMet = "100 255 100"; -var g_ColorDependenciesNotMet = "255 100 100"; - -function init() -{ - loadMods(); - initGUIFilters(); -} - -function loadMods() -{ - let mods = Engine.GetAvailableMods(); - - for (let folder in mods) - if (g_RequiredProperties.every(prop => mods[folder][prop] !== undefined)) - g_Mods[folder] = mods[folder]; - else - warn("Skipping mod '" + mod + "' which does not define '" + property + "'."); - - deepfreeze(g_Mods); - - g_ModsEnabled = Engine.ConfigDB_GetValue("user", "mod.enabledmods").split(/\s+/).filter(folder => !!g_Mods[folder]); - g_ModsDisabled = Object.keys(g_Mods).filter(folder => g_ModsEnabled.indexOf(folder) == -1); -} - -function initGUIFilters() -{ - Engine.GetGUIObjectByName("negateFilter").checked = false; - Engine.GetGUIObjectByName("modGenericFilter").caption = translate("Filter"); - Engine.GetGUIObjectByName("modTypeFilter").selected = 0; - - displayModLists(); -} - -function saveMods() -{ - sortEnabledMods(); - Engine.ConfigDB_CreateValue("user", "mod.enabledmods", ["mod"].concat(g_ModsEnabled).join(" ")); - Engine.ConfigDB_WriteFile("user", "config/user.cfg"); -} - -function startMods() -{ - sortEnabledMods(); - Engine.SetMods(["mod"].concat(g_ModsEnabled)); - Engine.RestartEngine(); -} - -function displayModLists() -{ - displayModList("modsEnabledList", g_ModsEnabled); - displayModList("modsDisabledList", g_ModsDisabled); -} - -function displayModList(listObjectName, folders) -{ - updateModTypes(); - - let listObject = Engine.GetGUIObjectByName(listObjectName); - - if (listObjectName == "modsDisabledList") - { - let sortFolder = folder => String(g_Mods[folder][listObject.selected_column] || folder); - folders.sort((folder1, folder2) => - listObject.selected_column_order * - sortFolder(folder1).localeCompare(sortFolder(folder2))); - } - - folders = folders.filter(filterMod); - - listObject.list_name = folders.map(folder => g_Mods[folder].name); - listObject.list_folder = folders; - listObject.list_label = folders.map(folder => g_Mods[folder].label); - listObject.list_type = folders.map(folder => g_Mods[folder].type || ""); - listObject.list_url = folders.map(folder => g_Mods[folder].url || ""); - listObject.list_version = folders.map(folder => g_Mods[folder].version); - listObject.list_dependencies = folders.map(folder => g_Mods[folder].dependencies.join(" ")); - listObject.list = folders; -} - -function updateModTypes() -{ - let types = [translate("Type: Any")]; - for (let folder in g_Mods) - { - if (g_Mods[folder].type && types.indexOf(g_Mods[folder].type) == -1) - types.push(g_Mods[folder].type); - } - Engine.GetGUIObjectByName("modTypeFilter").list = types; -} - -function enableMod() -{ - let modsDisabledList = Engine.GetGUIObjectByName("modsDisabledList"); - let pos = modsDisabledList.selected; - - if (pos == -1 || !areDependenciesMet(g_ModsDisabled[pos])) - return; - - g_ModsEnabled.push(g_ModsDisabled.splice(pos, 1)[0]); - - if (pos >= g_ModsDisabled.length) - --pos; - - modsDisabledList.selected = pos; - - displayModLists(); -} - -function disableMod() -{ - let modsEnabledList = Engine.GetGUIObjectByName("modsEnabledList"); - let pos = modsEnabledList.selected; - if (pos == -1) - return; - - g_ModsDisabled.push(g_ModsEnabled.splice(pos, 1)[0]); - - // Remove mods that required the removed mod and cascade - // Sort them, so we know which ones can depend on the removed mod - // TODO: Find position where the removed mod would have fit (for now assume idx 0) - - sortEnabledMods(); - - for (let i = 0; i < g_ModsEnabled.length; ++i) - if (!areDependenciesMet(g_ModsEnabled[i])) - { - g_ModsDisabled.push(g_ModsEnabled.splice(i, 1)[0]); - --i; - } - - modsEnabledList.selected = Math.min(pos, g_ModsEnabled.length - 1); - - displayModLists(); -} - -function resetFilters() -{ - Engine.GetGUIObjectByName("modGenericFilter").caption = ""; - Engine.GetGUIObjectByName("negateFilter").checked = false; - - // Calling displayModLists is not needed as the selection changes and that calls applyFilters - Engine.GetGUIObjectByName("modTypeFilter").selected = 0; -} - -function applyFilters() -{ - // Save selected rows - let modsDisabledList = Engine.GetGUIObjectByName("modsDisabledList"); - let modsEnabledList = Engine.GetGUIObjectByName("modsEnabledList"); - - let selectedDisabledFolder = modsDisabledList.list_folder[modsDisabledList.selected]; - let selectedEnabledFolder = modsEnabledList.list_folder[modsEnabledList.selected]; - - // Remove selected rows to prevent a link to a non existing item - modsDisabledList.selected = -1; - modsEnabledList.selected = -1; - - displayModLists(); - - // Restore previously selected rows - modsDisabledList.selected = modsDisabledList.list_folder.indexOf(selectedDisabledFolder); - modsEnabledList.selected = modsEnabledList.list_folder.indexOf(selectedEnabledFolder); - - Engine.GetGUIObjectByName("globalModDescription").caption = ""; -} - -function filterMod(folder) -{ - let mod = g_Mods[folder]; - - let modTypeFilter = Engine.GetGUIObjectByName("modTypeFilter"); - let negateFilter = Engine.GetGUIObjectByName("negateFilter").checked; - - if (modTypeFilter.selected > 0 && (mod.type || "") != modTypeFilter.list[modTypeFilter.selected]) - return negateFilter; - - let searchText = Engine.GetGUIObjectByName("modGenericFilter").caption; - if (searchText && - searchText != translate("Filter") && - folder.indexOf(searchText) == -1 && - mod.name.indexOf(searchText) == -1 && - mod.label.indexOf(searchText) == -1 && - (mod.type || "").indexOf(searchText) == -1 && - (mod.url || "").indexOf(searchText) == -1 && - mod.version.indexOf(searchText) == -1 && - mod.description.indexOf(searchText) == -1 && - mod.dependencies.indexOf(searchText) == -1) - return negateFilter; - - return !negateFilter; -} - -function closePage() -{ - Engine.SwitchGuiPage("page_pregame.xml", {}); -} - -/** - * Moves an item in the list up or down. - */ -function moveCurrItem(objectName, up) -{ - let obj = Engine.GetGUIObjectByName(objectName); - let idx = obj.selected; - if (idx == -1) - return; - - let num = obj.list.length; - let idx2 = idx + (up ? -1 : 1); - if (idx2 < 0 || idx2 >= num) - return; - - let tmp = g_ModsEnabled[idx]; - g_ModsEnabled[idx] = g_ModsEnabled[idx2]; - g_ModsEnabled[idx2] = tmp; - - obj.list = g_ModsEnabled; - obj.selected = idx2; - - displayModList("modsEnabledList", g_ModsEnabled); -} - -function areDependenciesMet(folder) -{ - let guiObject = Engine.GetGUIObjectByName("message"); - - for (let dependency of g_Mods[folder].dependencies) - { - if (isDependencyMet(dependency)) - continue; - - guiObject.caption = - '[color="' + g_ColorDependenciesNotMet + '"]' + - sprintf(translate('Dependency not met: %(dep)s'), { "dep": dependency }) + - '[/color]'; - - return false; - } - - guiObject.caption = - '[color="' + g_ColorDependenciesMet + '"]' + - translate('All dependencies met') + - '[/color]'; - - return true; -} - -/** - * @param dependency is a mod name or a mod version comparison. - */ -function isDependencyMet(dependency) -{ - let operator = dependency.match(g_CompareVersion); - let [name, version] = operator ? dependency.split(operator[0]) : [dependency, undefined]; - - return g_ModsEnabled.some(folder => - g_Mods[folder].name == name && - (!operator || versionSatisfied(g_Mods[folder].version, operator, version))); -} - -/** - * Compares the given versions using the given operator. - * '-' or '_' is ignored. Only numbers are supported. - * @note "5.3" < "5.3.0" - */ -function versionSatisfied(version1, operator, version2) -{ - let versionList1 = version1.split(/[-_]/)[0].split(/\./g); - let versionList2 = version2.split(/[-_]/)[0].split(/\./g); - - let eq = operator.indexOf("=") != -1; - let lt = operator.indexOf("<") != -1; - let gt = operator.indexOf(">") != -1; - - for (let i = 0; i < Math.min(versionList1.length, versionList2.length); ++i) - { - let diff = +versionList1[i] - +versionList2[i]; - if (isNaN(diff)) - continue; - - if (gt && diff > 0 || lt && diff < 0) - return true; - - if (gt && diff < 0 || lt && diff > 0 || eq && diff) - return false; - } - - // common prefix matches - let ldiff = versionList1.length - versionList2.length; - if (!ldiff) - return eq; - - // NB: 2.3 != 2.3.0 - if (ldiff < 0) - return lt; - - return gt; -} - -function sortEnabledMods() -{ - let dependencies = {}; - for (let folder of g_ModsEnabled) - dependencies[folder] = g_Mods[folder].dependencies.map(d => d.split()[0]); - - g_ModsEnabled.sort((folder1, folder2) => - dependencies[folder1].indexOf(g_Mods[folder2].name) != -1 ? 1 : - dependencies[folder2].indexOf(g_Mods[folder1].name) != -1 ? -1 : 0); - - displayModList("modsEnabledList", g_ModsEnabled); -} - -function showModDescription(listObjectName) -{ - let listObject = Engine.GetGUIObjectByName(listObjectName); - - Engine.GetGUIObjectByName("globalModDescription").caption = - listObject.list[listObject.selected] ? - g_Mods[listObject.list[listObject.selected]].description : - '[color="' + g_ColorNoModSelected + '"]' + translate("No mod has been selected.") + '[/color]'; -} Index: binaries/data/mods/mod/gui/modmod/modmod.xml =================================================================== --- binaries/data/mods/mod/gui/modmod/modmod.xml +++ binaries/data/mods/mod/gui/modmod/modmod.xml @@ -1,188 +0,0 @@ - - - - -