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 {
|
||||
railtype = railtype,
|
||||
connected_at = connected_at,
|
||||
distance = 0,
|
||||
velocity = 0,
|
||||
dir = vector.new(dir),
|
||||
velocity = 0
|
||||
}
|
||||
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 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
|
||||
-- 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
|
||||
local pos = staticdata.connected_at
|
||||
|
||||
-- Calculate next direction
|
||||
next_dir,last_switch = mcl_minecarts:get_rail_direction(pos, dir, nil, nil, staticdata.railtype)
|
||||
next_dir = vector.copy(next_dir) -- Needed to isolate the carts from one another
|
||||
elseif distance_to_next > max_step_distance then
|
||||
distance_to_next = max_step_distance
|
||||
end
|
||||
if not pos then return remaining_distance end
|
||||
if staticdata.velocity < 0.1 then return remaining_distance end
|
||||
|
||||
local distance = remaining_distance
|
||||
if distance > distance_to_next then
|
||||
distance = distance_to_next
|
||||
end
|
||||
local remaining_in_block = 1 - ( staticdata.distance or 0 )
|
||||
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
|
||||
|
||||
-- Calculate next position
|
||||
next_pos = vector.new(pos + next_dir * distance)
|
||||
|
||||
-- Fix up position
|
||||
if next_dir.x == 0 then next_pos.x = math.floor(next_pos.x+0.5) end
|
||||
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
|
||||
if next_dir == dir * -1 then
|
||||
-- TODO: detach the cart if there isn't a stop after the rail
|
||||
staticdata.velocity = 0
|
||||
local next_pos_before_round = vector.copy(next_pos)
|
||||
next_pos = vector.round(next_pos + dir * 0.5)
|
||||
|
||||
if DEBUG and self._driver then
|
||||
local node_name = minetest.get_node(next_pos).name
|
||||
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
|
||||
)
|
||||
-- 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
|
||||
|
||||
-- Anchor at the next node
|
||||
pos = pos + staticdata.dir
|
||||
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
|
||||
|
||||
-- check for hopper under the rail
|
||||
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
|
||||
|
||||
-- Get the next direction
|
||||
next_dir,last_switch = mcl_minecarts:get_rail_direction(pos, staticdata.dir, nil, nil, staticdata.railtype)
|
||||
|
||||
-- Handle end of track
|
||||
if next_dir == staticdata.dir * -1 then
|
||||
print("Stopping cart at "..tostring(pos))
|
||||
staticdata.velocity = 0
|
||||
distence = remaining_distance
|
||||
end
|
||||
|
||||
-- Update cart direction
|
||||
staticdata.dir = next_dir
|
||||
end
|
||||
|
||||
self.object:move_to(pos)
|
||||
|
||||
-- Update cart orientation
|
||||
local yaw = 0
|
||||
if next_dir.x < 0 then
|
||||
local dir = staticdata.dir
|
||||
if dir.x < 0 then
|
||||
yaw = 0.5
|
||||
elseif next_dir.x > 0 then
|
||||
elseif dir.x > 0 then
|
||||
yaw = 1.5
|
||||
elseif dir.z < 0 then
|
||||
yaw = 1
|
||||
end
|
||||
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
|
||||
return distance
|
||||
end
|
||||
|
||||
local function process_acceleration(self, timestep)
|
||||
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_def = minetest.registered_nodes[node_name]
|
||||
local max_vel = mcl_minecarts.speed_max
|
||||
|
||||
if self._go_forward then
|
||||
self._acceleration = 2
|
||||
|
@ -499,16 +477,19 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
elseif self._fueltime and self._fueltime > 0 then
|
||||
self._acceleration = 0.6
|
||||
else
|
||||
self._acceleration = node_def._rail_acceleration or -0.4
|
||||
if staticdata.velocity >= ( node_def._max_acceleration_velocity or max_vel ) then
|
||||
self._acceleration = 0
|
||||
else
|
||||
self._acceleration = node_def._rail_acceleration or -0.4
|
||||
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
|
||||
end
|
||||
|
||||
if math.abs(self._acceleration) > 0.1 then
|
||||
staticdata.velocity = ( staticdata.velocity or 0 ) + self._acceleration * timestep
|
||||
local max_vel = mcl_minecarts.speed_max
|
||||
if staticdata.velocity > max_vel then
|
||||
staticdata.velocity = max_vel
|
||||
elseif staticdata.velocity < 0.1 then
|
||||
|
@ -516,8 +497,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
end
|
||||
end
|
||||
|
||||
if false and staticdata.velocity > 0 then
|
||||
print( "acceleration="..tostring(self._acceleration)..",velocity="..tostring(staticdata.velocity)..
|
||||
if DEBUG and staticdata.velocity > 0 then
|
||||
print( " acceleration="..tostring(self._acceleration)..",velocity="..tostring(staticdata.velocity)..
|
||||
",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 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
|
||||
-- it is impossible to jump across gaps due to server lag
|
||||
-- causing large timesteps
|
||||
|
@ -555,8 +544,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
end
|
||||
|
||||
local pos, rou_pos, node = self.object:get_pos()
|
||||
local update = {}
|
||||
local acceleration = 0
|
||||
--local update = {}
|
||||
--local acceleration = 0
|
||||
|
||||
-- Controls
|
||||
local ctrl, player = nil, nil
|
||||
|
|
|
@ -50,7 +50,7 @@ end
|
|||
local rail_rules_long =
|
||||
{{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= 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,
|
||||
_rail_acceleration = 4,
|
||||
_max_acceleration_velocity = 8,
|
||||
mesecons = {
|
||||
conductor = {
|
||||
state = mesecon.state.on,
|
||||
|
|
|
@ -9,6 +9,8 @@ local function mcl_log(message)
|
|||
end
|
||||
end
|
||||
|
||||
mcl_hoppers = {}
|
||||
|
||||
--[[ BEGIN OF NODE DEFINITIONS ]]
|
||||
|
||||
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())
|
||||
inv:set_stack("main", i, stack)
|
||||
|
||||
-- Take one item and stop until next time
|
||||
return
|
||||
-- Take one item and stop until next time, report that we took something
|
||||
return true
|
||||
else
|
||||
mcl_log("no Room")
|
||||
end
|
||||
|
@ -475,6 +477,7 @@ local function hopper_pull_from_mc(mc_ent, dest_pos, inv_size)
|
|||
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 dest_inv = mcl_entity_invs.load_inv(mc_ent, inv_size)
|
||||
|
|
Loading…
Reference in New Issue