mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-25 20:11:06 +01:00
08b41a3b39
accelerate a non-moving minecart away from a solid opaque block the powered rail is facing Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/4097 Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land> Co-authored-by: nixnoxus <nixnoxus@web.de> Co-committed-by: nixnoxus <nixnoxus@web.de>
167 lines
3.7 KiB
Lua
167 lines
3.7 KiB
Lua
local vector = vector
|
|
|
|
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 {x=mcl_minecarts:get_sign(v.x), y=mcl_minecarts:get_sign(v.y), z=0}
|
|
else
|
|
return {x=0, y=mcl_minecarts:get_sign(v.y), z=mcl_minecarts:get_sign(v.z)}
|
|
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
|
|
|
|
function mcl_minecarts:check_front_up_down(pos, dir_, check_down, railtype)
|
|
local dir = vector.new(dir_)
|
|
-- Front
|
|
dir.y = 0
|
|
local cur = vector.add(pos, dir)
|
|
if mcl_minecarts:is_rail(cur, railtype) then
|
|
return dir
|
|
end
|
|
-- Up
|
|
if check_down then
|
|
dir.y = 1
|
|
cur = vector.add(pos, dir)
|
|
if mcl_minecarts:is_rail(cur, railtype) then
|
|
return dir
|
|
end
|
|
end
|
|
-- Down
|
|
dir.y = -1
|
|
cur = vector.add(pos, dir)
|
|
if mcl_minecarts:is_rail(cur, railtype) then
|
|
return dir
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function mcl_minecarts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
|
local pos = vector.round(pos_)
|
|
local cur
|
|
local left_check, right_check = true, true
|
|
|
|
-- Check left and right
|
|
local left = {x=0, y=0, z=0}
|
|
local right = {x=0, y=0, z=0}
|
|
if dir.z ~= 0 and dir.x == 0 then
|
|
left.x = -dir.z
|
|
right.x = dir.z
|
|
elseif dir.x ~= 0 and dir.z == 0 then
|
|
left.z = dir.x
|
|
right.z = -dir.x
|
|
end
|
|
|
|
if ctrl then
|
|
if old_switch == 1 then
|
|
left_check = false
|
|
elseif old_switch == 2 then
|
|
right_check = false
|
|
end
|
|
if ctrl.left and left_check then
|
|
cur = mcl_minecarts:check_front_up_down(pos, left, false, railtype)
|
|
if cur then
|
|
return cur, 1
|
|
end
|
|
left_check = false
|
|
end
|
|
if ctrl.right and right_check then
|
|
cur = mcl_minecarts:check_front_up_down(pos, right, false, railtype)
|
|
if cur then
|
|
return cur, 2
|
|
end
|
|
right_check = true
|
|
end
|
|
end
|
|
|
|
-- Normal
|
|
cur = mcl_minecarts:check_front_up_down(pos, dir, true, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
|
|
-- Left, if not already checked
|
|
if left_check then
|
|
cur = mcl_minecarts:check_front_up_down(pos, left, false, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
end
|
|
|
|
-- Right, if not already checked
|
|
if right_check then
|
|
cur = mcl_minecarts:check_front_up_down(pos, right, false, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
end
|
|
-- Backwards
|
|
if not old_switch then
|
|
cur = mcl_minecarts:check_front_up_down(pos, {
|
|
x = -dir.x,
|
|
y = dir.y,
|
|
z = -dir.z
|
|
}, true, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
end
|
|
return {x=0, y=0, z=0}
|
|
end
|
|
|
|
local plane_adjacents = {
|
|
vector.new(-1,0,0),
|
|
vector.new(1,0,0),
|
|
vector.new(0,0,-1),
|
|
vector.new(0,0,1),
|
|
}
|
|
|
|
function mcl_minecarts:get_start_direction(pos)
|
|
local dir
|
|
local i = 0
|
|
while (not dir and i < #plane_adjacents) do
|
|
i = i+1
|
|
local node = minetest.get_node_or_nil(vector.add(pos, plane_adjacents[i]))
|
|
if node ~= nil
|
|
and minetest.get_item_group(node.name, "rail") == 0
|
|
and minetest.get_item_group(node.name, "solid") == 1
|
|
and minetest.get_item_group(node.name, "opaque") == 1
|
|
then
|
|
dir = mcl_minecarts:check_front_up_down(pos, vector.multiply(plane_adjacents[i], -1), true)
|
|
end
|
|
end
|
|
return dir
|
|
end
|
|
|
|
function mcl_minecarts:set_velocity(obj, dir, factor)
|
|
obj._velocity = vector.multiply(dir, factor or 3)
|
|
obj._old_pos = nil
|
|
obj._punched = true
|
|
end
|