diff --git a/.gitignore b/.gitignore index cd2946a..b46bf61 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk +# Blender files +*.blend + # ========================= # Operating System Files # ========================= diff --git a/controller.lua b/controller.lua index 0560889..d81db51 100644 --- a/controller.lua +++ b/controller.lua @@ -72,6 +72,7 @@ minetest.register_node("digtron:controller", { }, drawtype = "nodebox", node_box = controller_nodebox, + sounds = default.node_sound_metal_defaults(), -- on_construct = function(pos) -- end, @@ -95,7 +96,10 @@ minetest.register_node("digtron:controller", { end -- call on_dignodes callback if digtron_id ~= "" then - digtron.remove_from_world(digtron_id, pos, player_name) + local removed = digtron.remove_from_world(digtron_id, pos, player_name) + for _, removed_pos in ipairs(removed) do + minetest.check_for_falling(removed_pos) + end else minetest.remove_node(pos) end @@ -139,12 +143,14 @@ minetest.register_node("digtron:controller", { local success, succeeded, failed = digtron.is_buildable_to(digtron_id, target_pos, player_name) if success then digtron.build_to_world(digtron_id, target_pos, player_name) + minetest.sound_play("digtron_machine_assemble", {gain = 0.5, pos=root_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 digtron.show_buildable_nodes(succeeded, failed) + minetest.sound_play("digtron_buzzer", {gain = 0.5, pos=root_pos}) end end return itemstack @@ -226,17 +232,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "digtron:controller_assembled" then return end - local name = player:get_player_name() - local digtron_id = player_interacting_with_digtron_id[name] + local player_name = player:get_player_name() + local digtron_id = player_interacting_with_digtron_id[player_name] if digtron_id == nil then return end if fields.disassemble then - local pos = digtron.disassemble(digtron_id, name) + local pos = digtron.disassemble(digtron_id, player_name) if pos then - player_interacting_with_digtron_pos[name] = pos - minetest.show_formspec(name, + player_interacting_with_digtron_pos[player_name] = pos + minetest.show_formspec(player_name, "digtron:controller_unassembled", - get_controller_unassembled_formspec(pos, name)) + get_controller_unassembled_formspec(pos, player_name)) end end @@ -247,7 +253,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if node.name == "digtron:controller" then local dir = minetest.facedir_to_dir(node.param2) local dest_pos = vector.add(dir, pos) - digtron.move(digtron_id, dest_pos) + digtron.move(digtron_id, dest_pos, player_name) end end end diff --git a/entities.lua b/entities.lua index 568ad75..ba1e954 100644 --- a/entities.lua +++ b/entities.lua @@ -1,12 +1,10 @@ -- The default minetest.add_entity crashes with an exception if you try adding an entity in an unloaded area -- this wrapper catches that exception and just ignores it. -digtron.safe_add_entity = function(pos, name) - success, ret = pcall(minetest.add_entity, pos, name) +safe_add_entity = function(pos, name) + local success, ret = pcall(minetest.add_entity, pos, name) if success then return ret else return nil end end -local safe_add_entity = digtron.safe_add_entity - ------------------------------------------------------------------------------------------------- -- For displaying where things get built under which periodicities @@ -78,6 +76,20 @@ end ----------------------------------------------------------------------------------------------- -- For displaying whether nodes are part of a digtron or are obstructed +digtron.show_buildable_nodes = function(succeeded, failed) + if succeeded then + for _, pos in ipairs(succeeded) do + safe_add_entity(pos, "digtron:marker_crate_good") + end + end + if failed then + for _, pos in ipairs(failed) do + safe_add_entity(pos, "digtron:marker_crate_bad") + end + end +end + + minetest.register_entity("digtron:marker_crate_good", { initial_properties = { visual = "cube", diff --git a/functions.lua b/functions.lua index 6a0ed81..286e129 100644 --- a/functions.lua +++ b/functions.lua @@ -164,19 +164,13 @@ end local get_table_functions = function(identifier) cache[identifier] = {} - -- add a callback for dispose_id - table.insert(dispose_callbacks, function(digtron_id) - mod_meta:set_string(digtron_id..":"..identifier, "") - cache[identifier][digtron_id] = nil - end) - return function(digtron_id, tbl) - minetest.chat_send_all("persisting " .. identifier .. " " .. digtron_id) + local persist_func = function(digtron_id, tbl) mod_meta:set_string(digtron_id..":"..identifier, minetest.serialize(tbl)) cache[identifier][digtron_id] = tbl - end, - function(digtron_id) - minetest.chat_send_all("retrieving " .. identifier .. " " .. digtron_id) + end + + local retrieve_func = function(digtron_id) local current = cache[identifier][digtron_id] if current then return current @@ -190,12 +184,22 @@ local get_table_functions = function(identifier) return current end end + + local dispose_func = function(digtron_id) + mod_meta:set_string(digtron_id..":"..identifier, "") + cache[identifier][digtron_id] = nil + end + + -- add a callback for dispose_id + table.insert(dispose_callbacks, dispose_func) + + return persist_func, retrieve_func, dispose_func end local persist_layout, retrieve_layout = get_table_functions("layout") local persist_adjacent, retrieve_adjacent = get_table_functions("adjacent") local persist_bounding_box, retrieve_bounding_box = get_table_functions("bounding_box") -local persist_pos, retrieve_pos = get_table_functions("pos") +local persist_pos, retrieve_pos, dispose_pos = get_table_functions("pos") digtron.get_pos = retrieve_pos @@ -315,6 +319,12 @@ digtron.assemble = function(root_pos, player_name) -- store the inventory size so the inventory can be easily recreated current_meta_table.inventory[listname] = #items end + + local node_def = minetest.registered_nodes[node.name] + if node_def and node_def._digtron_assembled_node then + node.name = node_def._digtron_assembled_node + minetest.swap_node(minetest.get_position_from_hash(hash), node) + end node.param1 = nil -- we don't care about param1, wipe it to save space layout[relative_hash] = {meta = current_meta_table, node = node} @@ -353,6 +363,7 @@ digtron.assemble = function(root_pos, player_name) minetest.log("action", "Digtron " .. digtron_id .. " assembled at " .. minetest.pos_to_string(root_pos) .. " by " .. player_name) + minetest.sound_play("digtron_machine_assemble", {gain = 0.5, pos=root_pos}) return digtron_id end @@ -361,7 +372,8 @@ end -- Returns pos, node, and meta for the digtron node provided the in-world node matches the layout -- returns nil otherwise local get_valid_data = function(digtron_id, root_hash, hash, data, function_name) - local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash) + local node_hash = hash + root_hash - origin_hash -- TODO may want to return this as well? + local node_pos = minetest.get_position_from_hash(node_hash) local node = minetest.get_node(node_pos) local node_meta = minetest.get_meta(node_pos) local target_digtron_id = node_meta:get_string("digtron_id") @@ -425,6 +437,11 @@ digtron.disassemble = function(digtron_id, player_name) end end + local node_def = minetest.registered_nodes[node.name] + if node_def and node_def._digtron_disassembled_node then + minetest.swap_node(node_pos, {name=node_def._digtron_disassembled_node, param2=node.param2}) + end + -- TODO: special handling for builder node inventories -- Ensure node metadata fields are all set, too @@ -437,13 +454,18 @@ digtron.disassemble = function(digtron_id, player_name) end end + minetest.log("action", "Digtron " .. digtron_id .. " disassembled at " .. minetest.pos_to_string(root_pos) + .. " by " .. player_name) + minetest.sound_play("digtron_machine_disassemble", {gain = 0.5, pos=root_pos}) + dispose_id(digtron_id) - + return root_pos 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, root_pos, player_name) local layout = retrieve_layout(digtron_id) @@ -453,7 +475,7 @@ digtron.remove_from_world = function(digtron_id, root_pos, player_name) local meta = minetest.get_meta(root_pos) meta:set_string("digtron_id", "") dispose_id(digtron_id) - return + return {} end local root_hash = minetest.hash_node_position(root_pos) @@ -466,25 +488,41 @@ digtron.remove_from_world = function(digtron_id, root_pos, player_name) end -- TODO: voxelmanip might be better here? - minetest.bulk_set_node(nodes_to_destroy, {name="air"}) + minetest.bulk_set_node(nodes_to_destroy, {name="air"}) + dispose_pos(digtron_id) + return nodes_to_destroy end -- Tests if a Digtron can be built at the designated location ---TODO implement ignore_nodes, needed for ignoring self nodes and nodes that have been flagged as dug +--TODO implement ignore_nodes, needed for ignoring nodes that have been flagged as dug digtron.is_buildable_to = function(digtron_id, root_pos, player_name, ignore_nodes, return_immediately_on_failure) local layout = retrieve_layout(digtron_id) + + -- 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_pos = retrieve_pos(digtron_id) + local old_hashes = {} + if old_pos then + local old_root_hash = minetest.hash_node_position(old_pos) + local old_root_minus_origin = old_root_hash - origin_hash + for layout_hash, _ in pairs(layout) do + old_hashes[layout_hash + old_root_minus_origin] = true + end + end + local root_hash = minetest.hash_node_position(root_pos) - local show_anything = show_successes or show_failures + local root_minus_origin = root_hash - origin_hash local succeeded = {} local failed = {} local permitted = true - for hash, data in pairs(layout) do - local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash) + for layout_hash, data in pairs(layout) do + local node_hash = layout_hash + root_minus_origin + 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) then + if not ((node_def and node_def.buildable_to) or old_hashes[node_hash]) then if return_immediately_on_failure then return false -- no need to test further, don't return node positions else @@ -499,25 +537,11 @@ digtron.is_buildable_to = function(digtron_id, root_pos, player_name, ignore_nod return permitted, succeeded, failed end -digtron.show_buildable_nodes = function(succeeded, failed) - if succeeded then - for _, pos in ipairs(succeeded) do - digtron.safe_add_entity(pos, "digtron:marker_crate_good") - end - end - if failed then - for _, pos in ipairs(failed) do - digtron.safe_add_entity(pos, "digtron:marker_crate_bad") - end - end -end - -- Places the Digtron into the world. digtron.build_to_world = function(digtron_id, root_pos, player_name) local layout = retrieve_layout(digtron_id) local root_hash = minetest.hash_node_position(root_pos) - -- TODO: voxelmanip might be better here, less likely than with destroy though since metadata needs to be written for hash, data in pairs(layout) do local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash) minetest.set_node(node_pos, data.node) @@ -527,11 +551,6 @@ digtron.build_to_world = function(digtron_id, root_pos, player_name) end meta:set_string("digtron_id", digtron_id) meta:mark_as_private("digtron_id") - -- Not needed - local inventories not used by active digtron, will be restored if disassembled --- local inv = meta:get_inventory() --- for listname, size in pairs(data.meta.inventory) do --- inv:set_size(listname, size) --- end end local bbox = retrieve_bounding_box(digtron_id) persist_bounding_box(digtron_id, bbox) @@ -542,7 +561,23 @@ end digtron.move = function(digtron_id, dest_pos, player_name) minetest.chat_send_all("move attempt") - + local current_pos = retrieve_pos(digtron_id) + if current_pos == nil then + minetest.chat_send_all("no pos recorded for digtron") + return + end + local permitted, succeeded, failed = digtron.is_buildable_to(digtron_id, dest_pos, player_name) + if permitted then + local removed = digtron.remove_from_world(digtron_id, current_pos, player_name) + digtron.build_to_world(digtron_id, 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) + end + else + digtron.show_buildable_nodes({}, failed) + minetest.sound_play("digtron_squeal", {gain = 0.5, pos=current_pos}) + end end diff --git a/nodes/node_digger.lua b/nodes/node_digger.lua index 6efa31e..4cbe02e 100644 --- a/nodes/node_digger.lua +++ b/nodes/node_digger.lua @@ -1,78 +1,87 @@ -local def = { - description = "Digger", - _doc_items_longdesc = nil, - _doc_items_usagehelp = nil, - drawtype = "mesh", - mesh = "digtron_digger.obj", - tiles = { - { name = "digtron_plate.png^digtron_digger_yb_frame.png", backface_culling = true }, - { name = "digtron_plate.png", backface_culling = true }, - { name = "digtron_drill_head_animated.png", backface_culling = true, animation = - { - type = "vertical_frames", - aspect_w = 48, - aspect_h = 12, - length = 1.0, - } - }, - { name = "digtron_plate.png^digtron_motor.png", backface_culling = true }, - }, - collision_box = { - type = "fixed", - fixed = { - {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill - {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block - {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive - }, - }, - selection_box = { - type = "fixed", - fixed = { - {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill - {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block - {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive - }, - }, - paramtype2 = "facedir", - paramtype = "light", - groups = {cracky = 3, oddly_breakable_by_hand = 3, digtron = 1}, - sounds = digtron.metal_sounds, -} +-- internationalization boilerplate +local MP = minetest.get_modpath(minetest.get_current_modname()) +local S, NS = dofile(MP.."/intllib.lua") -minetest.register_node("digtron:digger", def) +minetest.register_node("digtron:digger", { + description = S("Digtron Digger"), + _doc_items_longdesc = nil, + _doc_items_usagehelp = nil, + _digtron_disassembled_node = "digtron:digger_static", + drops = "digtron:digger_static", + drawtype = "mesh", + mesh = "digtron_digger.obj", + tiles = { + { name = "digtron_plate.png^digtron_digger_yb_frame.png", backface_culling = true }, + { name = "digtron_plate.png", backface_culling = true }, + { name = "digtron_drill_head_animated.png", backface_culling = true, animation = + { + type = "vertical_frames", + aspect_w = 48, + aspect_h = 12, + length = 1.0, + } + }, + { name = "digtron_plate.png^digtron_motor.png", backface_culling = true }, + }, + collision_box = { + type = "fixed", + fixed = { + {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill + {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block + {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill + {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block + {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive + }, + }, + paramtype2 = "facedir", + paramtype = "light", + groups = {cracky = 3, oddly_breakable_by_hand = 3, digtron = 1}, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + can_dig = digtron.can_dig, + on_blast = digtron.on_blast, +}) -local def_static = { - description = "Digger", - _doc_items_longdesc = nil, - _doc_items_usagehelp = nil, - drawtype = "mesh", - mesh = "digtron_digger_static.obj", - tiles = { - { name = "digtron_plate.png^digtron_digger_yb_frame.png", backface_culling = true }, - { name = "digtron_plate.png", backface_culling = true }, - { name = "digtron_drill_head_animated.png", backface_culling = true }, - { name = "digtron_plate.png^digtron_motor.png", backface_culling = true }, +minetest.register_node("digtron:digger_static",{ + description = S("Digtron Digger"), + _doc_items_longdesc = nil, + _doc_items_usagehelp = nil, + _digtron_assembled_node = "digtron:digger", + drawtype = "mesh", + mesh = "digtron_digger_static.obj", + tiles = { + { name = "digtron_plate.png^digtron_digger_yb_frame.png", backface_culling = true }, + { name = "digtron_plate.png", backface_culling = true }, + { name = "digtron_drill_head_animated.png", backface_culling = true }, + { name = "digtron_plate.png^digtron_motor.png", backface_culling = true }, + }, + collision_box = { + type = "fixed", + fixed = { + {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill + {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block + {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive }, - collision_box = { - type = "fixed", - fixed = { - {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill - {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block - {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive - }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill + {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block + {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive }, - selection_box = { - type = "fixed", - fixed = { - {-0.25, -0.25, 0.5, 0.25, 0.25, 0.8125}, -- Drill - {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, -- Block - {-0.25, -0.25, -0.5, 0.25, 0.25, 0}, -- Drive - }, - }, - paramtype2 = "facedir", - paramtype = "light", - groups = {cracky = 3, oddly_breakable_by_hand = 3, digtron = 1}, - sounds = digtron.metal_sounds, -} - -minetest.register_node("digtron:digger_static", def_static) + }, + paramtype2 = "facedir", + paramtype = "light", + groups = {cracky = 3, oddly_breakable_by_hand = 3, digtron = 1}, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + can_dig = digtron.can_dig, + on_blast = digtron.on_blast, +}) diff --git a/nodes/node_misc.lua b/nodes/node_misc.lua index 976b86b..9ae346d 100644 --- a/nodes/node_misc.lua +++ b/nodes/node_misc.lua @@ -10,7 +10,7 @@ minetest.register_node("digtron:structure", { groups = {cracky = 3, oddly_breakable_by_hand=3, digtron = 1}, tiles = {"digtron_plate.png"}, drawtype = "nodebox", - sounds = digtron.metal_sounds, + sounds = default.node_sound_metal_defaults(), climbable = true, walkable = false, paramtype = "light", @@ -69,7 +69,7 @@ minetest.register_node("digtron:panel", { drawtype = "nodebox", paramtype = "light", is_ground_content = false, - sounds = digtron.metal_sounds, + sounds = default.node_sound_metal_defaults(), paramtype2 = "facedir", node_box = { type = "fixed", @@ -93,7 +93,7 @@ minetest.register_node("digtron:edge_panel", { drawtype = "nodebox", paramtype = "light", is_ground_content = false, - sounds = digtron.metal_sounds, + sounds = default.node_sound_metal_defaults(), paramtype2 = "facedir", node_box = { type = "fixed", @@ -122,7 +122,7 @@ minetest.register_node("digtron:corner_panel", { drawtype = "nodebox", paramtype = "light", is_ground_content = false, - sounds = digtron.metal_sounds, + sounds = default.node_sound_metal_defaults(), paramtype2 = "facedir", node_box = { type = "fixed", diff --git a/sounds/buzzer.ogg b/sounds/digtron_buzzer.ogg similarity index 100% rename from sounds/buzzer.ogg rename to sounds/digtron_buzzer.ogg diff --git a/sounds/construction.ogg b/sounds/digtron_construction.ogg similarity index 100% rename from sounds/construction.ogg rename to sounds/digtron_construction.ogg diff --git a/sounds/dingding.ogg b/sounds/digtron_dingding.ogg similarity index 100% rename from sounds/dingding.ogg rename to sounds/digtron_dingding.ogg diff --git a/sounds/honk.ogg b/sounds/digtron_honk.ogg similarity index 100% rename from sounds/honk.ogg rename to sounds/digtron_honk.ogg diff --git a/sounds/machine1.ogg b/sounds/digtron_machine_assemble.ogg similarity index 100% rename from sounds/machine1.ogg rename to sounds/digtron_machine_assemble.ogg diff --git a/sounds/machine2.ogg b/sounds/digtron_machine_disassemble.ogg similarity index 100% rename from sounds/machine2.ogg rename to sounds/digtron_machine_disassemble.ogg diff --git a/sounds/sploosh.ogg b/sounds/digtron_sploosh.ogg similarity index 100% rename from sounds/sploosh.ogg rename to sounds/digtron_sploosh.ogg diff --git a/sounds/squeal.ogg b/sounds/digtron_squeal.ogg similarity index 100% rename from sounds/squeal.ogg rename to sounds/digtron_squeal.ogg diff --git a/sounds/steam_puff.ogg b/sounds/digtron_steam_puff.ogg similarity index 100% rename from sounds/steam_puff.ogg rename to sounds/digtron_steam_puff.ogg diff --git a/sounds/truck.ogg b/sounds/digtron_truck.ogg similarity index 100% rename from sounds/truck.ogg rename to sounds/digtron_truck.ogg diff --git a/sounds/whirr.ogg b/sounds/digtron_whirr.ogg similarity index 100% rename from sounds/whirr.ogg rename to sounds/digtron_whirr.ogg diff --git a/sounds/woopwoopwoop.ogg b/sounds/digtron_woopwoopwoop.ogg similarity index 100% rename from sounds/woopwoopwoop.ogg rename to sounds/digtron_woopwoopwoop.ogg diff --git a/sounds/license.txt b/sounds/license.txt index 1de8114..245e486 100644 --- a/sounds/license.txt +++ b/sounds/license.txt @@ -1,16 +1,16 @@ The sounds in this folder were sampled from source .wavs from Freesound.org. Specifically: -buzzer.ogg - https://freesound.org/people/hypocore/sounds/164090/ - public domain via CC 1.0 by hypocore -construction.ogg - https://www.freesound.org/people/mediapetros/sounds/109117/ - under the CC BY 3.0 license by mediapetros -dingding.ogg - https://www.freesound.org/people/JohnsonBrandEditing/sounds/173932/ public domain via CC 1.0 by JohnsonBrandEditing -honk.ogg - https://freesound.org/people/bigmanjoe/sounds/349922/ public domain via CC 1.0 by bigmanjoe -machine1.ogg and machine2.ogg - https://www.freesound.org/people/nuckan/sounds/212941/ public domain via CC 1.0 by nuckan -sploosh.ogg - https://www.freesound.org/people/mr_marcello/sounds/257609/ public domain via CC 1.0 by mr_marcello -squeal.ogg - https://www.freesound.org/people/RutgerMuller/sounds/104026/ public domain via CC 1.0 by RutgerMuller -truck.ogg - https://www.freesound.org/people/jberkuta14/sounds/134898/ public domain via CC 1.0 by jberkuta14 -whirr.ogg - https://www.freesound.org/people/daveincamas/sounds/25034/ - under the CC BY 3.0 license by daveincamas -woopwoopwoop.ogg - https://www.freesound.org/people/gregconquest/sounds/188012/ public domain via CC 1.0 by gregconquest -steam_puff.ogg - https://freesound.org/people/Aiwha/sounds/250703/ under the CC BY 3.0 license by Aiwha +digtron_buzzer.ogg - https://freesound.org/people/hypocore/sounds/164090/ - public domain via CC 1.0 by hypocore +digtron_construction.ogg - https://www.freesound.org/people/mediapetros/sounds/109117/ - under the CC BY 3.0 license by mediapetros +digtron_dingding.ogg - https://www.freesound.org/people/JohnsonBrandEditing/sounds/173932/ public domain via CC 1.0 by JohnsonBrandEditing +digtron_honk.ogg - https://freesound.org/people/bigmanjoe/sounds/349922/ public domain via CC 1.0 by bigmanjoe +digtron_machine_assemble.ogg and digtron_machine_disassemble.ogg - https://www.freesound.org/people/nuckan/sounds/212941/ public domain via CC 1.0 by nuckan +digtron_sploosh.ogg - https://www.freesound.org/people/mr_marcello/sounds/257609/ public domain via CC 1.0 by mr_marcello +digtron_squeal.ogg - https://www.freesound.org/people/RutgerMuller/sounds/104026/ public domain via CC 1.0 by RutgerMuller +digtron_truck.ogg - https://www.freesound.org/people/jberkuta14/sounds/134898/ public domain via CC 1.0 by jberkuta14 +digtron_whirr.ogg - https://www.freesound.org/people/daveincamas/sounds/25034/ - under the CC BY 3.0 license by daveincamas +digtron_woopwoopwoop.ogg - https://www.freesound.org/people/gregconquest/sounds/188012/ public domain via CC 1.0 by gregconquest +digtron_steam_puff.ogg - https://freesound.org/people/Aiwha/sounds/250703/ under the CC BY 3.0 license by Aiwha Creative Commons Attribution 3.0 license: