160 lines
4.5 KiB
Lua
160 lines
4.5 KiB
Lua
local function player_select_item_formspec(player)
|
|
edit.player_select_item(player, "Select item to use for fill", function(player, item_str)
|
|
local d = edit.player_data[player]
|
|
|
|
if
|
|
not d.fill1 or not d.fill2 or
|
|
not edit.has_privilege(player)
|
|
then return end
|
|
|
|
local p1 = d.fill1._pos
|
|
local p2 = d.fill2._pos
|
|
|
|
d.fill1.object:remove()
|
|
|
|
local item = ItemStack(item_str)
|
|
local name = item:get_name()
|
|
if name == "" then return end
|
|
|
|
local def = minetest.registered_items[name]
|
|
|
|
if not def then return end
|
|
|
|
local is_node = minetest.registered_nodes[name]
|
|
|
|
local param2
|
|
if def.paramtype2 == "facedir" or def.paramtype2 == "colorfacedir" then
|
|
param2 = minetest.dir_to_facedir(player:get_look_dir())
|
|
elseif def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" then
|
|
param2 = minetest.dir_to_wallmounted(player:get_look_dir(), true)
|
|
end
|
|
|
|
local start = vector.new(
|
|
math.min(p1.x, p2.x),
|
|
math.min(p1.y, p2.y),
|
|
math.min(p1.z, p2.z)
|
|
)
|
|
local _end = vector.new(
|
|
math.max(p1.x, p2.x),
|
|
math.max(p1.y, p2.y),
|
|
math.max(p1.z, p2.z)
|
|
)
|
|
|
|
local size = vector.add(vector.subtract(_end, start), 1)
|
|
d.undo_schematic = edit.schematic_from_map(start, size)
|
|
|
|
local volume = size.x * size.y * size.z
|
|
if is_node and volume >= edit.fast_node_fill_threshold then
|
|
local voxel_manip = VoxelManip()
|
|
local vm_start, vm_end = voxel_manip:read_from_map(start, _end)
|
|
local param2s = voxel_manip:get_param2_data()
|
|
local content_ids = voxel_manip:get_data()
|
|
local content_id = minetest.get_content_id(name)
|
|
|
|
local ones = vector.new(1, 1, 1)
|
|
local vm_size = vector.add(vector.subtract(vm_end, vm_start), ones)
|
|
local voxel_area = VoxelArea:new({MinEdge = ones, MaxEdge = vm_size})
|
|
local va_start = vector.add(vector.subtract(start, vm_start), ones)
|
|
local va_end = vector.subtract(vector.add(va_start, size), ones)
|
|
for i in voxel_area:iterp(va_start, va_end) do
|
|
content_ids[i] = content_id
|
|
param2s[i] = param2
|
|
end
|
|
voxel_manip:set_data(content_ids)
|
|
voxel_manip:set_param2_data(param2s)
|
|
voxel_manip:write_to_map(true)
|
|
voxel_manip:update_liquids()
|
|
else
|
|
local node = {name = item_str, param2 = param2}
|
|
-- Work top to bottom so we can remove falling nodes
|
|
for x = _end.x, start.x, -1 do
|
|
for y = _end.y, start.y, -1 do
|
|
for z = _end.z, start.z, -1 do
|
|
local pos = vector.new(x, y, z)
|
|
edit.place_item_like_player(player, node, pos)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return
|
|
end)
|
|
end
|
|
|
|
local function fill_on_place(itemstack, player, pointed_thing)
|
|
if not edit.on_place_checks(player) then return end
|
|
|
|
if not pointed_thing.above then
|
|
pointed_thing = edit.get_pointed_thing_node(player)
|
|
end
|
|
|
|
local pos = edit.pointed_thing_to_pos(pointed_thing)
|
|
|
|
local player_data = edit.player_data[player]
|
|
if player_data.fill1 and pos then
|
|
player_data.fill2 = edit.add_marker("edit:fill", pos, player)
|
|
if not player_data.fill2 then return end
|
|
|
|
local diff = vector.subtract(player_data.fill1._pos, pos)
|
|
local volume = vector.add(vector.apply(diff, math.abs), 1)
|
|
if volume.x * volume.y * volume.z > edit.max_operation_volume then
|
|
edit.display_size_error(player)
|
|
player_data.fill1.object:remove()
|
|
return
|
|
end
|
|
|
|
player_select_item_formspec(player)
|
|
elseif pos then
|
|
player_data.fill1 = edit.add_marker("edit:fill", pos, player)
|
|
end
|
|
end
|
|
|
|
minetest.register_tool("edit:fill", {
|
|
description = "Edit Fill",
|
|
tiles = {"edit_fill.png"},
|
|
inventory_image = "edit_fill.png",
|
|
range = 10,
|
|
groups = {edit_place_preview = 1, edit_box_select_preview = 1},
|
|
on_place = fill_on_place,
|
|
on_secondary_use = fill_on_place,
|
|
_edit_get_selection_points = function(player)
|
|
local d = edit.player_data[player]
|
|
return d.fill1 and d.fill1._pos, d.fill2 and d.fill2._pos
|
|
end,
|
|
})
|
|
|
|
minetest.register_entity("edit:fill", {
|
|
initial_properties = {
|
|
visual = "cube",
|
|
visual_size = { x = 1.1, y = 1.1 },
|
|
physical = false,
|
|
collide_with_objects = false,
|
|
static_save = false,
|
|
use_texture_alpha = true,
|
|
glow = -1,
|
|
backface_culling = false,
|
|
hp_max = 1,
|
|
textures = {
|
|
"edit_fill.png",
|
|
"edit_fill.png",
|
|
"edit_fill.png",
|
|
"edit_fill.png",
|
|
"edit_fill.png",
|
|
"edit_fill.png",
|
|
},
|
|
},
|
|
on_deactivate = function(self)
|
|
local player_data = edit.player_data[self._placer]
|
|
self.remove_called = true
|
|
if player_data then
|
|
if player_data.fill1 and not player_data.fill1.remove_called then
|
|
player_data.fill1.object:remove()
|
|
end
|
|
if player_data.fill2 and not player_data.fill2.remove_called then
|
|
player_data.fill2.object:remove()
|
|
end
|
|
player_data.fill1 = nil
|
|
player_data.fill2 = nil
|
|
end
|
|
end,
|
|
})
|