map.lua 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. map_master.registered_maps = {}
  2. local map_def_prototype =
  3. {
  4. middle = {x = 0, z = 0},
  5. }
  6. local function assert_vector(vec, msg)
  7. assert(type(vec.x) == "number" and
  8. type(vec.y) == "number" and
  9. type(vec.z) == "number", msg)
  10. end
  11. function map_master.register_map(name, def)
  12. assert(type(name) == "string",
  13. "Error registering map: name must be a string")
  14. assert_vector(def.size,
  15. "Error registering map: size must be a vector")
  16. assert(def.size.x > 0 and
  17. def.size.y > 0 and
  18. def.size.z > 0,
  19. "Error registering map: x, y and z of size must be positive")
  20. assert_vector(def.spawnpoint,
  21. "Error registering map: spawnpoint must be a vector")
  22. assert(type(def.path) == "string",
  23. "Error registering map: Path must be a string")
  24. local copy = {}
  25. for k, v in pairs(map_def_prototype)
  26. do
  27. copy[k] = v
  28. end
  29. for k, v in pairs(def)
  30. do
  31. copy[k] = v
  32. end
  33. map_master.registered_maps[name] = copy
  34. end
  35. local function set_spawnpoint(map)
  36. local minpos =
  37. {
  38. x = map.middle.x - map.size.x * 8 ,
  39. y = -19,
  40. z = map.middle.z - map.size.z * 8,
  41. }
  42. local spawn = vector.add(minpos, map.spawnpoint)
  43. movable_spawnpoint.set_spawnpoint(spawn)
  44. end
  45. local function place_schematics(map, done_callback)
  46. --defining variables that persist throughout iteration
  47. --by having them outside the iterating function
  48. local minpos =
  49. {
  50. x = map.middle.x - map.size.x * 8 ,
  51. y = -19,
  52. z = map.middle.z - map.size.z * 8,
  53. }
  54. local i, ii, iii = 0, 0, 0
  55. local ix = minpos.x
  56. local iy = minpos.y
  57. local iz = minpos.z
  58. --iterating funciton that will run asynchronously
  59. local function place_async()
  60. local success
  61. for I = 1, 10
  62. do
  63. local pos1 = vector.new(ix, iy, iz)
  64. local filename = map.path..i.."_"..ii.."_"..iii..".mts"
  65. success = minetest.place_schematic(
  66. pos1,
  67. filename,
  68. nil,
  69. nil,
  70. true)
  71. iii = iii + 1
  72. iz = iz + 16
  73. if iii == map.size.z
  74. then
  75. iii = 0
  76. iz = minpos.z
  77. ii = ii + 1
  78. iy = iy + 16
  79. if ii == map.size.y
  80. then
  81. ii = 0
  82. iy = minpos.y
  83. i = i + 1
  84. ix = ix + 16
  85. end
  86. end
  87. if i >= map.size.x or not success
  88. then
  89. break
  90. end
  91. end
  92. if i < map.size.x and success
  93. then
  94. --asynchronous looping
  95. minetest.after(0.05, place_async)
  96. elseif done_callback
  97. then
  98. done_callback(success)
  99. end
  100. end
  101. place_async()
  102. end
  103. local function place_border_volume(pos1, pos2, vm_buffer)
  104. local pmin =
  105. {
  106. x = math.min(pos1.x, pos2.x),
  107. y = math.min(pos1.y, pos2.y),
  108. z = math.min(pos1.z, pos2.z),
  109. }
  110. local pmax =
  111. {
  112. x = math.max(pos1.x, pos2.x),
  113. y = math.max(pos1.y, pos2.y),
  114. z = math.max(pos1.z, pos2.z),
  115. }
  116. local cid = minetest.get_content_id("invisible_wall")
  117. local vm = VoxelManip()
  118. local emin, emax = vm:read_from_map(pmin, pmax)
  119. local data = vm:get_data(vm_buffer)
  120. local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
  121. for iz = pmin.z, pmax.z
  122. do
  123. for iy = pmin.y, pmax.y
  124. do
  125. for ix = pmin.x, pmax.x
  126. do
  127. data[area:index(ix, iy, iz)] = cid
  128. end
  129. end
  130. end
  131. vm:set_data(data)
  132. vm:write_to_map()
  133. end
  134. local function place_borders(map)
  135. local min =
  136. {
  137. x = map.middle.x - map.size.x * 8 - 1,
  138. y = -19,
  139. z = map.middle.z - map.size.z * 8 - 1,
  140. }
  141. local max =
  142. {
  143. x = map.middle.x + map.size.x * 8,
  144. y = map.size.y * 16,
  145. z = map.middle.z + map.size.z * 8,
  146. }
  147. --placing sides
  148. local vm_buffer = {}
  149. place_border_volume(min, {x = max.x, y = max.y, z = min.z}, vm_buffer)
  150. place_border_volume(min, {x = min.x, y = max.y, z = max.z}, vm_buffer)
  151. place_border_volume(max, {x = min.x, y = max.y, z = min.z}, vm_buffer)
  152. place_border_volume(max, {x = max.x, y = min.y, z = min.z}, vm_buffer)
  153. place_border_volume(max, {x = min.x, y = min.y, z = max.z}, vm_buffer)
  154. end
  155. --
  156. function map_master.load_map(name, done_callback)
  157. local map = map_master.registered_maps[name]
  158. if not map
  159. then
  160. return false
  161. end
  162. place_schematics(map, done_callback)
  163. place_borders(map)
  164. set_spawnpoint(map)
  165. return true
  166. end