From 5f65950bf4fd7ac11e2acc5ac056bebaf81da091 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Sat, 8 Jan 2022 20:49:50 +0100 Subject: [PATCH] Use VManip for laser update --- mods/lzr_globals/init.lua | 4 +- mods/lzr_laser/physics.lua | 76 +++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/mods/lzr_globals/init.lua b/mods/lzr_globals/init.lua index ffa8207..ccbaa32 100644 --- a/mods/lzr_globals/init.lua +++ b/mods/lzr_globals/init.lua @@ -1,7 +1,7 @@ lzr_globals = {} -lzr_globals.PLAYFIELD_START = { x = -50, y = 0, z = -50 } -lzr_globals.PLAYFIELD_SIZE = { x = 100, y = 100, z = 100 } +lzr_globals.PLAYFIELD_START = { x = -5, y = 0, z = -5 } +lzr_globals.PLAYFIELD_SIZE = { x = 20, y = 20, z = 20 } lzr_globals.PLAYFIELD_END = vector.add(lzr_globals.PLAYFIELD_START, lzr_globals.PLAYFIELD_SIZE) lzr_globals.LEVEL_POS = { x = 0, y = 0, z = 0 } lzr_globals.MENU_SHIP_POS = { x = -500, y = -4, z = -500 } diff --git a/mods/lzr_laser/physics.lua b/mods/lzr_laser/physics.lua index 3147565..f1ad9fe 100644 --- a/mods/lzr_laser/physics.lua +++ b/mods/lzr_laser/physics.lua @@ -3,44 +3,46 @@ local MAX_LASER_ITERATIONS = 10000 -- 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) +function lzr_laser.add_laser(pos, dir, varea, vdata) -- Check if laser is still within the playfield if pos.x < lzr_globals.PLAYFIELD_START.x or pos.x > lzr_globals.PLAYFIELD_END.x or pos.y < lzr_globals.PLAYFIELD_START.y or pos.y > lzr_globals.PLAYFIELD_END.y or pos.z < lzr_globals.PLAYFIELD_START.z or pos.z > lzr_globals.PLAYFIELD_END.z then return false end - local node = minetest.get_node(pos) + local vi = varea:indexp(pos) + local content_id = vdata[vi] + local nodename = minetest.get_name_from_content_id(content_id) -- Laser through air - if node.name == "air" then + if content_id == minetest.CONTENT_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}) + vdata[vi] = minetest.get_content_id("lzr_laser:laser_"..dirstring) pos = vector.add(pos, dir) return {{pos, dir}} -- Laser through laser (laser intersection) - elseif minetest.get_item_group(node.name, "laser") > 0 then - local dirnum = minetest.get_item_group(node.name, "laser") + elseif minetest.get_item_group(nodename, "laser") > 0 then + local dirnum = minetest.get_item_group(nodename, "laser") local dirstring_old = lzr_laser.dec2bin(dirnum, 3) 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}) + vdata[vi] = minetest.get_content_id("lzr_laser:laser_"..place_dirstring) pos = vector.add(pos, dir) return {{pos, dir}} -- Mirror laser - elseif minetest.get_item_group(node.name, "mirror") > 0 then + elseif minetest.get_item_group(nodename, "mirror") > 0 then local mirror_dir = lzr_laser.get_mirrored_laser_dir(pos, dir) if mirror_dir then - local def = minetest.registered_nodes[node.name] + local def = minetest.registered_nodes[nodename] local active = def._lzr_active if not active then return false end -- Activate mirror node - minetest.set_node(pos, {name=def._lzr_active, param2 = node.param2}) + vdata[vi] = minetest.get_content_id(def._lzr_active) -- Set new pos and dir pos = vector.add(pos, mirror_dir) dir = mirror_dir @@ -49,16 +51,16 @@ function lzr_laser.add_laser(pos, dir) return false end -- Mirror and split laser - elseif minetest.get_item_group(node.name, "transmissive_mirror") > 0 then + elseif minetest.get_item_group(nodename, "transmissive_mirror") > 0 then local mirror_dir = lzr_laser.get_mirrored_laser_dir(pos, dir) if mirror_dir then - local def = minetest.registered_nodes[node.name] + local def = minetest.registered_nodes[nodename] local active = def._lzr_active if not active then return false end -- Activate mirror node - minetest.set_node(pos, {name=active, param2 = node.param2}) + vdata[vi] = minetest.get_content_id(active) -- Set new pos and dir local pos_straight = vector.add(pos, dir) local dir_straight = dir @@ -69,14 +71,14 @@ function lzr_laser.add_laser(pos, dir) return false end -- Spread laser to all directions - elseif minetest.get_item_group(node.name, "crystal") > 0 then - local def = minetest.registered_nodes[node.name] + elseif minetest.get_item_group(nodename, "crystal") > 0 then + local def = minetest.registered_nodes[nodename] local active = def._lzr_active if not active then return false end -- Activate node - minetest.set_node(pos, {name=active, param2 = node.param2}) + vdata[vi] = minetest.get_content_id(active) -- Set dirs local dirs = { { x = 0, y = -1, z = 0 }, @@ -98,13 +100,13 @@ function lzr_laser.add_laser(pos, dir) end return output -- Detector - elseif minetest.get_item_group(node.name, "detector") > 0 then + elseif minetest.get_item_group(nodename, "detector") > 0 then local detected = lzr_laser.check_detector(pos, dir) if detected then - local def = minetest.registered_nodes[node.name] + local def = minetest.registered_nodes[nodename] local active = def._lzr_active -- Activate node - minetest.set_node(pos, {name=active, param2 = node.param2}) + vdata[vi] = minetest.get_content_id(active) local done = lzr_laser.check_detectors_in_area(lzr_globals.PLAYFIELD_START, lzr_globals.PLAYFIELD_END) if done then lzr_levels.next_level() @@ -118,19 +120,24 @@ function lzr_laser.add_laser(pos, dir) end end -function lzr_laser.emit_laser(pos) - local node = minetest.get_node(pos) - if minetest.get_item_group(node.name, "emitter") == 0 then +function lzr_laser.emit_laser(pos, varea, vdata, vdata_p2) + local vi = varea:indexp(pos) + local content_id = vdata[vi] + local nodename = minetest.get_name_from_content_id(content_id) + if minetest.get_item_group(nodename, "emitter") == 0 then minetest.log("error", "[lzr_laser] lzr_laser.emit_laser was called at invalid pos!") return false end - local dir = minetest.facedir_to_dir(node.param2) + local param2 = vdata_p2[vi] + + local dir = minetest.facedir_to_dir(param2) dir = vector.multiply(dir, -1) local i_pos = vector.add(pos, dir) - lzr_laser.travel_laser(i_pos, dir) + lzr_laser.travel_laser(i_pos, dir, varea, vdata) + end -function lzr_laser.travel_laser(pos, dir) +function lzr_laser.travel_laser(pos, dir, varea, vdata) local i_pos = table.copy(pos) local cond = true local next_lasers = {{i_pos, dir}} @@ -143,7 +150,7 @@ function lzr_laser.travel_laser(pos, dir) break end local next_laser = next_lasers[1] - local add_laser_result = lzr_laser.add_laser(next_laser[1], next_laser[2]) + local add_laser_result = lzr_laser.add_laser(next_laser[1], next_laser[2], varea, vdata) table.remove(next_lasers, 1) if add_laser_result ~= false then for a=1, #add_laser_result do @@ -183,15 +190,26 @@ end -- Emit lasers from all active emitters function lzr_laser.emit_lasers_in_area(pos1, pos2) + local vmanip = minetest.get_voxel_manip(pos1, pos2) + local vpos1, vpos2 = vmanip:get_emerged_area() + local varea = VoxelArea:new({MinEdge = vpos1, MaxEdge = vpos2}) + local vdata = vmanip:get_data() + local vdata_p2 = vmanip:get_param2_data() local emitters = minetest.find_nodes_in_area(pos1, pos2, {"group:emitter"}) for e=1, #emitters do local epos = emitters[e] - local emitter = minetest.get_node(epos) - local is_active = minetest.get_item_group(emitter.name, "emitter") == 2 + local vi = varea:indexp(epos) + local emitter_cid = vdata[vi] + local emittername = minetest.get_name_from_content_id(emitter_cid) + local is_active = minetest.get_item_group(emittername, "emitter") == 2 if is_active then - lzr_laser.emit_laser(emitters[e]) + lzr_laser.emit_laser(emitters[e], varea, vdata, vdata_p2) end end + + vmanip:set_data(vdata) + vmanip:set_param2_data(vdata_p2) + vmanip:write_to_map() end -- Return true if all detectors in area are on (including if no detector)