indicator entities for when Digtron can't be built

This commit is contained in:
FaceDeer 2019-08-20 18:58:32 -06:00
parent f14b0a9a42
commit 292889651c
3 changed files with 248 additions and 26 deletions

201
entities.lua Normal file

@ -0,0 +1,201 @@
-- The default minetest.add_entity crashes with an exception if you try adding an entity in an unloaded area
-- this wrapper catches that exception and just ignores it.
digtron.safe_add_entity = function(pos, name)
success, ret = pcall(minetest.add_entity, pos, name)
if success then return ret else return nil end
end
local safe_add_entity = digtron.safe_add_entity
-------------------------------------------------------------------------------------------------
-- For displaying where things get built under which periodicities
minetest.register_entity("digtron:marker", {
initial_properties = {
visual = "cube",
visual_size = {x=1.05, y=1.05},
textures = {"digtron_marker_side.png","digtron_marker_side.png","digtron_marker.png","digtron_marker.png","digtron_marker_side.png","digtron_marker_side.png"},
collisionbox = {-0.525, -0.525, -0.525, 0.525, 0.525, 0.525},
physical = false,
},
on_activate = function(self, staticdata)
minetest.after(5.0,
function(self)
self.object:remove()
end,
self)
end,
on_rightclick=function(self, clicker)
self.object:remove()
end,
on_punch = function(self, hitter)
self.object:remove()
end,
})
local vertical = {x=1.5708, y=0, z=0}
-- TODO: update to new method of finding buildpos?
-- TODO: add item indicator entity as well
digtron.show_offset_markers = function(pos, offset, period)
local buildpos = digtron.find_new_pos(pos, minetest.get_node(pos).param2)
local x_pos = math.floor((buildpos.x+offset)/period)*period - offset
safe_add_entity({x=x_pos, y=buildpos.y, z=buildpos.z}, "digtron:marker")
if x_pos >= buildpos.x then
safe_add_entity({x=x_pos - period, y=buildpos.y, z=buildpos.z}, "digtron:marker")
end
if x_pos <= buildpos.x then
safe_add_entity({x=x_pos + period, y=buildpos.y, z=buildpos.z}, "digtron:marker")
end
local y_pos = math.floor((buildpos.y+offset)/period)*period - offset
local entity = safe_add_entity({x=buildpos.x, y=y_pos, z=buildpos.z}, "digtron:marker")
if entity ~= nil then entity:set_rotation(vertical) end
if y_pos >= buildpos.y then
local entity = safe_add_entity({x=buildpos.x, y=y_pos - period, z=buildpos.z}, "digtron:marker")
if entity ~= nil then entity:set_rotation(vertical) end
end
if y_pos <= buildpos.y then
local entity = safe_add_entity({x=buildpos.x, y=y_pos + period, z=buildpos.z}, "digtron:marker")
if entity ~= nil then entity:set_rotation(vertical) end
end
local z_pos = math.floor((buildpos.z+offset)/period)*period - offset
local entity = safe_add_entity({x=buildpos.x, y=buildpos.y, z=z_pos}, "digtron:marker")
if entity ~= nil then entity:setyaw(1.5708) end
if z_pos >= buildpos.z then
local entity = safe_add_entity({x=buildpos.x, y=buildpos.y, z=z_pos - period}, "digtron:marker")
if entity ~= nil then entity:setyaw(1.5708) end
end
if z_pos <= buildpos.z then
local entity = safe_add_entity({x=buildpos.x, y=buildpos.y, z=z_pos + period}, "digtron:marker")
if entity ~= nil then entity:setyaw(1.5708) end
end
end
-----------------------------------------------------------------------------------------------
-- For displaying whether nodes are part of a digtron or are obstructed
minetest.register_entity("digtron:marker_crate_good", {
initial_properties = {
visual = "cube",
visual_size = {x=1.05, y=1.05},
textures = {"digtron_crate.png", "digtron_crate.png", "digtron_crate.png", "digtron_crate.png", "digtron_crate.png", "digtron_crate.png"},
collisionbox = {-0.525, -0.525, -0.525, 0.525, 0.525, 0.525},
physical = false,
glow = minetest.LIGHT_MAX,
},
on_activate = function(self, staticdata)
minetest.after(digtron.config.marker_crate_good_duration,
function(self)
self.object:remove()
end,
self)
end,
on_rightclick=function(self, clicker)
self.object:remove()
end,
on_punch = function(self, hitter)
self.object:remove()
end,
})
minetest.register_entity("digtron:marker_crate_bad", {
initial_properties = {
visual = "cube",
visual_size = {x=1.05, y=1.05},
textures = {"digtron_no_entry.png", "digtron_no_entry.png", "digtron_no_entry.png", "digtron_no_entry.png", "digtron_no_entry.png", "digtron_no_entry.png"},
collisionbox = {-0.525, -0.525, -0.525, 0.525, 0.525, 0.525},
physical = false,
glow = minetest.LIGHT_MAX,
},
on_activate = function(self, staticdata)
minetest.after(digtron.config.marker_crate_bad_duration,
function(self)
self.object:remove()
end,
self)
end,
on_rightclick=function(self, clicker)
self.object:remove()
end,
on_punch = function(self, hitter)
self.object:remove()
end,
})
-----------------------------------------------------------------------------------------------------------------
-- Builder items
digtron.remove_builder_item = function(pos)
local objects = minetest.env:get_objects_inside_radius(pos, 0.5)
if objects ~= nil then
for _, obj in ipairs(objects) do
if obj and obj:get_luaentity() and obj:get_luaentity().name == "digtron:builder_item" then
obj:remove()
end
end
end
end
digtron.update_builder_item = function(pos)
digtron.remove_builder_item(pos)
node_inventory_table.pos = pos
local inv = minetest.get_inventory(node_inventory_table)
local item_stack = inv:get_stack("main", 1)
if not item_stack:is_empty() then
digtron.create_builder_item = item_stack:get_name()
minetest.add_entity(pos,"digtron:builder_item")
end
end
minetest.register_entity("digtron:builder_item", {
initial_properties = {
hp_max = 1,
is_visible = true,
visual = "wielditem",
visual_size = {x=0.25, y=0.25},
collisionbox = {0,0,0,0,0,0},
physical = false,
textures = {""},
automatic_rotate = math.pi * 0.25,
},
on_activate = function(self, staticdata)
local props = self.object:get_properties()
if staticdata ~= nil and staticdata ~= "" then
local pos = self.object:getpos()
local node = minetest.get_node(pos)
if minetest.get_node_group(node.name, "digtron") ~= 4 then
-- We were reactivated without a builder node on our location, self-destruct
self.object:remove()
return
end
props.textures = {staticdata}
self.object:set_properties(props)
elseif digtron.create_builder_item ~= nil then
props.textures = {digtron.create_builder_item}
self.object:set_properties(props)
digtron.create_builder_item = nil
else
self.object:remove()
end
end,
get_staticdata = function(self)
local props = self.object:get_properties()
if props ~= nil and props.textures ~= nil and props.textures[1] ~= nil then
return props.textures[1]
end
return ""
end,
})

@ -469,10 +469,10 @@ digtron.remove_from_world = function(digtron_id, root_pos, player_name)
minetest.bulk_set_node(nodes_to_destroy, {name="air"}) minetest.bulk_set_node(nodes_to_destroy, {name="air"})
end end
digtron.build_to_world = function(digtron_id, root_pos, player_name) -- Tests if a Digtron can be built at the designated location
digtron.is_buildable_to = function(digtron_id, root_pos, player_name, show_visualization)
local layout = retrieve_layout(digtron_id) local layout = retrieve_layout(digtron_id)
local root_hash = minetest.hash_node_position(root_pos) local root_hash = minetest.hash_node_position(root_pos)
local nodes_to_create = {}
local permitted = true local permitted = true
for hash, data in pairs(layout) do for hash, data in pairs(layout) do
@ -482,12 +482,28 @@ digtron.build_to_world = function(digtron_id, root_pos, player_name)
-- TODO: lots of testing needed here -- TODO: lots of testing needed here
if not (node_def and node_def.buildable_to) then if not (node_def and node_def.buildable_to) then
minetest.chat_send_all("not permitted due to " .. node.name .. " at " .. minetest.pos_to_string(node_pos)) minetest.chat_send_all("not permitted due to " .. node.name .. " at " .. minetest.pos_to_string(node_pos))
if not show_visualization then
return false
else
permitted = false permitted = false
break digtron.safe_add_entity(node_pos, "digtron:marker_crate_bad")
end end
elseif show_visualization then
digtron.safe_add_entity(node_pos, "digtron:marker_crate_good")
end
end
return permitted
end
-- Places the Digtron into the world.
digtron.build_to_world = function(digtron_id, root_pos, player_name)
local layout = retrieve_layout(digtron_id)
local root_hash = minetest.hash_node_position(root_pos)
if not digtron.is_buildable_to(digtron_id, root_pos, player_name, true) then
return false
end end
if permitted then
-- TODO: voxelmanip might be better here, less likely than with destroy though since metadata needs to be written -- TODO: voxelmanip might be better here, less likely than with destroy though since metadata needs to be written
for hash, data in pairs(layout) do for hash, data in pairs(layout) do
local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash) local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
@ -507,9 +523,8 @@ digtron.build_to_world = function(digtron_id, root_pos, player_name)
local bbox = retrieve_bounding_box(digtron_id) local bbox = retrieve_bounding_box(digtron_id)
persist_bounding_box(digtron_id, bbox) persist_bounding_box(digtron_id, bbox)
persist_pos(digtron_id, root_pos) persist_pos(digtron_id, root_pos)
end
return permitted return true
end end
--------------------------------------------------------------------------------- ---------------------------------------------------------------------------------

@ -1,8 +1,14 @@
digtron = {} digtron = {}
digtron.doc = {} digtron.doc = {}
digtron.config = {}
digtron.config.marker_crate_bad_duration = 5
digtron.config.marker_crate_good_duration = 5
local modpath = minetest.get_modpath(minetest.get_current_modname()) local modpath = minetest.get_modpath(minetest.get_current_modname())
dofile(modpath.."/entities.lua")
dofile(modpath.."/functions.lua") dofile(modpath.."/functions.lua")
dofile(modpath.."/controller.lua") dofile(modpath.."/controller.lua")
dofile(modpath.."/nodes/node_misc.lua") dofile(modpath.."/nodes/node_misc.lua")