2023-09-08 12:30:23 -05:00
|
|
|
local function place_circle(player, pos, node)
|
|
|
|
local player_data = edit.player_data[player]
|
|
|
|
if
|
|
|
|
player:get_player_control().aux1 or
|
|
|
|
not player_data or
|
|
|
|
not player_data.circle_luaentity
|
|
|
|
or player_data.ignore_node_placement
|
|
|
|
then return end
|
|
|
|
|
|
|
|
local center = player_data.circle_luaentity._pos
|
|
|
|
center.y = pos.y
|
|
|
|
local radius = vector.distance(center, pos)
|
|
|
|
|
|
|
|
if radius < 1 then
|
|
|
|
minetest.set_node(pos, node)
|
|
|
|
return
|
|
|
|
else
|
|
|
|
minetest.remove_node(pos)
|
|
|
|
end
|
|
|
|
|
|
|
|
local radius_rounded = math.ceil(radius) + 1
|
|
|
|
local size = vector.new(radius_rounded * 2, 1, radius_rounded * 2)
|
|
|
|
if size.x * size.y * size.z > edit.max_operation_volume then
|
|
|
|
edit.display_size_error(player)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
player_data.undo_schematic = edit.schematic_from_map(
|
|
|
|
vector.subtract(vector.round(center), vector.new(radius_rounded, 0, radius_rounded)),
|
|
|
|
size
|
|
|
|
)
|
|
|
|
|
|
|
|
player_data.ignore_node_placement = true -- Stop infinite recursion
|
|
|
|
|
|
|
|
-- Midpoint circle algorithm
|
|
|
|
local x = radius
|
|
|
|
local z = 0
|
|
|
|
if center.z % 1 ~= 0 then -- Is the marker in the middle of a node?
|
|
|
|
z = z + 0.5
|
|
|
|
end
|
|
|
|
while x >= z do
|
|
|
|
for factor_x = -1, 1, 2 do
|
|
|
|
for factor_z = -1, 1, 2 do
|
|
|
|
local factor = vector.new(factor_x, 1, factor_z)
|
|
|
|
local offset1 = vector.new(x, 0, z)
|
|
|
|
offset1 = vector.new(
|
|
|
|
offset1.x * factor.x,
|
|
|
|
offset1.y * factor.y,
|
|
|
|
offset1.z * factor.z )
|
|
|
|
local pos1 = vector.add(center, offset1)
|
2024-02-19 20:02:24 -06:00
|
|
|
edit.place_item_like_player(player, node, pos1)
|
2023-09-08 12:30:23 -05:00
|
|
|
|
|
|
|
local offset2 = vector.new(
|
|
|
|
offset1.z,
|
|
|
|
offset1.y,
|
|
|
|
offset1.x
|
|
|
|
)
|
|
|
|
local pos2 = vector.add(center, offset2)
|
2024-02-19 20:02:24 -06:00
|
|
|
edit.place_item_like_player(player, node, pos2)
|
2023-09-08 12:30:23 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
z = z + 1
|
|
|
|
while z * z + x * x > radius * radius do
|
|
|
|
x = x - 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
player_data.ignore_node_placement = false
|
|
|
|
end
|
|
|
|
|
|
|
|
minetest.register_on_dignode(function(pos, oldnode, digger)
|
|
|
|
if not digger or not digger:is_player() then return end
|
2024-01-09 21:58:27 -06:00
|
|
|
return place_circle(digger, pos, {name = "air"}) or true
|
2023-09-08 12:30:23 -05:00
|
|
|
end)
|
|
|
|
|
|
|
|
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
|
|
|
|
if not placer then return end
|
|
|
|
return place_circle(placer, pos, newnode)
|
|
|
|
end)
|
|
|
|
|
|
|
|
local function circle_tool_on_place(itemstack, player, pointed_thing)
|
|
|
|
if not edit.on_place_checks(player) then return end
|
|
|
|
|
|
|
|
local d = edit.player_data[player]
|
|
|
|
if d.circle_luaentity then
|
|
|
|
d.circle_luaentity.object:remove()
|
|
|
|
end
|
|
|
|
|
|
|
|
local pos = edit.get_half_node_pointed_pos(player)
|
|
|
|
|
|
|
|
d.circle_luaentity = edit.add_marker("edit:circle", pos, player)
|
|
|
|
|
|
|
|
d.circle_hud = player:hud_add({
|
|
|
|
hud_elem_type = "text",
|
|
|
|
text = "CIRCLE MODE\n\nPunch the circle center to exit.\nPress the aux1 key (E) while placing to bypass.",
|
|
|
|
position = {x = 0.5, y = 0.8},
|
|
|
|
z_index = 100,
|
|
|
|
number = 0xffffff
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
minetest.register_tool("edit:circle",{
|
|
|
|
description = "Edit Circle",
|
|
|
|
tiles = {"edit_circle.png"},
|
|
|
|
inventory_image = "edit_circle.png",
|
|
|
|
range = 10,
|
2024-01-09 21:58:27 -06:00
|
|
|
groups = {edit_place_preview = 1,},
|
2023-09-08 12:30:23 -05:00
|
|
|
on_place = circle_tool_on_place,
|
|
|
|
on_secondary_use = circle_tool_on_place,
|
2024-01-09 21:58:27 -06:00
|
|
|
_edit_get_pointed_pos = function(player)
|
|
|
|
return edit.get_half_node_pointed_pos(player)
|
|
|
|
end,
|
2023-09-08 12:30:23 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_entity("edit:circle", {
|
|
|
|
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_circle.png",
|
|
|
|
"edit_circle.png",
|
|
|
|
"edit_circle.png",
|
|
|
|
"edit_circle.png",
|
|
|
|
"edit_circle.png",
|
|
|
|
"edit_circle.png",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
on_deactivate = function(self)
|
|
|
|
local player_data = edit.player_data[self._placer]
|
|
|
|
if player_data then
|
|
|
|
player_data.circle_luaentity = nil
|
|
|
|
self._placer:hud_remove(player_data.circle_hud)
|
|
|
|
player_data.circle_hud = nil
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
})
|