mirror of
https://github.com/minetest-mods/digtron.git
synced 2024-08-19 20:34:04 +02:00
implement rotation. Broke builders in the process.
This commit is contained in:
parent
861d9b275c
commit
e63f016fc3
@ -58,13 +58,13 @@ local get_controller_assembled_formspec = function(digtron_id, player_name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local inv_tab = function(inv_list)
|
local inv_tab = function(inv_list)
|
||||||
return "size[9,9]"
|
return "size[8,9]"
|
||||||
.. "position[0.025,0.1]"
|
.. "position[0.025,0.1]"
|
||||||
.. "anchor[0,0]"
|
.. "anchor[0,0]"
|
||||||
.. "container[0.5,0]"
|
.. "container[0,0]"
|
||||||
.. "list[detached:" .. digtron_id .. ";"..inv_list..";0,0;8,4]" -- TODO: paging system for inventory
|
.. "list[detached:" .. digtron_id .. ";"..inv_list..";0,0;8,4]" -- TODO: paging system for inventory
|
||||||
.. "container_end[]"
|
.. "container_end[]"
|
||||||
.. "container[0.5,5]list[current_player;main;0,0;8,1;]list[current_player;main;0,1.25;8,3;8]container_end[]"
|
.. "container[0,5]list[current_player;main;0,0;8,1;]list[current_player;main;0,1.25;8,3;8]container_end[]"
|
||||||
.. "listring[current_player;main]"
|
.. "listring[current_player;main]"
|
||||||
.. "listring[detached:" .. digtron_id .. ";"..inv_list.."]"
|
.. "listring[detached:" .. digtron_id .. ";"..inv_list.."]"
|
||||||
end
|
end
|
||||||
@ -94,16 +94,14 @@ local get_controller_assembled_formspec = function(digtron_id, player_name)
|
|||||||
.. "container[4,1]"
|
.. "container[4,1]"
|
||||||
.. "box[0,0;3,2;#CCCCCC]"
|
.. "box[0,0;3,2;#CCCCCC]"
|
||||||
.. "label[1.3,0.825;Rotate]"
|
.. "label[1.3,0.825;Rotate]"
|
||||||
.. "button[0.1,0.1;1,1;rot_clockwise;Clockwise]"
|
.. "button[0.1,0.1;1,1;rot_counterclockwise;Widdershins]"
|
||||||
.. "button[2.1,0.1;1,1;rot_counterclockwise;Widdershins]"
|
.. "button[2.1,0.1;1,1;rot_clockwise;Clockwise]"
|
||||||
.. "button[1.1,0.1;1,1;rot_up;Pitch Up]"
|
.. "button[1.1,0.1;1,1;rot_up;Pitch Up]"
|
||||||
.. "button[1.1,1.1;1,1;rot_down;Pitch Down]"
|
.. "button[1.1,1.1;1,1;rot_down;Pitch Down]"
|
||||||
.. "button[0.1,1.1;1,1;rot_left;Yaw Left]"
|
.. "button[0.1,1.1;1,1;rot_left;Yaw Left]"
|
||||||
.. "button[2.1,1.1;1,1;rot_right;Yaw Right]"
|
.. "button[2.1,1.1;1,1;rot_right;Yaw Right]"
|
||||||
.. "container_end[]"
|
.. "container_end[]"
|
||||||
|
|
||||||
|
|
||||||
minetest.chat_send_all(dump(context))
|
|
||||||
if context.current_tab == 1 then
|
if context.current_tab == 1 then
|
||||||
return controls .. tabs
|
return controls .. tabs
|
||||||
else
|
else
|
||||||
@ -141,32 +139,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
local get_down = function(facedir)
|
|
||||||
local top = {
|
|
||||||
[0]={x=0,y=-1,z=0},
|
|
||||||
{x=0,y=0,z=1},
|
|
||||||
{x=0,y=0,z=-1},
|
|
||||||
{x=1,y=0,y=0},
|
|
||||||
{x=-1,y=0,z=0},
|
|
||||||
{x=0,y=1,z=0},
|
|
||||||
}
|
|
||||||
return top[math.floor(facedir/4)]
|
|
||||||
end
|
|
||||||
function crossProduct( a, b )
|
|
||||||
local x, y, z
|
|
||||||
x = a.y * (b.z or 0) - (a.z or 0) * b.y
|
|
||||||
y = (a.z or 0) * b.x - a.x * (b.z or 0)
|
|
||||||
z = a.x * b.y - a.y * b.x
|
|
||||||
return { x=x, y=y, z=z }
|
|
||||||
end
|
|
||||||
local facedir_to_right = {}
|
|
||||||
for i = 0, 23 do
|
|
||||||
local dir = minetest.facedir_to_dir(i)
|
|
||||||
local down = get_down(i)
|
|
||||||
facedir_to_right[i] = crossProduct(dir, down)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Controlling a fully armed and operational Digtron
|
-- Controlling a fully armed and operational Digtron
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
if formname ~= "digtron:controller_assembled" then
|
if formname ~= "digtron:controller_assembled" then
|
||||||
@ -175,15 +147,29 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
local player_name = player:get_player_name()
|
local player_name = player:get_player_name()
|
||||||
local context = player_interacting_with_digtron_id[player_name]
|
local context = player_interacting_with_digtron_id[player_name]
|
||||||
if context == nil then
|
if context == nil then
|
||||||
|
minetest.chat_send_all("no context")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local digtron_id = context.digtron_id
|
local digtron_id = context.digtron_id
|
||||||
if digtron_id == nil then
|
if digtron_id == nil then
|
||||||
|
minetest.chat_send_all("no id")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos = digtron.get_pos(digtron_id)
|
||||||
|
if pos == nil then
|
||||||
|
minetest.chat_send_all("no pos")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if node.name ~= "digtron:controller" then
|
||||||
|
minetest.chat_send_all("not controller " .. node.name .. " " .. minetest.pos_to_string(pos))
|
||||||
|
-- this happened somehow in testing, Digtron needs to be able to recover from this situation.
|
||||||
|
-- TODO catch this on_rightclick and try remapping the layout to the new position.
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local refresh = false
|
local refresh = false
|
||||||
|
|
||||||
if fields.tab_header then
|
if fields.tab_header then
|
||||||
local new_tab = tonumber(fields.tab_header)
|
local new_tab = tonumber(fields.tab_header)
|
||||||
if new_tab <= #(context.tabs) + 1 then
|
if new_tab <= #(context.tabs) + 1 then
|
||||||
@ -204,25 +190,33 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local pos = digtron.get_pos(digtron_id)
|
|
||||||
if pos then
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
if node.name == "digtron:controller" then
|
|
||||||
local facedir = node.param2
|
local facedir = node.param2
|
||||||
|
-- Translation
|
||||||
if fields.move_forward then
|
if fields.move_forward then
|
||||||
digtron.move(digtron_id, vector.add(pos, minetest.facedir_to_dir(facedir)), player_name)
|
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_dir(facedir)), player_name)
|
||||||
elseif fields.move_back then
|
elseif fields.move_back then
|
||||||
digtron.move(digtron_id, vector.add(pos, vector.multiply(minetest.facedir_to_dir(facedir), -1)), player_name)
|
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_dir(facedir), -1)), player_name)
|
||||||
elseif fields.move_up then
|
elseif fields.move_up then
|
||||||
digtron.move(digtron_id, vector.add(pos, vector.multiply(get_down(facedir), -1)), player_name)
|
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_up(facedir)), player_name)
|
||||||
elseif fields.move_down then
|
elseif fields.move_down then
|
||||||
digtron.move(digtron_id, vector.add(pos, get_down(facedir)), player_name)
|
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_up(facedir), -1)), player_name)
|
||||||
elseif fields.move_left then
|
elseif fields.move_left then
|
||||||
digtron.move(digtron_id, vector.add(pos, vector.multiply(facedir_to_right[facedir % 23], -1)), player_name)
|
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_right(facedir), -1)), player_name)
|
||||||
elseif fields.move_right then
|
elseif fields.move_right then
|
||||||
digtron.move(digtron_id, vector.add(pos, facedir_to_right[facedir % 23]), player_name)
|
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_right(facedir)), player_name)
|
||||||
end
|
-- Rotation
|
||||||
end
|
elseif fields.rot_counterclockwise then
|
||||||
|
digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_dir(facedir), -1), player_name)
|
||||||
|
elseif fields.rot_clockwise then
|
||||||
|
digtron.rotate(digtron_id, digtron.facedir_to_dir(facedir), player_name)
|
||||||
|
elseif fields.rot_up then
|
||||||
|
digtron.rotate(digtron_id, digtron.facedir_to_right(facedir), player_name)
|
||||||
|
elseif fields.rot_down then
|
||||||
|
digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_right(facedir), -1), player_name)
|
||||||
|
elseif fields.rot_left then
|
||||||
|
digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_up(facedir), -1), player_name)
|
||||||
|
elseif fields.rot_right then
|
||||||
|
digtron.rotate(digtron_id, digtron.facedir_to_up(facedir), player_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields.test_dig then
|
if fields.test_dig then
|
||||||
@ -244,7 +238,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
"digtron:controller_assembled",
|
"digtron:controller_assembled",
|
||||||
get_controller_assembled_formspec(digtron_id, player_name))
|
get_controller_assembled_formspec(digtron_id, player_name))
|
||||||
end
|
end
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
147
functions.lua
147
functions.lua
@ -29,7 +29,7 @@ digtron.retrieve_inventory = retrieve_inventory -- used by formspecs
|
|||||||
--------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
local create_new_id = function()
|
local create_new_id = function()
|
||||||
local digtron_id = "digtron" .. tostring(math.random(1, 2^21)) -- TODO: use SecureRandom()
|
local digtron_id = "digtron" .. tostring(math.random(1, 2^21))
|
||||||
-- It's super unlikely that we'll get a collision, but what the heck - maybe something will go
|
-- It's super unlikely that we'll get a collision, but what the heck - maybe something will go
|
||||||
-- wrong with the random number source
|
-- wrong with the random number source
|
||||||
while mod_meta:get_string(digtron_id..":layout") ~= "" do
|
while mod_meta:get_string(digtron_id..":layout") ~= "" do
|
||||||
@ -114,34 +114,10 @@ digtron.get_pos = retrieve_pos
|
|||||||
-------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------
|
||||||
-- Layout creation helpers
|
-- Layout creation helpers
|
||||||
|
|
||||||
local cardinal_dirs = {
|
|
||||||
{x= 0, y=0, z= 1},
|
|
||||||
{x= 1, y=0, z= 0},
|
|
||||||
{x= 0, y=0, z=-1},
|
|
||||||
{x=-1, y=0, z= 0},
|
|
||||||
{x= 0, y=-1, z= 0},
|
|
||||||
{x= 0, y=1, z= 0},
|
|
||||||
}
|
|
||||||
digtron.cardinal_dirs = cardinal_dirs -- used by builder entities as well
|
|
||||||
-- Mapping from facedir value to index in cardinal_dirs.
|
|
||||||
local facedir_to_dir_map = digtron.facedir_to_dir_map
|
|
||||||
|
|
||||||
-- Turn the cardinal directions into a set of integers you can add to a hash to step in that direction.
|
|
||||||
local cardinal_dirs_hash = {}
|
|
||||||
for i, dir in ipairs(cardinal_dirs) do
|
|
||||||
cardinal_dirs_hash[i] = minetest.hash_node_position(dir) - minetest.hash_node_position({x=0, y=0, z=0})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Given a facedir, returns an index into either cardinal_dirs or cardinal_dirs_hash that
|
|
||||||
-- can be used to determine what this node is "aimed" at
|
|
||||||
local facedir_to_dir_index = function(param2)
|
|
||||||
return facedir_to_dir_map[param2 % 32]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- recursive function searches out all connected unassigned digtron nodes
|
-- recursive function searches out all connected unassigned digtron nodes
|
||||||
local get_all_digtron_nodes
|
local get_all_digtron_nodes
|
||||||
get_all_digtron_nodes = function(pos, digtron_nodes, digtron_adjacent, player_name)
|
get_all_digtron_nodes = function(pos, digtron_nodes, digtron_adjacent, player_name)
|
||||||
for _, dir in ipairs(cardinal_dirs) do
|
for _, dir in ipairs(digtron.cardinal_dirs) do
|
||||||
local test_pos = vector.add(pos, dir)
|
local test_pos = vector.add(pos, dir)
|
||||||
local test_hash = minetest.hash_node_position(test_pos)
|
local test_hash = minetest.hash_node_position(test_pos)
|
||||||
if not (digtron_nodes[test_hash] or digtron_adjacent[test_hash]) then -- don't test twice
|
if not (digtron_nodes[test_hash] or digtron_adjacent[test_hash]) then -- don't test twice
|
||||||
@ -204,15 +180,15 @@ local refresh_adjacent = function(digtron_id)
|
|||||||
local adjacent_to_diggers = {}
|
local adjacent_to_diggers = {}
|
||||||
local adjacent_to_builders = {}
|
local adjacent_to_builders = {}
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
for _, dir_hash in ipairs(cardinal_dirs_hash) do
|
for _, dir_hash in ipairs(digtron.cardinal_dirs_hash) do
|
||||||
local potential_adjacent = hash+dir_hash
|
local potential_adjacent = hash + dir_hash
|
||||||
if layout[potential_adjacent] == nil then
|
if layout[potential_adjacent] == nil then
|
||||||
adjacent[potential_adjacent] = true
|
adjacent[potential_adjacent] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if minetest.get_item_group(data.node.name, "digtron") == 3 then
|
if minetest.get_item_group(data.node.name, "digtron") == 3 then
|
||||||
local dir_hash = cardinal_dirs_hash[facedir_to_dir_index(data.node.param2)]
|
local dir_hash = digtron.facedir_to_dir_hash(data.node.param2)
|
||||||
local potential_target = hash + dir_hash -- pointed at this hash
|
local potential_target = hash + dir_hash -- pointed at this hash
|
||||||
if layout[potential_target] == nil then -- not pointed at another Digtron node
|
if layout[potential_target] == nil then -- not pointed at another Digtron node
|
||||||
local fields = data.meta.fields
|
local fields = data.meta.fields
|
||||||
@ -224,7 +200,7 @@ local refresh_adjacent = function(digtron_id)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if minetest.get_item_group(data.node.name, "digtron") == 4 then
|
if minetest.get_item_group(data.node.name, "digtron") == 4 then
|
||||||
local dir_hash = cardinal_dirs_hash[facedir_to_dir_index(data.node.param2)]
|
local dir_hash = digtron.facedir_to_dir_hash(data.node.param2)
|
||||||
local potential_target = hash + dir_hash
|
local potential_target = hash + dir_hash
|
||||||
if layout[potential_target] == nil then
|
if layout[potential_target] == nil then
|
||||||
local fields = data.meta.fields
|
local fields = data.meta.fields
|
||||||
@ -307,7 +283,8 @@ digtron.assemble = function(root_pos, player_name)
|
|||||||
local layout = {}
|
local layout = {}
|
||||||
|
|
||||||
for hash, node in pairs(digtron_nodes) do
|
for hash, node in pairs(digtron_nodes) do
|
||||||
local relative_hash = hash - root_hash
|
local relative_hash = minetest.hash_node_position(vector.subtract(minetest.get_position_from_hash(hash), root_pos))
|
||||||
|
|
||||||
local current_meta
|
local current_meta
|
||||||
if hash == root_hash then
|
if hash == root_hash then
|
||||||
current_meta = root_meta -- we're processing the controller, we already have a reference to its meta
|
current_meta = root_meta -- we're processing the controller, we already have a reference to its meta
|
||||||
@ -385,9 +362,8 @@ end
|
|||||||
|
|
||||||
-- Returns pos, node, and meta for the digtron node provided the in-world node matches the layout
|
-- Returns pos, node, and meta for the digtron node provided the in-world node matches the layout
|
||||||
-- returns nil otherwise
|
-- returns nil otherwise
|
||||||
local get_valid_data = function(digtron_id, root_hash, hash, data, function_name)
|
local get_valid_data = function(digtron_id, root_pos, hash, data, function_name)
|
||||||
local node_hash = hash + root_hash -- TODO may want to return this as well?
|
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
|
||||||
local node_pos = minetest.get_position_from_hash(node_hash)
|
|
||||||
local node = minetest.get_node(node_pos)
|
local node = minetest.get_node(node_pos)
|
||||||
local node_meta = minetest.get_meta(node_pos)
|
local node_meta = minetest.get_meta(node_pos)
|
||||||
local target_digtron_id = node_meta:get_string("digtron_id")
|
local target_digtron_id = node_meta:get_string("digtron_id")
|
||||||
@ -440,11 +416,9 @@ digtron.disassemble = function(digtron_id, player_name)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local root_hash = minetest.hash_node_position(root_pos)
|
|
||||||
|
|
||||||
-- Write metadata and inventory to in-world node at this location
|
-- Write metadata and inventory to in-world node at this location
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
local node_pos, node, node_meta = get_valid_data(digtron_id, root_hash, hash, data, "digtron.disassemble")
|
local node_pos, node, node_meta = get_valid_data(digtron_id, root_pos, hash, data, "digtron.disassemble")
|
||||||
|
|
||||||
if node_pos then
|
if node_pos then
|
||||||
local node_inv = node_meta:get_inventory()
|
local node_inv = node_meta:get_inventory()
|
||||||
@ -515,10 +489,9 @@ digtron.remove_from_world = function(digtron_id, player_name)
|
|||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local root_hash = minetest.hash_node_position(root_pos)
|
|
||||||
local nodes_to_destroy = {}
|
local nodes_to_destroy = {}
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
local node_pos = get_valid_data(digtron_id, root_hash, hash, data, "digtron.destroy")
|
local node_pos = get_valid_data(digtron_id, root_pos, hash, data, "digtron.remove_from_world")
|
||||||
if node_pos then
|
if node_pos then
|
||||||
table.insert(nodes_to_destroy, node_pos)
|
table.insert(nodes_to_destroy, node_pos)
|
||||||
end
|
end
|
||||||
@ -542,12 +515,12 @@ digtron.is_buildable_to = function(digtron_id, root_pos, player_name, ignore_nod
|
|||||||
|
|
||||||
-- If this digtron is already in-world, we're likely testing as part of a movement attempt.
|
-- 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
|
-- Record its existing node locations, they will be treated as buildable_to
|
||||||
local old_pos = retrieve_pos(digtron_id)
|
local old_root_pos = retrieve_pos(digtron_id)
|
||||||
local ignore_hashes = {}
|
local ignore_hashes = {}
|
||||||
if old_pos then
|
if old_root_pos then
|
||||||
local old_root_hash = minetest.hash_node_position(old_pos)
|
for hash, _ in pairs(layout) do
|
||||||
for layout_hash, _ in pairs(layout) do
|
local old_hash = minetest.hash_node_position(vector.add(minetest.get_position_from_hash(hash), old_root_pos))
|
||||||
ignore_hashes[layout_hash + old_root_hash] = true
|
ignore_hashes[old_hash] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ignore_nodes then
|
if ignore_nodes then
|
||||||
@ -556,15 +529,14 @@ digtron.is_buildable_to = function(digtron_id, root_pos, player_name, ignore_nod
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local root_hash = minetest.hash_node_position(root_pos)
|
|
||||||
local succeeded = {}
|
local succeeded = {}
|
||||||
local failed = {}
|
local failed = {}
|
||||||
local permitted = true
|
local permitted = true
|
||||||
|
|
||||||
for layout_hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
-- Don't use get_valid_data, the Digtron isn't in-world yet
|
-- Don't use get_valid_data, the Digtron isn't in-world yet
|
||||||
local node_hash = layout_hash + root_hash
|
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
|
||||||
local node_pos = minetest.get_position_from_hash(node_hash)
|
local node_hash = minetest.hash_node_position(node_pos)
|
||||||
local node = minetest.get_node(node_pos)
|
local node = minetest.get_node(node_pos)
|
||||||
local node_def = minetest.registered_nodes[node.name]
|
local node_def = minetest.registered_nodes[node.name]
|
||||||
-- TODO: lots of testing needed here
|
-- TODO: lots of testing needed here
|
||||||
@ -590,11 +562,10 @@ end
|
|||||||
-- Places the Digtron into the world.
|
-- Places the Digtron into the world.
|
||||||
digtron.build_to_world = function(digtron_id, root_pos, player_name)
|
digtron.build_to_world = function(digtron_id, root_pos, player_name)
|
||||||
local layout = retrieve_layout(digtron_id)
|
local layout = retrieve_layout(digtron_id)
|
||||||
local root_hash = minetest.hash_node_position(root_pos)
|
|
||||||
|
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
-- Don't use get_valid_data, the Digtron isn't in-world yet
|
-- Don't use get_valid_data, the Digtron isn't in-world yet
|
||||||
local node_pos = minetest.get_position_from_hash(hash + root_hash)
|
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
|
||||||
minetest.set_node(node_pos, data.node)
|
minetest.set_node(node_pos, data.node)
|
||||||
local meta = minetest.get_meta(node_pos)
|
local meta = minetest.get_meta(node_pos)
|
||||||
for field, value in pairs(data.meta.fields) do
|
for field, value in pairs(data.meta.fields) do
|
||||||
@ -623,6 +594,61 @@ digtron.move = function(digtron_id, dest_pos, player_name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Rotation
|
||||||
|
|
||||||
|
local rotate_layout = function(digtron_id, axis)
|
||||||
|
local layout = retrieve_layout(digtron_id)
|
||||||
|
local axis_hash = minetest.hash_node_position(axis)
|
||||||
|
local rotated_layout = {}
|
||||||
|
for hash, data in pairs(layout) do
|
||||||
|
-- Facings
|
||||||
|
local node_name = data.node.name
|
||||||
|
local node_def = minetest.registered_nodes[node_name]
|
||||||
|
if node_def.paramtype2 == "wallmounted" then
|
||||||
|
data.node.param2 = digtron.rotate_wallmounted(axis_hash, data.node.param2)
|
||||||
|
elseif node_def.paramtype2 == "facedir" then
|
||||||
|
data.node.param2 = digtron.rotate_facedir(axis_hash, data.node.param2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Rotate builder item facings
|
||||||
|
if minetest.get_item_group(node_name, "digtron") == 4 then
|
||||||
|
local build_item = data.meta.fields.item
|
||||||
|
local build_item_def = minetest.registered_items[build_item]
|
||||||
|
if build_item_def.paramtype2 == "wallmounted" then
|
||||||
|
data.meta.fields.facing = digtron.rotate_wallmounted(axis_hash, tonumber(data.meta.fields.facing))
|
||||||
|
elseif build_item_def.paramtype2 == "facedir" then
|
||||||
|
data.meta.fields.facing = digtron.rotate_facedir(axis_hash, tonumber(data.meta.fields.facing))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Position
|
||||||
|
local pos = minetest.get_position_from_hash(hash)
|
||||||
|
pos = digtron.rotate_pos(axis_hash, pos)
|
||||||
|
local new_hash = minetest.hash_node_position(pos)
|
||||||
|
rotated_layout[new_hash] = data
|
||||||
|
end
|
||||||
|
|
||||||
|
invalidate_layout_cache(digtron_id)
|
||||||
|
persist_layout(digtron_id, rotated_layout)
|
||||||
|
end
|
||||||
|
|
||||||
|
digtron.rotate = function(digtron_id, axis, player_name)
|
||||||
|
-- TODO: rotation version of is_buildable_to
|
||||||
|
local root_pos = retrieve_pos(digtron_id)
|
||||||
|
local removed = digtron.remove_from_world(digtron_id, player_name)
|
||||||
|
rotate_layout(digtron_id, axis)
|
||||||
|
digtron.build_to_world(digtron_id, root_pos, player_name)
|
||||||
|
-- Don't need to do fancy callback checking for digtron nodes since I made all those
|
||||||
|
-- nodes and I know they don't have anything that needs to be done for them.
|
||||||
|
-- Just check for falling nodes.
|
||||||
|
for _, removed_pos in ipairs(removed) do
|
||||||
|
minetest.check_for_falling(removed_pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------
|
||||||
-- Digging
|
-- Digging
|
||||||
|
|
||||||
@ -634,14 +660,13 @@ local predict_dig = function(digtron_id, player_name, controlling_coordinate)
|
|||||||
.."a predictive inventory or a root position for " .. digtron_id)
|
.."a predictive inventory or a root position for " .. digtron_id)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local root_hash = minetest.hash_node_position(root_pos)
|
|
||||||
|
|
||||||
local leftovers = {}
|
local leftovers = {}
|
||||||
local dug_positions = {}
|
local dug_positions = {}
|
||||||
local cost = 0
|
local cost = 0
|
||||||
|
|
||||||
for target_hash, digger_data in pairs(retrieve_all_digger_targets(digtron_id)) do
|
for target_hash, digger_data in pairs(retrieve_all_digger_targets(digtron_id)) do
|
||||||
local target_pos = minetest.get_position_from_hash(target_hash + root_hash + digger_data.dir_hash)
|
local target_pos = vector.add(minetest.get_position_from_hash(target_hash + digger_data.dir_hash), root_pos)
|
||||||
local target_node = minetest.get_node(target_pos)
|
local target_node = minetest.get_node(target_pos)
|
||||||
local target_name = target_node.name
|
local target_name = target_node.name
|
||||||
local targetdef = minetest.registered_nodes[target_name]
|
local targetdef = minetest.registered_nodes[target_name]
|
||||||
@ -751,15 +776,14 @@ end
|
|||||||
------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------
|
||||||
-- Building
|
-- Building
|
||||||
|
|
||||||
-- need to provide new_pos because Digtron moves before building
|
-- need to provide root_pos because Digtron moves before building
|
||||||
local predict_build = function(digtron_id, new_pos, player_name, ignore_nodes, controlling_coordinate)
|
local predict_build = function(digtron_id, root_pos, player_name, ignore_nodes, controlling_coordinate)
|
||||||
local predictive_inv = get_predictive_inventory(digtron_id)
|
local predictive_inv = get_predictive_inventory(digtron_id)
|
||||||
if not predictive_inv then
|
if not predictive_inv then
|
||||||
minetest.log("error", "[Digtron] predict_build failed to retrieve "
|
minetest.log("error", "[Digtron] predict_build failed to retrieve "
|
||||||
.."a predictive inventory for " .. digtron_id)
|
.."a predictive inventory for " .. digtron_id)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local root_hash = minetest.hash_node_position(new_pos)
|
|
||||||
|
|
||||||
local ignore_hashes = {}
|
local ignore_hashes = {}
|
||||||
if ignore_nodes then
|
if ignore_nodes then
|
||||||
@ -773,11 +797,10 @@ local predict_build = function(digtron_id, new_pos, player_name, ignore_nodes, c
|
|||||||
local cost = 0
|
local cost = 0
|
||||||
|
|
||||||
for target_hash, builder_data in pairs(retrieve_all_builder_targets(digtron_id)) do
|
for target_hash, builder_data in pairs(retrieve_all_builder_targets(digtron_id)) do
|
||||||
local absolute_hash = target_hash + root_hash
|
|
||||||
local dir_hash = builder_data.dir_hash
|
local dir_hash = builder_data.dir_hash
|
||||||
local periodicity_permitted = nil
|
local periodicity_permitted = nil
|
||||||
for i = 1, builder_data.extrusion do
|
for i = 1, builder_data.extrusion do
|
||||||
local target_pos = minetest.get_position_from_hash(absolute_hash + i * dir_hash)
|
local target_pos = vector.add(minetest.get_position_from_hash(target_hash + i * dir_hash), root_pos)
|
||||||
if periodicity_permitted == nil then
|
if periodicity_permitted == nil then
|
||||||
-- test periodicity and offset once
|
-- test periodicity and offset once
|
||||||
periodicity_permitted = (target_pos[controlling_coordinate] + builder_data.offset) % builder_data.period == 0
|
periodicity_permitted = (target_pos[controlling_coordinate] + builder_data.offset) % builder_data.period == 0
|
||||||
@ -883,7 +906,7 @@ 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.
|
-- 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.
|
||||||
local get_controlling_coordinate = function(facedir)
|
local get_controlling_coordinate = function(facedir)
|
||||||
-- used for determining builder period and offset
|
-- used for determining builder period and offset
|
||||||
local dir = facedir_to_dir_map[facedir]
|
local dir = digtron.facedir_to_dir_map[facedir]
|
||||||
if dir == 1 or dir == 3 then
|
if dir == 1 or dir == 3 then
|
||||||
return "z"
|
return "z"
|
||||||
elseif dir == 2 or dir == 4 then
|
elseif dir == 2 or dir == 4 then
|
||||||
@ -913,7 +936,7 @@ digtron.execute_cycle = function(digtron_id, player_name)
|
|||||||
local controlling_coordinate = get_controlling_coordinate(root_facedir)
|
local controlling_coordinate = get_controlling_coordinate(root_facedir)
|
||||||
|
|
||||||
local dig_leftovers, nodes_to_dig, dig_cost = predict_dig(digtron_id, player_name, controlling_coordinate)
|
local dig_leftovers, nodes_to_dig, dig_cost = predict_dig(digtron_id, player_name, controlling_coordinate)
|
||||||
local new_root_pos = vector.add(old_root_pos, cardinal_dirs[facedir_to_dir_index(root_facedir)])
|
local new_root_pos = vector.add(old_root_pos, digtron.facedir_to_dir(root_facedir))
|
||||||
-- TODO: convert nodes_to_dig into a hash map here and pass that in to reduce duplication?
|
-- TODO: convert nodes_to_dig into a hash map here and pass that in to reduce duplication?
|
||||||
local buildable_to, succeeded, failed = digtron.is_buildable_to(digtron_id, new_root_pos, player_name, nodes_to_dig)
|
local buildable_to, succeeded, failed = digtron.is_buildable_to(digtron_id, new_root_pos, player_name, nodes_to_dig)
|
||||||
local missing_items, built_nodes, build_cost = predict_build(digtron_id, new_root_pos, player_name, nodes_to_dig, controlling_coordinate)
|
local missing_items, built_nodes, build_cost = predict_build(digtron_id, new_root_pos, player_name, nodes_to_dig, controlling_coordinate)
|
||||||
@ -952,7 +975,7 @@ digtron.execute_cycle = function(digtron_id, player_name)
|
|||||||
else
|
else
|
||||||
clear_predictive_inventory(digtron_id)
|
clear_predictive_inventory(digtron_id)
|
||||||
digtron.show_buildable_nodes({}, failed)
|
digtron.show_buildable_nodes({}, failed)
|
||||||
minetest.sound_play("digtron_squeal", {gain = 0.5, pos=new_pos})
|
minetest.sound_play("digtron_squeal", {gain = 0.5, pos=new_root_pos})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -989,9 +1012,7 @@ digtron.can_dig = function(pos, digger)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local root_hash = minetest.hash_node_position(root_pos)
|
local layout_hash = minetest.hash_node_position(vector.subtract(pos, root_pos))
|
||||||
local here_hash = minetest.hash_node_position(pos)
|
|
||||||
local layout_hash = here_hash - root_hash
|
|
||||||
local layout_data = layout[layout_hash]
|
local layout_data = layout[layout_hash]
|
||||||
if layout_data == nil or layout_data.node == nil then
|
if layout_data == nil or layout_data.node == nil then
|
||||||
minetest.log("error", "[Digtron] can_dig was called on a " .. node.name .. " at location "
|
minetest.log("error", "[Digtron] can_dig was called on a " .. node.name .. " at location "
|
||||||
|
146
geometry.lua
Normal file
146
geometry.lua
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
local cardinal_dirs = {
|
||||||
|
{x = 0, y = 0, z = 1},
|
||||||
|
{x = 1, y = 0, z = 0},
|
||||||
|
{x = 0, y = 0, z = -1},
|
||||||
|
{x = -1, y = 0, z = 0},
|
||||||
|
{x = 0, y = -1, z = 0},
|
||||||
|
{x = 0, y = 1, z = 0},
|
||||||
|
}
|
||||||
|
-- Turn the cardinal directions into a set of integers you can add to a hash to step in that direction.
|
||||||
|
local cardinal_dirs_hash = {}
|
||||||
|
for i, dir in ipairs(cardinal_dirs) do
|
||||||
|
cardinal_dirs_hash[i] = minetest.hash_node_position(dir) - minetest.hash_node_position({x = 0, y = 0, z = 0})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mapping from facedir value to index in cardinal_dirs.
|
||||||
|
local 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 facedir_to_up_map = {
|
||||||
|
[0] = 6, 6, 6, 6,
|
||||||
|
3, 3, 3, 3,
|
||||||
|
1, 1, 1, 1,
|
||||||
|
4, 4, 4, 4,
|
||||||
|
2, 2, 2, 2,
|
||||||
|
5, 5, 5, 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
local facedir_to_right_map = {
|
||||||
|
[0] = 2, 3, 4, 1,
|
||||||
|
2, 6, 4, 6,
|
||||||
|
2, 5, 4, 6,
|
||||||
|
5, 3, 6, 1,
|
||||||
|
6, 3, 5, 1,
|
||||||
|
4, 3, 2, 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
local facedir_to_dir = function(facedir)
|
||||||
|
return cardinal_dirs[facedir_to_dir_map[facedir % 32]]
|
||||||
|
end
|
||||||
|
local facedir_to_dir_hash = function(facedir)
|
||||||
|
return cardinal_dirs_hash[facedir_to_dir_map[facedir % 32]]
|
||||||
|
end
|
||||||
|
local facedir_to_up = function(facedir)
|
||||||
|
return cardinal_dirs[facedir_to_up_map[facedir % 32]]
|
||||||
|
end
|
||||||
|
local facedir_to_up_hash = function(facedir)
|
||||||
|
return cardinal_dirs_hash[facedir_to_up_map[facedir % 32]]
|
||||||
|
end
|
||||||
|
local facedir_to_right = function(facedir)
|
||||||
|
return cardinal_dirs[facedir_to_right_map[facedir % 32]]
|
||||||
|
end
|
||||||
|
local facedir_to_right_hash = function(facedir)
|
||||||
|
return cardinal_dirs_hash[facedir_to_right_map[facedir % 32]]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Rotation
|
||||||
|
|
||||||
|
local negative_x = minetest.hash_node_position({x = -1, y = 0, z = 0})
|
||||||
|
local positive_x = minetest.hash_node_position({x = 1, y = 0, z = 0})
|
||||||
|
local negative_y = minetest.hash_node_position({x = 0, y = -1, z = 0})
|
||||||
|
local positive_y = minetest.hash_node_position({x = 0, y = 1, z = 0})
|
||||||
|
local negative_z = minetest.hash_node_position({x = 0, y = 0, z = -1})
|
||||||
|
local positive_z = minetest.hash_node_position({x = 0, y = 0, z = 1})
|
||||||
|
|
||||||
|
local facedir_rot = {
|
||||||
|
[negative_x] = {[0] = 4, 5, 6, 7, 22, 23, 20, 21, 0, 1, 2, 3, 13, 14, 15, 12, 19, 16, 17, 18, 10, 11, 8, 9}, -- 270 degrees
|
||||||
|
[positive_x] = {[0] = 8, 9, 10, 11, 0, 1, 2, 3, 22, 23, 20, 21, 15, 12, 13, 14, 17, 18, 19, 16, 6, 7, 4, 5}, -- 90 degrees
|
||||||
|
[negative_y] = {[0] = 3, 0, 1, 2, 19, 16, 17, 18, 15, 12, 13, 14, 7, 4, 5, 6, 11, 8, 9, 10, 21, 22, 23, 20}, -- 270 degrees
|
||||||
|
[positive_y] = {[0] = 1, 2, 3, 0, 13, 14, 15, 12, 17, 18, 19, 16, 9, 10, 11, 8, 5, 6, 7, 4, 23, 20, 21, 22}, -- 90 degrees
|
||||||
|
[negative_z] = {[0] = 16, 17, 18, 19, 5, 6, 7, 4, 11, 8, 9, 10, 0, 1, 2, 3, 20, 21, 22, 23, 12, 13, 14, 15}, -- 270 degrees
|
||||||
|
[positive_z] = {[0] = 12, 13, 14, 15, 7, 4, 5, 6, 9, 10, 11, 8, 20, 21, 22, 23, 0, 1, 2, 3, 16, 17, 18, 19}, -- 90 degrees
|
||||||
|
}
|
||||||
|
|
||||||
|
local wallmounted_rot = {
|
||||||
|
[negative_x] = {[0] = 4, 5, 2, 3, 1, 0}, -- 270 degrees
|
||||||
|
[positive_x] = {[0] = 5, 4, 2, 3, 0, 1}, -- 90 degrees
|
||||||
|
[negative_y] = {[0] = 0, 1, 4, 5, 3, 2}, -- 270 degrees
|
||||||
|
[positive_y] = {[0] = 0, 1, 5, 4, 2, 3}, -- 90 degrees
|
||||||
|
[negative_z] = {[0] = 3, 2, 0, 1, 4, 5}, -- 270 degrees
|
||||||
|
[positive_z] = {[0] = 2, 3, 1, 0, 4, 5}, -- 90 degrees
|
||||||
|
}
|
||||||
|
|
||||||
|
local rotate_facedir = function(axis_hash, facedir)
|
||||||
|
return facedir_rot[axis_hash][facedir]
|
||||||
|
end
|
||||||
|
local rotate_wallmounted = function(axis_hash, facedir)
|
||||||
|
return wallmounted_rot[axis_hash][facedir]
|
||||||
|
end
|
||||||
|
|
||||||
|
--90 degrees CW about x-axis: (x, y, z) -> (x, -z, y)
|
||||||
|
--90 degrees CCW about x-axis: (x, y, z) -> (x, z, -y)
|
||||||
|
--90 degrees CW about y-axis: (x, y, z) -> (-z, y, x)
|
||||||
|
--90 degrees CCW about y-axis: (x, y, z) -> (z, y, -x)
|
||||||
|
--90 degrees CW about z-axis: (x, y, z) -> (y, -x, z)
|
||||||
|
--90 degrees CCW about z-axis: (x, y, z) -> (-y, x, z)
|
||||||
|
-- operates directly on the pos vector
|
||||||
|
-- Rotates it around origin
|
||||||
|
local rotate_pos = function(axis_hash, pos)
|
||||||
|
if axis_hash == negative_x and not (pos.y == 0 and pos.z == 0) then
|
||||||
|
local temp_z = pos.z
|
||||||
|
pos.z = pos.y
|
||||||
|
pos.y = -temp_z
|
||||||
|
elseif axis_hash == positive_x and not (pos.y == 0 and pos.z == 0) then
|
||||||
|
local temp_z = pos.z
|
||||||
|
pos.z = -pos.y
|
||||||
|
pos.y = temp_z
|
||||||
|
elseif axis_hash == negative_y and not (pos.x == 0 and pos.z == 0) then
|
||||||
|
local temp_x = pos.x
|
||||||
|
pos.x = -pos.z
|
||||||
|
pos.z = temp_x
|
||||||
|
elseif axis_hash == positive_y and not (pos.x == 0 and pos.z == 0) then
|
||||||
|
local temp_x = pos.x
|
||||||
|
pos.x = pos.z
|
||||||
|
pos.z = -temp_x
|
||||||
|
elseif axis_hash == negative_z and not (pos.x == 0 and pos.y == 0) then
|
||||||
|
local temp_x = pos.x
|
||||||
|
pos.x = -pos.y
|
||||||
|
pos.y = temp_x
|
||||||
|
elseif axis_hash == positive_z and not (pos.x == 0 and pos.y == 0) then
|
||||||
|
local temp_x = pos.x
|
||||||
|
pos.x = pos.y
|
||||||
|
pos.y = -temp_x
|
||||||
|
end
|
||||||
|
return pos
|
||||||
|
end
|
||||||
|
|
||||||
|
digtron.cardinal_dirs = cardinal_dirs -- used by builder entities as well
|
||||||
|
digtron.cardinal_dirs_hash = cardinal_dirs_hash
|
||||||
|
digtron.facedir_to_dir_map = facedir_to_dir_map
|
||||||
|
|
||||||
|
digtron.facedir_to_dir = facedir_to_dir
|
||||||
|
digtron.facedir_to_dir_hash = facedir_to_dir_hash
|
||||||
|
digtron.facedir_to_up = facedir_to_up
|
||||||
|
digtron.facedir_to_up_hash = facedir_to_up_hash
|
||||||
|
digtron.facedir_to_right = facedir_to_right
|
||||||
|
digtron.facedir_to_right_hash = facedir_to_right_hash
|
||||||
|
|
||||||
|
digtron.rotate_pos = rotate_pos
|
||||||
|
digtron.rotate_wallmounted = rotate_wallmounted
|
||||||
|
digtron.rotate_facedir = rotate_facedir
|
1
init.lua
1
init.lua
@ -28,6 +28,7 @@ dofile(modpath.."/class_fakeplayer.lua")
|
|||||||
digtron.fake_player = DigtronFakePlayer.create({x=0,y=0,z=0}, "fake_player") -- since we only need one fake player at a time and it doesn't retain useful state, create a global one and just update it as needed.
|
digtron.fake_player = DigtronFakePlayer.create({x=0,y=0,z=0}, "fake_player") -- since we only need one fake player at a time and it doesn't retain useful state, create a global one and just update it as needed.
|
||||||
dofile(modpath.."/util_item_place_node.lua")
|
dofile(modpath.."/util_item_place_node.lua")
|
||||||
|
|
||||||
|
dofile(modpath.."/geometry.lua")
|
||||||
dofile(modpath.."/entities.lua")
|
dofile(modpath.."/entities.lua")
|
||||||
dofile(modpath.."/functions.lua")
|
dofile(modpath.."/functions.lua")
|
||||||
dofile(modpath.."/controller.lua")
|
dofile(modpath.."/controller.lua")
|
||||||
|
@ -18,16 +18,6 @@
|
|||||||
--See the GNU Lesser General Public License for more details:
|
--See the GNU Lesser General Public License for more details:
|
||||||
--https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
|
--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 has_prefix(str, prefix)
|
local function has_prefix(str, prefix)
|
||||||
return str:sub(1, string.len(prefix)) == prefix
|
return str:sub(1, string.len(prefix)) == prefix
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user