init.lua 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. if minetest.raycast == nil then
  2. error(
  3. "worldedit_brush requires at least Minetest 5.0"
  4. )
  5. end
  6. local BRUSH_MAX_DIST = 150
  7. local brush_on_use = function(itemstack, placer)
  8. local meta = itemstack:get_meta()
  9. local name = placer:get_player_name()
  10. local cmd = meta:get_string("command")
  11. if cmd == "" then
  12. worldedit.player_notify(name,
  13. "This brush is not bound, use //brush to bind a command to it.")
  14. return false
  15. end
  16. local cmddef = worldedit.registered_commands[cmd]
  17. if cmddef == nil then return false end -- shouldn't happen as //brush checks this
  18. local has_privs, missing_privs = minetest.check_player_privs(name, cmddef.privs)
  19. if not has_privs then
  20. worldedit.player_notify(name,
  21. "Missing privileges: " .. table.concat(missing_privs, ", "))
  22. return false
  23. end
  24. local raybegin = vector.add(placer:get_pos(),
  25. {x=0, y=placer:get_properties().eye_height, z=0})
  26. local rayend = vector.add(raybegin, vector.multiply(placer:get_look_dir(), BRUSH_MAX_DIST))
  27. local ray = minetest.raycast(raybegin, rayend, false, true)
  28. local pointed_thing = ray:next()
  29. if pointed_thing == nil then
  30. worldedit.player_notify(name, "Too far away.")
  31. return false
  32. end
  33. assert(pointed_thing.type == "node")
  34. worldedit.pos1[name] = pointed_thing.under
  35. worldedit.pos2[name] = nil
  36. worldedit.marker_update(name)
  37. -- this isn't really clean...
  38. local player_notify_old = worldedit.player_notify
  39. worldedit.player_notify = function(name, msg)
  40. if string.match(msg, "^%d") then return end -- discard "1234 nodes added."
  41. return player_notify_old(name, msg)
  42. end
  43. assert(cmddef.require_pos < 2)
  44. local parsed = {cmddef.parse(meta:get_string("params"))}
  45. if not table.remove(parsed, 1) then return false end -- shouldn't happen
  46. minetest.log("action", string.format("%s uses WorldEdit brush (//%s) at %s",
  47. name, cmd, minetest.pos_to_string(pointed_thing.under)))
  48. cmddef.func(name, unpack(parsed))
  49. worldedit.player_notify = player_notify_old
  50. return true
  51. end
  52. minetest.register_tool(":worldedit:brush", {
  53. description = "WorldEdit Brush",
  54. inventory_image = "worldedit_brush.png",
  55. stack_max = 1, -- no need to stack these (metadata prevents this anyway)
  56. range = 0,
  57. on_use = function(itemstack, placer, pointed_thing)
  58. brush_on_use(itemstack, placer)
  59. return itemstack -- nothing consumed, nothing changed
  60. end,
  61. })
  62. worldedit.register_command("brush", {
  63. privs = {worldedit=true},
  64. params = "none/<cmd> [parameters]",
  65. description = "Assign command to WorldEdit brush item",
  66. parse = function(param)
  67. local found, _, cmd, params = param:find("^([^%s]+)%s+(.+)$")
  68. if not found then
  69. params = ""
  70. found, _, cmd = param:find("^(.+)$")
  71. end
  72. if not found then
  73. return false
  74. end
  75. return true, cmd, params
  76. end,
  77. func = function(name, cmd, params)
  78. local itemstack = minetest.get_player_by_name(name):get_wielded_item()
  79. if itemstack == nil or itemstack:get_name() ~= "worldedit:brush" then
  80. worldedit.player_notify(name, "Not holding brush item.")
  81. return
  82. end
  83. cmd = cmd:lower()
  84. local meta = itemstack:get_meta()
  85. if cmd == "none" then
  86. meta:from_table(nil)
  87. worldedit.player_notify(name, "Brush assignment cleared.")
  88. else
  89. local cmddef = worldedit.registered_commands[cmd]
  90. if cmddef == nil or cmddef.require_pos ~= 1 then
  91. worldedit.player_notify(name, "//" .. cmd .. " cannot be used with brushes")
  92. return
  93. end
  94. -- Try parsing command params so we can give the user feedback
  95. local ok, err = cmddef.parse(params)
  96. if not ok then
  97. err = err or "invalid usage"
  98. worldedit.player_notify(name, "Error with brush command: " .. err)
  99. return
  100. end
  101. meta:set_string("command", cmd)
  102. meta:set_string("params", params)
  103. local fullcmd = "//" .. cmd .. " " .. params
  104. meta:set_string("description",
  105. minetest.registered_tools["worldedit:brush"].description .. ": " .. fullcmd)
  106. worldedit.player_notify(name, "Brush assigned to command: " .. fullcmd)
  107. end
  108. minetest.get_player_by_name(name):set_wielded_item(itemstack)
  109. end,
  110. })