mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-08-12 16:35:11 +09:00
Final manual fixups
This commit is contained in:
+2
-2
@@ -5,8 +5,8 @@ All are welcome to make bug reports, feature requests, and pull requests for our
|
||||
For developers wanting to add features please follow these guidelines:
|
||||
|
||||
- All lua code is documented using ldoc.
|
||||
- Set `CLUSTERIO` to your clusterio checkout, the lint needs it to resolve `modules/clusterio/*`. emmylua does not normalise `..` in a library path, so it cannot be written relative to this repo.
|
||||
- Lua is checked with [emmylua](https://github.com/EmmyLuaLs/emmylua-analyzer-rust), configured by `.emmyrc.json`. Install the EmmyLua extension rather than sumneko, and let the factoriomod-debug extension write your machine local library paths to `.luarc.json`, which is git ignored. Note that an inline cast must be written `--[[@as T]]`, the spaced form is not parsed.
|
||||
- Set the `CLUSTERIO` environment variable to your clusterio development install path, the lint needs it to resolve `modules/clusterio/*`.
|
||||
- Lua is checked with [emmylua](https://github.com/EmmyLuaLs/emmylua-analyzer-rust), configured by `.emmyrc.json`. Install the EmmyLua extension rather than sumnekolua / luals, and use factoriomod-debug to generate the factorio api types. Note that an inline cast must be written `--[[@as T]]`, the spaced form is not parsed.
|
||||
- Changes should be made on your own fork and merged into `main` through a pull request.
|
||||
- Each pull request should be limited to one feature or a few bug fixes and link to the related issue page.
|
||||
- Pull requests are automatically linted and documentation checked.
|
||||
|
||||
@@ -25,18 +25,18 @@ end)
|
||||
--- @param page_size number The number of requests to show per page
|
||||
--- @return LocalisedString[][], number
|
||||
local function format_as_pages(commands, page_size)
|
||||
local pages = { {} }
|
||||
local current_page = {}
|
||||
local pages = { current_page }
|
||||
local page_length = 0
|
||||
local current_page = 1
|
||||
local total = 0
|
||||
|
||||
for _, command in pairs(commands) do
|
||||
total = total + 1
|
||||
page_length = page_length + 1
|
||||
if page_length > page_size then
|
||||
current_page = current_page + 1
|
||||
pages[current_page] = {}
|
||||
page_length = 1
|
||||
current_page = {}
|
||||
pages[#pages + 1] = current_page
|
||||
end
|
||||
|
||||
local description
|
||||
@@ -48,7 +48,7 @@ local function format_as_pages(commands, page_size)
|
||||
end
|
||||
|
||||
local aliases = #command.aliases > 0 and { "exp-commands_help.aliases", table.concat(command.aliases, ", ") } or ""
|
||||
assert(pages[current_page])[page_length] = { "exp-commands_help.format", command.name, description, aliases }
|
||||
current_page[page_length] = { "exp-commands_help.format", command.name, description, aliases }
|
||||
end
|
||||
|
||||
return pages, total
|
||||
|
||||
@@ -116,8 +116,8 @@ end
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function Gui.get_top_element(define, player)
|
||||
local value = assert(assert(player_elements[player.index]).top[define.name], "Element is not on the top flow")
|
||||
return value
|
||||
local elements = assert(player_elements[player.index])
|
||||
return (assert(elements.top[define.name], "Element is not on the top flow"))
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the left flow on join
|
||||
@@ -125,8 +125,8 @@ end
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function Gui.get_left_element(define, player)
|
||||
local value = assert(assert(player_elements[player.index]).left[define.name], "Element is not on the left flow")
|
||||
return value
|
||||
local elements = assert(player_elements[player.index])
|
||||
return (assert(elements.left[define.name], "Element is not on the left flow"))
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the relative flow on join
|
||||
@@ -134,8 +134,8 @@ end
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function Gui.get_relative_element(define, player)
|
||||
local value = assert(assert(player_elements[player.index]).relative[define.name], "Element is not on the relative flow")
|
||||
return value
|
||||
local elements = assert(player_elements[player.index])
|
||||
return (assert(elements.relative[define.name], "Element is not on the relative flow"))
|
||||
end
|
||||
|
||||
--- Ensure all the correct elements are visible and exist
|
||||
|
||||
@@ -319,8 +319,7 @@ Elements.screen_frame = Gui.define("screen_frame")
|
||||
--- @param screen_frame LuaGuiElement
|
||||
--- @return LuaGuiElement
|
||||
function Elements.screen_frame.get_button_flow(screen_frame)
|
||||
local value = assert(Elements.screen_frame.data[assert(screen_frame.parent)], "Screen frame has no button flow")
|
||||
return value
|
||||
return (assert(Elements.screen_frame.data[assert(screen_frame.parent)], "Screen frame has no button flow"))
|
||||
end
|
||||
|
||||
--- Get the root element of a screen frame
|
||||
|
||||
@@ -168,8 +168,7 @@ end
|
||||
--- @param name string
|
||||
--- @return ExpElement
|
||||
function ExpElement.get(name)
|
||||
local value = assert(ExpElement._elements[name], "ExpElement is not defined: " .. tostring(name))
|
||||
return value
|
||||
return (assert(ExpElement._elements[name], "ExpElement is not defined: " .. tostring(name)))
|
||||
end
|
||||
|
||||
--- Create a new instance of this element definition
|
||||
|
||||
@@ -150,6 +150,8 @@ local Storage = require("modules/exp_util/storage")
|
||||
|
||||
local DatastoreManager = {}
|
||||
local Datastores = {} --- @type table<string, Datastore>
|
||||
local Data = {}
|
||||
|
||||
--- @class Datastore
|
||||
--- @field name string
|
||||
--- @field value_name string
|
||||
@@ -163,7 +165,7 @@ local Datastores = {} --- @type table<string, Datastore>
|
||||
--- @field events table<string, function[]>
|
||||
--- @field data table
|
||||
local Datastore = {}
|
||||
local Data = {}
|
||||
|
||||
local copy = table.deep_copy
|
||||
local trace = debug.traceback
|
||||
local table_to_json = helpers.table_to_json
|
||||
|
||||
@@ -50,8 +50,7 @@ local servers = External.get_servers()
|
||||
]]
|
||||
function External.get_servers()
|
||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
local value = assert(ext.servers, "No server list was found, please ensure that the external service is running")
|
||||
return value
|
||||
return (assert(ext.servers, "No server list was found, please ensure that the external service is running"))
|
||||
end
|
||||
|
||||
--[[-- Gets a table of all the servers filtered by name, key is the server id, value is the server details
|
||||
@@ -86,8 +85,7 @@ function External.get_current_server()
|
||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
local servers = assert(ext.servers, "No server list was found, please ensure that the external service is running")
|
||||
local server_id = assert(ext.current, "No current id was found, please ensure that the external service is running")
|
||||
local value = assert(servers[server_id], "No details found for server with id: " .. tostring(server_id))
|
||||
return value
|
||||
return (assert(servers[server_id], "No details found for server with id: " .. tostring(server_id)))
|
||||
end
|
||||
|
||||
--[[-- Gets the details of the given server
|
||||
@@ -101,8 +99,7 @@ local server = External.get_server_details('eu-01')
|
||||
function External.get_server_details(server_id)
|
||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
local servers = assert(ext.servers, "No server list was found, please ensure that the external service is running")
|
||||
local value = assert(servers[server_id], "No details found for server with id: " .. tostring(server_id))
|
||||
return value
|
||||
return (assert(servers[server_id], "No details found for server with id: " .. tostring(server_id)))
|
||||
end
|
||||
|
||||
--[[-- Gets the status of the given server
|
||||
|
||||
@@ -376,8 +376,7 @@ function Roles.get_player_highest_role(player)
|
||||
end
|
||||
end
|
||||
|
||||
local value = assert(highest, "Player has no roles")
|
||||
return value
|
||||
return (assert(highest, "Player has no roles"))
|
||||
end
|
||||
|
||||
--- Assignment.
|
||||
|
||||
@@ -15,7 +15,7 @@ local abs = math.abs
|
||||
local commands = {}
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param area ExpUtil_AABB.Box
|
||||
--- @param area BoundingBox.struct
|
||||
--- @return boolean
|
||||
local function location_break(player, area)
|
||||
local surface = player.surface -- Allow remote view
|
||||
|
||||
@@ -37,7 +37,7 @@ end
|
||||
|
||||
--- Get the key used in protected_areas
|
||||
--- TODO expose this from EntityProtection
|
||||
--- @param area ExpUtil_AABB.Box
|
||||
--- @param area BoundingBox.struct
|
||||
--- @return string
|
||||
local function get_area_key(area)
|
||||
return format_string("%i,%i", floor(area.left_top.x), floor(area.left_top.y))
|
||||
@@ -49,7 +49,7 @@ end
|
||||
local function show_protected_entity(player, entity)
|
||||
local key = get_entity_key(entity)
|
||||
if renders[player.index][key] then return end
|
||||
local selection_box = entity.selection_box --[[@as ExpUtil_AABB.Box]]
|
||||
local selection_box = entity.selection_box
|
||||
local rb = selection_box.right_bottom
|
||||
local position = entity.position
|
||||
renders[player.index][key] = rendering.draw_sprite{
|
||||
@@ -69,7 +69,7 @@ end
|
||||
--- Show a protected area to a player
|
||||
--- @param player LuaPlayer
|
||||
--- @param surface LuaSurface
|
||||
--- @param area ExpUtil_AABB.Box
|
||||
--- @param area BoundingBox.struct
|
||||
local function show_protected_area(player, surface, area)
|
||||
local key = get_area_key(area)
|
||||
if renders[player.index][key] then return end
|
||||
|
||||
@@ -55,8 +55,7 @@ Commands.new("get-roles", { "exp-commands_roles.description-get" })
|
||||
end
|
||||
|
||||
local last = #roles_formatted
|
||||
--- @diagnostic disable-next-line: need-check-nil
|
||||
roles_formatted[last] = roles_formatted[last][2]
|
||||
roles_formatted[last] = assert(roles_formatted[last])[2]
|
||||
|
||||
return Commands.status.success(response)
|
||||
end)
|
||||
|
||||
@@ -42,7 +42,7 @@ local function format_position(pos)
|
||||
end
|
||||
|
||||
--- Convert an area to a string
|
||||
--- @param area ExpUtil_AABB.Box
|
||||
--- @param area BoundingBox.struct
|
||||
--- @return string
|
||||
local function format_area(area)
|
||||
return format_string("%.1f,%.1f,%.1f,%.1f", area.left_top.x, area.left_top.y, area.right_bottom.x, area.right_bottom.y)
|
||||
@@ -137,8 +137,7 @@ local function on_player_ammo_inventory_changed(event)
|
||||
if not player or not player.character then return end
|
||||
|
||||
local character_ammo = assert(player.get_inventory(defines.inventory.character_ammo))
|
||||
local gun_index = player.character.selected_gun_index
|
||||
--- @cast gun_index uint
|
||||
local gun_index = player.character.selected_gun_index --[[@as uint]]
|
||||
local item = character_ammo[gun_index]
|
||||
if not item or not item.valid or not item.valid_for_read then
|
||||
return
|
||||
|
||||
@@ -32,7 +32,7 @@ local function degrade_entity(entity)
|
||||
|
||||
local tiles = {}
|
||||
local surface = entity.surface
|
||||
local bounding_box = entity.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
local bounding_box = entity.bounding_box
|
||||
local left_top = bounding_box.left_top
|
||||
local right_bottom = bounding_box.right_bottom
|
||||
for x = left_top.x, right_bottom.x do
|
||||
|
||||
@@ -167,7 +167,7 @@ local function try_deconstruct_miner(entity)
|
||||
create_entity(create_entity_param)
|
||||
|
||||
-- Find all the entities to connect to
|
||||
local bounding_box = entity.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
local bounding_box = entity.bounding_box
|
||||
local search_area = {
|
||||
{ bounding_box.left_top.x - 1, bounding_box.left_top.y - 1 },
|
||||
{ bounding_box.right_bottom.x + 1, bounding_box.right_bottom.y + 1 },
|
||||
|
||||
@@ -57,7 +57,7 @@ local function rename_station(event)
|
||||
-- Find the closest resource
|
||||
local icon = ""
|
||||
local item_name = ""
|
||||
local bounding_box = entity.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
local bounding_box = entity.bounding_box
|
||||
local resources = entity.surface.find_entities_filtered{ position = entity.position, radius = 250, type = "resource" }
|
||||
if #resources > 0 then
|
||||
local closest_recourse --- @type LuaEntity?
|
||||
@@ -66,7 +66,7 @@ local function rename_station(event)
|
||||
|
||||
-- Check which recourse is closest
|
||||
for _, resource in ipairs(resources) do
|
||||
local resource_box = resource.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
local resource_box = resource.bounding_box
|
||||
local dx = px - resource_box.left_top.x
|
||||
local dy = py - resource_box.left_top.y
|
||||
local distance = (dx * dx) + (dy * dy)
|
||||
|
||||
@@ -427,7 +427,7 @@ local function on_entity_settings_pasted(event)
|
||||
-- Attempt to rotate a machine to match the source machine
|
||||
if (source.name == destination.name or source.prototype.fast_replaceable_group == destination.prototype.fast_replaceable_group) then
|
||||
if source.supports_direction and destination.supports_direction and source.type ~= "transport-belt" then
|
||||
local destination_box = destination.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
local destination_box = destination.bounding_box
|
||||
|
||||
local ltx = destination_box.left_top.x
|
||||
local lty = destination_box.left_top.y
|
||||
|
||||
@@ -433,8 +433,7 @@ function Elements.progress_table.add_row(progress_table, row_data)
|
||||
progress.style.padding = { 0, 2 }
|
||||
progress.style.font_color = row_data.color
|
||||
|
||||
local unit_number = row_data.entity.unit_number
|
||||
--- @cast unit_number uint
|
||||
local unit_number = row_data.entity.unit_number --[[@as uint]]
|
||||
rows[unit_number] = { x = x, y = y, progress = progress }
|
||||
end
|
||||
|
||||
@@ -457,8 +456,7 @@ end
|
||||
--- @param row_data ExpGui_RocketInfo.elements.progress_table.row_data
|
||||
function Elements.progress_table.refresh_row(progress_table, row_data)
|
||||
local element_data = Elements.progress_table.data[progress_table]
|
||||
local unit_number = row_data.entity.unit_number
|
||||
--- @cast unit_number uint
|
||||
local unit_number = row_data.entity.unit_number --[[@as uint]]
|
||||
local row = element_data.rows[unit_number]
|
||||
row.x.caption = row_data.x
|
||||
row.y.caption = row_data.y
|
||||
@@ -624,8 +622,7 @@ end
|
||||
function Elements.container.add_silo(entity)
|
||||
local force = entity.force --[[@as LuaForce]]
|
||||
local silos = Elements.container._get_force_data(force).silos
|
||||
local unit_number = entity.unit_number
|
||||
--- @cast unit_number uint
|
||||
local unit_number = entity.unit_number --[[@as uint]]
|
||||
silos[unit_number] = {
|
||||
entity = entity,
|
||||
launched = 0,
|
||||
@@ -661,9 +658,8 @@ Gui.toolbar.create_button{
|
||||
--- Record the launch and update the stats when a cargo pod finishes ascending
|
||||
--- @param event EventData.on_cargo_pod_finished_ascending
|
||||
local function on_cargo_pod_finished_ascending(event)
|
||||
local force = event.cargo_pod.force
|
||||
--- @cast force LuaForce
|
||||
local rockets_launched = force.rockets_launched
|
||||
local force = event.cargo_pod.force --[[@as LuaForce]]
|
||||
local rockets_launched = force.rockets_launched --[[@as number]]
|
||||
|
||||
-- Update the launch stats for the force
|
||||
local stats = Elements.container.get_stats(force)
|
||||
@@ -678,7 +674,6 @@ local function on_cargo_pod_finished_ascending(event)
|
||||
|
||||
-- Append the launch tick into the times array
|
||||
local times = Elements.container.get_launch_times(force)
|
||||
--- @cast rockets_launched uint
|
||||
times[rockets_launched] = event.tick
|
||||
|
||||
-- Discard the launch time that is no longer needed by any rolling average unless it is a milestone
|
||||
|
||||
+17
-22
@@ -7,31 +7,26 @@ local ceil = math.ceil
|
||||
local min = math.min
|
||||
local max = math.max
|
||||
|
||||
--- An axis aligned bounding box using named members, the shorthand form is not supported
|
||||
--- @class ExpUtil_AABB.Box
|
||||
--- @field left_top MapPosition.struct
|
||||
--- @field right_bottom MapPosition.struct
|
||||
|
||||
--- @class ExpUtil_AABB
|
||||
local AABB = {}
|
||||
|
||||
--- Check if an area is valid
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @return boolean # True if the area is valid
|
||||
function AABB.valid(aabb)
|
||||
return aabb.left_top.x < aabb.right_bottom.x and aabb.left_top.y < aabb.right_bottom.y
|
||||
end
|
||||
|
||||
--- Returns the size of the area contained within an AABB
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @return number
|
||||
function AABB.size(aabb)
|
||||
return (aabb.right_bottom.x - aabb.left_top.x) * (aabb.right_bottom.y - aabb.left_top.y)
|
||||
end
|
||||
|
||||
--- Clone an area, allows for safe mutation of an input value
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @return ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @return BoundingBox.struct
|
||||
function AABB.clone(aabb)
|
||||
return {
|
||||
left_top = { x = aabb.left_top.x, y = aabb.left_top.y },
|
||||
@@ -40,8 +35,8 @@ function AABB.clone(aabb)
|
||||
end
|
||||
|
||||
--- Expand an area to be integer aligned, expanding away from 0
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @return ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @return BoundingBox.struct
|
||||
function AABB.expand(aabb)
|
||||
return {
|
||||
left_top = { x = floor(aabb.left_top.x), y = floor(aabb.left_top.y) },
|
||||
@@ -50,8 +45,8 @@ function AABB.expand(aabb)
|
||||
end
|
||||
|
||||
--- Contract an area to be integer aligned, contracting towards 0
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @return ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @return BoundingBox.struct
|
||||
function AABB.contract(aabb)
|
||||
return {
|
||||
left_top = { x = ceil(aabb.left_top.x), y = ceil(aabb.left_top.y) },
|
||||
@@ -60,9 +55,9 @@ function AABB.contract(aabb)
|
||||
end
|
||||
|
||||
--- Expand an area to include all other areas
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @param ... ExpUtil_AABB.Box
|
||||
--- @return ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @param ... BoundingBox.struct
|
||||
--- @return BoundingBox.struct
|
||||
function AABB.union(aabb, ...)
|
||||
local rtn = AABB.clone(aabb)
|
||||
for _, next_aabb in ipairs{ ... } do
|
||||
@@ -75,9 +70,9 @@ function AABB.union(aabb, ...)
|
||||
end
|
||||
|
||||
--- Contract an area to include to the overlap of all areas
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @param ... ExpUtil_AABB.Box
|
||||
--- @return ExpUtil_AABB.Box? # Nil if there is no intersection
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @param ... BoundingBox.struct
|
||||
--- @return BoundingBox.struct? # Nil if there is no intersection
|
||||
function AABB.intersect(aabb, ...)
|
||||
local rtn = AABB.clone(aabb)
|
||||
for _, next_aabb in ipairs{ ... } do
|
||||
@@ -93,7 +88,7 @@ function AABB.intersect(aabb, ...)
|
||||
end
|
||||
|
||||
--- Check if a point is contained within an area
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @param point MapPosition.struct
|
||||
--- @return boolean # True if the point is within or on the edge of the bounding box
|
||||
function AABB.contains_point(aabb, point)
|
||||
@@ -102,8 +97,8 @@ function AABB.contains_point(aabb, point)
|
||||
end
|
||||
|
||||
--- Check if an area is fulling contained within another area
|
||||
--- @param aabb ExpUtil_AABB.Box
|
||||
--- @param other ExpUtil_AABB.Box
|
||||
--- @param aabb BoundingBox.struct
|
||||
--- @param other BoundingBox.struct
|
||||
--- @return boolean # True if the point is within or on the edge of the bounding box
|
||||
function AABB.contains_area(aabb, other)
|
||||
return AABB.contains_point(aabb, other.left_top) and AABB.contains_point(aabb, other.right_bottom)
|
||||
|
||||
@@ -42,7 +42,7 @@ end
|
||||
--- @param options FlyingText.create_above_entity_param
|
||||
function FlyingText.create_above_entity(options)
|
||||
local entity = assert(options.target_entity, "A target entity is required")
|
||||
local bounding_box = entity.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
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 }
|
||||
@@ -64,7 +64,7 @@ end
|
||||
function FlyingText.create_above_player(options)
|
||||
local player = assert(options.target_player, "A target player is required")
|
||||
local entity = player.character; if not entity then return end
|
||||
local bounding_box = entity.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
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 }
|
||||
@@ -86,7 +86,7 @@ end
|
||||
function FlyingText.create_as_player(options)
|
||||
local player = assert(options.target_player, "A target player is required")
|
||||
local entity = player.character; if not entity then return end
|
||||
local bounding_box = entity.bounding_box --[[@as ExpUtil_AABB.Box]]
|
||||
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 }
|
||||
|
||||
Reference in New Issue
Block a user