mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-08-12 16:35:11 +09:00
Merge pull request #450 from bbassie/feature/emmylua-lint
Migrate the lua lint from luals to emmylua
This commit is contained in:
@@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
+46
-28
@@ -1,76 +1,94 @@
|
|||||||
name: FMTK Lint
|
name: Lua Lint
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
EMMYLUA_CHECK_VERSION: "0.24.0"
|
||||||
|
CLUSTERIO: ${{ github.workspace }}/.clusterio
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- 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
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 10
|
version: 10
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: lts/*
|
node-version: lts/*
|
||||||
- name: Install FMTK
|
- name: Generate Factorio typedefs
|
||||||
run: |
|
run: |
|
||||||
# Pinned: 2.1.4+ generates typedefs targeting EmmyLua that LuaLS misreads
|
pnpm install factoriomod-debug
|
||||||
pnpm install factoriomod-debug@2.1.3
|
pnpm exec fmtk luals-addon "$RUNNER_TEMP"
|
||||||
pnpm exec fmtk luals-addon
|
- name: Install emmylua_check
|
||||||
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: |
|
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
|
curl -fsSL "https://github.com/EmmyLuaLs/emmylua-analyzer-rust/releases/download/${EMMYLUA_CHECK_VERSION}/emmylua_check-linux-x64.tar.gz" \
|
||||||
mkdir luals && tar -xf lusls.tar.gz -C luals && rm lusls.tar.gz
|
| tar -xz -C "$RUNNER_TEMP"
|
||||||
- name: Run Lint Report
|
- name: Run Lint Report
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
./luals/bin/lua-language-server --check=. --logpath=. --configpath=check.luarc.json --checklevel=Information --check_out_path=check.json
|
# 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
|
# Credit to https://github.com/Krealle/luals-check-action/blob/main/action.yml
|
||||||
# Although some minor fixes were needed
|
# 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)
|
# 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 --arg root "$PWD/" \
|
||||||
jq -r \
|
'.[] | (.file | ltrimstr($root)) as $file | .diagnostics[] |
|
||||||
'to_entries | map(.key as $file | .value[] |
|
|
||||||
{
|
{
|
||||||
file: $file | sub("file://${{ github.workspace }}/./"; ""),
|
file: $file,
|
||||||
code: .code,
|
code: .code,
|
||||||
line: .range.start.line,
|
line: .range.start.line,
|
||||||
message: (.message | split("\n")
|
message: (.message | split("\n")
|
||||||
| map(if startswith("- ") then .[2:] else . end)
|
| map(if startswith("- ") then .[2:] else . end)
|
||||||
| join("\n")),
|
| join("\n")),
|
||||||
severity: (if .severity <= 1 then "ERR" else "WARN" end)
|
severity: (if .severity <= 1 then "ERR" else "WARN" end)
|
||||||
}) |
|
} |
|
||||||
map("**[\(.severity)] \(.code):** \(.file)#L\(.line)<br><code>\(.message)</code>") | .[]' \
|
"**[\(.severity)] \(.code):** \(.file)#L\(.line + 1)<br><code>\(.message)</code>"' \
|
||||||
> $GITHUB_STEP_SUMMARY
|
check.json > "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Github Annotations (limited to 10)
|
# Github Annotations (limited to 10)
|
||||||
cat check.json | \
|
jq -r --arg root "$PWD/" \
|
||||||
jq -r \
|
'.[] | (.file | ltrimstr($root)) as $file | .diagnostics[] |
|
||||||
'to_entries | map(.key as $file | .value[] |
|
|
||||||
{
|
{
|
||||||
file: $file | sub("file://${{ github.workspace }}/./"; ""),
|
file: $file,
|
||||||
title: .code,
|
title: .code,
|
||||||
line: .range.start.line,
|
line: .range.start.line,
|
||||||
endLine: .range.end.line,
|
endLine: .range.end.line,
|
||||||
col: .range.start.character,
|
col: .range.start.character,
|
||||||
endColumn: .range.end.character,
|
endColumn: .range.end.character,
|
||||||
message: .message | gsub("\n"; "%0A"; "m"),
|
message: (.message | gsub("\n"; "%0A"; "m")),
|
||||||
level: (if .severity <= 1 then "error" else "warning" end)
|
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))") | .[]'
|
"::\(.level) file=\(.file),line=\(.line + 1),endLine=\(.endLine + 1),col=\(.col + 1),endColumn=\(.endColumn + 1),title=\(.title)::\(.message) (\(.title))"' \
|
||||||
|
check.json
|
||||||
|
|
||||||
if [[ $(wc -l < check.json) > 1 ]] ; then
|
# 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
|
exit 1
|
||||||
else
|
else
|
||||||
echo "✅ All checks succeeded!" | tee $GITHUB_STEP_SUMMARY
|
echo "✅ All checks succeeded!" | tee "$GITHUB_STEP_SUMMARY"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
dist/
|
dist/
|
||||||
node_modules/
|
node_modules/
|
||||||
.vscode
|
.vscode
|
||||||
|
.luarc.json
|
||||||
|
|||||||
-103
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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:
|
For developers wanting to add features please follow these guidelines:
|
||||||
|
|
||||||
- All lua code is documented using ldoc.
|
- 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.
|
- 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.
|
- 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.
|
- Pull requests are automatically linted and documentation checked.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ The default permission authorities controlled by the flags: admin_only, system_o
|
|||||||
|
|
||||||
local Storage = require("modules/exp_util/storage")
|
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 add, allow, deny = Commands.add_permission_authority, Commands.status.success, Commands.status.unauthorised
|
||||||
|
|
||||||
local authorities = {}
|
local authorities = {}
|
||||||
@@ -28,13 +28,13 @@ end)
|
|||||||
--- Allow a player access to system commands, use for debug purposes only
|
--- 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
|
--- @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)
|
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
|
end
|
||||||
|
|
||||||
--- Remove access from system commands for a player, use for debug purposes only
|
--- 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
|
--- @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)
|
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
|
end
|
||||||
|
|
||||||
--- Get a list of all players who have system commands unlocked
|
--- Get a list of all players who have system commands unlocked
|
||||||
|
|||||||
@@ -25,18 +25,18 @@ end)
|
|||||||
--- @param page_size number The number of requests to show per page
|
--- @param page_size number The number of requests to show per page
|
||||||
--- @return LocalisedString[][], number
|
--- @return LocalisedString[][], number
|
||||||
local function format_as_pages(commands, page_size)
|
local function format_as_pages(commands, page_size)
|
||||||
local pages = { {} }
|
local current_page = {}
|
||||||
|
local pages = { current_page }
|
||||||
local page_length = 0
|
local page_length = 0
|
||||||
local current_page = 1
|
|
||||||
local total = 0
|
local total = 0
|
||||||
|
|
||||||
for _, command in pairs(commands) do
|
for _, command in pairs(commands) do
|
||||||
total = total + 1
|
total = total + 1
|
||||||
page_length = page_length + 1
|
page_length = page_length + 1
|
||||||
if page_length > page_size then
|
if page_length > page_size then
|
||||||
current_page = current_page + 1
|
|
||||||
pages[current_page] = {}
|
|
||||||
page_length = 1
|
page_length = 1
|
||||||
|
current_page = {}
|
||||||
|
pages[#pages + 1] = current_page
|
||||||
end
|
end
|
||||||
|
|
||||||
local description
|
local description
|
||||||
@@ -48,7 +48,7 @@ local function format_as_pages(commands, page_size)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local aliases = #command.aliases > 0 and { "exp-commands_help.aliases", table.concat(command.aliases, ", ") } or ""
|
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
|
end
|
||||||
|
|
||||||
return pages, total
|
return pages, total
|
||||||
@@ -71,7 +71,7 @@ Commands.new("commands", { "exp-commands_help.description" })
|
|||||||
page = as_number
|
page = as_number
|
||||||
end
|
end
|
||||||
|
|
||||||
keyword = keyword:lower()
|
keyword = tostring(keyword):lower()
|
||||||
local pages, found
|
local pages, found
|
||||||
if cache and cache.keyword == keyword then
|
if cache and cache.keyword == keyword then
|
||||||
-- Cached value found, no search is needed
|
-- Cached value found, no search is needed
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ local ExpUtil = require("modules/exp_util")
|
|||||||
local Async = require("modules/exp_util/async")
|
local Async = require("modules/exp_util/async")
|
||||||
local Storage = require("modules/exp_util/storage")
|
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<string, any>
|
local rcon_env = {} --- @type table<string, any>
|
||||||
local rcon_static = {} --- @type table<string, any>
|
local rcon_static = {} --- @type table<string, any>
|
||||||
@@ -21,12 +21,10 @@ setmetatable(rcon_static, { __index = _G })
|
|||||||
setmetatable(rcon_env, { __index = rcon_static })
|
setmetatable(rcon_env, { __index = rcon_static })
|
||||||
|
|
||||||
--- Some common static values which can be added now
|
--- Some common static values which can be added now
|
||||||
--- @diagnostic disable: name-style-check
|
|
||||||
rcon_static.Async = Async
|
rcon_static.Async = Async
|
||||||
rcon_static.ExpUtil = ExpUtil
|
rcon_static.ExpUtil = ExpUtil
|
||||||
rcon_static.Commands = Commands
|
rcon_static.Commands = Commands
|
||||||
rcon_static.print = Commands.print
|
rcon_static.print = Commands.print
|
||||||
--- @diagnostic enable: name-style-check
|
|
||||||
|
|
||||||
--- Some common callback values which are useful when a player uses the command
|
--- Some common callback values which are useful when a player uses the command
|
||||||
--- @alias ExpCommand.RconDynamic fun(player: LuaPlayer?): any
|
--- @alias ExpCommand.RconDynamic fun(player: LuaPlayer?): any
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Commands.new("_sudo", { "exp-commands_sudo.description" })
|
|||||||
--- @cast command ExpCommand
|
--- @cast command ExpCommand
|
||||||
--- @cast parameter string
|
--- @cast parameter string
|
||||||
|
|
||||||
--- @diagnostic disable-next-line: invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
return Commands._event_handler{
|
return Commands._event_handler{
|
||||||
name = command.name,
|
name = command.name,
|
||||||
tick = game.tick,
|
tick = game.tick,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ local Commands = require("modules/exp_commands")
|
|||||||
local add, parse = Commands.add_data_type, Commands.parse_input
|
local add, parse = Commands.add_data_type, Commands.parse_input
|
||||||
local valid, invalid = Commands.status.success, Commands.status.invalid_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
|
--- A boolean value where true is one of: yes, y, true, 1
|
||||||
types.boolean =
|
types.boolean =
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ local Search = require("modules/exp_commands/search")
|
|||||||
--- @type LuaPlayer?
|
--- @type LuaPlayer?
|
||||||
local _print_player
|
local _print_player
|
||||||
|
|
||||||
--- @class Commands
|
--- @class (partial) Commands
|
||||||
local Commands = {
|
local Commands = {
|
||||||
color = ExpUtil.color,
|
color = ExpUtil.color,
|
||||||
format_rich_text_color = ExpUtil.format_rich_text_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
|
--- Contains the different status values a command can return
|
||||||
Commands.status = {}
|
Commands.status = {}
|
||||||
|
|
||||||
--- @class Commands.types: table<string, Commands.InputParser | Commands.InputParserFactory>
|
--- @class (partial) Commands.types: table<string, Commands.InputParser<any> | Commands.InputParserFactory<any>>
|
||||||
--- Stores all input parsers and validators for different data types
|
--- Stores all input parsers and validators for different data types
|
||||||
Commands.types = {}
|
Commands.types = {}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ end
|
|||||||
--- @class Commands.Argument
|
--- @class Commands.Argument
|
||||||
--- @field name string The name of the argument
|
--- @field name string The name of the argument
|
||||||
--- @field description LocalisedString? The description 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<any> The input parser for the argument
|
||||||
--- @field optional boolean True when the argument is optional
|
--- @field optional boolean True when the argument is optional
|
||||||
--- @field default any? The default value of the argument
|
--- @field default any? The default value of the argument
|
||||||
|
|
||||||
@@ -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)
|
--- @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
|
--- @return Commands.Status, LocalisedString # Should be returned directly without modification
|
||||||
function Commands.status.success(msg)
|
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
|
end
|
||||||
|
|
||||||
--- Used to signal an error has occurred in a command, data type parser, or permission authority
|
--- 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
|
--- @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
|
--- @return Commands.Status, LocalisedString # Should be returned directly without modification
|
||||||
function Commands.status.error(msg)
|
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
|
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
|
--- 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
|
--- @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
|
--- @return Commands.Status, LocalisedString # Should be returned directly without modification
|
||||||
function Commands.status.unauthorised(msg)
|
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
|
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
|
--- 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
|
--- @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
|
--- @return Commands.Status, LocalisedString # Should be returned directly without modification
|
||||||
function Commands.status.invalid_input(msg)
|
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
|
end
|
||||||
|
|
||||||
--- Used to signal an internal error has occurred, this is reserved for internal use only
|
--- 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
|
--- @return Commands.Status, LocalisedString # Should be returned directly without modification
|
||||||
--- @package
|
--- @package
|
||||||
function Commands.status.internal_error(msg)
|
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
|
end
|
||||||
|
|
||||||
--- @type table<Commands.Status, string>
|
--- @type table<Commands.Status, string>
|
||||||
@@ -281,7 +285,7 @@ end
|
|||||||
--- @alias Commands.InputParserFactory<T> fun(...: any): Commands.InputParser<T>
|
--- @alias Commands.InputParserFactory<T> fun(...: any): Commands.InputParser<T>
|
||||||
|
|
||||||
--- Add a new input parser to the command library, this method validates that it does not already exist
|
--- 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<any> | Commands.InputParserFactory<any>
|
||||||
--- @param data_type string The name of the data type the input parser reads in and validates, becomes a key of Commands.types
|
--- @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
|
--- @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
|
--- @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
|
end
|
||||||
|
|
||||||
--- Remove an input parser for a data type, must be the same string that was passed to add_input_parser
|
--- 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<any> | Commands.InputParserFactory<any> The data type or input parser you want to remove the input parser for
|
||||||
function Commands.remove_data_type(data_type)
|
function Commands.remove_data_type(data_type)
|
||||||
Commands.types[data_type] = nil
|
Commands.types[data_type] = nil
|
||||||
for k, v in pairs(Commands.types) do
|
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
|
--- Add a new required argument to the command of the given data type
|
||||||
--- @param name string The name of the argument being added
|
--- @param name string The name of the argument being added
|
||||||
--- @param description LocalisedString? The description 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<any> The input parser to be used for the argument
|
||||||
--- @return ExpCommand
|
--- @return ExpCommand
|
||||||
function Commands._prototype:argument(name, description, input_parser)
|
function Commands._prototype:argument(name, description, input_parser)
|
||||||
assert_command_mutable(self)
|
assert_command_mutable(self)
|
||||||
@@ -454,7 +458,7 @@ end
|
|||||||
--- Add a new optional argument to the command of the given data type
|
--- Add a new optional argument to the command of the given data type
|
||||||
--- @param name string The name of the argument being added
|
--- @param name string The name of the argument being added
|
||||||
--- @param description LocalisedString? The description 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<any> The input parser to be used for the argument
|
||||||
--- @return ExpCommand
|
--- @return ExpCommand
|
||||||
function Commands._prototype:optional(name, description, input_parser)
|
function Commands._prototype:optional(name, description, input_parser)
|
||||||
assert_command_mutable(self)
|
assert_command_mutable(self)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ local Search = {}
|
|||||||
local Storage = require("modules/exp_util/storage")
|
local Storage = require("modules/exp_util/storage")
|
||||||
|
|
||||||
--- Setup the storage to contain the pending translations and the completed ones
|
--- Setup the storage to contain the pending translations and the completed ones
|
||||||
local pending = {} --- @type { [1]: string, [2]: string }[]
|
local pending = {} --- @type table<uint, [string, string]>
|
||||||
local translations = {} --- @type table<string, table<string, string>>
|
local translations = {} --- @type table<string, table<string, string>>
|
||||||
Storage.register({
|
Storage.register({
|
||||||
pending,
|
pending,
|
||||||
@@ -50,6 +50,7 @@ function Search.prepare(custom_commands)
|
|||||||
name = name,
|
name = name,
|
||||||
description = locale_desc,
|
description = locale_desc,
|
||||||
help_text = locale_desc,
|
help_text = locale_desc,
|
||||||
|
usage = locale_desc,
|
||||||
aliases = {},
|
aliases = {},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -65,7 +66,7 @@ function Search.on_player_locale_changed(event)
|
|||||||
local ids = player.request_translations(required_translations)
|
local ids = player.request_translations(required_translations)
|
||||||
assert(ids, "Translation ids was nil")
|
assert(ids, "Translation ids was nil")
|
||||||
for i, command_name in ipairs(command_names) do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Adds permission group syncing to clusterio
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local clusterio_api = require("modules/clusterio/api")
|
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
|
--- Top level module table, contains event handlers and public methods
|
||||||
--- @class ExpGroups
|
--- @class ExpGroups
|
||||||
|
|||||||
@@ -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
|
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()`
|
-- Access using `/sc exp_groups.foo()`
|
||||||
exp_groups = require("modules/exp_groups/control")
|
exp_groups = require("modules/exp_groups/control")
|
||||||
|
|||||||
+17
-12
@@ -16,7 +16,7 @@ Storage.register(player_elements, function(tbl)
|
|||||||
player_elements = tbl
|
player_elements = tbl
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--- @class Gui
|
--- @class (partial) Gui
|
||||||
local Gui = {
|
local Gui = {
|
||||||
define = ExpElement.new,
|
define = ExpElement.new,
|
||||||
from_argument = ExpElement.from_argument,
|
from_argument = ExpElement.from_argument,
|
||||||
@@ -46,9 +46,11 @@ end
|
|||||||
--- @return LuaPlayer
|
--- @return LuaPlayer
|
||||||
function Gui.get_player(input)
|
function Gui.get_player(input)
|
||||||
if type(input) == "table" and not input.player_index then
|
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
|
end
|
||||||
return assert(game.get_player(input.player_index))
|
--- @cast input LuaGuiElement | { player_index: uint }
|
||||||
|
return (assert(game.get_player(input.player_index)))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Toggle the enable state of an element
|
--- Toggle the enable state of an element
|
||||||
@@ -88,7 +90,7 @@ end
|
|||||||
--- @param define ExpElement
|
--- @param define ExpElement
|
||||||
--- @param visible Gui.VisibleCallback | boolean | nil
|
--- @param visible Gui.VisibleCallback | boolean | nil
|
||||||
function Gui.add_top_element(define, visible)
|
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
|
Gui.top_elements[define] = visible or false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -96,7 +98,7 @@ end
|
|||||||
--- @param define ExpElement
|
--- @param define ExpElement
|
||||||
--- @param visible Gui.VisibleCallback | boolean | nil
|
--- @param visible Gui.VisibleCallback | boolean | nil
|
||||||
function Gui.add_left_element(define, visible)
|
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
|
Gui.left_elements[define] = visible or false
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -105,7 +107,7 @@ end
|
|||||||
--- @param define ExpElement
|
--- @param define ExpElement
|
||||||
--- @param visible Gui.VisibleCallback | boolean | nil
|
--- @param visible Gui.VisibleCallback | boolean | nil
|
||||||
function Gui.add_relative_element(define, visible)
|
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
|
Gui.relative_elements[define] = visible or false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -114,7 +116,8 @@ end
|
|||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function Gui.get_top_element(define, player)
|
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
|
end
|
||||||
|
|
||||||
--- Register a element define to be drawn to the left flow on join
|
--- Register a element define to be drawn to the left flow on join
|
||||||
@@ -122,7 +125,8 @@ end
|
|||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function Gui.get_left_element(define, player)
|
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
|
end
|
||||||
|
|
||||||
--- Register a element define to be drawn to the relative flow on join
|
--- Register a element define to be drawn to the relative flow on join
|
||||||
@@ -130,7 +134,8 @@ end
|
|||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function Gui.get_relative_element(define, player)
|
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
|
end
|
||||||
|
|
||||||
--- Ensure all the correct elements are visible and exist
|
--- 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
|
-- This check isn't needed, but allows the toolbar file to be deleted without modifying any lib code
|
||||||
if Gui.toolbar then
|
if Gui.toolbar then
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
Gui.toolbar._create_elements(player)
|
Gui.toolbar._create_elements(player)
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
Gui.toolbar._ensure_consistency(player)
|
Gui.toolbar._ensure_consistency(player)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -211,7 +216,7 @@ local function on_gui_opened(event)
|
|||||||
|
|
||||||
if visible then
|
if visible then
|
||||||
event.element = element
|
event.element = element
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
define:raise_event(event)
|
define:raise_event(event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ local GuiData = {
|
|||||||
--- @field player_data table<uint, any>
|
--- @field player_data table<uint, any>
|
||||||
--- @field force_data table<uint, any>
|
--- @field force_data table<uint, any>
|
||||||
--- @field global_data table
|
--- @field global_data table
|
||||||
|
--- @field [DataKey] any
|
||||||
-- This class has no prototype methods
|
-- This class has no prototype methods
|
||||||
-- Same as raw but __index ensures the values exist
|
-- 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.")
|
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
|
local object_name = key.object_name --- @diagnostic disable-line assign-type-mismatch
|
||||||
if object_name == "LuaGuiElement" then
|
if object_name == "LuaGuiElement" then
|
||||||
|
--- @cast key LuaGuiElement
|
||||||
local data = self._raw.element_data
|
local data = self._raw.element_data
|
||||||
local player_elements = data and data[key.player_index]
|
local player_elements = data and data[key.player_index]
|
||||||
return player_elements and player_elements[key.index]
|
return player_elements and player_elements[key.index]
|
||||||
elseif object_name == "LuaPlayer" then
|
elseif object_name == "LuaPlayer" then
|
||||||
|
--- @cast key LuaPlayer
|
||||||
local data = self._raw.player_data
|
local data = self._raw.player_data
|
||||||
return data and data[key.index]
|
return data and data[key.index]
|
||||||
elseif object_name == "LuaForce" then
|
elseif object_name == "LuaForce" then
|
||||||
|
--- @cast key LuaForce
|
||||||
local data = self._raw.force_data
|
local data = self._raw.force_data
|
||||||
return data and data[key.index]
|
return data and data[key.index]
|
||||||
else
|
else
|
||||||
@@ -168,7 +172,7 @@ local function on_object_destroyed(event)
|
|||||||
for _, scope in pairs(registered_scopes) do
|
for _, scope in pairs(registered_scopes) do
|
||||||
local data = scope._raw.element_data
|
local data = scope._raw.element_data
|
||||||
local player_elements = data and data[player_index]
|
local player_elements = data and data[player_index]
|
||||||
if player_elements then
|
if data and player_elements then
|
||||||
player_elements[element_index] = nil
|
player_elements[element_index] = nil
|
||||||
if not next(player_elements) then
|
if not next(player_elements) then
|
||||||
data[player_index] = nil
|
data[player_index] = nil
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- @class Gui
|
--- @class (partial) Gui
|
||||||
local Gui = require("modules/exp_gui")
|
local Gui = require("modules/exp_gui")
|
||||||
|
|
||||||
--- @class Gui.elements
|
--- @class Gui.elements
|
||||||
@@ -52,7 +52,7 @@ Elements.bar = Gui.define("bar")
|
|||||||
|
|
||||||
--- A label which is centered
|
--- A label which is centered
|
||||||
--- @class Gui.elements.centered_label: ExpElement
|
--- @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")
|
Elements.centered_label = Gui.define("centered_label")
|
||||||
:draw{
|
:draw{
|
||||||
type = "label",
|
type = "label",
|
||||||
@@ -165,7 +165,7 @@ Elements.container = Gui.define("container")
|
|||||||
--- @param container LuaGuiElement
|
--- @param container LuaGuiElement
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function Elements.container.get_root_element(container)
|
function Elements.container.get_root_element(container)
|
||||||
return container.parent
|
return assert(container.parent)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- A frame within a container
|
--- A frame within a container
|
||||||
@@ -319,14 +319,14 @@ Elements.screen_frame = Gui.define("screen_frame")
|
|||||||
--- @param screen_frame LuaGuiElement
|
--- @param screen_frame LuaGuiElement
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function Elements.screen_frame.get_button_flow(screen_frame)
|
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
|
end
|
||||||
|
|
||||||
--- Get the root element of a screen frame
|
--- Get the root element of a screen frame
|
||||||
--- @param screen_frame LuaGuiElement
|
--- @param screen_frame LuaGuiElement
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function Elements.screen_frame.get_root_element(screen_frame)
|
function Elements.screen_frame.get_root_element(screen_frame)
|
||||||
return screen_frame.parent
|
return assert(screen_frame.parent)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Elements
|
return Elements
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ end
|
|||||||
function GuiIter.get_tracked_elements(scope, filter)
|
function GuiIter.get_tracked_elements(scope, filter)
|
||||||
local class_name = ExpUtil.get_class_name(filter)
|
local class_name = ExpUtil.get_class_name(filter)
|
||||||
if class_name == "nil" then
|
if class_name == "nil" then
|
||||||
--- @cast filter nil
|
|
||||||
return GuiIter.all_elements(scope)
|
return GuiIter.all_elements(scope)
|
||||||
elseif class_name == "LuaPlayer" then
|
elseif class_name == "LuaPlayer" then
|
||||||
--- @cast filter LuaPlayer
|
--- @cast filter LuaPlayer
|
||||||
@@ -189,7 +188,6 @@ end
|
|||||||
function GuiIter.get_online_elements(scope, filter)
|
function GuiIter.get_online_elements(scope, filter)
|
||||||
local class_name = ExpUtil.get_class_name(filter)
|
local class_name = ExpUtil.get_class_name(filter)
|
||||||
if class_name == "nil" then
|
if class_name == "nil" then
|
||||||
--- @cast filter nil
|
|
||||||
return GuiIter.filtered_elements(scope, game.connected_players)
|
return GuiIter.filtered_elements(scope, game.connected_players)
|
||||||
elseif class_name == "LuaPlayer" then
|
elseif class_name == "LuaPlayer" then
|
||||||
--- @cast filter LuaPlayer
|
--- @cast filter LuaPlayer
|
||||||
@@ -235,7 +233,7 @@ end
|
|||||||
function GuiIter.remove_element(scope, player_index, element_index)
|
function GuiIter.remove_element(scope, player_index, element_index)
|
||||||
local scope_elements = registered_scopes[scope]
|
local scope_elements = registered_scopes[scope]
|
||||||
if not scope_elements then return end
|
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
|
if not player_elements then return end
|
||||||
player_elements[element_index] = nil
|
player_elements[element_index] = nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ ExpElement.events = {}
|
|||||||
--- @field _force_data ExpElement.PostDrawCallback?
|
--- @field _force_data ExpElement.PostDrawCallback?
|
||||||
--- @field _global_data ExpElement.PostDrawCallback?
|
--- @field _global_data ExpElement.PostDrawCallback?
|
||||||
--- @field _events table<defines.events, ExpElement.EventHandler<EventData>[]>
|
--- @field _events table<defines.events, ExpElement.EventHandler<EventData>[]>
|
||||||
|
--- @field _has_handlers boolean
|
||||||
|
--- @field _track_elements boolean
|
||||||
--- @overload fun(parent: LuaGuiElement, ...: any): LuaGuiElement
|
--- @overload fun(parent: LuaGuiElement, ...: any): LuaGuiElement
|
||||||
ExpElement._prototype = {
|
ExpElement._prototype = {
|
||||||
_track_elements = false,
|
_track_elements = false,
|
||||||
@@ -166,7 +168,7 @@ end
|
|||||||
--- @param name string
|
--- @param name string
|
||||||
--- @return ExpElement
|
--- @return ExpElement
|
||||||
function ExpElement.get(name)
|
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
|
end
|
||||||
|
|
||||||
--- Create a new instance of this element definition
|
--- Create a new instance of this element definition
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- @class Gui
|
--- @class (partial) Gui
|
||||||
local Gui = require("modules/exp_gui")
|
local Gui = require("modules/exp_gui")
|
||||||
|
|
||||||
--- @class Gui.styles
|
--- @class Gui.styles
|
||||||
|
|||||||
+13
-11
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
--- @class Gui
|
--- @class (partial) Gui
|
||||||
local Gui = require("modules/exp_gui")
|
local Gui = require("modules/exp_gui")
|
||||||
local ExpElement = require("modules/exp_gui/prototype")
|
local ExpElement = require("modules/exp_gui/prototype")
|
||||||
local mod_gui = require("mod-gui")
|
local mod_gui = require("mod-gui")
|
||||||
@@ -29,7 +29,7 @@ Toolbar.on_gui_button_toggled = script.generate_event_name()
|
|||||||
--- @class _ExpElement._prototype
|
--- @class _ExpElement._prototype
|
||||||
--- @field on_button_toggled ExpElement.OnEventAdder<EventData.on_gui_button_toggled>
|
--- @field on_button_toggled ExpElement.OnEventAdder<EventData.on_gui_button_toggled>
|
||||||
|
|
||||||
--- @diagnostic disable-next-line: invisible, inject-field
|
--- @diagnostic disable-next-line: access-invisible, inject-field
|
||||||
function ExpElement._prototype.on_button_toggled(self, handler)
|
function ExpElement._prototype.on_button_toggled(self, handler)
|
||||||
return self:on_event(Toolbar.on_gui_button_toggled, handler)
|
return self:on_event(Toolbar.on_gui_button_toggled, handler)
|
||||||
end
|
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
|
button.style = state and toolbar_button_active_style or toolbar_button_default_style
|
||||||
|
|
||||||
-- Make the extra required adjustments
|
-- Make the extra required adjustments
|
||||||
local style = button.style
|
local style = button.style --[[@as LuaStyle]]
|
||||||
style.minimal_width = original_width
|
style.minimal_width = original_width
|
||||||
style.maximal_height = original_height
|
style.maximal_height = original_height
|
||||||
if button.type == "sprite-button" then
|
if button.type == "sprite-button" then
|
||||||
@@ -335,9 +335,10 @@ Below here is the toolbar settings GUI and its associated functions
|
|||||||
--- @param dst LuaGuiElement
|
--- @param dst LuaGuiElement
|
||||||
local function copy_style(src, dst)
|
local function copy_style(src, dst)
|
||||||
dst.style = src.style.name
|
dst.style = src.style.name
|
||||||
dst.style.height = toolbar_button_small
|
local style = dst.style --[[@as LuaStyle]]
|
||||||
dst.style.width = toolbar_button_small
|
style.height = toolbar_button_small
|
||||||
dst.style.padding = -2
|
style.width = toolbar_button_small
|
||||||
|
style.padding = -2
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Reorder the buttons relative to each other, this will update the datastore
|
--- 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
|
-- Swap the position in the list
|
||||||
local list = assert(item.parent)
|
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)
|
list.swap_children(old_index, new_index)
|
||||||
|
|
||||||
-- Swap the position in the top flow, offset by 1 because of settings button
|
-- 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 other_element = Gui.get_left_element(other_left_element, player)
|
||||||
local left_index = element.get_index_in_parent()
|
local left_index = element.get_index_in_parent()
|
||||||
local other_index = other_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
|
end
|
||||||
|
|
||||||
-- If we are moving in/out of first/last place we need to update the move buttons
|
-- If we are moving in/out of first/last place we need to update the move buttons
|
||||||
@@ -499,7 +500,8 @@ function Toolbar._create_elements(player)
|
|||||||
-- Reset the state of the previous last child
|
-- Reset the state of the previous last child
|
||||||
local children = toolbar_list.children
|
local children = toolbar_list.children
|
||||||
if previous_last_index > 0 then
|
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
|
end
|
||||||
|
|
||||||
-- Set the state of the move buttons for the first and last element
|
-- Set the state of the move buttons for the first and last element
|
||||||
@@ -619,7 +621,7 @@ elements.move_item_up = Gui.define("move_item_up")
|
|||||||
size = toolbar_button_small,
|
size = toolbar_button_small,
|
||||||
})
|
})
|
||||||
:on_click(function(def, player, element)
|
: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)
|
move_toolbar_button(player, item, -1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -634,7 +636,7 @@ elements.move_item_down = Gui.define("move_item_down")
|
|||||||
size = toolbar_button_small,
|
size = toolbar_button_small,
|
||||||
})
|
})
|
||||||
:on_click(function(def, player, element)
|
: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)
|
move_toolbar_button(player, item, 1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ local afk_time_units = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
--- @type table<string, LocalisedString | fun(player: LuaPlayer, is_command: boolean): LocalisedString>
|
||||||
messages = { --- @setting messages will trigger when ever the word is said
|
messages = { --- @setting messages will trigger when ever the word is said
|
||||||
["discord"] = { "info.discord" },
|
["discord"] = { "info.discord" },
|
||||||
["expgaming"] = { "info.website" },
|
["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_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_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)
|
command_prefix = "!", --- @setting command_prefix prefix used for commands below and to print to all players (if enabled above)
|
||||||
|
--- @type table<string, LocalisedString | fun(player: LuaPlayer, is_command: boolean): LocalisedString>
|
||||||
commands = { --- @setting commands will trigger only when command prefix is given
|
commands = { --- @setting commands will trigger only when command prefix is given
|
||||||
["dev"] = { "exp_chat-auto-reply.reply-dev" },
|
["dev"] = { "exp_chat-auto-reply.reply-dev" },
|
||||||
["magic"] = { "exp_chat-auto-reply.reply-magic" },
|
["magic"] = { "exp_chat-auto-reply.reply-magic" },
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ local Colors = require("modules/exp_util/include/color")
|
|||||||
local format_player_name = ExpUtil.format_player_name_locale
|
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
|
--- 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)
|
local function set_accessors(player_getter, action_setter)
|
||||||
get_selected_player, set_selected_action = player_getter, action_setter
|
get_selected_player, set_selected_action = player_getter, action_setter
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ return {
|
|||||||
amount = 4000,
|
amount = 4000,
|
||||||
size = { 26, 27 },
|
size = { 26, 27 },
|
||||||
-- offset = {-64,-32}
|
-- offset = {-64,-32}
|
||||||
offset = { -64, -64 },
|
offset = { x = -64, y = -64 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled = false,
|
enabled = false,
|
||||||
@@ -196,7 +196,7 @@ return {
|
|||||||
amount = 4000,
|
amount = 4000,
|
||||||
size = { 26, 27 },
|
size = { 26, 27 },
|
||||||
-- offset = {-64, 0}
|
-- offset = {-64, 0}
|
||||||
offset = { 64, -64 },
|
offset = { x = 64, y = -64 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled = false,
|
enabled = false,
|
||||||
@@ -204,7 +204,7 @@ return {
|
|||||||
amount = 4000,
|
amount = 4000,
|
||||||
size = { 22, 20 },
|
size = { 22, 20 },
|
||||||
-- offset = {-64, 32}
|
-- offset = {-64, 32}
|
||||||
offset = { -64, 64 },
|
offset = { x = -64, y = 64 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled = false,
|
enabled = false,
|
||||||
@@ -212,7 +212,7 @@ return {
|
|||||||
amount = 4000,
|
amount = 4000,
|
||||||
size = { 22, 20 },
|
size = { 22, 20 },
|
||||||
-- offset = {-64, -64}
|
-- offset = {-64, -64}
|
||||||
offset = { 64, 64 },
|
offset = { x = 64, y = 64 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled = false,
|
enabled = false,
|
||||||
@@ -220,7 +220,7 @@ return {
|
|||||||
amount = 4000,
|
amount = 4000,
|
||||||
size = { 22, 20 },
|
size = { 22, 20 },
|
||||||
-- offset = {-64, -96}
|
-- offset = {-64, -96}
|
||||||
offset = { 0, 64 },
|
offset = { x = 0, y = 64 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -233,7 +233,7 @@ return {
|
|||||||
num_patches = 4,
|
num_patches = 4,
|
||||||
amount = 4000000,
|
amount = 4000000,
|
||||||
-- offset = {-80, -12},
|
-- offset = {-80, -12},
|
||||||
offset = { -12, 64 },
|
offset = { x = -12, y = 64 },
|
||||||
-- offset_next = {0, 6}
|
-- offset_next = {0, 6}
|
||||||
offset_next = { 6, 0 },
|
offset_next = { 6, 0 },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,6 +35,20 @@ return {
|
|||||||
storage_output = 1, -- >0 allows for item teleportation (allowed_items only)
|
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<string, Vlayer.ItemProperties>
|
||||||
allowed_items = { --- @setting allowed_items List of all items allowed in vlayer storage and their properties
|
allowed_items = { --- @setting allowed_items List of all items allowed in vlayer storage and their properties
|
||||||
--[[
|
--[[
|
||||||
Allowed properties:
|
Allowed properties:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
-- @config Warnings
|
-- @config Warnings
|
||||||
|
|
||||||
return {
|
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
|
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)
|
-- if a localized string is used then __1__ will by_player_name and __2__ will be the current warning count (auto inserted)
|
||||||
{ "warnings.received", "" },
|
{ "warnings.received", "" },
|
||||||
|
|||||||
@@ -149,9 +149,23 @@ PlayerData.Statistics:combine('JoinCount')
|
|||||||
local Storage = require("modules/exp_util/storage")
|
local Storage = require("modules/exp_util/storage")
|
||||||
|
|
||||||
local DatastoreManager = {}
|
local DatastoreManager = {}
|
||||||
local Datastores = {}
|
local Datastores = {} --- @type table<string, Datastore>
|
||||||
local Datastore = {}
|
|
||||||
local Data = {}
|
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<string, Datastore>
|
||||||
|
--- @field metadata table
|
||||||
|
--- @field events table<string, function[]>
|
||||||
|
--- @field data table
|
||||||
|
local Datastore = {}
|
||||||
|
|
||||||
local copy = table.deep_copy
|
local copy = table.deep_copy
|
||||||
local trace = debug.traceback
|
local trace = debug.traceback
|
||||||
local table_to_json = helpers.table_to_json
|
local table_to_json = helpers.table_to_json
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ end
|
|||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local ext, var
|
local ext --- @type table<string, any>
|
||||||
|
local var --- @type table<string, any>
|
||||||
local concat = table.concat
|
local concat = table.concat
|
||||||
|
|
||||||
local External = {}
|
local External = {}
|
||||||
@@ -29,12 +30,13 @@ end
|
|||||||
|
|
||||||
]]
|
]]
|
||||||
function External.valid()
|
function External.valid()
|
||||||
if storage.ext == nil then return false end
|
local stored = storage.ext
|
||||||
if ext == storage.ext and var == ext.var then
|
if stored == nil then return false end
|
||||||
|
if ext == stored and var == ext.var then
|
||||||
return var ~= nil
|
return var ~= nil
|
||||||
else
|
else
|
||||||
ext = storage.ext
|
ext = stored
|
||||||
var = ext.var
|
var = stored.var
|
||||||
return var ~= nil
|
return var ~= nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -48,7 +50,7 @@ local servers = External.get_servers()
|
|||||||
]]
|
]]
|
||||||
function External.get_servers()
|
function External.get_servers()
|
||||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
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
|
end
|
||||||
|
|
||||||
--[[-- Gets a table of all the servers filtered by name, key is the server id, value is the server details
|
--[[-- 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.")
|
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 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")
|
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
|
end
|
||||||
|
|
||||||
--[[-- Gets the details of the given server
|
--[[-- 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)
|
function External.get_server_details(server_id)
|
||||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
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 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
|
end
|
||||||
|
|
||||||
--[[-- Gets the status of the given server
|
--[[-- Gets the status of the given server
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ PlayerData:set_serializer(Datastore.name_serializer) -- use player name
|
|||||||
|
|
||||||
--- Store and enum for the data saving preference
|
--- Store and enum for the data saving preference
|
||||||
local DataSavingPreference = PlayerData:combine("DataSavingPreference")
|
local DataSavingPreference = PlayerData:combine("DataSavingPreference")
|
||||||
local PreferenceEnum = { "All", "Statistics", "Settings", "Required" }
|
local PreferenceEnum = { "All", "Statistics", "Settings", "Required" } --- @type table<string | number, string | number>
|
||||||
for k, v in ipairs(PreferenceEnum) do PreferenceEnum[v] = k end
|
for k, v in ipairs(PreferenceEnum) do PreferenceEnum[v] = k end
|
||||||
|
|
||||||
DataSavingPreference:set_default("All")
|
DataSavingPreference:set_default("All")
|
||||||
|
|||||||
@@ -117,11 +117,28 @@ local Groups = require("modules.exp_legacy.expcore.permission_groups")
|
|||||||
local Colours = ExpUtil.color
|
local Colours = ExpUtil.color
|
||||||
local write_json = ExpUtil.write_json
|
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<string, boolean>
|
||||||
|
--- @field allow_all_actions boolean
|
||||||
|
--- @field flags table<string, boolean>
|
||||||
|
--- @field disallowed_actions table<string, boolean>?
|
||||||
|
--- @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 = {
|
local Roles = {
|
||||||
_prototype = {},
|
_prototype = {},
|
||||||
config = {
|
config = {
|
||||||
order = {}, -- Contains the order of the roles, lower index is better
|
order = {}, --- @type string[] Contains the order of the roles, lower index is better
|
||||||
roles = {}, -- Contains the raw info for the roles, indexed by role name
|
roles = {}, --- @type table<string, Roles.Role> 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
|
flags = {}, -- Contains functions that run when a flag is added/removed from a player
|
||||||
internal = {}, -- Contains all internally accessed roles, such as root, default
|
internal = {}, -- Contains all internally accessed roles, such as root, default
|
||||||
players = {}, -- Contains the roles that players have
|
players = {}, -- Contains the roles that players have
|
||||||
@@ -200,7 +217,7 @@ function Roles.debug()
|
|||||||
local output = ""
|
local output = ""
|
||||||
for index, role_name in ipairs(Roles.config.order) do
|
for index, role_name in ipairs(Roles.config.order) do
|
||||||
local role = Roles.config.roles[role_name]
|
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)
|
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))
|
output = output .. string.format("\n%s %s) %s[/color]", color_str, index, serpent.line(role))
|
||||||
end
|
end
|
||||||
@@ -287,6 +304,7 @@ local role = Roles.get_role_by_name(2)
|
|||||||
]]
|
]]
|
||||||
function Roles.get_role_by_order(index)
|
function Roles.get_role_by_order(index)
|
||||||
local name = Roles.config.order[index]
|
local name = Roles.config.order[index]
|
||||||
|
if not name then return end
|
||||||
return Roles.config.roles[name]
|
return Roles.config.roles[name]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -348,16 +366,17 @@ end
|
|||||||
local role = Roles.get_player_highest_role(game.player)
|
local role = Roles.get_player_highest_role(game.player)
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
--- @return Roles.Role
|
||||||
function Roles.get_player_highest_role(player)
|
function Roles.get_player_highest_role(player)
|
||||||
local roles = Roles.get_player_roles(player)
|
local roles = Roles.get_player_roles(player)
|
||||||
local highest
|
local highest --- @type Roles.Role?
|
||||||
for _, role in ipairs(roles) do
|
for _, role in ipairs(roles) do
|
||||||
if not highest or role.index < highest.index then
|
if not highest or role.index < highest.index then
|
||||||
highest = role
|
highest = role
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return highest
|
return (assert(highest, "Player has no roles"))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Assignment.
|
--- 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
|
-- 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")
|
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 {}
|
local assign_later = Roles.config.deferred_roles[valid_player.name] or {}
|
||||||
for _, role in ipairs(role_objects) do
|
for _, role in ipairs(role_objects) do
|
||||||
local role_change = assign_later[role.name]
|
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)
|
function Roles.new_role(name, short_hand)
|
||||||
ExpUtil.assert_not_runtime()
|
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({
|
local role = setmetatable({
|
||||||
name = name,
|
name = name,
|
||||||
short_hand = short_hand or 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)
|
function Roles._prototype:set_permission_group(name, use_factorio_api)
|
||||||
ExpUtil.assert_not_runtime()
|
ExpUtil.assert_not_runtime()
|
||||||
if use_factorio_api then
|
if use_factorio_api then
|
||||||
self.permission_group = { true, name }
|
self.permission_group = { true, name } --[[@as [boolean, string] ]]
|
||||||
else
|
else
|
||||||
local group = Groups.get_group_by_name(name)
|
assert(Groups.get_group_by_name(name), "Permission group not found: " .. name)
|
||||||
if not group then return end
|
|
||||||
self.permission_group = name
|
self.permission_group = name
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
@@ -1115,8 +1133,9 @@ local function role_update(event)
|
|||||||
-- Updates the players permission group
|
-- Updates the players permission group
|
||||||
local highest = Roles.get_player_highest_role(player)
|
local highest = Roles.get_player_highest_role(player)
|
||||||
if highest.permission_group then
|
if highest.permission_group then
|
||||||
if highest.permission_group[1] then
|
local permission_group = highest.permission_group --[[@as [boolean, string] ]]
|
||||||
local group = game.permissions.get_group(highest.permission_group[2])
|
if permission_group[1] then
|
||||||
|
local group = game.permissions.get_group(permission_group[2])
|
||||||
if group then
|
if group then
|
||||||
Groups.add_to_permission_group_async(group, player)
|
Groups.add_to_permission_group_async(group, player)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ for _, config_key in ipairs{ "always_protected_names", "always_protected_types",
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Require roles if a permission is assigned in the config
|
-- Require roles if a permission is assigned in the config
|
||||||
local Roles
|
local Roles --- @type table<string, any>
|
||||||
if config.ignore_permission then
|
if config.ignore_permission then
|
||||||
Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ local Gui = require("modules/exp_gui")
|
|||||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||||
|
|
||||||
----- Locals -----
|
----- Locals -----
|
||||||
local follow_label -- Gui constructor
|
local follow_label --- @type ExpElement Gui constructor
|
||||||
local following = {}
|
local following = {}
|
||||||
local spectating = {}
|
local spectating = {}
|
||||||
local Public = {}
|
local Public = {}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ local mega = 1000000
|
|||||||
local vlayer = {}
|
local vlayer = {}
|
||||||
local vlayer_data = {
|
local vlayer_data = {
|
||||||
entity_interfaces = {
|
entity_interfaces = {
|
||||||
energy = {},
|
energy = {}, --- @type LuaEntity[]
|
||||||
circuit = {},
|
circuit = {}, --- @type LuaEntity[]
|
||||||
storage_input = {},
|
storage_input = {}, --- @type LuaEntity[]
|
||||||
storage_output = {},
|
storage_output = {}, --- @type LuaEntity[]
|
||||||
},
|
},
|
||||||
properties = {
|
properties = {
|
||||||
total_surface_area = 0,
|
total_surface_area = 0,
|
||||||
@@ -28,10 +28,10 @@ local vlayer_data = {
|
|||||||
capacity = 0,
|
capacity = 0,
|
||||||
},
|
},
|
||||||
storage = {
|
storage = {
|
||||||
items = {},
|
items = {}, --- @type table<string, number>
|
||||||
power_items = {},
|
power_items = {}, --- @type table<string, { value: number, count: number }>
|
||||||
energy = 0,
|
energy = 0,
|
||||||
unallocated = {},
|
unallocated = {}, --- @type table<string, number>
|
||||||
},
|
},
|
||||||
surface = table.deep_copy(config.surface),
|
surface = table.deep_copy(config.surface),
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ for name, properties in pairs(config.allowed_items) do
|
|||||||
|
|
||||||
if properties.power then
|
if properties.power then
|
||||||
vlayer_data.storage.power_items[name] = {
|
vlayer_data.storage.power_items[name] = {
|
||||||
value = properties.fuel_value * 1000000,
|
value = assert(properties.fuel_value) * 1000000,
|
||||||
count = 0,
|
count = 0,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -361,7 +361,7 @@ local function handle_input_interfaces()
|
|||||||
if not interface.valid then
|
if not interface.valid then
|
||||||
vlayer_data.entity_interfaces.storage_input[index] = nil
|
vlayer_data.entity_interfaces.storage_input[index] = nil
|
||||||
else
|
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
|
for _, v in pairs(inventory.get_contents()) do
|
||||||
if config.allowed_items[v.name] then
|
if config.allowed_items[v.name] then
|
||||||
@@ -384,8 +384,9 @@ local function handle_input_interfaces()
|
|||||||
|
|
||||||
if count_deduct and count_add then
|
if count_deduct and count_add then
|
||||||
if config.allowed_items[v.name].modded then
|
if config.allowed_items[v.name].modded then
|
||||||
|
local modded_item = assert(config.modded_items[v.name])
|
||||||
if config.modded_auto_downgrade then
|
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
|
else
|
||||||
vlayer.insert_item(v.name, count_add)
|
vlayer.insert_item(v.name, count_add)
|
||||||
end
|
end
|
||||||
@@ -439,14 +440,14 @@ local function handle_output_interfaces()
|
|||||||
if not interface.valid then
|
if not interface.valid then
|
||||||
vlayer_data.entity_interfaces.storage_output[index] = nil
|
vlayer_data.entity_interfaces.storage_output[index] = nil
|
||||||
else
|
else
|
||||||
local inventory = interface.get_inventory(defines.inventory.chest)
|
local inventory = assert(interface.get_inventory(defines.inventory.chest))
|
||||||
local inventory_request_sections = interface.get_logistic_sections().sections
|
local inventory_request_sections = assert(interface.get_logistic_sections()).sections
|
||||||
|
|
||||||
for i = 1, #inventory_request_sections do
|
for i = 1, #inventory_request_sections do
|
||||||
for _, v in pairs(inventory_request_sections[i].filters) do
|
for _, v in pairs(inventory_request_sections[i].filters) do
|
||||||
if v.value and config.allowed_items[v.value.name] then
|
if v.value and config.allowed_items[v.value.name] then
|
||||||
local current_amount = inventory.get_item_count(v.value.name)
|
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
|
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)
|
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
|
if not interface.valid then
|
||||||
vlayer_data.entity_interfaces.circuit[index] = nil
|
vlayer_data.entity_interfaces.circuit[index] = nil
|
||||||
else
|
else
|
||||||
local circuit_oc = interface.get_or_create_control_behavior()
|
local control = interface.get_or_create_control_behavior() --[[@as LuaConstantCombinatorControlBehavior]]
|
||||||
if circuit_oc.sections_count == 0 then
|
if control.sections_count == 0 then
|
||||||
circuit_oc.add_section()
|
control.add_section()
|
||||||
end
|
end
|
||||||
circuit_oc = circuit_oc.sections[1]
|
local circuit_oc = assert(control.sections[1])
|
||||||
local signal_index = 1
|
local signal_index = 1
|
||||||
local circuit = vlayer.get_circuits()
|
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)
|
-- Clear remaining signals to prevent outdated values being present (caused by count > 0 check)
|
||||||
for clear_index = signal_index, #circuit do
|
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
|
break -- There are no more signals to clear
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ function Warnings.add_warning(player, by_player_name, reason)
|
|||||||
|
|
||||||
reason = reason or "None given."
|
reason = reason or "None given."
|
||||||
|
|
||||||
local warning_count
|
local warning_count --- @type number
|
||||||
PlayerWarnings:update(player.name, function(_, warnings)
|
PlayerWarnings:update(player.name, function(_, warnings)
|
||||||
local warning = {
|
local warning = {
|
||||||
by_player_name = by_player_name,
|
by_player_name = by_player_name,
|
||||||
|
|||||||
@@ -126,19 +126,19 @@ lib.collect_loginet = function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if config.modules.logistorage then
|
if config.modules.logistorage then
|
||||||
for name, v in pairs(network.get_contents()) do
|
for _, item in pairs(network.get_contents()) do
|
||||||
stats.items[name] = (stats.items[name] or 0) + v
|
stats.items[item.name] = (stats.items[item.name] or 0) + item.count
|
||||||
end
|
end
|
||||||
|
|
||||||
-- pickups and deliveries of items
|
-- pickups and deliveries of items
|
||||||
for _, point_list in pairs{ network.provider_points, network.requester_points, network.storage_points } do
|
for _, point_list in pairs{ network.provider_points, network.requester_points, network.storage_points } do
|
||||||
for _, point in pairs(point_list) do
|
for _, point in pairs(point_list) do
|
||||||
for name, qty in pairs(point.targeted_items_pickup) do
|
for _, item in pairs(point.targeted_items_pickup) do
|
||||||
stats.pickups[name] = (stats.pickups[name] or 0) + qty
|
stats.pickups[item.name] = (stats.pickups[item.name] or 0) + item.count
|
||||||
end
|
end
|
||||||
|
|
||||||
for name, qty in pairs(point.targeted_items_deliver) do
|
for _, item in pairs(point.targeted_items_deliver) do
|
||||||
stats.deliveries[name] = (stats.deliveries[name] or 0) + qty
|
stats.deliveries[item.name] = (stats.deliveries[item.name] or 0) + item.count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ local Gui = require("modules/exp_gui")
|
|||||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||||
local Event = require("modules/exp_legacy/utils/event")
|
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_assigned, Gui._ensure_consistency)
|
||||||
Event.add(Roles.events.on_role_unassigned, Gui._ensure_consistency)
|
Event.add(Roles.events.on_role_unassigned, Gui._ensure_consistency)
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ local function aabb_align_expand(aabb)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local vlayer_container
|
local vlayer_container --- @type ExpElement
|
||||||
local vlayer_gui_control_type
|
local vlayer_gui_control_type --- @type ExpElement
|
||||||
local vlayer_gui_control_list
|
local vlayer_gui_control_list --- @type ExpElement
|
||||||
|
|
||||||
local vlayer_control_type_list = {
|
local vlayer_control_type_list = {
|
||||||
[1] = "energy",
|
[1] = "energy",
|
||||||
@@ -87,10 +87,10 @@ SelectArea:on_selection(function(event)
|
|||||||
local container = Gui.get_left_element(vlayer_container, player)
|
local container = Gui.get_left_element(vlayer_container, player)
|
||||||
local disp = container.frame["vlayer_st_2"].disp.table
|
local disp = container.frame["vlayer_st_2"].disp.table
|
||||||
local target = vlayer_control_type_list[disp[vlayer_gui_control_type.name].selected_index]
|
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 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 }
|
entities = event.surface.find_entities_filtered{ area = area, name = "constant-combinator", force = player.force }
|
||||||
else
|
else
|
||||||
player.print{ "vlayer.power-on-space-research", config.power_on_space_research.name, config.power_on_space_research.level }
|
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_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 }
|
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" }
|
player.print{ "vlayer.steel-chest-empty" }
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -325,7 +325,9 @@ local function vlayer_gui_list_refresh(player)
|
|||||||
local interface = vlayer.get_interfaces()[vlayer_control_type_list[target]]
|
local interface = vlayer.get_interfaces()[vlayer_control_type_list[target]]
|
||||||
|
|
||||||
for i = 1, vlayer.get_interface_counts()[vlayer_control_type_list[target]], 1 do
|
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
|
end
|
||||||
|
|
||||||
disp[vlayer_gui_control_list.name].items = full_list
|
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{
|
}:style{
|
||||||
width = 200,
|
width = 200,
|
||||||
}:on_click(function(def, player, element, event)
|
}:on_click(function(def, player, element, event)
|
||||||
local target = element.parent[vlayer_gui_control_type.name].selected_index
|
local target = assert(element.parent)[vlayer_gui_control_type.name].selected_index
|
||||||
local n = element.parent[vlayer_gui_control_list.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
|
if target and vlayer_control_type_list[target] and n > 0 then
|
||||||
local i = vlayer.get_interfaces()
|
local i = vlayer.get_interfaces()
|
||||||
local entity = i[vlayer_control_type_list[target]][n]
|
local entity = i[vlayer_control_type_list[target]][n]
|
||||||
if entity and entity.valid then
|
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.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) }
|
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
|
end
|
||||||
@@ -423,14 +424,15 @@ local vlayer_gui_control_remove = Gui.define("vlayer_gui_control_remove")
|
|||||||
}:style{
|
}:style{
|
||||||
width = 200,
|
width = 200,
|
||||||
}:on_click(function(def, player, element)
|
}:on_click(function(def, player, element)
|
||||||
local target = element.parent[vlayer_gui_control_type.name].selected_index
|
local target = assert(element.parent)[vlayer_gui_control_type.name].selected_index
|
||||||
local n = element.parent[vlayer_gui_control_list.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
|
if target and vlayer_control_type_list[target] and n > 0 then
|
||||||
local i = vlayer.get_interfaces()
|
local i = vlayer.get_interfaces()
|
||||||
|
|
||||||
if i and i[vlayer_control_type_list[target]] then
|
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
|
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 } }
|
game.print{ "vlayer.interface-result", player.name, pos_to_gps_string(interface_position, interface_surface.name), { "vlayer.result-remove" }, { "vlayer.control-type-" .. interface_type } }
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ local warp_icon_button = Gui.define("warp_icon_button")
|
|||||||
:style(Styles.sprite32)
|
:style(Styles.sprite32)
|
||||||
:on_click(function(def, player, element)
|
:on_click(function(def, player, element)
|
||||||
if element.type == "choose-elem-button" then return end
|
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)
|
Warps.teleport_player(warp_id, player)
|
||||||
|
|
||||||
-- Reset the warp cooldown if the player does not have unlimited warps
|
-- 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,
|
horizontally_stretchable = true,
|
||||||
}
|
}
|
||||||
:on_click(function(def, player, element)
|
: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)
|
local warp = Warps.get_warp(warp_id)
|
||||||
player.set_controller{ type = defines.controllers.remote, position = warp.position, surface = warp.surface }
|
player.set_controller{ type = defines.controllers.remote, position = warp.position, surface = warp.surface }
|
||||||
end)
|
end)
|
||||||
@@ -271,9 +271,9 @@ local warp_textfield = Gui.define("warp_textfield")
|
|||||||
right_margin = 2,
|
right_margin = 2,
|
||||||
}
|
}
|
||||||
:on_confirmed(function(def, player, element)
|
: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_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
|
if warp_icon.type == nil then warp_icon.type = "item" end
|
||||||
Warps.set_editing(warp_id, player.name)
|
Warps.set_editing(warp_id, player.name)
|
||||||
Warps.update_warp(warp_id, warp_name, warp_icon, 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)
|
:style(Styles.sprite22)
|
||||||
:on_click(function(def, player, element)
|
:on_click(function(def, player, element)
|
||||||
local warp_id = element.parent.caption
|
local parent = assert(element.parent)
|
||||||
local warp_name = element.parent.parent["name-" .. warp_id][warp_textfield.name].text
|
local grandparent = assert(parent.parent)
|
||||||
local warp_icon = element.parent.parent["icon-" .. warp_id][warp_icon_editing.name].elem_value --[[ @as SignalID ]]
|
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
|
if warp_icon.type == nil then warp_icon.type = "item" end
|
||||||
Warps.set_editing(warp_id, player.name)
|
Warps.set_editing(warp_id, player.name)
|
||||||
Warps.update_warp(warp_id, warp_name, warp_icon, 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)
|
:style(Styles.sprite22)
|
||||||
:on_click(function(def, player, element)
|
: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.
|
-- Check if this is the first edit, if so remove the warp.
|
||||||
local warp = Warps.get_warp(warp_id)
|
local warp = Warps.get_warp(warp_id)
|
||||||
if warp.updates == 1 then
|
if warp.updates == 1 then
|
||||||
@@ -333,7 +337,7 @@ local remove_warp_button = Gui.define("remove_warp_button")
|
|||||||
}
|
}
|
||||||
:style(Styles.sprite22)
|
:style(Styles.sprite22)
|
||||||
:on_click(function(def, player, element)
|
:on_click(function(def, player, element)
|
||||||
local warp_id = element.parent.caption
|
local warp_id = assert(element.parent).caption
|
||||||
Warps.remove_warp(warp_id)
|
Warps.remove_warp(warp_id)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -349,7 +353,7 @@ local edit_warp_button = Gui.define("edit_warp_button")
|
|||||||
}
|
}
|
||||||
:style(Styles.sprite22)
|
:style(Styles.sprite22)
|
||||||
:on_click(function(def, player, element)
|
: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)
|
Warps.set_editing(warp_id, player.name, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -429,8 +433,8 @@ local function update_warp_elements(element, warp, warp_player_is_on, on_cooldow
|
|||||||
-- Check if button element is valid
|
-- Check if button element is valid
|
||||||
if not element or not element.valid then return end
|
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 label_style = assert(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 warp_status_element = assert(element.parent).parent["name-" .. warp.warp_id][warp_status.name]
|
||||||
|
|
||||||
-- If player is not on a warp
|
-- If player is not on a warp
|
||||||
if not warp_player_is_on then
|
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
|
-- Draw the scroll table for the warps
|
||||||
local scroll_table = Gui.elements.scroll_table(container, 250, 3, "scroll")
|
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)
|
-- 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
|
-- Change the style of the scroll table
|
||||||
local scroll_table_style = scroll_table.style
|
local scroll_table_style = scroll_table.style
|
||||||
@@ -778,7 +782,7 @@ Event.on_nth_tick(math.floor(60 / config.update_smoothing), function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Check if the force has any warps
|
-- 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
|
local closest_distance = nil
|
||||||
if #warp_ids > 0 then
|
if #warp_ids > 0 then
|
||||||
local surface = player.surface
|
local surface = player.surface
|
||||||
@@ -838,7 +842,7 @@ end)
|
|||||||
Event.add(defines.events.on_player_created, function(event)
|
Event.add(defines.events.on_player_created, function(event)
|
||||||
-- If the force has no spawn then make a spawn warp
|
-- If the force has no spawn then make a spawn warp
|
||||||
local player = game.players[event.player_index]
|
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)
|
local spawn_id = Warps.get_spawn_warp_id(force.name)
|
||||||
if not spawn_id then
|
if not spawn_id then
|
||||||
local spawn_position = force.get_spawn_position(player.surface)
|
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
|
-- Check if user has permission to add warps
|
||||||
local allow_add_warp = check_player_permissions(player, "allow_add_warp")
|
local allow_add_warp = check_player_permissions(player, "allow_add_warp")
|
||||||
-- Update container size depending on whether the player is allowed to add warps
|
-- 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
|
-- Update the warps, in case the user can now edit them
|
||||||
local scroll_table = frame.scroll.table
|
local scroll_table = frame.scroll.table
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ made with `assign_player_local`.
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local clusterio_api = require("modules/clusterio/api")
|
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")
|
local Async = require("modules/exp_util/async")
|
||||||
|
|
||||||
--- @class ExpRoles
|
--- @class ExpRoles
|
||||||
@@ -399,7 +399,7 @@ end
|
|||||||
--- @param self ExpRoles.Role
|
--- @param self ExpRoles.Role
|
||||||
--- @param action string
|
--- @param action string
|
||||||
--- @return boolean
|
--- @return boolean
|
||||||
function Role:is_allowed(action)
|
function Role.is_allowed(self, action)
|
||||||
local allowed = self.allowed_actions
|
local allowed = self.allowed_actions
|
||||||
return allowed["core.admin"] or allowed[permission_from_action(action)] or false
|
return allowed["core.admin"] or allowed[permission_from_action(action)] or false
|
||||||
end
|
end
|
||||||
@@ -408,7 +408,7 @@ end
|
|||||||
--- @param self ExpRoles.Role
|
--- @param self ExpRoles.Role
|
||||||
--- @param name string
|
--- @param name string
|
||||||
--- @return boolean
|
--- @return boolean
|
||||||
function Role:has_flag(name)
|
function Role.has_flag(self, name)
|
||||||
return self.allowed_actions[permission_from_flag(name)] or false
|
return self.allowed_actions[permission_from_flag(name)] or false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -416,7 +416,7 @@ end
|
|||||||
--- @param self ExpRoles.Role
|
--- @param self ExpRoles.Role
|
||||||
--- @param online boolean? When given, filter by connected state
|
--- @param online boolean? When given, filter by connected state
|
||||||
--- @return LuaPlayer[]
|
--- @return LuaPlayer[]
|
||||||
function Role:get_players(online)
|
function Role.get_players(self, online)
|
||||||
local players = {}
|
local players = {}
|
||||||
for player_name, role_names in pairs(ExpRoles.config.players) do
|
for player_name, role_names in pairs(ExpRoles.config.players) do
|
||||||
for _, role_name in pairs(role_names) do
|
for _, role_name in pairs(role_names) do
|
||||||
@@ -437,7 +437,7 @@ end
|
|||||||
--- @param self ExpRoles.Role
|
--- @param self ExpRoles.Role
|
||||||
--- @param message LocalisedString
|
--- @param message LocalisedString
|
||||||
--- @return number # Number of players the message was sent to
|
--- @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)
|
local players = self:get_players(true)
|
||||||
for _, player in pairs(players) do
|
for _, player in pairs(players) do
|
||||||
player.print(message)
|
player.print(message)
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ had, and event_handler expects `events` to be the handlers to register.
|
|||||||
local clusterio_api = require("modules/clusterio/api")
|
local clusterio_api = require("modules/clusterio/api")
|
||||||
local ExpRoles = require("modules/exp_roles/control")
|
local ExpRoles = require("modules/exp_roles/control")
|
||||||
|
|
||||||
return {
|
--- @class ExpRoles.EventHandlers
|
||||||
|
--- @field on_load fun()
|
||||||
|
--- @field events table<defines.events, fun(event: EventData)>
|
||||||
|
local handlers = {
|
||||||
on_load = ExpRoles.on_load,
|
on_load = ExpRoles.on_load,
|
||||||
events = {
|
events = {
|
||||||
[clusterio_api.events.on_server_startup] = ExpRoles.on_server_startup,
|
[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,
|
[defines.events.on_player_joined_game] = ExpRoles.on_player_joined_game,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return handlers
|
||||||
|
|||||||
@@ -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
|
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()`
|
-- Access using `/sc exp_roles.foo()`
|
||||||
exp_roles = require("modules/exp_roles/control")
|
exp_roles = require("modules/exp_roles/control")
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ local valid, invalid = Commands.status.success, Commands.status.invalid_input
|
|||||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||||
local highest_role = Roles.get_player_highest_role
|
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
|
--- A role defined by exp roles
|
||||||
types.role = add("role", Commands.types.key_of(Roles.config.roles))
|
types.role = add("role", Commands.types.key_of(Roles.config.roles))
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ local abs = math.abs
|
|||||||
local commands = {}
|
local commands = {}
|
||||||
|
|
||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @param area BoundingBox
|
--- @param area BoundingBox.struct
|
||||||
--- @return boolean
|
--- @return boolean
|
||||||
local function location_break(player, area)
|
local function location_break(player, area)
|
||||||
local surface = player.surface -- Allow remote view
|
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
|
if is_charted(surface, { x = floor(area.left_top.x / 32), y = floor(area.left_top.y / 32) }) then
|
||||||
return true
|
return true
|
||||||
elseif is_charted(surface, { x = floor(area.left_top.x / 32), y = floor(area.right_bottom.y / 32) }) then
|
elseif is_charted(surface, { x = floor(area.left_top.x / 32), y = floor(area.right_bottom.y / 32) }) then
|
||||||
@@ -63,13 +63,14 @@ SelectArea:on_selection(function(event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
local count = 0
|
local count = 0
|
||||||
local hits = {} --- @type MapPosition[]
|
local hits = {} --- @type MapPosition.struct[]
|
||||||
for _, entity in ipairs(entities) do
|
for _, entity in ipairs(entities) do
|
||||||
local skip = false
|
local skip = false
|
||||||
|
|
||||||
|
local entity_position = entity.position
|
||||||
for _, pos in ipairs(hits) do
|
for _, pos in ipairs(hits) do
|
||||||
local x = abs(entity.position.x - pos.x)
|
local x = abs(entity_position.x - pos.x)
|
||||||
local y = abs(entity.position.y - pos.y)
|
local y = abs(entity_position.y - pos.y)
|
||||||
if x * x + y * y < 36 then
|
if x * x + y * y < 36 then
|
||||||
skip = true
|
skip = true
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ local function get_server_id(server)
|
|||||||
elseif status == "Offline" then
|
elseif status == "Offline" then
|
||||||
return false, { "exp-commands_connect.offline", server_details.name }
|
return false, { "exp-commands_connect.offline", server_details.name }
|
||||||
end
|
end
|
||||||
return true, server_id
|
return true, server_id --[[@as string]]
|
||||||
elseif server_count_before > 0 then
|
elseif server_count_before > 0 then
|
||||||
return false, { "exp-commands_connect.wrong-version", concat(server_names_before, ", ") }
|
return false, { "exp-commands_connect.wrong-version", concat(server_names_before, ", ") }
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Commands.new("kill", { "exp-commands_kill.description" })
|
|||||||
if script.active_mods["space-age"] then
|
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 }
|
other_player.surface.create_entity{ name = "lightning", position = { other_player.position.x, other_player.position.y - 16 }, target = other_player.character }
|
||||||
end
|
end
|
||||||
other_player.character.die()
|
assert(other_player.character).die()
|
||||||
else
|
else
|
||||||
return Commands.status.unauthorised{ "exp-commands_kill.lower-role" }
|
return Commands.status.unauthorised{ "exp-commands_kill.lower-role" }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ end
|
|||||||
|
|
||||||
--- Get the key used in protected_areas
|
--- Get the key used in protected_areas
|
||||||
--- TODO expose this from EntityProtection
|
--- TODO expose this from EntityProtection
|
||||||
--- @param area BoundingBox
|
--- @param area BoundingBox.struct
|
||||||
--- @return string
|
--- @return string
|
||||||
local function get_area_key(area)
|
local function get_area_key(area)
|
||||||
return format_string("%i,%i", floor(area.left_top.x), floor(area.left_top.y))
|
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 function show_protected_entity(player, entity)
|
||||||
local key = get_entity_key(entity)
|
local key = get_entity_key(entity)
|
||||||
if renders[player.index][key] then return end
|
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{
|
renders[player.index][key] = rendering.draw_sprite{
|
||||||
sprite = "utility/notification",
|
sprite = "utility/notification",
|
||||||
target = entity,
|
target = entity,
|
||||||
target_offset = {
|
target_offset = {
|
||||||
(rb.x - entity.position.x) * 0.75,
|
(rb.x - position.x) * 0.75,
|
||||||
(rb.y - entity.position.y) * 0.75,
|
(rb.y - position.y) * 0.75,
|
||||||
},
|
},
|
||||||
x_scale = 2,
|
x_scale = 2,
|
||||||
y_scale = 2,
|
y_scale = 2,
|
||||||
@@ -67,7 +69,7 @@ end
|
|||||||
--- Show a protected area to a player
|
--- Show a protected area to a player
|
||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @param surface LuaSurface
|
--- @param surface LuaSurface
|
||||||
--- @param area BoundingBox
|
--- @param area BoundingBox.struct
|
||||||
local function show_protected_area(player, surface, area)
|
local function show_protected_area(player, surface, area)
|
||||||
local key = get_area_key(area)
|
local key = get_area_key(area)
|
||||||
if renders[player.index][key] then return end
|
if renders[player.index][key] then return end
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ local Storage = require("modules/exp_util/storage")
|
|||||||
|
|
||||||
--- Storage variables
|
--- Storage variables
|
||||||
local active_players = {} --- @type table<number, boolean> Stores all players in in protected mode
|
local active_players = {} --- @type table<number, boolean> Stores all players in in protected mode
|
||||||
local map_tags = {} --- @type table<number, boolean> Stores all protected map tags
|
local map_tags = {} --- @type table<string, boolean> Stores all protected map tags
|
||||||
|
|
||||||
Storage.register({
|
Storage.register({
|
||||||
active_players = active_players,
|
active_players = active_players,
|
||||||
|
|||||||
@@ -6,6 +6,12 @@ local Commands = require("modules/exp_commands")
|
|||||||
local format_player_name = Commands.format_player_name_locale
|
local format_player_name = Commands.format_player_name_locale
|
||||||
local format_text = Commands.format_rich_text_color
|
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
|
--- Wraps one component into the next
|
||||||
--- @param c1 number
|
--- @param c1 number
|
||||||
--- @param c2 number
|
--- @param c2 number
|
||||||
@@ -21,8 +27,8 @@ local function step_component(c1, c2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Wraps all components of a colour ensuring it remains valid
|
--- Wraps all components of a colour ensuring it remains valid
|
||||||
--- @param color Color
|
--- @param color ExpCommands_Rainbow.Color
|
||||||
--- @return Color
|
--- @return ExpCommands_Rainbow.Color
|
||||||
local function step_color(color)
|
local function step_color(color)
|
||||||
color.r, color.g = step_component(color.r, color.g)
|
color.r, color.g = step_component(color.r, color.g)
|
||||||
color.g, color.b = step_component(color.g, color.b)
|
color.g, color.b = step_component(color.g, color.b)
|
||||||
@@ -32,9 +38,9 @@ local function step_color(color)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Get the next colour in the rainbow by the given step
|
--- Get the next colour in the rainbow by the given step
|
||||||
--- @param color Color
|
--- @param color ExpCommands_Rainbow.Color
|
||||||
--- @param step number
|
--- @param step number
|
||||||
--- @return Color
|
--- @return ExpCommands_Rainbow.Color
|
||||||
local function next_color(color, step)
|
local function next_color(color, step)
|
||||||
step = step or 0.1
|
step = step or 0.1
|
||||||
local new_color = { r = 0, g = 0, b = 0 }
|
local new_color = { r = 0, g = 0, b = 0 }
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Commands.new("ratio", { "exp-commands_ratio.description" })
|
|||||||
|
|
||||||
local amount_of_machines = 1
|
local amount_of_machines = 1
|
||||||
if items_per_second then
|
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
|
end
|
||||||
|
|
||||||
for _, ingredient in ipairs(ingredients) do
|
for _, ingredient in ipairs(ingredients) do
|
||||||
@@ -43,7 +43,7 @@ Commands.new("ratio", { "exp-commands_ratio.description" })
|
|||||||
for i, product in ipairs(products) do
|
for i, product in ipairs(products) do
|
||||||
Commands.print{
|
Commands.print{
|
||||||
product.type == "item" and "exp-commands_ratio.item-out" or "exp-commands_ratio.fluid-out",
|
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
|
product.name
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -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
|
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 function reportable_player(input, player)
|
||||||
local success, status, result = parse_input(input, player, Commands.types.player)
|
local success, status, result = parse_input(input, player, Commands.types.player)
|
||||||
if not success then return status, result end
|
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
|
if Reports.report_player(other_player, player.name, reason) then
|
||||||
local user_message = { "exp-commands_reports.response", other_player_name, reason }
|
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 }
|
local admin_message = { "exp-commands_reports.response-admin", other_player_name, player_name, reason }
|
||||||
for _, player in ipairs(game.connected_players) do
|
for _, connected_player in ipairs(game.connected_players) do
|
||||||
if player.admin then
|
if connected_player.admin then
|
||||||
player.print(admin_message)
|
connected_player.print(admin_message)
|
||||||
else
|
else
|
||||||
player.print(user_message)
|
connected_player.print(user_message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Commands.new("get-roles", { "exp-commands_roles.description-get" })
|
|||||||
--- @cast other_player LuaPlayer?
|
--- @cast other_player LuaPlayer?
|
||||||
local roles = get_roles_ordered()
|
local roles = get_roles_ordered()
|
||||||
local roles_formatted = { "" } --- @type LocalisedString
|
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
|
if other_player then
|
||||||
roles = get_player_roles(other_player)
|
roles = get_player_roles(other_player)
|
||||||
response[1] = "exp-commands_roles.list-player"
|
response[1] = "exp-commands_roles.list-player"
|
||||||
@@ -55,8 +55,7 @@ Commands.new("get-roles", { "exp-commands_roles.description-get" })
|
|||||||
end
|
end
|
||||||
|
|
||||||
local last = #roles_formatted
|
local last = #roles_formatted
|
||||||
--- @diagnostic disable-next-line nil-check
|
roles_formatted[last] = assert(roles_formatted[last])[2]
|
||||||
roles_formatted[last] = roles_formatted[last][2]
|
|
||||||
|
|
||||||
return Commands.status.success(response)
|
return Commands.status.success(response)
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ local format_player_name = Commands.format_player_name_locale
|
|||||||
local format_number = require("util").format_number
|
local format_number = require("util").format_number
|
||||||
|
|
||||||
--- A player who is of a lower role than the executing player
|
--- 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)
|
local function parse_item(input, player)
|
||||||
-- First Case - internal name is given
|
-- First Case - internal name is given
|
||||||
-- Second Case - rich text is given
|
-- Second Case - rich text is given
|
||||||
@@ -88,7 +91,7 @@ local function sort_results(results, func)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return sorted
|
return sorted --[[@as SearchResult[] ]]
|
||||||
end
|
end
|
||||||
|
|
||||||
local display_players_time_format = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
|
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)
|
end)
|
||||||
|
|
||||||
--- Return the amount of an item a player has
|
--- Return the amount of an item a player has
|
||||||
--- @type SortFunction
|
--- @param data SearchResult
|
||||||
|
--- @return number
|
||||||
local function sort_by_count(data)
|
local function sort_by_count(data)
|
||||||
return data.count
|
return data.count
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ local format_number = require("util").format_number
|
|||||||
local commands = {}
|
local commands = {}
|
||||||
|
|
||||||
--- Set all trains to automatic
|
--- 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?)
|
--- @overload fun(player: LuaPlayer, surface: LuaSurface?, force: LuaForce?)
|
||||||
commands.set_trains_to_automatic = Commands.new("set-trains-to-automatic", { "exp-commands_trains.description" })
|
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)
|
:optional("surface", { "exp-commands_trains.arg-surface" }, Commands.types.surface)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Commands.new("get-warnings", { "exp-commands_warnings.description-get" })
|
|||||||
local warnings = Warnings.get_warnings(player)
|
local warnings = Warnings.get_warnings(player)
|
||||||
local script_warnings = Warnings.get_script_warnings(player)
|
local script_warnings = Warnings.get_script_warnings(player)
|
||||||
local other_player_name = format_player_name(other_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
|
for _, warning in pairs(warnings) do
|
||||||
local by_player_name_formatted = format_player_name(warning.by_player_name)
|
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 }
|
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
|
for player_name, player_warnings in pairs(warnings) do
|
||||||
local player_name_formatted = format_player_name(player_name)
|
local player_name_formatted = format_player_name(player_name)
|
||||||
local script_warning_count = script_warnings[player_name] and #script_warnings[player_name] or 0
|
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
|
end
|
||||||
for player_name, player_warnings in pairs(script_warnings) do
|
for player_name, player_warnings in pairs(script_warnings) do
|
||||||
if not warnings[player_name] then
|
if not warnings[player_name] then
|
||||||
local player_name_formatted = format_player_name(player_name)
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ SelectArea:on_selection(function(event)
|
|||||||
if #chests > 0 then
|
if #chests > 0 then
|
||||||
for _, chest in pairs(chests) do
|
for _, chest in pairs(chests) do
|
||||||
tile_count = tile_count + 1
|
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 } }
|
tiles_to_make[tile_count] = { name = tile_to_apply, position = { chest.position.x, chest.position.y } }
|
||||||
chest.destroy()
|
chest.destroy()
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ local floor = math.floor
|
|||||||
--- Give a player their starting items
|
--- Give a player their starting items
|
||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
local function give_starting_items(player)
|
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 get_input_count = get_prod_stats.get_input_count
|
||||||
local insert_param = { name = "", count = 0 }
|
local insert_param = { name = "", count = 0 }
|
||||||
local insert = player.insert
|
local insert = player.insert
|
||||||
|
|||||||
@@ -26,11 +26,12 @@ local function on_entity_damaged(event)
|
|||||||
|
|
||||||
-- Outputs the message as floating text
|
-- Outputs the message as floating text
|
||||||
if message then
|
if message then
|
||||||
|
local entity_position = entity.position
|
||||||
local entity_radius = max(1, entity.get_radius())
|
local entity_radius = max(1, entity.get_radius())
|
||||||
local offset = (random() - 0.5) * entity_radius * config.damage_location_variance
|
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 }
|
local color = { r = 1 - health_percentage, g = health_percentage, b = 0 }
|
||||||
|
|
||||||
FlyingText.create{
|
FlyingText.create{
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ local function create_map_tag(corpse_data)
|
|||||||
message = message .. " at " .. time
|
message = message .. " at " .. time
|
||||||
end
|
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,
|
position = corpse_data.corpse.position,
|
||||||
icon = config.map_icon,
|
icon = config.map_icon,
|
||||||
text = message,
|
text = message,
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ local function format_position(pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Convert an area to a string
|
--- Convert an area to a string
|
||||||
--- @param area BoundingBox
|
--- @param area BoundingBox.struct
|
||||||
--- @return string
|
--- @return string
|
||||||
local function format_area(area)
|
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)
|
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
|
if not player or not player.character then return end
|
||||||
|
|
||||||
local character_ammo = assert(player.get_inventory(defines.inventory.character_ammo))
|
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
|
if not item or not item.valid or not item.valid_for_read then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,10 +16,9 @@ end
|
|||||||
|
|
||||||
--- Replace a tile with the next tile in the degrade chain
|
--- Replace a tile with the next tile in the degrade chain
|
||||||
--- @param surface LuaSurface
|
--- @param surface LuaSurface
|
||||||
--- @param position MapPosition
|
--- @param position MapPosition.struct
|
||||||
local function degrade_tile(surface, position)
|
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.x, position.y)
|
||||||
local tile = surface.get_tile(position)
|
|
||||||
local tile_name = tile.name
|
local tile_name = tile.name
|
||||||
local degrade_tile_name = config.degrade_order[tile_name]
|
local degrade_tile_name = config.degrade_order[tile_name]
|
||||||
if not degrade_tile_name then return end
|
if not degrade_tile_name then return end
|
||||||
@@ -33,8 +32,9 @@ local function degrade_entity(entity)
|
|||||||
|
|
||||||
local tiles = {}
|
local tiles = {}
|
||||||
local surface = entity.surface
|
local surface = entity.surface
|
||||||
local left_top = entity.bounding_box.left_top
|
local bounding_box = entity.bounding_box
|
||||||
local right_bottom = entity.bounding_box.right_bottom
|
local left_top = bounding_box.left_top
|
||||||
|
local right_bottom = bounding_box.right_bottom
|
||||||
for x = left_top.x, right_bottom.x do
|
for x = left_top.x, right_bottom.x do
|
||||||
for y = left_top.y, right_bottom.y do
|
for y = left_top.y, right_bottom.y do
|
||||||
local tile = surface.get_tile(x, y)
|
local tile = surface.get_tile(x, y)
|
||||||
@@ -58,11 +58,10 @@ end
|
|||||||
|
|
||||||
--- Gets the average tile strengths around position
|
--- Gets the average tile strengths around position
|
||||||
--- @param surface LuaSurface
|
--- @param surface LuaSurface
|
||||||
--- @param position MapPosition
|
--- @param position MapPosition.struct
|
||||||
--- @return number?
|
--- @return number?
|
||||||
local function get_tile_strength(surface, position)
|
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.x, position.y)
|
||||||
local tile = surface.get_tile(position)
|
|
||||||
local tile_name = tile.name
|
local tile_name = tile.name
|
||||||
local strength = config.strengths[tile_name]
|
local strength = config.strengths[tile_name]
|
||||||
if not strength then return end
|
if not strength then return end
|
||||||
|
|||||||
@@ -31,15 +31,15 @@ local function append_playtime(player_name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Get the player name from an event
|
--- Get the player name from an event
|
||||||
--- @param event { player_index: number, by_player_name: string? }
|
--- @param event { player_index: uint, by_player_name: string? }
|
||||||
--- @return string, string
|
--- @return string, string?
|
||||||
local function get_player_name(event)
|
local function get_player_name(event)
|
||||||
local player = game.players[event.player_index]
|
local player = game.players[event.player_index]
|
||||||
return player.name, event.by_player_name
|
return player.name, event.by_player_name
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Convert a colour value into hex
|
--- Convert a colour value into hex
|
||||||
--- @param color Color.0
|
--- @param color Color.struct
|
||||||
--- @return string
|
--- @return string
|
||||||
local function to_hex(color)
|
local function to_hex(color)
|
||||||
local hex_digits = "0123456789ABCDEF"
|
local hex_digits = "0123456789ABCDEF"
|
||||||
@@ -53,7 +53,7 @@ local function to_hex(color)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Emit the requires json to file for the given event arguments
|
--- 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 function emit_event(opts)
|
||||||
local admins_online = 0
|
local admins_online = 0
|
||||||
local players_online = 0
|
local players_online = 0
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ end
|
|||||||
--- @param event EventData.on_cargo_pod_finished_ascending
|
--- @param event EventData.on_cargo_pod_finished_ascending
|
||||||
local function on_cargo_pod_finished_ascending(event)
|
local function on_cargo_pod_finished_ascending(event)
|
||||||
if event.launched_by_rocket then
|
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
|
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")
|
add_log_line("[ROCKET]", force.rockets_launched, "rockets launched")
|
||||||
elseif config.rocket_launch_display[force.rockets_launched] then
|
elseif config.rocket_launch_display[force.rockets_launched] then
|
||||||
@@ -38,7 +38,7 @@ local function on_pre_player_died(event)
|
|||||||
local cause = event.cause
|
local cause = event.cause
|
||||||
if cause then
|
if cause then
|
||||||
if cause.type == "character" 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
|
else
|
||||||
add_log_line("[DEATH]", player.name, "died because of", cause.name)
|
add_log_line("[DEATH]", player.name, "died because of", cause.name)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ local min = math.min
|
|||||||
--- @field trees LuaEntity[]
|
--- @field trees LuaEntity[]
|
||||||
--- @field tree_count number
|
--- @field tree_count number
|
||||||
--- @field permission "fast" | "allow" | "disallow"
|
--- @field permission "fast" | "allow" | "disallow"
|
||||||
--- @field task Async.AsyncReturn
|
--- @field task Async.AsyncReturn<any>
|
||||||
|
|
||||||
local cache --- @type TreeDeconCache?
|
local cache --- @type TreeDeconCache?
|
||||||
|
|
||||||
@@ -77,7 +77,8 @@ local function get_player_cache(player_index)
|
|||||||
|
|
||||||
-- Create a new cache if the previous on is in use
|
-- Create a new cache if the previous on is in use
|
||||||
if not cache or cache.task and not cache.task.completed then
|
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
|
end
|
||||||
|
|
||||||
local player = assert(game.get_player(player_index))
|
local player = assert(game.get_player(player_index))
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ local Async = require("modules/exp_util/async")
|
|||||||
local Storage = require("modules/exp_util/storage")
|
local Storage = require("modules/exp_util/storage")
|
||||||
local config = require("modules.exp_legacy.config.compilatron")
|
local config = require("modules.exp_legacy.config.compilatron")
|
||||||
|
|
||||||
--- @type table<string, Async.AsyncReturn>
|
--- @type table<string, Async.AsyncReturn<any>>
|
||||||
local persistent_locations = {}
|
local persistent_locations = {}
|
||||||
Storage.register(persistent_locations, function(tbl)
|
Storage.register(persistent_locations, function(tbl)
|
||||||
persistent_locations = 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 entity LuaEntity the entity which will have messages spawn from it
|
||||||
--- @param messages LocalisedString[] the messages which should be shown
|
--- @param messages LocalisedString[] the messages which should be shown
|
||||||
--- @param starting_index number? the message index to start at, default 1
|
--- @param starting_index number? the message index to start at, default 1
|
||||||
--- @return Async.AsyncReturn
|
--- @return Async.AsyncReturn<any>
|
||||||
local function register_entity(entity, messages, starting_index)
|
local function register_entity(entity, messages, starting_index)
|
||||||
return speech_bubble_task{
|
return speech_bubble_task{
|
||||||
entity = entity,
|
entity = entity,
|
||||||
|
|||||||
@@ -68,12 +68,13 @@ local function try_deconstruct_output_chest(entity)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Get all adjacent mining drills and inserters
|
-- Get all adjacent mining drills and inserters
|
||||||
|
local target_position = target.position
|
||||||
local entities = target.surface.find_entities_filtered{
|
local entities = target.surface.find_entities_filtered{
|
||||||
type = { "mining-drill", "inserter" },
|
type = { "mining-drill", "inserter" },
|
||||||
to_be_deconstructed = false,
|
to_be_deconstructed = false,
|
||||||
area = {
|
area = {
|
||||||
{ target.position.x - 1, target.position.y - 1 },
|
left_top = { x = target_position.x - 1, y = target_position.y - 1 },
|
||||||
{ target.position.x + 1, 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{
|
local drills = resource.surface.find_entities_filtered{
|
||||||
type = "mining-drill",
|
type = "mining-drill",
|
||||||
area = {
|
area = {
|
||||||
{ position.x - max_mining_radius, position.y - max_mining_radius },
|
left_top = { x = position.x - max_mining_radius, y = position.y - max_mining_radius },
|
||||||
{ position.x + max_mining_radius, 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
|
-- Check which could have reached this resource
|
||||||
for _, drill in pairs(drills) do
|
for _, drill in pairs(drills) do
|
||||||
local radius = drill.prototype.mining_drill_radius
|
local radius = drill.prototype.mining_drill_radius
|
||||||
local dx = math.abs(drill.position.x - position.x)
|
local drill_position = drill.position
|
||||||
local dy = math.abs(drill.position.y - position.y)
|
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
|
if dx <= radius and dy <= radius then
|
||||||
try_deconstruct_miner(drill)
|
try_deconstruct_miner(drill)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ local config = require("modules.exp_legacy.config.spawn_area")
|
|||||||
--- Apply an offset to a LuaPosition
|
--- Apply an offset to a LuaPosition
|
||||||
--- @param position MapPosition
|
--- @param position MapPosition
|
||||||
--- @param offset MapPosition
|
--- @param offset MapPosition
|
||||||
--- @return MapPosition.0
|
--- @return MapPosition.struct
|
||||||
local function apply_offset(position, offset)
|
local function apply_offset(position, offset)
|
||||||
return {
|
return {
|
||||||
x = (position.x or position[1]) + (offset.x or offset[1]),
|
x = position.x + offset.x,
|
||||||
y = (position.y or position[2]) + (offset.y or offset[2])
|
y = position.y + offset.y,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ end
|
|||||||
--- @param x_index number
|
--- @param x_index number
|
||||||
--- @param y_index number
|
--- @param y_index number
|
||||||
local function apply_offset_to_array(positions, offset, x_index, y_index)
|
local function apply_offset_to_array(positions, offset, x_index, y_index)
|
||||||
local x = (offset.x or offset[1])
|
local x = offset.x
|
||||||
local y = (offset.y or offset[2])
|
local y = offset.y
|
||||||
for _, position in ipairs(positions) do
|
for _, position in ipairs(positions) do
|
||||||
position[x_index] = position[x_index] + x
|
position[x_index] = position[x_index] + x
|
||||||
position[y_index] = position[y_index] + y
|
position[y_index] = position[y_index] + y
|
||||||
@@ -149,13 +149,15 @@ local function create_entities(surface, offset)
|
|||||||
local pos = apply_offset({ entity_details[2], entity_details[3] }, 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" }
|
local entity = surface.create_entity{ name = entity_details[1], position = pos, force = "neutral" }
|
||||||
|
|
||||||
if entity and config.entities.protected then
|
if entity then
|
||||||
|
if config.entities.protected then
|
||||||
protect_entity(entity)
|
protect_entity(entity)
|
||||||
end
|
end
|
||||||
|
|
||||||
entity.operable = config.entities.operable
|
entity.operable = config.entities.operable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Generates an area with no water or entities, no water area is larger
|
--- Generates an area with no water or entities, no water area is larger
|
||||||
--- @param surface LuaSurface
|
--- @param surface LuaSurface
|
||||||
@@ -164,8 +166,7 @@ local function clear_spawn_area(surface, offset)
|
|||||||
local get_tile = surface.get_tile
|
local get_tile = surface.get_tile
|
||||||
|
|
||||||
-- Make sure a non water tile is used for filling
|
-- 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.x, offset.y)
|
||||||
local starting_tile = get_tile(offset)
|
|
||||||
local fill_tile = starting_tile.collides_with("player") and "landfill" or starting_tile.name
|
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 = config.spawn_area.landfill_radius
|
||||||
local fill_radius_sqr = fill_radius ^ 2
|
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 dst < tile_radius_sqr then
|
||||||
-- If it is inside the decon radius always set the tile
|
-- If it is inside the decon radius always set the tile
|
||||||
tiles_to_make[#tiles_to_make + 1] = { name = decon_tile, position = pos }
|
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.x, pos.y).collides_with("player") then
|
||||||
elseif dst < fill_radius_sqr and get_tile(pos).collides_with("player") then
|
|
||||||
-- If it is inside the fill radius only set the tile if it is water
|
-- 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 }
|
tiles_to_make[#tiles_to_make + 1] = { name = fill_tile, position = pos }
|
||||||
end
|
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.resource_patches.enabled then create_resource_patches(surface, offset) end
|
||||||
if config.turrets.enabled then update_turrets() 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)
|
player.teleport(offset, surface)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -66,8 +66,9 @@ local function rename_station(event)
|
|||||||
|
|
||||||
-- Check which recourse is closest
|
-- Check which recourse is closest
|
||||||
for _, resource in ipairs(resources) do
|
for _, resource in ipairs(resources) do
|
||||||
local dx = px - resource.bounding_box.left_top.x
|
local resource_box = resource.bounding_box
|
||||||
local dy = py - resource.bounding_box.left_top.y
|
local dx = px - resource_box.left_top.x
|
||||||
|
local dy = py - resource_box.left_top.y
|
||||||
local distance = (dx * dx) + (dy * dy)
|
local distance = (dx * dx) + (dy * dy)
|
||||||
if distance < closest_distance then
|
if distance < closest_distance then
|
||||||
closest_distance = distance
|
closest_distance = distance
|
||||||
@@ -78,7 +79,8 @@ local function rename_station(event)
|
|||||||
-- Set the item name and icon
|
-- Set the item name and icon
|
||||||
if closest_recourse then
|
if closest_recourse then
|
||||||
item_name = closest_recourse.name:gsub("^%l", string.upper):gsub("-", " ") -- remove dashes and making first letter capital
|
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)
|
icon = string.format("[img=%s.%s]", product.type, product.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ end
|
|||||||
|
|
||||||
--- Container added to the left gui flow
|
--- Container added to the left gui flow
|
||||||
--- @class ExpGui_Autofill.elements.container: ExpElement
|
--- @class ExpGui_Autofill.elements.container: ExpElement
|
||||||
--- @field data table<string, ExpGui_Autofill.entity_settings>
|
--- @field data table<LuaPlayer, table<string, ExpGui_Autofill.entity_settings>>
|
||||||
Elements.container = Gui.define("autofill/container")
|
Elements.container = Gui.define("autofill/container")
|
||||||
:draw(function(def, parent)
|
:draw(function(def, parent)
|
||||||
--- @cast def ExpGui_Autofill.elements.container
|
--- @cast def ExpGui_Autofill.elements.container
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function Public.show(container)
|
|||||||
local left_panel_style = left_panel.style
|
local left_panel_style = left_panel.style
|
||||||
left_panel_style.width = 300
|
left_panel_style.width = 300
|
||||||
|
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
for element_name in pairs(ExpElement._elements) do
|
for element_name in pairs(ExpElement._elements) do
|
||||||
local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = element_name }
|
local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = element_name }
|
||||||
Gui.set_data(header, 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.text = concat{ "ExpElement._elements[\"", element_name, "\"]" }
|
||||||
input_text_box.style.font_color = Color.black
|
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 define = ExpElement._elements[element_name]
|
||||||
local content = dump({
|
local content = dump({
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
debug = define._debug,
|
debug = define._debug,
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
has_handlers = define._has_handlers,
|
has_handlers = define._has_handlers,
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
track_elements = define._track_elements,
|
track_elements = define._track_elements,
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
elements = ExpIter._scopes[element_name],
|
elements = ExpIter._scopes[element_name],
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
data = ExpData._scopes[element_name]._raw,
|
data = ExpData._scopes[element_name]._raw,
|
||||||
}) or "nil"
|
}) or "nil"
|
||||||
right_panel.text = content
|
right_panel.text = content
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ local ExpUtil = require("modules/exp_util")
|
|||||||
local concat = table.concat
|
local concat = table.concat
|
||||||
local inspect = table.inspect
|
local inspect = table.inspect
|
||||||
local pcall = pcall
|
local pcall = pcall
|
||||||
local loadstring = loadstring --- @diagnostic disable-line
|
local loadstring = load
|
||||||
local rawset = rawset
|
local rawset = rawset
|
||||||
|
|
||||||
local Public = {}
|
local Public = {}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function Public.show(container)
|
|||||||
local left_panel_style = left_panel.style
|
local left_panel_style = left_panel.style
|
||||||
left_panel_style.width = 300
|
left_panel_style.width = 300
|
||||||
|
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line: access-invisible
|
||||||
for token_id in pairs(Storage._registered) do
|
for token_id in pairs(Storage._registered) do
|
||||||
local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = token_id }
|
local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = token_id }
|
||||||
Gui.set_data(header, token_id)
|
Gui.set_data(header, token_id)
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ Elements.online_player_dropdown = Gui.define("player_dropdown")
|
|||||||
} --[[@as any]]
|
} --[[@as any]]
|
||||||
|
|
||||||
--- To help with caching and avoid context changes the player list from the previous update is remembered
|
--- To help with caching and avoid context changes the player list from the previous update is remembered
|
||||||
--- @type (string?)[]
|
do local _player_names = {} --- @type (string?)[]
|
||||||
do local _player_names = {}
|
|
||||||
--- Updates the player name list after a join or leave
|
--- Updates the player name list after a join or leave
|
||||||
--- @return (string?)[]
|
--- @return (string?)[]
|
||||||
function Elements.online_player_dropdown._update_player_names()
|
function Elements.online_player_dropdown._update_player_names()
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ end
|
|||||||
--- @param machine_selector LuaGuiElement
|
--- @param machine_selector LuaGuiElement
|
||||||
function Elements.module_table.remove_row(module_table, machine_selector)
|
function Elements.module_table.remove_row(module_table, machine_selector)
|
||||||
local rows = Elements.module_table.data[module_table]
|
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
|
rows[machine_selector.index] = nil
|
||||||
Gui.destroy_if_valid(machine_selector)
|
Gui.destroy_if_valid(machine_selector)
|
||||||
for _, separator in pairs(row.row_separators) do
|
for _, separator in pairs(row.row_separators) do
|
||||||
@@ -193,7 +193,7 @@ end
|
|||||||
--- @param machine_selector LuaGuiElement
|
--- @param machine_selector LuaGuiElement
|
||||||
function Elements.module_table.reset_row(module_table, machine_selector)
|
function Elements.module_table.reset_row(module_table, machine_selector)
|
||||||
local rows = Elements.module_table.data[module_table]
|
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
|
for _, separator in pairs(row.row_separators) do
|
||||||
separator.visible = false
|
separator.visible = false
|
||||||
@@ -211,9 +211,9 @@ end
|
|||||||
--- @param machine_name string
|
--- @param machine_name string
|
||||||
function Elements.module_table.refresh_row(module_table, machine_selector, machine_name)
|
function Elements.module_table.refresh_row(module_table, machine_selector, machine_name)
|
||||||
local rows = Elements.module_table.data[module_table]
|
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_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 visible_module_count = visible_row_count * config.module_slots_per_row
|
||||||
local module_elem_value = { name = config.machines[machine_name].module }
|
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
|
-- Bounding box table to be reused in the loop below
|
||||||
--- @type BoundingBox
|
--- @type BoundingBox
|
||||||
local param_area = {
|
local param_area = {
|
||||||
left_top = {},
|
left_top = { x = 0, y = 0 },
|
||||||
right_bottom = {}
|
right_bottom = { x = 0, y = 0 },
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Update area param table to be reused in the loop below
|
-- Update area param table to be reused in the loop below
|
||||||
@@ -348,7 +348,7 @@ SelectArea:on_selection(function(event, module_table)
|
|||||||
|
|
||||||
-- Get all the modules selected
|
-- Get all the modules selected
|
||||||
for i = 1, entity_prototype.module_inventory_size do
|
for i = 1, entity_prototype.module_inventory_size do
|
||||||
local module_selector = module_selectors[i]
|
local module_selector = assert(module_selectors[i])
|
||||||
local module = module_selector.elem_value --[[@as { name: string, quality: string }?]]
|
local module = module_selector.elem_value --[[@as { name: string, quality: string }?]]
|
||||||
if module then
|
if module then
|
||||||
-- Module selected, add it the module arrays
|
-- Module selected, add it the module arrays
|
||||||
|
|||||||
@@ -22,13 +22,16 @@ local Elements = {}
|
|||||||
--- @field _cost_scale number
|
--- @field _cost_scale number
|
||||||
|
|
||||||
--- For perf calculate the division of scale against cost ahead of time
|
--- For perf calculate the division of scale against cost ahead of time
|
||||||
for _, bonus_data in pairs(config.player_bonus) do
|
--- @type table<string, ExpGui_PlayerBonus.bonus_data>
|
||||||
|
local player_bonus = config.player_bonus
|
||||||
|
|
||||||
|
for _, bonus_data in pairs(player_bonus) do
|
||||||
bonus_data._cost_scale = bonus_data.cost / bonus_data.scale
|
bonus_data._cost_scale = bonus_data.cost / bonus_data.scale
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Progress bar which displays how much of a bonus has been used
|
--- Progress bar which displays how much of a bonus has been used
|
||||||
--- @class ExpGui_PlayerBonus.elements.bonus_used: ExpElement
|
--- @class ExpGui_PlayerBonus.elements.bonus_used: ExpElement
|
||||||
--- @field data number
|
--- @field data table<LuaGuiElement, number>
|
||||||
--- @overload fun(parent: LuaGuiElement): LuaGuiElement
|
--- @overload fun(parent: LuaGuiElement): LuaGuiElement
|
||||||
Elements.bonus_used = Gui.define("player_bonus/bonus_used")
|
Elements.bonus_used = Gui.define("player_bonus/bonus_used")
|
||||||
:track_all_elements()
|
:track_all_elements()
|
||||||
@@ -47,8 +50,7 @@ Elements.bonus_used = Gui.define("player_bonus/bonus_used")
|
|||||||
:element_data(0) --[[@as any]]
|
:element_data(0) --[[@as any]]
|
||||||
|
|
||||||
--- Value is cached to save perf
|
--- Value is cached to save perf
|
||||||
--- @type table<number, number>
|
do local _points_limit = {} --- @type table<number, number>
|
||||||
do local _points_limit = {}
|
|
||||||
--- Clear the cache for points limit
|
--- Clear the cache for points limit
|
||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
function Elements.bonus_used._clear_points_limit_cache(player)
|
function Elements.bonus_used._clear_points_limit_cache(player)
|
||||||
@@ -442,7 +444,7 @@ end
|
|||||||
function Elements.container.calculate_cost(player)
|
function Elements.container.calculate_cost(player)
|
||||||
local cost = 0
|
local cost = 0
|
||||||
local player_data = Elements.container.data[player]
|
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
|
cost = cost + (player_data[bonus_data.name] or 0) * bonus_data._cost_scale
|
||||||
end
|
end
|
||||||
return cost
|
return cost
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ Elements.open_action_bar = Gui.define("player_list/open_action_bar")
|
|||||||
--- @param highlighted boolean
|
--- @param highlighted boolean
|
||||||
function Elements.open_action_bar.set_highlight(open_button, highlighted)
|
function Elements.open_action_bar.set_highlight(open_button, highlighted)
|
||||||
open_button.style = highlighted and "tool_button" or "frame_button"
|
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.padding = -2
|
||||||
style.width = 8
|
style.width = 8
|
||||||
style.height = 14
|
style.height = 14
|
||||||
@@ -102,11 +102,11 @@ Elements.reason_confirm = Gui.define("player_list/reason_confirm")
|
|||||||
local action_name = Elements.container.get_selected_action(player)
|
local action_name = Elements.container.get_selected_action(player)
|
||||||
local button_data = action_name and config.buttons[action_name]
|
local button_data = action_name and config.buttons[action_name]
|
||||||
if button_data and button_data.reason_callback then
|
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
|
if reason == nil or not reason:find("%S") then reason = "no reason given" end
|
||||||
button_data.reason_callback(player, reason)
|
button_data.reason_callback(player, reason)
|
||||||
end
|
end
|
||||||
element.parent.entry.text = ""
|
assert(element.parent).entry.text = ""
|
||||||
Elements.container.set_selected_player(player, nil)
|
Elements.container.set_selected_player(player, nil)
|
||||||
Elements.player_table.refresh_player(player)
|
Elements.player_table.refresh_player(player)
|
||||||
end) --[[@as any]]
|
end) --[[@as any]]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ local Roles = require("modules/exp_legacy/expcore/roles")
|
|||||||
local Elements = {}
|
local Elements = {}
|
||||||
|
|
||||||
--- The flow precision values in the same order as production_precision_dropdown.items
|
--- The flow precision values in the same order as production_precision_dropdown.items
|
||||||
|
--- @type defines.flow_precision_index[]
|
||||||
local precision_indexes = {
|
local precision_indexes = {
|
||||||
defines.flow_precision_index.five_seconds,
|
defines.flow_precision_index.five_seconds,
|
||||||
defines.flow_precision_index.one_minute,
|
defines.flow_precision_index.one_minute,
|
||||||
@@ -129,7 +130,7 @@ Elements.production_table = Gui.define("production_stats/production_table")
|
|||||||
:track_all_elements()
|
:track_all_elements()
|
||||||
:draw(function(def, parent)
|
:draw(function(def, parent)
|
||||||
local scroll_table = Gui.elements.scroll_table(parent, 304, 4)
|
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
|
for i = 2, 4 do
|
||||||
display_alignments[i] = "right"
|
display_alignments[i] = "right"
|
||||||
end
|
end
|
||||||
@@ -183,7 +184,7 @@ end
|
|||||||
--- @param item_selector LuaGuiElement
|
--- @param item_selector LuaGuiElement
|
||||||
function Elements.production_table.remove_row(production_table, item_selector)
|
function Elements.production_table.remove_row(production_table, item_selector)
|
||||||
local rows = Elements.production_table.data[production_table].rows
|
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
|
rows[item_selector.index] = nil
|
||||||
Gui.destroy_if_valid(item_selector)
|
Gui.destroy_if_valid(item_selector)
|
||||||
for _, element in pairs(row) do
|
for _, element in pairs(row) do
|
||||||
@@ -196,7 +197,7 @@ end
|
|||||||
--- @param item_selector LuaGuiElement
|
--- @param item_selector LuaGuiElement
|
||||||
function Elements.production_table.reset_row(production_table, item_selector)
|
function Elements.production_table.reset_row(production_table, item_selector)
|
||||||
local rows = Elements.production_table.data[production_table].rows
|
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.production.caption = "0.00"
|
||||||
row.consumption.caption = "0.00"
|
row.consumption.caption = "0.00"
|
||||||
row.net.caption = "0.00"
|
row.net.caption = "0.00"
|
||||||
@@ -209,7 +210,7 @@ end
|
|||||||
--- @param row_data ExpGui_ProductionStats.elements.production_table.row_data
|
--- @param row_data ExpGui_ProductionStats.elements.production_table.row_data
|
||||||
function Elements.production_table.refresh_row(production_table, item_selector, row_data)
|
function Elements.production_table.refresh_row(production_table, item_selector, row_data)
|
||||||
local rows = Elements.production_table.data[production_table].rows
|
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.production.caption = row_data.production
|
||||||
row.consumption.caption = row_data.consumption
|
row.consumption.caption = row_data.consumption
|
||||||
row.net.caption = row_data.net
|
row.net.caption = row_data.net
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ local function new_quick_action(command, on_click)
|
|||||||
:style{
|
:style{
|
||||||
width = 160,
|
width = 160,
|
||||||
}
|
}
|
||||||
:on_click(on_click or function(def, player, element, event)
|
:on_click(on_click or function(_def, player, _element, _event)
|
||||||
command(player)
|
command(player)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
@@ -261,7 +261,8 @@ define_tab(
|
|||||||
|
|
||||||
local rules = Gui.elements.scroll_table(container, scroll_height, 1)
|
local rules = Gui.elements.scroll_table(container, scroll_height, 1)
|
||||||
rules.style = "bordered_table"
|
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
|
for i = 1, 15 do
|
||||||
Gui.elements.centered_label(rules, frame_width - 30, { "exp-gui_readme.rules-" .. i })
|
Gui.elements.centered_label(rules, frame_width - 30, { "exp-gui_readme.rules-" .. i })
|
||||||
@@ -287,7 +288,8 @@ define_tab(
|
|||||||
|
|
||||||
local commands = Gui.elements.scroll_table(container, scroll_height, 2)
|
local commands = Gui.elements.scroll_table(container, scroll_height, 2)
|
||||||
commands.style = "bordered_table"
|
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
|
for name, command in pairs(Commands.list_for_player(player)) do
|
||||||
Gui.elements.centered_label(commands, 120, name)
|
Gui.elements.centered_label(commands, 120, name)
|
||||||
@@ -359,32 +361,32 @@ define_tab(
|
|||||||
roles = { "Senior Administrator", "Administrator" },
|
roles = { "Senior Administrator", "Administrator" },
|
||||||
title = { "exp-gui_readme.backers-management" },
|
title = { "exp-gui_readme.backers-management" },
|
||||||
width = 230,
|
width = 230,
|
||||||
players = {},
|
players = {}, --- @type string[]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
roles = { "Board Member", "Senior Backer" },
|
roles = { "Board Member", "Senior Backer" },
|
||||||
title = { "exp-gui_readme.backers-board" },
|
title = { "exp-gui_readme.backers-board" },
|
||||||
width = 145,
|
width = 145,
|
||||||
players = {},
|
players = {}, --- @type string[]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
roles = { "Sponsor", "Supporter" },
|
roles = { "Sponsor", "Supporter" },
|
||||||
title = { "exp-gui_readme.backers-backers" },
|
title = { "exp-gui_readme.backers-backers" },
|
||||||
width = 196,
|
width = 196,
|
||||||
players = {},
|
players = {}, --- @type string[]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
roles = { "Moderator", "Trainee" },
|
roles = { "Moderator", "Trainee" },
|
||||||
title = { "exp-gui_readme.backers-staff" },
|
title = { "exp-gui_readme.backers-staff" },
|
||||||
width = 235,
|
width = 235,
|
||||||
players = {},
|
players = {}, --- @type string[]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
roles = {},
|
roles = {},
|
||||||
time = 3 * 3600 * 60,
|
time = 3 * 3600 * 60,
|
||||||
title = { "exp-gui_readme.backers-active" },
|
title = { "exp-gui_readme.backers-active" },
|
||||||
width = 235,
|
width = 235,
|
||||||
players = {},
|
players = {}, --- @type string[]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,6 +610,7 @@ define_tab(
|
|||||||
--- Main readme container
|
--- Main readme container
|
||||||
--- @class ExpGui_Readme.elements.container: ExpElement
|
--- @class ExpGui_Readme.elements.container: ExpElement
|
||||||
--- @field data table<LuaGuiElement, ExpGui_Readme.elements.container.elements>
|
--- @field data table<LuaGuiElement, ExpGui_Readme.elements.container.elements>
|
||||||
|
--- @overload fun(parent: LuaGuiElement): LuaGuiElement
|
||||||
Elements.container = Gui.define("readme/container")
|
Elements.container = Gui.define("readme/container")
|
||||||
:track_all_elements()
|
:track_all_elements()
|
||||||
:draw(function(def, parent)
|
:draw(function(def, parent)
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ Elements.milestone_table = Gui.define("research_milestones/milestone_table")
|
|||||||
|
|
||||||
do local _row_data = {}
|
do local _row_data = {}
|
||||||
--- @type ExpGui_ResearchMilestones.elements.milestone_table.row_data
|
--- @type ExpGui_ResearchMilestones.elements.milestone_table.row_data
|
||||||
|
--- @diagnostic disable-next-line: missing-fields
|
||||||
local empty_row_data = { color = font_color.positive }
|
local empty_row_data = { color = font_color.positive }
|
||||||
|
|
||||||
--- Get the row data for a force and research
|
--- Get the row data for a force and research
|
||||||
@@ -203,7 +204,7 @@ end
|
|||||||
--- @param row_index number
|
--- @param row_index number
|
||||||
--- @param row_data ExpGui_ResearchMilestones.elements.milestone_table.row_data
|
--- @param row_data ExpGui_ResearchMilestones.elements.milestone_table.row_data
|
||||||
function Elements.milestone_table.refresh_row(milestone_table, row_index, 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.name.caption = row_data.name
|
||||||
row.target.caption = row_data.target
|
row.target.caption = row_data.target
|
||||||
row.achieved.caption = row_data.achieved
|
row.achieved.caption = row_data.achieved
|
||||||
@@ -269,10 +270,9 @@ Elements.container = Gui.define("research_milestones/container")
|
|||||||
local milestone_table = Elements.milestone_table(container)
|
local milestone_table = Elements.milestone_table(container)
|
||||||
Elements.clock_label(header)
|
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
|
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)
|
local start_index = Elements.container.calculate_starting_research_index(force)
|
||||||
for research_index = start_index, start_index + display_size - 1 do
|
for research_index = start_index, start_index + display_size - 1 do
|
||||||
local row_data = Elements.milestone_table.calculate_row_data(force, research_index)
|
local row_data = Elements.milestone_table.calculate_row_data(force, research_index)
|
||||||
@@ -296,7 +296,7 @@ end
|
|||||||
--- @param research_index number
|
--- @param research_index number
|
||||||
--- @return number
|
--- @return number
|
||||||
function Elements.container.get_achieved_time(force, research_index)
|
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
|
end
|
||||||
|
|
||||||
--- Calculate the starting research index for a force
|
--- Calculate the starting research index for a force
|
||||||
|
|||||||
@@ -404,9 +404,9 @@ end
|
|||||||
--- @return ExpGui_RocketInfo.elements.progress_table.row_data[]
|
--- @return ExpGui_RocketInfo.elements.progress_table.row_data[]
|
||||||
function Elements.progress_table.calculate_row_data_all(silo_data)
|
function Elements.progress_table.calculate_row_data_all(silo_data)
|
||||||
local row_data = {}
|
local row_data = {}
|
||||||
for unit_number, silo_data in pairs(silo_data) do
|
for unit_number, silo in pairs(silo_data) do
|
||||||
if silo_data.entity.valid then
|
if silo.entity.valid then
|
||||||
row_data[unit_number] = Elements.progress_table.calculate_row_data(silo_data)
|
row_data[unit_number] = Elements.progress_table.calculate_row_data(silo)
|
||||||
else
|
else
|
||||||
-- Prune silos that are no longer valid
|
-- Prune silos that are no longer valid
|
||||||
silo_data[unit_number] = nil
|
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.padding = { 0, 2 }
|
||||||
progress.style.font_color = row_data.color
|
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
|
end
|
||||||
|
|
||||||
--- Remove a silo row from the progress table
|
--- Remove a silo row from the progress table
|
||||||
@@ -455,7 +456,8 @@ end
|
|||||||
--- @param row_data ExpGui_RocketInfo.elements.progress_table.row_data
|
--- @param row_data ExpGui_RocketInfo.elements.progress_table.row_data
|
||||||
function Elements.progress_table.refresh_row(progress_table, row_data)
|
function Elements.progress_table.refresh_row(progress_table, row_data)
|
||||||
local element_data = Elements.progress_table.data[progress_table]
|
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.x.caption = row_data.x
|
||||||
row.y.caption = row_data.y
|
row.y.caption = row_data.y
|
||||||
row.progress.caption = row_data.caption
|
row.progress.caption = row_data.caption
|
||||||
@@ -620,7 +622,8 @@ end
|
|||||||
function Elements.container.add_silo(entity)
|
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
|
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,
|
entity = entity,
|
||||||
launched = 0,
|
launched = 0,
|
||||||
awaiting_reset = false,
|
awaiting_reset = false,
|
||||||
@@ -632,7 +635,9 @@ end
|
|||||||
function Elements.container.increment_silo(entity)
|
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 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
|
if not silo_data then return end
|
||||||
silo_data.launched = silo_data.launched + 1
|
silo_data.launched = silo_data.launched + 1
|
||||||
silo_data.awaiting_reset = true
|
silo_data.awaiting_reset = true
|
||||||
@@ -654,7 +659,7 @@ Gui.toolbar.create_button{
|
|||||||
--- @param event EventData.on_cargo_pod_finished_ascending
|
--- @param event EventData.on_cargo_pod_finished_ascending
|
||||||
local function on_cargo_pod_finished_ascending(event)
|
local function on_cargo_pod_finished_ascending(event)
|
||||||
local force = event.cargo_pod.force --[[@as LuaForce]]
|
local force = event.cargo_pod.force --[[@as LuaForce]]
|
||||||
local rockets_launched = force.rockets_launched
|
local rockets_launched = force.rockets_launched --[[@as number]]
|
||||||
|
|
||||||
-- Update the launch stats for the force
|
-- Update the launch stats for the force
|
||||||
local stats = Elements.container.get_stats(force)
|
local stats = Elements.container.get_stats(force)
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ function Elements.production_label.calculate_display_data(tooltip, value, cutoff
|
|||||||
end
|
end
|
||||||
|
|
||||||
local suffix, caption = format_number(value)
|
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.caption = caption
|
||||||
display_data.suffix = suffix
|
display_data.suffix = suffix
|
||||||
display_data.tooltip = tooltip
|
display_data.tooltip = tooltip
|
||||||
@@ -193,7 +193,8 @@ Elements.science_table = Gui.define("science_production/science_table")
|
|||||||
local science_table = Gui.elements.scroll_table(parent, 190, 4)
|
local science_table = Gui.elements.scroll_table(parent, 190, 4)
|
||||||
local no_production_label = Elements.no_production_label(science_table)
|
local no_production_label = Elements.no_production_label(science_table)
|
||||||
Elements.no_production_label.refresh(no_production_label)
|
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
|
return science_table
|
||||||
end)
|
end)
|
||||||
:element_data{} --[[@as any]]
|
:element_data{} --[[@as any]]
|
||||||
@@ -220,7 +221,7 @@ function Elements.science_table.calculate_row_data(force, science_pack, row_data
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Return the pack data
|
-- 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.visible = production.total.made > 0
|
||||||
row_data.science_pack = science_pack
|
row_data.science_pack = science_pack
|
||||||
row_data.icon_style = icon_style
|
row_data.icon_style = icon_style
|
||||||
@@ -280,7 +281,8 @@ function Elements.science_table.add_row(science_table, row_data)
|
|||||||
column_count = 2,
|
column_count = 2,
|
||||||
}
|
}
|
||||||
delta_table.style.padding = 0
|
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
|
-- Draw the net production label
|
||||||
local net = Elements.production_label(science_table, row_data.net)
|
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
|
-- Update the icon
|
||||||
local icon = row.icon
|
local icon = row.icon
|
||||||
icon.style = row_data.icon_style
|
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
|
-- Update the element visibility
|
||||||
row.net_suffix.visible = true
|
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)
|
Elements.production_label.refresh(row.used, row_data.used)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @type table<string, { [string]: ExpGui_ScienceProduction.elements.science_table.row_data }>
|
do local _row_data = {} --- @type table<string, table<number, ExpGui_ScienceProduction.elements.science_table.row_data>>
|
||||||
do local _row_data = {}
|
|
||||||
--- Refresh the production tables for all online players
|
--- Refresh the production tables for all online players
|
||||||
function Elements.science_table.refresh_online()
|
function Elements.science_table.refresh_online()
|
||||||
-- Refresh the row data for online forces
|
-- Refresh the row data for online forces
|
||||||
@@ -416,8 +418,7 @@ function Elements.eta_label.refresh(eta_label)
|
|||||||
eta_label.tooltip = display_data.tooltip
|
eta_label.tooltip = display_data.tooltip
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @type Elements.eta_label.display_data
|
do local _display_data = {} --- @type table<string, Elements.eta_label.display_data>
|
||||||
do local _display_data = {}
|
|
||||||
--- Refresh the eta label for all online players
|
--- Refresh the eta label for all online players
|
||||||
function Elements.eta_label.refresh_online()
|
function Elements.eta_label.refresh_online()
|
||||||
-- Refresh the row data for online forces
|
-- Refresh the row data for online forces
|
||||||
@@ -430,11 +431,13 @@ do local _display_data = {}
|
|||||||
-- Update the eta labels
|
-- Update the eta labels
|
||||||
for player, eta_label in Elements.eta_label:online_elements() do
|
for player, eta_label in Elements.eta_label:online_elements() do
|
||||||
local display_data = _display_data[player.force.name]
|
local display_data = _display_data[player.force.name]
|
||||||
|
if display_data then
|
||||||
eta_label.caption = display_data.caption
|
eta_label.caption = display_data.caption
|
||||||
eta_label.tooltip = display_data.tooltip
|
eta_label.tooltip = display_data.tooltip
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Container added to the left gui flow
|
--- Container added to the left gui flow
|
||||||
--- @class ExpGui_ScienceProduction.elements.container: ExpElement
|
--- @class ExpGui_ScienceProduction.elements.container: ExpElement
|
||||||
@@ -477,8 +480,7 @@ local _fp_one_hour = defines.flow_precision_index.one_hour
|
|||||||
--- @field ten_minutes ExpGui_ScienceProduction._item_data
|
--- @field ten_minutes ExpGui_ScienceProduction._item_data
|
||||||
--- @field one_hour ExpGui_ScienceProduction._item_data
|
--- @field one_hour ExpGui_ScienceProduction._item_data
|
||||||
|
|
||||||
--- @type table<string, { [string]: ExpGui_ScienceProduction.item_production_data }>
|
do local _production_data = {} --- @type table<string, { [string]: ExpGui_ScienceProduction.item_production_data }>
|
||||||
do local _production_data = {}
|
|
||||||
|
|
||||||
--- Get the production stats for a force
|
--- Get the production stats for a force
|
||||||
--- @param flow_stats any
|
--- @param flow_stats any
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ Elements.task_list = Gui.define("task_list/task_list")
|
|||||||
--- @param task_list LuaGuiElement
|
--- @param task_list LuaGuiElement
|
||||||
--- @param task ExpGui_TaskList.Task
|
--- @param task ExpGui_TaskList.Task
|
||||||
function Elements.task_list.add_task(task_list, 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]
|
local view_task_buttons = Elements.task_list.data[task_list]
|
||||||
view_task_buttons[task.id] = Elements.view_task_button(task_list, task, container)
|
view_task_buttons[task.id] = Elements.view_task_button(task_list, task, container)
|
||||||
end
|
end
|
||||||
@@ -532,7 +532,7 @@ Elements.task_message_textfield = Gui.define("task_list/task_message_textfield")
|
|||||||
}
|
}
|
||||||
:on_text_changed(function(def, player, task_message_textfield)
|
:on_text_changed(function(def, player, task_message_textfield)
|
||||||
--- @cast def ExpGui_TaskList.elements.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
|
confirm_task_button.enabled = string.len(task_message_textfield.text) > 5
|
||||||
end) --[[@as any]]
|
end) --[[@as any]]
|
||||||
|
|
||||||
@@ -549,7 +549,7 @@ end
|
|||||||
function Elements.task_message_textfield.refresh(task_message_textfield, task)
|
function Elements.task_message_textfield.refresh(task_message_textfield, task)
|
||||||
local elements = Elements.task_message_textfield.data[task_message_textfield]
|
local elements = Elements.task_message_textfield.data[task_message_textfield]
|
||||||
local message = task.new and "" or task.title .. "\n" .. task.body
|
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.text = message
|
||||||
task_message_textfield.focus()
|
task_message_textfield.focus()
|
||||||
end
|
end
|
||||||
@@ -612,7 +612,7 @@ function Elements.confirm_task_button.parse(message)
|
|||||||
-- Trim the spaces of the string
|
-- Trim the spaces of the string
|
||||||
local trimmed = string.gsub(message, "^%s*(.-)%s*$", "%1")
|
local trimmed = string.gsub(message, "^%s*(.-)%s*$", "%1")
|
||||||
local title, body = string.match(trimmed, "(.-)\n(.*)")
|
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 not title then
|
||||||
-- If it doesn't match the pattern return the str as a title
|
-- If it doesn't match the pattern return the str as a title
|
||||||
parsed.title = trimmed
|
parsed.title = trimmed
|
||||||
@@ -755,9 +755,14 @@ end
|
|||||||
--- @field view_task_footer LuaGuiElement
|
--- @field view_task_footer LuaGuiElement
|
||||||
--- @field edit_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
|
--- Container added to the left gui flow
|
||||||
--- @class ExpGui_TaskList.elements.container: ExpElement
|
--- @class ExpGui_TaskList.elements.container: ExpElement
|
||||||
--- @field data table<LuaForce, ExpGui_TaskList.Task[]> | table<LuaGuiElement, ExpGui_TaskList.elements.container.elements> | table<"global_data", { next_task_id: number }>
|
--- @field data ExpGui_TaskList.elements.container.data
|
||||||
Elements.container = Gui.define("task_list/container")
|
Elements.container = Gui.define("task_list/container")
|
||||||
:track_all_elements()
|
:track_all_elements()
|
||||||
:draw(function(def, parent)
|
:draw(function(def, parent)
|
||||||
|
|||||||
+18
-18
@@ -11,22 +11,22 @@ local max = math.max
|
|||||||
local AABB = {}
|
local AABB = {}
|
||||||
|
|
||||||
--- Check if an area is valid
|
--- Check if an area is valid
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @return boolean # True if the area is valid
|
--- @return boolean # True if the area is valid
|
||||||
function AABB.valid(aabb)
|
function AABB.valid(aabb)
|
||||||
return aabb.left_top.x < aabb.right_bottom.x and aabb.left_top.y < aabb.right_bottom.y
|
return aabb.left_top.x < aabb.right_bottom.x and aabb.left_top.y < aabb.right_bottom.y
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the size of the area contained within an AABB
|
--- Returns the size of the area contained within an AABB
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @return number
|
--- @return number
|
||||||
function AABB.size(aabb)
|
function AABB.size(aabb)
|
||||||
return (aabb.right_bottom.x - aabb.left_top.x) * (aabb.right_bottom.y - aabb.left_top.y)
|
return (aabb.right_bottom.x - aabb.left_top.x) * (aabb.right_bottom.y - aabb.left_top.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Clone an area, allows for safe mutation of an input value
|
--- Clone an area, allows for safe mutation of an input value
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @return BoundingBox
|
--- @return BoundingBox.struct
|
||||||
function AABB.clone(aabb)
|
function AABB.clone(aabb)
|
||||||
return {
|
return {
|
||||||
left_top = { x = aabb.left_top.x, y = aabb.left_top.y },
|
left_top = { x = aabb.left_top.x, y = aabb.left_top.y },
|
||||||
@@ -35,8 +35,8 @@ function AABB.clone(aabb)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Expand an area to be integer aligned, expanding away from 0
|
--- Expand an area to be integer aligned, expanding away from 0
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @return BoundingBox
|
--- @return BoundingBox.struct
|
||||||
function AABB.expand(aabb)
|
function AABB.expand(aabb)
|
||||||
return {
|
return {
|
||||||
left_top = { x = floor(aabb.left_top.x), y = floor(aabb.left_top.y) },
|
left_top = { x = floor(aabb.left_top.x), y = floor(aabb.left_top.y) },
|
||||||
@@ -45,8 +45,8 @@ function AABB.expand(aabb)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Contract an area to be integer aligned, contracting towards 0
|
--- Contract an area to be integer aligned, contracting towards 0
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @return BoundingBox
|
--- @return BoundingBox.struct
|
||||||
function AABB.contract(aabb)
|
function AABB.contract(aabb)
|
||||||
return {
|
return {
|
||||||
left_top = { x = ceil(aabb.left_top.x), y = ceil(aabb.left_top.y) },
|
left_top = { x = ceil(aabb.left_top.x), y = ceil(aabb.left_top.y) },
|
||||||
@@ -55,9 +55,9 @@ function AABB.contract(aabb)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Expand an area to include all other areas
|
--- Expand an area to include all other areas
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @param ... BoundingBox
|
--- @param ... BoundingBox.struct
|
||||||
--- @return BoundingBox
|
--- @return BoundingBox.struct
|
||||||
function AABB.union(aabb, ...)
|
function AABB.union(aabb, ...)
|
||||||
local rtn = AABB.clone(aabb)
|
local rtn = AABB.clone(aabb)
|
||||||
for _, next_aabb in ipairs{ ... } do
|
for _, next_aabb in ipairs{ ... } do
|
||||||
@@ -70,9 +70,9 @@ function AABB.union(aabb, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Contract an area to include to the overlap of all areas
|
--- Contract an area to include to the overlap of all areas
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @param ... BoundingBox
|
--- @param ... BoundingBox.struct
|
||||||
--- @return BoundingBox? # Nil if there is no intersection
|
--- @return BoundingBox.struct? # Nil if there is no intersection
|
||||||
function AABB.intersect(aabb, ...)
|
function AABB.intersect(aabb, ...)
|
||||||
local rtn = AABB.clone(aabb)
|
local rtn = AABB.clone(aabb)
|
||||||
for _, next_aabb in ipairs{ ... } do
|
for _, next_aabb in ipairs{ ... } do
|
||||||
@@ -88,8 +88,8 @@ function AABB.intersect(aabb, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Check if a point is contained within an area
|
--- Check if a point is contained within an area
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @param point MapPosition
|
--- @param point MapPosition.struct
|
||||||
--- @return boolean # True if the point is within or on the edge of the bounding box
|
--- @return boolean # True if the point is within or on the edge of the bounding box
|
||||||
function AABB.contains_point(aabb, point)
|
function AABB.contains_point(aabb, point)
|
||||||
return point.x >= aabb.left_top.x and point.y >= aabb.left_top.y
|
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
|
end
|
||||||
|
|
||||||
--- Check if an area is fulling contained within another area
|
--- Check if an area is fulling contained within another area
|
||||||
--- @param aabb BoundingBox
|
--- @param aabb BoundingBox.struct
|
||||||
--- @param other BoundingBox
|
--- @param other BoundingBox.struct
|
||||||
--- @return boolean # True if the point is within or on the edge of the bounding box
|
--- @return boolean # True if the point is within or on the edge of the bounding box
|
||||||
function AABB.contains_area(aabb, other)
|
function AABB.contains_area(aabb, other)
|
||||||
return AABB.contains_point(aabb, other.left_top) and AABB.contains_point(aabb, other.right_bottom)
|
return AABB.contains_point(aabb, other.left_top) and AABB.contains_point(aabb, other.right_bottom)
|
||||||
|
|||||||
+18
-21
@@ -93,8 +93,8 @@ local Async = {
|
|||||||
Async.status = {}
|
Async.status = {}
|
||||||
|
|
||||||
--- @class Async.AsyncFunction
|
--- @class Async.AsyncFunction
|
||||||
--- @field id number The id of this async function
|
--- @field id string The id of this async function
|
||||||
--- @operator call: Async.AsyncReturn
|
--- @overload fun(...: any): Async.AsyncReturn<any>
|
||||||
Async._function_prototype = {}
|
Async._function_prototype = {}
|
||||||
|
|
||||||
Async._function_metatable = {
|
Async._function_metatable = {
|
||||||
@@ -104,10 +104,10 @@ Async._function_metatable = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- @class Async.AsyncReturn<F>
|
--- @class Async.AsyncReturn<F>
|
||||||
--- @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 args any[] The arguments to call the function with
|
||||||
--- @field tick number? If present, the function will be called on this game tick
|
--- @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 canceled boolean? True if the call has been canceled
|
||||||
--- @field completed boolean? True if the call has completed
|
--- @field completed boolean? True if the call has completed
|
||||||
--- @field return_values any? The return values of the function call
|
--- @field return_values any? The return values of the function call
|
||||||
@@ -123,20 +123,20 @@ script.register_metatable("AsyncReturn", Async._return_metatable)
|
|||||||
|
|
||||||
--- Storage Variables
|
--- Storage Variables
|
||||||
|
|
||||||
local resolve_next --- @type Async.AsyncReturn[] Stores a queue of async functions to be executed on the next tick
|
local resolve_next --- @type Async.AsyncReturn<any>[] 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_queue --- @type Async.AsyncReturn<any>[] Stores a queue of async functions to be executed on a later tick
|
||||||
|
|
||||||
--- Insert an item into the priority queue
|
--- Insert an item into the priority queue
|
||||||
--- @param pending Async.AsyncReturn
|
--- @param pending Async.AsyncReturn<any>
|
||||||
--- @return Async.AsyncReturn
|
--- @return Async.AsyncReturn<any>
|
||||||
local function add_to_next_tick(pending)
|
local function add_to_next_tick(pending)
|
||||||
resolve_next[#resolve_next + 1] = pending
|
resolve_next[#resolve_next + 1] = pending
|
||||||
return pending
|
return pending
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Insert an item into the priority queue
|
--- Insert an item into the priority queue
|
||||||
--- @param pending Async.AsyncReturn
|
--- @param pending Async.AsyncReturn<any>
|
||||||
--- @return Async.AsyncReturn
|
--- @return Async.AsyncReturn<any>
|
||||||
local function add_to_resolve_queue(pending)
|
local function add_to_resolve_queue(pending)
|
||||||
local tick = pending.tick
|
local tick = pending.tick
|
||||||
for index = #resolve_queue, 1, -1 do
|
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
|
--- 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
|
--- @param ... any The arguments to call the function with
|
||||||
--- @return Async.AsyncReturn
|
--- @return Async.AsyncReturn<any>
|
||||||
function Async._function_prototype:start_soon(...)
|
function Async._function_prototype:start_soon(...)
|
||||||
assert(Async._registered[self.id], "Async function is not registered")
|
assert(Async._registered[self.id], "Async function is not registered")
|
||||||
Async._queue_pressure[self.id] = Async._queue_pressure[self.id] + 1
|
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
|
--- Run an async function after the given number of ticks
|
||||||
--- @param ticks number The number of ticks to call the function after
|
--- @param ticks number The number of ticks to call the function after
|
||||||
--- @param ... any The arguments to call the function with
|
--- @param ... any The arguments to call the function with
|
||||||
--- @return Async.AsyncReturn
|
--- @return Async.AsyncReturn<any>
|
||||||
function Async._function_prototype:start_after(ticks, ...)
|
function Async._function_prototype:start_after(ticks, ...)
|
||||||
ExpUtil.assert_argument_type(ticks, "number", 1, "ticks")
|
ExpUtil.assert_argument_type(ticks, "number", 1, "ticks")
|
||||||
assert(ticks > 0, "Ticks must be a positive number")
|
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
|
--- 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
|
--- @param ... any The arguments to call the function with
|
||||||
--- @return Async.AsyncReturn | nil
|
--- @return Async.AsyncReturn<any> | nil
|
||||||
function Async._function_prototype:start_task(...)
|
function Async._function_prototype:start_task(...)
|
||||||
assert(Async._registered[self.id], "Async function is not registered")
|
assert(Async._registered[self.id], "Async function is not registered")
|
||||||
if Async._queue_pressure[self.id] > 0 then return end
|
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
|
--- Run an async function on this tick, then queue it based on its return value
|
||||||
--- @param ... any The arguments to call the function with
|
--- @param ... any The arguments to call the function with
|
||||||
--- @return Async.AsyncReturn
|
--- @return Async.AsyncReturn<any>
|
||||||
function Async._function_prototype:start_now(...)
|
function Async._function_prototype:start_now(...)
|
||||||
assert(Async._registered[self.id], "Async function is not registered")
|
assert(Async._registered[self.id], "Async function is not registered")
|
||||||
local status, rtn1, rtn2 = Async._registered[self.id](...)
|
local status, rtn1, rtn2 = Async._registered[self.id](...)
|
||||||
@@ -261,7 +261,6 @@ local empty_table = setmetatable({}, {
|
|||||||
--- Default status, will raise on_function_complete
|
--- Default status, will raise on_function_complete
|
||||||
--- @param ... any The return value of the async call
|
--- @param ... any The return value of the async call
|
||||||
--- @return Async.Status, any[]
|
--- @return Async.Status, any[]
|
||||||
--- @type Async.Status
|
|
||||||
function Async.status.complete(...)
|
function Async.status.complete(...)
|
||||||
if ... == nil then
|
if ... == nil then
|
||||||
return Async.status.complete, empty_table
|
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
|
--- 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
|
--- @param ... any The arguments to call the function with
|
||||||
--- @return Async.Status, any[]
|
--- @return Async.Status, any[]
|
||||||
--- @type Async.Status
|
|
||||||
function Async.status.continue(...)
|
function Async.status.continue(...)
|
||||||
if ... == nil then
|
if ... == nil then
|
||||||
return Async.status.continue, empty_table
|
return Async.status.continue, empty_table
|
||||||
@@ -284,7 +282,6 @@ end
|
|||||||
--- @param ticks number The number of ticks to delay for
|
--- @param ticks number The number of ticks to delay for
|
||||||
--- @param ... any The arguments to call the function with
|
--- @param ... any The arguments to call the function with
|
||||||
--- @return Async.Status, number, any[]
|
--- @return Async.Status, number, any[]
|
||||||
--- @type Async.Status
|
|
||||||
function Async.status.delay(ticks, ...)
|
function Async.status.delay(ticks, ...)
|
||||||
ExpUtil.assert_argument_type(ticks, "number", 1, "ticks")
|
ExpUtil.assert_argument_type(ticks, "number", 1, "ticks")
|
||||||
assert(ticks > 0, "Ticks must be a positive number")
|
assert(ticks > 0, "Ticks must be a positive number")
|
||||||
@@ -296,11 +293,11 @@ end
|
|||||||
|
|
||||||
--- Status Returns.
|
--- Status Returns.
|
||||||
|
|
||||||
--- @type Async.AsyncReturn[], Async.AsyncReturn[]
|
--- @type Async.AsyncReturn<any>[], Async.AsyncReturn<any>[]
|
||||||
local new_next, new_queue = {}, {} -- File scope to allow for reuse
|
local new_next, new_queue = {}, {} -- File scope to allow for reuse
|
||||||
|
|
||||||
--- Executes an async function and processes the return value
|
--- Executes an async function and processes the return value
|
||||||
--- @param pending Async.AsyncReturn
|
--- @param pending Async.AsyncReturn<any>
|
||||||
--- @param tick number
|
--- @param tick number
|
||||||
local function exec(pending, tick)
|
local function exec(pending, tick)
|
||||||
local async_func = Async._registered[pending.func_id]
|
local async_func = Async._registered[pending.func_id]
|
||||||
@@ -400,9 +397,9 @@ end
|
|||||||
--- @package
|
--- @package
|
||||||
function Async.on_init()
|
function Async.on_init()
|
||||||
if storage.exp_async_next == nil then
|
if storage.exp_async_next == nil then
|
||||||
--- @type Async.AsyncReturn[]
|
--- @type Async.AsyncReturn<any>[]
|
||||||
storage.exp_async_next = {}
|
storage.exp_async_next = {}
|
||||||
--- @type Async.AsyncReturn[]
|
--- @type Async.AsyncReturn<any>[]
|
||||||
storage.exp_async_queue = {}
|
storage.exp_async_queue = {}
|
||||||
end
|
end
|
||||||
Async.on_load()
|
Async.on_load()
|
||||||
|
|||||||
@@ -42,12 +42,14 @@ end
|
|||||||
--- @param options FlyingText.create_above_entity_param
|
--- @param options FlyingText.create_above_entity_param
|
||||||
function FlyingText.create_above_entity(options)
|
function FlyingText.create_above_entity(options)
|
||||||
local entity = assert(options.target_entity, "A target entity is required")
|
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 }
|
local offset = options.offset or { x = 0, y = 0 }
|
||||||
|
|
||||||
options.position = {
|
options.position = {
|
||||||
x = offset.x + entity.position.x,
|
x = offset.x + position.x,
|
||||||
y = offset.y + entity.position.y + size_y * 0.25,
|
y = offset.y + position.y + size_y * 0.25,
|
||||||
}
|
}
|
||||||
|
|
||||||
FlyingText.create(options)
|
FlyingText.create(options)
|
||||||
@@ -62,12 +64,14 @@ end
|
|||||||
function FlyingText.create_above_player(options)
|
function FlyingText.create_above_player(options)
|
||||||
local player = assert(options.target_player, "A target player is required")
|
local player = assert(options.target_player, "A target player is required")
|
||||||
local entity = player.character; if not entity then return end
|
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 }
|
local offset = options.offset or { x = 0, y = 0 }
|
||||||
|
|
||||||
options.position = {
|
options.position = {
|
||||||
x = offset.x + entity.position.x,
|
x = offset.x + position.x,
|
||||||
y = offset.y + entity.position.y + size_y * 0.25,
|
y = offset.y + position.y + size_y * 0.25,
|
||||||
}
|
}
|
||||||
|
|
||||||
FlyingText.create(options)
|
FlyingText.create(options)
|
||||||
@@ -82,13 +86,15 @@ end
|
|||||||
function FlyingText.create_as_player(options)
|
function FlyingText.create_as_player(options)
|
||||||
local player = assert(options.target_player, "A target player is required")
|
local player = assert(options.target_player, "A target player is required")
|
||||||
local entity = player.character; if not entity then return end
|
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 }
|
local offset = options.offset or { x = 0, y = 0 }
|
||||||
|
|
||||||
options.color = player.chat_color
|
options.color = player.chat_color
|
||||||
options.position = {
|
options.position = {
|
||||||
x = offset.x + entity.position.x,
|
x = offset.x + position.x,
|
||||||
y = offset.y + entity.position.y + size_y * 0.25,
|
y = offset.y + position.y + size_y * 0.25,
|
||||||
}
|
}
|
||||||
|
|
||||||
FlyingText.create(options)
|
FlyingText.create(options)
|
||||||
|
|||||||
@@ -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)
|
function ExpUtil.assert_argument_type(arg_value, type_name, arg_index, arg_name)
|
||||||
local failed, actual_type = check_type(arg_value, type_name)
|
local failed, actual_type = check_type(arg_value, type_name)
|
||||||
if failed then
|
if failed then
|
||||||
local func_name = getinfo(2, "n").name or "<anonymous>"
|
local func_name = assert(getinfo(2, "n")).name or "<anonymous>"
|
||||||
error(assert_argument_fmt:format(arg_index, func_name, arg_name or "Argument", type_name, actual_type), 2)
|
error(assert_argument_fmt:format(arg_index, func_name, arg_name or "Argument", type_name, actual_type), 2)
|
||||||
end
|
end
|
||||||
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
|
--- @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
|
--- @return string # The relative filepath of the given stack frame
|
||||||
function ExpUtil.safe_file_path(level)
|
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__")
|
local safe_source = debug_info.source:find("@__level__")
|
||||||
return safe_source == 1 and debug_info.short_src:sub(10, -5) or debug_info.source
|
return safe_source == 1 and debug_info.short_src:sub(10, -5) or debug_info.source
|
||||||
end
|
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
|
--- @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
|
--- @return string # The name of the module at the given stack frame
|
||||||
function ExpUtil.get_module_name(level)
|
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("/")
|
local next_slash = file_within_module:find("/")
|
||||||
if next_slash then
|
if next_slash then
|
||||||
return file_within_module:sub(1, next_slash - 1)
|
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
|
--- @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
|
--- @return string # The name of the function at the given stack frame or provided as an argument
|
||||||
function ExpUtil.get_function_name(func, raw)
|
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 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 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
|
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
|
--- @param raw boolean? When true there will not be any < > around the name
|
||||||
--- @return string # The relative filepath of the given stack frame
|
--- @return string # The relative filepath of the given stack frame
|
||||||
function ExpUtil.get_current_line(level, raw)
|
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 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
|
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
|
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)
|
function ExpUtil.auto_complete(options, input, use_key, rtn_key, use_pattern)
|
||||||
input = input:lower()
|
input = input:lower()
|
||||||
local plain = use_pattern ~= true
|
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
|
for k, v in pairs(options) do
|
||||||
local str = use_key and k or v
|
local str = use_key and k or v
|
||||||
local index = str:lower():find(input, nil, plain)
|
local index = str:lower():find(input, nil, plain)
|
||||||
@@ -284,7 +284,7 @@ function ExpUtil.format_any(value, options)
|
|||||||
end
|
end
|
||||||
return inspect(value, { depth = options.depth or 5, indent = "", newline = "", process = ExpUtil.safe_value })
|
return inspect(value, { depth = options.depth or 5, indent = "", newline = "", process = ExpUtil.safe_value })
|
||||||
end
|
end
|
||||||
return formatted
|
return formatted --[[@as LocalisedString]]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @alias Common.format_time_param_format "short" | "long" | "clock"
|
--- @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
|
-- Remove units that are not requested
|
||||||
if not units.days then
|
if not units.days then
|
||||||
rtn.hours = rtn.hours + rtn.days * 24
|
rtn.hours = assert(rtn.hours) + assert(rtn.days) * 24
|
||||||
rtn.days = nil
|
rtn.days = nil
|
||||||
end
|
end
|
||||||
if not units.hours then
|
if not units.hours then
|
||||||
rtn.minutes = rtn.minutes + rtn.hours * 60
|
rtn.minutes = assert(rtn.minutes) + assert(rtn.hours) * 60
|
||||||
rtn.hours = nil
|
rtn.hours = nil
|
||||||
end
|
end
|
||||||
if not units.minutes then
|
if not units.minutes then
|
||||||
rtn.seconds = rtn.seconds + rtn.minutes * 60
|
rtn.seconds = assert(rtn.seconds) + assert(rtn.minutes) * 60
|
||||||
rtn.minutes = nil
|
rtn.minutes = nil
|
||||||
end
|
end
|
||||||
if not units.seconds then
|
if not units.seconds then
|
||||||
@@ -487,7 +487,7 @@ function ExpUtil.get_storage_for_stack(options)
|
|||||||
-- Find a valid entity from the search results
|
-- Find a valid entity from the search results
|
||||||
local current, count, entities = cache.current, cache.count, cache.entities
|
local current, count, entities = cache.current, cache.count, cache.entities
|
||||||
for i = 1, cache.count do
|
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
|
if entity.can_insert(item) then
|
||||||
cache.current = current + 1
|
cache.current = current + 1
|
||||||
return entity
|
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.
|
--- 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
|
--- @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)
|
function ExpUtil.copy_items_to_surface(options)
|
||||||
local entity
|
local entity
|
||||||
for item_index = 1, #options.items do
|
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.
|
--- 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
|
--- @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)
|
function ExpUtil.move_items_to_surface(options)
|
||||||
local entity
|
local entity
|
||||||
for item_index = 1, #options.items do
|
for item_index = 1, #options.items do
|
||||||
@@ -551,7 +551,8 @@ function ExpUtil.move_items_to_surface(options)
|
|||||||
options.item = item
|
options.item = item
|
||||||
entity = ExpUtil.get_storage_for_stack(options)
|
entity = ExpUtil.get_storage_for_stack(options)
|
||||||
entity.insert(options.item)
|
entity.insert(options.item)
|
||||||
options.item.clear()
|
local item_stack = options.item --[[@as LuaItemStack]]
|
||||||
|
item_stack.clear()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return entity
|
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.
|
--- 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
|
--- @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)
|
function ExpUtil.transfer_inventory_to_surface(options)
|
||||||
options.items = options.inventory
|
options.items = options.inventory
|
||||||
local entity = ExpUtil.copy_items_to_surface(options)
|
local entity = ExpUtil.copy_items_to_surface(options)
|
||||||
@@ -604,6 +605,7 @@ end
|
|||||||
--- @return string
|
--- @return string
|
||||||
function ExpUtil.comma_value(n) -- credit http://richard.warburton.it
|
function ExpUtil.comma_value(n) -- credit http://richard.warburton.it
|
||||||
local left, num, right = string.match(n, "^([^%d]*%d)(%d*)(.-)$")
|
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
|
return left .. (num:reverse():gsub("(%d%d%d)", "%1, "):reverse()) .. right
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ local Selection = {
|
|||||||
--- @field player_index number
|
--- @field player_index number
|
||||||
--- @field selection Selection.Active
|
--- @field selection Selection.Active
|
||||||
|
|
||||||
--- @type table<string, { [defines.events]: Selection.event_handler[] }>
|
--- @type table<string, { [defines.events]: Selection.event_handler<any>[] }>
|
||||||
_registered = {},
|
_registered = {},
|
||||||
|
|
||||||
--- @package
|
--- @package
|
||||||
@@ -54,7 +54,7 @@ local selection_tool = { name = "selection-tool" }
|
|||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return boolean?
|
--- @return boolean?
|
||||||
local function has_selection_tool_in_hand(player)
|
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
|
end
|
||||||
|
|
||||||
--- Give a selection tool to a player if they don't have one
|
--- Give a selection tool to a player if they don't have one
|
||||||
@@ -62,7 +62,7 @@ end
|
|||||||
local function give_selection_tool(player)
|
local function give_selection_tool(player)
|
||||||
if has_selection_tool_in_hand(player) then return end
|
if has_selection_tool_in_hand(player) then return end
|
||||||
player.clear_cursor()
|
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
|
-- This does not work for selection planners, will make a feature request for it
|
||||||
--player.cursor_stack_temporary = true
|
--player.cursor_stack_temporary = true
|
||||||
@@ -84,7 +84,7 @@ end
|
|||||||
local function remove_selection_tool(player, old_character)
|
local function remove_selection_tool(player, old_character)
|
||||||
-- Remove the selection tool
|
-- Remove the selection tool
|
||||||
if has_selection_tool_in_hand(player) then
|
if has_selection_tool_in_hand(player) then
|
||||||
player.cursor_stack.clear()
|
assert(player.cursor_stack).clear()
|
||||||
else
|
else
|
||||||
player.remove_item(selection_tool)
|
player.remove_item(selection_tool)
|
||||||
end
|
end
|
||||||
|
|||||||
+6
-37
@@ -1,39 +1,8 @@
|
|||||||
---@meta
|
---@meta
|
||||||
|
|
||||||
---@class script
|
--- The api documents MapPosition and BoundingBox as a union of the named form
|
||||||
script = {
|
--- and a positional array, because both are accepted as input. Everything read
|
||||||
---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:
|
--- back from the game uses the named form, and we always write it that way too,
|
||||||
---
|
--- so the positional variant is removed here.
|
||||||
---Events that can be raised manually:
|
---@alias MapPosition MapPosition.struct
|
||||||
---
|
---@alias BoundingBox BoundingBox.struct
|
||||||
---* [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
|
|
||||||
|
|||||||
Reference in New Issue
Block a user