Fix backwards rotation and add fast node filling
This commit is contained in:
parent
3e0ed1273b
commit
72457e934c
33
README.md
33
README.md
@ -27,7 +27,7 @@ This mod was inspired by the Fill Start and Fill End blocks in Manic Digger.
|
|||||||
| Undo | edit:undo | ![](textures/edit_undo.png) |
|
| Undo | edit:undo | ![](textures/edit_undo.png) |
|
||||||
|
|
||||||
|
|
||||||
## Dependences
|
## Dependencies
|
||||||
|
|
||||||
None
|
None
|
||||||
|
|
||||||
@ -43,17 +43,17 @@ When two copy nodes are placed at opposite corners of an area, they select the a
|
|||||||
|
|
||||||
### Paste Node
|
### Paste Node
|
||||||
|
|
||||||
The paste node is used for pasting the area copied by the copy node or a schematic loaded with the open node. When a paste node is placed, the copied area or schematic is placed at the corner of the paste node. In the case of a copied area, area is pasted relative to the position of the first placed copy node when it was copied. The copied area can be rotated when the paste preview is visable by pressing the sneak key and an arrow key.
|
The paste node is used for pasting the area copied by the copy node or a schematic loaded with the open node. When a paste node is placed, the copied area or schematic is placed at the corner of the paste node. In the case of a copied area, area is pasted relative to the position of the first placed copy node when it was copied. The copied area can be rotated when the paste preview is visible by pressing the sneak key and an arrow key.
|
||||||
|
|
||||||
|
|
||||||
### Delete Node
|
### Delete Node
|
||||||
|
|
||||||
Delete nodes are used to delete an area. When two delete nodes are placed at opposite corners of an area, they select the area as show in figure 1. When an area is selected, it is deleted and the two delete nodes are removed as well.
|
Delete nodes are used to delete a 3D area. When two delete nodes are placed at opposite corners of an area, they select the area as show in figure 1. When an area is selected, it is deleted and the two delete nodes are removed as well.
|
||||||
|
|
||||||
|
|
||||||
### Fill Node
|
### Fill Node
|
||||||
|
|
||||||
![figure1.png](figure2.png)
|
![figure2.png](figure2.png)
|
||||||
|
|
||||||
Fill nodes are used to fill a 3D area with a certain item. Start by placing two fill nodes at opposite corners of the desired area. The selected area includes the positions of the fill nodes themselves as shown in figure 2.
|
Fill nodes are used to fill a 3D area with a certain item. Start by placing two fill nodes at opposite corners of the desired area. The selected area includes the positions of the fill nodes themselves as shown in figure 2.
|
||||||
|
|
||||||
@ -77,7 +77,30 @@ Use a second time to redo the undo.
|
|||||||
Only the most resent world modification can be undone.
|
Only the most resent world modification can be undone.
|
||||||
|
|
||||||
|
|
||||||
### License
|
## Settings
|
||||||
|
|
||||||
|
### edit_paste_preview_max_entities
|
||||||
|
|
||||||
|
If the copied area has a larger number of nodes, some nodes will be randomly excluded from the preview.
|
||||||
|
|
||||||
|
|
||||||
|
### edit_max_operation_volume
|
||||||
|
|
||||||
|
The maximum volume of any edit operation. Increase to allow larger operations.
|
||||||
|
|
||||||
|
|
||||||
|
### edit_use_fast_node_fill
|
||||||
|
|
||||||
|
Fast filling of nodes. This uses VoxelManip for fast node placement.
|
||||||
|
No node placement callbacks are called so some nodes might be broken.
|
||||||
|
|
||||||
|
|
||||||
|
## Privileges
|
||||||
|
|
||||||
|
Edit tools and nodes can only be used by players with `edit` privilege.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
CC0 by MrRar check [License](LICENSE) file, this mod was started by MrRar,
|
CC0 by MrRar check [License](LICENSE) file, this mod was started by MrRar,
|
||||||
minetest-mods community.
|
minetest-mods community.
|
||||||
|
93
init.lua
93
init.lua
@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
local player_data = {}
|
local player_data = {}
|
||||||
|
|
||||||
local paste_preview_max_entities = tonumber(minetest.settings:get("paste_preview_max_entities") or 2000)
|
local paste_preview_max_entities = tonumber(minetest.settings:get("edit_paste_preview_max_entities") or 2000)
|
||||||
local max_operation_volume = tonumber(minetest.settings:get("max_operation_volume") or 20000)
|
local max_operation_volume = tonumber(minetest.settings:get("edit_max_operation_volume") or 20000)
|
||||||
|
local use_fast_node_fill = minetest.settings:get_bool("edit_use_fast_node_fill", false)
|
||||||
|
|
||||||
local function create_paste_preview(player)
|
local function create_paste_preview(player)
|
||||||
local player_pos = player:get_pos()
|
local player_pos = player:get_pos()
|
||||||
@ -135,10 +136,15 @@ local function has_privilege(player)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function display_size_error(player)
|
||||||
|
local msg = "Operation too large. The maximum operation volume can be changed in Minetest settings."
|
||||||
|
minetest.chat_send_player(player:get_player_name(), msg)
|
||||||
|
end
|
||||||
|
|
||||||
local function on_place_checks(player)
|
local function on_place_checks(player)
|
||||||
return player and
|
return player and
|
||||||
player:is_player() and
|
player:is_player() and
|
||||||
has_privilege(player)
|
has_privilege(player)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -200,7 +206,7 @@ minetest.register_node("edit:delete", {
|
|||||||
)
|
)
|
||||||
local size = vector.add(vector.subtract(_end, start), 1)
|
local size = vector.add(vector.subtract(_end, start), 1)
|
||||||
if size.x * size.y * size.z > max_operation_volume then
|
if size.x * size.y * size.z > max_operation_volume then
|
||||||
minetest.chat_send_player(player:get_player_name(), "Delete operation too big.")
|
display_size_error(player)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
player_data[player].undo_schematic = schematic_from_map(start, size)
|
player_data[player].undo_schematic = schematic_from_map(start, size)
|
||||||
@ -272,7 +278,7 @@ minetest.register_node("edit:copy",{
|
|||||||
|
|
||||||
local size = vector.add(vector.subtract(_end, start), vector.new(1, 1, 1))
|
local size = vector.add(vector.subtract(_end, start), vector.new(1, 1, 1))
|
||||||
if size.x * size.y * size.z > max_operation_volume then
|
if size.x * size.y * size.z > max_operation_volume then
|
||||||
minetest.chat_send_player(player:get_player_name(), "Copy operation too big.")
|
display_size_error(player)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -444,6 +450,16 @@ minetest.register_node("edit:fill",{
|
|||||||
local itemstack, pos = minetest.item_place_node(itemstack, player, pointed_thing)
|
local itemstack, pos = minetest.item_place_node(itemstack, player, pointed_thing)
|
||||||
|
|
||||||
if player_data[player].fill1_pos and pos then
|
if player_data[player].fill1_pos and pos then
|
||||||
|
local diff = vector.subtract(player_data[player].fill1_pos, pos)
|
||||||
|
local size = vector.add(vector.apply(diff, math.abs), 1)
|
||||||
|
if size.x * size.y * size.z > max_operation_volume then
|
||||||
|
display_size_error(player)
|
||||||
|
minetest.remove_node(player_data[player].fill1_pos)
|
||||||
|
player_data[player].fill1_pos = nil
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
player_data[player].fill2_pos = pos
|
player_data[player].fill2_pos = pos
|
||||||
player_data[player].fill_pointed_thing = pointed_thing
|
player_data[player].fill_pointed_thing = pointed_thing
|
||||||
|
|
||||||
@ -529,9 +545,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
local is_node = minetest.registered_nodes[name]
|
local is_node = minetest.registered_nodes[name]
|
||||||
|
|
||||||
local param2
|
local param2
|
||||||
if def.paramtype2 == "facedir" then
|
if def.paramtype2 == "facedir" or def.paramtype2 == "colorfacedir" then
|
||||||
param2 = minetest.dir_to_facedir(player:get_look_dir())
|
param2 = minetest.dir_to_facedir(player:get_look_dir())
|
||||||
elseif def.paramtype2 == "wallmounted" then
|
elseif def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" then
|
||||||
param2 = minetest.dir_to_wallmounted(player:get_look_dir(), true)
|
param2 = minetest.dir_to_wallmounted(player:get_look_dir(), true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -549,27 +565,46 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
)
|
)
|
||||||
|
|
||||||
local size = vector.add(vector.subtract(_end, start), 1)
|
local size = vector.add(vector.subtract(_end, start), 1)
|
||||||
if size.x * size.y * size.z > max_operation_volume then
|
|
||||||
minetest.chat_send_player(player:get_player_name(), "Fill operation too large.")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
player_data[player].undo_schematic = schematic_from_map(start, size)
|
player_data[player].undo_schematic = schematic_from_map(start, size)
|
||||||
|
|
||||||
for x = start.x, _end.x, 1 do
|
if is_node and use_fast_node_fill then
|
||||||
for y = start.y, _end.y, 1 do
|
local voxel_manip = VoxelManip()
|
||||||
for z = start.z, _end.z, 1 do
|
local vm_start, vm_end = voxel_manip:read_from_map(start, _end)
|
||||||
local pos = vector.new(x, y, z)
|
local param2s = voxel_manip:get_param2_data()
|
||||||
if is_node then
|
local content_ids = voxel_manip:get_data()
|
||||||
minetest.set_node(pos, {name = name, param2 = param2})
|
local content_id = minetest.get_content_id(name)
|
||||||
else
|
|
||||||
minetest.remove_node(pos)
|
local ones = vector.new(1, 1, 1)
|
||||||
end
|
local vm_size = vector.add(vector.subtract(vm_end, vm_start), ones)
|
||||||
if on_place then
|
local voxel_area = VoxelArea:new({MinEdge = ones, MaxEdge = vm_size})
|
||||||
local itemstack = ItemStack(name)
|
local va_start = vector.add(vector.subtract(start, vm_start), ones)
|
||||||
pointed_thing.intersection_point = vector.new(x + 0.5, y, z + 0.5)
|
local va_end = vector.subtract(vector.add(va_start, size), ones)
|
||||||
pointed_thing.above = pos
|
for i in voxel_area:iterp(va_start, va_end) do
|
||||||
pointed_thing.below = vector.new(x, y - 1, z)
|
content_ids[i] = content_id
|
||||||
on_place(itemstack, player, pointed_thing)
|
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
|
||||||
|
for x = start.x, _end.x, 1 do
|
||||||
|
for y = start.y, _end.y, 1 do
|
||||||
|
for z = start.z, _end.z, 1 do
|
||||||
|
local pos = vector.new(x, y, z)
|
||||||
|
if is_node then
|
||||||
|
minetest.set_node(pos, {name = name, param2 = param2})
|
||||||
|
else
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
end
|
||||||
|
if on_place then
|
||||||
|
local itemstack = ItemStack(name)
|
||||||
|
pointed_thing.intersection_point = vector.new(x + 0.5, y, z + 0.5)
|
||||||
|
pointed_thing.above = pos
|
||||||
|
pointed_thing.below = vector.new(x, y - 1, z)
|
||||||
|
on_place(itemstack, player, pointed_thing)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -804,13 +839,13 @@ minetest.register_globalstep(function(dtime)
|
|||||||
local control = player:get_player_control()
|
local control = player:get_player_control()
|
||||||
if control.sneak and control.left then
|
if control.sneak and control.left then
|
||||||
if d.paste_preview_can_rotate then
|
if d.paste_preview_can_rotate then
|
||||||
set_schematic_rotation(d.schematic, -90)
|
set_schematic_rotation(d.schematic, 90)
|
||||||
delete_paste_preview(player)
|
delete_paste_preview(player)
|
||||||
d.paste_preview_can_rotate = false
|
d.paste_preview_can_rotate = false
|
||||||
end
|
end
|
||||||
elseif control.sneak and control.right then
|
elseif control.sneak and control.right then
|
||||||
if d.paste_preview_can_rotate then
|
if d.paste_preview_can_rotate then
|
||||||
set_schematic_rotation(d.schematic, 90)
|
set_schematic_rotation(d.schematic, -90)
|
||||||
delete_paste_preview(player)
|
delete_paste_preview(player)
|
||||||
d.paste_preview_can_rotate = false
|
d.paste_preview_can_rotate = false
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
|
# The maximum number of entities used to construct the paste preview.
|
||||||
|
# If the copied area has a larger number of nodes, some nodes will be randomly excluded from the preview.
|
||||||
|
edit_paste_preview_max_entities (Paste preview max entities) int 2000
|
||||||
|
|
||||||
paste_preview_max_entities (Paste preview max entities) int 2000
|
# The maximum volume of any edit operation. Increase to allow larger operations.
|
||||||
|
edit_max_operation_volume (Max edit operation volume) int 20000
|
||||||
|
|
||||||
max_operation_volume (Max edit operation volume) int 20000
|
# Fast filling of nodes. This uses VoxelManip for fast node placement.
|
||||||
|
# No node placement callbacks are called so some nodes might be broken.
|
||||||
|
edit_use_fast_node_fill (Use fast node fill) bool false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user