Files
bbassieandClaude Opus 5.5 c0289ed8a7 Address review on exp_server_list
The controller and instance plugins are init functions with closures.
The controller batches refreshes with setMany and deleteMany, and the
instance gates updates on its status instead of a started flag.

short_name is now display_name. New always_on_top field sorts servers
first in get_servers. The record carries has_password from the game
password in factorio.settings, never the password itself, and the
description falls back to the one in factorio.settings. A controller
welcome is used when the instance has none, and the readme falls back
to a default welcome from the locale.

Lua gets is_synced for connect.lua. The readme passes an empty detail
instead of nil to the join tooltip so the player count stays in __2__,
restores the Password status, shows the welcome title as a centered
label and shortens long descriptions with the full text as a tooltip.

The Lua tests assert the lookups they index, which fixes the lint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:35:33 +00:00

109 lines
4.3 KiB
Lua

--[[-- Commands - Connect
Adds a commands that allows you to request a player move to another server
]]
local Async = require("modules/exp_util/async")
local Commands = require("modules/exp_commands")
local ExpServerList = require("modules/exp_server_list")
local request_connection_async = Async.register(ExpServerList.request_connection)
local concat = table.concat
--- Find the one server matching a name, is not an Commands.InputParser because it does not accept addresses
--- @param search string
--- @return boolean, LocalisedString | ExpServerList.Server # True for success
local function find_server(search)
local current_server = ExpServerList.get_current() --- @cast current_server -nil
local found = ExpServerList.find_servers(search)
local names_all, names = {}, {}
local matching = {} --- @type ExpServerList.Server[]
for index, server in ipairs(found) do
names_all[index] = server.name
if server.factorio_version == current_server.factorio_version then
matching[#matching + 1] = server
names[#names + 1] = server.name
end
end
if #matching > 1 then
return false, { "exp-commands_connect.too-many-matching", concat(names, ", ") }
elseif #matching == 1 then
local server = matching[1]
if server.id == current_server.id then
return false, { "exp-commands_connect.same-server", server.name }
elseif not ExpServerList.is_online(server) then
return false, { "exp-commands_connect.offline", server.name }
end
return true, server
elseif #found > 0 then
return false, { "exp-commands_connect.wrong-version", concat(names_all, ", ") }
else
return false, { "exp-commands_connect.none-matching" }
end
end
--- Resolve the server argument to a server, or leave it as an address
--- @param server string
--- @param is_address boolean?
--- @return boolean, LocalisedString | ExpServerList.Server | string # True for success
local function resolve_server(server, is_address)
if is_address or not ExpServerList.is_synced() then
return true, server
end
return find_server(server)
end
--- Connect to a different server
Commands.new("connect", { "exp-commands_connect.description" })
:argument("server", { "exp-commands_connect.arg-server" }, Commands.types.string)
:optional("is-address", { "exp-commands_connect.arg-is-address" }, Commands.types.boolean)
:add_aliases{ "join" }
:register(function(player, server, is_address)
--- @cast server string
--- @cast is_address boolean?
local success, result = resolve_server(server, is_address)
if not success then
return Commands.status.invalid_input(result)
end
request_connection_async(player, result, true)
end)
--- Connect another player to a different server
Commands.new("connect-player", { "exp-commands_connect.description-player" })
:argument("player", { "exp-commands_connect.arg-player" }, Commands.types.player_online)
:argument("server", { "exp-commands_connect.arg-server" }, Commands.types.string)
:optional("is-address", { "exp-commands_connect.arg-is-address" }, Commands.types.boolean)
:add_flags{ "admin_only" }
:register(function(player, other_player, server, is_address)
--- @cast other_player LuaPlayer
--- @cast server string
--- @cast is_address boolean?
local success, result = resolve_server(server, is_address)
if not success then
return Commands.status.invalid_input(result)
end
request_connection_async(other_player, result)
end)
--- Connect all players to a different server
Commands.new("connect-all", { "exp-commands_connect.description-all" })
:argument("server", { "exp-commands_connect.arg-server" }, Commands.types.string)
:optional("is-address", { "exp-commands_connect.arg-is-address" }, Commands.types.boolean)
:add_flags{ "admin_only" }
:register(function(player, server, is_address)
--- @cast server string
--- @cast is_address boolean?
local success, result = resolve_server(server, is_address)
if not success then
return Commands.status.invalid_input(result)
end
for _, next_player in pairs(game.connected_players) do
request_connection_async(next_player, result)
end
end)