diff --git a/.emmyrc.json b/.emmyrc.json new file mode 100644 index 00000000..213157cc --- /dev/null +++ b/.emmyrc.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json", + "runtime": { + "version": "Lua5.2", + "requirePattern": [ "?", "?.lua" ] + }, + "workspace": { + "$comment-moduleMap": "Replaces the fmtk --clusterio-modules plugin, rewrites each file's own module path rather than the require string", + "$comment-library": "clusterio is outside this repo, set CLUSTERIO to your checkout. The factorio typedefs come from .luarc.json, which the factoriomod-debug extension manages", + "library": [ "$CLUSTERIO/packages/host" ], + "ignoreDir": [ ".github", "web", "dist", "factorio" ], + "ignoreGlobs": [ "**/node_modules/**", "**/dist/**", "**/campaigns/**" ], + "moduleMap": [ + { "pattern": "^([^.]+)\\.module\\.module_exports$", "replace": "modules.$1" }, + { "pattern": "^([^.]+)\\.module\\.(.+)$", "replace": "modules.$1.$2" } + ] + }, + "doc": { + "privateName": [ "__*" ] + }, + "$comment-disable": "Carried over from the luals config, which had these as editor only rather than checked in ci", + "$comment-unnecessary-if": "Disabled by the config fmtk generates for itself, the api union types make it unreliable", + "diagnostics": { + "globals": [ "__DebugAdapter", "__Profiler" ], + "disable": [ + "assign-type-mismatch", + "param-type-mismatch", + "preferred-local-alias", + "unnecessary-assert", + "unnecessary-if", + "unused" + ] + } +} diff --git a/.github/workflows/fmtk.yml b/.github/workflows/fmtk.yml index 4050b457..227585f1 100644 --- a/.github/workflows/fmtk.yml +++ b/.github/workflows/fmtk.yml @@ -1,76 +1,94 @@ -name: FMTK Lint - -on: - push: - pull_request: - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 10 - - uses: actions/setup-node@v4 - with: - node-version: lts/* - - name: Install FMTK - run: | - # Pinned: 2.1.4+ generates typedefs targeting EmmyLua that LuaLS misreads - pnpm install factoriomod-debug@2.1.3 - pnpm exec fmtk luals-addon - jq '.["workspace.library"] += ["${{ github.workspace }}/factorio/library"] | .["runtime.plugin"] = "${{ github.workspace }}/factorio/plugin.lua"' .luarc.json > temp.luarc.json - jq -s '.[0] * .[1].settings' temp.luarc.json ${{ github.workspace }}/factorio/config.json > check.luarc.json - - name: Install LuaLS - run: | - wget https://github.com/LuaLS/lua-language-server/releases/download/3.18.2/lua-language-server-3.18.2-linux-x64.tar.gz -q -O lusls.tar.gz - mkdir luals && tar -xf lusls.tar.gz -C luals && rm lusls.tar.gz - - name: Run Lint Report - shell: bash - run: | - ./luals/bin/lua-language-server --check=. --logpath=. --configpath=check.luarc.json --checklevel=Information --check_out_path=check.json - - # Credit to https://github.com/Krealle/luals-check-action/blob/main/action.yml - # Although some minor fixes were needed - - # Format and print the messages (would be nice to format as a table, but that's too complex for jq) - cat check.json | \ - jq -r \ - 'to_entries | map(.key as $file | .value[] | - { - file: $file | sub("file://${{ github.workspace }}/./"; ""), - code: .code, - line: .range.start.line, - message: (.message | split("\n") - | map(if startswith("- ") then .[2:] else . end) - | join("\n")), - severity: (if .severity <= 1 then "ERR" else "WARN" end) - }) | - map("**[\(.severity)] \(.code):** \(.file)#L\(.line)
\(.message)") | .[]' \ - > $GITHUB_STEP_SUMMARY - - echo "" - - # Github Annotations (limited to 10) - cat check.json | \ - jq -r \ - 'to_entries | map(.key as $file | .value[] | - { - file: $file | sub("file://${{ github.workspace }}/./"; ""), - title: .code, - line: .range.start.line, - endLine: .range.end.line, - col: .range.start.character, - endColumn: .range.end.character, - message: .message | gsub("\n"; "%0A"; "m"), - level: (if .severity <= 1 then "error" else "warning" end) - }) | - map("::\(.level) file=\(.file),line=\(.line+1),endLine=\(.line+1),col=\(.col+1),endColumn=\(.endColumn+1),title=\(.title)::\(.message) (\(.title))") | .[]' - - if [[ $(wc -l < check.json) > 1 ]] ; then - exit 1 - else - echo "✅ All checks succeeded!" | tee $GITHUB_STEP_SUMMARY - fi - \ No newline at end of file +name: Lua Lint + +on: + push: + pull_request: + +env: + EMMYLUA_CHECK_VERSION: "0.24.0" + CLUSTERIO: ${{ github.workspace }}/.clusterio + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Checkout clusterio modules + uses: actions/checkout@v4 + with: + repository: clusterio/clusterio + path: .clusterio + sparse-checkout: packages/host/modules + sparse-checkout-cone-mode: false + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Generate Factorio typedefs + run: | + pnpm install factoriomod-debug + pnpm exec fmtk luals-addon "$RUNNER_TEMP" + - name: Install emmylua_check + run: | + curl -fsSL "https://github.com/EmmyLuaLs/emmylua-analyzer-rust/releases/download/${EMMYLUA_CHECK_VERSION}/emmylua_check-linux-x64.tar.gz" \ + | tar -xz -C "$RUNNER_TEMP" + - name: Run Lint Report + shell: bash + run: | + # The typedefs are generated per run, clusterio comes from CLUSTERIO above + jq -n --arg lib "$RUNNER_TEMP/factorio/library" \ + '{ workspace: { library: [ $lib ], ignoreGlobs: [ ".clusterio/**" ] } }' \ + > "$RUNNER_TEMP/ci.emmyrc.json" + + # Exits non zero on error severity, so the gate below is used instead + "$RUNNER_TEMP/emmylua_check" . --config ".emmyrc.json,$RUNNER_TEMP/ci.emmyrc.json" \ + --output-format json --output check.json || true + + # Credit to https://github.com/Krealle/luals-check-action/blob/main/action.yml + # Although some minor fixes were needed + + # Format and print the messages (would be nice to format as a table, but that's too complex for jq) + jq -r --arg root "$PWD/" \ + '.[] | (.file | ltrimstr($root)) as $file | .diagnostics[] | + { + file: $file, + code: .code, + line: .range.start.line, + message: (.message | split("\n") + | map(if startswith("- ") then .[2:] else . end) + | join("\n")), + severity: (if .severity <= 1 then "ERR" else "WARN" end) + } | + "**[\(.severity)] \(.code):** \(.file)#L\(.line + 1)
\(.message)"' \ + check.json > "$GITHUB_STEP_SUMMARY" + + echo "" + + # Github Annotations (limited to 10) + jq -r --arg root "$PWD/" \ + '.[] | (.file | ltrimstr($root)) as $file | .diagnostics[] | + { + file: $file, + title: .code, + line: .range.start.line, + endLine: .range.end.line, + col: .range.start.character, + endColumn: .range.end.character, + message: (.message | gsub("\n"; "%0A"; "m")), + level: (if .severity <= 1 then "error" else "warning" end) + } | + "::\(.level) file=\(.file),line=\(.line + 1),endLine=\(.endLine + 1),col=\(.col + 1),endColumn=\(.endColumn + 1),title=\(.title)::\(.message) (\(.title))"' \ + check.json + + # An entry is emitted for every file checked, including clean ones, so + # the gate counts diagnostics and asserts the workspace was actually read + if [[ $(jq 'length' check.json) -lt 100 ]] ; then + echo "::error::Only $(jq 'length' check.json) files were checked, expected the whole workspace" + exit 1 + elif [[ $(jq '[.[].diagnostics[]] | length' check.json) -gt 0 ]] ; then + exit 1 + else + echo "✅ All checks succeeded!" | tee "$GITHUB_STEP_SUMMARY" + fi diff --git a/.gitignore b/.gitignore index a331c19a..bf2406f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ dist/ node_modules/ .vscode +.luarc.json diff --git a/.luarc.json b/.luarc.json deleted file mode 100644 index ba4b39f0..00000000 --- a/.luarc.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json", - "workspace.ignoreDir": [ - ".vscode", ".github", "luals", "factorio", "web" - ], - "completion.requireSeparator": "/", - "runtime.pluginArgs": [ - "--clusterio-modules" - ], - "doc": { - "regengine": "glob", - "privateName": [ "__*" ], - "packageName": [ "_*" ] - }, - "type": { - "checkTableShape": true, - "inferParamType": true - }, - "$comment-name-style-check": "Disabled below until config issue fixed: https://github.com/LuaLS/lua-language-server/issues/2643", - "$comment-type-mismatch": "Disabled unless opened due to performance concerns, time reduced to 10s from 400s", - "diagnostics": { - "unusedLocalExclude": [ "_*", "i", "j", "k", "v" ], - "groupFileStatus": { - "ambiguity": "Any", - "await": "None", - "codestyle": "Opened", - "conventions": "Any", - "duplicate": "Any", - "global": "Any", - "luadoc": "Opened", - "redefined": "Opened", - "strict": "Any", - "strong": "Any", - "type-check": "Any", - "unbalanced": "Opened", - "unused": "Opened" - }, - "neededFileStatus": { - "no-unknown": "None!", - "spell-check": "None!", - "name-style-check": "None!", - "assign-type-mismatch": "Opened!", - "return-type-mismatch": "Opened!", - "param-type-mismatch": "Opened!" - } - }, - "nameStyle.config": { - "local_name_style": [{ - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "snake_case" - }], - "module_local_name_style": [{ - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "snake_case" - }, { - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "upper_snake_case" - }, { - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "pascal_case" - }], - "function_param_name_style": [{ - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "snake_case" - }], - "function_name_style": [{ - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "snake_case" - }], - "local_function_name_style": [{ - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "snake_case" - }], - "table_field_name_style": [{ - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "snake_case" - }], - "global_variable_name_style": [{ - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "snake_case" - }, { - "type" : "pattern", - "param": "_?_?(\\S*)", - "$1": "upper_snake_case" - }], - "module_name_style": [ "pascal_case", "snake_case" ], - "require_module_name_style": [ "pascal_case", "snake_case" ], - "class_name_style": "pascal_case", - "const_variable_name_style": "upper_snake_case" - }, - "format.defaultConfig": { - "continuation_indent.in_expr": "0" - } -} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d1e0254..9fa851c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,8 @@ All are welcome to make bug reports, feature requests, and pull requests for our For developers wanting to add features please follow these guidelines: - All lua code is documented using ldoc. +- Set the `CLUSTERIO` environment variable to your clusterio development install path, the lint needs it to resolve `modules/clusterio/*`. +- Lua is checked with [emmylua](https://github.com/EmmyLuaLs/emmylua-analyzer-rust), configured by `.emmyrc.json`. Install the EmmyLua extension rather than sumnekolua / luals, and use factoriomod-debug to generate the factorio api types. Note that an inline cast must be written `--[[@as T]]`, the spaced form is not parsed. - Changes should be made on your own fork and merged into `main` through a pull request. - Each pull request should be limited to one feature or a few bug fixes and link to the related issue page. - Pull requests are automatically linted and documentation checked. diff --git a/exp_commands/module/commands/authorities.lua b/exp_commands/module/commands/authorities.lua index db82a6ce..c1ec3309 100644 --- a/exp_commands/module/commands/authorities.lua +++ b/exp_commands/module/commands/authorities.lua @@ -10,7 +10,7 @@ The default permission authorities controlled by the flags: admin_only, system_o local Storage = require("modules/exp_util/storage") -local Commands = require("modules/exp_commands") --- @class Commands +local Commands = require("modules/exp_commands") --- @class (partial) Commands local add, allow, deny = Commands.add_permission_authority, Commands.status.success, Commands.status.unauthorised local authorities = {} @@ -28,13 +28,13 @@ end) --- Allow a player access to system commands, use for debug purposes only --- @param player_name string? The name of the player to give access to, default is the current player function Commands.unlock_system_commands(player_name) - system_players[player_name or game.player.name] = true + system_players[player_name or assert(game.player).name] = true end --- Remove access from system commands for a player, use for debug purposes only --- @param player_name string? The name of the player to give access to, default is the current player function Commands.lock_system_commands(player_name) - system_players[player_name or game.player.name] = nil + system_players[player_name or assert(game.player).name] = nil end --- Get a list of all players who have system commands unlocked diff --git a/exp_commands/module/commands/help.lua b/exp_commands/module/commands/help.lua index 602b84c4..bb8c6c8b 100644 --- a/exp_commands/module/commands/help.lua +++ b/exp_commands/module/commands/help.lua @@ -25,18 +25,18 @@ end) --- @param page_size number The number of requests to show per page --- @return LocalisedString[][], number local function format_as_pages(commands, page_size) - local pages = { {} } + local current_page = {} + local pages = { current_page } local page_length = 0 - local current_page = 1 local total = 0 for _, command in pairs(commands) do total = total + 1 page_length = page_length + 1 if page_length > page_size then - current_page = current_page + 1 - pages[current_page] = {} page_length = 1 + current_page = {} + pages[#pages + 1] = current_page end local description @@ -48,7 +48,7 @@ local function format_as_pages(commands, page_size) end local aliases = #command.aliases > 0 and { "exp-commands_help.aliases", table.concat(command.aliases, ", ") } or "" - pages[current_page][page_length] = { "exp-commands_help.format", command.name, description, aliases } + current_page[page_length] = { "exp-commands_help.format", command.name, description, aliases } end return pages, total @@ -71,7 +71,7 @@ Commands.new("commands", { "exp-commands_help.description" }) page = as_number end - keyword = keyword:lower() + keyword = tostring(keyword):lower() local pages, found if cache and cache.keyword == keyword then -- Cached value found, no search is needed diff --git a/exp_commands/module/commands/rcon.lua b/exp_commands/module/commands/rcon.lua index 1e1d2ec5..77da68f6 100644 --- a/exp_commands/module/commands/rcon.lua +++ b/exp_commands/module/commands/rcon.lua @@ -12,7 +12,7 @@ local ExpUtil = require("modules/exp_util") local Async = require("modules/exp_util/async") local Storage = require("modules/exp_util/storage") -local Commands = require("modules/exp_commands") --- @class Commands +local Commands = require("modules/exp_commands") --- @class (partial) Commands local rcon_env = {} --- @type table local rcon_static = {} --- @type table @@ -21,12 +21,10 @@ setmetatable(rcon_static, { __index = _G }) setmetatable(rcon_env, { __index = rcon_static }) --- Some common static values which can be added now ---- @diagnostic disable: name-style-check rcon_static.Async = Async rcon_static.ExpUtil = ExpUtil rcon_static.Commands = Commands rcon_static.print = Commands.print ---- @diagnostic enable: name-style-check --- Some common callback values which are useful when a player uses the command --- @alias ExpCommand.RconDynamic fun(player: LuaPlayer?): any diff --git a/exp_commands/module/commands/sudo.lua b/exp_commands/module/commands/sudo.lua index c56ef29d..33fb9e3c 100644 --- a/exp_commands/module/commands/sudo.lua +++ b/exp_commands/module/commands/sudo.lua @@ -19,7 +19,7 @@ Commands.new("_sudo", { "exp-commands_sudo.description" }) --- @cast command ExpCommand --- @cast parameter string - --- @diagnostic disable-next-line: invisible + --- @diagnostic disable-next-line: access-invisible return Commands._event_handler{ name = command.name, tick = game.tick, diff --git a/exp_commands/module/commands/types.lua b/exp_commands/module/commands/types.lua index 11511b4f..0cef9b84 100644 --- a/exp_commands/module/commands/types.lua +++ b/exp_commands/module/commands/types.lua @@ -25,7 +25,7 @@ local Commands = require("modules/exp_commands") local add, parse = Commands.add_data_type, Commands.parse_input local valid, invalid = Commands.status.success, Commands.status.invalid_input -local types = {} --- @class Commands.types +local types = {} --- @class (partial) Commands.types --- A boolean value where true is one of: yes, y, true, 1 types.boolean = diff --git a/exp_commands/module/module_exports.lua b/exp_commands/module/module_exports.lua index 93a5c626..af8fffc4 100644 --- a/exp_commands/module/module_exports.lua +++ b/exp_commands/module/module_exports.lua @@ -61,7 +61,7 @@ local Search = require("modules/exp_commands/search") --- @type LuaPlayer? local _print_player ---- @class Commands +--- @class (partial) Commands local Commands = { color = ExpUtil.color, format_rich_text_color = ExpUtil.format_rich_text_color, @@ -84,7 +84,7 @@ local Commands = { --- Contains the different status values a command can return Commands.status = {} ---- @class Commands.types: table +--- @class (partial) Commands.types: table | Commands.InputParserFactory> --- Stores all input parsers and validators for different data types Commands.types = {} @@ -103,7 +103,7 @@ end --- @class Commands.Argument --- @field name string The name of the argument --- @field description LocalisedString? The description of the argument ---- @field input_parser Commands.InputParser The input parser for the argument +--- @field input_parser Commands.InputParser The input parser for the argument --- @field optional boolean True when the argument is optional --- @field default any? The default value of the argument @@ -159,7 +159,7 @@ Commands.server = setmetatable({ Commands.error("Command does not support rcon usage, requires LuaPlayer." .. key) error("Command does not support rcon usage, requires LuaPlayer." .. key) end, -}) --[[ @as LuaPlayer ]] +}) --[[@as LuaPlayer]] --- Status Returns. -- Return values used by command callbacks @@ -170,7 +170,8 @@ Commands.server = setmetatable({ --- @param msg LocalisedString? An optional message to be included when a command completes (only has an effect in command callbacks) --- @return Commands.Status, LocalisedString # Should be returned directly without modification function Commands.status.success(msg) - return Commands.status.success, msg == nil and { "exp-commands.success" } or msg + if msg == nil then return Commands.status.success, { "exp-commands.success" } end + return Commands.status.success, msg end --- Used to signal an error has occurred in a command, data type parser, or permission authority @@ -178,7 +179,8 @@ end --- @param msg LocalisedString? An optional error message to be included in the output, a generic message is used if not provided --- @return Commands.Status, LocalisedString # Should be returned directly without modification function Commands.status.error(msg) - return Commands.status.error, { "exp-commands.error", msg == nil and { "exp-commands.error-default" } or msg } + if msg == nil then msg = { "exp-commands.error-default" } end + return Commands.status.error, { "exp-commands.error", msg } end --- Used to signal the player is unauthorised to use a command, primarily used by permission authorities but can be used in a command callback @@ -186,7 +188,8 @@ end --- @param msg LocalisedString? An optional error message to be included in the output, a generic message is used if not provided --- @return Commands.Status, LocalisedString # Should be returned directly without modification function Commands.status.unauthorised(msg) - return Commands.status.unauthorised, { "exp-commands.unauthorized", msg == nil and { "exp-commands.unauthorized-default" } or msg } + if msg == nil then msg = { "exp-commands.unauthorized-default" } end + return Commands.status.unauthorised, { "exp-commands.unauthorized", msg } end --- Used to signal the player provided invalid input to an command, primarily used by data type parsers but can be used in a command callback @@ -194,15 +197,16 @@ end --- @param msg LocalisedString? An optional error message to be included in the output, a generic message is used if not provided --- @return Commands.Status, LocalisedString # Should be returned directly without modification function Commands.status.invalid_input(msg) - return Commands.status.invalid_input, msg == nil and { "exp-commands.invalid-input" } or msg + if msg == nil then return Commands.status.invalid_input, { "exp-commands.invalid-input" } end + return Commands.status.invalid_input, msg end --- Used to signal an internal error has occurred, this is reserved for internal use only ---- @param msg LocalisedString A message detailing the error which has occurred, will be logged and outputted +--- @param msg LocalisedString? A message detailing the error which has occurred, will be logged and outputted --- @return Commands.Status, LocalisedString # Should be returned directly without modification --- @package function Commands.status.internal_error(msg) - return Commands.status.internal_error, { "exp-commands.internal-error", msg } + return Commands.status.internal_error, { "exp-commands.internal-error", msg or "" } end --- @type table @@ -281,7 +285,7 @@ end --- @alias Commands.InputParserFactory fun(...: any): Commands.InputParser --- Add a new input parser to the command library, this method validates that it does not already exist ---- @generic T : Commands.InputParser | Commands.InputParserFactory +--- @generic T : Commands.InputParser | Commands.InputParserFactory --- @param data_type string The name of the data type the input parser reads in and validates, becomes a key of Commands.types --- @param input_parser T The function used to parse and validate the data type --- @return T # The function which was provided as the second argument @@ -295,7 +299,7 @@ function Commands.add_data_type(data_type, input_parser) end --- Remove an input parser for a data type, must be the same string that was passed to add_input_parser ---- @param data_type string | Commands.InputParser | Commands.InputParserFactory The data type or input parser you want to remove the input parser for +--- @param data_type string | Commands.InputParser | Commands.InputParserFactory The data type or input parser you want to remove the input parser for function Commands.remove_data_type(data_type) Commands.types[data_type] = nil for k, v in pairs(Commands.types) do @@ -433,7 +437,7 @@ end --- Add a new required argument to the command of the given data type --- @param name string The name of the argument being added --- @param description LocalisedString? The description of the argument being added ---- @param input_parser Commands.InputParser The input parser to be used for the argument +--- @param input_parser Commands.InputParser The input parser to be used for the argument --- @return ExpCommand function Commands._prototype:argument(name, description, input_parser) assert_command_mutable(self) @@ -454,7 +458,7 @@ end --- Add a new optional argument to the command of the given data type --- @param name string The name of the argument being added --- @param description LocalisedString? The description of the argument being added ---- @param input_parser Commands.InputParser The input parser to be used for the argument +--- @param input_parser Commands.InputParser The input parser to be used for the argument --- @return ExpCommand function Commands._prototype:optional(name, description, input_parser) assert_command_mutable(self) diff --git a/exp_commands/module/search.lua b/exp_commands/module/search.lua index 56fe8b05..f4ddbaea 100644 --- a/exp_commands/module/search.lua +++ b/exp_commands/module/search.lua @@ -3,7 +3,7 @@ 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 pending = {} --- @type table local translations = {} --- @type table> Storage.register({ pending, @@ -50,6 +50,7 @@ function Search.prepare(custom_commands) name = name, description = locale_desc, help_text = locale_desc, + usage = locale_desc, aliases = {}, } end @@ -65,7 +66,7 @@ function Search.on_player_locale_changed(event) 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 } + pending[assert(ids[i])] = { locale, command_name } end end end diff --git a/exp_groups/module/control.lua b/exp_groups/module/control.lua index 0c61af71..232fd6e3 100644 --- a/exp_groups/module/control.lua +++ b/exp_groups/module/control.lua @@ -3,7 +3,7 @@ Adds permission group syncing to clusterio ]] local clusterio_api = require("modules/clusterio/api") -local compat = require("modules/clusterio/compat") +local compat = require("modules/clusterio/compat") --[[@as LibCompat]] --- Top level module table, contains event handlers and public methods --- @class ExpGroups diff --git a/exp_groups/module/globals.lua b/exp_groups/module/globals.lua index ce036c21..27ecdb31 100644 --- a/exp_groups/module/globals.lua +++ b/exp_groups/module/globals.lua @@ -5,7 +5,7 @@ Therefore, we advise that this should be the only file in your module to expose Typically this would be your control file as shown in the example below ]] ---- @diagnostic disable: global-element +--- @diagnostic disable: global-in-non-module -- Access using `/sc exp_groups.foo()` exp_groups = require("modules/exp_groups/control") diff --git a/exp_gui/module/control.lua b/exp_gui/module/control.lua index e6c7989a..6c7114ec 100644 --- a/exp_gui/module/control.lua +++ b/exp_gui/module/control.lua @@ -16,7 +16,7 @@ Storage.register(player_elements, function(tbl) player_elements = tbl end) ---- @class Gui +--- @class (partial) Gui local Gui = { define = ExpElement.new, from_argument = ExpElement.from_argument, @@ -46,9 +46,11 @@ end --- @return LuaPlayer function Gui.get_player(input) if type(input) == "table" and not input.player_index then - return assert(game.get_player(input.element.player_index)) + --- @cast input { element: LuaGuiElement } + return (assert(game.get_player(input.element.player_index))) end - return assert(game.get_player(input.player_index)) + --- @cast input LuaGuiElement | { player_index: uint } + return (assert(game.get_player(input.player_index))) end --- Toggle the enable state of an element @@ -88,7 +90,7 @@ end --- @param define ExpElement --- @param visible Gui.VisibleCallback | boolean | nil function Gui.add_top_element(define, visible) - assert(Gui.top_elements[define.name] == nil, "Element is already added to the top flow") + assert(Gui.top_elements[define] == nil, "Element is already added to the top flow") Gui.top_elements[define] = visible or false end @@ -96,7 +98,7 @@ end --- @param define ExpElement --- @param visible Gui.VisibleCallback | boolean | nil function Gui.add_left_element(define, visible) - assert(Gui.left_elements[define.name] == nil, "Element is already added to the left flow") + assert(Gui.left_elements[define] == nil, "Element is already added to the left flow") Gui.left_elements[define] = visible or false end @@ -105,7 +107,7 @@ end --- @param define ExpElement --- @param visible Gui.VisibleCallback | boolean | nil function Gui.add_relative_element(define, visible) - assert(Gui.relative_elements[define.name] == nil, "Element is already added to the relative flow") + assert(Gui.relative_elements[define] == nil, "Element is already added to the relative flow") Gui.relative_elements[define] = visible or false end @@ -114,7 +116,8 @@ end --- @param player LuaPlayer --- @return LuaGuiElement function Gui.get_top_element(define, player) - return assert(player_elements[player.index].top[define.name], "Element is not on the top flow") + local elements = assert(player_elements[player.index]) + return (assert(elements.top[define.name], "Element is not on the top flow")) end --- Register a element define to be drawn to the left flow on join @@ -122,7 +125,8 @@ end --- @param player LuaPlayer --- @return LuaGuiElement function Gui.get_left_element(define, player) - return assert(player_elements[player.index].left[define.name], "Element is not on the left flow") + local elements = assert(player_elements[player.index]) + return (assert(elements.left[define.name], "Element is not on the left flow")) end --- Register a element define to be drawn to the relative flow on join @@ -130,7 +134,8 @@ end --- @param player LuaPlayer --- @return LuaGuiElement function Gui.get_relative_element(define, player) - return assert(player_elements[player.index].relative[define.name], "Element is not on the relative flow") + local elements = assert(player_elements[player.index]) + return (assert(elements.relative[define.name], "Element is not on the relative flow")) end --- Ensure all the correct elements are visible and exist @@ -188,9 +193,9 @@ function Gui._ensure_consistency(event) -- This check isn't needed, but allows the toolbar file to be deleted without modifying any lib code if Gui.toolbar then - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible Gui.toolbar._create_elements(player) - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible Gui.toolbar._ensure_consistency(player) end end @@ -211,7 +216,7 @@ local function on_gui_opened(event) if visible then event.element = element - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible define:raise_event(event) end end diff --git a/exp_gui/module/data.lua b/exp_gui/module/data.lua index 8ae9e15e..327a11f1 100644 --- a/exp_gui/module/data.lua +++ b/exp_gui/module/data.lua @@ -62,6 +62,7 @@ local GuiData = { --- @field player_data table --- @field force_data table --- @field global_data table +--- @field [DataKey] any -- This class has no prototype methods -- Same as raw but __index ensures the values exist @@ -89,13 +90,16 @@ function GuiData._metatable.__index(self, key) assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.") local object_name = key.object_name --- @diagnostic disable-line assign-type-mismatch if object_name == "LuaGuiElement" then + --- @cast key LuaGuiElement local data = self._raw.element_data local player_elements = data and data[key.player_index] return player_elements and player_elements[key.index] elseif object_name == "LuaPlayer" then + --- @cast key LuaPlayer local data = self._raw.player_data return data and data[key.index] elseif object_name == "LuaForce" then + --- @cast key LuaForce local data = self._raw.force_data return data and data[key.index] else @@ -153,7 +157,7 @@ end --- @param scope string --- @return GuiData function GuiData.get(scope) - return GuiData._scopes[scope] --[[ @as GuiData ]] + return GuiData._scopes[scope] --[[@as GuiData]] end --- Used to clean up data from destroyed elements @@ -168,7 +172,7 @@ local function on_object_destroyed(event) for _, scope in pairs(registered_scopes) do local data = scope._raw.element_data local player_elements = data and data[player_index] - if player_elements then + if data and player_elements then player_elements[element_index] = nil if not next(player_elements) then data[player_index] = nil diff --git a/exp_gui/module/elements.lua b/exp_gui/module/elements.lua index f8df5853..b4dbd472 100644 --- a/exp_gui/module/elements.lua +++ b/exp_gui/module/elements.lua @@ -1,4 +1,4 @@ ---- @class Gui +--- @class (partial) Gui local Gui = require("modules/exp_gui") --- @class Gui.elements @@ -28,7 +28,7 @@ Elements.aligned_flow = Gui.define("aligned_flow") vertically_stretchable = vertical_align ~= "center", horizontally_stretchable = horizontal_align ~= "center", } - end) --[[ @as any ]] + end) --[[@as any]] --- A solid horizontal white bar element --- @class Gui.elements.bar: ExpElement @@ -48,11 +48,11 @@ Elements.bar = Gui.define("bar") else style.horizontally_stretchable = true end - end) --[[ @as any ]] + end) --[[@as any]] --- A label which is centered --- @class Gui.elements.centered_label: ExpElement ---- @overload fun(parent: LuaGuiElement, width: number, caption: LocalisedString, tooltip: LocalisedString?): LuaGuiElement +--- @overload fun(parent: LuaGuiElement, width: number, caption: LocalisedString?, tooltip: LocalisedString?): LuaGuiElement Elements.centered_label = Gui.define("centered_label") :draw{ type = "label", @@ -63,7 +63,7 @@ Elements.centered_label = Gui.define("centered_label") horizontal_align = "center", single_line = false, width = Gui.from_argument(1), - } --[[ @as any ]] + } --[[@as any]] --- A label which has two white bars on either side of it --- @class Gui.elements.title_label: ExpElement @@ -91,7 +91,7 @@ Elements.title_label = Gui.define("title_label") Elements.bar(flow) return label - end) --[[ @as any ]] + end) --[[@as any]] --- A fixed size vertical scroll pane --- @class Gui.elements.scroll_pane: ExpElement @@ -109,7 +109,7 @@ Elements.scroll_pane = Gui.define("scroll_pane") padding = { 1, 3 }, maximal_height = Gui.from_argument(1), horizontally_stretchable = true, - } --[[ @as any ]] + } --[[@as any]] --- A fixed size vertical scroll pane containing a table --- @class Gui.elements.scroll_table: ExpElement @@ -132,7 +132,7 @@ Elements.scroll_table = Gui.define("scroll_table") cell_padding = 1, vertical_align = "center", horizontally_stretchable = true, - } --[[ @as any ]] + } --[[@as any]] --- A container frame --- @class Gui.elements.container: ExpElement @@ -159,13 +159,13 @@ Elements.container = Gui.define("container") vertically_stretchable = false, horizontally_stretchable = false, minimal_width = Gui.from_argument(1), - } --[[ @as any ]] + } --[[@as any]] --- Get the root element of a container --- @param container LuaGuiElement --- @return LuaGuiElement function Elements.container.get_root_element(container) - return container.parent + return assert(container.parent) end --- A frame within a container @@ -183,7 +183,7 @@ Elements.subframe_base = Gui.define("container_subframe") padding = { 3, 6, 0, 6 }, use_header_filler = false, horizontally_stretchable = true, - } --[[ @as any ]] + } --[[@as any]] --- @class Gui.elements.header.opts --- @field name string? @@ -212,7 +212,7 @@ Elements.header = Gui.define("container_header") subframe.add{ type = "empty-widget" }.style.horizontally_stretchable = true return subframe - end) --[[ @as any ]] + end) --[[@as any]] --- @class Gui.elements.footer.opts --- @field name string? @@ -241,7 +241,7 @@ Elements.footer = Gui.define("container_footer") subframe.add{ type = "empty-widget" }.style.horizontally_stretchable = true return subframe - end) --[[ @as any ]] + end) --[[@as any]] --- A button used to destroy its target when clicked, intended for screen frames --- @class Gui.elements.screen_frame_close: ExpElement @@ -259,7 +259,7 @@ Elements.screen_frame_close = Gui.define("screen_frame_close") :on_click(function(def, player, element, event) --- @cast def Gui.elements.screen_frame_close Gui.destroy_if_valid(def.data[element]) - end) --[[ @as any ]] + end) --[[@as any]] --- A draggable frame with close button and button flow --- @class Gui.elements.screen_frame: ExpElement @@ -313,20 +313,20 @@ Elements.screen_frame = Gui.define("screen_frame") direction = "vertical", style = "inside_shallow_frame_packed", } - end) --[[ @as any ]] + end) --[[@as any]] --- Get the button flow for a screen frame --- @param screen_frame LuaGuiElement --- @return LuaGuiElement function Elements.screen_frame.get_button_flow(screen_frame) - return assert(Elements.screen_frame.data[screen_frame.parent], "Screen frame has no button flow") + return (assert(Elements.screen_frame.data[assert(screen_frame.parent)], "Screen frame has no button flow")) end --- Get the root element of a screen frame --- @param screen_frame LuaGuiElement --- @return LuaGuiElement function Elements.screen_frame.get_root_element(screen_frame) - return screen_frame.parent + return assert(screen_frame.parent) end return Elements diff --git a/exp_gui/module/iter.lua b/exp_gui/module/iter.lua index 9d8db2ea..ad1d609c 100644 --- a/exp_gui/module/iter.lua +++ b/exp_gui/module/iter.lua @@ -166,7 +166,6 @@ end function GuiIter.get_tracked_elements(scope, filter) local class_name = ExpUtil.get_class_name(filter) if class_name == "nil" then - --- @cast filter nil return GuiIter.all_elements(scope) elseif class_name == "LuaPlayer" then --- @cast filter LuaPlayer @@ -189,7 +188,6 @@ end function GuiIter.get_online_elements(scope, filter) local class_name = ExpUtil.get_class_name(filter) if class_name == "nil" then - --- @cast filter nil return GuiIter.filtered_elements(scope, game.connected_players) elseif class_name == "LuaPlayer" then --- @cast filter LuaPlayer @@ -235,7 +233,7 @@ end function GuiIter.remove_element(scope, player_index, element_index) local scope_elements = registered_scopes[scope] if not scope_elements then return end - local player_elements = registered_scopes[player_index] + local player_elements = scope_elements[player_index] if not player_elements then return end player_elements[element_index] = nil end diff --git a/exp_gui/module/prototype.lua b/exp_gui/module/prototype.lua index ea1e6a31..07890a2d 100644 --- a/exp_gui/module/prototype.lua +++ b/exp_gui/module/prototype.lua @@ -43,6 +43,8 @@ ExpElement.events = {} --- @field _force_data ExpElement.PostDrawCallback? --- @field _global_data ExpElement.PostDrawCallback? --- @field _events table[]> +--- @field _has_handlers boolean +--- @field _track_elements boolean --- @overload fun(parent: LuaGuiElement, ...: any): LuaGuiElement ExpElement._prototype = { _track_elements = false, @@ -158,7 +160,7 @@ function ExpElement.new(name) }, } - ExpElement._elements[element_name] = instance --[[ @as ExpElement ]] + ExpElement._elements[element_name] = instance --[[@as ExpElement]] return setmetatable(instance, ExpElement._metatable) end @@ -166,7 +168,7 @@ end --- @param name string --- @return ExpElement function ExpElement.get(name) - return assert(ExpElement._elements[name], "ExpElement is not defined: " .. tostring(name)) + return (assert(ExpElement._elements[name], "ExpElement is not defined: " .. tostring(name))) end --- Create a new instance of this element definition @@ -460,7 +462,7 @@ function ExpElement._prototype:raise_event(event) for _, handler in ipairs(handlers) do -- All gui elements will contain player and element, other events might have these as nil -- Therefore only the signature of on_event has these values as optional - handler(self, player --[[ @as LuaPlayer ]], event.element, event --[[ @as EventData ]]) + handler(self, player --[[@as LuaPlayer]], event.element, event --[[@as EventData]]) end end diff --git a/exp_gui/module/styles.lua b/exp_gui/module/styles.lua index ca04a907..b459d1c9 100644 --- a/exp_gui/module/styles.lua +++ b/exp_gui/module/styles.lua @@ -1,4 +1,4 @@ ---- @class Gui +--- @class (partial) Gui local Gui = require("modules/exp_gui") --- @class Gui.styles diff --git a/exp_gui/module/toolbar.lua b/exp_gui/module/toolbar.lua index 401d9bd6..e4a3ebe2 100644 --- a/exp_gui/module/toolbar.lua +++ b/exp_gui/module/toolbar.lua @@ -1,5 +1,5 @@ ---- @class Gui +--- @class (partial) Gui local Gui = require("modules/exp_gui") local ExpElement = require("modules/exp_gui/prototype") local mod_gui = require("mod-gui") @@ -29,7 +29,7 @@ Toolbar.on_gui_button_toggled = script.generate_event_name() --- @class _ExpElement._prototype --- @field on_button_toggled ExpElement.OnEventAdder ---- @diagnostic disable-next-line: invisible, inject-field +--- @diagnostic disable-next-line: access-invisible, inject-field function ExpElement._prototype.on_button_toggled(self, handler) return self:on_event(Toolbar.on_gui_button_toggled, handler) end @@ -85,7 +85,7 @@ function Toolbar.set_button_toggled_state(define, player, state, _from_left) button.style = state and toolbar_button_active_style or toolbar_button_default_style -- Make the extra required adjustments - local style = button.style + local style = button.style --[[@as LuaStyle]] style.minimal_width = original_width style.maximal_height = original_height if button.type == "sprite-button" then @@ -335,9 +335,10 @@ Below here is the toolbar settings GUI and its associated functions --- @param dst LuaGuiElement local function copy_style(src, dst) dst.style = src.style.name - dst.style.height = toolbar_button_small - dst.style.width = toolbar_button_small - dst.style.padding = -2 + local style = dst.style --[[@as LuaStyle]] + style.height = toolbar_button_small + style.width = toolbar_button_small + style.padding = -2 end --- Reorder the buttons relative to each other, this will update the datastore @@ -350,7 +351,7 @@ local function move_toolbar_button(player, item, offset) -- Swap the position in the list local list = assert(item.parent) - local other_item = list.children[new_index] + local other_item = assert(list.children[new_index]) list.swap_children(old_index, new_index) -- Swap the position in the top flow, offset by 1 because of settings button @@ -365,7 +366,7 @@ local function move_toolbar_button(player, item, offset) local other_element = Gui.get_left_element(other_left_element, player) local left_index = element.get_index_in_parent() local other_index = other_element.get_index_in_parent() - element.parent.swap_children(left_index, other_index) + assert(element.parent).swap_children(left_index, other_index) end -- If we are moving in/out of first/last place we need to update the move buttons @@ -393,7 +394,7 @@ end --- @param player LuaPlayer --- @param order Gui.ToolbarOrder function Toolbar.set_order(player, order) - local list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]] + local list = elements.toolbar_settings.data[player] --[[@as LuaGuiElement]] local left_flow = Gui.get_left_flow(player) local top_flow = Gui.get_top_flow(player) @@ -466,7 +467,7 @@ end function Toolbar.get_state(player) -- Get the order of toolbar buttons local order = {} - local list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]] + local list = elements.toolbar_settings.data[player] --[[@as LuaGuiElement]] for index, item in pairs(list.children) do order[index] = { name = item.name, favourite = elements.toolbar_list_item.data[item].set_favourite.state } end @@ -487,7 +488,7 @@ end --- @param player LuaPlayer function Toolbar._create_elements(player) -- Add any missing items to the gui - local toolbar_list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]] + local toolbar_list = elements.toolbar_settings.data[player] --[[@as LuaGuiElement]] local previous_last_index = #toolbar_list.children_names for define in pairs(Gui.top_elements) do if define ~= elements.close_toolbar and toolbar_list[define.name] == nil then @@ -499,7 +500,8 @@ function Toolbar._create_elements(player) -- Reset the state of the previous last child local children = toolbar_list.children if previous_last_index > 0 then - elements.toolbar_list_item.data[children[previous_last_index]].move_item_down.enabled = true + local previous_last = assert(children[previous_last_index]) + elements.toolbar_list_item.data[previous_last].move_item_down.enabled = true end -- Set the state of the move buttons for the first and last element @@ -513,7 +515,7 @@ end --- @param player LuaPlayer function Toolbar._ensure_consistency(player) -- Update the toolbar buttons - local list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]] + local list = elements.toolbar_settings.data[player] --[[@as LuaGuiElement]] for _, button in ipairs(toolbar_buttons) do -- Update the visible state based on if the player is allowed the button local element = Gui.get_top_element(button, player) @@ -619,7 +621,7 @@ elements.move_item_up = Gui.define("move_item_up") size = toolbar_button_small, }) :on_click(function(def, player, element) - local item = assert(element.parent.parent) + local item = assert(assert(element.parent).parent) move_toolbar_button(player, item, -1) end) @@ -634,7 +636,7 @@ elements.move_item_down = Gui.define("move_item_down") size = toolbar_button_small, }) :on_click(function(def, player, element) - local item = assert(element.parent.parent) + local item = assert(assert(element.parent).parent) move_toolbar_button(player, item, 1) end) @@ -658,7 +660,7 @@ elements.set_favourite = Gui.define("set_favourite") width = 180, } :on_checked_state_changed(function(def, player, element) - local define = ExpElement.get(element.tags.element_name --[[ @as string ]]) + local define = ExpElement.get(element.tags.element_name --[[@as string]]) local top_element = Gui.get_top_element(define, player) local had_visible = Toolbar.has_visible_buttons(player) top_element.visible = element.state diff --git a/exp_legacy/module/config/chat_reply.lua b/exp_legacy/module/config/chat_reply.lua index 1321f96d..5eabb22d 100644 --- a/exp_legacy/module/config/chat_reply.lua +++ b/exp_legacy/module/config/chat_reply.lua @@ -24,6 +24,7 @@ local afk_time_units = { } return { + --- @type table messages = { --- @setting messages will trigger when ever the word is said ["discord"] = { "info.discord" }, ["expgaming"] = { "info.website" }, @@ -66,6 +67,7 @@ return { command_admin_only = false, --- @setting command_admin_only when true will only allow chat commands for admins command_permission = "command/chat-commands", --- @setting command_permission the permission used to allow command prefixes command_prefix = "!", --- @setting command_prefix prefix used for commands below and to print to all players (if enabled above) + --- @type table commands = { --- @setting commands will trigger only when command prefix is given ["dev"] = { "exp_chat-auto-reply.reply-dev" }, ["magic"] = { "exp_chat-auto-reply.reply-magic" }, diff --git a/exp_legacy/module/config/gui/player_list_actions.lua b/exp_legacy/module/config/gui/player_list_actions.lua index f692b47f..c6bb968c 100644 --- a/exp_legacy/module/config/gui/player_list_actions.lua +++ b/exp_legacy/module/config/gui/player_list_actions.lua @@ -15,7 +15,8 @@ local Colors = require("modules/exp_util/include/color") local format_player_name = ExpUtil.format_player_name_locale --- Accessors injected by the gui so the actions can read the selected player and set the selected action -local get_selected_player, set_selected_action +local get_selected_player --- @type fun(player: LuaPlayer): LuaPlayer +local set_selected_action --- @type fun(player: LuaPlayer, action: string?) local function set_accessors(player_getter, action_setter) get_selected_player, set_selected_action = player_getter, action_setter end @@ -31,7 +32,7 @@ end -- gets the action player and a coloured name for the action to be used on local function get_action_player(player) - local selected_player = get_selected_player(player) --[[ @as LuaPlayer ]] + local selected_player = get_selected_player(player) --[[@as LuaPlayer]] local selected_player_color = format_player_name(selected_player) return selected_player, selected_player_color end diff --git a/exp_legacy/module/config/spawn_area.lua b/exp_legacy/module/config/spawn_area.lua index 70ffd243..6c228d1e 100644 --- a/exp_legacy/module/config/spawn_area.lua +++ b/exp_legacy/module/config/spawn_area.lua @@ -87,7 +87,7 @@ return { amount = 4000, size = { 26, 27 }, -- offset = {-64,-32} - offset = { -64, -64 }, + offset = { x = -64, y = -64 }, }, { enabled = false, @@ -95,7 +95,7 @@ return { amount = 4000, size = { 26, 27 }, -- offset = {-64, 0} - offset = { 64, -64 }, + offset = { x = 64, y = -64 }, }, { enabled = false, @@ -103,7 +103,7 @@ return { amount = 4000, size = { 22, 20 }, -- offset = {-64, 32} - offset = { -64, 64 }, + offset = { x = -64, y = 64 }, }, { enabled = false, @@ -111,7 +111,7 @@ return { amount = 4000, size = { 22, 20 }, -- offset = {-64, -64} - offset = { 64, 64 }, + offset = { x = 64, y = 64 }, }, { enabled = false, @@ -119,7 +119,7 @@ return { amount = 4000, size = { 22, 20 }, -- offset = {-64, -96} - offset = { 0, 64 }, + offset = { x = 0, y = 64 }, }, }, }, @@ -132,7 +132,7 @@ return { num_patches = 4, amount = 4000000, -- offset = {-80, -12}, - offset = { -12, 64 }, + offset = { x = -12, y = 64 }, -- offset_next = {0, 6} offset_next = { 6, 0 }, }, diff --git a/exp_legacy/module/config/vlayer.lua b/exp_legacy/module/config/vlayer.lua index d80ed827..c2e0761a 100644 --- a/exp_legacy/module/config/vlayer.lua +++ b/exp_legacy/module/config/vlayer.lua @@ -35,6 +35,20 @@ return { storage_output = 1, -- >0 allows for item teleportation (allowed_items only) }, + --- @class Vlayer.ItemProperties + --- @field starting_value number + --- @field required_area number + --- @field production number? + --- @field discharge number? + --- @field capacity number? + --- @field surface_area number? + --- @field fuel_value number? + --- @field power boolean? + --- @field modded boolean? Set when the item is registered from a modded equivalent + --- @field base_game_equivalent string? + --- @field multiplier number? + + --- @type table allowed_items = { --- @setting allowed_items List of all items allowed in vlayer storage and their properties --[[ Allowed properties: diff --git a/exp_legacy/module/config/warnings.lua b/exp_legacy/module/config/warnings.lua index e098dc2f..b60e003b 100644 --- a/exp_legacy/module/config/warnings.lua +++ b/exp_legacy/module/config/warnings.lua @@ -2,6 +2,7 @@ -- @config Warnings return { + --- @type (LocalisedString[] | fun(player: LuaPlayer, by_player_name: string, number_of_warnings: number))[] actions = { --- @setting actions what actions are taking at number of warnings -- if a localized string is used then __1__ will by_player_name and __2__ will be the current warning count (auto inserted) { "warnings.received", "" }, diff --git a/exp_legacy/module/expcore/datastore.lua b/exp_legacy/module/expcore/datastore.lua index 9d498787..08fe4de1 100644 --- a/exp_legacy/module/expcore/datastore.lua +++ b/exp_legacy/module/expcore/datastore.lua @@ -149,9 +149,23 @@ PlayerData.Statistics:combine('JoinCount') local Storage = require("modules/exp_util/storage") local DatastoreManager = {} -local Datastores = {} -local Datastore = {} +local Datastores = {} --- @type table local Data = {} + +--- @class Datastore +--- @field name string +--- @field value_name string +--- @field auto_save boolean +--- @field save_to_disk boolean +--- @field propagate_changes boolean +--- @field serializer function | false +--- @field parent Datastore | false +--- @field children table +--- @field metadata table +--- @field events table +--- @field data table +local Datastore = {} + local copy = table.deep_copy local trace = debug.traceback local table_to_json = helpers.table_to_json diff --git a/exp_legacy/module/expcore/external.lua b/exp_legacy/module/expcore/external.lua index f4065c53..be8fb078 100644 --- a/exp_legacy/module/expcore/external.lua +++ b/exp_legacy/module/expcore/external.lua @@ -14,7 +14,8 @@ end ]] -local ext, var +local ext --- @type table +local var --- @type table local concat = table.concat local External = {} @@ -29,12 +30,13 @@ end ]] function External.valid() - if storage.ext == nil then return false end - if ext == storage.ext and var == ext.var then + local stored = storage.ext + if stored == nil then return false end + if ext == stored and var == ext.var then return var ~= nil else - ext = storage.ext - var = ext.var + ext = stored + var = stored.var return var ~= nil end end @@ -48,7 +50,7 @@ local servers = External.get_servers() ]] function External.get_servers() assert(ext, "No external data was found, use External.valid() to ensure external data exists.") - return assert(ext.servers, "No server list was found, please ensure that the external service is running") + return (assert(ext.servers, "No server list was found, please ensure that the external service is running")) end --[[-- Gets a table of all the servers filtered by name, key is the server id, value is the server details @@ -83,7 +85,7 @@ function External.get_current_server() assert(ext, "No external data was found, use External.valid() to ensure external data exists.") local servers = assert(ext.servers, "No server list was found, please ensure that the external service is running") local server_id = assert(ext.current, "No current id was found, please ensure that the external service is running") - return assert(servers[server_id], "No details found for server with id: " .. tostring(server_id)) + return (assert(servers[server_id], "No details found for server with id: " .. tostring(server_id))) end --[[-- Gets the details of the given server @@ -97,7 +99,7 @@ local server = External.get_server_details('eu-01') function External.get_server_details(server_id) assert(ext, "No external data was found, use External.valid() to ensure external data exists.") local servers = assert(ext.servers, "No server list was found, please ensure that the external service is running") - return assert(servers[server_id], "No details found for server with id: " .. tostring(server_id)) + return (assert(servers[server_id], "No details found for server with id: " .. tostring(server_id))) end --[[-- Gets the status of the given server diff --git a/exp_legacy/module/expcore/permission_groups.lua b/exp_legacy/module/expcore/permission_groups.lua index b4477df5..35be0d9e 100644 --- a/exp_legacy/module/expcore/permission_groups.lua +++ b/exp_legacy/module/expcore/permission_groups.lua @@ -142,7 +142,7 @@ group:set_action('toggle_map_editor', false) ]] function PermissionsGroups._prototype:set_action(action, state) - local input_action = defines.input_action[action] --[[ @as defines.input_action? ]] + local input_action = defines.input_action[action] --[[@as defines.input_action?]] if input_action == nil then input_action = action end assert(type(input_action) == "number", tostring(action) .. " is not a valid input action") self.actions[input_action] = state diff --git a/exp_legacy/module/expcore/player_data.lua b/exp_legacy/module/expcore/player_data.lua index b6862873..07318191 100644 --- a/exp_legacy/module/expcore/player_data.lua +++ b/exp_legacy/module/expcore/player_data.lua @@ -55,7 +55,7 @@ PlayerData:set_serializer(Datastore.name_serializer) -- use player name --- Store and enum for the data saving preference local DataSavingPreference = PlayerData:combine("DataSavingPreference") -local PreferenceEnum = { "All", "Statistics", "Settings", "Required" } +local PreferenceEnum = { "All", "Statistics", "Settings", "Required" } --- @type table for k, v in ipairs(PreferenceEnum) do PreferenceEnum[v] = k end DataSavingPreference:set_default("All") diff --git a/exp_legacy/module/expcore/roles.lua b/exp_legacy/module/expcore/roles.lua index b84875f2..641eeaea 100644 --- a/exp_legacy/module/expcore/roles.lua +++ b/exp_legacy/module/expcore/roles.lua @@ -117,11 +117,28 @@ local Groups = require("modules.exp_legacy.expcore.permission_groups") local Colours = ExpUtil.color local write_json = ExpUtil.write_json + +--- @class Roles.Role +--- @field name string +--- @field short_hand string +--- @field index number Position within the role order +--- @field allowed_actions table +--- @field allow_all_actions boolean +--- @field flags table +--- @field disallowed_actions table? +--- @field permission_group ([boolean, string] | string)? +--- @field custom_tag string? +--- @field custom_color Color? +--- @field parent string? +--- @field block_auto_assign boolean? +--- @field auto_assign_condition function? +--- @field set_allow_all fun(self: Roles.Role, state: boolean?): Roles.Role Defined on Roles._prototype + local Roles = { _prototype = {}, config = { - order = {}, -- Contains the order of the roles, lower index is better - roles = {}, -- Contains the raw info for the roles, indexed by role name + order = {}, --- @type string[] Contains the order of the roles, lower index is better + roles = {}, --- @type table Contains the raw info for the roles, indexed by role name flags = {}, -- Contains functions that run when a flag is added/removed from a player internal = {}, -- Contains all internally accessed roles, such as root, default players = {}, -- Contains the roles that players have @@ -200,7 +217,7 @@ function Roles.debug() local output = "" for index, role_name in ipairs(Roles.config.order) do local role = Roles.config.roles[role_name] - local color = role.custom_color or Colours.white + local color = (role.custom_color or Colours.white) --[[@as Color.struct]] local color_str = string.format("[color=%d, %d, %d]", color.r, color.g, color.b) output = output .. string.format("\n%s %s) %s[/color]", color_str, index, serpent.line(role)) end @@ -287,6 +304,7 @@ local role = Roles.get_role_by_name(2) ]] function Roles.get_role_by_order(index) local name = Roles.config.order[index] + if not name then return end return Roles.config.roles[name] end @@ -348,16 +366,17 @@ end local role = Roles.get_player_highest_role(game.player) ]] +--- @return Roles.Role function Roles.get_player_highest_role(player) local roles = Roles.get_player_roles(player) - local highest + local highest --- @type Roles.Role? for _, role in ipairs(roles) do if not highest or role.index < highest.index then highest = role end end - return highest + return (assert(highest, "Player has no roles")) end --- Assignment. @@ -458,7 +477,7 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen -- If the player has a role that needs to defer the role changes, save the roles that need to be unassigned later into a table local defer_changes = Roles.player_has_flag(player, "defer_role_changes") - if defer_changes then + if defer_changes and valid_player then local assign_later = Roles.config.deferred_roles[valid_player.name] or {} for _, role in ipairs(role_objects) do local role_change = assign_later[role.name] @@ -719,7 +738,7 @@ local role = Roles.new_role('Moderator', 'Mod') ]] function Roles.new_role(name, short_hand) ExpUtil.assert_not_runtime() - if Roles.config.roles[name] then return error("Role name is non unique") end + if Roles.config.roles[name] then error("Role name is non unique") end local role = setmetatable({ name = name, short_hand = short_hand or name, @@ -894,10 +913,9 @@ role:set_permission_group('Admin') function Roles._prototype:set_permission_group(name, use_factorio_api) ExpUtil.assert_not_runtime() if use_factorio_api then - self.permission_group = { true, name } + self.permission_group = { true, name } --[[@as [boolean, string] ]] else - local group = Groups.get_group_by_name(name) - if not group then return end + assert(Groups.get_group_by_name(name), "Permission group not found: " .. name) self.permission_group = name end return self @@ -1115,8 +1133,9 @@ local function role_update(event) -- Updates the players permission group local highest = Roles.get_player_highest_role(player) if highest.permission_group then - if highest.permission_group[1] then - local group = game.permissions.get_group(highest.permission_group[2]) + local permission_group = highest.permission_group --[[@as [boolean, string] ]] + if permission_group[1] then + local group = game.permissions.get_group(permission_group[2]) if group then Groups.add_to_permission_group_async(group, player) end diff --git a/exp_legacy/module/modules/control/protection.lua b/exp_legacy/module/modules/control/protection.lua index 79415756..506d889d 100644 --- a/exp_legacy/module/modules/control/protection.lua +++ b/exp_legacy/module/modules/control/protection.lua @@ -34,7 +34,7 @@ for _, config_key in ipairs{ "always_protected_names", "always_protected_types", end -- Require roles if a permission is assigned in the config -local Roles +local Roles --- @type table if config.ignore_permission then Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles end diff --git a/exp_legacy/module/modules/control/spectate.lua b/exp_legacy/module/modules/control/spectate.lua index 1c1d1c70..dc2784f8 100644 --- a/exp_legacy/module/modules/control/spectate.lua +++ b/exp_legacy/module/modules/control/spectate.lua @@ -4,7 +4,7 @@ local Gui = require("modules/exp_gui") local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event ----- Locals ----- -local follow_label -- Gui constructor +local follow_label --- @type ExpElement Gui constructor local following = {} local spectating = {} local Public = {} diff --git a/exp_legacy/module/modules/control/vlayer.lua b/exp_legacy/module/modules/control/vlayer.lua index 39346063..72afba6c 100644 --- a/exp_legacy/module/modules/control/vlayer.lua +++ b/exp_legacy/module/modules/control/vlayer.lua @@ -14,10 +14,10 @@ local mega = 1000000 local vlayer = {} local vlayer_data = { entity_interfaces = { - energy = {}, - circuit = {}, - storage_input = {}, - storage_output = {}, + energy = {}, --- @type LuaEntity[] + circuit = {}, --- @type LuaEntity[] + storage_input = {}, --- @type LuaEntity[] + storage_output = {}, --- @type LuaEntity[] }, properties = { total_surface_area = 0, @@ -28,10 +28,10 @@ local vlayer_data = { capacity = 0, }, storage = { - items = {}, - power_items = {}, + items = {}, --- @type table + power_items = {}, --- @type table energy = 0, - unallocated = {}, + unallocated = {}, --- @type table }, surface = table.deep_copy(config.surface), } @@ -45,7 +45,7 @@ for name, properties in pairs(config.allowed_items) do if properties.power then vlayer_data.storage.power_items[name] = { - value = properties.fuel_value * 1000000, + value = assert(properties.fuel_value) * 1000000, count = 0, } end @@ -361,7 +361,7 @@ local function handle_input_interfaces() if not interface.valid then vlayer_data.entity_interfaces.storage_input[index] = nil else - local inventory = interface.get_inventory(defines.inventory.chest) + local inventory = assert(interface.get_inventory(defines.inventory.chest)) for _, v in pairs(inventory.get_contents()) do if config.allowed_items[v.name] then @@ -384,8 +384,9 @@ local function handle_input_interfaces() if count_deduct and count_add then if config.allowed_items[v.name].modded then + local modded_item = assert(config.modded_items[v.name]) if config.modded_auto_downgrade then - vlayer.insert_item(config.modded_items[v.name].base_game_equivalent, count_add * config.modded_items[v.name].multiplier) + vlayer.insert_item(modded_item.base_game_equivalent, count_add * modded_item.multiplier) else vlayer.insert_item(v.name, count_add) end @@ -439,14 +440,14 @@ local function handle_output_interfaces() if not interface.valid then vlayer_data.entity_interfaces.storage_output[index] = nil else - local inventory = interface.get_inventory(defines.inventory.chest) - local inventory_request_sections = interface.get_logistic_sections().sections + local inventory = assert(interface.get_inventory(defines.inventory.chest)) + local inventory_request_sections = assert(interface.get_logistic_sections()).sections for i = 1, #inventory_request_sections do for _, v in pairs(inventory_request_sections[i].filters) do if v.value and config.allowed_items[v.value.name] then local current_amount = inventory.get_item_count(v.value.name) - local request_amount = math.min(v.min - current_amount, vlayer_data.storage.items[v.value.name]) + local request_amount = math.min(assert(v.min) - current_amount, vlayer_data.storage.items[v.value.name]) if request_amount > 0 and inventory.can_insert{ name = v.value.name, count = request_amount } then local removed_item_count = vlayer.remove_item(v.value.name, request_amount) @@ -582,11 +583,11 @@ local function handle_circuit_interfaces() if not interface.valid then vlayer_data.entity_interfaces.circuit[index] = nil else - local circuit_oc = interface.get_or_create_control_behavior() - if circuit_oc.sections_count == 0 then - circuit_oc.add_section() + local control = interface.get_or_create_control_behavior() --[[@as LuaConstantCombinatorControlBehavior]] + if control.sections_count == 0 then + control.add_section() end - circuit_oc = circuit_oc.sections[1] + local circuit_oc = assert(control.sections[1]) local signal_index = 1 local circuit = vlayer.get_circuits() @@ -617,7 +618,7 @@ local function handle_circuit_interfaces() -- Clear remaining signals to prevent outdated values being present (caused by count > 0 check) for clear_index = signal_index, #circuit do - if not circuit_oc.get_slot(clear_index).signal then + if not circuit_oc.get_slot(clear_index).value then break -- There are no more signals to clear end diff --git a/exp_legacy/module/modules/control/warnings.lua b/exp_legacy/module/modules/control/warnings.lua index 628fc8d0..6a0fa116 100644 --- a/exp_legacy/module/modules/control/warnings.lua +++ b/exp_legacy/module/modules/control/warnings.lua @@ -107,7 +107,7 @@ function Warnings.add_warning(player, by_player_name, reason) reason = reason or "None given." - local warning_count + local warning_count --- @type number PlayerWarnings:update(player.name, function(_, warnings) local warning = { by_player_name = by_player_name, diff --git a/exp_legacy/module/modules/data/toolbar.lua b/exp_legacy/module/modules/data/toolbar.lua index a714ae0b..177aba50 100644 --- a/exp_legacy/module/modules/data/toolbar.lua +++ b/exp_legacy/module/modules/data/toolbar.lua @@ -18,7 +18,7 @@ ToolbarState:on_load(function(player_name, value) local decompressed = helpers.json_to_table(assert(helpers.decode_string(value), "Failed String Decode")) local player = assert(game.get_player(player_name)) - Gui.toolbar.set_state(player, decompressed --[[ @as Gui.ToolbarState ]]) + Gui.toolbar.set_state(player, decompressed --[[@as Gui.ToolbarState]]) return nil -- We don't save the state, use Gui.toolbar.get_state end) diff --git a/exp_legacy/module/modules/graftorio/forcestats.lua b/exp_legacy/module/modules/graftorio/forcestats.lua index a515869a..195f2e4c 100644 --- a/exp_legacy/module/modules/graftorio/forcestats.lua +++ b/exp_legacy/module/modules/graftorio/forcestats.lua @@ -126,19 +126,19 @@ lib.collect_loginet = function() end if config.modules.logistorage then - for name, v in pairs(network.get_contents()) do - stats.items[name] = (stats.items[name] or 0) + v + for _, item in pairs(network.get_contents()) do + stats.items[item.name] = (stats.items[item.name] or 0) + item.count end -- pickups and deliveries of items for _, point_list in pairs{ network.provider_points, network.requester_points, network.storage_points } do for _, point in pairs(point_list) do - for name, qty in pairs(point.targeted_items_pickup) do - stats.pickups[name] = (stats.pickups[name] or 0) + qty + for _, item in pairs(point.targeted_items_pickup) do + stats.pickups[item.name] = (stats.pickups[item.name] or 0) + item.count end - for name, qty in pairs(point.targeted_items_deliver) do - stats.deliveries[name] = (stats.deliveries[name] or 0) + qty + for _, item in pairs(point.targeted_items_deliver) do + stats.deliveries[item.name] = (stats.deliveries[item.name] or 0) + item.count end end end diff --git a/exp_legacy/module/modules/gui/_role_updates.lua b/exp_legacy/module/modules/gui/_role_updates.lua index 75273b57..ac171b49 100644 --- a/exp_legacy/module/modules/gui/_role_updates.lua +++ b/exp_legacy/module/modules/gui/_role_updates.lua @@ -2,6 +2,6 @@ local Gui = require("modules/exp_gui") local Roles = require("modules.exp_legacy.expcore.roles") local Event = require("modules/exp_legacy/utils/event") ---- @diagnostic disable invisible +--- @diagnostic disable: access-invisible Event.add(Roles.events.on_role_assigned, Gui._ensure_consistency) Event.add(Roles.events.on_role_unassigned, Gui._ensure_consistency) diff --git a/exp_legacy/module/modules/gui/vlayer.lua b/exp_legacy/module/modules/gui/vlayer.lua index a57f090a..727f9b9d 100644 --- a/exp_legacy/module/modules/gui/vlayer.lua +++ b/exp_legacy/module/modules/gui/vlayer.lua @@ -22,9 +22,9 @@ local function aabb_align_expand(aabb) } end -local vlayer_container -local vlayer_gui_control_type -local vlayer_gui_control_list +local vlayer_container --- @type ExpElement +local vlayer_gui_control_type --- @type ExpElement +local vlayer_gui_control_list --- @type ExpElement local vlayer_control_type_list = { [1] = "energy", @@ -87,10 +87,10 @@ SelectArea:on_selection(function(event) local container = Gui.get_left_element(vlayer_container, player) local disp = container.frame["vlayer_st_2"].disp.table local target = vlayer_control_type_list[disp[vlayer_gui_control_type.name].selected_index] - local entities + local entities --- @type LuaEntity[] if config.power_on_space and event.surface and event.surface.platform and target == "energy" then - if player.force.technologies[config.power_on_space_research.name].level >= config.power_on_space_research.level then + if (player.force --[[@as LuaForce]]).technologies[config.power_on_space_research.name].level >= config.power_on_space_research.level then entities = event.surface.find_entities_filtered{ area = area, name = "constant-combinator", force = player.force } else player.print{ "vlayer.power-on-space-research", config.power_on_space_research.name, config.power_on_space_research.level } @@ -116,7 +116,7 @@ SelectArea:on_selection(function(event) local e_pos = { x = string.format("%.1f", e.position.x), y = string.format("%.1f", e.position.y) } local e_circ = nil -- e.get_wire_connectors{ or_create = false } - if e.name and e.name == "steel-chest" and (not e.get_inventory(defines.inventory.chest).is_empty()) then + if e.name and e.name == "steel-chest" and (not assert(e.get_inventory(defines.inventory.chest)).is_empty()) then player.print{ "vlayer.steel-chest-empty" } return end @@ -325,7 +325,9 @@ local function vlayer_gui_list_refresh(player) local interface = vlayer.get_interfaces()[vlayer_control_type_list[target]] for i = 1, vlayer.get_interface_counts()[vlayer_control_type_list[target]], 1 do - table.insert(full_list, i .. " X " .. interface[i].position.x .. " Y " .. interface[i].position.y) + local entity = assert(interface[i]) + local entity_position = entity.position + table.insert(full_list, i .. " X " .. entity_position.x .. " Y " .. entity_position.y) end disp[vlayer_gui_control_list.name].items = full_list @@ -379,14 +381,13 @@ local vlayer_gui_control_see = Gui.define("vlayer_gui_control_see") }:style{ width = 200, }:on_click(function(def, player, element, event) - local target = element.parent[vlayer_gui_control_type.name].selected_index - local n = element.parent[vlayer_gui_control_list.name].selected_index + local target = assert(element.parent)[vlayer_gui_control_type.name].selected_index + local n = assert(element.parent)[vlayer_gui_control_list.name].selected_index if target and vlayer_control_type_list[target] and n > 0 then local i = vlayer.get_interfaces() local entity = i[vlayer_control_type_list[target]][n] if entity and entity.valid then - local player = Gui.get_player(event) player.set_controller{ type = defines.controllers.remote, position = entity.position, surface = entity.surface } player.print{ "vlayer.result-interface-location", { "vlayer.control-type-" .. vlayer_control_type_list[target]:gsub("_", "-") }, pos_to_gps_string(entity.position, entity.surface.name) } end @@ -423,14 +424,15 @@ local vlayer_gui_control_remove = Gui.define("vlayer_gui_control_remove") }:style{ width = 200, }:on_click(function(def, player, element) - local target = element.parent[vlayer_gui_control_type.name].selected_index - local n = element.parent[vlayer_gui_control_list.name].selected_index + local target = assert(element.parent)[vlayer_gui_control_type.name].selected_index + local n = assert(element.parent)[vlayer_gui_control_list.name].selected_index if target and vlayer_control_type_list[target] and n > 0 then local i = vlayer.get_interfaces() if i and i[vlayer_control_type_list[target]] then - local interface_type, interface_surface, interface_position = vlayer.remove_interface(i[vlayer_control_type_list[target]][n].surface, i[vlayer_control_type_list[target]][n].position) + local entity = assert(i[vlayer_control_type_list[target]][n]) + local interface_type, interface_surface, interface_position = vlayer.remove_interface(entity.surface, entity.position) if interface_type then game.print{ "vlayer.interface-result", player.name, pos_to_gps_string(interface_position, interface_surface.name), { "vlayer.result-remove" }, { "vlayer.control-type-" .. interface_type } } diff --git a/exp_legacy/module/modules/gui/warp-list.lua b/exp_legacy/module/modules/gui/warp-list.lua index 39759287..15359dbc 100644 --- a/exp_legacy/module/modules/gui/warp-list.lua +++ b/exp_legacy/module/modules/gui/warp-list.lua @@ -180,7 +180,7 @@ local warp_icon_button = Gui.define("warp_icon_button") :style(Styles.sprite32) :on_click(function(def, player, element) if element.type == "choose-elem-button" then return end - local warp_id = element.parent.caption + local warp_id = assert(element.parent).caption Warps.teleport_player(warp_id, player) -- Reset the warp cooldown if the player does not have unlimited warps @@ -226,7 +226,7 @@ local warp_label = Gui.define("warp_label") horizontally_stretchable = true, } :on_click(function(def, player, element) - local warp_id = element.parent.caption + local warp_id = assert(element.parent).caption local warp = Warps.get_warp(warp_id) player.set_controller{ type = defines.controllers.remote, position = warp.position, surface = warp.surface } end) @@ -271,9 +271,9 @@ local warp_textfield = Gui.define("warp_textfield") right_margin = 2, } :on_confirmed(function(def, player, element) - local warp_id = element.parent.caption + local warp_id = assert(element.parent).caption local warp_name = element.text - local warp_icon = element.parent.parent["icon-" .. warp_id][warp_icon_editing.name].elem_value --[[ @as SignalID ]] + local warp_icon = assert(element.parent).parent["icon-" .. warp_id][warp_icon_editing.name].elem_value --[[@as SignalID]] if warp_icon.type == nil then warp_icon.type = "item" end Warps.set_editing(warp_id, player.name) Warps.update_warp(warp_id, warp_name, warp_icon, player.name) @@ -291,9 +291,13 @@ local confirm_edit_button = Gui.define("confirm_edit_button") } :style(Styles.sprite22) :on_click(function(def, player, element) - local warp_id = element.parent.caption - local warp_name = element.parent.parent["name-" .. warp_id][warp_textfield.name].text - local warp_icon = element.parent.parent["icon-" .. warp_id][warp_icon_editing.name].elem_value --[[ @as SignalID ]] + local parent = assert(element.parent) + local grandparent = assert(parent.parent) + local warp_id = parent.caption --[[@as string]] + local name_flow = grandparent["name-" .. warp_id] + local icon_flow = grandparent["icon-" .. warp_id] + local warp_name = name_flow[warp_textfield.name].text + local warp_icon = icon_flow[warp_icon_editing.name].elem_value --[[@as SignalID]] if warp_icon.type == nil then warp_icon.type = "item" end Warps.set_editing(warp_id, player.name) Warps.update_warp(warp_id, warp_name, warp_icon, player.name) @@ -311,7 +315,7 @@ local cancel_edit_button = Gui.define("cancel_edit_button") } :style(Styles.sprite22) :on_click(function(def, player, element) - local warp_id = element.parent.caption + local warp_id = assert(element.parent).caption -- Check if this is the first edit, if so remove the warp. local warp = Warps.get_warp(warp_id) if warp.updates == 1 then @@ -333,7 +337,7 @@ local remove_warp_button = Gui.define("remove_warp_button") } :style(Styles.sprite22) :on_click(function(def, player, element) - local warp_id = element.parent.caption + local warp_id = assert(element.parent).caption Warps.remove_warp(warp_id) end) @@ -349,7 +353,7 @@ local edit_warp_button = Gui.define("edit_warp_button") } :style(Styles.sprite22) :on_click(function(def, player, element) - local warp_id = element.parent.caption + local warp_id = assert(element.parent).caption Warps.set_editing(warp_id, player.name, true) end) @@ -429,8 +433,8 @@ local function update_warp_elements(element, warp, warp_player_is_on, on_cooldow -- Check if button element is valid if not element or not element.valid then return end - local label_style = element.parent.parent["name-" .. warp.warp_id][warp_label.name].style - local warp_status_element = element.parent.parent["name-" .. warp.warp_id][warp_status.name] + local label_style = assert(element.parent).parent["name-" .. warp.warp_id][warp_label.name].style + local warp_status_element = assert(element.parent).parent["name-" .. warp.warp_id][warp_status.name] -- If player is not on a warp if not warp_player_is_on then @@ -669,7 +673,7 @@ warp_list_container = Gui.define("warp_list_container") -- Draw the scroll table for the warps local scroll_table = Gui.elements.scroll_table(container, 250, 3, "scroll") -- Set the scroll panel to always show the scrollbar (not doing this will result in a changing gui size) - scroll_table.parent.vertical_scroll_policy = "always" + assert(scroll_table.parent).vertical_scroll_policy = "always" -- Change the style of the scroll table local scroll_table_style = scroll_table.style @@ -778,7 +782,7 @@ Event.on_nth_tick(math.floor(60 / config.update_smoothing), function() end -- Check if the force has any warps - local closest_warp = nil + local closest_warp = nil --- @type { warp_id: string, name: string }? local closest_distance = nil if #warp_ids > 0 then local surface = player.surface @@ -838,7 +842,7 @@ end) Event.add(defines.events.on_player_created, function(event) -- If the force has no spawn then make a spawn warp local player = game.players[event.player_index] - local force = player.force + local force = player.force --[[@as LuaForce]] local spawn_id = Warps.get_spawn_warp_id(force.name) if not spawn_id then local spawn_position = force.get_spawn_position(player.surface) @@ -870,7 +874,7 @@ local function role_update_event(event) -- Check if user has permission to add warps local allow_add_warp = check_player_permissions(player, "allow_add_warp") -- Update container size depending on whether the player is allowed to add warps - frame.parent.style.width = allow_add_warp and 268 or 220 + assert(frame.parent).style.width = allow_add_warp and 268 or 220 -- Update the warps, in case the user can now edit them local scroll_table = frame.scroll.table diff --git a/exp_roles/module/control.lua b/exp_roles/module/control.lua index 59b5696e..f0622a0b 100644 --- a/exp_roles/module/control.lua +++ b/exp_roles/module/control.lua @@ -12,7 +12,7 @@ made with `assign_player_local`. ]] local clusterio_api = require("modules/clusterio/api") -local compat = require("modules/clusterio/compat") +local compat = require("modules/clusterio/compat") --[[@as LibCompat]] local Async = require("modules/exp_util/async") --- @class ExpRoles @@ -284,7 +284,7 @@ local server_role = setmetatable({ --- @param player LuaPlayer | string | nil --- @return ExpRoles.Role[] function ExpRoles.get_player_roles(player) - local player_name = type(player) == "table" and player.name or player --[[ @as string? ]] + local player_name = type(player) == "table" and player.name or player --[[@as string?]] -- The server is not a player and is allowed to do anything if player_name == nil then return { server_role } end @@ -399,7 +399,7 @@ end --- @param self ExpRoles.Role --- @param action string --- @return boolean -function Role:is_allowed(action) +function Role.is_allowed(self, action) local allowed = self.allowed_actions return allowed["core.admin"] or allowed[permission_from_action(action)] or false end @@ -408,7 +408,7 @@ end --- @param self ExpRoles.Role --- @param name string --- @return boolean -function Role:has_flag(name) +function Role.has_flag(self, name) return self.allowed_actions[permission_from_flag(name)] or false end @@ -416,7 +416,7 @@ end --- @param self ExpRoles.Role --- @param online boolean? When given, filter by connected state --- @return LuaPlayer[] -function Role:get_players(online) +function Role.get_players(self, online) local players = {} for player_name, role_names in pairs(ExpRoles.config.players) do for _, role_name in pairs(role_names) do @@ -437,7 +437,7 @@ end --- @param self ExpRoles.Role --- @param message LocalisedString --- @return number # Number of players the message was sent to -function Role:print(message) +function Role.print(self, message) local players = self:get_players(true) for _, player in pairs(players) do player.print(message) @@ -678,7 +678,7 @@ end --- @param silent boolean? --- @param sync boolean local function change_player_roles(player, roles, change_type, by_player_name, silent, sync) - local player_name = type(player) == "table" and player.name or player --[[ @as string? ]] + local player_name = type(player) == "table" and player.name or player --[[@as string?]] if not player_name then return end local role_objects = resolve_roles(roles) diff --git a/exp_roles/module/events.lua b/exp_roles/module/events.lua index 6537b5c1..12d8456d 100644 --- a/exp_roles/module/events.lua +++ b/exp_roles/module/events.lua @@ -9,7 +9,10 @@ had, and event_handler expects `events` to be the handlers to register. local clusterio_api = require("modules/clusterio/api") local ExpRoles = require("modules/exp_roles/control") -return { +--- @class ExpRoles.EventHandlers +--- @field on_load fun() +--- @field events table +local handlers = { on_load = ExpRoles.on_load, events = { [clusterio_api.events.on_server_startup] = ExpRoles.on_server_startup, @@ -17,3 +20,5 @@ return { [defines.events.on_player_joined_game] = ExpRoles.on_player_joined_game, }, } + +return handlers diff --git a/exp_roles/module/globals.lua b/exp_roles/module/globals.lua index 10d74063..2a982c2e 100644 --- a/exp_roles/module/globals.lua +++ b/exp_roles/module/globals.lua @@ -4,7 +4,7 @@ However, sometimes you need globals, for example to access functions within rcon Therefore, we advise that this should be the only file in your module to expose globals ]] ---- @diagnostic disable: global-element +--- @diagnostic disable: global-in-non-module -- Access using `/sc exp_roles.foo()` exp_roles = require("modules/exp_roles/control") diff --git a/exp_scenario/.luacheckrc b/exp_scenario/.luacheckrc deleted file mode 100644 index 9b043265..00000000 --- a/exp_scenario/.luacheckrc +++ /dev/null @@ -1,1697 +0,0 @@ ---[[---------------------------------------------------------------------------- - LICENSE - .luacheckrc for Factorio Version 0.18.8, luacheck version 0.23.0 - This file is free and unencumbered software released into the public domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this file, either in source code form or as a compiled - binary, for any purpose, commercial or non-commercial, and by any - means. - - In jurisdictions that recognize copyright laws, the author or authors - of this file dedicate any and all copyright interest in the - software to the public domain. We make this dedication for the benefit - of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to this - software under copyright law. - - THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - For more information, please refer to -------------------------------------------------------------------------------]] -local LINE_LENGTH = false - -local IGNORE = {'21./%w+_$', '21./^_%w+$', '213/[ijk]', '213/index', '213/key'} - --- These globals are not available to the factorio API -local NOT_GLOBALS = {'coroutine', 'io', 'socket', 'dofile', 'loadfile'} - -local STD_CONTROL = 'lua52+factorio+factorio_control+stdlib+factorio_defines' -local STD_DATA = 'lua52+factorio+factorio_data+stdlib+stdlib_data+factorio_defines' - --- For Base and Core Mods -local STD_BASE_DATA = 'lua52+factorio+factorio_data+factorio_defines+factorio_base_data' -local STD_BASE_CONTROL = 'lua52+factorio+factorio_control+factorio_defines+factorio_base_control' - -do -- Assume Factorio Control Stage as Default - std = STD_CONTROL - --cache = true - not_globals = NOT_GLOBALS - ignore = IGNORE - quiet = 1 -- pass -q option - max_cyclomatic_complexity = false - codes = true - max_line_length = LINE_LENGTH - max_code_line_length = LINE_LENGTH - max_string_line_length = LINE_LENGTH - max_comment_line_length = LINE_LENGTH - - --List of files and directories to exclude - exclude_files = { - --Ignore special folders - '**/.trash/', - '**/.history/', - '**/stdlib/vendor/', - - --Ignore development mods - '**/combat-tester/', - '**/test-maker/', - '**/trailer/', - - --Ignore love Includes - '**/love/includes/' - } -end - -do -- Set default prototype files - files['**/data.lua'].std = STD_DATA - files['**/data-updates.lua'].std = STD_DATA - files['**/data-final-fixes.lua'].std = STD_DATA - files['**/settings.lua'].std = STD_DATA - files['**/settings-updates.lua'].std = STD_DATA - files['**/settings-final-fixes.lua'].std = STD_DATA - files['**/prototypes/'].std = STD_DATA - files['**/settings/'].std = STD_DATA -end - -do -- Base and Core mod files - local base_scenarios = { - std = STD_BASE_CONTROL .. '+factorio_base_scenarios+factorio_base_story', - --ignore = {'212/event', '111', '112', '113', '211', '212', '213', '311', '411', '412', '421', '422', '423', '431', '432', '512'} - ignore = {'...'} - } - files['**/base/scenarios/'] = base_scenarios - files['**/base/tutorials/'] = base_scenarios - files['**/base/campaigns/'] = base_scenarios - files['**/wip-scenario/'] = base_scenarios - - files['**/base/migrations/'] = {std = STD_BASE_CONTROL} - - files['**/core/lualib/'] = {std = STD_BASE_CONTROL} - files['**/core/lualib/util.lua'] = {globals = {'util', 'table'}, ignore = {'432/object'}} - files['**/core/lualib/silo-script.lua'] = {globals = {'silo_script'}, ignore = {'4../player'}} - files['**/core/lualib/production-score.lua'] = {globals = {'production_score', 'get_price_recursive'}, ignore = {'4../player'}} - files['**/core/lualib/story*'] = {std = '+factorio_base_story', ignore = {'42./k', '42./filter'}} - files['**/core/lualib/mod-gui.lua'] = {globals = {'mod_gui'}} - files['**/core/lualib/camera.lua'] = {globals = {'camera'}} - files['**/core/lualib/builder.lua'] = {globals = {'Builder', 'builder', 'action', 'down', 'right'}} - - files['**/core/lualib/bonus-gui-ordering/'] = {std = STD_BASE_DATA} - files['**/core/lualib/dataloader.lua'] = {globals = {'data'}} - files['**/core/lualib/circuit-connector-*'] = {std = STD_BASE_DATA..'+factorio_circuit_connector_generated'} - files['**/core/lualib/bonus-gui-ordering.lua'] = {globals = {'bonus_gui_ordering'}} - - files['**/base/prototypes/'] = {std = STD_BASE_DATA} - files['**/core/prototypes/'] = {std = STD_BASE_DATA} - files['**/core/prototypes/noise-programs.lua'] = {ignore = {'212/x', '212/y', '212/tile', '212/map'}} -end - -do -- Stdlib Files - local stdlib_control = { - std = 'lua52+factorio+factorio_control+stdlib+factorio_defines', - max_line_length = LINE_LENGTH - } - - local stdlib_data = { - std = 'lua52+factorio+factorio_data+stdlib+factorio_defines', - max_line_length = LINE_LENGTH - } - - -- Assume control stage for stdlib - files['**/stdlib/'] = stdlib_control - - -- Assume generic lua for stdlib utils - files['**/stdlib/utils/**'].std = 'lua52+stdlib' - - -- STDLIB data stage files - files['**/stdlib/data/'] = stdlib_data - - -- STDLIB Busted Spec - files['**/spec/**'] = { - globals = {'serpent', 'log', 'package.remove_stdlib'}, - std = 'lua52c+busted+factorio_defines+factorio_control+stdlib' - } - - -- Love - files['**/love/'].std = 'luajit+love+love_extra+stdlib+stdlib_data' -end - -do -- Factorio STDs-- - stds.factorio = { - --Set the read only variables - read_globals = { - -- @log@: Gives writing access to Factorio's logger instance. - "log", - -- @serpent@: Lua serializer and pretty printer. (https://github.com/pkulchenko/serpent). - "serpent", - -- @table_size@: Returns the number of elements inside an LUA table. - "table_size", - -- @lldebugger@: Provided by lua local debugger vscode extension. - lldebugger = { - fields = {'requestBreak'}, - other_fields = true, - read_only = false, - }, - -- @__DebugAdapter@: Provided by Factorio Mod Debug vscode extension. - __DebugAdapter = { - fields = {'print', 'stepIgnoreAll', 'stepIgnore', 'breakpoint'}, - other_fields = true, - read_only = false - }, - util = { - fields = { - "by_pixel", "distance", "findfirstentity", "positiontostr", "formattime", "moveposition", "oppositedirection", - "ismoduleavailable", "multiplystripes", "format_number", "increment", "color", "conditional_return", - "add_shift", "merge", "premul_color", "encode", "decode", "insert_safe", - table = { - fields = { - "compare", "deepcopy" - }, - }, - }, - }, - table = { - fields = { - "compare", "deepcopy" - }, - }, - }, - } - - stds.factorio_control = { - read_globals = { - - -- @commands@: - commands = { - fields = { - "add_command", "commands", "game_commands", "remove_command" - }, - }, - - -- @settings@: - settings = { - fields = { - "get_player_settings", - startup = {other_fields = true}, - global = {other_fields = true}, - player = {other_fields = true}, - get = {read_only = false}, -- stdlib added - get_startup = {read_only = false} -- stdlib added - }, - }, - - -- @script@: Provides an interface for registering event handlers. - -- (http://lua-api.factorio.com/latest/LuaBootstrap.html) - script = { - fields = { - "on_event", "on_nth_tick", "on_configuration_changed", "on_init", "on_load", "generate_event_name", - "raise_event", "get_event_handler", "mod_name", "get_event_order", - "is_game_in_debug_mode", "object_name", "set_event_filter", "get_event_filter", "register_metatable", - active_mods = {read_only = true, other_fields = true}, - }, - other_fields = false, - }, - - -- @remote@: Allows inter-mod communication by providing a repository of interfaces that is shared by all mods. - -- (http://lua-api.factorio.com/latest/LuaRemote.html) - remote = { - fields = { - interfaces = {read_only = false, other_fields = true}, - "add_interface", "remove_interface", "call" - }, - read_only = true, - other_fields = false, - }, - - rcon = { - fields = {'print'} - }, - - rendering = { - other_fields = false, - read_only = true, - fields = { - 'draw_animation', - 'draw_line', - 'draw_text', - 'draw_circle', - 'draw_rectangle', - 'draw_arc', - 'draw_polygon', - 'draw_sprite', - 'draw_light', - 'destroy', - 'is_font_valid', - 'is_valid', - 'get_all_ids', - 'clear', - 'get_type', - 'get_surface', - 'get_time_to_live', - 'set_time_to_live', - 'get_forces', - 'set_forces', - 'get_players', - 'set_players', - 'get_color', - 'set_color', - 'get_width', - 'set_width', - 'get_from', - 'set_from', - 'get_to', - 'set_to', - 'get_gap_amount', - 'set_gap_amount', - 'get_gap_length', - 'set_gap_length', - 'get_target', - 'set_target', - 'get_orientation', - 'set_orientation', - 'get_scale', - 'set_scale', - 'get_text', - 'set_text', - 'get_font', - 'set_font', - 'get_alignment', - 'set_alignment', - 'get_scale_with_zoom', - 'set_scale_with_zoom', - 'get_filled', - 'set_filled', - 'get_radius', - 'set_radius', - 'get_left_top', - 'set_left_top', - 'get_right_bottom', - 'set_right_bottom', - 'get_max_radius', - 'set_max_radius', - 'get_min_radius', - 'set_min_radius', - 'get_start_angle', - 'set_start_angle', - 'get_angle', - 'set_angle', - 'get_vertices', - 'set_vertices', - 'get_sprite', - 'set_sprite', - 'get_x_scale', - 'set_x_scale', - 'get_y_scale', - 'set_y_scale', - 'get_render_layer', - 'set_render_layer', - 'get_orientation_target', - 'set_orientation_target', - 'get_oriented_offset', - 'set_oriented_offset', - 'get_intensity', - 'set_intensity', - 'get_minimum_darkness', - 'set_minimum_darkness' - } - }, - - -- @game@: Main object through which most of the API is accessed. - -- It is, however, not available inside handlers registered with @script.on_load@. - -- (http://lua-api.factorio.com/latest/LuaGameScript.html) - game ={ - other_fields = false, - read_only = false, - fields = { - 'auto_save', - 'ban_player', - 'check_consistency', - 'check_prototype_translations', - 'count_pipe_groups', - 'create_force', - 'create_profiler', - 'create_random_generator', - 'create_surface', - 'decode_string', - 'delete_surface', - 'direction_to_string', - 'disable_replay', - 'disable_tips_and_tricks', - 'disable_tutorial_triggers', - 'encode_string', - 'evaluate_expression', - 'force_crc', - 'get_active_entities_count', - 'get_entity_by_tag', - 'get_filtered_achievement_prototypes', - 'get_filtered_decorative_prototypes', - 'get_filtered_entity_prototypes', - 'get_filtered_equipment_prototypes', - 'get_filtered_fluid_prototypes', - 'get_filtered_item_prototypes', - 'get_filtered_mod_setting_prototypes', - 'get_filtered_recipe_prototypes', - 'get_filtered_technology_prototypes', - 'get_filtered_tile_prototypes', - 'get_map_exchange_string', - 'get_player', - 'get_surface', - 'get_train_stops', - 'help', - 'is_demo', - 'is_multiplayer', - 'is_valid_sound_path', - 'is_valid_sprite_path', - 'json_to_table', - 'kick_player', - 'log_recipe_locale', - 'merge_forces', - 'mute_player', - 'parse_map_exchange_string', - 'play_sound', - 'print', - 'print_stack_size', - 'purge_player', - 'regenerate_entity', - 'reload_mods', - 'reload_script', - 'remove_offline_players', - 'remove_path', - 'reset_time_played', - 'save_atlas', - 'server_save', - 'set_game_state', - 'set_wait_for_screenshots_to_finish', - 'show_message_dialog', - 'table_to_json', - 'take_screenshot', - 'take_technology_screenshot', - 'unban_player', - 'unmute_player', - 'write_file', - - achievement_prototypes = {read_only = true, other_fields = true}, - active_mods = {read_only = true, other_fields = true}, - ammo_category_prototypes = {read_only = true, other_fields = true}, - autoplace_control_prototypes = {read_only = true, other_fields = true}, - backer_names = {read_only = true, other_fields = true}, - connected_players = {read_only = true, other_fields = true}, - custom_input_prototypes = {read_only = true, other_fields = true}, - damage_prototypes = {read_only = true, other_fields = true}, - decorative_prototypes = {read_only = true, other_fields = true}, - default_map_gen_settings = {read_only = true, other_fields = true}, - difficulty = {read_only = true, other_fields = true}, - difficulty_settings = {read_only = true, other_fields = true}, - entity_prototypes = {read_only = true, other_fields = true}, - equipment_category_prototypes = {read_only = true, other_fields = true}, - equipment_grid_prototypes = {read_only = true, other_fields = true}, - equipment_prototypes = {read_only = true, other_fields = true}, - finished = {read_only = true, other_fields = true}, - fluid_prototypes = {read_only = true, other_fields = true}, - forces = {read_only = true, other_fields = true}, - fuel_category_prototypes = {read_only = true, other_fields = true}, - item_group_prototypes = {read_only = true, other_fields = true}, - item_prototypes = {read_only = true, other_fields = true}, - item_subgroup_prototypes = {read_only = true, other_fields = true}, - map_settings = {read_only = true, other_fields = true}, - mod_setting_prototypes = {read_only = true, other_fields = true}, - module_category_prototypes = {read_only = true, other_fields = true}, - named_noise_expressions = {read_only = true, other_fields = true}, - noise_layer_prototypes = {read_only = true, other_fields = true}, - object_name = {read_only = true, other_fields = true}, - particle_prototypes = {read_only = true, other_fields = true}, - permissions = {read_only = true, other_fields = true}, - player = {read_only = true, other_fields = true}, - players = {read_only = true, other_fields = true}, - pollution_statistics = {read_only = true, other_fields = true}, - recipe_category_prototypes = {read_only = true, other_fields = true}, - recipe_prototypes = {read_only = true, other_fields = true}, - resource_category_prototypes = {read_only = true, other_fields = true}, - shortcut_prototypes = {read_only = true, other_fields = true}, - styles = {read_only = true, other_fields = true}, - surfaces = {read_only = true, other_fields = true}, - technology_prototypes = {read_only = true, other_fields = true}, - tick = {read_only = true, other_fields = true}, - ticks_played = {read_only = true, other_fields = true}, - tile_prototypes = {read_only = true, other_fields = true}, - trivial_smoke_prototypes = {read_only = true, other_fields = true}, - virtual_signal_prototypes = {read_only = true, other_fields = true}, - - autosave_enabled = {read_only = false, other_fields = false}, - draw_resource_selection = {read_only = false, other_fields = false}, - enemy_has_vision_on_land_mines = {read_only = false, other_fields = false}, - speed = {read_only = false, other_fields = false}, - tick_paused = {read_only = false, other_fields = false}, - ticks_to_run = {read_only = false, other_fields = false} - }, - }, - }, - - globals = { - -- @global@: The global dictionary, useful for storing data persistent across a save-load cycle. - -- Writing access is given to the mod-id field (for mod-wise saved data). - -- (http://lua-api.factorio.com/latest/Global.html) - "global", - - -- @MOD@: Keep it organized, use this variable for anything that "NEEDS" to be global for some reason. - "MOD" - }, - } - - stds.factorio_data = { - - read_globals = { - data = { - fields = { - raw = { - other_fields = true, - read_only = false - }, - "extend", "is_demo" - }, - }, - - settings = { - fields = { - "startup", "global", "player", "get", "get_startup" - }, - }, - - mods = { - other_fields = true - }, - - -- Popular mods that think they need globals! - angelsmods = { - other_fields = true - }, - - -- Popular mods that think they need globals! - bobmods = { - other_fields = true - }, - - - } - } -end - -do -- Factorio Base/Core STDs-- - stds.factorio_base_control = { - read_globals = {"silo_script", "mod_gui", "camera"} - } - - stds.factorio_base_scenarios = { - globals = { - "check_automate_science_packs_advice", "check_research_hints", "check_supplies", "manage_attacks", "all_dead", - "on_win", "difficulty_number", "init_attack_data", "handle_attacks", "count_items_in_container", "progress", "scanned", - "check_light", "check_machine_gun", "level", "story_table", - - "tightspot_prices", "tightspot_make_offer", "tightspot_init", "tightspot_get_required_balance", - "tightspot_init_level", "tightspot_init_spending_frame", "tightspot_init_progress_frame", "tightspot_update_progress", "tightspot_update_spending", - "tightspot_get_missing_to_win", "tightspot_sell_back", "tightspot_start_level", "tightspot_show_level_description", "tightspot_update_speed_label", - "map_ignore", "tightspot_check_level", "land_price", - - "transport_belt_madness_init", "transport_belt_madness_init_level", "transport_belt_madness_create_chests", "transport_belt_madness_fill_chests", - "transport_belt_madness_start_level", "map_ignore", "map_clear", "map_load", "map_save", "transport_belt_madness_show_level_description", - "transport_belt_madness_check_level", "transport_belt_madness_next_level", "transport_belt_madness_clear_level", "transport_belt_madness_contains_next_level", - - "restricted", "check_built_items", "result", "disable_combat_technologies", "apply_character_modifiers", "apply_combat_modifiers", "apply_balance", - "load_config", "starting_area_constant", "create_next_surface", "end_round", "prepare_next_round", "silo_died","choose_joining_gui", - "destroy_joining_guis", "create_random_join_gui", "create_auto_assign_gui", "create_pick_join_gui", "create_config_gui", "make_config_table", "default", - "make_team_gui", "make_team_gui_config", "add_team_button_press", "trash_team_button_press", "remove_team_from_team_table", "add_team_to_team_table", - "set_teams_from_gui", "on_team_button_press", "make_color_dropdown", "create_balance_option", "create_disable_frame", "disable_frame", "parse_disabled_items", - "set_balance_settings", "config_confirm", "parse_config_from_gui", "get_color", "roll_starting_area", "delete_roll_surfaces", "auto_assign", - "destroy_config_for_all", "prepare_map", "set_evolution_factor", "update_players_on_team_count", "random_join", "init_player_gui", - "destroy_player_gui", "objective_button_press", "admin_button_press", "admin_frame_button_press", "diplomacy_button_press", "update_diplomacy_frame", - "diplomacy_frame_button_press", "team_changed_diplomacy", "diplomacy_check_press", "get_stance", "give_inventory", "setup_teams", "disable_items_for_all", - "set_random_team", "set_diplomacy", "create_spawn_positions", "set_spawn_position", "set_team_together_spawns", "chart_starting_area_for_force_spawns", - "check_starting_area_chunks_are_generated", "check_player_color", "check_round_start", "clear_starting_area_enemies", "check_no_rush_end", "check_no_rush_players", - "finish_setup", "chart_area_for_force", "setup_start_area_copy", "update_copy_progress", "update_progress_bar", "copy_paste_starting_area_tiles", - "copy_paste_starting_area_entities", "create_silo_for_force", "setup_research", "on_chunk_generated", "get_distance_to_nearest_spawn", - "create_wall_for_force", "fpn", "give_items", "create_item_frame", "create_technologies_frame", "create_cheat_frame", "create_day_frame", - "time_modifier", "points_per_second_start", "points_per_second_level_subtract", "levels", "update_info", "get_time_left", "update_time_left", - "on_joined", "make_frame", "update_frame", "update_table", "calculate_task_item_multiplayer", "setup_config", "select_from_probability_table", - "select_inventory", "select_equipment", "select_challange_type", "save_round_statistics", "start_challenge", "create_teams", "set_areas", - "decide_player_team", "set_teams", "refresh_leaderboard", "set_player", "generate_technology_list", "generate_research_task","setup_unlocks", - "check_technology_progress", "generate_production_task", "generate_shopping_list_task", "set_gui_flow_table", "create_visibility_button", - "check_item_lists", "update_task_gui", "check_end_of_round", "end_round_gui_update", "try_to_check_victory", "update_gui", "check_start_round", - "check_start_set_areas", "check_start_setting_entities", "check_set_areas", "check_clear_areas", "check_chests", "check_chests_shopping_list", - "check_chests_production", "check_input_chests", "fill_input_chests", "check_victory", "shopping_task_finished", "calculate_force_points", - "update_research_task_table", "update_production_task_table", "update_shopping_list_task_table", "create_joined_game_gui", "pre_ending_round", - "player_ending_prompt", "update_end_timer", "update_begin_timer", "team_finished", "save_points_list", "give_force_players_points", - "update_winners_list", "set_spectator", "set_character", "give_starting_inventory", "give_equipment", "shuffle_table", "format_time", - "spairs", "fill_leaderboard", "create_grid", "simple_entities", "save_map_data", "clear_map", "create_tiles", "recreate_entities", - "map_sets", "give_points", "init_forces", "init_globals", "init_unit_settings", "check_next_wave", "next_wave", "calculate_wave_power", - "wave_end", "make_next_spawn_tick", "check_spawn_units", "get_wave_units", "spawn_units", "randomize_ore", "set_command", "command_straglers", - "unit_config", "make_next_wave_tick", "time_to_next_wave", "time_to_wave_end", "rocket_died", "unit_died", "get_bounty_price", "setup_waypoints", - "insert_items", "give_starting_equipment", "give_spawn_equipment", "next_round_button_visible", "gui_init", "create_wave_frame", "create_money_frame", - "create_upgrade_gui", "update_upgrade_listing", "upgrade_research", "get_upgrades", "get_money", "update_connected_players", "update_round_number", - "set_research", "set_recipes", "check_deconstruction", "check_blueprint_placement", "loop_entities", "experiment_items", - "setup", "story_gui_click", "clear_surface", "add_run_trains_button", "puzzle_condition", "basic_signals", - "loop_trains", "Y_offset", "ghosts_1", "ghosts_2", "required_path", "through_wall_path", "count", "check_built_real_rail", - "current_ghosts_count", "other", "rails", "set_rails", "straight_section", "late_entities", "entities", "stop", - "get_spawn_coordinate", - - --tutorials - "intermission", "create_entities_on_tick", "on_player_created", "required_count", "non_player_entities", "clear_rails", - "chest", "damage", "furnace", "init_prototypes", "build_infi_table", "junk", "update_player_tags", "time_left", "team_production", - "create_task_frame", "create_visibilty_buttons", "update_leaderboard", "in_in_area" - } - } - - stds.factorio_base_data = { - globals = { - --Style - "make_cursor_box", "make_full_cursor_box", - "default_container_padding", "default_orange_color", "default_light_orange_color", "warning_red_color", - "achievement_green_color", "achievement_tan_color", "orangebuttongraphcialset", "bluebuttongraphcialset", - "bonus_gui_ordering", "trivial_smoke", "technology_slot_base_width", "technology_slot_base_height", "default_frame_font_vertical_compensation", - - --Belts - "transport_belt_connector_frame_sprites", "transport_belt_circuit_wire_connection_point", "transport_belt_circuit_wire_max_distance", - "transport_belt_circuit_connector_sprites", "ending_patch_prototype", "basic_belt_horizontal", "basic_belt_vertical", - "basic_belt_ending_top", "basic_belt_ending_bottom", "basic_belt_ending_side", "basic_belt_starting_top", "basic_belt_starting_bottom", - "basic_belt_starting_side", "fast_belt_horizontal", "fast_belt_vertical", "fast_belt_ending_top", "fast_belt_ending_bottom", - "fast_belt_ending_side", "fast_belt_starting_top", "fast_belt_starting_bottom", "fast_belt_starting_side", "express_belt_horizontal", - "express_belt_vertical", "express_belt_ending_top", "express_belt_ending_bottom", "express_belt_ending_side", "express_belt_starting_top", - "express_belt_starting_bottom", "express_belt_starting_side", - - --Circuit Connectors - "circuit_connector_definitions", "default_circuit_wire_max_distance", "inserter_circuit_wire_max_distance", - "universal_connector_template", "belt_connector_template", "belt_frame_connector_template", "inserter_connector_template", - - --Inserter Circuit Connectors - "inserter_circuit_wire_max_distance", "inserter_default_stack_control_input_signal", - - --Sounds/beams - "make_heavy_gunshot_sounds", "make_light_gunshot_sounds", "make_laser_sounds", - - --Gun/Laser - "gun_turret_extension", "gun_turret_extension_shadow", "gun_turret_extension_mask", "gun_turret_attack", - "laser_turret_extension", "laser_turret_extension_shadow", "laser_turret_extension_mask", - - --Pipes - "pipecoverspictures", "pipepictures", "assembler2pipepictures", "assembler3pipepictures", "make_heat_pipe_pictures", - - --Combinators - "generate_arithmetic_combinator", "generate_decider_combinator", "generate_constant_combinator", - - --Rail - "destroyed_rail_pictures", "rail_pictures", "rail_pictures_internal", "standard_train_wheels", "drive_over_tie", - "rolling_stock_back_light", "rolling_stock_stand_by_light", - - --Enemies - "make_enemy_autoplace", "make_enemy_spawner_autoplace", "make_enemy_worm_autoplace", - "make_spitter_attack_animation", "make_spitter_run_animation", "make_spitter_dying_animation", - "make_spitter_attack_parameters", "make_spitter_roars", "make_spitter_dying_sounds", - "make_spawner_idle_animation", "make_spawner_die_animation", - "make_biter_run_animation", "make_biter_attack_animation", "make_biter_die_animation", - "make_biter_roars", "make_biter_dying_sounds", "make_biter_calls", - "make_worm_roars", "make_worm_dying_sounds", "make_worm_folded_animation", "make_worm_preparing_animation", - "make_worm_prepared_animation", "make_worm_attack_animation", "make_worm_die_animation", - - --Other - "tile_variations_template", "make_water_autoplace_settings", - "make_unit_melee_ammo_type", "make_trivial_smoke", "make_4way_animation_from_spritesheet", "flying_robot_sounds", - "productivitymodulelimitation", "crash_trigger", "capsule_smoke", "make_beam", "playeranimations", - "make_blood_tint", "make_shadow_tint", - - --tiles - "water_transition_template", "make_water_transition_template", "water_autoplace_settings", "water_tile_type_names", - "patch_for_inner_corner_of_transition_between_transition", - } - } - - stds.factorio_base_story = { - globals = { - "story_init_helpers", "story_update_table", "story_init", "story_update", "story_on_tick", "story_add_update", - "story_remove_update", "story_jump_to", "story_elapsed", "story_elapsed_check", "story_show_message_dialog", - "set_goal", "player_set_goal", "on_player_joined", "flash_goal", "set_info", "player_set_info", "export_entities", - "list", "recreate_entities", "entity_to_connect", "limit_camera", "find_gui_recursive", "enable_entity_export", - "add_button", "on_gui_click", "set_continue_button_style", "add_message_log", "story_add_message_log", - "player_add_message_log", "message_log_frame", "message_log_scrollpane", "message_log_close_button", - "message_log_table", "toggle_message_log_button", "toggle_objective_button", "message_log_init", - "add_gui_recursive", "add_toggle_message_log_button", "add_toggle_objective_button", "mod_gui", - "flash_message_log_button", "flash_message_log_on_tick", "story_gui_click", "story_points_by_name", "story_branches", - "player", "surface", "deconstruct_on_tick", "recreate_entities_on_tick", "flying_congrats", "story_table" - } - } - - stds.factorio_circuit_connector_generated = { - globals = { - 'default_circuit_wire_max_distance', 'circuit_connector_definitions', 'universal_connector_template', - 'belt_connector_template', 'belt_frame_connector_template', 'inserter_connector_template', 'inserter_connector_template', - 'inserter_circuit_wire_max_distance', 'inserter_default_stack_control_input_signal', 'transport_belt_connector_frame_sprites', - 'transport_belt_circuit_wire_max_distance', - } - } -end - -do -- STDLIB STDs-- - stds.stdlib = { - read_globals = {}, - globals = { - 'STDLIB', - 'prequire', - 'rawtostring', - 'traceback', - 'data_traceback', - 'inspect', - 'serpent', - 'inline_if', - 'install', - 'log', - 'concat', - 'GAME', - 'AREA', - 'POSITION', - 'TILE', - 'SURFACE', - 'CHUNK', - 'COLOR', - 'ENTITY', - 'INVENTORY', - 'RESOURCE', - 'CONFIG', - 'LOGGER', - 'QUEUE', - 'EVENT', - 'GUI', - 'PLAYER', - 'FORCE', - 'MATH', - 'STRING', - 'TABLE' - } - } - - stds.stdlib_control = {} - - stds.stdlib_data = { - globals = { - 'DATA', - 'RECIPE', - 'ITEM', - 'FLUID', - 'ENTITY', - 'TECHNOLOGY', - 'CATEGORY' - } - } -end - -do -- Love STDs - stds.love_extra = { - read_globals = { - love = { - fields = { - arg = { - fields = { - 'parseGameArguments', - 'parseOption', - 'getLow', - 'optionIndices', - 'options' - } - } - } - }, - 'coroutine', - 'io', - 'socket', - 'dofile', - 'loadfile' - }, - globals = { - love = { - fields = { - 'handlers' - } - } - } - } -end - -do -- Factorio Defines STDs-- - stds.factorio_defines = { - read_globals = { - defines = { - fields = { - alert_type = { - fields = { - 'entity_destroyed', - 'entity_under_attack', - 'not_enough_construction_robots', - 'no_material_for_construction', - 'not_enough_repair_packs', - 'turret_fire', - 'custom', - 'no_storage', - 'train_out_of_fuel', - 'fluid_mixing' - } - }, - behavior_result = { - fields = { - 'in_progress', - 'fail', - 'success', - 'deleted' - } - }, - build_check_type = { - fields = { - 'script', - 'manual', - 'ghost_place', - 'ghost_revive' - } - }, - chain_signal_state = { - fields = { - 'all_open', - 'partially_open', - 'none_open' - } - }, - chunk_generated_status = { - fields = { - 'nothing', - 'custom_tiles', - 'basic_tiles', - 'corrected_tiles', - 'tiles', - 'entities' - } - }, - circuit_condition_index = { - fields = { - 'inserter_circuit', - 'inserter_logistic', - 'lamp', - 'arithmetic_combinator', - 'decider_combinator', - 'constant_combinator', - 'offshore_pump', - 'pump' - } - }, - circuit_connector_id = { - fields = { - 'accumulator', - 'constant_combinator', - 'container', - 'programmable_speaker', - 'rail_signal', - 'rail_chain_signal', - 'roboport', - 'storage_tank', - 'wall', - 'electric_pole', - 'inserter', - 'lamp', - 'combinator_input', - 'combinator_output', - 'offshore_pump', - 'pump' - } - }, - command = { - fields = { - 'attack', - 'go_to_location', - 'compound', - 'group', - 'attack_area', - 'wander', - 'flee', - 'stop', - 'build_base' - } - }, - compound_command = { - fields = { - 'logical_and', - 'logical_or', - 'return_last' - } - }, - control_behavior = { - fields = { - inserter = { - fields = { - circuit_mode_of_operation = { - fields = { - 'enable_disable', - 'set_filters', - 'read_hand_contents', - 'set_stack_size' - } - }, - hand_read_mode = { - fields = { - 'hold', - 'pulse' - } - } - } - }, - lamp = { - fields = { - circuit_mode_of_operation = { - fields = { - 'use_colors' - } - } - } - }, - logistic_container = { - fields = { - circuit_mode_of_operation = { - fields = { - 'send_contents', - 'set_requests' - } - } - } - }, - mining_drill = { - fields = { - resource_read_mode = { - fields = { - 'this_miner', - 'entire_patch' - } - } - } - }, - roboport = { - fields = { - circuit_mode_of_operation = { - fields = { - 'read_logistics', - 'read_robot_stats' - } - } - } - }, - train_stop = { - fields = { - circuit_mode_of_operation = { - fields = { - 'enable_disable', - 'send_to_train', - 'read_from_train', - 'read_stopped_train' - } - } - } - }, - transport_belt = { - fields = { - content_read_mode = { - fields = { - 'pulse', - 'hold' - } - } - } - }, - type = { - fields = { - 'container', - 'generic_on_off', - 'inserter', - 'lamp', - 'logistic_container', - 'roboport', - 'storage_tank', - 'train_stop', - 'decider_combinator', - 'arithmetic_combinator', - 'constant_combinator', - 'transport_belt', - 'accumulator', - 'rail_signal', - 'rail_chain_signal', - 'wall', - 'mining_drill', - 'programmable_speaker' - } - } - } - }, - controllers = { - fields = { - 'ghost', - 'character', - 'god', - 'editor', - 'cutscene', - 'spectator' - } - }, - deconstruction_item = { - fields = { - entity_filter_mode = { - fields = { - 'whitelist', - 'blacklist' - } - }, - tile_filter_mode = { - fields = { - 'whitelist', - 'blacklist' - } - }, - tile_selection_mode = { - fields = { - 'normal', - 'always', - 'never', - 'only' - } - } - } - }, - difficulty = { - fields = { - 'easy', - 'normal', - 'hard' - } - }, - difficulty_settings = { - fields = { - recipe_difficulty = { - fields = { - 'normal', - 'expensive' - } - }, - technology_difficulty = { - fields = { - 'normal', - 'expensive' - } - } - } - }, - direction = { - fields = { - 'north', - 'northeast', - 'east', - 'southeast', - 'south', - 'southwest', - 'west', - 'northwest' - } - }, - distraction = { - fields = { - 'by_enemy', - 'by_anything', - 'by_damage' - } - }, - entity_status = { - fields = { - 'working', - 'no_power', - 'no_fuel', - 'no_recipe', - 'no_input_fluid', - 'no_research_in_progress', - 'no_minable_resources', - 'low_input_fluid', - 'low_power', - 'disabled_by_control_behavior', - 'disabled_by_script', - 'fluid_ingredient_shortage', - 'fluid_production_overload', - 'item_ingredient_shortage', - 'item_production_overload', - 'marked_for_deconstruction', - 'missing_required_fluid', - 'missing_science_packs', - 'waiting_for_source_items', - 'waiting_for_space_in_destination', - 'waiting_to_launch_rocket' - } - }, - events = { - fields = { - 'on_tick', - 'on_gui_click', - 'on_gui_confirmed', - 'on_gui_text_changed', - 'on_gui_checked_state_changed', - 'on_entity_died', - 'on_post_entity_died', - 'on_entity_damaged', - 'on_picked_up_item', - 'on_built_entity', - 'on_sector_scanned', - 'on_player_mined_item', - 'on_put_item', - 'on_rocket_launched', - 'on_pre_player_mined_item', - 'on_chunk_generated', - 'on_player_crafted_item', - 'on_robot_built_entity', - 'on_robot_pre_mined', - 'on_robot_mined', - 'on_research_started', - 'on_research_finished', - 'on_player_rotated_entity', - 'on_player_set_quickbar_slot', - 'on_marked_for_deconstruction', - 'on_cancelled_deconstruction', - 'on_trigger_created_entity', - 'on_trigger_fired_artillery', - 'on_train_changed_state', - 'on_player_created', - 'on_resource_depleted', - 'on_player_driving_changed_state', - 'on_force_created', - 'on_forces_merging', - 'on_player_cursor_stack_changed', - 'on_pre_entity_settings_pasted', - 'on_entity_settings_pasted', - 'on_player_main_inventory_changed', - 'on_player_armor_inventory_changed', - 'on_player_ammo_inventory_changed', - 'on_player_gun_inventory_changed', - 'on_player_placed_equipment', - 'on_player_removed_equipment', - 'on_pre_player_died', - 'on_player_died', - 'on_player_respawned', - 'on_player_joined_game', - 'on_player_left_game', - 'on_player_built_tile', - 'on_player_mined_tile', - 'on_robot_built_tile', - 'on_robot_mined_tile', - 'on_player_selected_area', - 'on_player_alt_selected_area', - 'on_player_changed_surface', - 'on_selected_entity_changed', - 'on_market_item_purchased', - 'on_player_dropped_item', - 'on_biter_base_built', - 'on_player_changed_force', - 'on_entity_renamed', - 'on_gui_selection_state_changed', - 'on_runtime_mod_setting_changed', - 'on_difficulty_settings_changed', - 'on_surface_created', - 'on_surface_deleted', - 'on_pre_surface_deleted', - 'on_player_mined_entity', - 'on_robot_mined_entity', - 'on_train_created', - 'on_gui_elem_changed', - 'on_player_setup_blueprint', - 'on_player_deconstructed_area', - 'on_player_configured_blueprint', - 'on_console_chat', - 'on_console_command', - 'on_player_removed', - 'on_pre_player_removed', - 'on_player_used_capsule', - 'script_raised_built', - 'script_raised_destroy', - 'script_raised_revive', - 'on_player_promoted', - 'on_player_demoted', - 'on_combat_robot_expired', - 'on_player_changed_position', - 'on_mod_item_opened', - 'on_gui_opened', - 'on_gui_closed', - 'on_gui_value_changed', - 'on_player_muted', - 'on_player_unmuted', - 'on_player_cheat_mode_enabled', - 'on_player_cheat_mode_disabled', - 'on_character_corpse_expired', - 'on_pre_ghost_deconstructed', - 'on_player_pipette', - 'on_player_display_resolution_changed', - 'on_player_display_scale_changed', - 'on_pre_player_crafted_item', - 'on_player_cancelled_crafting', - 'on_chunk_charted', - 'on_technology_effects_reset', - 'on_land_mine_armed', - 'on_forces_merged', - 'on_player_trash_inventory_changed', - 'on_pre_player_left_game', - 'on_pre_surface_cleared', - 'on_surface_cleared', - 'on_chunk_deleted', - 'on_pre_chunk_deleted', - 'on_train_schedule_changed', - 'on_player_banned', - 'on_player_kicked', - 'on_player_unbanned', - 'on_rocket_launch_ordered', - 'on_script_path_request_finished', - 'on_ai_command_completed', - 'on_marked_for_upgrade', - 'on_cancelled_upgrade', - 'on_player_toggled_map_editor', - 'on_entity_cloned', - 'on_area_cloned', - 'on_brush_cloned', - 'on_game_created_from_scenario', - 'on_surface_imported', - 'on_surface_renamed', - 'on_player_toggled_alt_mode', - 'on_player_repaired_entity', - 'on_player_fast_transferred', - 'on_pre_robot_exploded_cliff', - 'on_robot_exploded_cliff', - 'on_entity_spawned', - 'on_cutscene_waypoint_reached', - 'on_unit_group_created', - 'on_unit_added_to_group', - 'on_unit_removed_from_group', - 'on_unit_group_finished_gathering', - 'on_build_base_arrived', - 'on_chart_tag_added', - 'on_chart_tag_modified', - 'on_chart_tag_removed', - 'on_lua_shortcut', - 'on_gui_location_changed', - 'on_gui_selected_tab_changed', - 'on_gui_switch_state_changed', - 'on_force_cease_fire_changed', - 'on_force_friends_changed', - 'on_string_translated', - 'on_script_trigger_effect' - } - }, - flow_precision_index = { - fields = { - 'one_second', - 'one_minute', - 'ten_minutes', - 'one_hour', - 'ten_hours', - 'fifty_hours', - 'two_hundred_fifty_hours', - 'one_thousand_hours' - } - }, - group_state = { - fields = { - 'gathering', - 'moving', - 'attacking_distraction', - 'attacking_target', - 'finished', - 'pathfinding', - 'wander_in_group' - } - }, - gui_type = { - fields = { - 'entity', - 'research', - 'controller', - 'production', - 'item', - 'bonus', - 'trains', - 'achievement', - 'blueprint_library', - 'equipment', - 'logistic', - 'other_player', - 'kills', - 'permissions', - 'tutorials', - 'custom', - 'server_management', - 'player_management', - 'tile' - } - }, - input_action = { - fields = { - 'activate_copy', - 'activate_cut', - 'activate_paste', - 'add_permission_group', - 'add_train_station', - 'admin_action', - 'alt_select_area', - 'alt_select_blueprint_entities', - 'alternative_copy', - 'begin_mining', - 'begin_mining_terrain', - 'build_item', - 'build_rail', - 'build_terrain', - 'cancel_craft', - 'cancel_deconstruct', - 'cancel_new_blueprint', - 'cancel_research', - 'cancel_upgrade', - 'change_active_item_group_for_crafting', - 'change_active_item_group_for_filters', - 'change_active_quick_bar', - 'change_arithmetic_combinator_parameters', - 'change_blueprint_book_record_label', - 'change_decider_combinator_parameters', - 'change_item_label', - 'change_multiplayer_config', - 'change_picking_state', - 'change_programmable_speaker_alert_parameters', - 'change_programmable_speaker_circuit_parameters', - 'change_programmable_speaker_parameters', - 'change_riding_state', - 'change_shooting_state', - 'change_single_blueprint_record_label', - 'change_train_stop_station', - 'change_train_wait_condition', - 'change_train_wait_condition_data', - 'clean_cursor_stack', - 'clear_selected_blueprint', - 'clear_selected_deconstruction_item', - 'clear_selected_upgrade_item', - 'connect_rolling_stock', - 'copy', - 'copy_entity_settings', - 'craft', - 'create_blueprint_like', - 'cursor_split', - 'cursor_transfer', - 'custom_input', - 'cycle_blueprint_book_backwards', - 'cycle_blueprint_book_forwards', - 'deconstruct', - 'delete_blueprint_library', - 'delete_blueprint_record', - 'delete_custom_tag', - 'delete_permission_group', - 'destroy_opened_item', - 'disconnect_rolling_stock', - 'drag_train_schedule', - 'drag_train_wait_condition', - 'drop_blueprint_record', - 'drop_item', - 'drop_to_blueprint_book', - 'edit_custom_tag', - 'edit_permission_group', - 'export_blueprint', - 'fast_entity_split', - 'fast_entity_transfer', - 'go_to_train_station', - 'grab_blueprint_record', - 'gui_checked_state_changed', - 'gui_click', - 'gui_confirmed', - 'gui_elem_changed', - 'gui_location_changed', - 'gui_selected_tab_changed', - 'gui_selection_state_changed', - 'gui_switch_state_changed', - 'gui_text_changed', - 'gui_value_changed', - 'import_blueprint', - 'import_blueprint_string', - 'import_permissions_string', - 'inventory_split', - 'inventory_transfer', - 'launch_rocket', - 'lua_shortcut', - 'map_editor_action', - 'market_offer', - 'mod_settings_changed', - 'open_achievements_gui', - 'open_blueprint_library_gui', - 'open_blueprint_record', - 'open_bonus_gui', - 'open_character_gui', - 'open_equipment', - 'open_gui', - 'open_item', - 'open_kills_gui', - 'open_logistic_gui', - 'open_mod_item', - 'open_production_gui', - 'open_technology_gui', - 'open_train_gui', - 'open_train_station_gui', - 'open_trains_gui', - 'open_tutorials_gui', - 'paste_entity_settings', - 'place_equipment', - 'quick_bar_pick_slot', - 'quick_bar_set_selected_page', - 'quick_bar_set_slot', - 'remove_cables', - 'remove_train_station', - 'reset_assembling_machine', - 'rotate_entity', - 'select_area', - 'select_blueprint_entities', - 'select_entity_slot', - 'select_item', - 'select_mapper_slot', - 'select_next_valid_gun', - 'select_tile_slot', - 'set_auto_launch_rocket', - 'set_autosort_inventory', - 'set_behavior_mode', - 'set_car_weapons_control', - 'set_circuit_condition', - 'set_circuit_mode_of_operation', - 'set_deconstruction_item_tile_selection_mode', - 'set_deconstruction_item_trees_and_rocks_only', - 'set_entity_color', - 'set_entity_energy_property', - 'set_filter', - 'set_heat_interface_mode', - 'set_heat_interface_temperature', - 'set_infinity_container_filter_item', - 'set_infinity_container_remove_unfiltered_items', - 'set_infinity_pipe_filter', - 'set_inserter_max_stack_size', - 'set_inventory_bar', - 'set_logistic_filter_item', - 'set_logistic_filter_signal', - 'set_logistic_trash_filter_item', - 'set_request_from_buffers', - 'set_research_finished_stops_game', - 'set_signal', - 'set_single_blueprint_record_icon', - 'set_splitter_priority', - 'set_train_stopped', - 'setup_assembling_machine', - 'setup_blueprint', - 'setup_single_blueprint_record', - 'smart_pipette', - 'stack_split', - 'stack_transfer', - 'start_repair', - 'start_research', - 'start_walking', - 'stop_building_by_moving', - 'switch_connect_to_logistic_network', - 'switch_constant_combinator_state', - 'switch_inserter_filter_mode_state', - 'switch_power_switch_state', - 'switch_to_rename_stop_gui', - 'take_equipment', - 'toggle_deconstruction_item_entity_filter_mode', - 'toggle_deconstruction_item_tile_filter_mode', - 'toggle_driving', - 'toggle_enable_vehicle_logistics_while_moving', - 'toggle_equipment_movement_bonus', - 'toggle_map_editor', - 'toggle_personal_roboport', - 'toggle_show_entity_info', - 'translate_string', - 'undo', - 'upgrade', - 'upgrade_opened_blueprint', - 'use_artillery_remote', - 'use_item', - 'wire_dragging', - 'write_to_console' - } - }, - inventory = { - fields = { - 'fuel', - 'burnt_result', - 'chest', - 'furnace_source', - 'furnace_result', - 'furnace_modules', - 'character_main', - 'character_guns', - 'character_ammo', - 'character_armor', - 'character_vehicle', - 'character_trash', - 'god_main', - 'editor_main', - 'editor_guns', - 'editor_ammo', - 'editor_armor', - 'roboport_robot', - 'roboport_material', - 'robot_cargo', - 'robot_repair', - 'assembling_machine_input', - 'assembling_machine_output', - 'assembling_machine_modules', - 'lab_input', - 'lab_modules', - 'mining_drill_modules', - 'item_main', - 'rocket_silo_rocket', - 'rocket_silo_result', - 'rocket', - 'car_trunk', - 'car_ammo', - 'cargo_wagon', - 'turret_ammo', - 'beacon_modules', - 'character_corpse', - 'artillery_turret_ammo', - 'artillery_wagon_ammo' - } - }, - logistic_member_index = { - fields = { - 'logistic_container', - 'vehicle_storage', - 'character_requester', - 'character_storage', - 'character_provider', - 'generic_on_off_behavior' - } - }, - logistic_mode = { - fields = { - 'active_provider', - 'storage', - 'requester', - 'passive_provider', - 'buffer' - } - }, - mouse_button_type = { - fields = { - 'left', - 'right', - 'middle' - } - }, - rail_connection_direction = { - fields = { - 'left', - 'straight', - 'right' - } - }, - rail_direction = { - fields = { - 'front', - 'back' - } - }, - render_mode = { - fields = { - 'game', - 'chart', - 'chart_zoomed_in' - } - }, - rich_text_setting = { - fields = { - 'enabled', - 'disabled', - 'highlight' - } - }, - riding = { - fields = { - acceleration = { - fields = { - 'nothing', - 'accelerating', - 'braking', - 'reversing' - } - }, - direction = { - fields = { - 'left', - 'straight', - 'right' - } - } - } - }, - shooting = { - fields = { - 'not_shooting', - 'shooting_enemies', - 'shooting_selected' - } - }, - signal_state = { - fields = { - 'open', - 'closed', - 'reserved', - 'reserved_by_circuit_network' - } - }, - train_state = { - fields = { - 'on_the_path', - 'path_lost', - 'no_schedule', - 'no_path', - 'arrive_signal', - 'wait_signal', - 'arrive_station', - 'wait_station', - 'manual_control_stop', - 'manual_control' - } - }, - transport_line = { - fields = { - 'left_line', - 'right_line', - 'left_underground_line', - 'right_underground_line', - 'secondary_left_line', - 'secondary_right_line', - 'left_split_line', - 'right_split_line', - 'secondary_left_split_line', - 'secondary_right_split_line' - } - }, - wire_connection_id = { - fields = { - 'electric_pole', - 'power_switch_left', - 'power_switch_right' - } - }, - wire_type = { - fields = { - 'red', - 'green', - 'copper' - } - }, - -- Defines additional modules - color = { - other_fields = true - }, - anticolor = { - other_fields = true - }, - lightcolor = { - other_fields = true - }, - time = { - fields = { - 'second', - 'minute', - 'hour', - 'day', - 'week', - 'month', - 'year' - } - } - } - } - } - } -end - ---[[ Options - "ignore", "std", "globals", "unused_args", "self", "compat", "global", "unused", "redefined", - "unused_secondaries", "allow_defined", "allow_defined_top", "module", - "read_globals", "new_globals", "new_read_globals", "enable", "only", "not_globals", - "max_line_length", "max_code_line_length", "max_string_line_length", "max_comment_line_length", - "max_cyclomatic_complexity" ---]] - ---[[ Warnings list - -- 011 A syntax error. - -- 021 An invalid inline option. - -- 022 An unpaired inline push directive. - -- 023 An unpaired inline pop directive. - -- 111 Setting an undefined global variable. - -- 112 Mutating an undefined global variable. - -- 113 Accessing an undefined global variable. - -- 121 Setting a read-only global variable. - -- 122 Setting a read-only field of a global variable. - -- 131 Unused implicitly defined global variable. - -- 142 Setting an undefined field of a global variable. - -- 143 Accessing an undefined field of a global variable. - -- 211 Unused local variable. - -- 212 Unused argument. - -- 213 Unused loop variable. - -- 221 Local variable is accessed but never set. - -- 231 Local variable is set but never accessed. - -- 232 An argument is set but never accessed. - -- 233 Loop variable is set but never accessed. - -- 241 Local variable is mutated but never accessed. - -- 311 Value assigned to a local variable is unused. - -- 312 Value of an argument is unused. - -- 313 Value of a loop variable is unused. - -- 314 Value of a field in a table literal is unused. - -- 321 Accessing uninitialized local variable. - -- 331 Value assigned to a local variable is mutated but never accessed. - -- 341 Mutating uninitialized local variable. - -- 411 Redefining a local variable. - -- 412 Redefining an argument. - -- 413 Redefining a loop variable. - -- 421 Shadowing a local variable. - -- 422 Shadowing an argument. - -- 423 Shadowing a loop variable. - -- 431 Shadowing an upvalue. - -- 432 Shadowing an upvalue argument. - -- 433 Shadowing an upvalue loop variable. - -- 511 Unreachable code. - -- 512 Loop can be executed at most once. - -- 521 Unused label. - -- 531 Left-hand side of an assignment is too short. - -- 532 Left-hand side of an assignment is too long. - -- 541 An empty do end block. - -- 542 An empty if branch. - -- 551 An empty statement. - -- 611 A line consists of nothing but whitespace. - -- 612 A line contains trailing whitespace. - -- 613 Trailing whitespace in a string. - -- 614 Trailing whitespace in a comment. - -- 621 Inconsistent indentation (SPACE followed by TAB). - -- 631 Line is too long. ---]] diff --git a/exp_scenario/module/commands/_types.lua b/exp_scenario/module/commands/_types.lua index 0acfeb82..f23ff943 100644 --- a/exp_scenario/module/commands/_types.lua +++ b/exp_scenario/module/commands/_types.lua @@ -18,7 +18,7 @@ local valid, invalid = Commands.status.success, Commands.status.invalid_input local Roles = require("modules.exp_legacy.expcore.roles") local highest_role = Roles.get_player_highest_role -local types = {} --- @class Commands.types +local types = {} --- @class (partial) Commands.types --- A role defined by exp roles types.role = add("role", Commands.types.key_of(Roles.config.roles)) diff --git a/exp_scenario/module/commands/artillery.lua b/exp_scenario/module/commands/artillery.lua index 95749da9..9f93732b 100644 --- a/exp_scenario/module/commands/artillery.lua +++ b/exp_scenario/module/commands/artillery.lua @@ -15,11 +15,11 @@ local abs = math.abs local commands = {} --- @param player LuaPlayer ---- @param area BoundingBox +--- @param area BoundingBox.struct --- @return boolean local function location_break(player, area) local surface = player.surface -- Allow remote view - local is_charted = player.force.is_chunk_charted + local is_charted = (player.force --[[@as LuaForce]]).is_chunk_charted if is_charted(surface, { x = floor(area.left_top.x / 32), y = floor(area.left_top.y / 32) }) then return true elseif is_charted(surface, { x = floor(area.left_top.x / 32), y = floor(area.right_bottom.y / 32) }) then @@ -43,7 +43,7 @@ commands.artillery = Commands.new("artillery", { "exp-commands_artillery.descrip end SelectArea:start(player) return Commands.status.success{ "exp-commands_artillery.enter" } - end) --[[ @as any ]] + end) --[[@as any]] --- when an area is selected to add protection to the area SelectArea:on_selection(function(event) @@ -63,13 +63,14 @@ SelectArea:on_selection(function(event) } local count = 0 - local hits = {} --- @type MapPosition[] + local hits = {} --- @type MapPosition.struct[] for _, entity in ipairs(entities) do local skip = false + local entity_position = entity.position for _, pos in ipairs(hits) do - local x = abs(entity.position.x - pos.x) - local y = abs(entity.position.y - pos.y) + local x = abs(entity_position.x - pos.x) + local y = abs(entity_position.y - pos.y) if x * x + y * y < 36 then skip = true break diff --git a/exp_scenario/module/commands/connect.lua b/exp_scenario/module/commands/connect.lua index b935b45d..cf53b181 100644 --- a/exp_scenario/module/commands/connect.lua +++ b/exp_scenario/module/commands/connect.lua @@ -41,7 +41,7 @@ local function get_server_id(server) elseif status == "Offline" then return false, { "exp-commands_connect.offline", server_details.name } end - return true, server_id + return true, server_id --[[@as string]] elseif server_count_before > 0 then return false, { "exp-commands_connect.wrong-version", concat(server_names_before, ", ") } else diff --git a/exp_scenario/module/commands/kill.lua b/exp_scenario/module/commands/kill.lua index 17d291fd..a71528ed 100644 --- a/exp_scenario/module/commands/kill.lua +++ b/exp_scenario/module/commands/kill.lua @@ -25,7 +25,7 @@ Commands.new("kill", { "exp-commands_kill.description" }) if script.active_mods["space-age"] then other_player.surface.create_entity{ name = "lightning", position = { other_player.position.x, other_player.position.y - 16 }, target = other_player.character } end - other_player.character.die() + assert(other_player.character).die() else return Commands.status.unauthorised{ "exp-commands_kill.lower-role" } end diff --git a/exp_scenario/module/commands/lawnmower.lua b/exp_scenario/module/commands/lawnmower.lua index 5ff1d2e1..b77014e3 100644 --- a/exp_scenario/module/commands/lawnmower.lua +++ b/exp_scenario/module/commands/lawnmower.lua @@ -22,7 +22,7 @@ commands.lawnmower = Commands.new("lawnmower", { "exp-commands_lawnmower.descrip SelectArea:start(player) return Commands.status.success{ "exp-commands_lawnmower.enter" } - end) --[[ @as any ]] + end) --[[@as any]] --- When an area is selected to be handled SelectArea:on_selection(function(event) diff --git a/exp_scenario/module/commands/protected_entities.lua b/exp_scenario/module/commands/protected_entities.lua index 34426b24..7f906413 100644 --- a/exp_scenario/module/commands/protected_entities.lua +++ b/exp_scenario/module/commands/protected_entities.lua @@ -37,7 +37,7 @@ end --- Get the key used in protected_areas --- TODO expose this from EntityProtection ---- @param area BoundingBox +--- @param area BoundingBox.struct --- @return string local function get_area_key(area) return format_string("%i,%i", floor(area.left_top.x), floor(area.left_top.y)) @@ -49,13 +49,15 @@ end local function show_protected_entity(player, entity) local key = get_entity_key(entity) if renders[player.index][key] then return end - local rb = entity.selection_box.right_bottom + local selection_box = entity.selection_box + local rb = selection_box.right_bottom + local position = entity.position renders[player.index][key] = rendering.draw_sprite{ sprite = "utility/notification", target = entity, target_offset = { - (rb.x - entity.position.x) * 0.75, - (rb.y - entity.position.y) * 0.75, + (rb.x - position.x) * 0.75, + (rb.y - position.y) * 0.75, }, x_scale = 2, y_scale = 2, @@ -67,7 +69,7 @@ end --- Show a protected area to a player --- @param player LuaPlayer --- @param surface LuaSurface ---- @param area BoundingBox +--- @param area BoundingBox.struct local function show_protected_area(player, surface, area) local key = get_area_key(area) if renders[player.index][key] then return end diff --git a/exp_scenario/module/commands/protected_tags.lua b/exp_scenario/module/commands/protected_tags.lua index 1667b008..fce30257 100644 --- a/exp_scenario/module/commands/protected_tags.lua +++ b/exp_scenario/module/commands/protected_tags.lua @@ -7,7 +7,7 @@ local Storage = require("modules/exp_util/storage") --- Storage variables local active_players = {} --- @type table Stores all players in in protected mode -local map_tags = {} --- @type table Stores all protected map tags +local map_tags = {} --- @type table Stores all protected map tags Storage.register({ active_players = active_players, diff --git a/exp_scenario/module/commands/rainbow.lua b/exp_scenario/module/commands/rainbow.lua index 1084f84c..c5fd1a36 100644 --- a/exp_scenario/module/commands/rainbow.lua +++ b/exp_scenario/module/commands/rainbow.lua @@ -6,6 +6,12 @@ local Commands = require("modules/exp_commands") local format_player_name = Commands.format_player_name_locale local format_text = Commands.format_rich_text_color +--- A colour with every channel set, Color.struct leaves them optional +--- @class ExpCommands_Rainbow.Color +--- @field r number +--- @field g number +--- @field b number + --- Wraps one component into the next --- @param c1 number --- @param c2 number @@ -21,8 +27,8 @@ local function step_component(c1, c2) end --- Wraps all components of a colour ensuring it remains valid ---- @param color Color ---- @return Color +--- @param color ExpCommands_Rainbow.Color +--- @return ExpCommands_Rainbow.Color local function step_color(color) color.r, color.g = step_component(color.r, color.g) color.g, color.b = step_component(color.g, color.b) @@ -32,9 +38,9 @@ local function step_color(color) end --- Get the next colour in the rainbow by the given step ---- @param color Color +--- @param color ExpCommands_Rainbow.Color --- @param step number ---- @return Color +--- @return ExpCommands_Rainbow.Color local function next_color(color, step) step = step or 0.1 local new_color = { r = 0, g = 0, b = 0 } diff --git a/exp_scenario/module/commands/ratio.lua b/exp_scenario/module/commands/ratio.lua index 2e12e444..201dd339 100644 --- a/exp_scenario/module/commands/ratio.lua +++ b/exp_scenario/module/commands/ratio.lua @@ -29,7 +29,7 @@ Commands.new("ratio", { "exp-commands_ratio.description" }) local amount_of_machines = 1 if items_per_second then - amount_of_machines = math.ceil(products[1].amount * crafts_per_second) + amount_of_machines = math.ceil(assert(assert(products[1]).amount) * crafts_per_second) end for _, ingredient in ipairs(ingredients) do @@ -43,7 +43,7 @@ Commands.new("ratio", { "exp-commands_ratio.description" }) for i, product in ipairs(products) do Commands.print{ product.type == "item" and "exp-commands_ratio.item-out" or "exp-commands_ratio.fluid-out", - math.round(product.amount * crafts_per_second, 3), + math.round(assert(product.amount) * crafts_per_second, 3), product.name } end diff --git a/exp_scenario/module/commands/reports.lua b/exp_scenario/module/commands/reports.lua index e0f845aa..aab4351c 100644 --- a/exp_scenario/module/commands/reports.lua +++ b/exp_scenario/module/commands/reports.lua @@ -11,7 +11,10 @@ local player_has_flag = Roles.player_has_flag local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports ---- @type Commands.InputParser +--- @param input string +--- @param player LuaPlayer +--- @return Commands.Status +--- @return LuaPlayer | LocalisedString local function reportable_player(input, player) local success, status, result = parse_input(input, player, Commands.types.player) if not success then return status, result end @@ -40,11 +43,11 @@ Commands.new("create-report", { "exp-commands_reports.description-create" }) if Reports.report_player(other_player, player.name, reason) then local user_message = { "exp-commands_reports.response", other_player_name, reason } local admin_message = { "exp-commands_reports.response-admin", other_player_name, player_name, reason } - for _, player in ipairs(game.connected_players) do - if player.admin then - player.print(admin_message) + for _, connected_player in ipairs(game.connected_players) do + if connected_player.admin then + connected_player.print(admin_message) else - player.print(user_message) + connected_player.print(user_message) end end else diff --git a/exp_scenario/module/commands/roles.lua b/exp_scenario/module/commands/roles.lua index 7adbb3a1..b8a510ad 100644 --- a/exp_scenario/module/commands/roles.lua +++ b/exp_scenario/module/commands/roles.lua @@ -42,7 +42,7 @@ Commands.new("get-roles", { "exp-commands_roles.description-get" }) --- @cast other_player LuaPlayer? local roles = get_roles_ordered() local roles_formatted = { "" } --- @type LocalisedString - local response = { "exp-commands_roles.list-roles", roles_formatted } + local response = { "exp-commands_roles.list-roles", roles_formatted } --[[@as LocalisedString]] if other_player then roles = get_player_roles(other_player) response[1] = "exp-commands_roles.list-player" @@ -55,8 +55,7 @@ Commands.new("get-roles", { "exp-commands_roles.description-get" }) end local last = #roles_formatted - --- @diagnostic disable-next-line nil-check - roles_formatted[last] = roles_formatted[last][2] + roles_formatted[last] = assert(roles_formatted[last])[2] return Commands.status.success(response) end) diff --git a/exp_scenario/module/commands/search.lua b/exp_scenario/module/commands/search.lua index 13bc03b8..fe4bba77 100644 --- a/exp_scenario/module/commands/search.lua +++ b/exp_scenario/module/commands/search.lua @@ -10,7 +10,10 @@ local format_player_name = Commands.format_player_name_locale local format_number = require("util").format_number --- A player who is of a lower role than the executing player ---- @type Commands.InputParser +--- @param input string +--- @param player LuaPlayer +--- @return Commands.Status +--- @return LuaItemPrototype | LocalisedString local function parse_item(input, player) -- First Case - internal name is given -- Second Case - rich text is given @@ -88,7 +91,7 @@ local function sort_results(results, func) end end - return sorted + return sorted --[[@as SearchResult[] ]] end local display_players_time_format = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true } @@ -146,7 +149,8 @@ Commands.new("search-online", { "exp-commands_search.description-online" }) end) --- Return the amount of an item a player has ---- @type SortFunction +--- @param data SearchResult +--- @return number local function sort_by_count(data) return data.count end diff --git a/exp_scenario/module/commands/surface.lua b/exp_scenario/module/commands/surface.lua index 18504724..0cb2bc43 100644 --- a/exp_scenario/module/commands/surface.lua +++ b/exp_scenario/module/commands/surface.lua @@ -69,7 +69,7 @@ commands.clear_blueprints = Commands.new("clear-blueprints", { "exp-commands_sur SelectArea:start(player) return Commands.status.success{ "exp-commands_surface.enter" } - end) --[[ @as any ]] + end) --[[@as any]] --- When an area is selected SelectArea:on_selection(function(event) diff --git a/exp_scenario/module/commands/teleport.lua b/exp_scenario/module/commands/teleport.lua index 964e8ed7..a7892047 100644 --- a/exp_scenario/module/commands/teleport.lua +++ b/exp_scenario/module/commands/teleport.lua @@ -34,7 +34,7 @@ commands.teleport = Commands.new("teleport", { "exp-commands_teleport.descriptio elseif not teleport_player(other_player, target_player.physical_surface, target_player.physical_position) then return Commands.status.error{ "exp-commands_teleport.unavailable" } end - end) --[[ @as any ]] + end) --[[@as any]] --- Teleports a player to you. --- @class ExpCommands_Teleport.commands.bring: ExpCommand @@ -49,7 +49,7 @@ commands.bring = Commands.new("bring", { "exp-commands_teleport.description-brin elseif not teleport_player(other_player, player.physical_surface, player.physical_position) then return Commands.status.error{ "exp-commands_teleport.unavailable" } end - end) --[[ @as any ]] + end) --[[@as any]] --- Teleports you to a player. --- @class ExpCommands_Teleport.commands.goto: ExpCommand @@ -64,7 +64,7 @@ commands["goto"] = Commands.new("goto", { "exp-commands_teleport.description-got elseif not teleport_player(player, other_player.physical_surface, other_player.physical_position) then return Commands.status.error{ "exp-commands_teleport.unavailable" } end - end) --[[ @as any ]] + end) --[[@as any]] --- Teleport to spawn --- @class ExpCommands_Teleport.commands.spawn: ExpCommand @@ -92,7 +92,7 @@ commands.spawn = Commands.new("spawn", { "exp-commands_teleport.description-spaw else return Commands.status.unauthorised() end - end) --[[ @as any ]] + end) --[[@as any]] return { commands = commands, diff --git a/exp_scenario/module/commands/trains.lua b/exp_scenario/module/commands/trains.lua index ee8885a5..9d79b755 100644 --- a/exp_scenario/module/commands/trains.lua +++ b/exp_scenario/module/commands/trains.lua @@ -10,7 +10,7 @@ local format_number = require("util").format_number local commands = {} --- Set all trains to automatic ---- @class ExpCommand_Artillery.commands.artillery: ExpCommand +--- @class ExpCommand_Trains.commands.set_trains_to_automatic: ExpCommand --- @overload fun(player: LuaPlayer, surface: LuaSurface?, force: LuaForce?) commands.set_trains_to_automatic = Commands.new("set-trains-to-automatic", { "exp-commands_trains.description" }) :optional("surface", { "exp-commands_trains.arg-surface" }, Commands.types.surface) @@ -32,7 +32,7 @@ commands.set_trains_to_automatic = Commands.new("set-trains-to-automatic", { "ex end game.print{ "exp-commands_trains.response", format_player_name(player), format_number(#trains, false) } - end) --[[ @as any ]] + end) --[[@as any]] return { commands = commands, diff --git a/exp_scenario/module/commands/warnings.lua b/exp_scenario/module/commands/warnings.lua index bcc8c38d..14be9aad 100644 --- a/exp_scenario/module/commands/warnings.lua +++ b/exp_scenario/module/commands/warnings.lua @@ -35,7 +35,7 @@ Commands.new("get-warnings", { "exp-commands_warnings.description-get" }) local warnings = Warnings.get_warnings(player) local script_warnings = Warnings.get_script_warnings(player) local other_player_name = format_player_name(other_player) - Commands.print{ "exp-commands_warnings.player-title", other_player_name, #warnings, #script_warnings, config.temp_warning_limit } + Commands.print{ "exp-commands_warnings.player-title", other_player_name, #warnings, #script_warnings, config.script_warning_limit } for _, warning in pairs(warnings) do local by_player_name_formatted = format_player_name(warning.by_player_name) Commands.print{ "exp-commands_warnings.list-element-player", by_player_name_formatted, warning.reason } @@ -47,12 +47,12 @@ Commands.new("get-warnings", { "exp-commands_warnings.description-get" }) for player_name, player_warnings in pairs(warnings) do local player_name_formatted = format_player_name(player_name) local script_warning_count = script_warnings[player_name] and #script_warnings[player_name] or 0 - Commands.print{ "exp-commands_warnings.list-element", player_name_formatted, #player_warnings, script_warning_count, config.temp_warning_limit } + Commands.print{ "exp-commands_warnings.list-element", player_name_formatted, #player_warnings, script_warning_count, config.script_warning_limit } end for player_name, player_warnings in pairs(script_warnings) do if not warnings[player_name] then local player_name_formatted = format_player_name(player_name) - Commands.print{ "exp-commands_warnings.list-element", player_name_formatted, 0, #player_warnings, config.temp_warning_limit } + Commands.print{ "exp-commands_warnings.list-element", player_name_formatted, 0, #player_warnings, config.script_warning_limit } end end end diff --git a/exp_scenario/module/commands/waterfill.lua b/exp_scenario/module/commands/waterfill.lua index 6e1a8e24..a9313f92 100644 --- a/exp_scenario/module/commands/waterfill.lua +++ b/exp_scenario/module/commands/waterfill.lua @@ -36,7 +36,7 @@ commands.waterfill = Commands.new("waterfill", { "exp-commands_waterfill.descrip SelectArea:start(player) return Commands.status.success{ "exp-commands_waterfill.enter" } end - end) --[[ @as any ]] + end) --[[@as any]] --- When an area is selected to be converted to water SelectArea:on_selection(function(event) @@ -70,7 +70,7 @@ SelectArea:on_selection(function(event) if #chests > 0 then for _, chest in pairs(chests) do tile_count = tile_count + 1 - if chest.get_inventory(defines.inventory.chest).is_empty() and tile_count <= item_count_total then + if assert(chest.get_inventory(defines.inventory.chest)).is_empty() and tile_count <= item_count_total then tiles_to_make[tile_count] = { name = tile_to_apply, position = { chest.position.x, chest.position.y } } chest.destroy() else diff --git a/exp_scenario/module/control/custom_start.lua b/exp_scenario/module/control/custom_start.lua index 1c4e64ff..62d59a1a 100644 --- a/exp_scenario/module/control/custom_start.lua +++ b/exp_scenario/module/control/custom_start.lua @@ -8,7 +8,7 @@ local floor = math.floor --- Give a player their starting items --- @param player LuaPlayer local function give_starting_items(player) - local get_prod_stats = player.force.get_item_production_statistics(player.physical_surface) + local get_prod_stats = (player.force --[[@as LuaForce]]).get_item_production_statistics(player.physical_surface) local get_input_count = get_prod_stats.get_input_count local insert_param = { name = "", count = 0 } local insert = player.insert diff --git a/exp_scenario/module/control/damage_popups.lua b/exp_scenario/module/control/damage_popups.lua index 54dfc0e1..803f95b6 100644 --- a/exp_scenario/module/control/damage_popups.lua +++ b/exp_scenario/module/control/damage_popups.lua @@ -26,11 +26,12 @@ local function on_entity_damaged(event) -- Outputs the message as floating text if message then + local entity_position = entity.position local entity_radius = max(1, entity.get_radius()) local offset = (random() - 0.5) * entity_radius * config.damage_location_variance - local position = { x = entity.position.x + offset, y = entity.position.y - entity_radius } + local position = { x = entity_position.x + offset, y = entity_position.y - entity_radius } - local health_percentage = entity.get_health_ratio() + local health_percentage = assert(entity.get_health_ratio()) local color = { r = 1 - health_percentage, g = health_percentage, b = 0 } FlyingText.create{ diff --git a/exp_scenario/module/control/death_markers.lua b/exp_scenario/module/control/death_markers.lua index efb25694..24a74f30 100644 --- a/exp_scenario/module/control/death_markers.lua +++ b/exp_scenario/module/control/death_markers.lua @@ -31,7 +31,7 @@ local function create_map_tag(corpse_data) message = message .. " at " .. time end - corpse_data.tag = player.force.add_chart_tag(corpse_data.corpse.surface, { + corpse_data.tag = (player.force --[[@as LuaForce]]).add_chart_tag(corpse_data.corpse.surface, { position = corpse_data.corpse.position, icon = config.map_icon, text = message, diff --git a/exp_scenario/module/control/deconstruction_log.lua b/exp_scenario/module/control/deconstruction_log.lua index 087030ab..b6d2b05d 100644 --- a/exp_scenario/module/control/deconstruction_log.lua +++ b/exp_scenario/module/control/deconstruction_log.lua @@ -42,7 +42,7 @@ local function format_position(pos) end --- Convert an area to a string ---- @param area BoundingBox +--- @param area BoundingBox.struct --- @return string local function format_area(area) return format_string("%.1f,%.1f,%.1f,%.1f", area.left_top.x, area.left_top.y, area.right_bottom.x, area.right_bottom.y) @@ -137,7 +137,8 @@ local function on_player_ammo_inventory_changed(event) if not player or not player.character then return end local character_ammo = assert(player.get_inventory(defines.inventory.character_ammo)) - local item = character_ammo[player.character.selected_gun_index] + local gun_index = player.character.selected_gun_index --[[@as uint]] + local item = character_ammo[gun_index] if not item or not item.valid or not item.valid_for_read then return end diff --git a/exp_scenario/module/control/degrading_tiles.lua b/exp_scenario/module/control/degrading_tiles.lua index ad16dbfd..dc3a1b11 100644 --- a/exp_scenario/module/control/degrading_tiles.lua +++ b/exp_scenario/module/control/degrading_tiles.lua @@ -16,10 +16,9 @@ end --- Replace a tile with the next tile in the degrade chain --- @param surface LuaSurface ---- @param position MapPosition +--- @param position MapPosition.struct local function degrade_tile(surface, position) - --- @diagnostic disable-next-line Incorrect Api Type: https://forums.factorio.com/viewtopic.php?f=233&t=109145&p=593761&hilit=get_tile#p593761 - local tile = surface.get_tile(position) + local tile = surface.get_tile(position.x, position.y) local tile_name = tile.name local degrade_tile_name = config.degrade_order[tile_name] if not degrade_tile_name then return end @@ -33,8 +32,9 @@ local function degrade_entity(entity) local tiles = {} local surface = entity.surface - local left_top = entity.bounding_box.left_top - local right_bottom = entity.bounding_box.right_bottom + local bounding_box = entity.bounding_box + local left_top = bounding_box.left_top + local right_bottom = bounding_box.right_bottom for x = left_top.x, right_bottom.x do for y = left_top.y, right_bottom.y do local tile = surface.get_tile(x, y) @@ -58,11 +58,10 @@ end --- Gets the average tile strengths around position --- @param surface LuaSurface ---- @param position MapPosition +--- @param position MapPosition.struct --- @return number? local function get_tile_strength(surface, position) - --- @diagnostic disable-next-line Incorrect Api Type: https://forums.factorio.com/viewtopic.php?f=233&t=109145&p=593761&hilit=get_tile#p593761 - local tile = surface.get_tile(position) + local tile = surface.get_tile(position.x, position.y) local tile_name = tile.name local strength = config.strengths[tile_name] if not strength then return end diff --git a/exp_scenario/module/control/discord_alerts.lua b/exp_scenario/module/control/discord_alerts.lua index 38978e1c..c4675140 100644 --- a/exp_scenario/module/control/discord_alerts.lua +++ b/exp_scenario/module/control/discord_alerts.lua @@ -31,15 +31,15 @@ local function append_playtime(player_name) end --- Get the player name from an event ---- @param event { player_index: number, by_player_name: string? } ---- @return string, string +--- @param event { player_index: uint, by_player_name: string? } +--- @return string, string? local function get_player_name(event) local player = game.players[event.player_index] return player.name, event.by_player_name end --- Convert a colour value into hex ---- @param color Color.0 +--- @param color Color.struct --- @return string local function to_hex(color) local hex_digits = "0123456789ABCDEF" @@ -53,7 +53,7 @@ local function to_hex(color) end --- Emit the requires json to file for the given event arguments ---- @param opts { title: string?, color: (Color.0 | string)?, description: string?, tick: number?, fields: { name: string, value: string, inline: boolean? }[] } +--- @param opts { title: string?, color: (Color.struct | string)?, description: string?, tick: number?, fields: { name: string, value: string, inline: boolean? }[] } local function emit_event(opts) local admins_online = 0 local players_online = 0 diff --git a/exp_scenario/module/control/extra_logging.lua b/exp_scenario/module/control/extra_logging.lua index d469c390..07055245 100644 --- a/exp_scenario/module/control/extra_logging.lua +++ b/exp_scenario/module/control/extra_logging.lua @@ -23,7 +23,7 @@ end --- @param event EventData.on_cargo_pod_finished_ascending local function on_cargo_pod_finished_ascending(event) if event.launched_by_rocket then - local force = event.cargo_pod.force + local force = event.cargo_pod.force --[[@as LuaForce]] if force.rockets_launched >= config.rocket_launch_display_rate and force.rockets_launched % config.rocket_launch_display_rate == 0 then add_log_line("[ROCKET]", force.rockets_launched, "rockets launched") elseif config.rocket_launch_display[force.rockets_launched] then @@ -38,7 +38,7 @@ local function on_pre_player_died(event) local cause = event.cause if cause then if cause.type == "character" then - add_log_line("[DEATH]", player.name, "died because of", cause.player.name) + add_log_line("[DEATH]", player.name, "died because of", assert(cause.player).name) else add_log_line("[DEATH]", player.name, "died because of", cause.name) end diff --git a/exp_scenario/module/control/fast_deconstruction.lua b/exp_scenario/module/control/fast_deconstruction.lua index 4481f9b4..acd83069 100644 --- a/exp_scenario/module/control/fast_deconstruction.lua +++ b/exp_scenario/module/control/fast_deconstruction.lua @@ -22,7 +22,7 @@ local min = math.min --- @field trees LuaEntity[] --- @field tree_count number --- @field permission "fast" | "allow" | "disallow" ---- @field task Async.AsyncReturn +--- @field task Async.AsyncReturn local cache --- @type TreeDeconCache? @@ -77,14 +77,15 @@ local function get_player_cache(player_index) -- Create a new cache if the previous on is in use if not cache or cache.task and not cache.task.completed then - cache = {} --[[@as any]] + --- @diagnostic disable-next-line: missing-fields + cache = {} --[[@as TreeDeconCache]] end local player = assert(game.get_player(player_index)) cache.tick = game.tick cache.player_index = player_index cache.player = player - cache.force = player.force --[[ @as LuaForce ]] + cache.force = player.force --[[@as LuaForce]] cache.tree_count = 0 cache.trees = {} cache.permission = get_permission(player) diff --git a/exp_scenario/module/control/help_bubbles.lua b/exp_scenario/module/control/help_bubbles.lua index 6740b93a..b37c143f 100644 --- a/exp_scenario/module/control/help_bubbles.lua +++ b/exp_scenario/module/control/help_bubbles.lua @@ -6,7 +6,7 @@ local Async = require("modules/exp_util/async") local Storage = require("modules/exp_util/storage") local config = require("modules.exp_legacy.config.compilatron") ---- @type table +--- @type table> local persistent_locations = {} Storage.register(persistent_locations, function(tbl) persistent_locations = tbl @@ -55,7 +55,7 @@ local speech_bubble_task = --- @param entity LuaEntity the entity which will have messages spawn from it --- @param messages LocalisedString[] the messages which should be shown --- @param starting_index number? the message index to start at, default 1 ---- @return Async.AsyncReturn +--- @return Async.AsyncReturn local function register_entity(entity, messages, starting_index) return speech_bubble_task{ entity = entity, diff --git a/exp_scenario/module/control/mine_depletion.lua b/exp_scenario/module/control/mine_depletion.lua index 894c3dfb..f8a6cb55 100644 --- a/exp_scenario/module/control/mine_depletion.lua +++ b/exp_scenario/module/control/mine_depletion.lua @@ -68,12 +68,13 @@ local function try_deconstruct_output_chest(entity) end -- Get all adjacent mining drills and inserters + local target_position = target.position local entities = target.surface.find_entities_filtered{ type = { "mining-drill", "inserter" }, to_be_deconstructed = false, area = { - { target.position.x - 1, target.position.y - 1 }, - { target.position.x + 1, target.position.y + 1 } + left_top = { x = target_position.x - 1, y = target_position.y - 1 }, + right_bottom = { x = target_position.x + 1, y = target_position.y + 1 }, }, } @@ -250,16 +251,17 @@ local function on_resource_depleted(event) local drills = resource.surface.find_entities_filtered{ type = "mining-drill", area = { - { position.x - max_mining_radius, position.y - max_mining_radius }, - { position.x + max_mining_radius, position.y + max_mining_radius }, + left_top = { x = position.x - max_mining_radius, y = position.y - max_mining_radius }, + right_bottom = { x = position.x + max_mining_radius, y = position.y + max_mining_radius }, }, } -- Check which could have reached this resource for _, drill in pairs(drills) do local radius = drill.prototype.mining_drill_radius - local dx = math.abs(drill.position.x - position.x) - local dy = math.abs(drill.position.y - position.y) + local drill_position = drill.position + local dx = math.abs(drill_position.x - position.x) + local dy = math.abs(drill_position.y - position.y) if dx <= radius and dy <= radius then try_deconstruct_miner(drill) end diff --git a/exp_scenario/module/control/spawn_area.lua b/exp_scenario/module/control/spawn_area.lua index e4c7213e..aab08d17 100644 --- a/exp_scenario/module/control/spawn_area.lua +++ b/exp_scenario/module/control/spawn_area.lua @@ -7,11 +7,11 @@ local config = require("modules.exp_legacy.config.spawn_area") --- Apply an offset to a LuaPosition --- @param position MapPosition --- @param offset MapPosition ---- @return MapPosition.0 +--- @return MapPosition.struct local function apply_offset(position, offset) return { - x = (position.x or position[1]) + (offset.x or offset[1]), - y = (position.y or position[2]) + (offset.y or offset[2]) + x = position.x + offset.x, + y = position.y + offset.y, } end @@ -21,8 +21,8 @@ end --- @param x_index number --- @param y_index number local function apply_offset_to_array(positions, offset, x_index, y_index) - local x = (offset.x or offset[1]) - local y = (offset.y or offset[2]) + local x = offset.x + local y = offset.y for _, position in ipairs(positions) do position[x_index] = position[x_index] + x position[y_index] = position[y_index] + y @@ -149,11 +149,13 @@ local function create_entities(surface, offset) local pos = apply_offset({ entity_details[2], entity_details[3] }, offset) local entity = surface.create_entity{ name = entity_details[1], position = pos, force = "neutral" } - if entity and config.entities.protected then - protect_entity(entity) - end + if entity then + if config.entities.protected then + protect_entity(entity) + end - entity.operable = config.entities.operable + entity.operable = config.entities.operable + end end end @@ -164,8 +166,7 @@ local function clear_spawn_area(surface, offset) local get_tile = surface.get_tile -- Make sure a non water tile is used for filling - --- @diagnostic disable-next-line Incorrect Api Type: https://forums.factorio.com/viewtopic.php?f=233&t=109145&p=593761&hilit=get_tile#p593761 - local starting_tile = get_tile(offset) + local starting_tile = get_tile(offset.x, offset.y) local fill_tile = starting_tile.collides_with("player") and "landfill" or starting_tile.name local fill_radius = config.spawn_area.landfill_radius local fill_radius_sqr = fill_radius ^ 2 @@ -185,8 +186,7 @@ local function clear_spawn_area(surface, offset) if dst < tile_radius_sqr then -- If it is inside the decon radius always set the tile tiles_to_make[#tiles_to_make + 1] = { name = decon_tile, position = pos } - --- @diagnostic disable-next-line Incorrect Api Type: https://forums.factorio.com/viewtopic.php?f=233&t=109145&p=593761&hilit=get_tile#p593761 - elseif dst < fill_radius_sqr and get_tile(pos).collides_with("player") then + elseif dst < fill_radius_sqr and get_tile(pos.x, pos.y).collides_with("player") then -- If it is inside the fill radius only set the tile if it is water tiles_to_make[#tiles_to_make + 1] = { name = fill_tile, position = pos } end @@ -278,7 +278,8 @@ local function on_player_created(event) if config.resource_patches.enabled then create_resource_patches(surface, offset) end if config.turrets.enabled then update_turrets() end - player.force.set_spawn_position(offset, surface) + local force = player.force --[[@as LuaForce]] + force.set_spawn_position(offset, surface) player.teleport(offset, surface) end diff --git a/exp_scenario/module/control/station_auto_name.lua b/exp_scenario/module/control/station_auto_name.lua index fb9b8905..96b8fc09 100644 --- a/exp_scenario/module/control/station_auto_name.lua +++ b/exp_scenario/module/control/station_auto_name.lua @@ -66,8 +66,9 @@ local function rename_station(event) -- Check which recourse is closest for _, resource in ipairs(resources) do - local dx = px - resource.bounding_box.left_top.x - local dy = py - resource.bounding_box.left_top.y + local resource_box = resource.bounding_box + local dx = px - resource_box.left_top.x + local dy = py - resource_box.left_top.y local distance = (dx * dx) + (dy * dy) if distance < closest_distance then closest_distance = distance @@ -78,7 +79,8 @@ local function rename_station(event) -- Set the item name and icon if closest_recourse then item_name = closest_recourse.name:gsub("^%l", string.upper):gsub("-", " ") -- remove dashes and making first letter capital - local product = closest_recourse.prototype.mineable_properties.products[1] + local products = assert(closest_recourse.prototype.mineable_properties.products) + local product = assert(products[1]) icon = string.format("[img=%s.%s]", product.type, product.name) end end diff --git a/exp_scenario/module/gui/autofill.lua b/exp_scenario/module/gui/autofill.lua index c973a256..3dc16175 100644 --- a/exp_scenario/module/gui/autofill.lua +++ b/exp_scenario/module/gui/autofill.lua @@ -49,7 +49,7 @@ Elements.toggle_section_button = Gui.define("autofill/toggle_section_button") element.sprite = "utility/expand" element.tooltip = { "exp-gui_autofill.tooltip-toggle-section-expand" } end - end) --[[ @as any ]] + end) --[[@as any]] --- Toggle if an entity will be autofilled when played --- @class ExpGui_Autofill.elements.toggle_entity_button: ExpElement @@ -88,7 +88,7 @@ Elements.toggle_entity_button = Gui.define("autofill/toggle_entity_button") style.padding = 0 style.height = 22 style.width = 22 - end) --[[ @as any ]] + end) --[[@as any]] --- Toggle if an item will be inserted into an entity --- @class ExpGui_Autofill.elements.toggle_item_button: ExpElement @@ -127,7 +127,7 @@ Elements.toggle_item_button = Gui.define("autofill/toggle_item_button") style.padding = -2 style.height = 32 style.width = 32 - end) --[[ @as any ]] + end) --[[@as any]] --- The amount of an item to insert --- @class ExpGui_Autofill.elements.amount_textfield: ExpElement @@ -165,7 +165,7 @@ Elements.amount_textfield = Gui.define("autofill/amount_textfield") element.text = tostring(clamped) player.print{ "exp-gui_autofill.invalid", clamped, rich_img("item", item_settings.name), rich_img("entity", item_settings.entity) } end - end) --[[ @as any ]] + end) --[[@as any]] --- A disabled version of the autofill settings used as a filler Elements.disabled_autofill_setting = Gui.define("autofill/empty_autofill_setting") @@ -221,9 +221,9 @@ Elements.section = Gui.define("autofill/section") end) :on_click(function(def, player, element, event) --- @cast def ExpGui_Autofill.elements.section - event.element = def.data[element] --[[ @as LuaGuiElement ]] + event.element = def.data[element] --[[@as LuaGuiElement]] Elements.toggle_section_button:raise_event(event) - end) --[[ @as any ]] + end) --[[@as any]] --- Add an item category to a section, at most three can exist --- @param section LuaGuiElement @@ -238,7 +238,7 @@ function Elements.section.add_category(section, category_name) category.style.vertical_spacing = 1 local ctn = 0 - local entity_settings = Elements.section.data[section] --[[ @as ExpGui_Autofill.entity_settings ]] + local entity_settings = Elements.section.data[section] --[[@as ExpGui_Autofill.entity_settings]] for _, item_data in pairs(entity_settings.items) do if item_data.category == category_name then Elements.toggle_item_button(category, item_data) @@ -265,7 +265,7 @@ end --- Container added to the left gui flow --- @class ExpGui_Autofill.elements.container: ExpElement ---- @field data table +--- @field data table> Elements.container = Gui.define("autofill/container") :draw(function(def, parent) --- @cast def ExpGui_Autofill.elements.container @@ -312,7 +312,7 @@ Elements.container = Gui.define("autofill/container") end return container.parent - end) --[[ @as any ]] + end) --[[@as any]] --- Get the autofill settings for a player --- @param player LuaPlayer diff --git a/exp_scenario/module/gui/debug/expcore_gui_view.lua b/exp_scenario/module/gui/debug/expcore_gui_view.lua index 4fd18849..399656de 100644 --- a/exp_scenario/module/gui/debug/expcore_gui_view.lua +++ b/exp_scenario/module/gui/debug/expcore_gui_view.lua @@ -27,7 +27,7 @@ function Public.show(container) local left_panel_style = left_panel.style left_panel_style.width = 300 - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible for element_name in pairs(ExpElement._elements) do local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = element_name } Gui.set_data(header, element_name) @@ -92,18 +92,18 @@ Gui.on_click( input_text_box.text = concat{ "ExpElement._elements[\"", element_name, "\"]" } input_text_box.style.font_color = Color.black - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible local define = ExpElement._elements[element_name] local content = dump({ - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible debug = define._debug, - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible has_handlers = define._has_handlers, - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible track_elements = define._track_elements, - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible elements = ExpIter._scopes[element_name], - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible data = ExpData._scopes[element_name]._raw, }) or "nil" right_panel.text = content diff --git a/exp_scenario/module/gui/debug/model.lua b/exp_scenario/module/gui/debug/model.lua index 52ab850f..387aed88 100644 --- a/exp_scenario/module/gui/debug/model.lua +++ b/exp_scenario/module/gui/debug/model.lua @@ -4,7 +4,7 @@ local ExpUtil = require("modules/exp_util") local concat = table.concat local inspect = table.inspect local pcall = pcall -local loadstring = loadstring --- @diagnostic disable-line +local loadstring = load local rawset = rawset local Public = {} diff --git a/exp_scenario/module/gui/debug/redmew_global_view.lua b/exp_scenario/module/gui/debug/redmew_global_view.lua index 8e387479..de43f1ac 100644 --- a/exp_scenario/module/gui/debug/redmew_global_view.lua +++ b/exp_scenario/module/gui/debug/redmew_global_view.lua @@ -24,7 +24,7 @@ function Public.show(container) local left_panel_style = left_panel.style left_panel_style.width = 300 - --- @diagnostic disable-next-line invisible + --- @diagnostic disable-next-line: access-invisible for token_id in pairs(Storage._registered) do local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = token_id } Gui.set_data(header, token_id) diff --git a/exp_scenario/module/gui/elements.lua b/exp_scenario/module/gui/elements.lua index 66cfc99d..f399c82d 100644 --- a/exp_scenario/module/gui/elements.lua +++ b/exp_scenario/module/gui/elements.lua @@ -22,11 +22,10 @@ Elements.online_player_dropdown = Gui.define("player_dropdown") end) :style{ height = 24, - } --[[ @as any ]] + } --[[@as any]] --- To help with caching and avoid context changes the player list from the previous update is remembered ---- @type (string?)[] -do local _player_names = {} +do local _player_names = {} --- @type (string?)[] --- Updates the player name list after a join or leave --- @return (string?)[] function Elements.online_player_dropdown._update_player_names() diff --git a/exp_scenario/module/gui/module_inserter.lua b/exp_scenario/module/gui/module_inserter.lua index a39bd391..33011cec 100644 --- a/exp_scenario/module/gui/module_inserter.lua +++ b/exp_scenario/module/gui/module_inserter.lua @@ -78,7 +78,7 @@ Elements.create_selection_planner = Gui.define("module_inserter/create_selection :on_click(function(def, player, element) --- @cast def ExpGui_ModuleInserter.elements.create_selection_planner SelectArea:start(player, def.data[element]) - end) --[[ @as any ]] + end) --[[@as any]] --- Used to select the machine to apply modules to --- @class ExpGui_ModuleInserter.elements.machine_selector: ExpElement @@ -98,7 +98,7 @@ Elements.machine_selector = Gui.define("module_inserter/machine_selector") :on_elem_changed(function(def, player, element, event) --- @cast def ExpGui_ModuleInserter.elements.machine_selector local element_data = def.data[element] - local machine_name = element.elem_value --[[ @as string? ]] + local machine_name = element.elem_value --[[@as string?]] if not machine_name then if element_data.on_last_row then Elements.module_table.reset_row(element_data.module_table, element) @@ -112,7 +112,7 @@ Elements.machine_selector = Gui.define("module_inserter/machine_selector") Elements.module_table.add_row(element_data.module_table) end end - end) --[[ @as any ]] + end) --[[@as any]] --- Used to select the modules to be applied Elements.module_selector = Gui.define("module_inserter/module_selector") @@ -140,7 +140,7 @@ Elements.module_table = Gui.define("module_inserter/module_table") local slots_per_row = config.module_slots_per_row + 1 return Gui.elements.scroll_table(parent, 280, slots_per_row) end) - :element_data{} --[[ @as any ]] + :element_data{} --[[@as any]] --- Get all the rows in a module table --- @param module_table LuaGuiElement @@ -177,7 +177,7 @@ end --- @param machine_selector LuaGuiElement function Elements.module_table.remove_row(module_table, machine_selector) local rows = Elements.module_table.data[module_table] - local row = rows[machine_selector.index] + local row = assert(rows[machine_selector.index]) rows[machine_selector.index] = nil Gui.destroy_if_valid(machine_selector) for _, separator in pairs(row.row_separators) do @@ -193,7 +193,7 @@ end --- @param machine_selector LuaGuiElement function Elements.module_table.reset_row(module_table, machine_selector) local rows = Elements.module_table.data[module_table] - local row = rows[machine_selector.index] + local row = assert(rows[machine_selector.index]) for _, separator in pairs(row.row_separators) do separator.visible = false @@ -211,9 +211,9 @@ end --- @param machine_name string function Elements.module_table.refresh_row(module_table, machine_selector, machine_name) local rows = Elements.module_table.data[module_table] - local row = rows[machine_selector.index] + local row = assert(rows[machine_selector.index]) - local active_module_count = prototypes.entity[machine_name].module_inventory_size + local active_module_count = assert(prototypes.entity[machine_name].module_inventory_size) local visible_row_count = math.ceil(active_module_count / config.module_slots_per_row) local visible_module_count = visible_row_count * config.module_slots_per_row local module_elem_value = { name = config.machines[machine_name].module } @@ -277,8 +277,8 @@ local function apply_planners_in_area(player, area, machine_name, planner_with_p -- Bounding box table to be reused in the loop below --- @type BoundingBox local param_area = { - left_top = {}, - right_bottom = {} + left_top = { x = 0, y = 0 }, + right_bottom = { x = 0, y = 0 }, } -- Update area param table to be reused in the loop below @@ -334,7 +334,7 @@ SelectArea:on_selection(function(event, module_table) } for _, row in pairs(Elements.module_table.get_rows(module_table)) do - local machine_name = row.machine_selector.elem_value --[[ @as string? ]] + local machine_name = row.machine_selector.elem_value --[[@as string?]] if not machine_name then goto continue end @@ -348,8 +348,8 @@ SelectArea:on_selection(function(event, module_table) -- Get all the modules selected for i = 1, entity_prototype.module_inventory_size do - local module_selector = module_selectors[i] - local module = module_selector.elem_value --[[ @as { name: string, quality: string }? ]] + local module_selector = assert(module_selectors[i]) + local module = module_selector.elem_value --[[@as { name: string, quality: string }?]] if module then -- Module selected, add it the module arrays local no_prod_name = module.name:gsub("productivity", "efficiency") diff --git a/exp_scenario/module/gui/player_bonus.lua b/exp_scenario/module/gui/player_bonus.lua index 7c5fd84b..054c3088 100644 --- a/exp_scenario/module/gui/player_bonus.lua +++ b/exp_scenario/module/gui/player_bonus.lua @@ -22,13 +22,16 @@ local Elements = {} --- @field _cost_scale number --- For perf calculate the division of scale against cost ahead of time -for _, bonus_data in pairs(config.player_bonus) do +--- @type table +local player_bonus = config.player_bonus + +for _, bonus_data in pairs(player_bonus) do bonus_data._cost_scale = bonus_data.cost / bonus_data.scale end --- Progress bar which displays how much of a bonus has been used --- @class ExpGui_PlayerBonus.elements.bonus_used: ExpElement ---- @field data number +--- @field data table --- @overload fun(parent: LuaGuiElement): LuaGuiElement Elements.bonus_used = Gui.define("player_bonus/bonus_used") :track_all_elements() @@ -44,11 +47,10 @@ Elements.bonus_used = Gui.define("player_bonus/bonus_used") font = "heading-2", color = { 1, 0, 0 }, } - :element_data(0) --[[ @as any ]] + :element_data(0) --[[@as any]] --- Value is cached to save perf ---- @type table -do local _points_limit = {} +do local _points_limit = {} --- @type table --- Clear the cache for points limit --- @param player LuaPlayer function Elements.bonus_used._clear_points_limit_cache(player) @@ -145,7 +147,7 @@ Elements.reset_button = Gui.define("player_bonus/reset_button") Elements.bonus_table.reset_sliders(element_data.bonus_table) local bonus_cost = Elements.bonus_table.calculate_cost(element_data.bonus_table) Elements.bonus_used.refresh(element_data.bonus_used, bonus_cost) - end) --[[ @as any ]] + end) --[[@as any]] --- Link an apply button to this reset button so that it will be disabled after being pressed --- @param reset_button LuaGuiElement @@ -186,7 +188,7 @@ Elements.apply_button = Gui.define("player_bonus/apply_button") Elements.bonus_table.save_sliders(element_data.bonus_table) Elements.container.apply_player_bonus(player) end - end) --[[ @as any ]] + end) --[[@as any]] --- Link an apply button to this reset button so that it will be disabled after being pressed --- @param apply_button LuaGuiElement @@ -207,7 +209,7 @@ Elements.bonus_table_label = Gui.define("player_bonus/table_label") } :style{ width = Gui.from_argument(3, 70), - } --[[ @as any ]] + } --[[@as any]] --- @class ExpGui_PlayerBonus.elements.bonus_slider.elements --- @field bonus_used LuaGuiElement @@ -265,7 +267,7 @@ Elements.bonus_slider = Gui.define("player_bonus/bonus_slider") element_data.label.caption = Elements.bonus_slider.calculate_slider_caption(bonus_data, value) element_data.apply_button.enabled = Elements.bonus_used.update(element_data.bonus_used, value_change * bonus_data._cost_scale) element_data.reset_button.enabled = true - end) --[[ @as any ]] + end) --[[@as any]] --- Get the caption of the slider label --- @param bonus_data ExpGui_PlayerBonus.bonus_data @@ -311,7 +313,7 @@ Elements.bonus_table = Gui.define("player_bonus/bonus_table") :draw(function(_, parent) return Gui.elements.scroll_table(parent, 300, 3) end) - :element_data{} --[[ @as any ]] + :element_data{} --[[@as any]] --- Adds a row to the milestone table --- @param bonus_table LuaGuiElement @@ -378,7 +380,7 @@ Elements.container = Gui.define("player_bonus/container") Elements.bonus_used.refresh(elements.bonus_used, bonus_cost) return Gui.elements.container.get_root_element(container) - end) --[[ @as any ]] + end) --[[@as any]] --- Set the bonus value for a player --- @param player LuaPlayer @@ -442,7 +444,7 @@ end function Elements.container.calculate_cost(player) local cost = 0 local player_data = Elements.container.data[player] - for _, bonus_data in pairs(config.player_bonus) do + for _, bonus_data in pairs(player_bonus) do cost = cost + (player_data[bonus_data.name] or 0) * bonus_data._cost_scale end return cost diff --git a/exp_scenario/module/gui/player_list.lua b/exp_scenario/module/gui/player_list.lua index 3b5379b3..905b5be2 100644 --- a/exp_scenario/module/gui/player_list.lua +++ b/exp_scenario/module/gui/player_list.lua @@ -48,14 +48,14 @@ Elements.open_action_bar = Gui.define("player_list/open_action_bar") --- @cast def ExpGui_PlayerList.elements.open_action_bar Elements.container.toggle_selected_player(player, def.data[element]) Elements.player_table.refresh_player(player) - end) --[[ @as any ]] + end) --[[@as any]] --- Set whether an open action bar button shows as highlighted --- @param open_button LuaGuiElement --- @param highlighted boolean function Elements.open_action_bar.set_highlight(open_button, highlighted) open_button.style = highlighted and "tool_button" or "frame_button" - local style = open_button.style + local style = open_button.style --[[@as LuaStyle]] style.padding = -2 style.width = 8 style.height = 14 @@ -80,7 +80,7 @@ Elements.close_action_bar = Gui.define("player_list/close_action_bar") :on_click(function(_, player) Elements.container.set_selected_player(player, nil) Elements.player_table.refresh_player(player) - end) --[[ @as any ]] + end) --[[@as any]] --- Button used to confirm a reason --- @class ExpGui_PlayerList.elements.reason_confirm: ExpElement @@ -102,14 +102,14 @@ Elements.reason_confirm = Gui.define("player_list/reason_confirm") local action_name = Elements.container.get_selected_action(player) local button_data = action_name and config.buttons[action_name] if button_data and button_data.reason_callback then - local reason = element.parent.entry.text + local reason = assert(element.parent).entry.text --[[@as string?]] if reason == nil or not reason:find("%S") then reason = "no reason given" end button_data.reason_callback(player, reason) end - element.parent.entry.text = "" + assert(element.parent).entry.text = "" Elements.container.set_selected_player(player, nil) Elements.player_table.refresh_player(player) - end) --[[ @as any ]] + end) --[[@as any]] --- Clickable player name label, left click opens the map and right click toggles the action bar --- @class ExpGui_PlayerList.elements.player_name_label: ExpElement @@ -142,7 +142,7 @@ Elements.player_name_label = Gui.define("player_list/player_name_label") Elements.container.toggle_selected_player(player, selected_player) Elements.player_table.refresh_player(player) end - end) --[[ @as any ]] + end) --[[@as any]] --- @class ExpGui_PlayerList.elements.player_table.row --- @field open_button LuaGuiElement @@ -165,7 +165,7 @@ Elements.player_table = Gui.define("player_list/player_table") end) :style{ padding = { 1, 0, 1, 2 }, - } --[[ @as any ]] + } --[[@as any]] --- Store the action and reason bars associated with a player table --- @param player_table LuaGuiElement @@ -342,7 +342,7 @@ Elements.action_bar = Gui.define("player_list/action_bar") :style{ height = 35, padding = { 1, 3 }, - } --[[ @as any ]] + } --[[@as any]] --- Update the action bar buttons to match the selection for a player, hidden when nothing is selected --- @param action_bar LuaGuiElement @@ -390,7 +390,7 @@ Elements.reason_bar = Gui.define("player_list/reason_bar") :style{ height = 35, padding = { -1, 3 }, - } --[[ @as any ]] + } --[[@as any]] --- Update the reason bar visibility to match the selection, shown only while an action awaits a reason --- @param reason_bar LuaGuiElement @@ -420,7 +420,7 @@ Elements.container = Gui.define("player_list/container") Elements.player_table.rebuild(player_table, row_data) return Gui.elements.container.get_root_element(container) - end) --[[ @as any ]] + end) --[[@as any]] --- Get or create the selection state for a player --- @param player LuaPlayer diff --git a/exp_scenario/module/gui/player_stats.lua b/exp_scenario/module/gui/player_stats.lua index c615506d..b0a57df3 100644 --- a/exp_scenario/module/gui/player_stats.lua +++ b/exp_scenario/module/gui/player_stats.lua @@ -93,7 +93,7 @@ Elements.table_label = Gui.define("player_stats/table_label") } :style{ width = Gui.from_argument("width"), - } --[[ @as any ]] + } --[[@as any]] --- Data table that shows all data for a player --- @class ExpGui_PlayerStats.elements.player_stats_table: ExpElement @@ -139,7 +139,7 @@ Elements.player_stats_table = Gui.define("player_stats/data_table") def.data[data_table] = labels return data_table - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh a data table with the most recent stats for a player --- @param data_table LuaGuiElement @@ -185,7 +185,7 @@ Elements.player_dropdown = Gui.define("player_stats/player_dropdown") local data_table = def.data[element] local target_player = ElementsExtra.online_player_dropdown.get_selected(element) Elements.player_stats_table.refresh(data_table, target_player) - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh all stats tables associated with a player dropdown function Elements.player_dropdown.refresh_online() diff --git a/exp_scenario/module/gui/production_stats.lua b/exp_scenario/module/gui/production_stats.lua index deea2314..94b49562 100644 --- a/exp_scenario/module/gui/production_stats.lua +++ b/exp_scenario/module/gui/production_stats.lua @@ -9,6 +9,7 @@ local Roles = require("modules/exp_legacy/expcore/roles") local Elements = {} --- The flow precision values in the same order as production_precision_dropdown.items +--- @type defines.flow_precision_index[] local precision_indexes = { defines.flow_precision_index.five_seconds, defines.flow_precision_index.one_minute, @@ -94,7 +95,7 @@ Elements.item_selector = Gui.define("production_stats/item_selector") element_data.on_last_row = false Elements.production_table.add_row(element_data.production_table) end - end) --[[ @as any ]] + end) --[[@as any]] --- Label used for every element in the production table Elements.table_label = Gui.define("production_stats/table_label") @@ -129,7 +130,7 @@ Elements.production_table = Gui.define("production_stats/production_table") :track_all_elements() :draw(function(def, parent) local scroll_table = Gui.elements.scroll_table(parent, 304, 4) - local display_alignments = scroll_table.style.column_alignments + local display_alignments = assert(scroll_table.style.column_alignments) for i = 2, 4 do display_alignments[i] = "right" end @@ -144,7 +145,7 @@ Elements.production_table = Gui.define("production_stats/production_table") Elements.table_label(scroll_table, { "exp-gui_production-stats.caption-net" }, { "exp-gui_production-stats.tooltip-per-second" }, "heading_2_label") return scroll_table - end) --[[ @as any ]] + end) --[[@as any]] --- Calculate the row data for a production table --- @param force LuaForce @@ -183,7 +184,7 @@ end --- @param item_selector LuaGuiElement function Elements.production_table.remove_row(production_table, item_selector) local rows = Elements.production_table.data[production_table].rows - local row = rows[item_selector.index] + local row = assert(rows[item_selector.index]) rows[item_selector.index] = nil Gui.destroy_if_valid(item_selector) for _, element in pairs(row) do @@ -196,7 +197,7 @@ end --- @param item_selector LuaGuiElement function Elements.production_table.reset_row(production_table, item_selector) local rows = Elements.production_table.data[production_table].rows - local row = rows[item_selector.index] + local row = assert(rows[item_selector.index]) row.production.caption = "0.00" row.consumption.caption = "0.00" row.net.caption = "0.00" @@ -209,7 +210,7 @@ end --- @param row_data ExpGui_ProductionStats.elements.production_table.row_data function Elements.production_table.refresh_row(production_table, item_selector, row_data) local rows = Elements.production_table.data[production_table].rows - local row = rows[item_selector.index] + local row = assert(rows[item_selector.index]) row.production.caption = row_data.production row.consumption.caption = row_data.consumption row.net.caption = row_data.net @@ -223,9 +224,9 @@ function Elements.production_table.refresh_online() local precision_index = precision_indexes[element_data.precision_dropdown.selected_index] for _, row in pairs(element_data.rows) do local item_selector = row.item_selector - local item_name = item_selector.elem_value --[[ @as string? ]] + local item_name = item_selector.elem_value --[[@as string?]] if item_name then - local row_data = Elements.production_table.calculate_row_data(player.force --[[ @as LuaForce ]], player.surface, item_name, precision_index) + local row_data = Elements.production_table.calculate_row_data(player.force --[[@as LuaForce]], player.surface, item_name, precision_index) Elements.production_table.refresh_row(production_table, item_selector, row_data) end end diff --git a/exp_scenario/module/gui/quick_actions.lua b/exp_scenario/module/gui/quick_actions.lua index 0eacba2c..92d358aa 100644 --- a/exp_scenario/module/gui/quick_actions.lua +++ b/exp_scenario/module/gui/quick_actions.lua @@ -43,13 +43,13 @@ local function new_quick_action(command, on_click) :style{ width = 160, } - :on_click(on_click or function(def, player, element, event) + :on_click(on_click or function(_def, player, _element, _event) command(player) end) Elements[command_name] = element Actions[command_name] = { - command = command --[[ @as ExpCommand ]], + command = command --[[@as ExpCommand]], element = element, } end diff --git a/exp_scenario/module/gui/readme.lua b/exp_scenario/module/gui/readme.lua index ed0cf6ea..5a7749b6 100644 --- a/exp_scenario/module/gui/readme.lua +++ b/exp_scenario/module/gui/readme.lua @@ -47,7 +47,7 @@ Elements.title_table = Gui.define("readme/title_table") cell_padding = 0, vertical_align = "center", horizontally_stretchable = true, - } --[[ @as any ]] + } --[[@as any]] --- Scroll pane used for title tables --- @class ExpGui_Readme.elements.title_table_scroll: ExpElement @@ -64,7 +64,7 @@ Elements.title_table_scroll = Gui.define("readme/title_table_scroll") padding = { 1, 3 }, maximal_height = scroll_height, horizontally_stretchable = true, - } --[[ @as any ]] + } --[[@as any]] --- Sub content frame --- @class ExpGui_Readme.elements.sub_content: ExpElement @@ -80,7 +80,7 @@ Elements.sub_content = Gui.define("readme/sub_content") horizontal_align = "center", padding = { 2, 2 }, top_margin = 2, - } --[[ @as any ]] + } --[[@as any]] --- @class ExpGui_Readme.elements.join_server.elements --- @field server_id string @@ -119,7 +119,7 @@ Elements.join_server = Gui.define("readme/join_server") --- @cast def ExpGui_Readme.elements.join_server local server_id = def.data[button].server_id External.request_connection(player, server_id, true) - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh join server button --- @param button LuaGuiElement @@ -244,7 +244,7 @@ define_tab( ) return container - end) --[[ @as any ]] + end) --[[@as any]] ) --- Rules tab @@ -261,14 +261,15 @@ define_tab( local rules = Gui.elements.scroll_table(container, scroll_height, 1) rules.style = "bordered_table" - rules.style.cell_padding = 4 + local rules_style = rules.style --[[@as LuaStyle]] + rules_style.cell_padding = 4 for i = 1, 15 do Gui.elements.centered_label(rules, frame_width - 30, { "exp-gui_readme.rules-" .. i }) end return container - end) --[[ @as any ]] + end) --[[@as any]] ) --- Commands tab @@ -287,7 +288,8 @@ define_tab( local commands = Gui.elements.scroll_table(container, scroll_height, 2) commands.style = "bordered_table" - commands.style.cell_padding = 0 + local commands_style = commands.style --[[@as LuaStyle]] + commands_style.cell_padding = 0 for name, command in pairs(Commands.list_for_player(player)) do Gui.elements.centered_label(commands, 120, name) @@ -295,7 +297,7 @@ define_tab( end return container - end) --[[ @as any ]] + end) --[[@as any]] ) --- Servers tab @@ -338,7 +340,7 @@ define_tab( end return container - end) --[[ @as any ]] + end) --[[@as any]] ) --- Backers tab @@ -359,32 +361,32 @@ define_tab( roles = { "Senior Administrator", "Administrator" }, title = { "exp-gui_readme.backers-management" }, width = 230, - players = {}, + players = {}, --- @type string[] }, { roles = { "Board Member", "Senior Backer" }, title = { "exp-gui_readme.backers-board" }, width = 145, - players = {}, + players = {}, --- @type string[] }, { roles = { "Sponsor", "Supporter" }, title = { "exp-gui_readme.backers-backers" }, width = 196, - players = {}, + players = {}, --- @type string[] }, { roles = { "Moderator", "Trainee" }, title = { "exp-gui_readme.backers-staff" }, width = 235, - players = {}, + players = {}, --- @type string[] }, { roles = {}, time = 3 * 3600 * 60, title = { "exp-gui_readme.backers-active" }, width = 235, - players = {}, + players = {}, --- @type string[] }, } @@ -433,7 +435,7 @@ define_tab( end return container - end) --[[ @as any ]] + end) --[[@as any]] ) --- @class (exact) ExpGui_Readme.elements.readme_data.param table @@ -599,7 +601,7 @@ define_tab( end return container - end) --[[ @as any ]] + end) --[[@as any]] ) --- @class ExpGui_Readme.elements.container.elements @@ -608,6 +610,7 @@ define_tab( --- Main readme container --- @class ExpGui_Readme.elements.container: ExpElement --- @field data table +--- @overload fun(parent: LuaGuiElement): LuaGuiElement Elements.container = Gui.define("readme/container") :track_all_elements() :draw(function(def, parent) diff --git a/exp_scenario/module/gui/research_milestones.lua b/exp_scenario/module/gui/research_milestones.lua index d1c1a5d9..4652edcd 100644 --- a/exp_scenario/module/gui/research_milestones.lua +++ b/exp_scenario/module/gui/research_milestones.lua @@ -72,7 +72,7 @@ Elements.clock_label = Gui.define("research_milestones/clock_label") type = "label", caption = research_time_format_nil, style = "heading_2_label", - } --[[ @as any ]] + } --[[@as any]] --- Update the clock label for all online players function Elements.clock_label.refresh_online() @@ -95,7 +95,7 @@ Elements.milestone_table_label = Gui.define("research_milestones/table_label") minimal_width = Gui.from_argument(2, 70), horizontal_align = Gui.from_argument(3, "right"), font_color = font_color.neutral, - } --[[ @as any ]] + } --[[@as any]] --- @class ExpGui_ResearchMilestones.elements.milestone_table.row_elements --- @field name LuaGuiElement @@ -124,10 +124,11 @@ Elements.milestone_table = Gui.define("research_milestones/milestone_table") Elements.milestone_table_label(milestone_table, { "exp-gui_research-milestones.caption-difference" }) return milestone_table end) - :element_data{} --[[ @as any ]] + :element_data{} --[[@as any]] do local _row_data = {} --- @type ExpGui_ResearchMilestones.elements.milestone_table.row_data + --- @diagnostic disable-next-line: missing-fields local empty_row_data = { color = font_color.positive } --- Get the row data for a force and research @@ -203,7 +204,7 @@ end --- @param row_index number --- @param row_data ExpGui_ResearchMilestones.elements.milestone_table.row_data function Elements.milestone_table.refresh_row(milestone_table, row_index, row_data) - local row = Elements.milestone_table.data[milestone_table][row_index] + local row = assert(Elements.milestone_table.data[milestone_table][row_index]) row.name.caption = row_data.name row.target.caption = row_data.target row.achieved.caption = row_data.achieved @@ -224,7 +225,7 @@ end --- Refresh all the labels on the table --- @param milestone_table LuaGuiElement function Elements.milestone_table.refresh(milestone_table) - local force = Gui.get_player(milestone_table).force --[[ @as LuaForce ]] + local force = Gui.get_player(milestone_table).force --[[@as LuaForce]] local start_index = Elements.container.calculate_starting_research_index(force) for row_index = 1, display_size do local row_data = Elements.milestone_table.calculate_row_data(force, start_index + row_index - 1) @@ -234,7 +235,7 @@ end --- Refresh all tables for a player function Elements.milestone_table.refresh_player(player) - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] local start_index = Elements.container.calculate_starting_research_index(force) for _, milestone_table in Elements.milestone_table:online_elements(player) do for row_index = 1, display_size do @@ -269,10 +270,9 @@ Elements.container = Gui.define("research_milestones/container") local milestone_table = Elements.milestone_table(container) Elements.clock_label(header) - local force = Gui.get_player(parent).force + local force = Gui.get_player(parent).force --[[@as LuaForce]] def.data[force] = def.data[force] or {} -- used by start index and row data - local force = Gui.get_player(parent).force --[[ @as LuaForce ]] local start_index = Elements.container.calculate_starting_research_index(force) for research_index = start_index, start_index + display_size - 1 do local row_data = Elements.milestone_table.calculate_row_data(force, research_index) @@ -296,7 +296,7 @@ end --- @param research_index number --- @return number function Elements.container.get_achieved_time(force, research_index) - return Elements.container.data[force][research_index] + return assert(Elements.container.data[force][research_index]) end --- Calculate the starting research index for a force diff --git a/exp_scenario/module/gui/rocket_info.lua b/exp_scenario/module/gui/rocket_info.lua index c377155a..d7999db3 100644 --- a/exp_scenario/module/gui/rocket_info.lua +++ b/exp_scenario/module/gui/rocket_info.lua @@ -90,7 +90,7 @@ Elements.toggle_section_button = Gui.define("rocket_info/toggle_section_button") element.sprite = "utility/expand" element.tooltip = { "exp-gui_rocket-info.tooltip-toggle-section-expand" } end - end) --[[ @as any ]] + end) --[[@as any]] --- A clickable coordinate label which opens the silo location on the map when pressed --- @class ExpGui_RocketInfo.elements.position_label: ExpElement @@ -114,7 +114,7 @@ Elements.position_label = Gui.define("rocket_info/position_label") local entity = def.data[element] if not entity or not entity.valid then return end player.set_controller{ type = defines.controllers.remote, position = entity.position, surface = entity.surface } - end) --[[ @as any ]] + end) --[[@as any]] --- Data table showing the launch statistics for a force --- @class ExpGui_RocketInfo.elements.stats_table: ExpElement @@ -125,7 +125,7 @@ Elements.stats_table = Gui.define("rocket_info/stats_table") :element_data{} :draw(function(def, parent) return Gui.elements.scroll_table(parent, 215, 2) - end) --[[ @as any ]] + end) --[[@as any]] --- @class ExpGui_RocketInfo.elements.stats_table.row_data --- @field key string Unique key used to look up the value label @@ -218,7 +218,7 @@ end --- Refresh the stats table for a player, adding any rows that do not yet exist --- @param player LuaPlayer function Elements.stats_table.refresh_player(player) - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] local row_data = Elements.stats_table.calculate_row_data(force) for _, stats_table in Elements.stats_table:online_elements(player) do Elements.stats_table.refresh(stats_table, row_data) @@ -243,7 +243,7 @@ Elements.milestones_table = Gui.define("rocket_info/milestones_table") :element_data{} :draw(function(def, parent) return Gui.elements.scroll_table(parent, 215, 2) - end) --[[ @as any ]] + end) --[[@as any]] --- @class ExpGui_RocketInfo.elements.milestones_table.row_data --- @field milestone number The milestone this row represents @@ -315,7 +315,7 @@ end --- Refresh the milestones table for a player, adding rows as new milestones become visible --- @param player LuaPlayer function Elements.milestones_table.refresh_player(player) - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] local row_data = Elements.stats_table.calculate_row_data(force) for _, stats_table in Elements.stats_table:online_elements(player) do Elements.stats_table.refresh(stats_table, row_data) @@ -359,7 +359,7 @@ Elements.progress_table = Gui.define("rocket_info/progress_table") def.data[progress_table] = { rows = {}, no_silos = no_silos } return progress_table - end) --[[ @as any ]] + end) --[[@as any]] --- @class ExpGui_RocketInfo.elements.progress_table.row_data --- @field entity LuaEntity @@ -404,9 +404,9 @@ end --- @return ExpGui_RocketInfo.elements.progress_table.row_data[] function Elements.progress_table.calculate_row_data_all(silo_data) local row_data = {} - for unit_number, silo_data in pairs(silo_data) do - if silo_data.entity.valid then - row_data[unit_number] = Elements.progress_table.calculate_row_data(silo_data) + for unit_number, silo in pairs(silo_data) do + if silo.entity.valid then + row_data[unit_number] = Elements.progress_table.calculate_row_data(silo) else -- Prune silos that are no longer valid silo_data[unit_number] = nil @@ -433,7 +433,8 @@ function Elements.progress_table.add_row(progress_table, row_data) progress.style.padding = { 0, 2 } progress.style.font_color = row_data.color - rows[row_data.entity.unit_number] = { x = x, y = y, progress = progress } + local unit_number = row_data.entity.unit_number --[[@as uint]] + rows[unit_number] = { x = x, y = y, progress = progress } end --- Remove a silo row from the progress table @@ -455,7 +456,8 @@ end --- @param row_data ExpGui_RocketInfo.elements.progress_table.row_data function Elements.progress_table.refresh_row(progress_table, row_data) local element_data = Elements.progress_table.data[progress_table] - local row = element_data.rows[row_data.entity.unit_number] + local unit_number = row_data.entity.unit_number --[[@as uint]] + local row = element_data.rows[unit_number] row.x.caption = row_data.x row.y.caption = row_data.y row.progress.caption = row_data.caption @@ -496,7 +498,7 @@ end --- Refresh the progress table for a player, reconciling rows with the current set of silos --- @param player LuaPlayer function Elements.progress_table.refresh_player(player) - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] local silos = Elements.container.get_silos(force) local row_data = Elements.progress_table.calculate_row_data_all(silos) for _, progress_table in Elements.progress_table:online_elements(player) do @@ -539,7 +541,7 @@ Elements.container = Gui.define("rocket_info/container") container.style.padding = 0 local player = Gui.get_player(parent) - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] local force_data = def._get_force_data(force) if config.stats.show_stats then @@ -618,9 +620,10 @@ end --- Add a silo to the list of current silos for a force --- @param entity LuaEntity function Elements.container.add_silo(entity) - local force = entity.force --[[ @as LuaForce ]] + local force = entity.force --[[@as LuaForce]] local silos = Elements.container._get_force_data(force).silos - silos[entity.unit_number] = { + local unit_number = entity.unit_number --[[@as uint]] + silos[unit_number] = { entity = entity, launched = 0, awaiting_reset = false, @@ -630,9 +633,11 @@ end --- Increment the launch count for a silo --- @param entity LuaEntity function Elements.container.increment_silo(entity) - local force = entity.force --[[ @as LuaForce ]] + local force = entity.force --[[@as LuaForce]] local silos = Elements.container._get_force_data(force).silos - local silo_data = silos[entity.unit_number] + local unit_number = entity.unit_number + --- @cast unit_number uint + local silo_data = silos[unit_number] if not silo_data then return end silo_data.launched = silo_data.launched + 1 silo_data.awaiting_reset = true @@ -653,8 +658,8 @@ Gui.toolbar.create_button{ --- Record the launch and update the stats when a cargo pod finishes ascending --- @param event EventData.on_cargo_pod_finished_ascending local function on_cargo_pod_finished_ascending(event) - local force = event.cargo_pod.force --[[ @as LuaForce ]] - local rockets_launched = force.rockets_launched + local force = event.cargo_pod.force --[[@as LuaForce]] + local rockets_launched = force.rockets_launched --[[@as number]] -- Update the launch stats for the force local stats = Elements.container.get_stats(force) @@ -686,7 +691,7 @@ end --- @param event EventData.on_rocket_launch_ordered local function on_rocket_launch_ordered(event) Elements.container.increment_silo(event.rocket_silo) - Elements.progress_table.refresh_force(event.rocket_silo.force --[[ @as LuaForce ]]) + Elements.progress_table.refresh_force(event.rocket_silo.force --[[@as LuaForce]]) end --- Refresh the gui when a player joins the game as it may be outdated @@ -704,7 +709,7 @@ local function on_built(event) local entity = event.entity if not entity.valid or entity.name ~= "rocket-silo" then return end Elements.container.add_silo(entity) - Elements.progress_table.refresh_force(entity.force --[[ @as LuaForce ]]) + Elements.progress_table.refresh_force(entity.force --[[@as LuaForce]]) end --- Refresh the progress for all forces that own at least one silo diff --git a/exp_scenario/module/gui/science_production.lua b/exp_scenario/module/gui/science_production.lua index 0224a253..ad7772af 100644 --- a/exp_scenario/module/gui/science_production.lua +++ b/exp_scenario/module/gui/science_production.lua @@ -79,7 +79,7 @@ Elements.production_label = Gui.define("science_production/production_label") def.data[label] = suffix return label - end) --[[ @as any ]] + end) --[[@as any]] --- @class Elements.production_label.display_data --- @field caption LocalisedString @@ -109,7 +109,7 @@ function Elements.production_label.calculate_display_data(tooltip, value, cutoff end local suffix, caption = format_number(value) - display_data = display_data or {} + display_data = display_data or {} --[[@as Elements.production_label.display_data]] display_data.caption = caption display_data.suffix = suffix display_data.tooltip = tooltip @@ -144,12 +144,12 @@ Elements.no_production_label = Gui.define("science_production/no_production_labe padding = { 2, 4 }, single_line = false, width = 200, - } --[[ @as any ]] + } --[[@as any]] --- Refresh a no production label --- @param no_production_label LuaGuiElement function Elements.no_production_label.refresh(no_production_label) - local force = Gui.get_player(no_production_label).force --[[ @as LuaForce ]] + local force = Gui.get_player(no_production_label).force --[[@as LuaForce]] no_production_label.visible = not Elements.container.has_production(force) end @@ -157,7 +157,7 @@ end function Elements.no_production_label.refresh_online() local force_data = {} for player, no_production_label in Elements.no_production_label:online_elements() do - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] local visible = force_data[force.name] if visible == nil then visible = not Elements.container.has_production(force) @@ -193,10 +193,11 @@ Elements.science_table = Gui.define("science_production/science_table") local science_table = Gui.elements.scroll_table(parent, 190, 4) local no_production_label = Elements.no_production_label(science_table) Elements.no_production_label.refresh(no_production_label) - science_table.style.column_alignments[3] = "right" + local science_table_style = science_table.style --[[@as LuaStyle]] + science_table_style.column_alignments[3] = "right" return science_table end) - :element_data{} --[[ @as any ]] + :element_data{} --[[@as any]] --- Calculate the data needed to add or refresh a row --- @param force LuaForce @@ -220,7 +221,7 @@ function Elements.science_table.calculate_row_data(force, science_pack, row_data end -- Return the pack data - row_data = row_data or {} + row_data = row_data or {} --[[@as ExpGui_ScienceProduction.elements.science_table.row_data]] row_data.visible = production.total.made > 0 row_data.science_pack = science_pack row_data.icon_style = icon_style @@ -280,7 +281,8 @@ function Elements.science_table.add_row(science_table, row_data) column_count = 2, } delta_table.style.padding = 0 - delta_table.style.column_alignments[1] = "right" + local delta_table_style = delta_table.style --[[@as LuaStyle]] + delta_table_style.column_alignments[1] = "right" -- Draw the net production label local net = Elements.production_label(science_table, row_data.net) @@ -312,7 +314,8 @@ function Elements.science_table.refresh_row(science_table, row_data) -- Update the icon local icon = row.icon icon.style = row_data.icon_style - icon.style.height = 55 + local icon_style = icon.style --[[@as LuaStyle]] + icon_style.height = 55 -- Update the element visibility row.net_suffix.visible = true @@ -326,8 +329,7 @@ function Elements.science_table.refresh_row(science_table, row_data) Elements.production_label.refresh(row.used, row_data.used) end ---- @type table -do local _row_data = {} +do local _row_data = {} --- @type table> --- Refresh the production tables for all online players function Elements.science_table.refresh_online() -- Refresh the row data for online forces @@ -361,7 +363,7 @@ Elements.eta_label = Gui.define("science_production/eta_label") caption = clock_time_format_nil, tooltip = long_time_format_nil, style = "frame_title", - } --[[ @as any ]] + } --[[@as any]] --- @class Elements.eta_label.display_data --- @field caption LocalisedString @@ -410,14 +412,13 @@ end --- Refresh an eta label --- @param eta_label LuaGuiElement function Elements.eta_label.refresh(eta_label) - local force = Gui.get_player(eta_label).force --[[ @as LuaForce ]] + local force = Gui.get_player(eta_label).force --[[@as LuaForce]] local display_data = Elements.eta_label.calculate_display_data(force) eta_label.caption = display_data.caption eta_label.tooltip = display_data.tooltip end ---- @type Elements.eta_label.display_data -do local _display_data = {} +do local _display_data = {} --- @type table --- Refresh the eta label for all online players function Elements.eta_label.refresh_online() -- Refresh the row data for online forces @@ -430,8 +431,10 @@ do local _display_data = {} -- Update the eta labels for player, eta_label in Elements.eta_label:online_elements() do local display_data = _display_data[player.force.name] - eta_label.caption = display_data.caption - eta_label.tooltip = display_data.tooltip + if display_data then + eta_label.caption = display_data.caption + eta_label.tooltip = display_data.tooltip + end end end end @@ -443,7 +446,7 @@ Elements.container = Gui.define("science_production/container") local container = Gui.elements.container(parent) Gui.elements.header(container, { caption = { "exp-gui_science-production.caption-main" } }) - local force = Gui.get_player(parent).force --[[ @as LuaForce ]] + local force = Gui.get_player(parent).force --[[@as LuaForce]] local science_table = Elements.science_table(container) for _, science_pack in ipairs(config) do --- @cast science_pack any @@ -462,7 +465,7 @@ Elements.container = Gui.define("science_production/container") end return Gui.elements.container.get_root_element(container) - end) --[[ @as any ]] + end) --[[@as any]] --- Cached mostly because they are long names local _fp_one_minute = defines.flow_precision_index.one_minute @@ -477,8 +480,7 @@ local _fp_one_hour = defines.flow_precision_index.one_hour --- @field ten_minutes ExpGui_ScienceProduction._item_data --- @field one_hour ExpGui_ScienceProduction._item_data ---- @type table -do local _production_data = {} +do local _production_data = {} --- @type table --- Get the production stats for a force --- @param flow_stats any diff --git a/exp_scenario/module/gui/surveillance.lua b/exp_scenario/module/gui/surveillance.lua index 0c1e79e2..0fd65924 100644 --- a/exp_scenario/module/gui/surveillance.lua +++ b/exp_scenario/module/gui/surveillance.lua @@ -25,7 +25,7 @@ Elements.player_dropdown = Gui.define("surveillance/player_dropdown") local camera = def.data[element] local target_player = assert(ElementsExtra.online_player_dropdown.get_selected(element)) Elements.camera.set_target_player(camera, target_player) - end) --[[ @as any ]] + end) --[[@as any]] --- Button which sets the target of a camera to the current location --- @class ExpGui_Surveillance.elements.set_location_button: ExpElement @@ -48,7 +48,7 @@ Elements.set_location_button = Gui.define("surveillance/set_location_button") --- @cast def ExpGui_Surveillance.elements.set_location_button local camera = def.data[element] Elements.camera.set_target_position(camera, player.physical_surface_index, player.physical_position) - end) --[[ @as any ]] + end) --[[@as any]] --- @class ExpGui_Surveillance.elements.type_dropdown.data --- @field player_dropdown LuaGuiElement @@ -87,7 +87,7 @@ Elements.type_dropdown = Gui.define("surveillance/type_dropdown") local target_player = ElementsExtra.online_player_dropdown.get_selected(element_data.player_dropdown) Elements.camera.set_target_player(element_data.camera, target_player) end - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh all online type dropdowns by cycling the associated player dropdown function Elements.type_dropdown.refresh_online() @@ -131,7 +131,7 @@ Elements.zoom_out_button = Gui.define("surveillance/zoom_out_button") if camera.zoom > 0.2 then camera.zoom = camera.zoom - 0.05 end - end) --[[ @as any ]] + end) --[[@as any]] --- Buttons which increases zoom by 5% --- @class ExpGui_Surveillance.elements.zoom_in_button: ExpElement @@ -156,7 +156,7 @@ Elements.zoom_in_button = Gui.define("surveillance/zoom_in_button") if camera.zoom < 2.0 then camera.zoom = camera.zoom + 0.05 end - end) --[[ @as any ]] + end) --[[@as any]] --- Camera which tracks a target with a physical_position and surface_index --- @class ExpGui_Surveillance.elements.camera: ExpElement @@ -176,7 +176,7 @@ Elements.camera = Gui.define("surveillance/camera") } :element_data( Gui.from_argument(1) - ) --[[ @as any ]] + ) --[[@as any]] --- Set the target player for the camera --- @param camera LuaGuiElement diff --git a/exp_scenario/module/gui/task_list.lua b/exp_scenario/module/gui/task_list.lua index e777aa3d..75858bad 100644 --- a/exp_scenario/module/gui/task_list.lua +++ b/exp_scenario/module/gui/task_list.lua @@ -105,7 +105,7 @@ Elements.new_task_button = Gui.define("task_list/new_task_button") body = "", new = true, }) - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the visibility based on player permissions --- @param new_task_button LuaGuiElement @@ -154,7 +154,7 @@ Elements.view_task_button = Gui.define("task_list/view_task_button") --- @cast def ExpGui_TaskList.element.view_task_button local elements = def.data[view_task_button] Elements.container.open_view_task(elements.container, elements.task) - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the title and tooltip of the view task button --- @param view_task_button LuaGuiElement @@ -187,19 +187,19 @@ Elements.no_tasks_header = Gui.define("task_list/no_tasks_header") :style{ padding = { 2, 0 }, bottom_margin = 0, - } --[[ @as any ]] + } --[[@as any]] --- Refresh the visibility of the no tasks label --- @param no_tasks_header LuaGuiElement function Elements.no_tasks_header.refresh(no_tasks_header) - local force = Gui.get_player(no_tasks_header).force --[[ @as LuaForce ]] + local force = Gui.get_player(no_tasks_header).force --[[@as LuaForce]] no_tasks_header.visible = not Elements.container.has_tasks(force) end --- Refresh the visibility of the no tasks label --- @param player LuaPlayer function Elements.no_tasks_header.refresh_player(player) - local visible = not Elements.container.has_tasks(player.force --[[ @as LuaForce ]]) + local visible = not Elements.container.has_tasks(player.force --[[@as LuaForce]]) for _, no_tasks_header in Elements.no_tasks_header:tracked_elements(player) do no_tasks_header.visible = visible end @@ -246,13 +246,13 @@ Elements.task_list = Gui.define("task_list/task_list") return task_list end) - :element_data{} --[[ @as any ]] + :element_data{} --[[@as any]] --- Adds a task to the task list --- @param task_list LuaGuiElement --- @param task ExpGui_TaskList.Task function Elements.task_list.add_task(task_list, task) - local container = assert(task_list.parent.parent.parent) + local container = assert(assert(assert(task_list.parent).parent).parent) local view_task_buttons = Elements.task_list.data[task_list] view_task_buttons[task.id] = Elements.view_task_button(task_list, task, container) end @@ -330,7 +330,7 @@ Elements.task_footer = Gui.define("task_list/task_footer") height = 0, padding = 5, use_header_filler = false, - } --[[ @as any ]] + } --[[@as any]] --- @class ExpGui_TaskList.elements.close_task_button.elements --- @field container LuaGuiElement @@ -354,7 +354,7 @@ Elements.close_task_button = Gui.define("task_list/close_task_button") --- @cast def ExpGui_TaskList.element.close_task_button local elements = def.data[close_task_button] Elements.container.close_footers(elements.container) - end) --[[ @as any ]] + end) --[[@as any]] --- @class ExpGui_TaskList.elements.task_button.elements --- @field task ExpGui_TaskList.Task? @@ -379,7 +379,7 @@ Elements.edit_task_button = Gui.define("task_list/edit_task_button") --- @cast def ExpGui_TaskList.element.edit_task_button local elements = def.data[edit_task_button] Elements.container.open_edit_task(elements.container, assert(elements.task)) - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the edit button --- @param edit_task_button LuaGuiElement @@ -415,9 +415,9 @@ Elements.delete_task_button = Gui.define("task_list/delete_task_button") :on_click(function(def, player, delete_task_button) --- @cast def ExpGui_TaskList.element.delete_task_button local elements = def.data[delete_task_button] - Elements.container.remove_task(player.force --[[ @as LuaForce ]], elements.task) + Elements.container.remove_task(player.force --[[@as LuaForce]], elements.task) Elements.container.close_footers(elements.container) - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the delete button --- @param delete_task_button LuaGuiElement @@ -477,7 +477,7 @@ Elements.view_task_footer = Gui.define("task_list/view_task_footer") } return view_task_footer - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the view task with new task details --- @param view_task_footer LuaGuiElement @@ -532,9 +532,9 @@ Elements.task_message_textfield = Gui.define("task_list/task_message_textfield") } :on_text_changed(function(def, player, task_message_textfield) --- @cast def ExpGui_TaskList.elements.task_message_textfield - local confirm_task_button = def.data[task_message_textfield].confirm_task_button + local confirm_task_button = assert(def.data[task_message_textfield].confirm_task_button) confirm_task_button.enabled = string.len(task_message_textfield.text) > 5 - end) --[[ @as any ]] + end) --[[@as any]] --- Set the confirm task button to update on text changed --- @param task_message_textfield LuaGuiElement @@ -549,7 +549,7 @@ end function Elements.task_message_textfield.refresh(task_message_textfield, task) local elements = Elements.task_message_textfield.data[task_message_textfield] local message = task.new and "" or task.title .. "\n" .. task.body - elements.confirm_task_button.enabled = string.len(message) > 5 + assert(elements.confirm_task_button).enabled = string.len(message) > 5 task_message_textfield.text = message task_message_textfield.focus() end @@ -590,13 +590,13 @@ Elements.confirm_task_button = Gui.define("task_list/confirm_task_button") Elements.container.close_footers(elements.container) - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] if task.new then Elements.container.add_task(force, task) else Elements.container.refresh_force_online(force, task) end - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the confirm task button --- @param confirm_task_button LuaGuiElement @@ -612,7 +612,7 @@ function Elements.confirm_task_button.parse(message) -- Trim the spaces of the string local trimmed = string.gsub(message, "^%s*(.-)%s*$", "%1") local title, body = string.match(trimmed, "(.-)\n(.*)") - local parsed = { title = title, body = body } + local parsed = { title = title, body = body } --[[@as { title: string, body: string }]] if not title then -- If it doesn't match the pattern return the str as a title parsed.title = trimmed @@ -649,7 +649,7 @@ Elements.discard_task_button = Gui.define("task_list/discard_task_button") else Elements.container.open_view_task(elements.container, task) end - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the discard task button --- @param discard_task_button LuaGuiElement @@ -696,7 +696,7 @@ Elements.edit_task_footer = Gui.define("task_list/edit_task_footer") } return edit_task_footer - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the view task with new task details --- @param edit_task_footer LuaGuiElement @@ -755,9 +755,14 @@ end --- @field view_task_footer LuaGuiElement --- @field edit_task_footer LuaGuiElement +--- @class ExpGui_TaskList.elements.container.data +--- @field global_data { next_task_id: number } +--- @field [LuaGuiElement] ExpGui_TaskList.elements.container.elements +--- @field [LuaForce] ExpGui_TaskList.Task[] + --- Container added to the left gui flow --- @class ExpGui_TaskList.elements.container: ExpElement ---- @field data table | table | table<"global_data", { next_task_id: number }> +--- @field data ExpGui_TaskList.elements.container.data Elements.container = Gui.define("task_list/container") :track_all_elements() :draw(function(def, parent) @@ -781,7 +786,7 @@ Elements.container = Gui.define("task_list/container") -- Add tasks to the list if there are any local player = Gui.get_player(parent) - local force = player.force --[[ @as LuaForce ]] + local force = player.force --[[@as LuaForce]] local tasks = def.data[force] if tasks then for _, task in ipairs(tasks) do @@ -796,11 +801,11 @@ Elements.container = Gui.define("task_list/container") elements.edit_task_footer.visible = false -- Set the data and return - def.data[root] = elements --[[ @as any ]] + def.data[root] = elements --[[@as any]] return root end) :global_data{ next_task_id = 1 } - :force_data{} --[[ @as any ]] + :force_data{} --[[@as any]] --- Check if a force has tasks --- @param force LuaForce @@ -885,7 +890,7 @@ end --- Refresh all tasks for a player --- @param player LuaPlayer function Elements.container.refresh_player(player) - local tasks = Elements.container.data[ player.force --[[ @as LuaForce ]] ] + local tasks = Elements.container.data[ player.force --[[@as LuaForce]] ] for _, container in Elements.container:tracked_elements(player) do local elements = Elements.container.data[container] Elements.task_list.refresh_tasks(elements.task_list, tasks) @@ -908,7 +913,7 @@ end --- Add the element to the left flow with a toolbar button Gui.add_left_element(Elements.container, function(player) - return Elements.container.has_tasks(player.force --[[ @as LuaForce ]]) + return Elements.container.has_tasks(player.force --[[@as LuaForce]]) end) Gui.toolbar.create_button{ diff --git a/exp_server_ups/module/control.lua b/exp_server_ups/module/control.lua index b39eab29..6d51c9d3 100644 --- a/exp_server_ups/module/control.lua +++ b/exp_server_ups/module/control.lua @@ -42,7 +42,7 @@ Elements.server_ups = Gui.define("server_ups") if not existing or not existing.valid then def.data[player] = element -- Only set if previous is invalid end - end) --[[ @as any ]] + end) --[[@as any]] --- Refresh the caption for all online players --- @param ups number The UPS to be displayed diff --git a/exp_util/module/aabb.lua b/exp_util/module/aabb.lua index 64c5719d..7b985702 100644 --- a/exp_util/module/aabb.lua +++ b/exp_util/module/aabb.lua @@ -11,22 +11,22 @@ local max = math.max local AABB = {} --- Check if an area is valid ---- @param aabb BoundingBox +--- @param aabb BoundingBox.struct --- @return boolean # True if the area is valid function AABB.valid(aabb) return aabb.left_top.x < aabb.right_bottom.x and aabb.left_top.y < aabb.right_bottom.y end --- Returns the size of the area contained within an AABB ---- @param aabb BoundingBox +--- @param aabb BoundingBox.struct --- @return number function AABB.size(aabb) return (aabb.right_bottom.x - aabb.left_top.x) * (aabb.right_bottom.y - aabb.left_top.y) end --- Clone an area, allows for safe mutation of an input value ---- @param aabb BoundingBox ---- @return BoundingBox +--- @param aabb BoundingBox.struct +--- @return BoundingBox.struct function AABB.clone(aabb) return { left_top = { x = aabb.left_top.x, y = aabb.left_top.y }, @@ -35,8 +35,8 @@ function AABB.clone(aabb) end --- Expand an area to be integer aligned, expanding away from 0 ---- @param aabb BoundingBox ---- @return BoundingBox +--- @param aabb BoundingBox.struct +--- @return BoundingBox.struct function AABB.expand(aabb) return { left_top = { x = floor(aabb.left_top.x), y = floor(aabb.left_top.y) }, @@ -45,8 +45,8 @@ function AABB.expand(aabb) end --- Contract an area to be integer aligned, contracting towards 0 ---- @param aabb BoundingBox ---- @return BoundingBox +--- @param aabb BoundingBox.struct +--- @return BoundingBox.struct function AABB.contract(aabb) return { left_top = { x = ceil(aabb.left_top.x), y = ceil(aabb.left_top.y) }, @@ -55,9 +55,9 @@ function AABB.contract(aabb) end --- Expand an area to include all other areas ---- @param aabb BoundingBox ---- @param ... BoundingBox ---- @return BoundingBox +--- @param aabb BoundingBox.struct +--- @param ... BoundingBox.struct +--- @return BoundingBox.struct function AABB.union(aabb, ...) local rtn = AABB.clone(aabb) for _, next_aabb in ipairs{ ... } do @@ -70,9 +70,9 @@ function AABB.union(aabb, ...) end --- Contract an area to include to the overlap of all areas ---- @param aabb BoundingBox ---- @param ... BoundingBox ---- @return BoundingBox? # Nil if there is no intersection +--- @param aabb BoundingBox.struct +--- @param ... BoundingBox.struct +--- @return BoundingBox.struct? # Nil if there is no intersection function AABB.intersect(aabb, ...) local rtn = AABB.clone(aabb) for _, next_aabb in ipairs{ ... } do @@ -88,8 +88,8 @@ function AABB.intersect(aabb, ...) end --- Check if a point is contained within an area ---- @param aabb BoundingBox ---- @param point MapPosition +--- @param aabb BoundingBox.struct +--- @param point MapPosition.struct --- @return boolean # True if the point is within or on the edge of the bounding box function AABB.contains_point(aabb, point) return point.x >= aabb.left_top.x and point.y >= aabb.left_top.y @@ -97,8 +97,8 @@ function AABB.contains_point(aabb, point) end --- Check if an area is fulling contained within another area ---- @param aabb BoundingBox ---- @param other BoundingBox +--- @param aabb BoundingBox.struct +--- @param other BoundingBox.struct --- @return boolean # True if the point is within or on the edge of the bounding box function AABB.contains_area(aabb, other) return AABB.contains_point(aabb, other.left_top) and AABB.contains_point(aabb, other.right_bottom) diff --git a/exp_util/module/async.lua b/exp_util/module/async.lua index 9afaa377..e3847436 100644 --- a/exp_util/module/async.lua +++ b/exp_util/module/async.lua @@ -93,8 +93,8 @@ local Async = { Async.status = {} --- @class Async.AsyncFunction ---- @field id number The id of this async function ---- @operator call: Async.AsyncReturn +--- @field id string The id of this async function +--- @overload fun(...: any): Async.AsyncReturn Async._function_prototype = {} Async._function_metatable = { @@ -104,10 +104,10 @@ Async._function_metatable = { } --- @class Async.AsyncReturn ---- @field func_id number The id of the async function to be called +--- @field func_id string The id of the async function to be called --- @field args any[] The arguments to call the function with --- @field tick number? If present, the function will be called on this game tick ---- @field next_id number? The id of the async function to be called with the return value +--- @field next_id string? The id of the async function to be called with the return value --- @field canceled boolean? True if the call has been canceled --- @field completed boolean? True if the call has completed --- @field return_values any? The return values of the function call @@ -123,20 +123,20 @@ script.register_metatable("AsyncReturn", Async._return_metatable) --- Storage Variables -local resolve_next --- @type Async.AsyncReturn[] Stores a queue of async functions to be executed on the next tick -local resolve_queue --- @type Async.AsyncReturn[] Stores a queue of async functions to be executed on a later tick +local resolve_next --- @type Async.AsyncReturn[] Stores a queue of async functions to be executed on the next tick +local resolve_queue --- @type Async.AsyncReturn[] Stores a queue of async functions to be executed on a later tick --- Insert an item into the priority queue ---- @param pending Async.AsyncReturn ---- @return Async.AsyncReturn +--- @param pending Async.AsyncReturn +--- @return Async.AsyncReturn local function add_to_next_tick(pending) resolve_next[#resolve_next + 1] = pending return pending end --- Insert an item into the priority queue ---- @param pending Async.AsyncReturn ---- @return Async.AsyncReturn +--- @param pending Async.AsyncReturn +--- @return Async.AsyncReturn local function add_to_resolve_queue(pending) local tick = pending.tick for index = #resolve_queue, 1, -1 do @@ -191,7 +191,7 @@ end --- Run an async function on the next tick, this is the default and can be used to bypass permission groups --- @param ... any The arguments to call the function with ---- @return Async.AsyncReturn +--- @return Async.AsyncReturn function Async._function_prototype:start_soon(...) assert(Async._registered[self.id], "Async function is not registered") Async._queue_pressure[self.id] = Async._queue_pressure[self.id] + 1 @@ -204,7 +204,7 @@ end --- Run an async function after the given number of ticks --- @param ticks number The number of ticks to call the function after --- @param ... any The arguments to call the function with ---- @return Async.AsyncReturn +--- @return Async.AsyncReturn function Async._function_prototype:start_after(ticks, ...) ExpUtil.assert_argument_type(ticks, "number", 1, "ticks") assert(ticks > 0, "Ticks must be a positive number") @@ -219,7 +219,7 @@ end --- Run an async function on the next tick if the function is not already queued, allows singleton task/thread behaviour --- @param ... any The arguments to call the function with ---- @return Async.AsyncReturn | nil +--- @return Async.AsyncReturn | nil function Async._function_prototype:start_task(...) assert(Async._registered[self.id], "Async function is not registered") if Async._queue_pressure[self.id] > 0 then return end @@ -228,7 +228,7 @@ end --- Run an async function on this tick, then queue it based on its return value --- @param ... any The arguments to call the function with ---- @return Async.AsyncReturn +--- @return Async.AsyncReturn function Async._function_prototype:start_now(...) assert(Async._registered[self.id], "Async function is not registered") local status, rtn1, rtn2 = Async._registered[self.id](...) @@ -261,7 +261,6 @@ local empty_table = setmetatable({}, { --- Default status, will raise on_function_complete --- @param ... any The return value of the async call --- @return Async.Status, any[] ---- @type Async.Status function Async.status.complete(...) if ... == nil then return Async.status.complete, empty_table @@ -272,7 +271,6 @@ end --- Will queue the function to be called again on the next tick using the new arguments --- @param ... any The arguments to call the function with --- @return Async.Status, any[] ---- @type Async.Status function Async.status.continue(...) if ... == nil then return Async.status.continue, empty_table @@ -284,7 +282,6 @@ end --- @param ticks number The number of ticks to delay for --- @param ... any The arguments to call the function with --- @return Async.Status, number, any[] ---- @type Async.Status function Async.status.delay(ticks, ...) ExpUtil.assert_argument_type(ticks, "number", 1, "ticks") assert(ticks > 0, "Ticks must be a positive number") @@ -296,11 +293,11 @@ end --- Status Returns. ---- @type Async.AsyncReturn[], Async.AsyncReturn[] +--- @type Async.AsyncReturn[], Async.AsyncReturn[] local new_next, new_queue = {}, {} -- File scope to allow for reuse --- Executes an async function and processes the return value ---- @param pending Async.AsyncReturn +--- @param pending Async.AsyncReturn --- @param tick number local function exec(pending, tick) local async_func = Async._registered[pending.func_id] @@ -400,9 +397,9 @@ end --- @package function Async.on_init() if storage.exp_async_next == nil then - --- @type Async.AsyncReturn[] + --- @type Async.AsyncReturn[] storage.exp_async_next = {} - --- @type Async.AsyncReturn[] + --- @type Async.AsyncReturn[] storage.exp_async_queue = {} end Async.on_load() diff --git a/exp_util/module/flying_text.lua b/exp_util/module/flying_text.lua index f7ecaec3..180cd77e 100644 --- a/exp_util/module/flying_text.lua +++ b/exp_util/module/flying_text.lua @@ -42,12 +42,14 @@ end --- @param options FlyingText.create_above_entity_param function FlyingText.create_above_entity(options) local entity = assert(options.target_entity, "A target entity is required") - local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y + local bounding_box = entity.bounding_box + local size_y = bounding_box.left_top.y - bounding_box.right_bottom.y + local position = entity.position local offset = options.offset or { x = 0, y = 0 } options.position = { - x = offset.x + entity.position.x, - y = offset.y + entity.position.y + size_y * 0.25, + x = offset.x + position.x, + y = offset.y + position.y + size_y * 0.25, } FlyingText.create(options) @@ -62,12 +64,14 @@ end function FlyingText.create_above_player(options) local player = assert(options.target_player, "A target player is required") local entity = player.character; if not entity then return end - local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y + local bounding_box = entity.bounding_box + local size_y = bounding_box.left_top.y - bounding_box.right_bottom.y + local position = entity.position local offset = options.offset or { x = 0, y = 0 } options.position = { - x = offset.x + entity.position.x, - y = offset.y + entity.position.y + size_y * 0.25, + x = offset.x + position.x, + y = offset.y + position.y + size_y * 0.25, } FlyingText.create(options) @@ -82,13 +86,15 @@ end function FlyingText.create_as_player(options) local player = assert(options.target_player, "A target player is required") local entity = player.character; if not entity then return end - local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y + local bounding_box = entity.bounding_box + local size_y = bounding_box.left_top.y - bounding_box.right_bottom.y + local position = entity.position local offset = options.offset or { x = 0, y = 0 } options.color = player.chat_color options.position = { - x = offset.x + entity.position.x, - y = offset.y + entity.position.y + size_y * 0.25, + x = offset.x + position.x, + y = offset.y + position.y + size_y * 0.25, } FlyingText.create(options) diff --git a/exp_util/module/module_exports.lua b/exp_util/module/module_exports.lua index e6394bae..358c1706 100644 --- a/exp_util/module/module_exports.lua +++ b/exp_util/module/module_exports.lua @@ -92,7 +92,7 @@ local assert_argument_fmt = "Bad argument #%d to %s; %s expected to be of type % function ExpUtil.assert_argument_type(arg_value, type_name, arg_index, arg_name) local failed, actual_type = check_type(arg_value, type_name) if failed then - local func_name = getinfo(2, "n").name or "" + local func_name = assert(getinfo(2, "n")).name or "" error(assert_argument_fmt:format(arg_index, func_name, arg_name or "Argument", type_name, actual_type), 2) end end @@ -136,7 +136,7 @@ end --- @param level number? The level of the stack to get the file of, a value of 1 is the caller of this function --- @return string # The relative filepath of the given stack frame function ExpUtil.safe_file_path(level) - local debug_info = getinfo((level or 1) + 1, "Sn") + local debug_info = assert(getinfo((level or 1) + 1, "Sn")) local safe_source = debug_info.source:find("@__level__") return safe_source == 1 and debug_info.short_src:sub(10, -5) or debug_info.source end @@ -145,7 +145,7 @@ end --- @param level number? The level of the stack to get the module of, a value of 1 is the caller of this function --- @return string # The name of the module at the given stack frame function ExpUtil.get_module_name(level) - local file_within_module = getinfo((level or 1) + 1, "S").short_src:sub(19, -5) + local file_within_module = assert(getinfo((level or 1) + 1, "S")).short_src:sub(19, -5) local next_slash = file_within_module:find("/") if next_slash then return file_within_module:sub(1, next_slash - 1) @@ -159,7 +159,7 @@ end --- @param raw boolean? When true there will not be any < > around the name --- @return string # The name of the function at the given stack frame or provided as an argument function ExpUtil.get_function_name(func, raw) - local debug_info = getinfo(func, "Sn") + local debug_info = assert(getinfo(func, "Sn")) local safe_source = debug_info.source:find("@__level__") local file_name = safe_source == 1 and debug_info.source:sub(12, -5) or debug_info.source local func_name = debug_info.name or debug_info.linedefined @@ -172,7 +172,7 @@ end --- @param raw boolean? When true there will not be any < > around the name --- @return string # The relative filepath of the given stack frame function ExpUtil.get_current_line(level, raw) - local debug_info = getinfo((level or 1) + 1, "Snl") + local debug_info = assert(getinfo((level or 1) + 1, "Snl")) local safe_source = debug_info.source:find("@__level__") local file_path = safe_source == 1 and debug_info.short_src:sub(10, -5) or debug_info.source if raw then return file_path .. ":" .. debug_info.currentline end @@ -207,7 +207,7 @@ end function ExpUtil.auto_complete(options, input, use_key, rtn_key, use_pattern) input = input:lower() local plain = use_pattern ~= true - local found = {} --- @type { length: number, index: number, start: boolean, value: any } + local found = {} --- @type { length: number?, index: number?, start: boolean?, value: any } for k, v in pairs(options) do local str = use_key and k or v local index = str:lower():find(input, nil, plain) @@ -284,7 +284,7 @@ function ExpUtil.format_any(value, options) end return inspect(value, { depth = options.depth or 5, indent = "", newline = "", process = ExpUtil.safe_value }) end - return formatted + return formatted --[[@as LocalisedString]] end --- @alias Common.format_time_param_format "short" | "long" | "clock" @@ -319,15 +319,15 @@ function ExpUtil.extract_time_units(ticks, units) -- Remove units that are not requested if not units.days then - rtn.hours = rtn.hours + rtn.days * 24 + rtn.hours = assert(rtn.hours) + assert(rtn.days) * 24 rtn.days = nil end if not units.hours then - rtn.minutes = rtn.minutes + rtn.hours * 60 + rtn.minutes = assert(rtn.minutes) + assert(rtn.hours) * 60 rtn.hours = nil end if not units.minutes then - rtn.seconds = rtn.seconds + rtn.minutes * 60 + rtn.seconds = assert(rtn.seconds) + assert(rtn.minutes) * 60 rtn.minutes = nil end if not units.seconds then @@ -487,7 +487,7 @@ function ExpUtil.get_storage_for_stack(options) -- Find a valid entity from the search results local current, count, entities = cache.current, cache.count, cache.entities for i = 1, cache.count do - local entity = entities[((current + i - 1) % count) + 1] + local entity = assert(entities[((current + i - 1) % count) + 1]) if entity.can_insert(item) then cache.current = current + 1 return entity @@ -522,7 +522,7 @@ end --- Insert a copy of the given items into the found entities. If no entities are found then they will be created if possible. --- @param options Common.copy_items_to_surface_param ---- @return LuaEntity # The last entity inserted into +--- @return LuaEntity? # The last entity inserted into, nil if there were no items function ExpUtil.copy_items_to_surface(options) local entity for item_index = 1, #options.items do @@ -542,7 +542,7 @@ end --- Insert a copy of the given items into the found entities. If no entities are found then they will be created if possible. --- @param options Common.move_items_to_surface_param ---- @return LuaEntity # The last entity inserted into +--- @return LuaEntity? # The last entity inserted into, nil if there were no items function ExpUtil.move_items_to_surface(options) local entity for item_index = 1, #options.items do @@ -551,7 +551,8 @@ function ExpUtil.move_items_to_surface(options) options.item = item entity = ExpUtil.get_storage_for_stack(options) entity.insert(options.item) - options.item.clear() + local item_stack = options.item --[[@as LuaItemStack]] + item_stack.clear() end end return entity @@ -563,7 +564,7 @@ end --- Move the given inventory into the found entities. If no entities are found then they will be created if possible. --- @param options Common.transfer_inventory_to_surface_param ---- @return LuaEntity # The last entity inserted into +--- @return LuaEntity? # The last entity inserted into, nil if there were no items function ExpUtil.transfer_inventory_to_surface(options) options.items = options.inventory local entity = ExpUtil.copy_items_to_surface(options) @@ -604,6 +605,7 @@ end --- @return string function ExpUtil.comma_value(n) -- credit http://richard.warburton.it local left, num, right = string.match(n, "^([^%d]*%d)(%d*)(.-)$") + assert(left and num and right) return left .. (num:reverse():gsub("(%d%d%d)", "%1, "):reverse()) .. right end diff --git a/exp_util/module/selection.lua b/exp_util/module/selection.lua index a50a7940..461963f6 100644 --- a/exp_util/module/selection.lua +++ b/exp_util/module/selection.lua @@ -23,7 +23,7 @@ local Selection = { --- @field player_index number --- @field selection Selection.Active - --- @type table + --- @type table[] }> _registered = {}, --- @package @@ -54,7 +54,7 @@ local selection_tool = { name = "selection-tool" } --- @param player LuaPlayer --- @return boolean? local function has_selection_tool_in_hand(player) - return player.cursor_stack and player.cursor_stack.valid_for_read and player.cursor_stack.name == "selection-tool" + return assert(player.cursor_stack) and assert(player.cursor_stack).valid_for_read and assert(player.cursor_stack).name == "selection-tool" end --- Give a selection tool to a player if they don't have one @@ -62,7 +62,7 @@ end local function give_selection_tool(player) if has_selection_tool_in_hand(player) then return end player.clear_cursor() - player.cursor_stack.set_stack(selection_tool) + assert(player.cursor_stack).set_stack(selection_tool) -- This does not work for selection planners, will make a feature request for it --player.cursor_stack_temporary = true @@ -84,7 +84,7 @@ end local function remove_selection_tool(player, old_character) -- Remove the selection tool if has_selection_tool_in_hand(player) then - player.cursor_stack.clear() + assert(player.cursor_stack).clear() else player.remove_item(selection_tool) end diff --git a/type.patch.lua b/type.patch.lua index 38c854d7..191d59d8 100644 --- a/type.patch.lua +++ b/type.patch.lua @@ -1,39 +1,8 @@ ----@meta - ----@class script -script = { - ---Raise an event. Only events generated with [LuaBootstrap::generate\_event\_name](https://lua-api.factorio.com/latest/classes/LuaBootstrap.html#generate_event_name) and the following can be raised: - --- - ---Events that can be raised manually: - --- - ---* [on\_console\_chat](https://lua-api.factorio.com/latest/events.html#on_console_chat) - ---* [on\_player\_crafted\_item](https://lua-api.factorio.com/latest/events.html#on_player_crafted_item) - ---* [on\_player\_fast\_transferred](https://lua-api.factorio.com/latest/events.html#on_player_fast_transferred) - ---* [on\_biter\_base\_built](https://lua-api.factorio.com/latest/events.html#on_biter_base_built) - ---* [on\_market\_item\_purchased](https://lua-api.factorio.com/latest/events.html#on_market_item_purchased) - ---* [script\_raised\_built](https://lua-api.factorio.com/latest/events.html#script_raised_built) - ---* [script\_raised\_destroy](https://lua-api.factorio.com/latest/events.html#script_raised_destroy) - ---* [script\_raised\_revive](https://lua-api.factorio.com/latest/events.html#script_raised_revive) - ---* [script\_raised\_teleported](https://lua-api.factorio.com/latest/events.html#script_raised_teleported) - ---* [script\_raised\_set\_tiles](https://lua-api.factorio.com/latest/events.html#script_raised_set_tiles) - --- - ---### Example - --- - ---``` - ----- Raise the on_console_chat event with the desired message 'from' the first player - ---local data = {player_index = 1, message = "Hello friends!"} - ---script.raise_event(defines.events.on_console_chat, data) - ---``` - --- - ---[View Documentation](https://lua-api.factorio.com/latest/classes/LuaBootstrap.html#raise_event) - --- - --- Type patched in 2.0.28: [Bug Report](https://forums.factorio.com/viewtopic.php?f=233&t=125062) - --- Changed "event" from "string | integer" to "LuaEventType" - --- Resolved in 2.0.29, this patch will be removed was version is stable - ---@param event LuaEventType ID or name of the event to raise. - ---@param data table Table with extra data that will be passed to the event handler. Any invalid LuaObjects will silently stop the event from being raised. - raise_event = function(event, data) end; -} - ----@class LuaObject:userdata ---https://github.com/justarandomgeek/vscode-factoriomod-debug/issues/165 +---@meta + +--- The api documents MapPosition and BoundingBox as a union of the named form +--- and a positional array, because both are accepted as input. Everything read +--- back from the game uses the named form, and we always write it that way too, +--- so the positional variant is removed here. +---@alias MapPosition MapPosition.struct +---@alias BoundingBox BoundingBox.struct