mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-30 22:41:20 +01:00
Refactor enter/leave hook processing, add node watches for implementing hopper-to-minecart functionality (should properly handle heavy server lag without missing any time), temporarily disable hopper push/pull to minecart in mcl_hoppers, prepare to move minecart-specific on_step behavior out of main on_step function and to a minecart-specific handler
This commit is contained in:
parent
b0c075714f
commit
6c6bfcfcb2
3 changed files with 103 additions and 53 deletions
|
@ -68,7 +68,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
An array of (u,v,w) positions to check. Actual direction is u * dir + v * right + w * vector.new(0,1,0)
|
An array of (u,v,w) positions to check. Actual direction is u * dir + v * right + w * up
|
||||||
]]
|
]]
|
||||||
local rail_checks = {
|
local rail_checks = {
|
||||||
{ 1, 0, 0 }, -- forwards
|
{ 1, 0, 0 }, -- forwards
|
||||||
|
|
|
@ -21,27 +21,11 @@ local function mcl_log(message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function handle_cart_enter(self, pos, next_dir)
|
mcl_minecarts.on_enter_below = function(pos, cart, next_dir, node_def)
|
||||||
local staticdata = self._staticdata
|
local staticdata = cart._staticdata
|
||||||
local node = minetest.get_node(pos)
|
if (node_def.groups.hopper or 0) == 0 then return end
|
||||||
|
|
||||||
-- Handle track behaviors
|
local hopper_pulled = mcl_hoppers.pull_from_minecart( cart, pos, cart._inv_size or 0 )
|
||||||
local node_def = minetest.registered_nodes[node.name]
|
|
||||||
if node_def._mcl_minecarts_on_enter then
|
|
||||||
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 under_node_def._mcl_minecarts_on_enter_above then
|
|
||||||
under_node_def._mcl_minecarts_on_enter_above(under_pos, self)
|
|
||||||
else
|
|
||||||
local hopper_pulled = false
|
|
||||||
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
|
|
||||||
hopper_pulled = mcl_hoppers.pull_from_minecart( self, under_pos, self._inv_size or 0 )
|
|
||||||
if DEBUG then print( "Attempt pull_from_minecart, hopper_pulled="..tostring(hopper_pulled) ) end
|
if DEBUG then print( "Attempt pull_from_minecart, hopper_pulled="..tostring(hopper_pulled) ) end
|
||||||
|
|
||||||
if hopper_pulled and next_dir ~= staticdata.dir then
|
if hopper_pulled and next_dir ~= staticdata.dir then
|
||||||
|
@ -51,29 +35,65 @@ local function handle_cart_enter(self, pos, next_dir)
|
||||||
staticdata.delay = 1.5
|
staticdata.delay = 1.5
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle above-track behaviors (to ensure hoppers can transfer at least one item)
|
--[[
|
||||||
local above_pos = pos + vector.new(0,1,0)
|
Array of hooks { {u,v,w}, name }
|
||||||
local above_node_name = minetest.get_node(above_pos).name
|
Actual position is pos + u * dir + v * right + w * up
|
||||||
local above_node_def = minetest.registered_nodes[above_node_name]
|
]]
|
||||||
if above_node_def._mcl_minecarts_on_enter_below then
|
local enter_exit_checks = {
|
||||||
above_node_def._mcl_minecarts_on_enter_below(above_pos, self)
|
{ 0, 0, 0, "" },
|
||||||
|
{ 0, 0, 1, "_above" },
|
||||||
|
{ 0, 0,-1, "_below" },
|
||||||
|
{ 0, 1, 0, "_side" },
|
||||||
|
{ 0,-1, 0, "_side" },
|
||||||
|
}
|
||||||
|
|
||||||
|
local function handle_cart_enter_exit(self, pos, next_dir, event)
|
||||||
|
local staticdata = self._staticdata
|
||||||
|
|
||||||
|
local dir = staticdata.dir
|
||||||
|
local right = vector.new( dir.z, dir.y, -dir.x)
|
||||||
|
local up = vector.new(0,1,0)
|
||||||
|
for _,check in ipairs(enter_exit_checks) do
|
||||||
|
local check_pos = pos + dir * check[1] + right * check[2] + up * check[3]
|
||||||
|
local node = minetest.get_node(check_pos)
|
||||||
|
local node_def = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
|
-- node-specific hook
|
||||||
|
local hook = node_def["_mcl_minecarts_"..event..check[4]]
|
||||||
|
if hook then hook(check_pos, self, next_dir) end
|
||||||
|
|
||||||
|
-- global minecart hook
|
||||||
|
hook = mcl_minecarts[event..check[4]]
|
||||||
|
if hook then hook(check_pos, self, next_dir, node_def) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle cart-specific behaviors
|
-- Handle cart-specific behaviors
|
||||||
if self._mcl_minecarts_on_enter then
|
local hook = self["_mcl_minecarts_"..event]
|
||||||
self._mcl_minecarts_on_enter(self, pos)
|
if hook then hook(self, pos) end
|
||||||
end
|
end
|
||||||
|
local function handle_cart_enter(self, pos, next_dir)
|
||||||
|
handle_cart_enter_exit(self, pos, next_dir, "on_enter" )
|
||||||
|
end
|
||||||
|
local function handle_cart_leave(self, pos, next_dir)
|
||||||
|
handle_cart_enter_exit(self, pos, next_dir, "on_leave" )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function handle_cart_leave(pos)
|
local function handle_cart_node_watches(self, dtime)
|
||||||
local node_name = minetest.get_node(pos).name
|
local staticdata = self._staticdata
|
||||||
local node_def = minetest.registered_nodes[node_name]
|
local watches = staticdata.node_watches or {}
|
||||||
if node_def._mcl_minecarts_on_leave then
|
local new_watches = {}
|
||||||
node_def._mcl_minecarts_on_leave(pos, self)
|
for _,node_pos in ipairs(watches) do
|
||||||
|
local node = minetest.get_node(node_pos)
|
||||||
|
local node_def = minetest.registered_nodes[node.name]
|
||||||
|
local hook = node_def._mcl_minecarts_node_on_step
|
||||||
|
if hook and hook(node_pos, self, dtime) then
|
||||||
|
new_watches[#new_watches] = node_pos
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
staticdata.node_watches = new_watches
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update_cart_orientation(self,staticdata)
|
local function update_cart_orientation(self,staticdata)
|
||||||
|
@ -276,10 +296,8 @@ local function do_movement_step(self, dtime)
|
||||||
if x_1 >= 0.99 then
|
if x_1 >= 0.99 then
|
||||||
staticdata.distance = 0
|
staticdata.distance = 0
|
||||||
|
|
||||||
-- Leave the old node
|
|
||||||
handle_cart_leave(pos)
|
|
||||||
|
|
||||||
-- Anchor at the next node
|
-- Anchor at the next node
|
||||||
|
local old_pos = pos
|
||||||
pos = pos + staticdata.dir
|
pos = pos + staticdata.dir
|
||||||
staticdata.connected_at = pos
|
staticdata.connected_at = pos
|
||||||
|
|
||||||
|
@ -289,6 +307,9 @@ local function do_movement_step(self, dtime)
|
||||||
print( "Changing direction from "..tostring(staticdata.dir).." to "..tostring(next_dir))
|
print( "Changing direction from "..tostring(staticdata.dir).." to "..tostring(next_dir))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Leave the old node
|
||||||
|
handle_cart_leave(self, old_pos, next_dir )
|
||||||
|
|
||||||
-- Enter the new node
|
-- Enter the new node
|
||||||
handle_cart_enter(self, pos, next_dir)
|
handle_cart_enter(self, pos, next_dir)
|
||||||
|
|
||||||
|
@ -362,7 +383,12 @@ 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
|
||||||
dtime = do_movement_step(self, dtime)
|
local new_dtime = do_movement_step(self, dtime)
|
||||||
|
|
||||||
|
-- Handle node watches here in steps to prevent server lag from changing behavior
|
||||||
|
handle_cart_node_watches(self, dtime - new_dtime)
|
||||||
|
|
||||||
|
dtime = new_dtime
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Clear punched flag now that movement for this step has been completed
|
-- Clear punched flag now that movement for this step has been completed
|
||||||
|
@ -581,6 +607,7 @@ local function register_entity(entity_id, def)
|
||||||
on_activate_by_rail = def.on_activate_by_rail,
|
on_activate_by_rail = def.on_activate_by_rail,
|
||||||
_mcl_minecarts_on_enter = def._mcl_minecarts_on_enter,
|
_mcl_minecarts_on_enter = def._mcl_minecarts_on_enter,
|
||||||
_mcl_minecarts_on_place = def._mcl_minecarts_on_place,
|
_mcl_minecarts_on_place = def._mcl_minecarts_on_place,
|
||||||
|
_mcl_minecarts_on_step = def._mcl_minecarts_on_step,
|
||||||
|
|
||||||
_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
|
||||||
|
@ -728,8 +755,20 @@ local function register_entity(entity_id, def)
|
||||||
|
|
||||||
local passenger_attach_position = vector.new(0, -1.75, 0)
|
local passenger_attach_position = vector.new(0, -1.75, 0)
|
||||||
|
|
||||||
|
function cart:add_node_watch(pos)
|
||||||
|
local staticdata = self._staticdata
|
||||||
|
local watches = staticdata.watches
|
||||||
|
for _,watch in ipairs(watches) do
|
||||||
|
if watch == pos then return end
|
||||||
|
end
|
||||||
|
|
||||||
|
watches[#watches+1] = pos
|
||||||
|
end
|
||||||
|
|
||||||
function cart:on_step(dtime)
|
function cart:on_step(dtime)
|
||||||
|
-- TODO: move to _mcl_minecarts_on_step handler and on_enter handler for hopper minecart
|
||||||
hopper_take_item(self, dtime)
|
hopper_take_item(self, dtime)
|
||||||
|
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
|
|
||||||
-- Make sure all carts have an ID to isolate them
|
-- Make sure all carts have an ID to isolate them
|
||||||
|
@ -787,6 +826,7 @@ local function register_entity(entity_id, def)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO: move to _mcl_minecarts_on_step handler for plain minecart
|
||||||
-- Grab mob
|
-- Grab mob
|
||||||
if math.random(1,20) > 15 and not self._passenger then
|
if math.random(1,20) > 15 and not self._passenger then
|
||||||
if self.name == "mcl_minecarts:minecart" then
|
if self.name == "mcl_minecarts:minecart" then
|
||||||
|
@ -811,6 +851,7 @@ local function register_entity(entity_id, def)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Drop minecart if it isn't on a rail anymore
|
-- Drop minecart if it isn't on a rail anymore
|
||||||
|
--[[ Remove this entirely once off-cart minecart behavior is implemented
|
||||||
if self._last_float_check == nil then
|
if self._last_float_check == nil then
|
||||||
self._last_float_check = 0
|
self._last_float_check = 0
|
||||||
else
|
else
|
||||||
|
@ -837,7 +878,14 @@ local function register_entity(entity_id, def)
|
||||||
end
|
end
|
||||||
self._last_float_check = 0
|
self._last_float_check = 0
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
|
|
||||||
|
local hook = cart._mcl_minecarts_on_step
|
||||||
|
if hook then hook(cart,dtime) end
|
||||||
|
|
||||||
|
-- TODO: move the below into cart-specific hooks
|
||||||
|
|
||||||
|
-- TODO: move to _mcl_minecarts_on_step handler for furnace minecart
|
||||||
-- Update furnace stuff
|
-- Update furnace stuff
|
||||||
if self._fueltime and self._fueltime > 0 then
|
if self._fueltime and self._fueltime > 0 then
|
||||||
self._fueltime = self._fueltime - dtime
|
self._fueltime = self._fueltime - dtime
|
||||||
|
@ -857,6 +905,7 @@ local function register_entity(entity_id, def)
|
||||||
end
|
end
|
||||||
local has_fuel = self._fueltime and self._fueltime > 0
|
local has_fuel = self._fueltime and self._fueltime > 0
|
||||||
|
|
||||||
|
-- TODO: move to _mcl_minecarts_on_step handler for TNT minecart
|
||||||
-- Update TNT stuff
|
-- Update TNT stuff
|
||||||
if self._boomtimer then
|
if self._boomtimer then
|
||||||
-- Explode
|
-- Explode
|
||||||
|
|
|
@ -437,6 +437,7 @@ minetest.register_node("mcl_hoppers:hopper_side_disabled", def_hopper_side_disab
|
||||||
|
|
||||||
--[[ END OF NODE DEFINITIONS ]]
|
--[[ END OF NODE DEFINITIONS ]]
|
||||||
|
|
||||||
|
|
||||||
local function hopper_pull_from_mc(mc_ent, dest_pos, inv_size)
|
local function hopper_pull_from_mc(mc_ent, dest_pos, inv_size)
|
||||||
local inv = mcl_entity_invs.load_inv(mc_ent, inv_size)
|
local inv = mcl_entity_invs.load_inv(mc_ent, inv_size)
|
||||||
if not inv then
|
if not inv then
|
||||||
|
@ -558,7 +559,7 @@ minetest.register_abm({
|
||||||
and (hm_pos.z >= pos.z - DIST_FROM_MC and hm_pos.z <= pos.z + DIST_FROM_MC) then
|
and (hm_pos.z >= pos.z - DIST_FROM_MC and hm_pos.z <= pos.z + DIST_FROM_MC) then
|
||||||
mcl_log("Minecart close enough")
|
mcl_log("Minecart close enough")
|
||||||
if entity.name == "mcl_minecarts:hopper_minecart" then
|
if entity.name == "mcl_minecarts:hopper_minecart" then
|
||||||
hopper_pull_from_mc(entity, pos, 5)
|
--hopper_pull_from_mc(entity, pos, 5)
|
||||||
elseif entity.name == "mcl_minecarts:chest_minecart" or entity.name == "mcl_boats:chest_boat" then
|
elseif entity.name == "mcl_minecarts:chest_minecart" or entity.name == "mcl_boats:chest_boat" then
|
||||||
hopper_pull_from_mc(entity, pos, 27)
|
hopper_pull_from_mc(entity, pos, 27)
|
||||||
end
|
end
|
||||||
|
@ -567,7 +568,7 @@ minetest.register_abm({
|
||||||
and (hm_pos.z >= pos.z - DIST_FROM_MC and hm_pos.z <= pos.z + DIST_FROM_MC) then
|
and (hm_pos.z >= pos.z - DIST_FROM_MC and hm_pos.z <= pos.z + DIST_FROM_MC) then
|
||||||
mcl_log("Minecart close enough")
|
mcl_log("Minecart close enough")
|
||||||
if entity.name == "mcl_minecarts:hopper_minecart" then
|
if entity.name == "mcl_minecarts:hopper_minecart" then
|
||||||
hopper_push_to_mc(entity, pos, 5)
|
--hopper_push_to_mc(entity, pos, 5)
|
||||||
elseif entity.name == "mcl_minecarts:chest_minecart" or entity.name == "mcl_boats:chest_boat" then
|
elseif entity.name == "mcl_minecarts:chest_minecart" or entity.name == "mcl_boats:chest_boat" then
|
||||||
hopper_push_to_mc(entity, pos, 27)
|
hopper_push_to_mc(entity, pos, 27)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue