Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make //lua work with expressions as well #243

Merged
merged 11 commits into from
Apr 20, 2024
3 changes: 2 additions & 1 deletion .luacheckrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
read_globals = {"minetest", "vector", "VoxelArea", "ItemStack",
"table",
"unified_inventory", "sfinv", "smart_inventory", "inventory_plus"
"unified_inventory", "sfinv", "smart_inventory", "inventory_plus",
"dump"
}
globals = {"worldedit"}
-- Ignore these errors until someone decides to fix them
Expand Down
14 changes: 11 additions & 3 deletions WorldEdit API.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,19 @@ Code
----
Contained in code.lua, this module allows arbitrary Lua code to be used with WorldEdit.

### error = worldedit.lua(code)
### error = worldedit.lua(code, name)

Executes `code` as a Lua chunk in the global namespace.
the given code gets encapsulated into a function with parameters `name`, `player`, `pos`
where
* `name` is a playername or `nil`
* `player` is the player object of the above player if applicable, otherwise `nil`
* `pos` is the position of the aforementioned player (if applicable, otherwise `nil`) rounded to integers

Returns an error if the code fails or nil otherwise.
the resulting function is then executed as a Lua chunk in the global namespace.

The return is
* a string in case of an error
* a tuple of `nil` and return of the function converted to a string in case of success

### error = worldedit.luatransform(pos1, pos2, code)

Expand Down
28 changes: 20 additions & 8 deletions worldedit/code.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,29 @@
-- @module worldedit.code

--- Executes `code` as a Lua chunk in the global namespace.
-- @return An error message if the code fails, or nil on success.
function worldedit.lua(code)
local func, err = loadstring(code)
if not func then -- Syntax error
-- the code will be encapsulated into a function with parameters
-- * name (the name of the player issuing the //lua command)
-- * player (the player object of the player)
-- * pos (the position of the player rounded to integers)
-- @return string in case of error, tuple of nil, return of code as string in case of success
function worldedit.lua(code, name)
local factory, err = loadstring("return function(name, player, pos)\n" .. code .. "\nend")
if not factory then -- Syntax error
return err
end
local good, err = pcall(func)
if not good then -- Runtime error
return err
local func = factory()
local player, pos
if name then
player = minetest.get_player_by_name(name)
if player then
pos = vector.round(player:get_pos())
end
end
return nil
local good, err = pcall(func, name, player, pos)
if not good then -- Runtime error
return tostring(err)
end
return nil, dump(err)
end


Expand Down
23 changes: 17 additions & 6 deletions worldedit_commands/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1525,16 +1525,27 @@ worldedit.register_command("lua", {
description = S("Executes <code> as a Lua chunk in the global namespace"),
privs = {worldedit=true, server=true},
parse = function(param)
if param == "" then
return false
end
return true, param
end,
func = function(name, param)
local err = worldedit.lua(param)
if err then
worldedit.player_notify(name, "code error: " .. err)
minetest.log("action", name.." tried to execute "..param)
-- shorthand like in the Lua interpreter
if param:sub(1, 1) == "=" then
param = "return " .. param:sub(2)
end
local err, ret = worldedit.lua(param, name)
if err == nil then
minetest.log("action", name .. " executed " .. param)
if ret ~= "nil" then
worldedit.player_notify(name, "code successfully executed, returned " .. ret)
else
worldedit.player_notify(name, "code successfully executed")
end
else
worldedit.player_notify(name, "code successfully executed", false)
minetest.log("action", name.." executed "..param)
minetest.log("action", name .. " tried to execute " .. param)
worldedit.player_notify(name, "code error: " .. err)
end
end,
})
Expand Down
Loading