artifact.register_node("forcefield", { drawtype = "glasslike_framed", use_texture_alpha = "blend", light_source = 6, tiles = {"artifact_forcefield_border.png", "artifact_forcefield_inner.png"}, visual_scale = 0.75, diggable = false }) local vm_data = {} local vm_p2_data = {} local c_air = minetest.get_content_id("air") local c_forcefield = minetest.get_content_id("forcefield") function artifact.place_forcefield(pos, def) if def.type == "cube" then if def.offset then pos = pos:add(def.offset) end local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius)) local va = VoxelArea(vm:get_emerged_area()) vm:get_data(vm_data) vm:get_param2_data(vm_p2_data) for x = pos.x -def.radius, pos.x +def.radius, def.radius *2 do for y = pos.y -def.radius, pos.y +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x, y, z) if vm_data[idx] == c_air then vm_data[idx] = c_forcefield vm_p2_data[idx] = 1 elseif vm_data[idx] == c_forcefield then vm_p2_data[idx] = vm_p2_data[idx] +1 end end end end for y = pos.y -def.radius, pos.y +def.radius, def.radius *2 do for x = pos.x -def.radius, pos.x +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x, y, z) if vm_data[idx] == c_air then vm_data[idx] = c_forcefield vm_p2_data[idx] = 1 elseif vm_data[idx] == c_forcefield then vm_p2_data[idx] = vm_p2_data[idx] +1 end end end end for z = pos.z -def.radius, pos.z +def.radius, def.radius *2 do for y = pos.y -def.radius, pos.y +def.radius do for x = pos.x -def.radius, pos.x +def.radius do local idx = va:index(x, y, z) if vm_data[idx] == c_air then vm_data[idx] = c_forcefield vm_p2_data[idx] = 1 elseif vm_data[idx] == c_forcefield then vm_p2_data[idx] = vm_p2_data[idx] +1 end end end end vm:set_data(vm_data) vm:set_param2_data(vm_p2_data) vm:write_to_map() elseif def.type == "plane" then local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius)) local va = VoxelArea(vm:get_emerged_area()) vm:get_data(vm_data) vm:get_param2_data(vm_p2_data) local x local y local z if def.axis == "x" then local x = pos.x for y = pos.y -def.radius, pos.y +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z) if vm_data[idx] == c_air then vm_data[idx] = c_forcefield vm_p2_data[idx] = 1 elseif vm_data[idx] == c_forcefield and vm_p2_data[idx] > 0 then vm_p2_data[idx] = vm_p2_data[idx] +1 end end end elseif def.axis == "y" then local y = pos.y for x = pos.x -def.radius, pos.x +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z) if vm_data[idx] == c_air then vm_data[idx] = c_forcefield vm_p2_data[idx] = 1 elseif vm_data[idx] == c_forcefield and vm_p2_data[idx] > 0 then vm_p2_data[idx] = vm_p2_data[idx] +1 end end end elseif def.axis == "z" then local z = pos.z for y = pos.y -def.radius, pos.y +def.radius do for x = pos.x -def.radius, pos.x +def.radius do local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z) if vm_data[idx] == c_air then vm_data[idx] = c_forcefield vm_p2_data[idx] = 1 elseif vm_data[idx] == c_forcefield and vm_p2_data[idx] > 0 then vm_p2_data[idx] = vm_p2_data[idx] +1 end end end end vm:set_data(vm_data) vm:set_param2_data(vm_p2_data) vm:write_to_map() end end function artifact.remove_forcefield(pos, def) if def.type == "cube" then if def.offset then pos = pos:add(def.offset) end local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius)) local va = VoxelArea(vm:get_emerged_area()) vm:get_data(vm_data) vm:get_param2_data(vm_p2_data) for x = pos.x -def.radius, pos.x +def.radius, def.radius *2 do for y = pos.y -def.radius, pos.y +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x, y, z) if vm_data[idx] == c_forcefield then if vm_p2_data[idx] <= 1 then vm_data[idx] = c_air vm_p2_data[idx] = 0 else vm_p2_data[idx] = vm_p2_data[idx] -1 end end end end end for y = pos.y -def.radius, pos.y +def.radius, def.radius *2 do for x = pos.x -def.radius, pos.x +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x, y, z) if vm_data[idx] == c_forcefield then if vm_p2_data[idx] <= 1 then vm_data[idx] = c_air vm_p2_data[idx] = 0 else vm_p2_data[idx] = vm_p2_data[idx] -1 end end end end end for z = pos.z -def.radius, pos.z +def.radius, def.radius *2 do for y = pos.y -def.radius, pos.y +def.radius do for x = pos.x -def.radius, pos.x +def.radius do local idx = va:index(x, y, z) if vm_data[idx] == c_forcefield then if vm_p2_data[idx] <= 1 then vm_data[idx] = c_air vm_p2_data[idx] = 0 else vm_p2_data[idx] = vm_p2_data[idx] -1 end end end end end vm:set_data(vm_data) vm:set_param2_data(vm_p2_data) vm:write_to_map() elseif def.type == "plane" then local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius)) local va = VoxelArea(vm:get_emerged_area()) vm:get_data(vm_data) vm:get_param2_data(vm_p2_data) local x local y local z if def.axis == "x" then local x = pos.x for y = pos.y -def.radius, pos.y +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z) if vm_data[idx] == c_forcefield then if vm_p2_data[idx] <= 1 then vm_data[idx] = c_air vm_p2_data[idx] = 0 else vm_p2_data[idx] = vm_p2_data[idx] -1 end end end end elseif def.axis == "y" then local y = pos.y for x = pos.x -def.radius, pos.x +def.radius do for z = pos.z -def.radius, pos.z +def.radius do local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z) if vm_data[idx] == c_forcefield then if vm_p2_data[idx] <= 1 then vm_data[idx] = c_air vm_p2_data[idx] = 0 else vm_p2_data[idx] = vm_p2_data[idx] -1 end end end end elseif def.axis == "z" then local z = pos.z for y = pos.y -def.radius, pos.y +def.radius do for x = pos.x -def.radius, pos.x +def.radius do local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z) if vm_data[idx] == c_forcefield then if vm_p2_data[idx] <= 1 then vm_data[idx] = c_air vm_p2_data[idx] = 0 else vm_p2_data[idx] = vm_p2_data[idx] -1 end end end end end vm:set_data(vm_data) vm:set_param2_data(vm_p2_data) vm:write_to_map() end end local function onload(pos) local m = minetest.get_meta(pos) if not m:contains("initialized") then local conf = minetest.deserialize(m:get("config") or "return nil") or {type = "plane", radius = 5, axis = "x", offset = vector.new(3,0,0)} m:set_string("_config", minetest.serialize(conf)) m:set_string("config", minetest.serialize(conf)) artifact.place_forcefield(pos, conf) end end artifact.register_node("forcefield_generator", { drawtype = "mesh", mesh = "artifact_forcefield_generator.gltf", tiles = {"artifact_forcefield_generator.png"}, paramtype = "light", light_source = 10, paramtype2 = "facedir", groups = {whackable = 1}, collision_box = { type = "fixed", fixed = { -1, -0.5, -0.5, 1, 0.5, 0.5 } }, selection_box = { type = "fixed", fixed = { -1, -0.5, -0.5, 1, 0.5, 0.5 } }, sounds = artifact.sounds.metal, on_construct = onload, on_load = onload, on_rightclick = artifact.debug and function(pos) local m = minetest.get_meta(pos) artifact.remove_forcefield(pos, minetest.deserialize(m:get("_config") or "return nil") or {type = "plane", radius = 5, axis = "x", offset = vector.new(3,0,0)}) local conf = minetest.deserialize(m:get("config") or "return nil") or {type = "plane", radius = 5, axis = "x", offset = 3} m:set_string("_config", minetest.serialize(conf)) artifact.place_forcefield(pos, conf) end or nil, on_destruct = function(pos) local m = minetest.get_meta(pos) local conf = minetest.deserialize(m:get("config") or "return nil") or {type = "cube", radius = 5} artifact.remove_forcefield(pos, conf) local node = minetest.get_node(pos) node.name = "forcefield_generator_off" minetest.after(0, function() minetest.set_node(pos, node) end) artifact.play_sound { name = "artifact_forcefield_generator_destruct", pos = pos, } minetest.add_particlespawner { pos = pos, vel = vector.zero(), acc = vector.new(0, -9.81, 0), drag = vector.new(3, 0, 3), radius = 0.1, attract = { kind = "point", origin = pos, strength = -50 }, texture = { name = "artifact_light_gold.png", alpha_tween = {1, 0} }, size_tween = { { min = 3, max = 6 }, { min = 1, max = 2 } }, time = 0.3, amount = 100, } end }) artifact.register_node("forcefield_generator_off", { drawtype = "mesh", mesh = "artifact_forcefield_generator.gltf", tiles = {"artifact_forcefield_generator_off.png"}, paramtype = "light", light_source = 6, paramtype2 = "facedir", collision_box = { type = "fixed", fixed = { -1, -0.5, -0.5, 1, 0.5, 0.5 } }, selection_box = { type = "fixed", fixed = { -1, -0.5, -0.5, 1, 0.5, 0.5 } }, sounds = artifact.sounds.metal, on_impact = artifact.debug and function(pos) local node = minetest.get_node(pos) node.name = "forcefield_generator" minetest.set_node(pos, node) end or nil, })