local Search = {} local Storage = require("modules/exp_util/storage") --- Setup the storage to contain the pending translations and the completed ones local pending = {} --- @type { [1]: string, [2]: string }[] local translations = {} --- @type table> Storage.register({ pending, translations, }, function(tbl) pending = tbl[1] translations = tbl[2] end) local command_names = {} --- @type string[] local command_objects = {} --- @type table local required_translations = {} --- @type LocalisedString[] --- Gets the descriptions of all commands, not including their aliases --- @param custom_commands table The complete list of registered custom commands function Search.prepare(custom_commands) local known_aliases = {} --- @type table for name, command in pairs(custom_commands) do for _, alias in ipairs(command.aliases) do known_aliases[alias] = name end end local index = 0 for name, locale_desc in pairs(commands.commands) do if not known_aliases[name] then index = index + 1 command_names[index] = name required_translations[index] = locale_desc command_objects[name] = custom_commands[name] or { name = name, description = locale_desc, help_text = locale_desc, aliases = {}, } end end for name, locale_desc in pairs(commands.game_commands) do index = index + 1 command_names[index] = name required_translations[index] = locale_desc command_objects[name] = { name = name, description = locale_desc, help_text = locale_desc, aliases = {}, } end end --- Called when a locale changes so the new translations can be requested --- @param event EventData.on_player_locale_changed | EventData.on_player_joined_game function Search.on_player_locale_changed(event) local player = game.players[event.player_index] local locale = player.locale if not translations[locale] then translations[locale] = {} local ids = player.request_translations(required_translations) assert(ids, "Translation ids was nil") for i, command_name in ipairs(command_names) do pending[ids[i]] = { locale, command_name } end end end --- Called when a translation request is completed --- @param event EventData.on_string_translated --- @return nil function Search.on_string_translated(event) local info = pending[event.id] if not info then return end pending[event.id] = nil if not event.translated then return log("Failed translation for " .. info[1] .. " " .. info[2]) end translations[info[1]][info[2]] = event.result:lower() end --- Searches all game commands and the provided custom commands for the given keyword --- @param keyword string The keyword to search for --- @param custom_commands table A dictionary of commands to search --- @param locale string? The local to search, default is english ("en") --- @return table # A dictionary of commands function Search.search_commands(keyword, custom_commands, locale) local rtn = {} --- @type table keyword = keyword:lower() locale = locale or "en" local searchable_commands = translations[locale] if not searchable_commands then return {} end -- Search all custom commands for name, search_text in pairs(searchable_commands) do if search_text:match(keyword) or name:match(keyword) then local obj = command_objects[name] if not obj.defined_at or custom_commands[name] then rtn[name] = obj end end end return rtn end return Search