Files
factorio-expcluster/exp_scenario/module/config/chat_auto_reply.lua
T
bbassieandClaude Opus 5.5 4bc1773c82 Address review: page layout, five more features, framework changes
Framework:
- Intervals are gone. Update periods are hardcoded on_nth_tick values
  again, since nobody has needed to change them.
- apply is a single loop over the declared fields and logs a warning
  when an override is invalid. receive_update also warns about
  unknown keys.
- Nested tables are addressed as "section.key". Lists of strings can be
  overridden. Features.optional declares a value with no default.
- Features.on_apply rebuilds values derived from the config, such as
  lookup sets. It also runs during on_load.

exp_roles is assumed to be present:
- AFK Kick picks a role (active_role_id) instead of a custom check
  function.
- Chat Auto Reply, Protection, and Nuke Protection no longer take a
  permission as a setting.

New features, each chosen for an edge case:
- Discord Alerts: conditional handlers, and a command map that becomes
  a list.
- Entity Protection: lists turned into sets at load, and bookkeeping
  that must keep running while disabled.
- Nuke Protection: config keyed by defines, flattened to a banned items
  list.
- Popups: one config shared by two control files.
- Spawn Area: nested sections, and settings that only apply when the
  map is created.

Page: now laid out like the role page. It has a search across every
setting, one long list with a sticky sidebar to jump between sections,
and the enabled switch separated at the front of each header with
Reset to defaults on the right. Changed rows are highlighted, and a
bottom bar offers Revert and Apply. Role settings use a role picker and
lists use a tag select.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:28:23 +00:00

138 lines
7.3 KiB
Lua

--- This file defines the different triggers for the chat bot
-- @config Chat-Auto-Reply
local ExpUtil = require("modules/exp_util")
local Features = require("modules/exp_scenario/features")
local Async = require("modules/exp_util/async")
local config_server_detail = require("modules.exp_legacy.config.server_detail") --- @dep config.server_detail
local floor = math.floor
local random = math.random
local format_string = string.format
local locale_reply = "exp_chat-auto-reply.chat-reply"
local send_message_async =
Async.register(function(player, message)
if player == nil then
game.print(message)
else
player.print(message)
end
end)
local afk_time_units = {
minutes = true,
seconds = true,
}
return Features.config("chat_auto_reply", {
--- @type table<string, LocalisedString | fun(player: LuaPlayer, is_command: boolean): LocalisedString>
messages = { --- @setting messages will trigger when ever the word is said
["discord"] = { "info.discord", config_server_detail["discord"] },
["expgaming"] = { "info.website", config_server_detail["website"] },
["website"] = { "info.website", config_server_detail["website"] },
["status"] = { "info.status", config_server_detail["status"] },
["github"] = { "info.github", config_server_detail["github"] },
["patreon"] = { "info.patreon", config_server_detail["patreon"] },
["donate"] = { "info.patreon", config_server_detail["patreon"] },
["command"] = { "info.custom-commands" },
["commands"] = { "info.custom-commands" },
["softmod"] = { "info.softmod" },
["plugin"] = { "info.softmod" },
["script"] = { "info.softmod" },
["redmew"] = { "info.redmew" },
["comfy"] = { "info.redmew" },
["rhd"] = { "info.lhd" },
["lhd"] = { "info.lhd" },
["loop"] = { "exp_chat-auto-reply.reply-loops" },
["roundabout"] = { "exp_chat-auto-reply.reply-loops" },
["roundabouts"] = { "exp_chat-auto-reply.reply-loops" },
["clusterio"] = { "exp_chat-auto-reply.reply-clusterio" },
["players"] = function()
return { "exp_chat-auto-reply.reply-players", #game.players }
end,
["online"] = function()
return { "exp_chat-auto-reply.reply-online", #game.connected_players }
end,
["afk"] = function(player)
local max = player
for _, next_player in pairs(game.connected_players) do
if max.afk_time < next_player.afk_time then
max = next_player
end
end
return { "exp_chat-auto-reply.reply-afk", max.name, ExpUtil.format_time_locale(max.afk_time, "long", afk_time_units) }
end,
},
allow_command_prefix_for_messages = true, --- @setting allow_command_prefix_for_messages when true any message trigger will print to all player when prefixed
command_admin_only = false, --- @setting command_admin_only when true will only allow chat commands for admins
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
["dev"] = { "exp_chat-auto-reply.reply-dev" },
["magic"] = { "exp_chat-auto-reply.reply-magic" },
["aids"] = { "exp_chat-auto-reply.reply-aids" },
["riot"] = { "exp_chat-auto-reply.reply-riot" },
["lenny"] = { "exp_chat-auto-reply.reply-lenny" },
["blame"] = function(player)
local names = { "Cooldude2606", "arty714", "badgamernl", "mark9064", "aldldl", "Drahc_pro", player.name }
for _, next_player in pairs(game.connected_players) do
names[#names + 1] = next_player.name
end
return { "exp_chat-auto-reply.reply-blame", table.get_random(names) }
end,
["hodor"] = function()
local options = { "?", ".", "!", "!!!" }
return { "exp_chat-auto-reply.reply-hodor", table.get_random(options) }
end,
["evolution"] = function(player)
return { "exp_chat-auto-reply.reply-evolution", format_string("%.2f", game.forces["enemy"].get_evolution_factor(player.surface)) }
end,
["makepopcorn"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-popcorn-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-popcorn-1" } }
end,
["passsomesnaps"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-snaps-2", player.name } })
send_message_async:start_after(timeout * (random() + 0.5), nil, { locale_reply, { "exp_chat-auto-reply.reply-snaps-3", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-snaps-1" } }
end,
["makecocktail"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-cocktail-2", player.name } })
send_message_async:start_after(timeout * (random() + 0.5), nil, { locale_reply, { "exp_chat-auto-reply.reply-cocktail-3", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-cocktail-1" } }
end,
["makecoffee"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-coffee-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-coffee-1" } }
end,
["orderpizza"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-pizza-2", player.name } })
send_message_async:start_after(timeout * (random() + 0.5), nil, { locale_reply, { "exp_chat-auto-reply.reply-pizza-3", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-pizza-1" } }
end,
["maketea"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-tea-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-tea-1" } }
end,
["meadplease"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-mead-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-mead-1" } }
end,
["passabeer"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-beer-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-beer-1" } }
end,
},
})