Add API to create filled map

This commit is contained in:
Elias Fleckenstein 2021-05-01 17:36:51 +02:00
parent e11185638f
commit 2228b30658

View file

@ -1,3 +1,5 @@
mcl_maps = {}
local S = minetest.get_translator("mcl_maps") local S = minetest.get_translator("mcl_maps")
local storage = minetest.get_mod_storage() local storage = minetest.get_mod_storage()
local modpath = minetest.get_modpath("mcl_maps") local modpath = minetest.get_modpath("mcl_maps")
@ -25,127 +27,122 @@ local loaded_maps = {}
local c_air = minetest.get_content_id("air") local c_air = minetest.get_content_id("air")
-- Turn empty map into filled map by rightclick function mcl_maps.create_map(pos)
local make_filled_map = function(itemstack, placer, pointed_thing) local itemstack = ItemStack("mcl_maps:filled_map")
local new_map = ItemStack("mcl_maps:filled_map") local meta = itemstack:get_meta()
if minetest.settings:get_bool("enable_real_maps", true) then local id = storage:get_int("next_id")
local meta = new_map:get_meta() storage:set_int("next_id", id + 1)
local id = storage:get_int("next_id") local texture_file = "mcl_maps_map_texture_" .. id .. ".tga"
storage:set_int("next_id", id + 1) local texture_path = map_textures_path .. texture_file
local texture_file = "mcl_maps_map_texture_" .. id .. ".tga" local texture = "[combine:140x140:0,0=mcl_maps_map_background.png:6,6=" .. texture_file
local texture_path = map_textures_path .. texture_file meta:set_int("mcl_maps:id", id)
local texture = "[combine:140x140:0,0=mcl_maps_map_background.png:6,6=" .. texture_file meta:set_string("mcl_maps:texture", texture)
meta:set_int("mcl_maps:id", id) meta:set_string("mcl_maps:texture_path", texture_path)
meta:set_string("mcl_maps:texture", texture) tt.reload_itemstack_description(itemstack)
meta:set_string("mcl_maps:texture_path", texture_path) creating_maps[texture] = true
tt.reload_itemstack_description(new_map) local minp = vector.multiply(vector.floor(vector.divide(pos, 128)), 128)
creating_maps[texture] = true local maxp = vector.add(minp, vector.new(127, 127, 127))
local pos = placer:get_pos() minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining)
local minp = vector.multiply(vector.floor(vector.divide(pos, 128)), 128) if calls_remaining > 0 then
local maxp = vector.add(minp, vector.new(127, 127, 127)) return
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining) end
if calls_remaining < 1 then local vm = minetest.get_voxel_manip()
local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(minp, maxp)
local emin, emax = vm:read_from_map(minp, maxp) local data = vm:get_data()
local data = vm:get_data() local param2data = vm:get_param2_data()
local param2data = vm:get_param2_data() local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local pixels = {}
local pixels = {} local last_heightmap
local last_heightmap for x = 1, 128 do
for x = 1, 128 do local map_x = minp.x - 1 + x
local map_x = minp.x - 1 + x local heightmap = {}
local heightmap = {} for z = 1, 128 do
for z = 1, 128 do local map_z = minp.z - 1 + z
local map_z = minp.z - 1 + z local color
local color for map_y = maxp.y, minp.y, -1 do
for map_y = maxp.y, minp.y, -1 do local index = area:index(map_x, map_y, map_z)
local index = area:index(map_x, map_y, map_z) local c_id = data[index]
local c_id = data[index] if c_id ~= c_air then
color = color_cache[c_id]
if c_id ~= c_air then if color == nil then
color = color_cache[c_id] local nodename = minetest.get_name_from_content_id(c_id)
local def = minetest.registered_nodes[nodename]
if color == nil then if def then
local nodename = minetest.get_name_from_content_id(c_id) local texture
local def = minetest.registered_nodes[nodename] if def.palette then
texture = def.palette
if def then elseif def.tiles then
local texture texture = def.tiles[1]
if type(texture) == "table" then
if def.palette then texture = texture.name
texture = def.palette
elseif def.tiles then
texture = def.tiles[1]
if type(texture) == "table" then
texture = texture.name
end
end
if texture then
texture = texture:match("([^=^%^]-([^.]+))$"):split("^")[1]
end
if def.palette then
local palette = palettes[texture]
color = palette and {palette = palette}
else
color = texture_colors[texture]
end
end end
end end
if texture then
if color and color.palette then texture = texture:match("([^=^%^]-([^.]+))$"):split("^")[1]
color = color.palette[param2data[index] + 1] end
if def.palette then
local palette = palettes[texture]
color = palette and {palette = palette}
else else
color_cache[c_id] = color or false color = texture_colors[texture]
end end
if color and last_heightmap then
local last_height = last_heightmap[z]
if last_height < map_y then
color = {
math.min(255, color[1] + 16),
math.min(255, color[2] + 16),
math.min(255, color[3] + 16),
}
elseif last_height > map_y then
color = {
math.max(0, color[1] - 16),
math.max(0, color[2] - 16),
math.max(0, color[3] - 16),
}
end
end
height = map_y
break
end end
end end
heightmap[z] = height
pixels[z] = pixels[z] or {} if color and color.palette then
pixels[z][x] = color or {0, 0, 0} color = color.palette[param2data[index] + 1]
else
color_cache[c_id] = color or false
end
if color and last_heightmap then
local last_height = last_heightmap[z]
if last_height < map_y then
color = {
math.min(255, color[1] + 16),
math.min(255, color[2] + 16),
math.min(255, color[3] + 16),
}
elseif last_height > map_y then
color = {
math.max(0, color[1] - 16),
math.max(0, color[2] - 16),
math.max(0, color[3] - 16),
}
end
end
height = map_y
break
end end
last_heightmap = heightmap
end end
heightmap[z] = height
tga_encoder.image(pixels):save(texture_path) pixels[z] = pixels[z] or {}
pixels[z][x] = color or {0, 0, 0}
creating_maps[texture] = false
end end
end) last_heightmap = heightmap
end end
itemstack:take_item() tga_encoder.image(pixels):save(texture_path)
if itemstack:is_empty() then creating_maps[texture] = false
return new_map end)
else return itemstack
local inv = placer:get_inventory() end
if inv:room_for_item("main", new_map) then
inv:add_item("main", new_map) -- Turn empty map into filled map by rightclick
else local make_filled_map = function(itemstack, placer, pointed_thing)
minetest.add_item(placer:get_pos(), new_map) if minetest.settings:get_bool("enable_real_maps", true) then
local new_map = mcl_maps.create_map(placer:get_pos())
itemstack:take_item()
if itemstack:is_empty() then
return new_map
else
local inv = placer:get_inventory()
if inv:room_for_item("main", new_map) then
inv:add_item("main", new_map)
else
minetest.add_item(placer:get_pos(), new_map)
end
return itemstack
end end
return itemstack
end end
end end