From 2695c6103383996fedfd12098cf3f28c5fc43fe2 Mon Sep 17 00:00:00 2001 From: FaceDeer Date: Fri, 30 Dec 2016 23:38:18 -0700 Subject: [PATCH] Initial commit Initial commit. Contains digger head, sand digger, builder, controller, pusher, structure node, light, inventory, and digtron core crafting item. --- LICENSE.txt | 33 ++++ README.txt | 156 ++++++++++++++++ depends.txt | 1 + init.lua | 22 +++ node_builders.lua | 185 +++++++++++++++++++ node_controllers.lua | 317 +++++++++++++++++++++++++++++++++ node_diggers.lua | 147 +++++++++++++++ node_misc.lua | 79 ++++++++ pointset.lua | 73 ++++++++ recipes.lua | 115 ++++++++++++ sounds/buzzer.ogg | Bin 0 -> 12346 bytes sounds/construction.ogg | Bin 0 -> 20200 bytes sounds/dingding.ogg | Bin 0 -> 23005 bytes sounds/honk.ogg | Bin 0 -> 7224 bytes sounds/license.txt | 99 ++++++++++ sounds/squeal.ogg | Bin 0 -> 14246 bytes sounds/truck.ogg | Bin 0 -> 12542 bytes textures/digtron_builder.png | Bin 0 -> 741 bytes textures/digtron_control.png | Bin 0 -> 798 bytes textures/digtron_core.png | Bin 0 -> 789 bytes textures/digtron_digger.png | Bin 0 -> 2797 bytes textures/digtron_inventory.png | Bin 0 -> 752 bytes textures/digtron_light.png | Bin 0 -> 796 bytes textures/digtron_motor.png | Bin 0 -> 793 bytes textures/digtron_plate.png | Bin 0 -> 690 bytes util.lua | 312 ++++++++++++++++++++++++++++++++ util_item_place_node.lua | 138 ++++++++++++++ 27 files changed, 1677 insertions(+) create mode 100644 LICENSE.txt create mode 100644 README.txt create mode 100644 depends.txt create mode 100644 init.lua create mode 100644 node_builders.lua create mode 100644 node_controllers.lua create mode 100644 node_diggers.lua create mode 100644 node_misc.lua create mode 100644 pointset.lua create mode 100644 recipes.lua create mode 100644 sounds/buzzer.ogg create mode 100644 sounds/construction.ogg create mode 100644 sounds/dingding.ogg create mode 100644 sounds/honk.ogg create mode 100644 sounds/license.txt create mode 100644 sounds/squeal.ogg create mode 100644 sounds/truck.ogg create mode 100644 textures/digtron_builder.png create mode 100644 textures/digtron_control.png create mode 100644 textures/digtron_core.png create mode 100644 textures/digtron_digger.png create mode 100644 textures/digtron_inventory.png create mode 100644 textures/digtron_light.png create mode 100644 textures/digtron_motor.png create mode 100644 textures/digtron_plate.png create mode 100644 util.lua create mode 100644 util_item_place_node.lua diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..f85a59e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,33 @@ +Modular Tunnel Boring Machine: +The Almighty Digtron +==================== + +All source code aside from the contents of util_item_place_node.lua and all art are by FaceDeer. + +util_item_place_node.lua is derived from default mod code under the LGPL 2.1, see header of that file for details. + +Sounds are under various licenses, see the license.txt file in the /sounds directory for details. + +License for Code +---------------- + +Copyright (C) 2016 FaceDeer + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +License for Textures +--------------------------------------- + +CC-BY-SA 3.0 UNPORTED. Created by FaceDeer diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..bef8e2b --- /dev/null +++ b/README.txt @@ -0,0 +1,156 @@ + Modular Tunnel Boring Machine, aka + The Almighty Digtron + ==================== + +This mod contains a set of nodes that can be used to construct highly customizable and modular tunnel-boring machines, bridge-builders, road-pavers, wall-o-matics, and other such construction/destruction contraptions. + +The basic nodes that can be assembled into a functioning digging machine are: + +* Digger heads, which excavate material in front of them when the machine is triggered +* Builder heads, which build a user-configured node in front of them +* Inventory modules, which hold material produced by the digger and provide material to the builders +* Control node, used to trigger the machine and move it in a particular direction. + +A digging machine's components must be connected to the control node via a path leading through the faces of the nodes - diagonal connections across edges and corners don't count. + +Important general concepts +-------------------------- + +Several general concepts are important when building more sophisticated diggers. + +* Facing - a number between 0-23 that determines which direction a node is facing and what orientation it has. Not all nodes make use of facing (basic blocks such as cobble or sand have no facing, for example) so it's not always necessary to set this when configuring a builder head. The facing of already-placed nodes can be altered through the use of the screwdriver tool. + +* Period - Builder and digger heads can be made periodic by changing the period value to something other than 1. This determines how frequently they trigger. A period of 1 triggers on every node, a period of 2 triggers once every second node, a period of 3 triggers once every third node, etc. These are useful when setting up a machine to place regularly-spaced features as it goes. For example, you could have a builder head that places a torch every 8 steps, or a digger node that punches a landing in the side of a vertical stairwell at every level. + +* Offset - The location at which a periodic module triggers is globally uniform. This is handy if you want to line up the nodes you're building (for example, placing pillars and a crosspiece every 4 nodes in a tunnel, or punching alcoves in a wall to place glass windows). If you wish to change how the pattern lines up, modify the "offset" setting. + +Note that offset and period are calculated from the location of the *controller* node, which is shared across the whole array of modules, so it's not necessary to line up all of your builder heads in the same row or column. + +* Shift-right-clicking - since most of the nodes of the digging machine have control screens associated with right-clicking, building additional nodes on top of them or rotating them with the screwdriver requires the shift key to be held down when right-clicking on them. + +Detailed module guide +===================== + +Control Module +-------------- + +Right-click on this module to make the digging machine go. The digging machine will go in the direction that the control module is oriented, so in theory you could adjust the digging machine's position by reoriented the control module (or building additional ones) and nudging it to the side. + +A control module can only trigger once per second. Gives you time to enjoy the scenery and smell the flowers (or their mulched remains, at any rate). + +If you're standing within the digging machine's volume, or in a node adjacent to it, you will be pulled along with the machine when it moves. + +Pusher Module +------------- + +Aka the "can you rebuild it six inches to the left" module. This is a much simplified control module that does not trigger the digger or builder heads when right-clicked, it only moves the digging machine. It's up to you to ensure there's space for it to move into. + +Digger Head +----------- + +Facing of a digger head is significant; it will excavate material from the node on the spinning grinder wheel face of the digger head. Generally speaking, you'll want these to face forward - though having them aimed to the sides can also be useful. + +Digger heads can have a period and offset defined if you want them to punch regularly-spaced holes. Note that diggers aimed forward should generally always have a period of 1, otherwise the digging machine may be unable to move. + +Sand Digger Head +---------------- + +This specialized digger head is designed to excavate only loose material such as sand or gravel. It has no period/offset settings; it will always attempt to dig sand when it's present in its target node. It leaves all other types of nodes alone. (in techinical terms, this digger digs nodes belonging to the "falling_node" group) + +The intended purpose of this digger is to be aimed at the ceiling or walls of a tunnel being dug, making spaces to allow shoring nodes to be inserted into unstable roofs but leaving the wall alone if it's composed of a more stable material. + +Builder Head +------------ + +A builder head is the most complex component of this system. It has period and offset properties, and also an inventory slot where you "program" it by placing an example of the node type that you want it to build. Only a single item is needed here, any additional items in this inventory stack will be shunted into the digger's general inventory (or ejected from the control node if there's no space for it). + +Builders also have a "facing" setting. If you haven't memorized the meaning of the 24 facing values yet, builder heads have a helpful "Read & Save" button to fill this value in for you. Simply build a temporary instance of the node in the output location in front of the builder, adjust it to the orientation you want using the screwdriver tool, and then when you click the "Read & Save" button the node's facing will be read and saved. + +Inventory Module +---------------- + +Inventory modules have the same capacity as a chest. They're used both for storing the products of the digger heads and as the source of materials used by the builder heads. A digging machine whose builder heads are laying down cobble can automatically self-replenish in this way, but note that an inventory module is still required as buffer space even if the digger heads produced everything needed by the builder heads in a given cycle. + +Inventory modules are not required for a digging-only machine. If there's not enough storage space to hold the materials produced by the digging heads, the excess material will be ejected out the back of the control node. They're handy for accumulating ores and other building materials, though. + +Digging machines can have multiple inventory modules added to expand their capacity. + +Structural Module +----------------- + +These nodes allow otherwise-disconnected sections of builder machines to be linked together. You can also use them to build a platform to stand on as you ride your mighty mechanical leviathan through the landscape. + +Digtron Lamp +------------ + +A light source that moves along with the digging machine. Convenient if you're digging a tunnel that you don't intend to outfit with torches or other permanent light fixtures. Not quite as bright as a torch since the protective lens tends to get grimy while burrowing through the earth. + +What Do These Noises Mean? +========================== + +When a digging machine is unable to complete a cycle it will make one of several noises to indicate what the problem is. + +Squealing traction wheels indicates a mobility problem. If the squealing is accompanied by a buzzer, the digging machine has encountered an obstruction it can't dig through. This could be a protected region (the digging machine has only the priviledges of the player triggering it), a chest containing items, or perhaps the digger was incorrectly designed and can't dug the correctly sized and shaped cavity for it to move forward into. There are many possibilities. + +Squealing traction wheels with no accompanying buzzer indicates that the digging machine has no solid adjacent nodes to push off of. Tunnel boring machines cannot fly or swim, not even through lava, and they don't dig fast enough to "catch sick air" when they emerge from a cliffside. If you wish to cross a chasm you'll need to ensure that there are builder heads placing a solid surface as you go. + +A ringing bell indicates that there are insufficient materials in inventory to supply all the builder heads for this cycle. + +A short high-pitched honk means that one or more of the builder heads don't have an item set. A common oversight, especially with large and elaborate digging machines, that might be hard to notice and annoying to fix if not noticed right away. + +Crafting recipes +================ + +All machine nodes are constructed from a "Digtron Core" craft item and other materials. + +Digtron cores are made with the following recipe: + + steel +steel mese fragment steel + steel + +Digger heads: + + diamond +diamond core diamond + diamond + +Sand/gravel digger heads: + + steel + steel core steel + steel + +Builder heads: + + mese fragment +mese fragment core mese fragment + mese fragment + +Controller heads: + + mese crystal + mese crystal core mese crystal + mese crystal + +Inventory modules: + + chest + core + +Structural modules: + +stick stick + core +stick stick + +Lantern module: + + torch + core + +Pusher controller: + + coal +coal core coal + coal diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/depends.txt @@ -0,0 +1 @@ +default diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..92e0a88 --- /dev/null +++ b/init.lua @@ -0,0 +1,22 @@ +dofile( minetest.get_modpath( "digtron" ) .. "/util.lua" ) +dofile( minetest.get_modpath( "digtron" ) .. "/pointset.lua" ) + +dofile( minetest.get_modpath( "digtron" ) .. "/node_misc.lua" ) -- contains inventory and structure nodes +dofile( minetest.get_modpath( "digtron" ) .. "/node_diggers.lua" ) -- contains all diggers +dofile( minetest.get_modpath( "digtron" ) .. "/node_builders.lua" ) -- contains all builders (there's just one currently) +dofile( minetest.get_modpath( "digtron" ) .. "/node_controllers.lua" ) -- controllers + +dofile( minetest.get_modpath( "digtron" ) .."/recipes.lua" ) + +digtron.refractory = 1.0 -- How long a digtron waits between cycles. + +-- digtron group numbers: +-- 1 - generic digtron node, nothing special is done with these. They're just dragged along. +-- 2 - inventory-holding digtron, has a "main" inventory that the digtron can add to and take from. +-- 3 - digger head, has an "execute_dig" method in its definition +-- 4 - builder head, has a "test_build" and "execute_build" method in its definition + + + + + diff --git a/node_builders.lua b/node_builders.lua new file mode 100644 index 0000000..b8218b7 --- /dev/null +++ b/node_builders.lua @@ -0,0 +1,185 @@ +-- Note: builders go in group 4 and have both test_build and execute_build methods. + +-- Builds objects in the targeted node. This is a complicated beastie. +minetest.register_node("digtron:builder", { + description = "Builder Unit", + groups = {cracky = 3, stone = 1, digtron = 4}, + drop = "digtron:builder", + paramtype2= 'facedir', + tiles = { + "digtron_plate.png^[transformR90", + "digtron_plate.png^[transformR270", + "digtron_plate.png", + "digtron_plate.png^[transformR180", + "digtron_builder.png", + "digtron_plate.png", + }, + + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = { + {-0.25, 0.3125, 0.3125, 0.25, 0.5, 0.5}, -- FrontFrame_top + {-0.25, -0.5, 0.3125, 0.25, -0.3125, 0.5}, -- FrontFrame_bottom + {0.3125, -0.25, 0.3125, 0.5, 0.25, 0.5}, -- FrontFrame_right + {-0.5, -0.25, 0.3125, -0.3125, 0.25, 0.5}, -- FrontFrame_left + {-0.5, 0.25, -0.5, -0.25, 0.5, 0.5}, -- edge_topright + {-0.5, -0.5, -0.5, -0.25, -0.25, 0.5}, -- edge_bottomright + {0.25, 0.25, -0.5, 0.5, 0.5, 0.5}, -- edge_topleft + {0.25, -0.5, -0.5, 0.5, -0.25, 0.5}, -- edge_bottomleft + {-0.25, 0.4375, -0.5, 0.25, 0.5, -0.4375}, -- backframe_top + {-0.25, -0.5, -0.5, 0.25, -0.4375, -0.4375}, -- backframe_bottom + {-0.5, -0.25, -0.5, -0.4375, 0.25, -0.4375}, -- backframe_left + {0.4375, -0.25, -0.5, 0.5, 0.25, -0.4375}, -- Backframe_right + {-0.0625, -0.3125, 0.3125, 0.0625, 0.3125, 0.375}, -- frontcross_vertical + {-0.3125, -0.0625, 0.3125, 0.3125, 0.0625, 0.375}, -- frontcross_horizontal + } + }, + + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_string("formspec", + "size[8,5.2]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "list[current_name;main;0.5,0;1,1;]" .. +-- "tooltip[main;Builder will build the type of node in this slot. Note that only one item needs to be placed here, to 'program' it. The builder will draw construction materials from the central inventory when building.]" .. + "label[0.5,0.8;Node to build]" .. + "field[2.5,0.8;1,0.1;period;Periodicity;${period}]" .. + "tooltip[period;Builder will build once every n steps. These steps are globally aligned, so all builders with the same period and offset will build on the same location.]" .. + "field[3.5,0.8;1,0.1;offset;Offset;${offset}]" .. + "tooltip[offset;Offsets the start of periodicity counting by this amount. For example, a builder with period 2 and offset 0 builds every even-numbered node and one with period 2 and offset 1 builds every odd-numbered node.]" .. + "button_exit[4.2,0.5;1,0.1;set;Save]" .. + "tooltip[set;Saves settings]" .. + "field[5.7,0.8;1,0.1;build_facing;Facing;${build_facing}]" .. + "tooltip[build_facing;Value from 0-23. Not all node types make use of this. Use the 'Read & Save' button to copy the facing of the node currently in the builder output location]" .. + "button_exit[6.4,0.5;1,0.1;read;Read &\nSave]" .. + "tooltip[read;Reads the facing of the node currently in the build location, then saves all settings]" .. + "list[current_player;main;0,1.3;8,1;]" .. + "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]" .. + "listring[current_player;main]" + ) + meta:set_string("period", 1) + meta:set_string("offset", 0) + meta:set_string("build_facing", 0) + + local inv = meta:get_inventory() + inv:set_size("main", 1) + end, + + on_receive_fields = function(pos, formname, fields, sender) + local meta = minetest.get_meta(pos) + local period = tonumber(fields.period) + local offset = tonumber(fields.offset) + if period and period > 0 then + meta:set_string("period", math.floor(tonumber(fields.period))) + end + if offset then + meta:set_string("offset", math.floor(tonumber(fields.offset))) + end + + if fields.read then + local meta = minetest.get_meta(pos) + local facing = minetest.get_node(pos).param2 + local buildpos = digtron.find_new_pos(pos, facing) + meta:set_string("build_facing", minetest.get_node(buildpos).param2) + else + local build_facing = tonumber(fields.build_facing) + if build_facing and build_facing >= 0 and build_facing < 24 then + meta:set_string("build_facing", math.floor(build_facing)) + end + end + end, + + -- "builder at pos, imagine that you're in test_pos. If you're willing and able to build from there, take the item you need from inventory. + -- return the item you took and the inventory location you took it from so it can be put back after all the other builders have been tested. + -- If you couldn't get the item from inventory, return an error code so we can abort the cycle. + -- If you're not supposed to build at all, or the location is obstructed, return 0 to let us know you're okay and we shouldn't abort." + test_build = function(pos, test_pos, inventory_positions, protected_nodes, nodes_dug, controlling_coordinate, controller_pos) + local meta = minetest.get_meta(pos) + local facing = minetest.get_node(pos).param2 + local buildpos = digtron.find_new_pos(test_pos, facing) + + if (buildpos[controlling_coordinate] + meta:get_string("offset")) % meta:get_string("period") ~= 0 then + --It's not the builder's turn to build right now. + return 0 + end + + if not digtron.can_move_to(buildpos, protected_nodes, nodes_dug) then + --using "can_move_to" instead of "can_build_to" test case in case the builder is pointed "backward", and will thus + --be building into the space that it's currently in and will be vacating after moving, or in case the builder is aimed + --sideways and a fellow digtron node was ahead of it (will also be moving out of the way). + + --If the player has built his digtron stupid (eg has another digtron node in the place the builder wants to build) this + --assumption is wrong, but I can't hold the player's hand through *every* possible bad design decision. Worst case, + --the digtron will think its inventory can't handle the next build step and abort the build when it actually could have + --managed one more cycle. That's not a bad outcome for a digtron array that was built stupidly to begin with. + --The player should be thanking me for all the error-checking I *do* do, really. + --Ungrateful wretch. + return 0 + end + + local inv = minetest.get_inventory({type="node", pos=pos}) + local item_stack = inv:get_stack("main", 1) + local count = item_stack:get_count() + if count ~= 0 then + if count > 1 then + -- player has put more than one item in the "program" slot. Wasteful. Move all the rest to the main inventory so it can be used. + item_stack:set_count(count - 1) + digtron.place_in_inventory(item_stack, inventory_positions, controller_pos) + item_stack:set_count(1) + inv:set_stack("main", 1, item_stack) + end + local source_location = digtron.take_from_inventory(item_stack:get_name(), inventory_positions) + if source_location ~= nil then + return {item=item_stack, location=source_location} + end + return 2 -- error code for "needed an item but couldn't get it from inventory" + else + return 1 -- error code for "this builder's item slot is unset" + end + end, + + execute_build = function(pos, player, inventory_positions, protected_nodes, nodes_dug, controlling_coordinate, controller_pos) + local meta = minetest.get_meta(pos) + local build_facing = meta:get_string("build_facing") + local facing = minetest.get_node(pos).param2 + local buildpos = digtron.find_new_pos(pos, facing) + + if (buildpos[controlling_coordinate] + meta:get_string("offset")) % meta:get_string("period") ~= 0 then + return nil + end + + if digtron.can_build_to(buildpos, protected_nodes, nodes_dug) then + local inv = minetest.get_inventory({type="node", pos=pos}) + local item_stack = inv:get_stack("main", 1) + local count = item_stack:get_count() + if not item_stack:is_empty() then + local sourcepos = digtron.take_from_inventory(item_stack:get_name(), inventory_positions) + if sourcepos == nil then + -- item not in inventory! Need to sound the angry buzzer to let the player know, so return false. + return false + end + local returned_stack, success = digtron.item_place_node(item_stack, player, buildpos, tonumber(build_facing)) + if success == true then + --flag this node as *not* to be dug. + nodes_dug:set(buildpos.x, buildpos.y, buildpos.z, false) + else + --failed to build for some unknown reason. Put the item back in inventory. + digtron.place_in_specific_inventory(item_stack, sourcepos, inventory_positions, controller_pos) + end + end + end + return true -- no errors were encountered that we should notify the player about + end, + + can_dig = function(pos,player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:is_empty("main") + end, +}) \ No newline at end of file diff --git a/node_controllers.lua b/node_controllers.lua new file mode 100644 index 0000000..f8b0b6b --- /dev/null +++ b/node_controllers.lua @@ -0,0 +1,317 @@ +local controller_nodebox ={ + {-0.3125, -0.3125, -0.3125, 0.3125, 0.3125, 0.3125}, -- Core + {-0.1875, 0.3125, -0.1875, 0.1875, 0.5, 0.1875}, -- +y_connector + {-0.1875, -0.5, -0.1875, 0.1875, -0.3125, 0.1875}, -- -y_Connector + {0.3125, -0.1875, -0.1875, 0.5, 0.1875, 0.1875}, -- +x_connector + {-0.5, -0.1875, -0.1875, -0.3125, 0.1875, 0.1875}, -- -x_connector + {-0.1875, -0.1875, 0.3125, 0.1875, 0.1875, 0.5}, -- +z_connector + {-0.5, 0.125, -0.5, -0.125, 0.5, -0.3125}, -- back_connector_3 + {0.125, 0.125, -0.5, 0.5, 0.5, -0.3125}, -- back_connector_1 + {0.125, -0.5, -0.5, 0.5, -0.125, -0.3125}, -- back_connector_2 + {-0.5, -0.5, -0.5, -0.125, -0.125, -0.3125}, -- back_connector_4 +} + +-- Master controller. Most complicated part of the whole system. Determines which direction a digtron moves and triggers all of its component parts. +minetest.register_node("digtron:controller", { + description = "Digtron Control Unit", + groups = {cracky = 3, stone = 1, digtron = 1}, + drop = 'digtron:controller', + paramtype2= 'facedir', + -- Aims in the +Z direction by default + tiles = { + "digtron_plate.png^[transformR90", + "digtron_plate.png^[transformR270", + "digtron_plate.png", + "digtron_plate.png^[transformR180", + "digtron_plate.png", + "digtron_control.png", + }, + + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = controller_nodebox, + }, + + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) + if meta:get_string("waiting") == "true" then + -- Been too soon since last time the digtron did a cycle. + return + end + + local layout = digtron.get_all_digtron_neighbours(pos, clicker) + if layout.all == nil then + -- get_all_digtron_neighbours returns nil if the digtron array touches unloaded nodes, too dangerous to do anything in that situation. Abort. + minetest.sound_play("buzzer", {gain=0.5, pos=pos}) + return + end + + if layout.traction == false then + -- digtrons can't fly + minetest.sound_play("squeal", {gain=1.0, pos=pos}) + return + end + + local facing = minetest.get_node(pos).param2 + local controlling_coordinate = digtron.get_controlling_coordinate(pos, facing) + + ---------------------------------------------------------------------------------------------------------------------- + + local nodes_dug = Pointset.create() + local items_dropped = {} + + -- execute the execute_dig method on all digtron components that have one + -- This builds a set of nodes that will be dug and returns a list of products that will be generated + -- but doesn't actually dig the nodes yet. That comes later. + -- If we dug them now, sand would fall and some digtron nodes would die. + for k, location in pairs(layout.diggers) do + local target = minetest.get_node(location) + local targetdef = minetest.registered_nodes[target.name] + if targetdef.execute_dig ~= nil then + local dropped = targetdef.execute_dig(location, layout.protected, nodes_dug, controlling_coordinate) + if dropped ~= nil then + for _, itemname in pairs(dropped) do + table.insert(items_dropped, itemname) + end + end + else + minetest.log(string.format("%s has digger group but is missing execute_dig method! This is an error in mod programming, file a bug.", targetdef.name)) + end + end + + ---------------------------------------------------------------------------------------------------------------------- + + -- test if any digtrons are obstructed by non-digtron nodes that haven't been marked + -- as having been dug. + local can_move = true + for _, location in pairs(layout.all) do + local newpos = digtron.find_new_pos(location, facing) + if not digtron.can_move_to(newpos, layout.protected, nodes_dug) then + can_move = false + end + end + + if not can_move then + -- mark this node as waiting, will clear this flag in digtron.refractory seconds + minetest.get_meta(pos):set_string("waiting", "true") + minetest.after(digtron.refractory, + function (pos) + minetest.get_meta(pos):set_string("waiting", nil) + end, pos + ) + minetest.sound_play("squeal", {gain=1.0, pos=pos}) + minetest.sound_play("buzzer", {gain=0.5, pos=pos}) + return --Abort, don't dig and don't build. + end + + ---------------------------------------------------------------------------------------------------------------------- + + -- ask each builder node if it can get what it needs from inventory to build this cycle. + -- This is a complicated test because each builder needs to actually *take* the item it'll + -- need from inventory, and then we put it all back afterward. + local can_build = true + local test_build_return = nil + local test_items = {} + for k, location in pairs(layout.builders) do + local target = minetest.get_node(location) + local targetdef = minetest.registered_nodes[target.name] + local test_location = digtron.find_new_pos(location, facing) + if targetdef.test_build ~= nil then + test_build_return = targetdef.test_build(location, test_location, layout.inventories, layout.protected, nodes_dug, controlling_coordinate, layout.controller) + if test_build_return == 1 or test_build_return == 2 then + can_build = false + break + end + if test_build_return ~= 0 then + table.insert(test_items, test_build_return) + end + else + minetest.log(string.format("%s has builder group but is missing test_build method! This is an error in mod programming, file a bug.", targetdef.name)) + end + end + for k, item_return in pairs(test_items) do + --Put everything back where it came from + digtron.place_in_specific_inventory(item_return.item, item_return.location, layout.inventories, layout.controller) + end + + if not can_build then + minetest.get_meta(pos):set_string("waiting", "true") + minetest.after(digtron.refractory, + function (pos) + minetest.get_meta(pos):set_string("waiting", nil) + end, pos + ) + if test_build_return == 1 then + minetest.sound_play("honk", {gain=0.5, pos=pos}) -- A builder is not configured + elseif test_build_return == 2 then + minetest.sound_play("dingding", {gain=1.0, pos=pos}) -- Insufficient inventory + end + return --Abort, don't dig and don't build. + end + + ---------------------------------------------------------------------------------------------------------------------- + + -- All tests passed, ready to go for real! + minetest.sound_play("construction", {gain=1.0, pos=pos}) + + -- store or drop the products of the digger heads + for _, itemname in pairs(items_dropped) do + digtron.place_in_inventory(itemname, layout.inventories, pos) + end + + -- if the player is standing within the array or next to it, move him too. + local player_pos = clicker:getpos() + local move_player = false + if player_pos.x >= layout.extents.min_x - 1 and player_pos.x <= layout.extents.max_x + 1 and + player_pos.y >= layout.extents.min_y - 1 and player_pos.y <= layout.extents.max_y + 1 and + player_pos.z >= layout.extents.min_z - 1 and player_pos.z <= layout.extents.max_z + 1 then + move_player = true + end + + --move the array + digtron.move_digtron(facing, layout.all, layout.extents, nodes_dug) + local oldpos = {x=pos.x, y=pos.y, z=pos.z} + pos = digtron.find_new_pos(pos, facing) + if move_player then + clicker:moveto(digtron.find_new_pos(player_pos, facing), true) + end + + -- Start the delay before digtron can run again. Do this after moving the array or pos will be wrong. + minetest.get_meta(pos):set_string("waiting", "true") + minetest.after(digtron.refractory, + function (pos) + minetest.get_meta(pos):set_string("waiting", nil) + end, pos + ) + + -- execute_build on all digtron components that have one + for k, location in pairs(layout.builders) do + local target = minetest.get_node(location) + local targetdef = minetest.registered_nodes[target.name] + if targetdef.execute_build ~= nil then + --using the old location of the controller as fallback so that any leftovers land with the rest of the digger output. Not that there should be any. + can_build = targetdef.execute_build(location, clicker, layout.inventories, layout.protected, nodes_dug, controlling_coordinate, oldpos) + else + minetest.log(string.format("%s has builder group but is missing execute_build method! This is an error in mod programming, file a bug.", targetdef.name)) + end + end + if can_build == false then + -- We weren't able to detect this build failure ahead of time, so make a big noise now. This is strange, shouldn't happen often. + minetest.sound_play("dingding", {gain=1.0, pos=pos}) + minetest.sound_play("buzzer", {gain=0.5, pos=pos}) + end + + -- finally, dig out any nodes remaining to be dug. Some of these will have had their flag revoked because + -- a builder put something there or because they're another digtron node. + local node_to_dig, whether_to_dig = nodes_dug:pop() + while node_to_dig ~= nil do + if whether_to_dig == true then + minetest.remove_node(node_to_dig) + end + node_to_dig, whether_to_dig = nodes_dug:pop() + end + end, +}) + +-- A much simplified control unit that only moves the digtron, and doesn't trigger the diggers or builders. +-- Handy for shoving a digtron to the side if it's been built a bit off. +minetest.register_node("digtron:pusher", { + description = "Digtron Pusher Unit", + groups = {cracky = 3, stone = 1, digtron = 1}, + drop = 'digtron:pusher', + paramtype2= 'facedir', + -- Aims in the +Z direction by default + tiles = { + "digtron_plate.png^[transformR90^[colorize:#00880030", + "digtron_plate.png^[transformR270^[colorize:#00880030", + "digtron_plate.png^[colorize:#00880030", + "digtron_plate.png^[transformR180^[colorize:#00880030", + "digtron_plate.png^[colorize:#00880030", + "digtron_control.png^[colorize:#00880030", + }, + + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = controller_nodebox, + }, + + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) + if meta:get_string("waiting") == "true" then + -- Been too soon since last time the digtron did a cycle. + return + end + + local layout = digtron.get_all_digtron_neighbours(pos, clicker) + if layout.all == nil then + -- get_all_digtron_neighbours returns nil if the digtron array touches unloaded nodes, too dangerous to do anything in that situation. Abort. + minetest.sound_play("buzzer", {gain=0.5, pos=pos}) + return + end + + if layout.traction == false then + -- digtrons can't fly + minetest.sound_play("squeal", {gain=1.0, pos=pos}) + return + end + + local facing = minetest.get_node(pos).param2 + local controlling_coordinate = digtron.get_controlling_coordinate(pos, facing) + + local nodes_dug = Pointset.create() -- empty set, we're not digging anything + + -- test if any digtrons are obstructed by non-digtron nodes that haven't been marked + -- as having been dug. + local can_move = true + for _, location in pairs(layout.all) do + local newpos = digtron.find_new_pos(location, facing) + if not digtron.can_move_to(newpos, layout.protected, nodes_dug) then + can_move = false + end + end + + if not can_move then + -- mark this node as waiting, will clear this flag in digtron.refractory seconds + minetest.get_meta(pos):set_string("waiting", "true") + minetest.after(digtron.refractory, + function (pos) + minetest.get_meta(pos):set_string("waiting", nil) + end, pos + ) + minetest.sound_play("squeal", {gain=1.0, pos=pos}) + minetest.sound_play("buzzer", {gain=0.5, pos=pos}) + return --Abort + end + + minetest.sound_play("truck", {gain=1.0, pos=pos}) + + -- if the player is standing within the array or next to it, move him too. + local player_pos = clicker:getpos() + local move_player = false + if player_pos.x >= layout.extents.min_x - 1 and player_pos.x <= layout.extents.max_x + 1 and + player_pos.y >= layout.extents.min_y - 1 and player_pos.y <= layout.extents.max_y + 1 and + player_pos.z >= layout.extents.min_z - 1 and player_pos.z <= layout.extents.max_z + 1 then + move_player = true + end + + --move the array + digtron.move_digtron(facing, layout.all, layout.extents, nodes_dug) + local oldpos = {x=pos.x, y=pos.y, z=pos.z} + pos = digtron.find_new_pos(pos, facing) + if move_player then + clicker:moveto(digtron.find_new_pos(player_pos, facing), true) + end + + -- Start the delay before digtron can run again. Do this after moving the array or pos will be wrong. + minetest.get_meta(pos):set_string("waiting", "true") + minetest.after(digtron.refractory, + function (pos) + minetest.get_meta(pos):set_string("waiting", nil) + end, pos + ) + end, +}) \ No newline at end of file diff --git a/node_diggers.lua b/node_diggers.lua new file mode 100644 index 0000000..f2ffdff --- /dev/null +++ b/node_diggers.lua @@ -0,0 +1,147 @@ +-- Note: diggers go in group 3 and have an execute_dig method. + +local digger_nodebox = { + {-0.5, -0.5, 0, 0.5, 0.5, 0.4375}, -- Block + {-0.4375, -0.3125, 0.4375, 0.4375, 0.3125, 0.5}, -- Cutter1 + {-0.3125, -0.4375, 0.4375, 0.3125, 0.4375, 0.5}, -- Cutter2 + {-0.5, -0.125, -0.125, 0.5, 0.125, 0}, -- BackFrame1 + {-0.125, -0.5, -0.125, 0.125, 0.5, 0}, -- BackFrame2 + {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive +} + +-- Digs out nodes that are "in front" of the digger head. +minetest.register_node("digtron:digger", { + description = "Digger Head", + groups = {cracky = 3, stone = 1, digtron = 3}, + drop = 'digtron:digger', + paramtype = "light", + paramtype2= 'facedir', + + drawtype="nodebox", + node_box = { + type = "fixed", + fixed = digger_nodebox, + }, + + -- Aims in the +Z direction by default + tiles = { + "digtron_plate.png^[transformR90", + "digtron_plate.png^[transformR270", + "digtron_plate.png", + "digtron_plate.png^[transformR180", + { + name = "digtron_digger.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.0, + }, + }, + "digtron_motor.png", + }, + + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_string("formspec", + "size[3.5,1]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "field[0.5,0.8;1,0.1;period;Periodicity;${period}]" .. + "tooltip[period;Digger will dig once every n steps. These steps are globally aligned, all diggers with the same period and offset will dig on the same location.]" .. + "field[1.5,0.8;1,0.1;offset;Offset;${offset}]" .. + "tooltip[offset;Offsets the start of periodicity counting by this amount. For example, a digger with period 2 and offset 0 digs every even-numbered node and one with period 2 and offset 1 digs every odd-numbered node.]" .. + "button_exit[2.2,0.5;1,0.1;set;Save]" .. + "tooltip[set;Saves settings]" + ) + meta:set_string("period", 1) + meta:set_string("offset", 0) + + local inv = meta:get_inventory() + inv:set_size("main", 1) + end, + + on_receive_fields = function(pos, formname, fields, sender) + local meta = minetest.get_meta(pos) + local period = tonumber(fields.period) + local offset = tonumber(fields.offset) + if period and period > 0 then + meta:set_string("period", math.floor(tonumber(fields.period))) + end + if offset then + meta:set_string("offset", math.floor(tonumber(fields.offset))) + end + end, + + execute_dig = function(pos, protected_nodes, nodes_dug, controlling_coordinate) + local facing = minetest.get_node(pos).param2 + local digpos = digtron.find_new_pos(pos, facing) + + if protected_nodes:get(digpos.x, digpos.y, digpos.z) then + return nil + end + + local meta = minetest.get_meta(pos) + if (digpos[controlling_coordinate] + meta:get_string("offset")) % meta:get_string("period") ~= 0 then + return nil + end + + return digtron.mark_diggable(digpos, nodes_dug) + end, +}) + +-- A special-purpose digger to deal with stuff like sand and gravel in the ceiling. It always digs (no periodicity or offset), but it only digs falling_block nodes +minetest.register_node("digtron:sand_digger", { + description = "Sand Digger Head", + groups = {cracky = 3, stone = 1, digtron = 3}, + drop = 'digtron:sand_digger', + paramtype = "light", + paramtype2= 'facedir', + + drawtype="nodebox", + node_box = { + type = "fixed", + fixed = digger_nodebox, + }, + + -- Aims in the +Z direction by default + tiles = { + "digtron_plate.png^[transformR90^[colorize:#88880030", + "digtron_plate.png^[transformR270^[colorize:#88880030", + "digtron_plate.png^[colorize:#88880030", + "digtron_plate.png^[transformR180^[colorize:#88880030", + { + name = "digtron_digger.png^[colorize:#88880030", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.0, + }, + }, + "digtron_motor.png^[colorize:#88880030", + }, + + can_dig = function(pos,player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:is_empty("main") and inv:is_empty("inv") + end, + + execute_dig = function(pos, protected_nodes, nodes_dug, controlling_coordinate) + local facing = minetest.get_node(pos).param2 + local digpos = digtron.find_new_pos(pos, facing) + + if protected_nodes:get(digpos.x, digpos.y, digpos.z) then + return nil + end + + local target_node = minetest.get_node(digpos) + if minetest.get_item_group(target_node.name, "falling_node") ~= 0 then + return digtron.mark_diggable(digpos, nodes_dug) + end + + return nil + end, +}) \ No newline at end of file diff --git a/node_misc.lua b/node_misc.lua new file mode 100644 index 0000000..3168a46 --- /dev/null +++ b/node_misc.lua @@ -0,0 +1,79 @@ +-- A do-nothing "structural" node, to ensure all digtron nodes that are supposed to be connected to each other can be connected to each other. +minetest.register_node("digtron:structure", { + description = "Digger Structure", + groups = {cracky = 3, stone = 1, digtron = 1}, + drop = 'digtron:structure', + tiles = {"digtron_plate.png"}, + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = { + {0.3125, 0.3125, -0.5, 0.5, 0.5, 0.5}, + {0.3125, -0.5, -0.5, 0.5, -0.3125, 0.5}, + {-0.5, 0.3125, -0.5, -0.3125, 0.5, 0.5}, + {-0.5, -0.5, -0.5, -0.3125, -0.3125, 0.5}, + {-0.3125, 0.3125, 0.3125, 0.3125, 0.5, 0.5}, + {-0.3125, -0.5, 0.3125, 0.3125, -0.3125, 0.5}, + {-0.5, -0.3125, 0.3125, -0.3125, 0.3125, 0.5}, + {0.3125, -0.3125, 0.3125, 0.5, 0.3125, 0.5}, + {-0.5, -0.3125, -0.5, -0.3125, 0.3125, -0.3125}, + {0.3125, -0.3125, -0.5, 0.5, 0.3125, -0.3125}, + {-0.3125, 0.3125, -0.5, 0.3125, 0.5, -0.3125}, + {-0.3125, -0.5, -0.5, 0.3125, -0.3125, -0.3125}, + } + }, +}) + +-- A modest light source that will move with the digtron, handy for working in a tunnel you aren't bothering to install permanent lights in. +minetest.register_node("digtron:light", { + description = "Digger Light", + groups = {cracky = 3, stone = 1, digtron = 1}, + drop = 'digtron:light', + tiles = {"digtron_light.png"}, + drawtype = "nodebox", + paramtype = "light", + light_source = 10, + paramtype2 = "wallmounted", + node_box = { + type = "wallmounted", + wall_top = {-0.25, 0.3125, -0.25, 0.25, 0.5, 0.25}, + wall_bottom = {-0.25, -0.3125, -0.25, 0.25, -0.5, 0.25}, + wall_side = {-0.5, -0.25, -0.25, -0.1875, 0.25, 0.25}, + }, +}) + +-- Storage buffer. Builder nodes draw from this inventory and digger nodes deposit into it. +-- Note that inventories are digtron group 2. +minetest.register_node("digtron:inventory", +{ + description = "Digtron Inventory Hopper", + groups = {cracky = 3, stone = 1, digtron = 2}, + drop = 'digtron:inventory', + paramtype2= 'facedir', + tiles = {"digtron_inventory.png"}, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", + "size[8,9]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "list[current_name;main;0,0.3;8,4;]" .. + "list[current_player;main;0,4.85;8,1;]" .. + "list[current_player;main;0,6.08;8,3;8]" .. + "listring[current_name;main]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0,4.85) + ) + local inv = meta:get_inventory() + inv:set_size("main", 8*4) + end, + + can_dig = function(pos,player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:is_empty("main") + end, +}) \ No newline at end of file diff --git a/pointset.lua b/pointset.lua new file mode 100644 index 0000000..5bfd22a --- /dev/null +++ b/pointset.lua @@ -0,0 +1,73 @@ +-- A simple special-purpose class, this is used for building up sets of three-dimensional points +-- I only added features to it as I needed them so may not be highly useful outside of this mod's context. + +Pointset = {} +Pointset.__index = Pointset + +function Pointset.create() + local set = {} + setmetatable(set,Pointset) + set.points = {} + return set +end + +function Pointset:set(x, y, z, value) + -- sets a value in the 3D array "points". + if self.points[x] == nil then + self.points[x] = {} + end + if self.points[x][y] == nil then + self.points[x][y] = {} + end + self.points[x][y][z] = value +end + +function Pointset:set_if_not_in(excluded, x, y, z, value) + -- If a value is not already set for this point in the 3D array "excluded", set it in "points" + if excluded:get(x, y, z) ~= nil then + return + end + self:set(x, y, z, value) +end + +function Pointset:get(x, y, z) + -- return a value from the 3D array "points" + if self.points[x] == nil or self.points[x][y] == nil then + return nil + end + return self.points[x][y][z] +end + +function Pointset:pop() + -- returns a point that's in the 3D array, and then removes it. + local pos = {} + local ytable + local ztable + local val + + local count = 0 + for _ in pairs(self.points) do count = count + 1 end + if count == 0 then + return nil + end + + pos.x, ytable = next(self.points) + pos.y, ztable = next(ytable) + pos.z, val = next(ztable) + + self.points[pos.x][pos.y][pos.z] = nil + + count = 0 + for _ in pairs(self.points[pos.x][pos.y]) do count = count + 1 end + if count == 0 then + self.points[pos.x][pos.y] = nil + end + + count = 0 + for _ in pairs(self.points[pos.x]) do count = count + 1 end + if count == 0 then + self.points[pos.x] = nil + end + + return pos, val +end \ No newline at end of file diff --git a/recipes.lua b/recipes.lua new file mode 100644 index 0000000..e25f065 --- /dev/null +++ b/recipes.lua @@ -0,0 +1,115 @@ +minetest.register_craftitem("digtron:digtron_core", { + description = "Digtron Core", + inventory_image = "digtron_core.png" +}) + +minetest.register_craft({ + output = "digtron:digtron_core", + recipe = { + {"","default:steel_ingot",""}, + {"default:steel_ingot","default:mese_crystal_fragment","default:steel_ingot"}, + {"","default:steel_ingot",""} + } +}) + +minetest.register_craft({ + output = "digtron:controller", + recipe = { + {"","default:mese_crystal",""}, + {"default:mese_crystal","digtron:digtron_core","default:mese_crystal"}, + {"","default:mese_crystal",""} + } +}) + +minetest.register_craft({ + output = "digtron:builder", + recipe = { + {"","default:mese_crystal_fragment",""}, + {"default:mese_crystal_fragment","digtron:digtron_core","default:mese_crystal_fragment"}, + {"","default:mese_crystal_fragment",""} + } +}) + +minetest.register_craft({ + output = "digtron:light", + recipe = { + {"","default:torch",""}, + {"","digtron:digtron_core",""}, + {"","",""} + } +}) + +minetest.register_craft({ + output = "digtron:digger", + recipe = { + {"","default:diamond",""}, + {"default:diamond","digtron:digtron_core","default:diamond"}, + {"","default:diamond",""} + } +}) + +minetest.register_craft({ + output = "digtron:sand_digger", + recipe = { + {"","default:steel_ingot",""}, + {"default:steel_ingot","digtron:digtron_core","default:steel_ingot"}, + {"","default:steel_ingot",""} + } +}) + +minetest.register_craft({ + output = "digtron:inventory", + recipe = { + {"","default:chest",""}, + {"","digtron:digtron_core",""}, + {"","",""} + } +}) + +minetest.register_craft({ + output = "digtron:structure", + recipe = { + {"default:stick","","default:stick"}, + {"","digtron:digtron_core",""}, + {"default:stick","","default:stick"} + } +}) + +minetest.register_craft({ + output = "digtron:pusher", + recipe = { + {"","default:coal_lump",""}, + {"default:coal_lump","digtron:digtron_core","default:coal_lump"}, + {"","default:coal_lump",""} + } +}) + +-- And some recycling reactions to get digtron cores out of the "cheap" parts: + +minetest.register_craft({ + output = "digtron:digtron_core", + recipe = { + {"digtron:structure"}, + } +}) + +minetest.register_craft({ + output = "digtron:digtron_core", + recipe = { + {"digtron:inventory"}, + } +}) + +minetest.register_craft({ + output = "digtron:digtron_core", + recipe = { + {"digtron:light"}, + } +}) + +minetest.register_craft({ + output = "digtron:digtron_core", + recipe = { + {"digtron:pusher"}, + } +}) \ No newline at end of file diff --git a/sounds/buzzer.ogg b/sounds/buzzer.ogg new file mode 100644 index 0000000000000000000000000000000000000000..df9bdd392c968532da00f0cbe2a2f6d10053c1c5 GIT binary patch literal 12346 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 literal 0 HcmV?d00001 diff --git a/textures/digtron_builder.png b/textures/digtron_builder.png new file mode 100644 index 0000000000000000000000000000000000000000..fc3d5cc76965e3c6eb9983a22959b7618e9250a3 GIT binary patch literal 741 zcmVKBNEu03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00K!#L_t(2&t=KGawA0) z0ML7H-|n8bG_qE!!sXDZBY(gaxFDknVgmR?2>1hMikvEAtttmv%X-YHUw4`uPI~ay zUw)o-ZAwujN=(KW=i~lx27u429*FZK2swn90fTc?H}!B0i`A;Eo3d_-W_EF5x7+P@ zJ8SEzs`8ZQvspjumdjO!%+}aN-(vK ziHHx(nl(d=TASr^2>>yAQ?+h58C&@4NJ@hwcH_uhV+u12gY%vhO%t5YX8=IO$zPrK zDJGS3hz9NH?EWJ_(h#8Xn`Pbh{sh@uQ-WFv> z%sHo&0Kj`k88Ajc;;f8DgcwswT5BRQRqfoErz|2w)c1?v0!xhFj)%S}B~3ABt2xGa zcXtN>3Q5}%5sfh-vfI59ApzpDze#9}EkIFLMLnBsHk-|64hWFU8GbZ8()Nlj2>E@cM*00M$ZL_t(2&jrEHj}%1| z0N_`zUR8BZ_jFJ9?9K+4m>3lk1P>%0AOtT42qY$YGvVafyLZpVtABuZ?-0-a1FInh zqsX#5xU4I)+tXdYUX|Y`zWDsJww=cim;;BXwPEI%QqEZt38`{o$jSQvLb%CdJ+H>e z_p4P|)n!!|bvs3Fx<%P6jH$}9%$yc&+qKPdXD>r0txUJ*LbJ`<|rc0{s+LvVUl`M_ifA3Op8N3!EcO|1*P-EOUO zIq^S7udck$W+sm|%RHiWE`}&`_Q3)Gm9t8K${>lzP4?jQc=xOKzQ3P?QLi5U@+~yD ze>tU;5tq9=hcBMvG;Yt%UW?3$c^Za4?|=CCb@B7l`tS+oKhC~6Jw4l;3q&G1JbXz? zVdl78c6OR_hNI+c3|IG7cdvc@RNo2jT*k>=Q7D86AvE)v5K)-|1fmqf=HHn>-&7v) z;MdyyrT-FE^20Agm45)p60>LSmtee}c4TW;%^84>%g_s)w)kG>qop{t7! zQ_5LMDRgmZ|1GW5v)`Z17oD>XB{K8H`9xaaDM+O#a!!eZn?@<6A{Ao<5Q>1bLL_OlVfLhFWi{{mE^<&x zXFvd`+wQ+NZ>p*`M(^(JpKs3PrM=a~uo0;2G-Sk+{bwEh8KT77a&3i!)CKS cK4MP)174SBGcJ+5@Bjb+07*qoM6N<$f-7leegFUf literal 0 HcmV?d00001 diff --git a/textures/digtron_core.png b/textures/digtron_core.png new file mode 100644 index 0000000000000000000000000000000000000000..5edb2809a9c0220b49b25756f6e42c72ec0fd5f9 GIT binary patch literal 789 zcmV+w1M2*VP)WFU8GbZ8()Nlj2>E@cM*00MbQL_t(I%Y~D_OIuMC z$3M^HVIN6s$U~D-K_%D_!92tWPF=Hv;*g#C|Qxm>RILWo|!-=EcWz1qp|x+i`MoB@lHB!z~ChMo)z4A@RiPUKRl zG!LA$I1de4z&4-&D2hTX7Q=40b8v8gWm&Ya?M{=f_OpSFcF|ET7jx&hl)3 zA4j>|dGSU|^Vh)V^DWAtRbqHkhi;*-bY zv0YqT(0_D<`}P*u>Evl3fNOA&?}vxjgrK|8pcV+wY&HRUbY0)F1NB@k*EKRSLMRmC z`23vVSPaGMWqo!QfHw;ZxPw6&l?u}MIH^>Md_MmIpi7dZ+V1YIl}sk7R;vW!aTKqY zt6c8x!|q@ZvsmP7GKtIOA|8)3GczL#A)HdHiMk|7Aw^N}XEO8}26l&ompeOL<#J?K zSFvg}imJ+wsVSn-DB*C}a=YFA?J*t-A*k2ud=NQsI}+M>Z1S+T#JhvMkdujFr16 z>$+amG_44{0V%QDeulxDL@ zDwV=C%{I*h=33l`yU+rLRaM;#hr?E(Q23qC=Wm1%SzrYi?i4?^#(hEv=VQD-)MpG^ TmY-f600000NkvXXu0mjfPYGO+ literal 0 HcmV?d00001 diff --git a/textures/digtron_digger.png b/textures/digtron_digger.png new file mode 100644 index 0000000000000000000000000000000000000000..effc1013a9a02619ecc7890baeb3b6d7273b4fc1 GIT binary patch literal 2797 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 literal 0 HcmV?d00001 diff --git a/textures/digtron_motor.png b/textures/digtron_motor.png new file mode 100644 index 0000000000000000000000000000000000000000..4e1f437ef988ff26901b9b2671ce3dc56b1aebaa GIT binary patch literal 793 zcmV+!1LpjRP)WFU8GbZ8()Nlj2>E@cM*00MnUL_t(2&jrC-Zxcrp z0N|N3m%V!J^<}{>v}!~v1TP4BdEf={im257=T_pSPgPsm3P=+>aT3S&I=h~kb7qF` zz=EV`o`H%(TQSy86t&^lKZ znJlU#E%Q8&A&!Q_dRR@TO=J-goy_mgcw_(~&9ca2J)MC_b#Qr+a}M=ngor{a=dr3P z04d0Ob2L&al_XLKAp{1Z$Pum13x{4NsY3^hF;CL;y{t-|>aOdIwak-gyYv6oM7Ct( zsty(%A&D3r8par8dCsDYOh_p`QF^`n(VSM)Z?13q-+%k--8%sgLLd&4S!2nIr%xVt z$F9gTbdDePuf|+Fc=YGqrqgDWrQ6k6OQD`MQp)w!l~Pi?oySI4IBW)o3o`usAD;iZ zY8T%=yS};Uh{oK1THk&*biQMksu3C^Tg3>oZE)Rzf@Bcl!+*oJp$*eafL_V() z4|3FB4Z4dGTe&OmxjZN5C^1Rgv%Y=##pI9k|7_RYQ}VJs#D^!l@d*(z#;i3E8AtRS zWE6TZ8DCTn>VEfTjIVPS*Jq&`eRcA+_Z|T1dhCpo9&xkZ)@9}?V2mFxm`O2{UN9O8Fw6s`kZvc3Um9lrfU`!h4_U)bs~H zhsb!E7e`|l6I`l5+^8ZmTYKz<5K1Z{VvH-vq*eezBr5UVNu6iKU{sGN(8z2z#hfu# zR`u;}TNGuI=vlMa?^8gEGgv2yk_=;+!$pXTjd7;pyo|;DCsC`~7OQ3?Y67 XkL+-nM)Q0)00000NkvXXu0mjfV|!?# literal 0 HcmV?d00001 diff --git a/textures/digtron_plate.png b/textures/digtron_plate.png new file mode 100644 index 0000000000000000000000000000000000000000..7c1c327f05140b28acc2f7b9cdd07615479796c0 GIT binary patch literal 690 zcmV;j0!{siP)WFU8GbZ8()Nlj2>E@cM*00I_CL_t(2&jrDWZW}ic z0MNO}y<|yi*+S8eD$xEvP^5`nph)5AtS;Xb?ES$a9ah#g!dO2%tEUCI4k4GY5b1!=lNog2_nVFlZo2k}3FHK#Bv1ua! zaHFzq0X>hoX}jMaZWch^3|x`L>RxKywjFx3QUHLad4`Yx77>U*CNu3|h-j+jo>S_* z8`9aU-Gs+9Oo*6scK5fpFGNUy__AIMa~?)u3Lcl!iPGTKOL;JK2y=IL zAM=RONt-I*I4^rC0F08lVMOn)b>EmdNis74OahV<5%Z7+_a=FsmZ$T2Hg75A00Mx+ zasB?|V_6QvkYBIA-+uh$->$E}9zT&%+3!L0-@oq&sO5no;qd9x--M*9_uK9L{jK-- YA4$w?Ak7WAd;kCd07*qoM6N<$f`8XEy#N3J literal 0 HcmV?d00001 diff --git a/util.lua b/util.lua new file mode 100644 index 0000000..c9e6a34 --- /dev/null +++ b/util.lua @@ -0,0 +1,312 @@ +-- A random assortment of methods used in various places in this mod. + +digtron = {} + +dofile( minetest.get_modpath( "digtron" ) .. "/util_item_place_node.lua" ) -- separated out to avoid potential for license complexity + +digtron.find_new_pos = function(pos, facing) + -- finds the point one node "forward", based on facing + local dir = minetest.facedir_to_dir(facing) + local newpos = {} + newpos.x = pos.x + dir.x + newpos.y = pos.y + dir.y + newpos.z = pos.z + dir.z + return newpos +end + +digtron.mark_diggable = function(pos, nodes_dug) + -- mark the node as dug, if the player provided would have been able to dig it. + -- Don't *actually* dig the node yet, though, because if we dig a node with sand over it the sand will start falling + -- and then destroy whatever node we place there subsequently (either by a builder head or by moving a digtron node) + -- I don't like sand. It's coarse and rough and irritating and it gets everywhere. And it necessitates complicated dig routines. + -- returns what will be dropped by digging these nodes. + + local target = minetest.get_node(pos) + + -- prevent digtrons from being marked for digging. + if minetest.get_item_group(target.name, "digtron") ~= 0 then + return nil + end + + local targetdef = minetest.registered_nodes[target.name] + if targetdef.can_dig == nil or targetdef.can_dig(pos, player) then + nodes_dug:set(pos.x, pos.y, pos.z, true) + if target.name ~= "air" then + return minetest.get_node_drops(target.name, "") + end + end + return nil +end + +digtron.can_build_to = function(pos, protected_nodes, dug_nodes) + -- Returns whether a space is clear to have something put into it + + if protected_nodes:get(pos.x, pos.y, pos.z) then + return false + end + + -- tests if the location pointed to is clear to move something into + local target = minetest.get_node(pos) + if target.name == "air" or + dug_nodes:get(pos.x, pos.y, pos.z) == true or + minetest.registered_nodes[target.name].buildable_to == true + then + return true + end + return false +end + +digtron.can_move_to = function(pos, protected_nodes, dug_nodes) + -- Same as can_build_to, but also checks if the current node is part of the digtron. + -- this allows us to disregard obstructions that *will* move out of the way. + if digtron.can_build_to(pos, protected_nodes, dug_nodes) == true or + minetest.get_item_group(minetest.get_node(pos).name, "digtron") ~= 0 then + return true + end + return false +end + +digtron.move_node = function(pos, newpos) + -- Moves nodes, preserving digtron metadata and inventory + local node = minetest.get_node(pos) + minetest.add_node(newpos, { name=node.name, param1=node.param1, param2=node.param2 }) + + local oldmeta = minetest.get_meta(pos) + local oldinv = oldmeta:get_inventory() + local list = oldinv:get_list("main") + local oldformspec = oldmeta:get_string("formspec") + + local newmeta = minetest.get_meta(newpos) + local newinv = newmeta:get_inventory() + newinv:set_list("main", list) + newmeta:set_string("formspec", oldformspec) + + newmeta:set_string("offset", oldmeta:get_string("offset")) + newmeta:set_string("period", oldmeta:get_string("period")) + newmeta:set_string("build_facing", oldmeta:get_string("build_facing")) + + -- remove node from old position + minetest.remove_node(pos) +end + +digtron.get_all_digtron_neighbours = function(pos, player) + -- returns table containing a list of all digtron node locations, lists of special digtron node types, a table of the coordinate extents of the digtron array, a Pointset of protected nodes, and a bool to determine if the array is adjacent to non-digtron nodes (for traction) + + --minetest.debug(string.format("digtron search started at component %d %d %d", pos.x, pos.y, pos.z)) + + local layout = {} + --initialize. We're assuming that the start position is a controller digtron, should be a safe assumption since only the controller node should call this + layout.traction = false + layout.all = {} + layout.inventories = {} + layout.diggers = {} + layout.builders = {} + layout.extents = {} + layout.protected = Pointset.create() -- if any nodes we look at are protected, make note of that. That way we don't need to keep re-testing protection state later. + layout.controller = {x=pos.x, y=pos.y, z=pos.z} --Make a deep copy of the pos parameter just in case the calling code wants to play silly buggers with it + + table.insert(layout.all, layout.controller) + layout.extents.max_x = pos.x + layout.extents.min_x = pos.x + layout.extents.max_y = pos.y + layout.extents.min_y = pos.y + layout.extents.max_z = pos.z + layout.extents.min_z = pos.z + + -- temporary pointsets used while searching + local to_test = Pointset.create() + local tested = Pointset.create() + + tested:set(pos.x, pos.y, pos.z, true) + to_test:set(pos.x + 1, pos.y, pos.z, true) + to_test:set(pos.x - 1, pos.y, pos.z, true) + to_test:set(pos.x, pos.y + 1, pos.z, true) + to_test:set(pos.x, pos.y - 1, pos.z, true) + to_test:set(pos.x, pos.y, pos.z + 1, true) + to_test:set(pos.x, pos.y, pos.z - 1, true) + + if minetest.is_protected(pos, player:get_player_name()) and not minetest.check_player_privs(player, "protection_bypass") then + layout.protected:set(pos.x, pos.y, pos.z, true) + end + + -- Do a loop on to_test positions, adding new to_test positions as we find digtron nodes. This is a flood fill operation + -- that follows node faces (no diagonals) + local testpos, _ = to_test:pop() + while testpos ~= nil do + tested:set(testpos.x, testpos.y, testpos.z, true) -- track nodes we've looked at to prevent infinite loops + local node = minetest.get_node(testpos) + + if node.name == "ignore" then + --buildtron array is next to unloaded nodes, too dangerous to do anything. Abort. + layout.all = nil + return layout + end + + if minetest.is_protected(pos, player:get_player_name()) and not minetest.check_player_privs(player, "protection_bypass") then + layout.protected:set(testpos.x, testpos.y, testpos.z, true) + end + + local group_number = minetest.get_item_group(node.name, "digtron") + if group_number > 0 then + --minetest.debug(string.format("found digtron component at %d %d %d", testpos.x, testpos.y, testpos.z)) + --found one. Add it to the digtrons output + table.insert(layout.all, testpos) + + -- update extents + layout.extents.max_x = math.max(layout.extents.max_x, testpos.x) + layout.extents.min_x = math.min(layout.extents.min_x, testpos.x) + layout.extents.max_y = math.max(layout.extents.max_y, testpos.y) + layout.extents.min_y = math.min(layout.extents.min_y, testpos.y) + layout.extents.max_z = math.max(layout.extents.max_z, testpos.z) + layout.extents.min_z = math.min(layout.extents.min_z, testpos.z) + + -- add a reference to this node's position to special node lists + if group_number == 2 then + table.insert(layout.inventories, testpos) + elseif group_number == 3 then + table.insert(layout.diggers, testpos) + elseif group_number == 4 then + table.insert(layout.builders, testpos) + end + + --queue up potential new test points adjacent to this digtron node + to_test:set_if_not_in(tested, testpos.x + 1, testpos.y, testpos.z, true) + to_test:set_if_not_in(tested, testpos.x - 1, testpos.y, testpos.z, true) + to_test:set_if_not_in(tested, testpos.x, testpos.y + 1, testpos.z, true) + to_test:set_if_not_in(tested, testpos.x, testpos.y - 1, testpos.z, true) + to_test:set_if_not_in(tested, testpos.x, testpos.y, testpos.z + 1, true) + to_test:set_if_not_in(tested, testpos.x, testpos.y, testpos.z - 1, true) + elseif not layout.traction and minetest.registered_nodes[node.name].buildable_to ~= true then + -- Tracks whether the digtron is hovering in mid-air. If any part of the digtron array touches something solid, it can move. + layout.traction = true + end + + testpos, _ = to_test:pop() + end + + return layout +end + +digtron.place_in_inventory = function(itemname, inventory_positions, fallback_pos) + --tries placing the item in each inventory node in turn. If there's no room, drop it at fallback_pos + local itemstack = ItemStack(itemname) + for k, location in pairs(inventory_positions) do + local inv = minetest.get_inventory({type="node", pos=location}) + itemstack = inv:add_item("main", itemstack) + if itemstack:is_empty() then + return nil + end + end + minetest.add_item(fallback_pos, itemstack) +end + +digtron.place_in_specific_inventory = function(itemname, pos, inventory_positions, fallback_pos) + --tries placing the item in a specific inventory. Other parameters are used as fallbacks on failure + --Use this method for putting stuff back after testing and failed builds so that if the player + --is trying to keep various inventories organized manually stuff will go back where it came from, + --probably. + local itemstack = ItemStack(itemname) + local inv = minetest.get_inventory({type="node", pos=pos}) + local returned_stack = inv:add_item("main", itemstack) + if not returned_stack:is_empty() then + -- we weren't able to put the item back into that particular inventory for some reason. + -- try putting it *anywhere.* + digtron.place_in_inventory(returned_stack, inventory_positions, fallback_pos) + end +end + +digtron.take_from_inventory = function(itemname, inventory_positions) + --tries to take an item from each inventory node in turn. Returns location of inventory item was taken from on success, nil on failure + local itemstack = ItemStack(itemname) + for k, location in pairs(inventory_positions) do + local inv = minetest.get_inventory({type="node", pos=location}) + local output = inv:remove_item("main", itemstack) + if not output:is_empty() then + return location + end + end + return nil +end + +digtron.move_digtron = function(facing, digtrons, extents, nodes_dug) + -- move everything. Note! order is important or they'll step on each other, that's why this has complicated loops and filtering. + -- Nodes are moved in a "caterpillar" pattern - front plane first, then next plane back, then next plane back, etc. + -- positions in the digtron list will be updated when this method executes. Note that the inventories list shares + -- references to the node position tables in the digtron list, so it will reflect the updates too. + local dir = digtron.facedir_to_dir_map[facing] + local increment + local filter + local index + local target + if dir == 1 then -- z+ + filter = "z" + increment = -1 + index = extents.max_z + target = extents.min_z + extents.max_z = extents.max_z + 1 + extents.min_z = extents.min_z + 1 + elseif dir == 2 then -- x+ + filter = "x" + increment = -1 + index = extents.max_x + target = extents.min_x + extents.max_x = extents.max_x + 1 + extents.min_x = extents.min_x + 1 + elseif dir == 3 then -- z- + filter = "z" + increment = 1 + index = extents.min_z + target = extents.max_z + extents.max_z = extents.max_z - 1 + extents.min_z = extents.min_z - 1 + elseif dir == 4 then -- x- + filter = "x" + increment = 1 + index = extents.min_x + target = extents.max_x + extents.max_x = extents.max_x - 1 + extents.min_x = extents.min_x - 1 + elseif dir == 5 then -- y- + filter = "y" + increment = 1 + index = extents.min_y + target = extents.max_y + extents.max_y = extents.max_y - 1 + extents.min_y = extents.min_y - 1 + elseif dir == 6 then -- y+ + filter = "y" + increment = -1 + index = extents.max_y + target = extents.min_y + extents.max_y = extents.max_y + 1 + extents.min_y = extents.min_y + 1 + end + + while index ~= target + increment do + for k, location in pairs(digtrons) do + if location[filter] == index then + local newpos = digtron.find_new_pos(location, facing) + digtron.move_node(location, newpos) + --By updating the digtron position table in-place we also update all the special node tables as well + digtrons[k].x= newpos.x + digtrons[k].y= newpos.y + digtrons[k].z= newpos.z + nodes_dug:set(newpos.x, newpos.y, newpos.z, false) -- we've moved a digtron node into this space, mark it so that we don't dig it. + end + end + index = index + increment + end +end + +-- Used to determine which coordinate is being checked for periodicity. eg, if the digtron is moving in the z direction, then periodicity is checked for every n nodes in the z axis. +digtron.get_controlling_coordinate = function(pos, facedir) + -- used for determining builder period and offset + local dir = digtron.facedir_to_dir_map[facedir] + if dir == 1 or dir == 3 then + return "z" + elseif dir == 2 or dir == 4 then + return "x" + else + return "y" + end +end \ No newline at end of file diff --git a/util_item_place_node.lua b/util_item_place_node.lua new file mode 100644 index 0000000..759ef8e --- /dev/null +++ b/util_item_place_node.lua @@ -0,0 +1,138 @@ +-- The default minetest.item_place_node from item.lua was hard to work with given some of the details +-- of how it handled pointed_thing. It also didn't work right with default:torch. It was simpler to +-- just copy it here and chop out the special cases that were causing problems. + +-- This specific file is therefore licensed under the LGPL 2.1 + +--GNU Lesser General Public License, version 2.1 +--Copyright (C) 2011-2016 celeron55, Perttu Ahola +--Copyright (C) 2011-2016 Various Minetest developers and contributors + +--This program is free software; you can redistribute it and/or modify it under the terms +--of the GNU Lesser General Public License as published by the Free Software Foundation; +--either version 2.1 of the License, or (at your option) any later version. + +--This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +--without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +--See the GNU Lesser General Public License for more details: +--https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + +-- Mapping from facedir value to index in facedir_to_dir. +digtron.facedir_to_dir_map = { + [0]=1, 2, 3, 4, + 5, 2, 6, 4, + 6, 2, 5, 4, + 1, 5, 3, 6, + 1, 6, 3, 5, + 1, 4, 3, 2, +} + +local function copy_pointed_thing(pointed_thing) + return { + type = pointed_thing.type, + above = vector.new(pointed_thing.above), + under = vector.new(pointed_thing.under), + } +end + +local function check_attached_node(p, n) + local def = minetest.registered_nodes[n.name] + local d = {x = 0, y = 0, z = 0} + if def.paramtype2 == "wallmounted" then + -- The fallback vector here is in case 'wallmounted to dir' is nil due + -- to voxelmanip placing a wallmounted node without resetting a + -- pre-existing param2 value that is out-of-range for wallmounted. + -- The fallback vector corresponds to param2 = 0. + d = minetest.wallmounted_to_dir(n.param2) or {x = 0, y = 1, z = 0} + else + d.y = -1 + end + local p2 = vector.add(p, d) + local nn = minetest.get_node(p2).name + local def2 = minetest.registered_nodes[nn] + if def2 and not def2.walkable then + return false + end + return true +end + +digtron.item_place_node = function(itemstack, placer, place_to, param2) + local item = itemstack:peek_item() + local def = itemstack:get_definition() + if def.type ~= "node" then + return itemstack, false + end + + local pointed_thing = {} + pointed_thing.type = "node" + pointed_thing.above = {x=place_to.x, y=place_to.y, z=place_to.z} + pointed_thing.under = {x=place_to.x, y=place_to.y - 1, z=place_to.z} + + local oldnode = minetest.get_node_or_nil(place_to) + + --this should never happen, digtron is testing for adjacent unloaded nodes before getting here. + if not oldnode then + minetest.log("info", placer:get_player_name() .. " tried to place" + .. " node in unloaded position " .. minetest.pos_to_string(place_to) + .. " using a digtron.") + return itemstack, false + end + + local newnode = {name = def.name, param1 = 0, param2 = param2} + if def.place_param2 ~= nil then + newnode.param2 = def.place_param2 + end + + -- Check if the node is attached and if it can be placed there + if minetest.get_item_group(def.name, "attached_node") ~= 0 and + not check_attached_node(place_to, newnode) then + minetest.log("action", "attached node " .. def.name .. + " can not be placed at " .. minetest.pos_to_string(place_to)) + return itemstack, false + end + + -- digtron HACK! the default torch mod uses "on_place" to change its model to the correct one, + -- not "after_place_node". It probably should be using after_place_node, but until then I must + -- adapt as best I can to the quirks of default. + if newnode.name == "default:torch" then + if newnode.param2 == 0 then + newnode.name = "default:torch_ceiling" + elseif newnode.param2 > 1 then + newnode.name = "default:torch_wall" + end + end + + -- Add node and update + minetest.add_node(place_to, newnode) + + local take_item = true + + -- Run callback + if def.after_place_node then + -- Deepcopy place_to and pointed_thing because callback can modify it + local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z} + local pointed_thing_copy = copy_pointed_thing(pointed_thing) + if def.after_place_node(place_to_copy, placer, itemstack, + pointed_thing_copy) then + take_item = false + end + end + + -- Run script hook + local _, callback + for _, callback in ipairs(minetest.registered_on_placenodes) do + -- Deepcopy pos, node and pointed_thing because callback can modify them + local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z} + local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2} + local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2} + local pointed_thing_copy = copy_pointed_thing(pointed_thing) + if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then + take_item = false + end + end + + if take_item then + itemstack:take_item() + end + return itemstack, true +end \ No newline at end of file