diff --git a/controller.lua b/controller.lua index 36c9ad2..ffda5dc 100644 --- a/controller.lua +++ b/controller.lua @@ -51,7 +51,7 @@ local get_controller_assembled_formspec = function(digtron_id, player_name) .. "position[0.025,0.1]" .. "anchor[0,0]" .. "container[0,0]" - .. "list[detached:" .. digtron_id .. ";"..inv_list..";0,0;8,4]" -- TODO: paging system for inventory + .. "list[detached:" .. digtron_id .. ";"..inv_list..";0,0;8,5]" -- TODO: paging system for inventory .. "container_end[]" .. "container[0,5]list[current_player;main;0,0;8,1;]list[current_player;main;0,1.25;8,3;8]container_end[]" .. "listring[current_player;main]" @@ -64,10 +64,10 @@ local get_controller_assembled_formspec = function(digtron_id, player_name) .. "container[0,0]" .. "button[0,0;1,1;disassemble;Disassemble]" .. "field[1.2,0.3;1.75,1;digtron_name;Digtron name;" - ..minetest.formspec_escape(digtron.get_name(digtron_id)).."]" + .. minetest.formspec_escape(digtron.get_name(digtron_id)).."]" .. "field_close_on_enter[digtron_name;false]" .. "field[2.9,0.3;0.7,1;cycles;Cycles;1]" -- TODO persist, actually use - .. "button[3.2,0;1,1;test_dig;Execute]" + .. "button[3.2,0;1,1;execute;Execute]" .. "container_end[]" .. "container[0,1]" @@ -82,7 +82,7 @@ local get_controller_assembled_formspec = function(digtron_id, player_name) .. "container_end[]" .. "container[0.5,3.2]" - .. "box[0,0;3,2;#CCCCCC]" + .. "box[0,0;3,2;#DDDDDD]" .. "label[1.3,0.825;Rotate]" .. "button[0.1,0.1;1,1;rot_counterclockwise;Widdershins]" .. "button[2.1,0.1;1,1;rot_clockwise;Clockwise]" @@ -174,7 +174,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) digtron.rotate(digtron_id, digtron.facedir_to_up(facedir), player_name) end - if fields.test_dig then + if fields.execute then digtron.execute_cycle(digtron_id, player_name) end @@ -195,7 +195,19 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end end) -minetest.register_node("digtron:controller", { +-- Doesn't deep-copy +local combine_defs = function(base_def, override_content) + local out = {} + for key, value in pairs(base_def) do + out[key] = value + end + for key, value in pairs(override_content) do + out[key] = value + end + return out +end + +local base_def = { description = S("Digtron Control Module"), _doc_items_longdesc = nil, _doc_items_usagehelp = nil, @@ -231,6 +243,46 @@ minetest.register_node("digtron:controller", { }, }, sounds = default.node_sound_metal_defaults(), + on_blast = digtron.on_blast, +} + +minetest.register_node("digtron:controller_unassembled", combine_defs(base_def, { + _digtron_assembled_node = "digtron:controller", + + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local returnstack, success = digtron.on_rightclick(pos, node, clicker, itemstack, pointed_thing) + if returnstack then + return returnstack, success + end + + if clicker == nil then return end + + local player_name = clicker:get_player_name() + local digtron_id = digtron.assemble(pos, player_name) + if digtron_id then + local meta = minetest.get_meta(pos) + meta:set_string("digtron_id", digtron_id) + meta:mark_as_private("digtron_id") + player_interacting_with_digtron_id[player_name] = {digtron_id = digtron_id} + minetest.show_formspec(player_name, + "digtron:controller_assembled", + get_controller_assembled_formspec(digtron_id, player_name)) + end + end +})) + +minetest.register_node("digtron:controller", combine_defs(base_def, { + + tiles = { + "digtron_plate.png^[transformR90", + "digtron_plate.png^[transformR270", + "digtron_plate.png", + "digtron_plate.png^[transformR180", + "digtron_plate.png", + "digtron_plate.png^digtron_control.png^digtron_intermittent.png", + }, + _digtron_disassembled_node = "digtron:controller_unassembled", + groups = {cracky = 3, oddly_breakable_by_hand = 3, not_in_creative_inventory = 1}, on_dig = function(pos, node, digger) local player_name @@ -249,7 +301,7 @@ minetest.register_node("digtron:controller", { if stack:get_count() > 0 then minetest.add_item(pos, stack) end - -- call on_dignodes callback + -- TODO call on_dignodes callback if digtron_id ~= "" then local removed = digtron.remove_from_world(digtron_id, player_name) for _, removed_pos in ipairs(removed) do @@ -280,11 +332,6 @@ minetest.register_node("digtron:controller", { local stack_meta = itemstack:get_meta() local digtron_id = stack_meta:get_string("digtron_id") if digtron_id ~= "" then - -- Test if Digtron will fit the surroundings - -- if not, try moving it up so that the lowest y-coordinate on the Digtron is - -- at the y-coordinate of the place clicked on and test again. - -- if that fails, show ghost of Digtron and fail to place. - local target_pos local below_node = minetest.get_node(pointed_thing.under) local below_def = minetest.registered_nodes[below_node.name] @@ -293,23 +340,36 @@ minetest.register_node("digtron:controller", { else target_pos = pointed_thing.above end + -- TODO rotate layout based on player orientation + + -- move up so that the lowest y-coordinate on the Digtron is + -- at the y-coordinate of the place clicked on and test again. + local bbox = digtron.get_bounding_box(digtron_id) + target_pos.y = target_pos.y + math.abs(bbox.minp.y) if target_pos then local success, succeeded, failed = digtron.is_buildable_to(digtron_id, nil, target_pos, player_name) if success then - digtron.build_to_world(digtron_id, nil, target_pos, player_name) + local built_positions = digtron.build_to_world(digtron_id, nil, target_pos, player_name) + for _, built_pos in ipairs(built_positions) do + minetest.check_for_falling(built_pos) + end + minetest.sound_play("digtron_machine_assemble", {gain = 0.5, pos=target_pos}) -- Note: DO NOT RESPECT CREATIVE MODE here. -- If we allow multiple copies of a Digtron running around with the same digtron_id, -- human sacrifice, dogs and cats living together, mass hysteria return ItemStack("") else + -- if that fails, show ghost of Digtron and fail to place. digtron.show_buildable_nodes(succeeded, failed) minetest.sound_play("digtron_buzzer", {gain = 0.5, pos=target_pos}) end end return itemstack else + -- Should be impossible to have a controller without an ID, but if it happens place an unassembled node + itemstack:set_name("digtron:controller_unassembled") return minetest.item_place(itemstack, placer, pointed_thing) end end, @@ -336,29 +396,15 @@ minetest.register_node("digtron:controller", { local meta = minetest.get_meta(pos) local digtron_id = meta:get_string("digtron_id") - local player_name = clicker:get_player_name() if digtron_id == "" then - local digtron_id = digtron.assemble(pos, player_name) - if digtron_id then - meta:set_string("digtron_id", digtron_id) - meta:mark_as_private("digtron_id") - player_interacting_with_digtron_id[player_name] = {digtron_id = digtron_id} - minetest.show_formspec(player_name, - "digtron:controller_assembled", - get_controller_assembled_formspec(digtron_id, player_name)) - end + -- TODO: error message, fix digtron else - -- initialized + local player_name = clicker:get_player_name() player_interacting_with_digtron_id[player_name] = {digtron_id = digtron_id} minetest.show_formspec(player_name, "digtron:controller_assembled", get_controller_assembled_formspec(digtron_id, player_name)) end end, - - on_timer = function(pos, elapsed) - end, - - on_blast = digtron.on_blast, -}) \ No newline at end of file +})) \ No newline at end of file diff --git a/functions.lua b/functions.lua index 4a1fa06..690c710 100644 --- a/functions.lua +++ b/functions.lua @@ -24,8 +24,6 @@ local get_predictive_inventory = inventory_functions.get_predictive_inventory local commit_predictive_inventory = inventory_functions.commit_predictive_inventory local clear_predictive_inventory = inventory_functions.clear_predictive_inventory -digtron.retrieve_inventory = retrieve_inventory -- used by formspecs - -------------------------------------------------------------------------------------- local create_new_id = function() @@ -58,11 +56,11 @@ end -- Name -- Not bothering with a dynamic table store for names, they're just strings with no need for serialization or deserialization -digtron.get_name = function(digtron_id) +local get_name = function(digtron_id) return mod_meta:get_string(digtron_id..":name") end -digtron.set_name = function(digtron_id, digtron_name) +local set_name = function(digtron_id, digtron_name) -- Don't allow a name to be set for a non-existent Digtron if mod_meta:get(digtron_id..":layout") then mod_meta:set_string(digtron_id..":name", digtron_name) @@ -109,8 +107,6 @@ end local persist_layout, retrieve_layout = get_table_functions("layout") local persist_pos, retrieve_pos, dispose_pos = get_table_functions("pos") -digtron.get_pos = retrieve_pos - ------------------------------------------------------------------------------------------------------- -- Layout creation helpers @@ -253,15 +249,9 @@ table.insert(dispose_callbacks, invalidate_layout_cache) -- assemble and disassemble -- Returns the id of the new Digtron record, or nil on failure -digtron.assemble = function(root_pos, player_name) - local node = minetest.get_node(root_pos) - -- TODO: a more generic test? Not needed with the more generic controller design, as far as I can tell. There's only going to be the one type of controller. - if node.name ~= "digtron:controller" then - -- Called on an incorrect node - minetest.log("error", "[Digtron] digtron.assemble called with pos " .. minetest.pos_to_string(root_pos) - .. " but the node at this location was " .. node.name) - return nil - end +local assemble = function(root_pos, player_name) + local root_node = minetest.get_node(root_pos) + local root_meta = minetest.get_meta(root_pos) if root_meta:contains("digtron_id") then -- Already assembled. TODO: validate that the digtron_id actually exists as well @@ -269,8 +259,18 @@ digtron.assemble = function(root_pos, player_name) .. " but the controller at this location was already part of a assembled Digtron.") return nil end + local digtron_name = root_meta:get_string("infotext") + + -- This should be called on an unassembled node. + if root_node.name ~= "digtron:controller_unassembled" then + -- Called on an incorrect node + minetest.log("error", "[Digtron] digtron.assemble called with pos " .. minetest.pos_to_string(root_pos) + .. " but the node at this location was " .. root_node.name) + return nil + end + local root_hash = minetest.hash_node_position(root_pos) - local digtron_nodes = {[root_hash] = node} -- Nodes that are part of Digtron. + local digtron_nodes = {[root_hash] = root_node} -- Nodes that are part of Digtron. -- Initialize with the controller, it won't be added by get_all_adjacent_digtron_nodes local digtron_adjacent = {} -- Nodes that are adjacent to Digtron but not a part of it. -- There's a slight inefficiency in throwing away digtron_adjacent when retrieve_all_adjacent_pos could @@ -326,9 +326,9 @@ digtron.assemble = function(root_pos, player_name) layout[relative_hash] = {meta = current_meta_table, node = node} end - digtron.set_name(digtron_id, root_meta:get_string("infotext")) persist_inventory(digtron_id) persist_layout(digtron_id, layout) + set_name(digtron_id, digtron_name) invalidate_layout_cache(digtron_id) persist_pos(digtron_id, root_pos) @@ -394,8 +394,7 @@ local get_valid_data = function(digtron_id, root_pos, hash, data, function_name) end -- Turns the Digtron back into pieces -digtron.disassemble = function(digtron_id, player_name) - local bbox = retrieve_bounding_box(digtron_id) +local disassemble = function(digtron_id, player_name) local root_pos = retrieve_pos(digtron_id) if not root_pos then minetest.log("error", "[Digtron] digtron.disassemble was unable to find a position for " .. digtron_id @@ -403,11 +402,8 @@ digtron.disassemble = function(digtron_id, player_name) return end - local root_meta = minetest.get_meta(root_pos) - root_meta:set_string("infotext", digtron.get_name(digtron_id)) - local layout = retrieve_layout(digtron_id) - local inv = digtron.retrieve_inventory(digtron_id) + local inv = retrieve_inventory(digtron_id) if not (layout and inv) then minetest.log("error", "[Digtron] digtron.disassemble was unable to find either layout or inventory record for " .. digtron_id @@ -451,7 +447,16 @@ digtron.disassemble = function(digtron_id, player_name) -- Clear digtron_id, this node is no longer part of an active digtron node_meta:set_string("digtron_id", "") end - end + end + + -- replace the controller node with the disassembled version + local root_node = minetest.get_node(root_pos) + if root_node.name == "digtron:controller" then + root_node.name = "digtron:controller_disassembled" + minetest.set_node(root_pos, root_node) + end + local root_meta = minetest.get_meta(root_pos) + root_meta:set_string("infotext", get_name(digtron_id)) minetest.log("action", "Digtron " .. digtron_id .. " disassembled at " .. minetest.pos_to_string(root_pos) .. " by " .. player_name) @@ -468,7 +473,7 @@ end -- Removes the in-world nodes of a digtron -- Does not destroy its layout info -- returns a table of vectors of all the nodes that were removed -digtron.remove_from_world = function(digtron_id, player_name) +local remove_from_world = function(digtron_id, player_name) local layout = retrieve_layout(digtron_id) local root_pos = retrieve_pos(digtron_id) @@ -504,7 +509,7 @@ digtron.remove_from_world = function(digtron_id, player_name) end -- Tests if a Digtron can be built at the designated location -digtron.is_buildable_to = function(digtron_id, layout, root_pos, player_name, ignore_nodes, return_immediately_on_failure) +local is_buildable_to = function(digtron_id, layout, root_pos, player_name, ignore_nodes, return_immediately_on_failure) -- If this digtron is already in-world, we're likely testing as part of a movement attempt. -- Record its existing node locations, they will be treated as buildable_to local old_root_pos = retrieve_pos(digtron_id) @@ -557,10 +562,11 @@ digtron.is_buildable_to = function(digtron_id, layout, root_pos, player_name, ig end -- Places the Digtron into the world. -digtron.build_to_world = function(digtron_id, layout, root_pos, player_name) +local build_to_world = function(digtron_id, layout, root_pos, player_name) if layout == nil then layout = retrieve_layout(digtron_id) end + local built_positions = {} for hash, data in pairs(layout) do -- Don't use get_valid_data, the Digtron isn't in-world yet local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos) @@ -571,18 +577,19 @@ digtron.build_to_world = function(digtron_id, layout, root_pos, player_name) end meta:set_string("digtron_id", digtron_id) meta:mark_as_private("digtron_id") + table.insert(built_positions, node_pos) end persist_pos(digtron_id, root_pos) - return true + return built_positions end -digtron.move = function(digtron_id, dest_pos, player_name) +local move = function(digtron_id, dest_pos, player_name) local layout = retrieve_layout(digtron_id) - local permitted, succeeded, failed = digtron.is_buildable_to(digtron_id, layout, dest_pos, player_name) + local permitted, succeeded, failed = is_buildable_to(digtron_id, layout, dest_pos, player_name) if permitted then - local removed = digtron.remove_from_world(digtron_id, player_name) - digtron.build_to_world(digtron_id, layout, dest_pos, player_name) + local removed = remove_from_world(digtron_id, player_name) + build_to_world(digtron_id, layout, dest_pos, player_name) minetest.sound_play("digtron_truck", {gain = 0.5, pos=dest_pos}) for _, removed_pos in ipairs(removed) do minetest.check_for_falling(removed_pos) @@ -646,13 +653,13 @@ local rotate_layout = function(digtron_id, axis) return rotated_layout end -digtron.rotate = function(digtron_id, axis, player_name) +local rotate = function(digtron_id, axis, player_name) local rotated_layout = rotate_layout(digtron_id, axis) local root_pos = retrieve_pos(digtron_id) - local permitted, succeeded, failed = digtron.is_buildable_to(digtron_id, rotated_layout, root_pos, player_name) + local permitted, succeeded, failed = is_buildable_to(digtron_id, rotated_layout, root_pos, player_name) if permitted then - local removed = digtron.remove_from_world(digtron_id, player_name) - digtron.build_to_world(digtron_id, rotated_layout, root_pos, player_name) + local removed = remove_from_world(digtron_id, player_name) + build_to_world(digtron_id, rotated_layout, root_pos, player_name) minetest.sound_play("digtron_hydraulic", {gain = 0.5, pos=dest_pos}) persist_layout(digtron_id, rotated_layout) -- Don't need to do fancy callback checking for digtron nodes since I made all those @@ -947,7 +954,7 @@ local insert_or_eject = function(digtron_id, item_list, pos) end end -digtron.execute_cycle = function(digtron_id, player_name) +local execute_cycle = function(digtron_id, player_name) local old_root_pos = retrieve_pos(digtron_id) local root_node = minetest.get_node(old_root_pos) local root_facedir = root_node.param2 @@ -1005,7 +1012,7 @@ end -- If the digtron node has an assigned ID and a layout for that ID exists and -- a matching node exists in the layout then don't let it be dug. -- TODO: add protection check? -digtron.can_dig = function(pos, digger) +local can_dig = function(pos, digger) local meta = minetest.get_meta(pos) local digtron_id = meta:get_string("digtron_id") if digtron_id == "" then @@ -1025,7 +1032,7 @@ digtron.can_dig = function(pos, digger) minetest.log("error", "[Digtron] can_dig was called on a " .. node.name .. " at location " .. minetest.pos_to_string(pos) .. " that claimed to belong to " .. digtron_id .. ". However, layout and/or location data are missing: " .. missing) - -- May be better to do this to prevent node duplication. But we're already in bug land here so tread gently. + -- TODO May be better to do this to prevent node duplication. But we're already in bug land here so tread gently. --minetest.remove_node(pos) --return false return true @@ -1053,7 +1060,7 @@ end -- put this on all Digtron nodes. If other inventory types are added (eg, batteries) -- update this. -digtron.on_blast = function(pos, intensity) +local on_blast = function(pos, intensity) if intensity < 1.0 then return end -- The Almighty Digtron ignores weak-ass explosions local meta = minetest.get_meta(pos) @@ -1079,7 +1086,7 @@ end -- Use this inside other on_rightclicks for configuring Digtron nodes, this -- overrides if you're right-clicking with another Digtron node and assumes -- that you're trying to build it. -digtron.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) +local on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) local item_def = itemstack:get_definition() if item_def.type == "node" and minetest.get_item_group(itemstack:get_name(), "digtron") > 0 then local returnstack, success = minetest.item_place_node(itemstack, clicker, pointed_thing) @@ -1115,3 +1122,29 @@ if minetest.get_modpath("creative") then end end end + + + +--------------------------------------------------------------------------------------------------------------------------- +-- External API + +-- node definition methods +digtron.can_dig = can_dig +digtron.on_blast = on_blast +digtron.on_rightclick = on_rightclick + +digtron.get_name = get_name +digtron.set_name = set_name +digtron.get_pos = retrieve_pos +digtron.get_bounding_box = retrieve_bounding_box + +digtron.retrieve_inventory = retrieve_inventory -- used by formspecs + +digtron.assemble = assemble +digtron.disassemble = disassemble +digtron.remove_from_world = remove_from_world +digtron.is_buildable_to = is_buildable_to +digtron.build_to_world = build_to_world +digtron.move = move +digtron.rotate = rotate +digtron.execute_cycle = execute_cycle \ No newline at end of file diff --git a/init.lua b/init.lua index 3415d18..c46c5af 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,21 @@ digtron = {} digtron.doc = {} -- TODO: move to doc file +-- A global dictionary is used here so that other substitutions can be added easily by other mods, if necessary +digtron.builder_read_item_substitutions = { + ["default:torch_ceiling"] = "default:torch", + ["default:torch_wall"] = "default:torch", + ["default:dirt_with_grass"] = "default:dirt", + ["default:dirt_with_grass_footsteps"] = "default:dirt", + ["default:dirt_with_dry_grass"] = "default:dirt", + ["default:dirt_with_rainforest_litter"] = "default:dirt", + ["default:dirt_with_snow"] = "default:dirt", + ["default:furnace_active"] = "default:furnace", + ["farming:soil"] = "default:dirt", + ["farming:soil_wet"] = "default:dirt", + ["farming:desert_sand_soil"] = "default:desert_sand", + ["farming:desert_sand_soil_wet"] = "default:desert_sand", +} -- Sometimes we want builder heads to call an item's "on_place" method, other times we -- don't want them to. There's no way to tell which situation is best programmatically diff --git a/nodes/node_builder.lua b/nodes/node_builder.lua index e6ba720..2962aa2 100644 --- a/nodes/node_builder.lua +++ b/nodes/node_builder.lua @@ -23,17 +23,21 @@ local get_formspec = function(pos) "listcolors[#00000069;#5A5A5A00;#141318;#30434C;#FFF]" .. "list[detached:digtron:builder_item;main;0,0;1,1;]" .. "field[1.3,0.8;1,0.1;extrusion;" .. S("Extrusion") .. ";" ..extrusion .. "]" .. + "field_close_on_enter[extrusion;false]" .. "tooltip[extrusion;" .. S("Builder will extrude this many blocks in the direction it is facing.\nCan be set from 1 to @1.\nNote that Digtron won't build into unloaded map regions.", digtron.config.maximum_extrusion) .. "]" .. "field[2.3,0.8;1,0.1;period;" .. S("Periodicity") .. ";".. period .. "]" .. + "field_close_on_enter[period;false]" .. "tooltip[period;" .. S("Builder will build once every n steps.\nThese steps are globally aligned, so all builders with the\nsame period and offset will build on the same location.") .. "]" .. "field[3.3,0.8;1,0.1;offset;" .. S("Offset") .. ";" .. offset .. "]" .. + "field_close_on_enter[offset;false]" .. "tooltip[offset;" .. S("Offsets the start of periodicity counting by this amount.\nFor example, a builder with period 2 and offset 0 builds\nevery even-numbered block and one with period 2 and\noffset 1 builds every odd-numbered block.") .. "]" .. "button[4.0,0.5;1,0.1;set;" .. S("Save &\nShow") .. "]" .. - "tooltip[set;" .. S("Saves settings") .. "]" .. + "tooltip[set;" .. S("Saves settings, closes interface, and shows the locations this builder will build to in-world.") .. "]" .. "field[5.3,0.8;1,0.1;facing;" .. S("Facing") .. ";" .. facing .. "]" .. + "field_close_on_enter[facing;false]" .. "tooltip[facing;" .. S("Value from 0-23. Not all block types make use of this.\nUse the 'Read & Save' button to copy the facing of the block\ncurrently in the builder output location.") .. "]" .. - "button[6.0,0.5;1,0.1;read;" .. S("Read &\nSave") .. "]" .. - "tooltip[read;" .. S("Reads the facing of the block currently in the build location,\nthen saves all settings.") .. "]" .. + "button[6.0,0.5;1,0.1;read;" .. S("Read") .. "]" .. + "tooltip[read;" .. S("Reads the facing of the block currently in the build location.") .. "]" .. "list[current_player;main;0,1.3;8,1;]" .. default.get_hotbar_bg(0,1.3) .. "list[current_player;main;0,2.5;8,3;8]" .. @@ -44,6 +48,19 @@ end ---------------------------------------------------------------------- -- Detached inventory for setting the builder item +local is_item_allowed = function(item) + -- Ignore unknown items + if minetest.registered_items[item] == nil then return false end + + local stack_def = minetest.registered_nodes[item] + if not stack_def and not digtron.whitelisted_on_place(item) then + return false -- don't allow craft items unless their on_place is whitelisted. + end + + return true +end + + local inv = minetest.create_detached_inventory("digtron:builder_item", { allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) return 0 @@ -52,9 +69,10 @@ local inv = minetest.create_detached_inventory("digtron:builder_item", { -- Always disallow put, but use this to read what the player *tried* adding and set the builder appropriately local item = stack:get_name() - -- Ignore unknown items - if minetest.registered_items[item] == nil then return 0 end - + if not is_item_allowed(item) then + return 0 + end + local player_name = player:get_player_name() local pos = player_interacting_with_builder_pos[player_name] if pos == nil then @@ -78,11 +96,6 @@ local inv = minetest.create_detached_inventory("digtron:builder_item", { return 0 end - local stack_def = minetest.registered_nodes[item] - if not stack_def and not digtron.whitelisted_on_place(item) then - return 0 -- don't allow craft items unless their on_place is whitelisted. - end - -- If we're adding a wallmounted item and the build facing is greater than 5, reset it to 0 if stack_def ~= nil and stack_def.paramtype2 == "wallmounted" and tonumber(meta:get_int("facing")) > 5 then meta:set_int("facing", 0) @@ -97,12 +110,6 @@ local inv = minetest.create_detached_inventory("digtron:builder_item", { allow_take = function(inv, listname, index, stack, player) return 0 end, --- on_move = function(inv, from_list, from_index, to_list, to_index, count, player) --- end, --- on_take = function(inv, listname, index, stack, player) --- end, --- on_put = function(inv, listname, index, stack, player) --- end }) inv:set_size("main", 1) @@ -142,30 +149,31 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields) .. " no position was recorded.") return end - + local meta = minetest.get_meta(pos) - local period = tonumber(fields.period) - local offset = tonumber(fields.offset) - local facing = tonumber(fields.facing) - local extrusion = tonumber(fields.extrusion) local item = meta:get_string("item") + local period = tonumber(fields.period) if period and period > 0 then meta:set_int("period", math.floor(period)) else period = meta:get_int("period") end + + local offset = tonumber(fields.offset) if offset then meta:set_int("offset", math.floor(offset)) else offset = meta:get_int("offset") end + + local facing = tonumber(fields.facing) if facing and facing >= 0 and facing < 24 then local target_item = ItemStack(item) if target_item:get_definition().paramtype2 == "wallmounted" then if facing < 6 then - meta:set_int("facing", facing) + meta:set_int("facing", math.floor(facing)) -- wallmounted facings only run from 0-5 end else @@ -175,27 +183,32 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields) facing = meta:get_int("facing") end + local extrusion = tonumber(fields.extrusion) if extrusion and extrusion > 0 and extrusion <= digtron.config.maximum_extrusion then meta:set_int("extrusion", math.floor(extrusion)) else extrusion = meta:get_int("extrusion") end --- if fields.set then --- digtron.show_offset_markers(pos, offset, period) --- --- elseif fields.read then --- local facing = minetest.get_node(pos).param2 --- local buildpos = digtron.find_new_pos(pos, facing) --- local target_node = minetest.get_node(buildpos) --- if target_node.name ~= "air" and minetest.get_item_group(target_node.name, "digtron") == 0 then --- local meta = minetest.get_meta(pos) --- local inv = meta:get_inventory() --- local target_name = digtron.builder_read_item_substitutions[target_node.name] or target_node.name --- inv:set_stack("main", 1, target_name) --- meta:set_int("facing", target_node.param2) --- end --- end + if fields.set then + --digtron.show_offset_markers(pos, offset, period) + end + + if fields.read then + local builder_facing = minetest.get_node(pos).param2 + local buildpos = vector.add(minetest.facedir_to_dir(builder_facing), pos) + local target_node = minetest.get_node(buildpos) + local target_name = target_node.name + if digtron.builder_read_item_substitutions[target_name] then + target_name = digtron.builder_read_item_substitutions[target_name] + end + if target_name ~= "air" and is_item_allowed(target_name) then + local meta = minetest.get_meta(pos) + item = target_name + meta:set_string("item", item) + meta:set_int("facing", target_node.param2) + end + end if fields.help then minetest.after(0.5, doc.show_entry, sender:get_player_name(), "nodes", "digtron:builder", true) @@ -208,8 +221,9 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields) end meta:set_string("infotext", S("Builder for @1\nperiod @2, offset @3, extrusion @4", item_desc, period, offset, extrusion)) - digtron.update_builder_item(pos) + minetest.show_formspec(player_name, "digtron:builder", get_formspec(pos)) + end)