mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-30 22:41:20 +01:00
Rework in preparation to add code to pull from containers into the hopper minecart
This commit is contained in:
parent
f57d202a9d
commit
0951acd06c
1 changed files with 378 additions and 333 deletions
|
@ -21,6 +21,265 @@ local function mcl_log(message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function handle_cart_enter(self,pos)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
|
||||||
|
-- Handle track behaviors
|
||||||
|
local node_def = minetest.registered_nodes[node.name]
|
||||||
|
if node_def._mcl_minecarts_on_enter then
|
||||||
|
node_def._mcl_minecarts_on_enter(pos, cart)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle above-track behaviors (to ensure hoppers can transfer at least one item)
|
||||||
|
pos = pos + vector.new(0,1,0)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if node_def._mcl_minecarts_on_enter_below then
|
||||||
|
node_def._mcl_minecarts_on_enter_below(pos, cart)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle cart-specific behaviors
|
||||||
|
if self._mcl_minecarts_on_enter then
|
||||||
|
self._mcl_minecarts_on_enter(self, pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function handle_cart_leave(pos)
|
||||||
|
local node_name = minetest.get_node(pos).name
|
||||||
|
local node_def = minetest.registered_nodes[node_name]
|
||||||
|
if node_def._mcl_minecarts_on_leave then
|
||||||
|
node_def._mcl_minecarts_on_leave(pos, self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function update_cart_orientation(self,staticdata)
|
||||||
|
-- constants
|
||||||
|
local _2_pi = math.pi * 2
|
||||||
|
local pi = math.pi
|
||||||
|
local dir = staticdata.dir
|
||||||
|
|
||||||
|
-- Calculate an angle from the x,z direction components
|
||||||
|
local rot_y = math.atan2( dir.x, dir.z ) + ( staticdata.rot_adjust or 0 )
|
||||||
|
if rot_y < 0 then
|
||||||
|
rot_y = rot_y + _2_pi
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if the rotation is a 180 flip and don't change if so
|
||||||
|
local rot = self.object:get_rotation()
|
||||||
|
local diff = math.abs((rot_y - ( rot.y + pi ) % _2_pi) )
|
||||||
|
if diff < 0.001 or diff > _2_pi - 0.001 then
|
||||||
|
-- Update rotation adjust and recalculate the rotation
|
||||||
|
staticdata.rot_adjust = ( ( staticdata.rot_adjust or 0 ) + pi ) % _2_pi
|
||||||
|
rot.y = math.atan2( dir.x, dir.z ) + ( staticdata.rot_adjust or 0 )
|
||||||
|
else
|
||||||
|
rot.y = rot_y
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Forward/backwards tilt (pitch)
|
||||||
|
if dir.y < 0 then
|
||||||
|
rot.x = -0.25 * pi
|
||||||
|
elseif dir.y > 0 then
|
||||||
|
rot.x = 0.25 * pi
|
||||||
|
else
|
||||||
|
rot.x = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( staticdata.rot_adjust or 0 ) < 0.01 then
|
||||||
|
rot.x = -rot.x
|
||||||
|
end
|
||||||
|
|
||||||
|
self.object:set_rotation(rot)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function do_movement_step(self, remaining_distance)
|
||||||
|
local staticdata = self._staticdata
|
||||||
|
|
||||||
|
local pos = staticdata.connected_at
|
||||||
|
|
||||||
|
if not pos then return remaining_distance end
|
||||||
|
if staticdata.velocity < 0.1 then return remaining_distance 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
|
||||||
|
|
||||||
|
-- Leave the old node
|
||||||
|
handle_cart_leave(pos)
|
||||||
|
|
||||||
|
-- Anchor at the next node
|
||||||
|
pos = pos + staticdata.dir
|
||||||
|
staticdata.connected_at = pos
|
||||||
|
|
||||||
|
-- Enter the new node
|
||||||
|
handle_cart_enter(self,pos)
|
||||||
|
|
||||||
|
-- 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]
|
||||||
|
if DEBUG then print( "under_node_name="..under_node_name..", hopper="..tostring(under_node_def.groups.hopper)) end
|
||||||
|
if under_node_def and under_node_def.groups.hopper ~= 0 then
|
||||||
|
if DEBUG then print( "Attempt pull_from_minecart" ) end
|
||||||
|
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
|
||||||
|
local next_dir,_ = mcl_minecarts:get_rail_direction(pos, staticdata.dir, nil, nil, staticdata.railtype)
|
||||||
|
if DEBUG and next_dir ~= staticdata.dir then
|
||||||
|
print( "Changing direction from "..tostring(staticdata.dir).." to "..tostring(next_dir))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle end of track
|
||||||
|
if next_dir == staticdata.dir * -1 then
|
||||||
|
if DEBUG then print("Stopping cart at "..tostring(pos)) end
|
||||||
|
staticdata.velocity = 0
|
||||||
|
distence = remaining_distance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update cart direction
|
||||||
|
staticdata.dir = next_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
self.object:move_to(pos)
|
||||||
|
|
||||||
|
-- Update cart orientation
|
||||||
|
update_cart_orientation(self,staticdata)
|
||||||
|
|
||||||
|
-- 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 acceleration = 0
|
||||||
|
|
||||||
|
if DEBUG and staticdata.velocity > 0 then
|
||||||
|
print( " acceleration="..tostring(acceleration)..",velocity="..tostring(staticdata.velocity)..
|
||||||
|
",timestep="..tostring(timestep)..
|
||||||
|
",dir="..tostring(staticdata.dir))
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
acceleration = 2
|
||||||
|
elseif self._brake then
|
||||||
|
acceleration = -1.5
|
||||||
|
elseif self._punched then
|
||||||
|
acceleration = 2
|
||||||
|
elseif self._fueltime and self._fueltime > 0 then
|
||||||
|
acceleration = 0.6
|
||||||
|
elseif staticdata.velocity >= ( node_def._max_acceleration_velocity or max_vel ) then
|
||||||
|
acceleration = 0
|
||||||
|
else
|
||||||
|
acceleration = node_def._rail_acceleration or -friction
|
||||||
|
end
|
||||||
|
|
||||||
|
if math.abs(acceleration) > (friction / 5) then
|
||||||
|
staticdata.velocity = ( staticdata.velocity or 0 ) + acceleration * timestep
|
||||||
|
if staticdata.velocity > max_vel then
|
||||||
|
staticdata.velocity = max_vel
|
||||||
|
elseif staticdata.velocity < 0.1 then
|
||||||
|
staticdata.velocity = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Factor in gravity after everything else
|
||||||
|
local gravity_accel = 0
|
||||||
|
local gravity_strength = friction + 0.2
|
||||||
|
if staticdata.dir.y < 0 then
|
||||||
|
gravity_accel = gravity_strength
|
||||||
|
elseif staticdata.dir.y > 0 then
|
||||||
|
gravity_accel = -gravity_strength
|
||||||
|
end
|
||||||
|
if DEBUG and gravity_accel ~= 0 then
|
||||||
|
print("gravity_accel="..tostring(gravity_accel))
|
||||||
|
end
|
||||||
|
if gravity_accel ~= 0 then
|
||||||
|
staticdata.velocity = (staticdata.velocity or 0) + gravity_accel
|
||||||
|
if staticdata.velocity < 0 then
|
||||||
|
if DEBUG then
|
||||||
|
print("Gravity flipped direction")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Complete moving thru this block into the next, reverse direction, and put us back at the same position we were at
|
||||||
|
staticdata.velocity = staticdata.velocity * -1
|
||||||
|
next_dir = -staticdata.dir
|
||||||
|
pos = pos + staticdata.dir
|
||||||
|
staticdata.distance = 1 - staticdata.distance
|
||||||
|
staticdata.connected_at = pos
|
||||||
|
|
||||||
|
local next_dir,_ = mcl_minecarts:get_rail_direction(pos + staticdata.dir, next_dir, nil, nil, staticdata.railtype)
|
||||||
|
staticdata.dir = next_dir
|
||||||
|
|
||||||
|
update_cart_orientation(self,staticdata)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Force the cart to stop if moving slowly enough
|
||||||
|
if (staticdata.velocity or 0) < 0.1 then
|
||||||
|
staticdata.velocity = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if DEBUG and staticdata.velocity > 0 then
|
||||||
|
print( " acceleration="..tostring(acceleration)..",velocity="..tostring(staticdata.velocity)..
|
||||||
|
",timestep="..tostring(timestep)..
|
||||||
|
",dir="..tostring(staticdata.dir))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
local initial_velocity = 1
|
||||||
|
if self._punched and statcdata.velocity < initial_velocity then
|
||||||
|
staticdata.velocity = initial_velocity
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Break long movements into fixed-size steps so that
|
||||||
|
-- it is impossible to jump across gaps due to server lag
|
||||||
|
-- causing large timesteps
|
||||||
|
local total_distance = dtime * ( staticdata.velocity or 0 )
|
||||||
|
local remaining_distance = total_distance
|
||||||
|
|
||||||
|
process_acceleration(self,dtime * max_step_distance / total_distance)
|
||||||
|
|
||||||
|
-- Skip processing stopped railcarts
|
||||||
|
if not staticdata.velocity or math.abs(staticdata.velocity) < 0.05 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
while remaining_distance > 0.1 do
|
||||||
|
local step_distance = do_movement_step(self, remaining_distance)
|
||||||
|
if step_distance > 0.1 then
|
||||||
|
process_acceleration(self, dtime * step_distance / total_distance)
|
||||||
|
end
|
||||||
|
remaining_distance = remaining_distance - step_distance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Clear punched flag now that movement for this step has been completed
|
||||||
|
self._punched = false
|
||||||
|
end
|
||||||
|
|
||||||
local function detach_driver(self)
|
local function detach_driver(self)
|
||||||
if not self._driver then
|
if not self._driver then
|
||||||
|
@ -211,18 +470,21 @@ local function to_dirstring(dir)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
|
local function register_entity(entity_id, def)
|
||||||
|
assert( def.drop, "drop is required parameter" )
|
||||||
local cart = {
|
local cart = {
|
||||||
initial_properties = {
|
initial_properties = {
|
||||||
physical = false,
|
physical = false,
|
||||||
collisionbox = {-10/16., -0.5, -10/16, 10/16, 0.25, 10/16},
|
collisionbox = {-10/16., -0.5, -10/16, 10/16, 0.25, 10/16},
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = mesh,
|
mesh = def.mesh,
|
||||||
visual_size = {x=1, y=1},
|
visual_size = {x=1, y=1},
|
||||||
textures = textures,
|
textures = def.textures,
|
||||||
},
|
},
|
||||||
|
|
||||||
on_rightclick = on_rightclick,
|
on_rightclick = def.on_rightclick,
|
||||||
|
on_activate_by_rail = def.on_activate_by_rail,
|
||||||
|
_mcl_minecarts_on_enter = def._mcl_minecarts_on_enter,
|
||||||
|
|
||||||
_driver = nil, -- player who sits in and controls the minecart (only for minecart!)
|
_driver = nil, -- player who sits in and controls the minecart (only for minecart!)
|
||||||
_passenger = nil, -- for mobs
|
_passenger = nil, -- for mobs
|
||||||
|
@ -321,6 +583,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Drop items and remove cart entity
|
-- Drop items and remove cart entity
|
||||||
|
local drop = def.drop
|
||||||
if not minetest.is_creative_enabled(puncher:get_player_name()) then
|
if not minetest.is_creative_enabled(puncher:get_player_name()) then
|
||||||
for d=1, #drop do
|
for d=1, #drop do
|
||||||
minetest.add_item(self.object:get_pos(), drop[d])
|
minetest.add_item(self.object:get_pos(), drop[d])
|
||||||
|
@ -367,248 +630,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
cart.on_activate_by_rail = on_activate_by_rail
|
|
||||||
|
|
||||||
local passenger_attach_position = vector.new(0, -1.75, 0)
|
local passenger_attach_position = vector.new(0, -1.75, 0)
|
||||||
|
|
||||||
local function update_cart_orientation(self,staticdata)
|
|
||||||
-- constants
|
|
||||||
local _2_pi = math.pi * 2
|
|
||||||
local pi = math.pi
|
|
||||||
local dir = staticdata.dir
|
|
||||||
|
|
||||||
-- Calculate an angle from the x,z direction components
|
|
||||||
local rot_y = math.atan2( dir.x, dir.z ) + ( staticdata.rot_adjust or 0 )
|
|
||||||
if rot_y < 0 then
|
|
||||||
rot_y = rot_y + _2_pi
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if the rotation is a 180 flip and don't change if so
|
|
||||||
local rot = self.object:get_rotation()
|
|
||||||
local diff = math.abs((rot_y - ( rot.y + pi ) % _2_pi) )
|
|
||||||
if diff < 0.001 or diff > _2_pi - 0.001 then
|
|
||||||
-- Update rotation adjust and recalculate the rotation
|
|
||||||
staticdata.rot_adjust = ( ( staticdata.rot_adjust or 0 ) + pi ) % _2_pi
|
|
||||||
rot.y = math.atan2( dir.x, dir.z ) + ( staticdata.rot_adjust or 0 )
|
|
||||||
else
|
|
||||||
rot.y = rot_y
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Forward/backwards tilt (pitch)
|
|
||||||
if dir.y < 0 then
|
|
||||||
rot.x = -0.25 * pi
|
|
||||||
elseif dir.y > 0 then
|
|
||||||
rot.x = 0.25 * pi
|
|
||||||
else
|
|
||||||
rot.x = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
if ( staticdata.rot_adjust or 0 ) < 0.01 then
|
|
||||||
rot.x = -rot.x
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:set_rotation(rot)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function do_movement_step(self, remaining_distance)
|
|
||||||
local staticdata = self._staticdata
|
|
||||||
|
|
||||||
local pos = staticdata.connected_at
|
|
||||||
|
|
||||||
if not pos then return remaining_distance end
|
|
||||||
if staticdata.velocity < 0.1 then return remaining_distance 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
|
|
||||||
|
|
||||||
-- 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]
|
|
||||||
if DEBUG then print( "under_node_name="..under_node_name..", hopper="..tostring(under_node_def.groups.hopper)) end
|
|
||||||
if under_node_def and under_node_def.groups.hopper ~= 0 then
|
|
||||||
if DEBUG then print( "Attempt pull_from_minecart" ) end
|
|
||||||
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
|
|
||||||
local next_dir,_ = mcl_minecarts:get_rail_direction(pos, staticdata.dir, nil, nil, staticdata.railtype)
|
|
||||||
if DEBUG and next_dir ~= staticdata.dir then
|
|
||||||
print( "Changing direction from "..tostring(staticdata.dir).." to "..tostring(next_dir))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle end of track
|
|
||||||
if next_dir == staticdata.dir * -1 then
|
|
||||||
if DEBUG then print("Stopping cart at "..tostring(pos)) end
|
|
||||||
staticdata.velocity = 0
|
|
||||||
distence = remaining_distance
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update cart direction
|
|
||||||
staticdata.dir = next_dir
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:move_to(pos)
|
|
||||||
|
|
||||||
-- Update cart orientation
|
|
||||||
update_cart_orientation(self,staticdata)
|
|
||||||
|
|
||||||
-- 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 acceleration = 0
|
|
||||||
|
|
||||||
if DEBUG and staticdata.velocity > 0 then
|
|
||||||
print( " acceleration="..tostring(acceleration)..",velocity="..tostring(staticdata.velocity)..
|
|
||||||
",timestep="..tostring(timestep)..
|
|
||||||
",dir="..tostring(staticdata.dir))
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
|
||||||
acceleration = 2
|
|
||||||
elseif self._brake then
|
|
||||||
acceleration = -1.5
|
|
||||||
elseif self._punched then
|
|
||||||
acceleration = 2
|
|
||||||
elseif self._fueltime and self._fueltime > 0 then
|
|
||||||
acceleration = 0.6
|
|
||||||
elseif staticdata.velocity >= ( node_def._max_acceleration_velocity or max_vel ) then
|
|
||||||
acceleration = 0
|
|
||||||
else
|
|
||||||
acceleration = node_def._rail_acceleration or -friction
|
|
||||||
end
|
|
||||||
|
|
||||||
if math.abs(acceleration) > (friction / 5) then
|
|
||||||
staticdata.velocity = ( staticdata.velocity or 0 ) + acceleration * timestep
|
|
||||||
if staticdata.velocity > max_vel then
|
|
||||||
staticdata.velocity = max_vel
|
|
||||||
elseif staticdata.velocity < 0.1 then
|
|
||||||
staticdata.velocity = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Factor in gravity after everything else
|
|
||||||
local gravity_accel = 0
|
|
||||||
local gravity_strength = friction + 0.2
|
|
||||||
if staticdata.dir.y < 0 then
|
|
||||||
gravity_accel = gravity_strength
|
|
||||||
elseif staticdata.dir.y > 0 then
|
|
||||||
gravity_accel = -gravity_strength
|
|
||||||
end
|
|
||||||
if DEBUG and gravity_accel ~= 0 then
|
|
||||||
print("gravity_accel="..tostring(gravity_accel))
|
|
||||||
end
|
|
||||||
if gravity_accel ~= 0 then
|
|
||||||
staticdata.velocity = (staticdata.velocity or 0) + gravity_accel
|
|
||||||
if staticdata.velocity < 0 then
|
|
||||||
if DEBUG then
|
|
||||||
print("Gravity flipped direction")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Complete moving thru this block into the next, reverse direction, and put us back at the same position we were at
|
|
||||||
staticdata.velocity = staticdata.velocity * -1
|
|
||||||
next_dir = -staticdata.dir
|
|
||||||
pos = pos + staticdata.dir
|
|
||||||
staticdata.distance = 1 - staticdata.distance
|
|
||||||
staticdata.connected_at = pos
|
|
||||||
|
|
||||||
local next_dir,_ = mcl_minecarts:get_rail_direction(pos + staticdata.dir, next_dir, nil, nil, staticdata.railtype)
|
|
||||||
staticdata.dir = next_dir
|
|
||||||
|
|
||||||
update_cart_orientation(self,staticdata)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Force the cart to stop if moving slowly enough
|
|
||||||
if (staticdata.velocity or 0) < 0.1 then
|
|
||||||
staticdata.velocity = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
if DEBUG and staticdata.velocity > 0 then
|
|
||||||
print( " acceleration="..tostring(acceleration)..",velocity="..tostring(staticdata.velocity)..
|
|
||||||
",timestep="..tostring(timestep)..
|
|
||||||
",dir="..tostring(staticdata.dir))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
local initial_velocity = 1
|
|
||||||
if self._punched and statcdata.velocity < initial_velocity then
|
|
||||||
staticdata.velocity = initial_velocity
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Break long movements into fixed-size steps so that
|
|
||||||
-- it is impossible to jump across gaps due to server lag
|
|
||||||
-- causing large timesteps
|
|
||||||
local total_distance = dtime * ( staticdata.velocity or 0 )
|
|
||||||
local remaining_distance = total_distance
|
|
||||||
|
|
||||||
process_acceleration(self,dtime * max_step_distance / total_distance)
|
|
||||||
|
|
||||||
-- Skip processing stopped railcarts
|
|
||||||
if not staticdata.velocity or math.abs(staticdata.velocity) < 0.05 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
while remaining_distance > 0.1 do
|
|
||||||
local step_distance = do_movement_step(self, remaining_distance)
|
|
||||||
if step_distance > 0.1 then
|
|
||||||
process_acceleration(self, dtime * step_distance / total_distance)
|
|
||||||
end
|
|
||||||
remaining_distance = remaining_distance - step_distance
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Clear punched flag now that movement for this step has been completed
|
|
||||||
self._punched = false
|
|
||||||
end
|
|
||||||
|
|
||||||
function cart:on_step(dtime)
|
function cart:on_step(dtime)
|
||||||
hopper_take_item(self, dtime)
|
hopper_take_item(self, dtime)
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
|
@ -652,6 +675,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
for _, node_pos in pairs({{r, 0}, {0, r}, {-r, 0}, {0, -r}}) do
|
for _, node_pos in pairs({{r, 0}, {0, r}, {-r, 0}, {0, -r}}) do
|
||||||
if minetest.get_node(vector.offset(pos, node_pos[1], 0, node_pos[2])).name == "mcl_core:cactus" then
|
if minetest.get_node(vector.offset(pos, node_pos[1], 0, node_pos[2])).name == "mcl_core:cactus" then
|
||||||
detach_driver(self)
|
detach_driver(self)
|
||||||
|
local drop = def.drop
|
||||||
for d = 1, #drop do
|
for d = 1, #drop do
|
||||||
minetest.add_item(pos, drop[d])
|
minetest.add_item(pos, drop[d])
|
||||||
end
|
end
|
||||||
|
@ -811,11 +835,7 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
|
||||||
le._staticdata = make_staticdata( railtype, railpos, cart_dir )
|
le._staticdata = make_staticdata( railtype, railpos, cart_dir )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle track behaviors
|
handle_cart_enter( railpos )
|
||||||
local node_def = minetest.registered_nodes[node.name]
|
|
||||||
if node_def._mcl_minecarts_on_enter then
|
|
||||||
node_def._mcl_minecarts_on_enter(railpos, cart)
|
|
||||||
end
|
|
||||||
|
|
||||||
local pname = ""
|
local pname = ""
|
||||||
if placer then
|
if placer then
|
||||||
|
@ -891,30 +911,30 @@ Register a minecart
|
||||||
* on_activate_by_rail: Called when above activator rail
|
* on_activate_by_rail: Called when above activator rail
|
||||||
* creative: If false, don't show in Creative Inventory
|
* creative: If false, don't show in Creative Inventory
|
||||||
]]
|
]]
|
||||||
local function register_minecart(itemstring, entity_id, description, tt_help, longdesc, usagehelp, mesh, textures, icon, drop, on_rightclick, on_activate_by_rail, creative)
|
local function register_minecart(def)
|
||||||
register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
|
register_entity(def.entity_id, def)
|
||||||
register_craftitem(itemstring, entity_id, description, tt_help, longdesc, usagehelp, icon, creative)
|
register_craftitem(def.itemstring, def.entity_id, def.description, def.tt_help, def.longdesc, def.usagehelp, def.icon, def.creative)
|
||||||
if minetest.get_modpath("doc_identifier") then
|
if minetest.get_modpath("doc_identifier") then
|
||||||
doc.sub.identifier.register_object(entity_id, "craftitems", itemstring)
|
doc.sub.identifier.register_object(def.entity_id, "craftitems", itemstring)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Minecart
|
-- Minecart
|
||||||
register_minecart(
|
register_minecart({
|
||||||
"mcl_minecarts:minecart",
|
itemstring = "mcl_minecarts:minecart",
|
||||||
"mcl_minecarts:minecart",
|
entity_id = "mcl_minecarts:minecart",
|
||||||
S("Minecart"),
|
description = S("Minecart"),
|
||||||
S("Vehicle for fast travel on rails"),
|
tt_helop = S("Vehicle for fast travel on rails"),
|
||||||
S("Minecarts can be used for a quick transportion on rails.") .. "\n" ..
|
long_descp = S("Minecarts can be used for a quick transportion on rails.") .. "\n" ..
|
||||||
S("Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type."),
|
S("Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type."),
|
||||||
S("You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.") .. "\n" ..
|
S("You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.") .. "\n" ..
|
||||||
S("To obtain the minecart, punch it while holding down the sneak key.") .. "\n" ..
|
S("To obtain the minecart, punch it while holding down the sneak key.") .. "\n" ..
|
||||||
S("If it moves over a powered activator rail, you'll get ejected."),
|
S("If it moves over a powered activator rail, you'll get ejected."),
|
||||||
"mcl_minecarts_minecart.b3d",
|
mesh = "mcl_minecarts_minecart.b3d",
|
||||||
{"mcl_minecarts_minecart.png"},
|
textures = {"mcl_minecarts_minecart.png"},
|
||||||
"mcl_minecarts_minecart_normal.png",
|
icon = "mcl_minecarts_minecart_normal.png",
|
||||||
{"mcl_minecarts:minecart"},
|
drop = {"mcl_minecarts:minecart"},
|
||||||
function(self, clicker)
|
on_rightclick = function(self, clicker)
|
||||||
local name = clicker:get_player_name()
|
local name = clicker:get_player_name()
|
||||||
if not clicker or not clicker:is_player() then
|
if not clicker or not clicker:is_player() then
|
||||||
return
|
return
|
||||||
|
@ -937,34 +957,43 @@ register_minecart(
|
||||||
end
|
end
|
||||||
end, name)
|
end, name)
|
||||||
end
|
end
|
||||||
end, activate_normal_minecart
|
end,
|
||||||
)
|
on_activate_by_rail = activate_normal_minecart
|
||||||
|
})
|
||||||
|
|
||||||
-- Minecart with Chest
|
-- Minecart with Chest
|
||||||
register_minecart(
|
register_minecart({
|
||||||
"mcl_minecarts:chest_minecart",
|
itemstring = "mcl_minecarts:chest_minecart",
|
||||||
"mcl_minecarts:chest_minecart",
|
entity_id = "mcl_minecarts:chest_minecart",
|
||||||
S("Minecart with Chest"),
|
description = S("Minecart with Chest"),
|
||||||
nil, nil, nil,
|
tt_help = nil,
|
||||||
"mcl_minecarts_minecart_chest.b3d",
|
longdesc = nil,
|
||||||
{ "mcl_chests_normal.png", "mcl_minecarts_minecart.png" },
|
usagehelp = nil,
|
||||||
"mcl_minecarts_minecart_chest.png",
|
mesh = "mcl_minecarts_minecart_chest.b3d",
|
||||||
{"mcl_minecarts:minecart", "mcl_chests:chest"},
|
textures = {
|
||||||
nil, nil, true)
|
"mcl_chests_normal.png",
|
||||||
|
"mcl_minecarts_minecart.png"
|
||||||
|
},
|
||||||
|
icon = "mcl_minecarts_minecart_chest.png",
|
||||||
|
drop = {"mcl_minecarts:minecart", "mcl_chests:chest"},
|
||||||
|
on_rightclick = nil,
|
||||||
|
on_activate_by_rail = nil,
|
||||||
|
creative = true
|
||||||
|
})
|
||||||
mcl_entity_invs.register_inv("mcl_minecarts:chest_minecart","Minecart",27,false,true)
|
mcl_entity_invs.register_inv("mcl_minecarts:chest_minecart","Minecart",27,false,true)
|
||||||
|
|
||||||
-- Minecart with Furnace
|
-- Minecart with Furnace
|
||||||
register_minecart(
|
register_minecart({
|
||||||
"mcl_minecarts:furnace_minecart",
|
itemstring = "mcl_minecarts:furnace_minecart",
|
||||||
"mcl_minecarts:furnace_minecart",
|
entity_id = "mcl_minecarts:furnace_minecart",
|
||||||
S("Minecart with Furnace"),
|
description = S("Minecart with Furnace"),
|
||||||
nil,
|
tt_help = nil,
|
||||||
S("A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel."),
|
longdesc = S("A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel."),
|
||||||
S("Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.") .. "\n" ..
|
usagehelp = S("Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.") .. "\n" ..
|
||||||
S("To obtain the minecart and furnace, punch them while holding down the sneak key."),
|
S("To obtain the minecart and furnace, punch them while holding down the sneak key."),
|
||||||
|
|
||||||
"mcl_minecarts_minecart_block.b3d",
|
mesh = "mcl_minecarts_minecart_block.b3d",
|
||||||
{
|
textures = {
|
||||||
"default_furnace_top.png",
|
"default_furnace_top.png",
|
||||||
"default_furnace_top.png",
|
"default_furnace_top.png",
|
||||||
"default_furnace_front.png",
|
"default_furnace_front.png",
|
||||||
|
@ -973,10 +1002,10 @@ register_minecart(
|
||||||
"default_furnace_side.png",
|
"default_furnace_side.png",
|
||||||
"mcl_minecarts_minecart.png",
|
"mcl_minecarts_minecart.png",
|
||||||
},
|
},
|
||||||
"mcl_minecarts_minecart_furnace.png",
|
icon = "mcl_minecarts_minecart_furnace.png",
|
||||||
{"mcl_minecarts:minecart", "mcl_furnaces:furnace"},
|
drop = {"mcl_minecarts:minecart", "mcl_furnaces:furnace"},
|
||||||
|
on_rightclick = function(self, clicker)
|
||||||
-- Feed furnace with coal
|
-- Feed furnace with coal
|
||||||
function(self, clicker)
|
|
||||||
if not clicker or not clicker:is_player() then
|
if not clicker or not clicker:is_player() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -1004,17 +1033,21 @@ register_minecart(
|
||||||
"mcl_minecarts_minecart.png",
|
"mcl_minecarts_minecart.png",
|
||||||
}})
|
}})
|
||||||
end
|
end
|
||||||
end, nil, true
|
end,
|
||||||
)
|
on_activate_by_rail = nil,
|
||||||
|
creative = true
|
||||||
|
})
|
||||||
|
|
||||||
-- Minecart with Command Block
|
-- Minecart with Command Block
|
||||||
register_minecart(
|
register_minecart({
|
||||||
"mcl_minecarts:command_block_minecart",
|
itemstring = "mcl_minecarts:command_block_minecart",
|
||||||
"mcl_minecarts:command_block_minecart",
|
entity_id = "mcl_minecarts:command_block_minecart",
|
||||||
S("Minecart with Command Block"),
|
description = S("Minecart with Command Block"),
|
||||||
nil, nil, nil,
|
tt_help = nil,
|
||||||
"mcl_minecarts_minecart_block.b3d",
|
loncdesc = nil,
|
||||||
{
|
usagehelp = nil,
|
||||||
|
mesh = "mcl_minecarts_minecart_block.b3d",
|
||||||
|
textures = {
|
||||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||||
|
@ -1023,41 +1056,50 @@ register_minecart(
|
||||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||||
"mcl_minecarts_minecart.png",
|
"mcl_minecarts_minecart.png",
|
||||||
},
|
},
|
||||||
"mcl_minecarts_minecart_command_block.png",
|
icon = "mcl_minecarts_minecart_command_block.png",
|
||||||
{"mcl_minecarts:minecart"},
|
drop = {"mcl_minecarts:minecart"},
|
||||||
nil, nil, false
|
on_rightclick = nil,
|
||||||
)
|
on_activate_by_rail = nil,
|
||||||
|
creative = false
|
||||||
|
})
|
||||||
|
|
||||||
-- Minecart with Hopper
|
-- Minecart with Hopper
|
||||||
register_minecart(
|
register_minecart({
|
||||||
"mcl_minecarts:hopper_minecart",
|
itemstring = "mcl_minecarts:hopper_minecart",
|
||||||
"mcl_minecarts:hopper_minecart",
|
entity_id = "mcl_minecarts:hopper_minecart",
|
||||||
S("Minecart with Hopper"),
|
description = S("Minecart with Hopper"),
|
||||||
nil, nil, nil,
|
tt_help = nil,
|
||||||
"mcl_minecarts_minecart_hopper.b3d",
|
longdesc = nil,
|
||||||
{
|
usagehelp = nil,
|
||||||
|
mesh = "mcl_minecarts_minecart_hopper.b3d",
|
||||||
|
textures = {
|
||||||
"mcl_hoppers_hopper_inside.png",
|
"mcl_hoppers_hopper_inside.png",
|
||||||
"mcl_minecarts_minecart.png",
|
"mcl_minecarts_minecart.png",
|
||||||
"mcl_hoppers_hopper_outside.png",
|
"mcl_hoppers_hopper_outside.png",
|
||||||
"mcl_hoppers_hopper_top.png",
|
"mcl_hoppers_hopper_top.png",
|
||||||
},
|
},
|
||||||
"mcl_minecarts_minecart_hopper.png",
|
icon = "mcl_minecarts_minecart_hopper.png",
|
||||||
{"mcl_minecarts:minecart", "mcl_hoppers:hopper"},
|
drop = {"mcl_minecarts:minecart", "mcl_hoppers:hopper"},
|
||||||
nil, nil, true
|
on_rightclick = nil,
|
||||||
)
|
on_activate_by_rail = nil,
|
||||||
|
_mcl_minecarts_on_enter = function(self,pos)
|
||||||
|
-- TODO: try to pull from containers into our inventory
|
||||||
|
end,
|
||||||
|
creative = true
|
||||||
|
})
|
||||||
mcl_entity_invs.register_inv("mcl_minecarts:hopper_minecart", "Hopper Minecart", 5, false, true)
|
mcl_entity_invs.register_inv("mcl_minecarts:hopper_minecart", "Hopper Minecart", 5, false, true)
|
||||||
|
|
||||||
-- Minecart with TNT
|
-- Minecart with TNT
|
||||||
register_minecart(
|
register_minecart({
|
||||||
"mcl_minecarts:tnt_minecart",
|
itemstring = "mcl_minecarts:tnt_minecart",
|
||||||
"mcl_minecarts:tnt_minecart",
|
entity_id = "mcl_minecarts:tnt_minecart",
|
||||||
S("Minecart with TNT"),
|
description = S("Minecart with TNT"),
|
||||||
S("Vehicle for fast travel on rails").."\n"..S("Can be ignited by tools or powered activator rail"),
|
tt_help = S("Vehicle for fast travel on rails").."\n"..S("Can be ignited by tools or powered activator rail"),
|
||||||
S("A minecart with TNT is an explosive vehicle that travels on rail."),
|
longdesc = S("A minecart with TNT is an explosive vehicle that travels on rail."),
|
||||||
S("Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.") .. "\n" ..
|
usagehelp = S("Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.") .. "\n" ..
|
||||||
S("To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited."),
|
S("To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited."),
|
||||||
"mcl_minecarts_minecart_block.b3d",
|
mesh = "mcl_minecarts_minecart_block.b3d",
|
||||||
{
|
textures = {
|
||||||
"default_tnt_top.png",
|
"default_tnt_top.png",
|
||||||
"default_tnt_bottom.png",
|
"default_tnt_bottom.png",
|
||||||
"default_tnt_side.png",
|
"default_tnt_side.png",
|
||||||
|
@ -1066,10 +1108,10 @@ register_minecart(
|
||||||
"default_tnt_side.png",
|
"default_tnt_side.png",
|
||||||
"mcl_minecarts_minecart.png",
|
"mcl_minecarts_minecart.png",
|
||||||
},
|
},
|
||||||
"mcl_minecarts_minecart_tnt.png",
|
icon = "mcl_minecarts_minecart_tnt.png",
|
||||||
{"mcl_minecarts:minecart", "mcl_tnt:tnt"},
|
drop = {"mcl_minecarts:minecart", "mcl_tnt:tnt"},
|
||||||
|
on_rightclick = function(self, clicker)
|
||||||
-- Ingite
|
-- Ingite
|
||||||
function(self, clicker)
|
|
||||||
if not clicker or not clicker:is_player() then
|
if not clicker or not clicker:is_player() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -1086,7 +1128,10 @@ register_minecart(
|
||||||
end
|
end
|
||||||
activate_tnt_minecart(self)
|
activate_tnt_minecart(self)
|
||||||
end
|
end
|
||||||
end, activate_tnt_minecart)
|
end,
|
||||||
|
on_activate_by_rail = activate_tnt_minecart,
|
||||||
|
creative = false
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
|
|
Loading…
Reference in a new issue