Change connected railcar behavior to fix unreliable end of track stopping, set maximum acceleration of powered rails to 8 blocks per second (per https://minecraft.fandom.com/wiki/Powered_Rail), stop powered rails from powering the block underneath it (allows below rail hopper to work while the rail is powered like in https://www.youtube.com/watch?v=szjO0-duTAk), modify mcl_hoppers to allow triggering a hopper pull once the minecart is stopped on top of the hopper and wait before allowing the cart to move to allow redstone circuits time to process
This commit is contained in:
parent
c9d6a417cd
commit
2dcb790ace
|
@ -188,8 +188,9 @@ local function make_staticdata( railtype, connected_at, dir )
|
||||||
return {
|
return {
|
||||||
railtype = railtype,
|
railtype = railtype,
|
||||||
connected_at = connected_at,
|
connected_at = connected_at,
|
||||||
|
distance = 0,
|
||||||
|
velocity = 0,
|
||||||
dir = vector.new(dir),
|
dir = vector.new(dir),
|
||||||
velocity = 0
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -380,115 +381,92 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
|
|
||||||
local function do_movement_step(self, remaining_distance)
|
local function do_movement_step(self, remaining_distance)
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
local pos = self.object:get_pos()
|
|
||||||
local dir = staticdata.dir or vector.new(1,0,0)
|
|
||||||
dir = vector.new(dir)
|
|
||||||
|
|
||||||
-- Calculate the distance to the next block
|
local pos = staticdata.connected_at
|
||||||
-- This is just short of a full block to keep from jumping
|
|
||||||
local distance_to_next = distance_to_next_block( dir, pos ) - 0.01
|
|
||||||
local next_pos
|
|
||||||
local next_dir,last_switch
|
|
||||||
next_dir = dir
|
|
||||||
if distance_to_next < 0.01 then
|
|
||||||
distance_to_next = 0.5
|
|
||||||
|
|
||||||
-- Calculate next direction
|
if not pos then return remaining_distance end
|
||||||
next_dir,last_switch = mcl_minecarts:get_rail_direction(pos, dir, nil, nil, staticdata.railtype)
|
if staticdata.velocity < 0.1 then return remaining_distance end
|
||||||
next_dir = vector.copy(next_dir) -- Needed to isolate the carts from one another
|
|
||||||
elseif distance_to_next > max_step_distance then
|
local remaining_in_block = 1 - ( staticdata.distance or 0 )
|
||||||
distance_to_next = max_step_distance
|
local dinstance = 0
|
||||||
|
if remaining_in_block > remaining_distance then
|
||||||
|
distance = remaining_distance
|
||||||
|
staticdata.distance = ( staticdata.distance or 0 ) + distance
|
||||||
|
pos = pos + staticdata.dir * staticdata.distance
|
||||||
|
else
|
||||||
|
distance = remaining_in_block
|
||||||
|
staticdata.distance = 0
|
||||||
|
|
||||||
|
-- Leave the old node
|
||||||
|
local old_node_name = minetest.get_node(pos).name
|
||||||
|
local old_node_def = minetest.registered_nodes[old_node_name]
|
||||||
|
if old_node_def._mcl_minecarts_on_leave then
|
||||||
|
old_node_def._mcl_minecarts_on_leave( pos, self )
|
||||||
end
|
end
|
||||||
|
|
||||||
local distance = remaining_distance
|
-- Anchor at the next node
|
||||||
if distance > distance_to_next then
|
pos = pos + staticdata.dir
|
||||||
distance = distance_to_next
|
staticdata.connected_at = pos
|
||||||
|
|
||||||
|
-- Enter the new node
|
||||||
|
local new_node_name = minetest.get_node(pos).name
|
||||||
|
local new_node_def = minetest.registered_nodes[new_node_name]
|
||||||
|
if new_node_def._mcl_minecarts_on_enter then
|
||||||
|
new_node_def._mcl_minecarts_on_enter( pos, self )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Calculate next position
|
-- check for hopper under the rail
|
||||||
next_pos = vector.new(pos + next_dir * distance)
|
local under_pos = pos - vector.new(0,1,0)
|
||||||
|
local under_node_name = minetest.get_node(under_pos).name
|
||||||
|
local under_node_def = minetest.registered_nodes[under_node_name]
|
||||||
|
print( "under_node_name="..under_node_name..", hopper="..tostring(under_node_def.groups.hopper))
|
||||||
|
if under_node_def and under_node_def.groups.hopper ~= 0 then
|
||||||
|
print( "Attempt pull_from_minecart" )
|
||||||
|
if mcl_hoppers.pull_from_minecart( self, under_pos, self._inv_size or 0 ) then
|
||||||
|
staticdata.delay = 1.5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Fix up position
|
-- Get the next direction
|
||||||
if next_dir.x == 0 then next_pos.x = math.floor(next_pos.x+0.5) end
|
next_dir,last_switch = mcl_minecarts:get_rail_direction(pos, staticdata.dir, nil, nil, staticdata.railtype)
|
||||||
if next_dir.y == 0 then next_pos.y = math.floor(next_pos.y+0.5) end
|
|
||||||
if next_dir.z == 0 then next_pos.z = math.floor(next_pos.z+0.5) end
|
|
||||||
|
|
||||||
-- Direction flipped, stop
|
-- Handle end of track
|
||||||
if next_dir == dir * -1 then
|
if next_dir == staticdata.dir * -1 then
|
||||||
-- TODO: detach the cart if there isn't a stop after the rail
|
print("Stopping cart at "..tostring(pos))
|
||||||
staticdata.velocity = 0
|
staticdata.velocity = 0
|
||||||
local next_pos_before_round = vector.copy(next_pos)
|
distence = remaining_distance
|
||||||
next_pos = vector.round(next_pos + dir * 0.5)
|
end
|
||||||
|
|
||||||
if DEBUG and self._driver then
|
-- Update cart direction
|
||||||
local node_name = minetest.get_node(next_pos).name
|
staticdata.dir = next_dir
|
||||||
print("Stopping cart on "..node_name.." at "..tostring(next_pos)
|
|
||||||
.." pos="..tostring(pos)
|
|
||||||
..",next_pos="..tostring(next_pos)
|
|
||||||
..",next_pos_before_round="..tostring(next_pos_before_round)
|
|
||||||
..",distance="..distance
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.object:move_to(pos)
|
||||||
|
|
||||||
-- Update cart orientation
|
-- Update cart orientation
|
||||||
local yaw = 0
|
local yaw = 0
|
||||||
if next_dir.x < 0 then
|
local dir = staticdata.dir
|
||||||
|
if dir.x < 0 then
|
||||||
yaw = 0.5
|
yaw = 0.5
|
||||||
elseif next_dir.x > 0 then
|
elseif dir.x > 0 then
|
||||||
yaw = 1.5
|
yaw = 1.5
|
||||||
elseif dir.z < 0 then
|
elseif dir.z < 0 then
|
||||||
yaw = 1
|
yaw = 1
|
||||||
end
|
end
|
||||||
self.object:set_yaw( yaw * math.pi )
|
self.object:set_yaw( yaw * math.pi )
|
||||||
|
|
||||||
-- Update cart position
|
|
||||||
local next_pos_rounded = vector.round(next_pos)
|
|
||||||
staticdata.connected_at = next_pos_rounded
|
|
||||||
staticdata.dir = next_dir
|
|
||||||
self.object:move_to(next_pos)
|
|
||||||
|
|
||||||
if DEBUG and self._driver then
|
|
||||||
local prefix = " "
|
|
||||||
if next_dir ~= dir then
|
|
||||||
prefix = "--->"
|
|
||||||
end
|
|
||||||
print( prefix
|
|
||||||
.. "pos="..tostring(pos)
|
|
||||||
..",dir="..to_dirstring(dir)
|
|
||||||
..",next_dir="..to_dirstring(next_dir)
|
|
||||||
..",next_pos="..tostring(next_pos)
|
|
||||||
..",velocity="..tostring(staticdata.velocity)
|
|
||||||
..",distance="..tostring(distance)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle track interactions
|
|
||||||
local pos_rounded = vector.round(pos)
|
|
||||||
if pos_rounded ~= next_pos_rounded then
|
|
||||||
local old_node_name = minetest.get_node(pos_rounded).name
|
|
||||||
local old_node_def = minetest.registered_nodes[old_node_name]
|
|
||||||
if old_node_def._mcl_minecarts_on_leave then
|
|
||||||
old_node_def._mcl_minecarts_on_leave( pos_rounded, self )
|
|
||||||
end
|
|
||||||
|
|
||||||
local new_node_name = minetest.get_node(next_pos_rounded).name
|
|
||||||
local new_node_def = minetest.registered_nodes[new_node_name]
|
|
||||||
if new_node_def._mcl_minecarts_on_enter then
|
|
||||||
new_node_def._mcl_minecarts_on_enter( next_pos_rounded, self )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Report distance traveled
|
-- Report distance traveled
|
||||||
return distance
|
return distance
|
||||||
end
|
end
|
||||||
|
|
||||||
local function process_acceleration(self, timestep)
|
local function process_acceleration(self, timestep)
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
|
if not staticdata.connected_at then return end
|
||||||
|
|
||||||
local pos = self.object:get_pos()
|
local pos = staticdata.connected_at
|
||||||
local node_name = minetest.get_node(pos).name
|
local node_name = minetest.get_node(pos).name
|
||||||
local node_def = minetest.registered_nodes[node_name]
|
local node_def = minetest.registered_nodes[node_name]
|
||||||
|
local max_vel = mcl_minecarts.speed_max
|
||||||
|
|
||||||
if self._go_forward then
|
if self._go_forward then
|
||||||
self._acceleration = 2
|
self._acceleration = 2
|
||||||
|
@ -498,17 +476,20 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
self._acceleration = 2
|
self._acceleration = 2
|
||||||
elseif self._fueltime and self._fueltime > 0 then
|
elseif self._fueltime and self._fueltime > 0 then
|
||||||
self._acceleration = 0.6
|
self._acceleration = 0.6
|
||||||
|
else
|
||||||
|
if staticdata.velocity >= ( node_def._max_acceleration_velocity or max_vel ) then
|
||||||
|
self._acceleration = 0
|
||||||
else
|
else
|
||||||
self._acceleration = node_def._rail_acceleration or -0.4
|
self._acceleration = node_def._rail_acceleration or -0.4
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if self._acceleration > 0 and staticdata.velocity < 0.1 then
|
if self._acceleration > 0 and (staticdata.velocity or 0) < 0.1 then
|
||||||
staticdata.velocity = 0.1
|
staticdata.velocity = 0.1
|
||||||
end
|
end
|
||||||
|
|
||||||
if math.abs(self._acceleration) > 0.1 then
|
if math.abs(self._acceleration) > 0.1 then
|
||||||
staticdata.velocity = ( staticdata.velocity or 0 ) + self._acceleration * timestep
|
staticdata.velocity = ( staticdata.velocity or 0 ) + self._acceleration * timestep
|
||||||
local max_vel = mcl_minecarts.speed_max
|
|
||||||
if staticdata.velocity > max_vel then
|
if staticdata.velocity > max_vel then
|
||||||
staticdata.velocity = max_vel
|
staticdata.velocity = max_vel
|
||||||
elseif staticdata.velocity < 0.1 then
|
elseif staticdata.velocity < 0.1 then
|
||||||
|
@ -516,7 +497,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if false and staticdata.velocity > 0 then
|
if DEBUG and staticdata.velocity > 0 then
|
||||||
print( " acceleration="..tostring(self._acceleration)..",velocity="..tostring(staticdata.velocity)..
|
print( " acceleration="..tostring(self._acceleration)..",velocity="..tostring(staticdata.velocity)..
|
||||||
",timestep="..tostring(timestep))
|
",timestep="..tostring(timestep))
|
||||||
end
|
end
|
||||||
|
@ -526,6 +507,14 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
local function do_movement( self, dtime )
|
local function do_movement( self, dtime )
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
|
|
||||||
|
-- Allow the carts to be delay for the rest of the world to react before moving again
|
||||||
|
if ( staticdata.delay or 0 ) > dtime then
|
||||||
|
staticdata.delay = staticdata.delay - dtime
|
||||||
|
return
|
||||||
|
else
|
||||||
|
staticdata.delay = 0
|
||||||
|
end
|
||||||
|
|
||||||
-- Break long movements into fixed-size steps so that
|
-- Break long movements into fixed-size steps so that
|
||||||
-- it is impossible to jump across gaps due to server lag
|
-- it is impossible to jump across gaps due to server lag
|
||||||
-- causing large timesteps
|
-- causing large timesteps
|
||||||
|
@ -555,8 +544,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
end
|
end
|
||||||
|
|
||||||
local pos, rou_pos, node = self.object:get_pos()
|
local pos, rou_pos, node = self.object:get_pos()
|
||||||
local update = {}
|
--local update = {}
|
||||||
local acceleration = 0
|
--local acceleration = 0
|
||||||
|
|
||||||
-- Controls
|
-- Controls
|
||||||
local ctrl, player = nil, nil
|
local ctrl, player = nil, nil
|
||||||
|
|
|
@ -50,7 +50,7 @@ end
|
||||||
local rail_rules_long =
|
local rail_rules_long =
|
||||||
{{x=-1, y= 0, z= 0, spread=true},
|
{{x=-1, y= 0, z= 0, spread=true},
|
||||||
{x= 1, y= 0, z= 0, spread=true},
|
{x= 1, y= 0, z= 0, spread=true},
|
||||||
{x= 0, y=-1, z= 0, spread=true},
|
-- {x= 0, y=-1, z= 0, spread=true},
|
||||||
{x= 0, y= 1, z= 0, spread=true},
|
{x= 0, y= 1, z= 0, spread=true},
|
||||||
{x= 0, y= 0, z=-1, spread=true},
|
{x= 0, y= 0, z=-1, spread=true},
|
||||||
{x= 0, y= 0, z= 1, spread=true},
|
{x= 0, y= 0, z= 1, spread=true},
|
||||||
|
@ -105,6 +105,7 @@ register_rail("mcl_minecarts:golden_rail_on",
|
||||||
{
|
{
|
||||||
_doc_items_create_entry = false,
|
_doc_items_create_entry = false,
|
||||||
_rail_acceleration = 4,
|
_rail_acceleration = 4,
|
||||||
|
_max_acceleration_velocity = 8,
|
||||||
mesecons = {
|
mesecons = {
|
||||||
conductor = {
|
conductor = {
|
||||||
state = mesecon.state.on,
|
state = mesecon.state.on,
|
||||||
|
|
|
@ -9,6 +9,8 @@ local function mcl_log(message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mcl_hoppers = {}
|
||||||
|
|
||||||
--[[ BEGIN OF NODE DEFINITIONS ]]
|
--[[ BEGIN OF NODE DEFINITIONS ]]
|
||||||
|
|
||||||
local mcl_hoppers_formspec = table.concat({
|
local mcl_hoppers_formspec = table.concat({
|
||||||
|
@ -464,8 +466,8 @@ local function hopper_pull_from_mc(mc_ent, dest_pos, inv_size)
|
||||||
dest_inv:add_item("main", stack:take_item())
|
dest_inv:add_item("main", stack:take_item())
|
||||||
inv:set_stack("main", i, stack)
|
inv:set_stack("main", i, stack)
|
||||||
|
|
||||||
-- Take one item and stop until next time
|
-- Take one item and stop until next time, report that we took something
|
||||||
return
|
return true
|
||||||
else
|
else
|
||||||
mcl_log("no Room")
|
mcl_log("no Room")
|
||||||
end
|
end
|
||||||
|
@ -475,6 +477,7 @@ local function hopper_pull_from_mc(mc_ent, dest_pos, inv_size)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
mcl_hoppers.pull_from_minecart = hopper_pull_from_mc
|
||||||
|
|
||||||
local function hopper_push_to_mc(mc_ent, dest_pos, inv_size)
|
local function hopper_push_to_mc(mc_ent, dest_pos, inv_size)
|
||||||
local dest_inv = mcl_entity_invs.load_inv(mc_ent, inv_size)
|
local dest_inv = mcl_entity_invs.load_inv(mc_ent, inv_size)
|
||||||
|
|
Loading…
Reference in New Issue