Skip to content

Commit

Permalink
Introduce the console command /fac, the same as /c but accessible and…
Browse files Browse the repository at this point in the history
… in the Factorio Access environment

If you are sighted /c is fine. If you are blind /c is wrap things in print and then
go check the launcher output, and probably also throw serpent around that.  /fac instead
handles figuring out the common cases of when to use serpent, overrides lua print to work with the launcher, and lets
the specified code run in the FA environment (e.g. it can see storage).

Crashes are guarded with pcall on a best effort basis, but there is probably still a way to crash this.  Still, it's for devs not players.
  • Loading branch information
ahicks92 committed Nov 5, 2024
1 parent 49b64c6 commit 1da2148
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
4 changes: 4 additions & 0 deletions control.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local fa_warnings = require("scripts.warnings")
local fa_circuits = require("scripts.circuit-networks")
local fa_kk = require("scripts.kruise-kontrol-wrapper")
local fa_quickbar = require("scripts.quickbar")
local FaCommands = require("scripts.fa-commands")
local Consts = require("scripts.consts")
local Research = require("scripts.research")
local Rulers = require("scripts.rulers")
Expand Down Expand Up @@ -8314,6 +8315,9 @@ script.on_event(defines.events.on_console_chat, function(event)
end)

script.on_event(defines.events.on_console_command, function(event)
-- For our own commands, we handle the speaking and must not read here.
if FaCommands.COMMANDS[event.command] then return end

local speaker = game.get_player(event.player_index).name
if speaker == nil or speaker == "" then speaker = "Player" end
for pindex, player in pairs(players) do
Expand Down
94 changes: 94 additions & 0 deletions scripts/fa-commands.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
--[[
Custom console commands, primarily for debugging and internal use. Docs with
the handlers in this file.
Handlers registered by this file are exported and not announced through our
normal handling. This is because the launcher cannot handle queueing. We need
the mod to be silent.
]]

local mod = {}

--[[
/fac <script>
Exactrly the same as /c, but accessible without fiddling around. It:
- Captures return values, then speaks them through serpent:
- Tries to run the code wrapped in a function, with return prepended
- Otherwise, runs the code directly, and uses whatever the chunk returns.
- Overrides Lua print to go to speech, and concatenates everything up so that we
don't "trip" over the announcements.
- Makes printout available, as a mocked version that will just call to print
(IMPORTANT: only works on the current player; pindex is ignored).
- Announces errors, with tracebacks, using pcall.
Also due to launcher limitations, "print" here doesn't do newlines. That'll
cause the launcher to not read right.
]]
---@param cmd CustomCommandData
function cmd_fac(cmd)
local pindex = cmd.player_index
local script = cmd.parameter

if not cmd.parameter or cmd.parameter == "" then
printout("A script is required", pindex)
return
end

local printbuffer = ""

local function print_override(...)
-- Send a copy to launcher stdout for debugging.
print(...)

local args = table.pack(...)
for i = 1, args.n do
printbuffer = printbuffer .. tostring(args[i]) .. " "
end
end

local with_return = "return " .. script

local environment = {}
for k, v in pairs(_ENV) do
environment[k] = v
end
environment.print = print_override
environment.printout = function(arg, pindex)
print_override(arg, "for pindex", pindex)
end

local chunk, err = load(with_return, "=(load)", "t", environment)
if not chunk then
chunk, err = load(cmd.parameter, "=(load)", "t", environment)
if err then
printout(err, pindex)
print(err)
return
end
end

local _good, val = pcall(function()
local r = chunk()
return serpent.line(r, { nocode = true })
end)

print_override(val)

print("Printbuffer is", printbuffer)
printout(printbuffer, pindex)
end

mod.COMMANDS = {
fac = {
help = "See commands.lua",
handler = cmd_fac,
},
}

for name, args in pairs(mod.COMMANDS) do
commands.add_command(name, args.help, args.handler)
end

return mod

0 comments on commit 1da2148

Please sign in to comment.