-- Arguments -- map_data: The map data source -- chunk: The chunk coordinate conversion API local map_data, chunk = ...; -- The map 'class' local Map = {}; Map.__index = Map; for _,loaded_map in ipairs(map_data.maps) do setmetatable(loaded_map, Map); end -- Resize this map -- -- w: The new width -- h: The new height function Map.resize(self, w, h) if w >= self.w and h >= self.h then self.w = w; self.h = h; -- FIXME: Is this really correct? Seems questionable. end end -- Fill in a region of this map -- -- x: The x position, in map coordinates -- z: The z position, in map coordinates -- w: The width, in map coordinates -- h: The height, in map coordinates function Map.fill_area(self, x, z, w, h) for i = math.max(x, 0),math.min(x + w - 1, self.w),1 do for j = math.max(z, 0),math.min(z + h - 1, self.h),1 do self.fill[i + (j * self.w)] = self.detail; end end end -- Set the marker at the given position -- -- x: The x position, in map coordinates -- z: The z position, in map coordinates -- marker: The marker ID to set, or nil to unset function Map.set_marker(self, x, z, marker) if x < 0 or x > self.w or z < 0 or z > self.h then return; end if not self.markers[x] then self.markers[x] = { [z] = marker, }; else self.markers[x][z] = marker; end end -- Get the marker at the given position -- -- x: The x position, in map coordinates -- z: The z position, in map coordinates -- -- Returns a marker id function Map.get_marker(self, x, z) if x < 0 or x > self.w or z < 0 or z > self.h or not self.markers[x] then return nil; end return self.markers[x][z]; end -- Fill in the local area of a map around a position -- -- id: A map ID -- x: The x position, in world coordinates -- z: The z position, in world coordinates function Map.fill_local(self, x, z) x, z = self:to_coordinates(x, z, true); -- TODO: Adjust size to match map scale if x >= -2 and x <= self.w + 1 and z >= -2 and z <= self.h + 1 then self:fill_area(x - 2, z - 2, 5, 5); end end -- Convert a position in world coordinates to the given map's coordinate system -- -- x: The x position, in world coordinates -- z: The z position, in world coordinates -- (Optional) relative: When true, the coordinates are relative to this map's -- position. -- -- Returns The converted x and z coordinates function Map.to_coordinates(self, x, z, relative) if self.scale == 0 then return chunk.to(x), chunk.to(z); end if relative then return math.floor((chunk.to(x) - self.x) / self.scale + 0.5), math.floor((chunk.to(z) - self.z) / self.scale + 0.5); else return math.floor(chunk.to(x) / self.scale + 0.5), math.floor(chunk.to(z) / self.scale + 0.5); end end -- Check if the given position on this map is filled -- -- x: The x position, in map coordinates -- z: The z position, in map coordinates function Map.is_filled(self, x, z) return self.fill[(x - self.x) + ((z - self.z) * self.w)] ~= nil; end -- The Map API local maps = { -- Create a new map object with the given parameters -- -- x: The x position, in map coordinates -- z: The z position, in map coordinates -- w: The width, in map coordinates -- h: The height, in map coordinates -- filled: Whether or not the map is pre-filled -- detail: The detail level -- scale: The scale factor -- -- Returns the new map's id create = function(x, z, w, h, filled, detail, scale) local id = map_data.next_map_id; local map = { id = id, x = x, z = z, w = w, h = h, detail = detail, scale = scale, fill = {}, markers = {}, }; setmetatable(map, Map); map_data.maps[id] = map; if filled then map:fill_area(0, 0, w, h); end map_data.next_map_id = map_data.next_map_id + 1; return id; end, -- Get the map objwct assigned to the given id -- -- id: The map id -- -- Returns a map object, or nil if the id is invalid get = function(id) return map_data.maps[id]; end, } return maps;