forked from MineClone5/MineClone5
Add API to create filled map
This commit is contained in:
parent
e11185638f
commit
2228b30658
|
@ -1,3 +1,5 @@
|
|||
mcl_maps = {}
|
||||
|
||||
local S = minetest.get_translator("mcl_maps")
|
||||
local storage = minetest.get_mod_storage()
|
||||
local modpath = minetest.get_modpath("mcl_maps")
|
||||
|
@ -25,127 +27,122 @@ local loaded_maps = {}
|
|||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
-- Turn empty map into filled map by rightclick
|
||||
local make_filled_map = function(itemstack, placer, pointed_thing)
|
||||
local new_map = ItemStack("mcl_maps:filled_map")
|
||||
if minetest.settings:get_bool("enable_real_maps", true) then
|
||||
local meta = new_map:get_meta()
|
||||
local id = storage:get_int("next_id")
|
||||
storage:set_int("next_id", id + 1)
|
||||
local texture_file = "mcl_maps_map_texture_" .. id .. ".tga"
|
||||
local texture_path = map_textures_path .. texture_file
|
||||
local texture = "[combine:140x140:0,0=mcl_maps_map_background.png:6,6=" .. texture_file
|
||||
meta:set_int("mcl_maps:id", id)
|
||||
meta:set_string("mcl_maps:texture", texture)
|
||||
meta:set_string("mcl_maps:texture_path", texture_path)
|
||||
tt.reload_itemstack_description(new_map)
|
||||
creating_maps[texture] = true
|
||||
local pos = placer:get_pos()
|
||||
local minp = vector.multiply(vector.floor(vector.divide(pos, 128)), 128)
|
||||
local maxp = vector.add(minp, vector.new(127, 127, 127))
|
||||
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining)
|
||||
if calls_remaining < 1 then
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(minp, maxp)
|
||||
local data = vm:get_data()
|
||||
local param2data = vm:get_param2_data()
|
||||
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
||||
local pixels = {}
|
||||
local last_heightmap
|
||||
for x = 1, 128 do
|
||||
local map_x = minp.x - 1 + x
|
||||
local heightmap = {}
|
||||
for z = 1, 128 do
|
||||
local map_z = minp.z - 1 + z
|
||||
local color
|
||||
for map_y = maxp.y, minp.y, -1 do
|
||||
local index = area:index(map_x, map_y, map_z)
|
||||
local c_id = data[index]
|
||||
|
||||
if c_id ~= c_air then
|
||||
color = color_cache[c_id]
|
||||
|
||||
if color == nil then
|
||||
local nodename = minetest.get_name_from_content_id(c_id)
|
||||
local def = minetest.registered_nodes[nodename]
|
||||
|
||||
if def then
|
||||
local texture
|
||||
|
||||
if def.palette then
|
||||
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
|
||||
function mcl_maps.create_map(pos)
|
||||
local itemstack = ItemStack("mcl_maps:filled_map")
|
||||
local meta = itemstack:get_meta()
|
||||
local id = storage:get_int("next_id")
|
||||
storage:set_int("next_id", id + 1)
|
||||
local texture_file = "mcl_maps_map_texture_" .. id .. ".tga"
|
||||
local texture_path = map_textures_path .. texture_file
|
||||
local texture = "[combine:140x140:0,0=mcl_maps_map_background.png:6,6=" .. texture_file
|
||||
meta:set_int("mcl_maps:id", id)
|
||||
meta:set_string("mcl_maps:texture", texture)
|
||||
meta:set_string("mcl_maps:texture_path", texture_path)
|
||||
tt.reload_itemstack_description(itemstack)
|
||||
creating_maps[texture] = true
|
||||
local minp = vector.multiply(vector.floor(vector.divide(pos, 128)), 128)
|
||||
local maxp = vector.add(minp, vector.new(127, 127, 127))
|
||||
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining)
|
||||
if calls_remaining > 0 then
|
||||
return
|
||||
end
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(minp, maxp)
|
||||
local data = vm:get_data()
|
||||
local param2data = vm:get_param2_data()
|
||||
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
||||
local pixels = {}
|
||||
local last_heightmap
|
||||
for x = 1, 128 do
|
||||
local map_x = minp.x - 1 + x
|
||||
local heightmap = {}
|
||||
for z = 1, 128 do
|
||||
local map_z = minp.z - 1 + z
|
||||
local color
|
||||
for map_y = maxp.y, minp.y, -1 do
|
||||
local index = area:index(map_x, map_y, map_z)
|
||||
local c_id = data[index]
|
||||
if c_id ~= c_air then
|
||||
color = color_cache[c_id]
|
||||
if color == nil then
|
||||
local nodename = minetest.get_name_from_content_id(c_id)
|
||||
local def = minetest.registered_nodes[nodename]
|
||||
if def then
|
||||
local texture
|
||||
if def.palette then
|
||||
texture = def.palette
|
||||
elseif def.tiles then
|
||||
texture = def.tiles[1]
|
||||
if type(texture) == "table" then
|
||||
texture = texture.name
|
||||
end
|
||||
end
|
||||
|
||||
if color and color.palette then
|
||||
color = color.palette[param2data[index] + 1]
|
||||
if texture then
|
||||
texture = texture:match("([^=^%^]-([^.]+))$"):split("^")[1]
|
||||
end
|
||||
if def.palette then
|
||||
local palette = palettes[texture]
|
||||
color = palette and {palette = palette}
|
||||
else
|
||||
color_cache[c_id] = color or false
|
||||
color = texture_colors[texture]
|
||||
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
|
||||
heightmap[z] = height
|
||||
pixels[z] = pixels[z] or {}
|
||||
pixels[z][x] = color or {0, 0, 0}
|
||||
|
||||
if color and color.palette then
|
||||
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
|
||||
last_heightmap = heightmap
|
||||
end
|
||||
|
||||
tga_encoder.image(pixels):save(texture_path)
|
||||
|
||||
creating_maps[texture] = false
|
||||
heightmap[z] = height
|
||||
pixels[z] = pixels[z] or {}
|
||||
pixels[z][x] = color or {0, 0, 0}
|
||||
end
|
||||
end)
|
||||
end
|
||||
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)
|
||||
last_heightmap = heightmap
|
||||
end
|
||||
tga_encoder.image(pixels):save(texture_path)
|
||||
creating_maps[texture] = false
|
||||
end)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Turn empty map into filled map by rightclick
|
||||
local make_filled_map = function(itemstack, placer, pointed_thing)
|
||||
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
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue