common.lua 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. --- Common functions [INTERNAL]. All of these functions are internal!
  2. -- @module worldedit.common
  3. --- Copies and modifies positions `pos1` and `pos2` so that each component of
  4. -- `pos1` is less than or equal to the corresponding component of `pos2`.
  5. -- Returns the new positions.
  6. function worldedit.sort_pos(pos1, pos2)
  7. pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
  8. pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
  9. if pos1.x > pos2.x then
  10. pos2.x, pos1.x = pos1.x, pos2.x
  11. end
  12. if pos1.y > pos2.y then
  13. pos2.y, pos1.y = pos1.y, pos2.y
  14. end
  15. if pos1.z > pos2.z then
  16. pos2.z, pos1.z = pos1.z, pos2.z
  17. end
  18. return pos1, pos2
  19. end
  20. --- Determines the volume of the region defined by positions `pos1` and `pos2`.
  21. -- @return The volume.
  22. function worldedit.volume(pos1, pos2)
  23. local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
  24. return (pos2.x - pos1.x + 1) *
  25. (pos2.y - pos1.y + 1) *
  26. (pos2.z - pos1.z + 1)
  27. end
  28. --- Gets other axes given an axis.
  29. -- @raise Axis must be x, y, or z!
  30. function worldedit.get_axis_others(axis)
  31. if axis == "x" then
  32. return "y", "z"
  33. elseif axis == "y" then
  34. return "x", "z"
  35. elseif axis == "z" then
  36. return "x", "y"
  37. else
  38. error("Axis must be x, y, or z!")
  39. end
  40. end
  41. function worldedit.keep_loaded(pos1, pos2)
  42. -- Create a vmanip and read the area from map, this
  43. -- causes all MapBlocks to be loaded into memory.
  44. -- This doesn't actually *keep* them loaded, unlike the name implies.
  45. local manip = minetest.get_voxel_manip()
  46. manip:read_from_map(pos1, pos2)
  47. end
  48. local mh = {}
  49. worldedit.manip_helpers = mh
  50. --- Generates an empty VoxelManip data table for an area.
  51. -- @return The empty data table.
  52. function mh.get_empty_data(area)
  53. -- Fill emerged area with ignore so that blocks in the area that are
  54. -- only partially modified aren't overwriten.
  55. local data = {}
  56. local c_ignore = minetest.get_content_id("ignore")
  57. for i = 1, worldedit.volume(area.MinEdge, area.MaxEdge) do
  58. data[i] = c_ignore
  59. end
  60. return data
  61. end
  62. function mh.init(pos1, pos2)
  63. local manip = minetest.get_voxel_manip()
  64. local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
  65. local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
  66. return manip, area
  67. end
  68. function mh.init_radius(pos, radius)
  69. local pos1 = vector.subtract(pos, radius)
  70. local pos2 = vector.add(pos, radius)
  71. return mh.init(pos1, pos2)
  72. end
  73. function mh.init_axis_radius(base_pos, axis, radius)
  74. return mh.init_axis_radius_length(base_pos, axis, radius, radius)
  75. end
  76. function mh.init_axis_radius_length(base_pos, axis, radius, length)
  77. local other1, other2 = worldedit.get_axis_others(axis)
  78. local pos1 = {
  79. [axis] = base_pos[axis],
  80. [other1] = base_pos[other1] - radius,
  81. [other2] = base_pos[other2] - radius
  82. }
  83. local pos2 = {
  84. [axis] = base_pos[axis] + length,
  85. [other1] = base_pos[other1] + radius,
  86. [other2] = base_pos[other2] + radius
  87. }
  88. return mh.init(pos1, pos2)
  89. end
  90. function mh.finish(manip, data)
  91. -- Update map
  92. if data ~= nil then
  93. manip:set_data(data)
  94. end
  95. manip:write_to_map()
  96. manip:update_map()
  97. end