1
0
Fork 0

Remove do_movement dependency on the existence of a cart luaentity

This commit is contained in:
teknomunk 2024-04-09 11:59:45 +00:00
parent 79d068b98a
commit a4987f63e9
4 changed files with 82 additions and 63 deletions

View File

@ -257,7 +257,12 @@ function DEFAULT_CART_DEF:on_step(dtime)
end end
if staticdata.connected_at then if staticdata.connected_at then
do_movement(self, dtime) do_movement(staticdata, dtime)
-- Update entity
local pos = mod.get_cart_position(staticdata)
if pos then self.object:move_to(pos) end
mod.update_cart_orientation(self)
else else
do_detached_movement(self, dtime) do_detached_movement(self, dtime)
end end

View File

@ -7,6 +7,8 @@ local S = minetest.get_translator(modname)
local mcl_debug,DEBUG = mcl_util.make_mcl_logger("mcl_logging_minecart_debug", "Minecart Debug") local mcl_debug,DEBUG = mcl_util.make_mcl_logger("mcl_logging_minecart_debug", "Minecart Debug")
local friction = mcl_minecarts.FRICTION local friction = mcl_minecarts.FRICTION
local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH
DEBUG = true
mcl_debug = function(msg) print(msg) end
-- Imports -- Imports
local train_length = mod.train_length local train_length = mod.train_length
@ -17,16 +19,17 @@ local update_cart_orientation = mod.update_cart_orientation
local get_cart_data = mod.get_cart_data local get_cart_data = mod.get_cart_data
local get_cart_position = mod.get_cart_position local get_cart_position = mod.get_cart_position
local function detach_minecart(self) local function detach_minecart(staticdata)
local staticdata = self._staticdata
staticdata.connected_at = nil staticdata.connected_at = nil
self.object:set_velocity(staticdata.dir * staticdata.velocity)
local luaentity = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
if luaentity then
luaentity.object:set_velocity(staticdata.dir * staticdata.velocity)
end
end end
mod.detach_minecart = detach_minecart mod.detach_minecart = detach_minecart
local function try_detach_minecart(self) local function try_detach_minecart(staticdata)
local staticdata = self._staticdata
if not staticdata then return end if not staticdata then return end
-- Don't try to detach if alread detached -- Don't try to detach if alread detached
@ -34,7 +37,7 @@ local function try_detach_minecart(self)
local node = minetest.get_node(staticdata.connected_at) local node = minetest.get_node(staticdata.connected_at)
if minetest.get_item_group(node.name, "rail") == 0 then if minetest.get_item_group(node.name, "rail") == 0 then
detach_minecart(self) detach_minecart(staticdata)
end end
end end
@ -50,9 +53,8 @@ local enter_exit_checks = {
{ 0,-1, 0, "_side" }, { 0,-1, 0, "_side" },
} }
local function handle_cart_enter_exit(self, pos, next_dir, event) local function handle_cart_enter_exit(staticdata, pos, next_dir, event)
local staticdata = self._staticdata local luaentity = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
local dir = staticdata.dir local dir = staticdata.dir
local right = vector.new( dir.z, dir.y, -dir.x) local right = vector.new( dir.z, dir.y, -dir.x)
local up = vector.new(0,1,0) local up = vector.new(0,1,0)
@ -64,16 +66,20 @@ local function handle_cart_enter_exit(self, pos, next_dir, event)
-- node-specific hook -- node-specific hook
local hook_name = "_mcl_minecarts_"..event..check[4] local hook_name = "_mcl_minecarts_"..event..check[4]
local hook = node_def[hook_name] local hook = node_def[hook_name]
if hook then hook(check_pos, self, next_dir, pos) end if hook then hook(check_pos, luaentity, next_dir, pos) end
-- global minecart hook -- global minecart hook
hook = mcl_minecarts[event..check[4]] hook = mcl_minecarts[event..check[4]]
if hook then hook(check_pos, self, next_dir, node_def) end if hook then hook(check_pos, luaentity, next_dir, node_def) end
end end
end end
-- Handle cart-specific behaviors -- Handle cart-specific behaviors
local hook = self["_mcl_minecarts_"..event] if luaentity then
local hook = luaentity["_mcl_minecarts_"..event]
else
minetest.log("warning", "TODO: chanve _mcl_minecarts_"..event.." calling so it is not dependent on the existence of a luaentity")
end
if hook then hook(self, pos) end if hook then hook(self, pos) end
end end
local function set_metadata_cart_status(pos, uuid, state) local function set_metadata_cart_status(pos, uuid, state)
@ -82,26 +88,26 @@ local function set_metadata_cart_status(pos, uuid, state)
carts[uuid] = state carts[uuid] = state
meta:set_string("_mcl_minecarts_carts", minetest.serialize(carts)) meta:set_string("_mcl_minecarts_carts", minetest.serialize(carts))
end end
local function handle_cart_enter(self, pos, next_dir) local function handle_cart_enter(staticdata, pos, next_dir)
--print("entering "..tostring(pos)) --print("entering "..tostring(pos))
set_metadata_cart_status(pos, self._staticdata.uuid, 1) set_metadata_cart_status(pos, staticdata.uuid, 1)
handle_cart_enter_exit(self, pos, next_dir, "on_enter" ) handle_cart_enter_exit(staticdata, pos, next_dir, "on_enter" )
end end
local function handle_cart_leave(self, pos, next_dir) local function handle_cart_leave(staticdata, pos, next_dir)
--print("leaving "..tostring(pos)) --print("leaving "..tostring(pos))
set_metadata_cart_status(pos, self._staticdata.uuid, nil) set_metadata_cart_status(pos, staticdata.uuid, nil)
handle_cart_enter_exit(self, pos, next_dir, "on_leave" ) handle_cart_enter_exit(staticdata, pos, next_dir, "on_leave" )
end end
local function handle_cart_node_watches(self, dtime) local function handle_cart_node_watches(staticdata, dtime)
local staticdata = self._staticdata
local watches = staticdata.node_watches or {} local watches = staticdata.node_watches or {}
local new_watches = {} local new_watches = {}
local luaentity = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
for _,node_pos in ipairs(watches) do for _,node_pos in ipairs(watches) do
local node = minetest.get_node(node_pos) local node = minetest.get_node(node_pos)
local node_def = minetest.registered_nodes[node.name] local node_def = minetest.registered_nodes[node.name]
if node_def then if node_def then
local hook = node_def._mcl_minecarts_node_on_step local hook = node_def._mcl_minecarts_node_on_step
if hook and hook(node_pos, self, dtime) then if hook and hook(node_pos, luaentity, dtime) then
new_watches[#new_watches+1] = node_pos new_watches[#new_watches+1] = node_pos
end end
end end
@ -110,7 +116,7 @@ local function handle_cart_node_watches(self, dtime)
staticdata.node_watches = new_watches staticdata.node_watches = new_watches
end end
local function handle_cart_collision(cart1, prev_pos, next_dir) local function handle_cart_collision(cart1_staticdata, prev_pos, next_dir)
-- Look ahead one block -- Look ahead one block
local pos = vector.add(prev_pos, next_dir) local pos = vector.add(prev_pos, next_dir)
@ -127,7 +133,7 @@ local function handle_cart_collision(cart1, prev_pos, next_dir)
uuid = nil uuid = nil
end end
if uuid and uuid ~= cart1._staticdata.uuid then cart_uuid = uuid end if uuid and uuid ~= cart1_staticdata.uuid then cart_uuid = uuid end
end end
if dirty then if dirty then
meta:set_string("_mcl_minecarts_carts",minetest.serialize(carts)) meta:set_string("_mcl_minecarts_carts",minetest.serialize(carts))
@ -137,12 +143,11 @@ local function handle_cart_collision(cart1, prev_pos, next_dir)
if not cart_uuid then return end if not cart_uuid then return end
-- Don't collide with the train car in front of you -- Don't collide with the train car in front of you
if cart1._staticdata.ahead == cart_uuid then return end if cart1_staticdata.ahead == cart_uuid then return end
minetest.log("action","cart #"..cart1._staticdata.uuid.." collided with cart #"..cart_uuid.." at "..tostring(pos)) minetest.log("action","cart #"..cart1_staticdata.uuid.." collided with cart #"..cart_uuid.." at "..tostring(pos))
-- Standard Collision Handling -- Standard Collision Handling
local cart1_staticdata = cart1._staticdata
local cart2_staticdata = get_cart_data(cart_uuid) local cart2_staticdata = get_cart_data(cart_uuid)
local u1 = cart1_staticdata.velocity local u1 = cart1_staticdata.velocity
@ -171,8 +176,8 @@ local function handle_cart_collision(cart1, prev_pos, next_dir)
cart2_staticdata.dir = mcl_minecarts:get_rail_direction(cart2_staticdata.connected_at, cart1_staticdata.dir) cart2_staticdata.dir = mcl_minecarts:get_rail_direction(cart2_staticdata.connected_at, cart1_staticdata.dir)
end end
local function vector_away_from_players(self, staticdata) local function vector_away_from_players(cart, staticdata)
local function player_repel(obj, self) local function player_repel(obj)
-- Only repel from players -- Only repel from players
local player_name = obj:get_player_name() local player_name = obj:get_player_name()
if not player_name or player_name == "" then return false end if not player_name or player_name == "" then return false end
@ -184,8 +189,13 @@ local function vector_away_from_players(self, staticdata)
return true return true
end end
for _,obj in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.1)) do -- Get the cart position
if player_repel(obj, self) then local cart_pos = mod.get_cart_position(staticdata)
if cart then cart_pos = cart.object:get_pos() end
if not cart_pos then return nil end
for _,obj in pairs(minetest.get_objects_inside_radius(cart_pos, 1.1)) do
if player_repel(obj) then
return obj:get_pos() - self.object:get_pos() return obj:get_pos() - self.object:get_pos()
end end
end end
@ -193,8 +203,8 @@ local function vector_away_from_players(self, staticdata)
return nil return nil
end end
local function direction_away_from_players(self, staticdata) local function direction_away_from_players(staticdata)
local diff = vector_away_from_players(self, staticdata) local diff = vector_away_from_players(staticdata)
if not diff then return 0 end if not diff then return 0 end
local length = vector.distance(vector.new(0,0,0),diff) local length = vector.distance(vector.new(0,0,0),diff)
@ -217,7 +227,7 @@ local function direction_away_from_players(self, staticdata)
return 0 return 0
end end
local function calculate_acceleration(self, staticdata) local function calculate_acceleration(staticdata)
local acceleration = 0 local acceleration = 0
-- Fix up movement data -- Fix up movement data
@ -233,9 +243,11 @@ local function calculate_acceleration(self, staticdata)
local node_def = minetest.registered_nodes[node_name] local node_def = minetest.registered_nodes[node_name]
local max_vel = mcl_minecarts.speed_max local max_vel = mcl_minecarts.speed_max
if self._go_forward then local ctrl = staticdata.controls or {}
if ctrl.go_forward then
acceleration = 4 acceleration = 4
elseif self._brake then elseif ctrl.brake then
acceleration = -1.5 acceleration = -1.5
elseif (staticdata.fueltime or 0) > 0 and staticdata.velocity <= 4 then elseif (staticdata.fueltime or 0) > 0 and staticdata.velocity <= 4 then
acceleration = 0.6 acceleration = 0.6
@ -256,7 +268,7 @@ local function calculate_acceleration(self, staticdata)
return acceleration return acceleration
end end
local function reverse_direction(self, staticdata) local function reverse_direction(staticdata)
if staticdata.behind or staticdata.ahead then if staticdata.behind or staticdata.ahead then
reverse_train(self) reverse_train(self)
return return
@ -265,18 +277,17 @@ local function reverse_direction(self, staticdata)
mod.reverse_cart_direction(staticdata) mod.reverse_cart_direction(staticdata)
end end
local function do_movement_step(self, dtime) local function do_movement_step(staticdata, dtime)
local staticdata = self._staticdata
if not staticdata.connected_at then return 0 end if not staticdata.connected_at then return 0 end
-- Calculate timestep remaiing in this block -- Calculate timestep remaiing in this block
local x_0 = staticdata.distance or 0 local x_0 = staticdata.distance or 0
local remaining_in_block = 1 - x_0 local remaining_in_block = 1 - x_0
local a = calculate_acceleration(self, staticdata) local a = calculate_acceleration(staticdata)
local v_0 = staticdata.velocity local v_0 = staticdata.velocity
-- Repel minecarts -- Repel minecarts
local away = direction_away_from_players(self, staticdata) local away = direction_away_from_players(nil, staticdata)
if away > 0 then if away > 0 then
v_0 = away v_0 = away
elseif away < 0 then elseif away < 0 then
@ -379,10 +390,10 @@ local function do_movement_step(self, dtime)
handle_cart_collision(self, pos, next_dir) handle_cart_collision(self, pos, next_dir)
-- Leave the old node -- Leave the old node
handle_cart_leave(self, old_pos, next_dir ) handle_cart_leave(staticdata, old_pos, next_dir )
-- Enter the new node -- Enter the new node
handle_cart_enter(self, pos, next_dir) handle_cart_enter(staticdata, pos, next_dir)
-- Handle end of track -- Handle end of track
if next_dir == staticdata.dir * -1 and next_dir.y == 0 then if next_dir == staticdata.dir * -1 and next_dir.y == 0 then
@ -399,7 +410,7 @@ local function do_movement_step(self, dtime)
-- Velocity should be zero at this point -- Velocity should be zero at this point
staticdata.velocity = 0 staticdata.velocity = 0
reverse_direction(self, staticdata) reverse_direction(staticdata)
-- Intermediate movement -- Intermediate movement
pos = staticdata.connected_at + staticdata.dir * staticdata.distance pos = staticdata.connected_at + staticdata.dir * staticdata.distance
@ -408,11 +419,6 @@ local function do_movement_step(self, dtime)
pos = pos + staticdata.dir * staticdata.distance pos = pos + staticdata.dir * staticdata.distance
end end
self.object:move_to(pos)
-- Update cart orientation
update_cart_orientation(self)
-- Debug reporting -- Debug reporting
if DEBUG and ( v_0 > 0 or v_1 > 0 ) then if DEBUG and ( v_0 > 0 or v_1 > 0 ) then
mcl_debug( " cart #"..tostring(staticdata.uuid).. mcl_debug( " cart #"..tostring(staticdata.uuid)..
@ -433,8 +439,8 @@ local function do_movement_step(self, dtime)
return dtime - timestep return dtime - timestep
end end
local function do_movement( self, dtime ) local function do_movement( staticdata, dtime )
local staticdata = self._staticdata assert(staticdata)
-- Allow the carts to be delay for the rest of the world to react before moving again -- Allow the carts to be delay for the rest of the world to react before moving again
if ( staticdata.delay or 0 ) > dtime then if ( staticdata.delay or 0 ) > dtime then
@ -448,13 +454,13 @@ local function do_movement( self, dtime )
-- it impossible to jump across gaps due to server lag -- it impossible to jump across gaps due to server lag
-- causing large timesteps -- causing large timesteps
while dtime > 0 do while dtime > 0 do
local new_dtime = do_movement_step(self, dtime) local new_dtime = do_movement_step(staticdata, dtime)
try_detach_minecart(self) try_detach_minecart(staticdata)
update_train(self) update_train(staticdata)
-- Handle node watches here in steps to prevent server lag from changing behavior -- Handle node watches here in steps to prevent server lag from changing behavior
handle_cart_node_watches(self, dtime - new_dtime) handle_cart_node_watches(staticdata, dtime - new_dtime)
dtime = new_dtime dtime = new_dtime
end end

View File

@ -9,6 +9,8 @@ local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH
-- Follow .behind to the back end of a train -- Follow .behind to the back end of a train
local function find_back(start) local function find_back(start)
assert(start)
while start.behind do while start.behind do
local nxt = get_cart_data(start.behind) local nxt = get_cart_data(start.behind)
if not nxt then return start end if not nxt then return start end
@ -18,8 +20,10 @@ local function find_back(start)
end end
-- Iterate across all the cars in a train -- Iterate across all the cars in a train
local function train_cars(anchor) local function train_cars(staticdata)
local back = find_back(anchor._staticdata) assert(staticdata)
local back = find_back(staticdata)
local limit = MAX_TRAIN_LENGTH local limit = MAX_TRAIN_LENGTH
return function() return function()
if not back or limit <= 0 then return end if not back or limit <= 0 then return end
@ -84,8 +88,8 @@ local function break_train_at(cart)
end end
mod.break_train_at = break_train_at mod.break_train_at = break_train_at
function mod.update_train(cart) function mod.update_train(staticdata)
local staticdata = cart._staticdata --local staticdata = cart._staticdata
-- Only update from the back -- Only update from the back
if staticdata.behind or not staticdata.ahead then return end if staticdata.behind or not staticdata.ahead then return end
@ -97,7 +101,7 @@ function mod.update_train(cart)
-- Calculate the maximum velocity of all train cars -- Calculate the maximum velocity of all train cars
local velocity = 0 local velocity = 0
local count = 0 local count = 0
for cart in train_cars(cart) do for cart in train_cars(staticdata) do
velocity = velocity + (cart.velocity or 0) velocity = velocity + (cart.velocity or 0)
count = count + 1 count = count + 1
end end
@ -106,7 +110,7 @@ function mod.update_train(cart)
-- Set the entire train to the average velocity -- Set the entire train to the average velocity
local behind = nil local behind = nil
for c in train_cars(cart) do for c in train_cars(staticdata) do
local e = 0 local e = 0
local separation local separation
local cart_velocity = velocity local cart_velocity = velocity
@ -145,7 +149,6 @@ function mod.link_cart_ahead(cart, cart_ahead)
ca_staticdata.behind = staticdata.uuid ca_staticdata.behind = staticdata.uuid
end end
function mod.reverse_train(cart) function mod.reverse_train(cart)
for c in train_cars(cart) do for c in train_cars(cart) do
mod.reverse_cart_direction(c) mod.reverse_cart_direction(c)

View File

@ -253,6 +253,11 @@ local def_hopper = {
cart:remove_node_watch(pos) cart:remove_node_watch(pos)
end, end,
_mcl_minecarts_node_on_step = function(pos, cart, dtime) _mcl_minecarts_node_on_step = function(pos, cart, dtime)
if not cart then
minetest.log("warning", "trying to process hopper-to-minecart movement without luaentity")
return
end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local timer = meta:get_int("minecart_hopper_timer") local timer = meta:get_int("minecart_hopper_timer")