Basic laser physics
This commit is contained in:
parent
e651c2757b
commit
d254ae1d49
@ -11,7 +11,8 @@ minetest.register_node("lzr_laser:mirror", {
|
||||
"lzr_laser_mirror_block.png",
|
||||
"lzr_laser_mirror_hole.png",
|
||||
},
|
||||
groups = { mirror = 1, dig_immediate = 2 },
|
||||
groups = { mirror = 1, laser_block = 1, dig_immediate = 2 },
|
||||
_lzr_active = "lzr_laser:mirror_on",
|
||||
})
|
||||
|
||||
minetest.register_node("lzr_laser:mirror_on", {
|
||||
@ -25,7 +26,8 @@ minetest.register_node("lzr_laser:mirror_on", {
|
||||
"lzr_laser_mirror_on_block.png",
|
||||
"lzr_laser_mirror_on_hole.png",
|
||||
},
|
||||
groups = { mirror = 2, laser = 2, dig_immediate = 2, not_in_creative_inventory = 1 },
|
||||
groups = { mirror = 2, laser_block = 1, dig_immediate = 2, not_in_creative_inventory = 1 },
|
||||
_lzr_inactive = "lzr_laser:mirror",
|
||||
})
|
||||
|
||||
minetest.register_node("lzr_laser:emitter", {
|
||||
@ -39,7 +41,8 @@ minetest.register_node("lzr_laser:emitter", {
|
||||
"lzr_laser_emitter.png",
|
||||
"lzr_laser_emitter_front.png",
|
||||
},
|
||||
groups = { emitter = 1, dig_immediate = 2 },
|
||||
groups = { emitter = 1, laser_block = 1, dig_immediate = 2 },
|
||||
_lzr_active = "lzr_laser:emitter_on",
|
||||
})
|
||||
|
||||
minetest.register_node("lzr_laser:emitter_on", {
|
||||
@ -53,7 +56,8 @@ minetest.register_node("lzr_laser:emitter_on", {
|
||||
"lzr_laser_emitter_on.png",
|
||||
"lzr_laser_emitter_on_front.png",
|
||||
},
|
||||
groups = { emitter = 2, dig_immediate = 2, not_in_creative_inventory = 1 },
|
||||
groups = { emitter = 2, laser_block = 1, dig_immediate = 2, not_in_creative_inventory = 1 },
|
||||
_lzr_inactive = "lzr_laser:emitter",
|
||||
})
|
||||
|
||||
minetest.register_node("lzr_laser:detector", {
|
||||
@ -67,7 +71,8 @@ minetest.register_node("lzr_laser:detector", {
|
||||
"lzr_laser_detector.png",
|
||||
"lzr_laser_detector_front.png",
|
||||
},
|
||||
groups = { detector = 1, dig_immediate = 2 },
|
||||
groups = { detector = 1, laser_block = 1, dig_immediate = 2 },
|
||||
_lzr_active = "lzr_laser:detector_on",
|
||||
})
|
||||
|
||||
minetest.register_node("lzr_laser:detector_on", {
|
||||
@ -81,6 +86,7 @@ minetest.register_node("lzr_laser:detector_on", {
|
||||
"lzr_laser_detector_on.png",
|
||||
"lzr_laser_detector_on_front.png",
|
||||
},
|
||||
groups = { detector = 2, dig_immediate = 2, not_in_creative_inventory = 1 },
|
||||
groups = { detector = 2, laser_block = 1, dig_immediate = 2, not_in_creative_inventory = 1 },
|
||||
_lzr_inactive = "lzr_laser:detector",
|
||||
})
|
||||
|
||||
|
@ -3,3 +3,4 @@ lzr_laser = {}
|
||||
dofile(minetest.get_modpath("lzr_laser").."/util.lua")
|
||||
dofile(minetest.get_modpath("lzr_laser").."/laser.lua")
|
||||
dofile(minetest.get_modpath("lzr_laser").."/blocks.lua")
|
||||
dofile(minetest.get_modpath("lzr_laser").."/physics.lua")
|
||||
|
@ -65,6 +65,6 @@ for i=1, 64 do
|
||||
type = "fixed",
|
||||
fixed = dirs_to_nodebox(dirs),
|
||||
},
|
||||
groups = { laser = 1, dig_immediate = 3, not_in_creative_inventory = 1 },
|
||||
groups = { laser = i, dig_immediate = 3, not_in_creative_inventory = 1 },
|
||||
})
|
||||
end
|
||||
|
73
mods/lzr_laser/physics.lua
Normal file
73
mods/lzr_laser/physics.lua
Normal file
@ -0,0 +1,73 @@
|
||||
-- Max. number of steps in the laser travel algorithm
|
||||
local MAX_LASER_ITERATIONS = 50
|
||||
|
||||
-- Add a laser node to pos with the direction `dir`.
|
||||
-- Dir is a direction vector, and only one direction must be set
|
||||
function lzr_laser.add_laser(pos, dir)
|
||||
local node = minetest.get_node(pos)
|
||||
-- Laser through air
|
||||
if node.name == "air" then
|
||||
local dirs = lzr_laser.vector_to_dirs(dir)
|
||||
local dirstring = lzr_laser.dirs_to_dirstring(dirs)
|
||||
minetest.set_node(pos, {name="lzr_laser:laser_"..dirstring})
|
||||
return true
|
||||
-- Laser through laser (laser intersection)
|
||||
elseif minetest.get_item_group(node.name, "laser") > 0 then
|
||||
local dirnum = minetest.get_item_group(node.name, "laser")
|
||||
local dirstring_old = lzr_laser.dec2bin(dirnum, 6)
|
||||
|
||||
local dirs_new = lzr_laser.vector_to_dirs(dir)
|
||||
local dirstring_new = lzr_laser.dirs_to_dirstring(dirs_new)
|
||||
|
||||
local place_dirstring = lzr_laser.bitwise_or(dirstring_old, dirstring_new)
|
||||
minetest.set_node(pos, {name="lzr_laser:laser_"..place_dirstring})
|
||||
return true
|
||||
-- Anything else: fail
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function lzr_laser.emit_laser(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if not minetest.get_item_group(node.name, "emitter") > 0 then
|
||||
minetest.log("error", "[lzr_lazer] lzr_laser.emit_laser was called at invalid pos!")
|
||||
return false
|
||||
end
|
||||
local dir = minetest.facedir_to_dir(node.param2)
|
||||
local i_pos = vector.add(pos, dir)
|
||||
end
|
||||
|
||||
function lzr_laser.travel_laser(pos, dir)
|
||||
local i_pos = vector.add(pos, dir)
|
||||
local cond = true
|
||||
local i = 0
|
||||
while cond do
|
||||
i = i + 1
|
||||
-- Halt execution for very long loops to prevent freezing the game
|
||||
if i > MAX_LASER_ITERATIONS then
|
||||
minetest.log("error", "[lzr_laser] lzr_laser.travel_laser aborted (too many iterations!)")
|
||||
break
|
||||
end
|
||||
local i_node = minetest.get_node(i_pos)
|
||||
cond = lzr_laser.add_laser(i_pos, dir)
|
||||
i_pos = vector.add(i_pos, dir)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove all lasers in area and disable all laser blocks
|
||||
function lzr_laser.clear_lasers_in_area(pos1, pos2)
|
||||
local lasers = minetest.find_nodes_in_area(pos1, pos2, {"group:laser"})
|
||||
minetest.bulk_set_node(lasers, {name="air"})
|
||||
local laser_blocks = minetest.find_nodes_in_area(pos1, pos2, {"group:laser_block"})
|
||||
for b=1, #laser_blocks do
|
||||
local block = minetest.get_node(laser_blocks[b])
|
||||
local def = minetest.registered_nodes[block.name]
|
||||
if def then
|
||||
local inactive = def._lzr_inactive
|
||||
if inactive then
|
||||
minetest.set_node(block, {name="inactive", param2=block.param2})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -5,7 +5,7 @@ local LASER_RADIUS = -1/16
|
||||
--[[ dirstring: A representation of 6 cardinal directions which are either
|
||||
'active' (1) or 'inactive' (0)
|
||||
Each direction has the character "1" or "0".
|
||||
The characters stand for these directions, in order: -X, +X, -Y, +Y, -Z, +Z
|
||||
The characters stand for these directions, in order: -X, -Y, -Z, +X, +Y, +Z
|
||||
Example: "101010"
|
||||
]]
|
||||
--[[ dirs table: Like dirstring, but in table format. It's a table
|
||||
@ -44,6 +44,29 @@ function lzr_laser.dirs_to_dirstring(dirs)
|
||||
return dirstring
|
||||
end
|
||||
|
||||
function lzr_laser.vector_to_dirs(dir_vector)
|
||||
local dirs = {0,0,0,0,0,0}
|
||||
if dir_vector.x > 0 then
|
||||
dirs[4] = 1
|
||||
end
|
||||
if dir_vector.x < 0 then
|
||||
dirs[1] = 1
|
||||
end
|
||||
if dir_vector.y > 0 then
|
||||
dirs[5] = 1
|
||||
end
|
||||
if dir_vector.y < 0 then
|
||||
dirs[2] = 1
|
||||
end
|
||||
if dir_vector.z > 0 then
|
||||
dirs[6] = 1
|
||||
end
|
||||
if dir_vector.z < 0 then
|
||||
dirs[3] = 1
|
||||
end
|
||||
return dirs
|
||||
end
|
||||
|
||||
-- Convert number to string in binary form
|
||||
-- * num: Number
|
||||
-- * minLength: Minimum number of characters the string must have, will
|
||||
@ -69,3 +92,18 @@ function lzr_laser.dec2bin(num, minLength)
|
||||
return bin
|
||||
end
|
||||
|
||||
-- Takes 2 binary numbers (as strings!)
|
||||
-- and returns the 'bitwise or' of them (also as string).
|
||||
-- Both strings MUST be of equal length.
|
||||
function lzr_laser.bitwise_or(bin1, bin2)
|
||||
local len = string.len(bin1)
|
||||
local out = ""
|
||||
for i=1, len do
|
||||
if string.sub(bin1, i, i) == "1" or string.sub(bin2, i, i) == "1" then
|
||||
out = out .. "1"
|
||||
else
|
||||
out = out .. "0"
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user