implement rotation. Broke builders in the process.

This commit is contained in:
FaceDeer 2019-08-27 20:23:02 -06:00
parent 861d9b275c
commit e63f016fc3
5 changed files with 281 additions and 130 deletions

@ -58,13 +58,13 @@ local get_controller_assembled_formspec = function(digtron_id, player_name)
end
local inv_tab = function(inv_list)
return "size[9,9]"
return "size[8,9]"
.. "position[0.025,0.1]"
.. "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
.. "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[detached:" .. digtron_id .. ";"..inv_list.."]"
end
@ -94,16 +94,14 @@ local get_controller_assembled_formspec = function(digtron_id, player_name)
.. "container[4,1]"
.. "box[0,0;3,2;#CCCCCC]"
.. "label[1.3,0.825;Rotate]"
.. "button[0.1,0.1;1,1;rot_clockwise;Clockwise]"
.. "button[2.1,0.1;1,1;rot_counterclockwise;Widdershins]"
.. "button[0.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,1.1;1,1;rot_down;Pitch Down]"
.. "button[0.1,1.1;1,1;rot_left;Yaw Left]"
.. "button[2.1,1.1;1,1;rot_right;Yaw Right]"
.. "container_end[]"
minetest.chat_send_all(dump(context))
if context.current_tab == 1 then
return controls .. tabs
else
@ -141,32 +139,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
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
minetest.register_on_player_receive_fields(function(player, formname, fields)
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 context = player_interacting_with_digtron_id[player_name]
if context == nil then
minetest.chat_send_all("no context")
return
end
local digtron_id = context.digtron_id
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
end
local refresh = false
if fields.tab_header then
local new_tab = tonumber(fields.tab_header)
if new_tab <= #(context.tabs) + 1 then
@ -204,27 +190,35 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
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
if fields.move_forward then
digtron.move(digtron_id, vector.add(pos, minetest.facedir_to_dir(facedir)), player_name)
elseif fields.move_back then
digtron.move(digtron_id, vector.add(pos, vector.multiply(minetest.facedir_to_dir(facedir), -1)), player_name)
elseif fields.move_up then
digtron.move(digtron_id, vector.add(pos, vector.multiply(get_down(facedir), -1)), player_name)
elseif fields.move_down then
digtron.move(digtron_id, vector.add(pos, get_down(facedir)), player_name)
elseif fields.move_left then
digtron.move(digtron_id, vector.add(pos, vector.multiply(facedir_to_right[facedir % 23], -1)), player_name)
elseif fields.move_right then
digtron.move(digtron_id, vector.add(pos, facedir_to_right[facedir % 23]), player_name)
end
end
end
local facedir = node.param2
-- Translation
if fields.move_forward then
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_dir(facedir)), player_name)
elseif fields.move_back then
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_dir(facedir), -1)), player_name)
elseif fields.move_up then
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_up(facedir)), player_name)
elseif fields.move_down then
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_up(facedir), -1)), player_name)
elseif fields.move_left then
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_right(facedir), -1)), player_name)
elseif fields.move_right then
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_right(facedir)), player_name)
-- Rotation
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
if fields.test_dig then
digtron.execute_cycle(digtron_id, player_name)
end
@ -243,8 +237,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
minetest.show_formspec(player_name,
"digtron:controller_assembled",
get_controller_assembled_formspec(digtron_id, player_name))
end
end
end)

@ -29,7 +29,7 @@ digtron.retrieve_inventory = retrieve_inventory -- used by formspecs
--------------------------------------------------------------------------------------
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
-- wrong with the random number source
while mod_meta:get_string(digtron_id..":layout") ~= "" do
@ -114,34 +114,10 @@ digtron.get_pos = retrieve_pos
-------------------------------------------------------------------------------------------------------
-- 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
local get_all_digtron_nodes
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_hash = minetest.hash_node_position(test_pos)
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_builders = {}
for hash, data in pairs(layout) do
for _, dir_hash in ipairs(cardinal_dirs_hash) do
local potential_adjacent = hash+dir_hash
for _, dir_hash in ipairs(digtron.cardinal_dirs_hash) do
local potential_adjacent = hash + dir_hash
if layout[potential_adjacent] == nil then
adjacent[potential_adjacent] = true
end
end
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
if layout[potential_target] == nil then -- not pointed at another Digtron node
local fields = data.meta.fields
@ -224,7 +200,7 @@ local refresh_adjacent = function(digtron_id)
end
end
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
if layout[potential_target] == nil then
local fields = data.meta.fields
@ -307,7 +283,8 @@ digtron.assemble = function(root_pos, player_name)
local layout = {}
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
if hash == root_hash then
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 nil otherwise
local get_valid_data = function(digtron_id, root_hash, hash, data, function_name)
local node_hash = hash + root_hash -- TODO may want to return this as well?
local node_pos = minetest.get_position_from_hash(node_hash)
local get_valid_data = function(digtron_id, root_pos, hash, data, function_name)
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
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")
@ -440,11 +416,9 @@ digtron.disassemble = function(digtron_id, player_name)
return
end
local root_hash = minetest.hash_node_position(root_pos)
-- Write metadata and inventory to in-world node at this location
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
local node_inv = node_meta:get_inventory()
@ -515,10 +489,9 @@ digtron.remove_from_world = function(digtron_id, player_name)
return {}
end
local root_hash = minetest.hash_node_position(root_pos)
local nodes_to_destroy = {}
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
table.insert(nodes_to_destroy, node_pos)
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.
-- 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 = {}
if old_pos then
local old_root_hash = minetest.hash_node_position(old_pos)
for layout_hash, _ in pairs(layout) do
ignore_hashes[layout_hash + old_root_hash] = true
if old_root_pos then
for 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[old_hash] = true
end
end
if ignore_nodes then
@ -556,15 +529,14 @@ digtron.is_buildable_to = function(digtron_id, root_pos, player_name, ignore_nod
end
end
local root_hash = minetest.hash_node_position(root_pos)
local succeeded = {}
local failed = {}
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
local node_hash = layout_hash + root_hash
local node_pos = minetest.get_position_from_hash(node_hash)
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
local node_hash = minetest.hash_node_position(node_pos)
local node = minetest.get_node(node_pos)
local node_def = minetest.registered_nodes[node.name]
-- TODO: lots of testing needed here
@ -590,11 +562,10 @@ 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)
for hash, data in pairs(layout) do
-- Don't use get_valid_data, the Digtron isn't in-world yet
local node_pos = minetest.get_position_from_hash(hash + root_hash)
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
minetest.set_node(node_pos, data.node)
local meta = minetest.get_meta(node_pos)
for field, value in pairs(data.meta.fields) do
@ -623,6 +594,61 @@ digtron.move = function(digtron_id, dest_pos, player_name)
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
@ -634,14 +660,13 @@ local predict_dig = function(digtron_id, player_name, controlling_coordinate)
.."a predictive inventory or a root position for " .. digtron_id)
return
end
local root_hash = minetest.hash_node_position(root_pos)
local leftovers = {}
local dug_positions = {}
local cost = 0
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_name = target_node.name
local targetdef = minetest.registered_nodes[target_name]
@ -751,15 +776,14 @@ end
------------------------------------------------------------------------------------------------------
-- Building
-- need to provide new_pos because Digtron moves before building
local predict_build = function(digtron_id, new_pos, player_name, ignore_nodes, controlling_coordinate)
-- need to provide root_pos because Digtron moves before building
local predict_build = function(digtron_id, root_pos, player_name, ignore_nodes, controlling_coordinate)
local predictive_inv = get_predictive_inventory(digtron_id)
if not predictive_inv then
minetest.log("error", "[Digtron] predict_build failed to retrieve "
.."a predictive inventory for " .. digtron_id)
return
end
local root_hash = minetest.hash_node_position(new_pos)
local ignore_hashes = {}
if ignore_nodes then
@ -773,11 +797,10 @@ local predict_build = function(digtron_id, new_pos, player_name, ignore_nodes, c
local cost = 0
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 periodicity_permitted = nil
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
-- test periodicity and offset once
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.
local get_controlling_coordinate = function(facedir)
-- 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
return "z"
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 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?
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)
@ -952,7 +975,7 @@ digtron.execute_cycle = function(digtron_id, player_name)
else
clear_predictive_inventory(digtron_id)
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
@ -989,9 +1012,7 @@ digtron.can_dig = function(pos, digger)
return true
end
local root_hash = minetest.hash_node_position(root_pos)
local here_hash = minetest.hash_node_position(pos)
local layout_hash = here_hash - root_hash
local layout_hash = minetest.hash_node_position(vector.subtract(pos, root_pos))
local layout_data = layout[layout_hash]
if layout_data == nil or layout_data.node == nil then
minetest.log("error", "[Digtron] can_dig was called on a " .. node.name .. " at location "

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

@ -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.
dofile(modpath.."/util_item_place_node.lua")
dofile(modpath.."/geometry.lua")
dofile(modpath.."/entities.lua")
dofile(modpath.."/functions.lua")
dofile(modpath.."/controller.lua")

@ -18,16 +18,6 @@
--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 has_prefix(str, prefix)
return str:sub(1, string.len(prefix)) == prefix
end