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 = {
|
||||
{ 1, 0, 0 }, -- forwards
|
||||
|
|
|
@ -21,59 +21,79 @@ local function mcl_log(message)
|
|||
end
|
||||
end
|
||||
|
||||
local function handle_cart_enter(self, pos, next_dir)
|
||||
local staticdata = self._staticdata
|
||||
local node = minetest.get_node(pos)
|
||||
mcl_minecarts.on_enter_below = function(pos, cart, next_dir, node_def)
|
||||
local staticdata = cart._staticdata
|
||||
if (node_def.groups.hopper or 0) == 0 then return end
|
||||
|
||||
-- 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, self)
|
||||
end
|
||||
local hopper_pulled = mcl_hoppers.pull_from_minecart( cart, pos, cart._inv_size or 0 )
|
||||
if DEBUG then print( "Attempt pull_from_minecart, hopper_pulled="..tostring(hopper_pulled) ) 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 hopper_pulled and next_dir ~= staticdata.dir then
|
||||
-- If there was an item pulled by a hopper under the rails force the cart to stay put for 1.5 seconds
|
||||
-- to allow redstone time to process
|
||||
if hopper_pulled then
|
||||
staticdata.delay = 1.5
|
||||
end
|
||||
end
|
||||
if hopper_pulled and next_dir ~= staticdata.dir then
|
||||
-- If there was an item pulled by a hopper under the rails force the cart to stay put for 1.5 seconds
|
||||
-- to allow redstone time to process
|
||||
if hopper_pulled then
|
||||
staticdata.delay = 1.5
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle above-track behaviors (to ensure hoppers can transfer at least one item)
|
||||
local above_pos = pos + vector.new(0,1,0)
|
||||
local above_node_name = minetest.get_node(above_pos).name
|
||||
local above_node_def = minetest.registered_nodes[above_node_name]
|
||||
if above_node_def._mcl_minecarts_on_enter_below then
|
||||
above_node_def._mcl_minecarts_on_enter_below(above_pos, self)
|
||||
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)
|
||||
--[[
|
||||
Array of hooks { {u,v,w}, name }
|
||||
Actual position is pos + u * dir + v * right + w * up
|
||||
]]
|
||||
local enter_exit_checks = {
|
||||
{ 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
|
||||
|
||||
-- Handle cart-specific behaviors
|
||||
local hook = self["_mcl_minecarts_"..event]
|
||||
if hook then hook(self, pos) 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
|
||||
|
||||
local function handle_cart_node_watches(self, dtime)
|
||||
local staticdata = self._staticdata
|
||||
local watches = staticdata.node_watches or {}
|
||||
local new_watches = {}
|
||||
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
|
||||
|
||||
staticdata.node_watches = new_watches
|
||||
end
|
||||
|
||||
local function update_cart_orientation(self,staticdata)
|
||||
|
@ -276,10 +296,8 @@ local function do_movement_step(self, dtime)
|
|||
if x_1 >= 0.99 then
|
||||
staticdata.distance = 0
|
||||
|
||||
-- Leave the old node
|
||||
handle_cart_leave(pos)
|
||||
|
||||
-- Anchor at the next node
|
||||
local old_pos = pos
|
||||
pos = pos + staticdata.dir
|
||||
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))
|
||||
end
|
||||
|
||||
-- Leave the old node
|
||||
handle_cart_leave(self, old_pos, next_dir )
|
||||
|
||||
-- Enter the new node
|
||||
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
|
||||
-- causing large timesteps
|
||||
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
|
||||
|
||||
-- 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,
|
||||
_mcl_minecarts_on_enter = def._mcl_minecarts_on_enter,
|
||||
_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!)
|
||||
_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)
|
||||
|
||||
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)
|
||||
-- TODO: move to _mcl_minecarts_on_step handler and on_enter handler for hopper minecart
|
||||
hopper_take_item(self, dtime)
|
||||
|
||||
local staticdata = self._staticdata
|
||||
|
||||
-- Make sure all carts have an ID to isolate them
|
||||
|
@ -787,6 +826,7 @@ local function register_entity(entity_id, def)
|
|||
end
|
||||
end
|
||||
|
||||
-- TODO: move to _mcl_minecarts_on_step handler for plain minecart
|
||||
-- Grab mob
|
||||
if math.random(1,20) > 15 and not self._passenger then
|
||||
if self.name == "mcl_minecarts:minecart" then
|
||||
|
@ -811,6 +851,7 @@ local function register_entity(entity_id, def)
|
|||
end
|
||||
|
||||
-- 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
|
||||
self._last_float_check = 0
|
||||
else
|
||||
|
@ -837,7 +878,14 @@ local function register_entity(entity_id, def)
|
|||
end
|
||||
self._last_float_check = 0
|
||||
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
|
||||
if self._fueltime and self._fueltime > 0 then
|
||||
self._fueltime = self._fueltime - dtime
|
||||
|
@ -857,6 +905,7 @@ local function register_entity(entity_id, def)
|
|||
end
|
||||
local has_fuel = self._fueltime and self._fueltime > 0
|
||||
|
||||
-- TODO: move to _mcl_minecarts_on_step handler for TNT minecart
|
||||
-- Update TNT stuff
|
||||
if self._boomtimer then
|
||||
-- Explode
|
||||
|
|
|
@ -437,6 +437,7 @@ minetest.register_node("mcl_hoppers:hopper_side_disabled", def_hopper_side_disab
|
|||
|
||||
--[[ END OF NODE DEFINITIONS ]]
|
||||
|
||||
|
||||
local function hopper_pull_from_mc(mc_ent, dest_pos, inv_size)
|
||||
local inv = mcl_entity_invs.load_inv(mc_ent, inv_size)
|
||||
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
|
||||
mcl_log("Minecart close enough")
|
||||
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
|
||||
hopper_pull_from_mc(entity, pos, 27)
|
||||
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
|
||||
mcl_log("Minecart close enough")
|
||||
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
|
||||
hopper_push_to_mc(entity, pos, 27)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue