mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-11-13 16:14:52 +09:00
Review feedback from Cooldude on the first version.
Features.register is renamed to Features.config, and guard also takes a
feature name so a feature without settings needs no config call.
Autofill uses this. Small configs now live at the top of the file that
uses them: death markers, mine depletion, station auto name, and
lawnmower. AFK kick and chat auto reply keep separate files because
they contain functions.
Periods no longer need a restart. A lib can list intervals, which map a
config key to a handler that runs every config[key] seconds. They are
checked once a second with a stateless tick check. AFK kick and death
markers use this and expose their periods on the page.
Guis: receive_update raises on_feature_changed, and control/features.lua
refreshes every player's gui when it fires. Autofill's toolbar button
checks Features.is_enabled, and hiding the button also hides its left
element. Quick actions refresh on the event too.
Commands: add_flags{ feature = ... } ties a command to a feature, and a
new authority denies it while the feature is disabled. The custom help
and quick actions already leave out denied commands. Lawnmower uses this
and is now added as a lib, so its destroy_decoratives handlers are
actually registered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
113 lines
4.0 KiB
Lua
113 lines
4.0 KiB
Lua
--[[-- Control - Station Auto Name
|
|
Automatically name stations when they are placed based on closest resource and direction from spawn
|
|
]]
|
|
|
|
local Features = require("modules/exp_scenario/features")
|
|
|
|
local config = Features.config("station_auto_name", {
|
|
--- @setting station_name the name given to new stations, placeholders:
|
|
-- __icon__ __item_name__ __backer_name__ __direction__ __x__ __y__
|
|
station_name = "[L] __icon__",
|
|
})
|
|
|
|
local get_direction do
|
|
local directions = {
|
|
["W"] = -0.875,
|
|
["NW"] = -0.625,
|
|
["N"] = -0.375,
|
|
["NE"] = -0.125,
|
|
["E"] = 0.125,
|
|
["SE"] = 0.375,
|
|
["S"] = 0.625,
|
|
["SW"] = 0.875,
|
|
}
|
|
|
|
--- Get the direction of a position from the centre of the surface
|
|
--- @param position MapPosition
|
|
--- @return string
|
|
function get_direction(position)
|
|
local angle = math.atan2(position.y, position.x) / math.pi
|
|
for direction, required_angle in pairs(directions) do
|
|
if angle < required_angle then
|
|
return direction
|
|
end
|
|
end
|
|
|
|
return "W"
|
|
end
|
|
end
|
|
|
|
-- Custom strings are used to detect backer names from ghosts
|
|
local custom_string = " *"
|
|
local custom_string_len = #custom_string
|
|
|
|
--- Change the name of a station when it is placed
|
|
--- @param event EventData.on_built_entity | EventData.on_robot_built_entity
|
|
local function rename_station(event)
|
|
local entity = event.entity
|
|
local name = entity.name
|
|
if name == "entity-ghost" and entity.ghost_name == "train-stop" then
|
|
local backer_name = entity.backer_name
|
|
if backer_name ~= "" then
|
|
entity.backer_name = backer_name .. custom_string
|
|
end
|
|
|
|
elseif name == "train-stop" then
|
|
-- Restore the backer name
|
|
local backer_name = entity.backer_name or ""
|
|
if backer_name:sub(-custom_string_len) == custom_string then
|
|
entity.backer_name = backer_name:sub(1, -custom_string_len - 1)
|
|
return
|
|
end
|
|
|
|
-- Find the closest resource
|
|
local icon = ""
|
|
local item_name = ""
|
|
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?
|
|
local closest_distance = 250 * 250 -- search radius + 1
|
|
local px, py = bounding_box.left_top.x, bounding_box.left_top.y
|
|
|
|
-- Check which recourse is closest
|
|
for _, resource in ipairs(resources) do
|
|
local resource_box = resource.bounding_box
|
|
local dx = px - resource_box.left_top.x
|
|
local dy = py - resource_box.left_top.y
|
|
local distance = (dx * dx) + (dy * dy)
|
|
if distance < closest_distance then
|
|
closest_distance = distance
|
|
closest_recourse = resource
|
|
end
|
|
end
|
|
|
|
-- Set the item name and icon
|
|
if closest_recourse then
|
|
item_name = closest_recourse.name:gsub("^%l", string.upper):gsub("-", " ") -- remove dashes and making first letter capital
|
|
local products = assert(closest_recourse.prototype.mineable_properties.products)
|
|
local product = assert(products[1])
|
|
icon = string.format("[img=%s.%s]", product.type, product.name)
|
|
end
|
|
end
|
|
|
|
-- Rename the station
|
|
entity.backer_name = config.station_name
|
|
:gsub("__icon__", icon)
|
|
:gsub("__item_name__", item_name)
|
|
:gsub("__backer_name__", entity.backer_name)
|
|
:gsub("__direction__", get_direction(entity.position))
|
|
:gsub("__x__", math.floor(entity.position.x))
|
|
:gsub("__y__", math.floor(entity.position.y))
|
|
end
|
|
end
|
|
|
|
local e = defines.events
|
|
|
|
return Features.guard(config, {
|
|
events = {
|
|
[e.on_built_entity] = rename_station,
|
|
[e.on_robot_built_entity] = rename_station,
|
|
},
|
|
})
|