local map_data, chunk, scanner = ...; local Map = {}; Map.__index = Map; for _,loaded_map in ipairs(map_data.maps) do setmetatable(loaded_map, Map); end 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 function Map.fill_area(self, x, z, w, h) for i = math.max(x, self.x),math.min(x + w - 1, self.x + self.w),1 do for j = math.max(z, self.z),math.min(z + h - 1, self.z + self.h),1 do self.fill[(i - self.x) + ((j - self.z) * self.w)] = self.detail; end end end function Map.set_marker(self, x, z, marker) if x < self.x or x > self.x + self.w or z < self.z or z > self.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 function Map.get_marker(self, x, z) if x < self.x or x > self.x + self.w or z < self.z or z > self.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); -- TODO: Adjust size to match map scale if x >= self.x - 2 and x <= self.x + self.w + 1 and z >= self.z - 2 and z <= self.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 -- self: The map to use as reference -- x: The x position, in world coordinates -- z: The z position, in world coordinates -- -- Returns The converted x and z coordinates function Map.to_coordinates(self, x, z) if self.scale == 0 then return chunk.to(x), chunk.to(z); end return math.floor(chunk.to(x) / self.scale + 0.5), math.floor(chunk.to(z) / self.scale + 0.5); end function Map.is_filled(self, x, z) return self.fill[(x - self.x) + ((z - self.z) * self.w)] ~= nil; end local maps = { 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(map, x, z, w, h); end map_data.next_map_id = map_data.next_map_id + 1; return id; end, get = function(id) return map_data.maps[id]; end, } -- Periodically-called function to fill in maps and queue chunks for manual -- scanning local function fill_loop() -- Fill in all player-held maps for _,p in ipairs(minetest.get_connected_players()) do local inventory = p:get_inventory(); local pos = p:get_pos(); if pos.y > -10 then for i = 1,inventory:get_size("main") do local stack = inventory:get_stack("main", i); local map = maps.get(stack:get_meta():get_int("cartographer:map_id")); if map then map:fill_local(pos.x, pos.z); end end for i = -2,2 do for j = -2,2 do local adjusted_pos = { x = pos.x + chunk.from(i), y = pos.y, z = pos.z + chunk.from(j), } scanner.queue_region(adjusted_pos); end end end end for _ = 1,10 do scanner.scan_regions(); end minetest.after(5, fill_loop); end minetest.after(5, fill_loop); return maps;