digtron 2.0 can now move

This commit is contained in:
FaceDeer 2019-08-22 21:16:08 -06:00
parent 5d7eea2540
commit c2959998fd
19 changed files with 206 additions and 141 deletions

3
.gitignore vendored

@ -17,6 +17,9 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
# Blender files
*.blend
# =========================
# Operating System Files
# =========================

@ -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

@ -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",

@ -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

@ -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,
})

@ -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",

@ -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: