2023-03-20 12:15:40 -05:00
|
|
|
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
|
|
|
|
|
2023-09-08 12:30:23 -05:00
|
|
|
local pos = edit.pointed_thing_to_pos(pointed_thing)
|
2023-03-20 12:15:40 -05:00
|
|
|
|
2023-09-08 12:30:23 -05:00
|
|
|
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)
|
2023-03-20 12:15:40 -05:00
|
|
|
local size = vector.add(vector.apply(diff, math.abs), 1)
|
|
|
|
if size.x * size.y * size.z > edit.max_operation_volume then
|
|
|
|
edit.display_size_error(player)
|
2023-09-08 12:30:23 -05:00
|
|
|
player_data.fill1.object:remove()
|
2023-03-20 12:15:40 -05:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local inv = minetest.get_inventory({type = "player", name = player:get_player_name()})
|
|
|
|
local formspec = "size[8,6]label[2,0.5;Select item for filling]button_exit[7,0;1,1;quit;X]"
|
|
|
|
for y = 1, 4 do
|
|
|
|
for x = 1, 8 do
|
|
|
|
local name = inv:get_stack("main", ((y - 1) * 8) + x):get_name()
|
|
|
|
formspec =
|
|
|
|
formspec ..
|
|
|
|
"item_image_button[" ..
|
|
|
|
(x - 1) .. "," ..
|
|
|
|
(y + 1) .. ";1,1;" ..
|
|
|
|
name .. ";" ..
|
|
|
|
name .. ";]"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
minetest.show_formspec(player:get_player_name(), "edit:fill", formspec)
|
|
|
|
elseif pos then
|
2023-09-08 12:30:23 -05:00
|
|
|
player_data.fill1 = edit.add_marker("edit:fill", pos, player)
|
2023-03-20 12:15:40 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-09-08 12:30:23 -05:00
|
|
|
minetest.register_tool("edit:fill", {
|
2023-03-20 12:15:40 -05:00
|
|
|
description = "Edit Fill",
|
|
|
|
tiles = {"edit_fill.png"},
|
|
|
|
inventory_image = "edit_fill.png",
|
|
|
|
range = 10,
|
|
|
|
on_place = fill_on_place,
|
|
|
|
on_secondary_use = fill_on_place,
|
2023-09-08 12:30:23 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
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()
|
2023-03-20 12:15:40 -05:00
|
|
|
end
|
2023-09-08 12:30:23 -05:00
|
|
|
if player_data.fill2 and not player_data.fill2.remove_called then
|
|
|
|
player_data.fill2.object:remove()
|
2023-03-20 12:15:40 -05:00
|
|
|
end
|
2023-09-08 12:30:23 -05:00
|
|
|
player_data.fill1 = nil
|
|
|
|
player_data.fill2 = nil
|
2023-03-20 12:15:40 -05:00
|
|
|
end
|
2023-09-08 12:30:23 -05:00
|
|
|
end,
|
2023-03-20 12:15:40 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
|
|
if formname ~= "edit:fill" then return false end
|
|
|
|
|
|
|
|
minetest.close_formspec(player:get_player_name(), "edit:fill")
|
|
|
|
|
|
|
|
local d = edit.player_data[player]
|
|
|
|
|
|
|
|
if
|
2023-09-08 12:30:23 -05:00
|
|
|
not d.fill1 or not d.fill2 or
|
2023-03-20 12:15:40 -05:00
|
|
|
not edit.has_privilege(player)
|
|
|
|
then return true end
|
|
|
|
|
2023-09-08 12:30:23 -05:00
|
|
|
local p1 = d.fill1._pos
|
|
|
|
local p2 = d.fill2._pos
|
|
|
|
|
|
|
|
d.fill1.object:remove()
|
2023-03-20 12:15:40 -05:00
|
|
|
|
|
|
|
local name
|
|
|
|
local def
|
|
|
|
for key, val in pairs(fields) do
|
|
|
|
if key == "quit" then return true end
|
|
|
|
if key == "" then key = "air" end
|
|
|
|
|
|
|
|
name = key
|
|
|
|
def = minetest.registered_items[name]
|
|
|
|
|
|
|
|
if def then break end
|
|
|
|
end
|
|
|
|
|
|
|
|
if not def then return true 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
|
|
|
|
|
2023-09-08 12:30:23 -05:00
|
|
|
local on_place = def.on_place or function() end
|
2023-03-20 12:15:40 -05:00
|
|
|
|
|
|
|
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
|
2023-09-08 12:30:23 -05:00
|
|
|
local node = {name = name, param2 = param2}
|
2023-03-20 12:15:40 -05:00
|
|
|
-- 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)
|
2023-09-08 12:30:23 -05:00
|
|
|
edit.place_node_like_player(player, node, pos)
|
2023-03-20 12:15:40 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
2023-09-08 12:30:23 -05:00
|
|
|
end)
|