diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..7e50163 --- /dev/null +++ b/config.lua @@ -0,0 +1,69 @@ +local CONFIG_FILE_PREFIX = "digtron_" + +digtron.config = {} + +local print_settingtypes = false + +local function setting(stype, name, default, description) + local value + if stype == "bool" then + value = minetest.settings:get_bool(CONFIG_FILE_PREFIX..name) + elseif stype == "string" then + value = minetest.settings:get(CONFIG_FILE_PREFIX..name) + elseif stype == "int" or stype == "float" then + value = tonumber(minetest.settings:get(CONFIG_FILE_PREFIX..name)) + end + if value == nil then + value = default + end + digtron.config[name] = value + + if print_settingtypes then + minetest.debug(CONFIG_FILE_PREFIX..name.." ("..description..") "..stype.." "..tostring(default)) + end +end + +setting("bool", "uses_resources", true, "Digtron uses resources when active") +setting("bool", "lava_impassible", true, "Lava counts as a protected node") +setting("bool", "damage_creatures", true, "Diggers damage creatures") -- TODO: legacy setting, remove eventually +setting("int", "damage_hp", 8, "Damage diggers do") +setting("int", "size_limit", 1000, "Digtron size limit in nodes per moving digtron") + +if digtron.config.damage_creatures == false then digtron.config.damage_hp = 0 end -- TODO: remove when damage_creatures is removed + +-- Enables the spray of particles out the back of a digger head and puffs of smoke from the controller +local particle_effects = minetest.settings:get_bool("enable_particles") +digtron.config.particle_effects = particle_effects or particle_effects == nil -- default true + + +setting("int", "maximum_extrusion", 25, "Maximum builder extrusion distance") +setting("float", "cycle_time", 1.0, "Minimum Digtron cycle time") +setting("float", "traction_factor", 3.0, "Traction factor") + +-- fuel costs. For comparison, in the default game: +-- one default tree block is 30 units +-- one coal lump is 40 units +-- one coal block is 370 units (apparently it's slightly more productive making your coal lumps into blocks before burning) +-- one book is 3 units + +-- how much fuel is required to dig a node if not in one of the following groups. +setting("float", "dig_cost_default", 0.5, "Default dig cost") +-- eg, stone +setting("float", "dig_cost_cracky", 1.0, "Cracky dig cost") +-- eg, dirt, sand +setting("float", "dig_cost_crumbly", 0.5, "Crumbly dig cost") +-- eg, wood +setting("float", "dig_cost_choppy", 0.75, "Choppy dig cost") +-- how much fuel is required to build a node +setting("float", "build_cost", 1.0, "Build cost") + +-- How much charge (an RE battery holds 10000 EU) is equivalent to 1 unit of heat produced by burning coal +-- With 100, the battery is 2.5 better than a coal lump, yet 3.7 less powerful than a coal block +-- Being rechargeable should pay off for this "average" performance. +setting("int", "power_ratio", 100, "The electrical charge to 1 coal heat unit conversion ratio") + + +setting("float", "marker_crate_good_duration", 3.0, "Duration that 'good' crate markers last") +setting("float", "marker_crate_bad_duration", 9.0, "Duration that 'bad' crate markers last") + +setting("bool", "emerge_unloaded_mapblocks", true, "When Digtron encounters unloaded map blocks, emerge them.") diff --git a/controller.lua b/controller.lua index f8b8e14..575fead 100644 --- a/controller.lua +++ b/controller.lua @@ -263,6 +263,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local products, nodes_to_dig, cost = digtron.predict_dig(digtron_id, player_name) minetest.chat_send_all("products: " .. dump(products)) minetest.chat_send_all("positions: " .. dump(nodes_to_dig)) + minetest.chat_send_all("cost: " .. cost) end --TODO: this isn't recording the field when using ESC to exit the formspec diff --git a/functions.lua b/functions.lua index ed165e6..8870859 100644 --- a/functions.lua +++ b/functions.lua @@ -573,7 +573,7 @@ digtron.remove_from_world = function(digtron_id, player_name) local root_hash = minetest.hash_node_position(root_pos) local nodes_to_destroy = {} for hash, data in pairs(layout) do - local node_pos, node, node_meta = get_valid_data(digtron_id, root_hash, hash, data, "digtron.destroy") + local node_pos = get_valid_data(digtron_id, root_hash, hash, data, "digtron.destroy") if node_pos then table.insert(nodes_to_destroy, node_pos) end @@ -607,12 +607,17 @@ digtron.is_buildable_to = function(digtron_id, root_pos, player_name, ignore_nod local permitted = true for layout_hash, data in pairs(layout) do + -- Don't use get_valid_data, the Digtron isn't in-world yet local node_hash = layout_hash + root_hash local node_pos = minetest.get_position_from_hash(node_hash) local node = minetest.get_node(node_pos) local node_def = minetest.registered_nodes[node.name] -- TODO: lots of testing needed here - if not ((node_def and node_def.buildable_to) or old_hashes[node_hash]) then + if not ( + (node_def and node_def.buildable_to) + or old_hashes[node_hash]) or + minetest.is_protected(target_pos, player_name) + then if return_immediately_on_failure then return false -- no need to test further, don't return node positions else @@ -633,6 +638,7 @@ digtron.build_to_world = function(digtron_id, root_pos, player_name) local root_hash = minetest.hash_node_position(root_pos) for hash, data in pairs(layout) do + -- Don't use get_valid_data, the Digtron isn't in-world yet local node_pos = minetest.get_position_from_hash(hash + root_hash) minetest.set_node(node_pos, data.node) local meta = minetest.get_meta(node_pos) @@ -680,7 +686,9 @@ digtron.predict_dig = function(digtron_id, player_name) local target_name = target_node.name local targetdef = minetest.registered_nodes[target_name] --TODO periodicity/offset test - if minetest.get_item_group(target_name, "digtron") == 0 and + if + target_name ~= "air" and -- TODO: generalise this somehow for liquids and other undiggables + minetest.get_item_group(target_name, "digtron") == 0 and minetest.get_item_group(target_name, "digtron_protected") == 0 and minetest.get_item_group(target_name, "immortal") == 0 and ( @@ -689,26 +697,27 @@ digtron.predict_dig = function(digtron_id, player_name) targetdef.can_dig(target_pos, minetest.get_player_by_name(player_name)) ) and not minetest.is_protected(target_pos, player_name) - then - - -- TODO: move this into some kind of shared definition - --if digtron.config.uses_resources then - -- if minetest.get_item_group(target.name, "cracky") ~= 0 then - -- in_known_group = true - -- material_cost = math.max(material_cost, digtron.config.dig_cost_cracky) - -- end - -- if minetest.get_item_group(target.name, "crumbly") ~= 0 then - -- in_known_group = true - -- material_cost = math.max(material_cost, digtron.config.dig_cost_crumbly) - -- end - -- if minetest.get_item_group(target.name, "choppy") ~= 0 then - -- in_known_group = true - -- material_cost = math.max(material_cost, digtron.config.dig_cost_choppy) - -- end - -- if not in_known_group then - -- material_cost = digtron.config.dig_cost_default - -- end - --end + then + local material_cost = 0 + if digtron.config.uses_resources then + local in_known_group = false + if minetest.get_item_group(target_name, "cracky") ~= 0 then + in_known_group = true + material_cost = math.max(material_cost, digtron.config.dig_cost_cracky) + end + if minetest.get_item_group(target_name, "crumbly") ~= 0 then + in_known_group = true + material_cost = math.max(material_cost, digtron.config.dig_cost_crumbly) + end + if minetest.get_item_group(target_name, "choppy") ~= 0 then + in_known_group = true + material_cost = math.max(material_cost, digtron.config.dig_cost_choppy) + end + if not in_known_group then + material_cost = digtron.config.dig_cost_default + end + end + cost = cost + material_cost local drops = minetest.get_node_drops(target_name, "") for _, drop in ipairs(drops) do @@ -804,32 +813,25 @@ end ------------------------------------------------------------------------------------ -- Creative trash --- This is wrapped in an after() call as a workaround for to https://github.com/minetest/minetest/issues/8827 +-- Catch when someone throws a Digtron controller with an ID into the trash, dispose +-- of the persisted layout. if minetest.get_modpath("creative") then - minetest.after(1, function() - if minetest.get_inventory({type="detached", name="creative_trash"}) then - if minetest.remove_detached_inventory("creative_trash") then - -- Create the trash field - local trash = minetest.create_detached_inventory("creative_trash", { - -- Allow the stack to be placed and remove it in on_put() - -- This allows the creative inventory to restore the stack - allow_put = function(inv, listname, index, stack, player) - return stack:get_count() - end, - on_put = function(inv, listname, index, stack, player) - local stack = inv:get_stack(listname, index) - local stack_meta = stack:get_meta() - local digtron_id = stack_meta:get_string("digtron_id") - if digtron_id ~= "" then - minetest.log("action", player:get_player_name() .. " disposed of " .. digtron_id - .. " in the creative inventory's trash receptacle.") - dispose_id(digtron_id) - end - inv:set_list(listname, {}) - end, - }) - trash:set_size("main", 1) + local trash = minetest.detached_inventories["creative_trash"] + if trash then + local old_on_put = trash.on_put + if old_on_put then + local digtron_on_put = function(inv, listname, index, stack, player) + local stack = inv:get_stack(listname, index) + local stack_meta = stack:get_meta() + local digtron_id = stack_meta:get_string("digtron_id") + if stack:get_name() == "digtron:controller" and digtron_id ~= "" then + minetest.log("action", player:get_player_name() .. " disposed of " .. digtron_id + .. " in the creative inventory's trash receptacle.") + dispose_id(digtron_id) + end + return old_on_put(inv, listname, index, stack, player) end + trash.on_put = digtron_on_put end - end) + end end diff --git a/init.lua b/init.lua index 2968f62..96cecdb 100644 --- a/init.lua +++ b/init.lua @@ -1,13 +1,9 @@ digtron = {} -digtron.doc = {} - -digtron.config = {} - -digtron.config.marker_crate_bad_duration = 5 -digtron.config.marker_crate_good_duration = 5 +digtron.doc = {} -- TODO: move to doc file local modpath = minetest.get_modpath(minetest.get_current_modname()) +dofile(modpath.."/config.lua") dofile(modpath.."/entities.lua") dofile(modpath.."/functions.lua") dofile(modpath.."/controller.lua") diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..1e351e6 --- /dev/null +++ b/mod.conf @@ -0,0 +1,9 @@ +name = digtron +title = Digtron +author = FaceDeer +description = Adds components for building modular tunnel boring machines +license = MIT, LGPL 2.1 or later +forum = https://forum.minetest.net/viewtopic.php?t=16295 +version = 2.0 +depends = default +optional_depends = intllib, creative \ No newline at end of file diff --git a/settingtypes.txt b/settingtypes.txt new file mode 100644 index 0000000..49d8344 --- /dev/null +++ b/settingtypes.txt @@ -0,0 +1,51 @@ +#This can cause digtrons to operate without consuming fuel or building materials, +#though they still check whether they have enough in inventory. +#It's a separate setting from regular creative mode. +digtron_uses_resources (Digtron uses resources) bool true + +#When true, lava counts as protected blocks. +digtron_lava_impassible (Lava is impassible to Digtrons) bool true + +#Sets how much HP damage a digger does. Soft material diggers do half this. +#Set to 0 to disable damage entirely. +digtron_damage_hp (Diggers damage this many hp) int 8 + +#How many seconds a digtron waits between cycles. +#Auto-controllers can make this wait longer, but cannot make it shorter. +digtron_cycle_time (Minimum Digtron cycle time in seconds) float 1.0 0.0 60.0 + +#How many Digtron blocks can be moved for each adjacent +#solid block that the Digtron has traction against +digtron_traction_factor (Digtron traction factor) float 3.0 0.0 1000.0 + +#The maximum extrusion setting permitted for a Digtron builder module. +digtron_maximum_extrusion (Digtron maximum extrusion) int 25 1 100 + +digtron_marker_crate_good_duration (Duration that 'good' crate markers last) float 3.0 0.0 100.0 +digtron_marker_crate_bad_duration (Duration that 'bad' crate markers last) float 9.0 0.0 100.0 + +#When a Digtron encounters unloaded map blocks, cause them to load +#so that the Digtron can continue moving. +digtron_emerge_unloaded_mapblocks (Emerge unloaded map blocks) bool true + +[Fuel costs] + +#eg, stone. +#In a default Minetest game one lump of coal provides 40.0 units of fuel. +digtron_dig_cost_cracky (Fuel cost for digging cracky blocks) float 1.0 0.0 100.0 +# eg, dirt, sand. +#In a default Minetest game one lump of coal provides 40.0 units of fuel. +digtron_dig_cost_crumbly (Fuel cost for digging crumbly blocks) float 0.5 0.0 100.0 +#eg, wood. +#In a default Minetest game one lump of coal provides 40.0 units of fuel. +digtron_dig_cost_choppy (Fuel cost for digging choppy blocks) float 0.75 0.0 100.0 +#Fuel cost to dig a block that doesn't fall into one of the other categories. +#In a default Minetest game one lump of coal provides 40.0 units of fuel. +digtron_dig_cost_default (Fuel cost for digging other block types) float 0.5 0.0 100.0 +#How much fuel is required to build a block +digtron_build_cost (Fuel cost to build one block) float 1.0 0.0 100.0 + +#If the [technic] mod is installed Digtron can draw power from technic batteries. +#A full battery holds 10000 electrical units. This is divided by the power ratio +#setting to convert it into fuel units. +digtron_power_ratio (Electrical charge to coal heat conversion ratio) int 1 1000 100