VoxeLibre/mods/ENTITIES/mcl_minecarts/functions.lua

122 lines
2.8 KiB
Lua
Raw Normal View History

2021-05-25 00:43:42 +02:00
local vector = vector
2017-01-05 15:23:14 +01:00
function mcl_minecarts:get_sign(z)
if z == 0 then
return 0
else
return z / math.abs(z)
end
end
function mcl_minecarts:velocity_to_dir(v)
if math.abs(v.x) > math.abs(v.z) then
return vector.new(
mcl_minecarts:get_sign(v.x),
mcl_minecarts:get_sign(v.y),
0
)
2017-01-05 15:23:14 +01:00
else
return vector.new(
0,
mcl_minecarts:get_sign(v.y),
mcl_minecarts:get_sign(v.z)
)
2017-01-05 15:23:14 +01:00
end
end
function mcl_minecarts:is_rail(pos, railtype)
local node = minetest.get_node(pos).name
if node == "ignore" then
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(pos, pos)
local area = VoxelArea:new{
MinEdge = emin,
MaxEdge = emax,
}
local data = vm:get_data()
local vi = area:indexp(pos)
node = minetest.get_name_from_content_id(data[vi])
end
if minetest.get_item_group(node, "rail") == 0 then
return false
end
if not railtype then
return true
end
return minetest.get_item_group(node, "connect_to_raillike") == railtype
end
--[[
Returns a string description of a direction, with optional _up/_down suffix
]]
function mcl_minecarts:name_from_dir(dir, vertical)
local res = ""
if dir.z == 1 then res = res .. "n" end
if dir.z == -1 then res = res .. "s" end
if dir.x == -1 then res = res .. "w" end
if dir.x == 1 then res = res .. "e" end
if vertical then
if dir.y == 1 then res = res .. "_up" end
if dir.y == 1 then res = res .. "_down" end
2017-01-05 15:23:14 +01:00
end
return res
2017-01-05 15:23:14 +01:00
end
--[[
An array of (u,v,w) positions to check. Actual direction is u * dir + v * right + w * vector.new(0,1,0)
]]
local rail_checks = {
{ 1, 0, 0 }, -- forwards
{ 1, 0, 1 }, -- forwards and up
{ 1, 0, -1 }, -- forwards and down
{ 1, 1, 0 }, -- diagonal left
{ 0, 1, 0 }, -- left
{ 0, 1, 1 }, -- left and up
{ 0, 1, -1 }, -- left and down
{ 1, -1, 0 }, -- diagonal right
{ 0, -1, 0 }, -- right
{ 0, -1, 1 }, -- right and up
{ 0, -1, -1 }, -- right and down
{ -1, 0, 0 }, -- backwards
}
-- Rotate diagonal directions 45 degrees clockwise
local diagonal_convert = {
nw = vector.new( 0,0, 1), -- north
ne = vector.new( 1,0, 0), -- east
se = vector.new( 0,0,-1), -- south
sw = vector.new(-1,0, 0), -- west
}
2017-01-05 15:23:14 +01:00
function mcl_minecarts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
local pos = vector.round(pos_)
2021-05-25 00:43:42 +02:00
-- Diagonal conversion
if dir.x ~= 0 and dir.z ~= 0 then
dir = diagonal_convert[ mcl_minecarts:name_from_dir(dir, false) ]
2017-01-05 15:23:14 +01:00
end
2021-05-25 00:43:42 +02:00
-- Calculate coordinate space
local right = vector.new( dir.z, dir.y, -dir.x)
local up = vector.new(0,1,0)
2021-05-25 00:43:42 +02:00
-- Perform checks
for _,check in ipairs(rail_checks) do
local check_dir = dir * check[1] + right * check[2] + up * check[3]
local check_pos = pos + check_dir
if mcl_minecarts:is_rail(check_pos,railtype) then
return check_dir
2017-01-05 15:23:14 +01:00
end
end
2021-05-25 00:43:42 +02:00
return vector.new(0,0,0)
end