A minetest mod for mapmaking
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
4.8KB

  1. -- Arguments
  2. -- map_data: The map data source
  3. -- chunk: The chunk coordinate conversion API
  4. local map_data, chunk = ...;
  5. -- The map 'class'
  6. local Map = {};
  7. Map.__index = Map;
  8. for _,loaded_map in ipairs(map_data.maps) do
  9. setmetatable(loaded_map, Map);
  10. end
  11. -- Rescale this map
  12. --
  13. -- scale: The new scale
  14. function Map.rescale(self, scale)
  15. if scale >= self.scale then
  16. self.fill = {};
  17. self.markers = {};
  18. self.scale = scale;
  19. end
  20. end
  21. -- Resize this map
  22. --
  23. -- w: The new width
  24. -- h: The new height
  25. function Map.resize(self, w, h)
  26. if w >= self.w and h >= self.h then
  27. self.w = w;
  28. self.h = h;
  29. end
  30. end
  31. -- Fill in a region of this map
  32. --
  33. -- x: The x position, in map coordinates
  34. -- z: The z position, in map coordinates
  35. -- w: The width, in map coordinates
  36. -- h: The height, in map coordinates
  37. function Map.fill_area(self, x, z, w, h)
  38. for i = math.max(x, 0),math.min(x + w - 1, self.w),1 do
  39. if not self.fill[i] then
  40. self.fill[i] = {};
  41. end
  42. for j = math.max(z, 0),math.min(z + h - 1, self.h),1 do
  43. self.fill[i][j] = self.detail;
  44. end
  45. end
  46. end
  47. -- Set the marker at the given position
  48. --
  49. -- x: The x position, in map coordinates
  50. -- z: The z position, in map coordinates
  51. -- marker: The marker ID to set, or nil to unset
  52. function Map.set_marker(self, x, z, marker)
  53. if x < 0 or x > self.w or z < 0 or z > self.h then
  54. return;
  55. end
  56. if not self.markers[x] then
  57. self.markers[x] = {
  58. [z] = marker,
  59. };
  60. else
  61. self.markers[x][z] = marker;
  62. end
  63. end
  64. -- Get the marker at the given position
  65. --
  66. -- x: The x position, in map coordinates
  67. -- z: The z position, in map coordinates
  68. --
  69. -- Returns a marker id
  70. function Map.get_marker(self, x, z)
  71. if x < 0 or x > self.w or z < 0 or z > self.h or not self.markers[x] then
  72. return nil;
  73. end
  74. return self.markers[x][z];
  75. end
  76. -- Fill in the local area of a map around a position
  77. --
  78. -- id: A map ID
  79. -- x: The x position, in world coordinates
  80. -- z: The z position, in world coordinates
  81. function Map.fill_local(self, x, z)
  82. x, z = self:to_coordinates(x, z, true);
  83. local scale_sizes = {
  84. 7,
  85. 5,
  86. 5,
  87. 3,
  88. 3,
  89. 3,
  90. 1,
  91. 1,
  92. };
  93. local fill_size = scale_sizes[math.min(self.scale, #scale_sizes)];
  94. local fill_radius = math.floor(fill_size / 2);
  95. if x >= 0 - fill_radius and x <= self.w + (fill_radius - 1)
  96. and z >= 0 - fill_radius and z <= self.h + (fill_radius - 1) then
  97. self:fill_area(x - fill_radius, z - fill_radius, fill_size, fill_size);
  98. end
  99. end
  100. -- Convert a position in world coordinates to the given map's coordinate system
  101. --
  102. -- x: The x position, in world coordinates
  103. -- z: The z position, in world coordinates
  104. -- (Optional) relative: When true, the coordinates are relative to this map's
  105. -- position.
  106. --
  107. -- Returns The converted x and z coordinates
  108. function Map.to_coordinates(self, x, z, relative)
  109. if self.scale == 0 then
  110. return chunk.to(x), chunk.to(z);
  111. end
  112. if relative then
  113. return math.floor((chunk.to(x) - self.x) / self.scale + 0.5),
  114. math.floor((chunk.to(z) - self.z) / self.scale + 0.5);
  115. else
  116. return math.floor(chunk.to(x) / self.scale + 0.5),
  117. math.floor(chunk.to(z) / self.scale + 0.5);
  118. end
  119. end
  120. -- Check if the given position on this map is filled
  121. --
  122. -- x: The x position, in map coordinates
  123. -- z: The z position, in map coordinates
  124. function Map.is_filled(self, x, z)
  125. return self.fill[x - self.x] and self.fill[x - self.x][z - self.z];
  126. end
  127. -- The Map API
  128. local maps = {
  129. -- Create a new map object with the given parameters
  130. --
  131. -- x: The x position, in map coordinates
  132. -- z: The z position, in map coordinates
  133. -- w: The width, in map coordinates
  134. -- h: The height, in map coordinates
  135. -- filled: Whether or not the map is pre-filled
  136. -- detail: The detail level
  137. -- scale: The scale factor
  138. --
  139. -- Returns the new map's id
  140. create = function(x, z, w, h, filled, detail, scale)
  141. local id = map_data.next_map_id;
  142. local map = {
  143. id = id,
  144. x = x,
  145. z = z,
  146. w = w,
  147. h = h,
  148. detail = detail,
  149. scale = scale,
  150. fill = {},
  151. markers = {},
  152. };
  153. setmetatable(map, Map);
  154. map_data.maps[id] = map;
  155. if filled then
  156. map:fill_area(0, 0, w, h);
  157. end
  158. map_data.next_map_id = map_data.next_map_id + 1;
  159. return id;
  160. end,
  161. -- Get the map objwct assigned to the given id
  162. --
  163. -- id: The map id
  164. --
  165. -- Returns a map object, or nil if the id is invalid
  166. get = function(id)
  167. return map_data.maps[id];
  168. end,
  169. }
  170. return maps;