mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-28 05:21:05 +01:00
Fix hopper-minecart interaction, convert ipairs(table) to use for i=1,#table instead
This commit is contained in:
parent
59f64ca947
commit
f3b0ee67ed
5 changed files with 158 additions and 71 deletions
|
@ -156,8 +156,8 @@ function DEFAULT_CART_DEF:add_node_watch(pos)
|
|||
local staticdata = self._staticdata
|
||||
local watches = staticdata.node_watches or {}
|
||||
|
||||
for _,watch in ipairs(watches) do
|
||||
if watch == pos then return end
|
||||
for i=1,#watches do
|
||||
if watches[i] == pos then return end
|
||||
end
|
||||
|
||||
watches[#watches+1] = pos
|
||||
|
@ -168,9 +168,10 @@ function DEFAULT_CART_DEF:remove_node_watch(pos)
|
|||
local watches = staticdata.node_watches or {}
|
||||
|
||||
local new_watches = {}
|
||||
for _,node_pos in ipairs(watches) do
|
||||
for i=1,#watches do
|
||||
local node_pos = watches[i]
|
||||
if node_pos ~= pos then
|
||||
new_watches[#new_watches] = node_pos
|
||||
new_watches[#new_watches + 1] = node_pos
|
||||
end
|
||||
end
|
||||
staticdata.node_watches = new_watches
|
||||
|
@ -256,7 +257,7 @@ function DEFAULT_CART_DEF:on_step(dtime)
|
|||
|
||||
mod.update_cart_orientation(self)
|
||||
end
|
||||
function mod.kill_cart(staticdata)
|
||||
function mod.kill_cart(staticdata, killer)
|
||||
local pos
|
||||
minetest.log("action", "cart #"..staticdata.uuid.." was killed")
|
||||
|
||||
|
@ -288,16 +289,33 @@ function mod.kill_cart(staticdata)
|
|||
|
||||
-- Drop items
|
||||
if not staticdata.dropped then
|
||||
|
||||
-- Try to drop the cart
|
||||
local entity_def = minetest.registered_entities[staticdata.cart_type]
|
||||
if entity_def then
|
||||
local drop = entity_def.drop
|
||||
for d=1, #drop do
|
||||
minetest.add_item(pos, drop[d])
|
||||
local drop_cart = true
|
||||
if killer and minetest.is_creative_enabled(killer:get_player_name()) then
|
||||
drop_cart = false
|
||||
end
|
||||
|
||||
-- Prevent item duplication
|
||||
staticdata.dropped = true
|
||||
if drop_cart then
|
||||
local drop = entity_def.drop
|
||||
for d=1, #drop do
|
||||
minetest.add_item(pos, drop[d])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Drop any items in the inventory
|
||||
local inventory = staticdata.inventory
|
||||
if inventory then
|
||||
for i=1,#inventory do
|
||||
minetest.add_item(pos, inventory[i])
|
||||
end
|
||||
end
|
||||
|
||||
-- Prevent item duplication
|
||||
staticdata.dropped = true
|
||||
end
|
||||
|
||||
-- Remove data
|
||||
|
@ -306,7 +324,7 @@ end
|
|||
local kill_cart = mod.kill_cart
|
||||
|
||||
function DEFAULT_CART_DEF:on_death(killer)
|
||||
kill_cart(self._staticdata)
|
||||
kill_cart(self._staticdata, killer)
|
||||
end
|
||||
|
||||
-- Create a minecart
|
||||
|
@ -551,6 +569,8 @@ end
|
|||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
||||
-- Periodically respawn carts that come into range of a player
|
||||
timer = timer - dtime
|
||||
if timer <= 0 then
|
||||
local start_time = minetest.get_us_time()
|
||||
|
@ -559,11 +579,13 @@ minetest.register_globalstep(function(dtime)
|
|||
local duration = (stop_time - start_time) / 1e6
|
||||
timer = duration / 250e-6 -- Schedule 50us per second
|
||||
if timer > 5 then timer = 5 end
|
||||
--print("Took "..tostring(duration).." seconds, rescheduling for "..tostring(timer).." seconds in the future")
|
||||
end
|
||||
|
||||
-- Handle periodically updating out-of-range carts
|
||||
-- TODO: change how often cart positions are updated based on velocity
|
||||
local start_time
|
||||
if DEBUG then start_time = minetest.get_us_time() end
|
||||
|
||||
for uuid,staticdata in mod.carts() do
|
||||
local pos = mod.get_cart_position(staticdata)
|
||||
--[[
|
||||
|
@ -580,5 +602,10 @@ minetest.register_globalstep(function(dtime)
|
|||
do_movement(staticdata, dtime)
|
||||
end
|
||||
end
|
||||
|
||||
if DEBUG then
|
||||
local stop_time = minetest.get_us_time()
|
||||
print("Update took "..((stop_time-start_time)*1e-6).." seconds")
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
@ -156,13 +156,13 @@ mod.register_minecart({
|
|||
groups = { container = 1 },
|
||||
on_rightclick = nil,
|
||||
on_activate_by_rail = nil,
|
||||
_mcl_minecarts_on_enter = function(self, pos)
|
||||
local staticdata = self._staticdata
|
||||
_mcl_minecarts_on_enter = function(self, pos, staticdata)
|
||||
if (staticdata.hopper_delay or 0) > 0 then
|
||||
return
|
||||
end
|
||||
|
||||
-- try to pull from containers into our inventory
|
||||
if not self then return end
|
||||
local inv = mcl_entity_invs.load_inv(self,5)
|
||||
local above_pos = pos + vector.new(0,1,0)
|
||||
mcl_util.hopper_pull_to_inventory(inv, 'main', above_pos, pos)
|
||||
|
|
|
@ -185,7 +185,8 @@ local function get_rail_connections(pos, opt)
|
|||
local ignore_neighbor_connections = opt and opt.ignore_neighbor_connections
|
||||
|
||||
local connections = 0
|
||||
for i,dir in ipairs(CONNECTIONS) do
|
||||
for i = 1,#CONNECTIONS do
|
||||
dir = CONNECTIONS[i]
|
||||
local neighbor = vector.add(pos, dir)
|
||||
local node = minetest.get_node(neighbor)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
|
@ -223,7 +224,8 @@ local function update_rail_connections(pos, opt)
|
|||
local connections = get_rail_connections(pos, opt)
|
||||
|
||||
-- Check for rasing rails to slopes
|
||||
for i,dir in ipairs(CONNECTIONS) do
|
||||
for i = 1,#CONNECTIONS do
|
||||
local dir = CONNECTIONS[i]
|
||||
local neighbor = vector.add(pos, dir)
|
||||
make_sloped_if_straight( vector.offset(neighbor, 0, -1, 0), dir )
|
||||
end
|
||||
|
@ -258,7 +260,8 @@ local function update_rail_connections(pos, opt)
|
|||
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
if get_path(node_def, "_mcl_minecarts", "can_slope") then
|
||||
for _,dir in ipairs(CONNECTIONS) do
|
||||
for i=1,#CONNECTIONS do
|
||||
local dir = CONNECTIONS[i]
|
||||
local higher_rail_pos = vector.offset(pos,dir.x,1,dir.z)
|
||||
local rev_dir = vector.direction(dir,vector.new(0,0,0))
|
||||
if mcl_minecarts:is_rail(higher_rail_pos) and is_connection(higher_rail_pos, rev_dir) then
|
||||
|
|
|
@ -55,7 +55,9 @@ local function handle_cart_enter_exit(staticdata, pos, next_dir, event)
|
|||
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
|
||||
for i=1,#enter_exit_checks do
|
||||
local check = enter_exit_checks[i]
|
||||
|
||||
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]
|
||||
|
@ -74,7 +76,7 @@ local function handle_cart_enter_exit(staticdata, pos, next_dir, event)
|
|||
-- Handle cart-specific behaviors
|
||||
if luaentity then
|
||||
local hook = luaentity["_mcl_minecarts_"..event]
|
||||
if hook then hook(self, pos) end
|
||||
if hook then hook(luaentity, pos, staticdata) end
|
||||
else
|
||||
--minetest.log("warning", "TODO: change _mcl_minecarts_"..event.." calling so it is not dependent on the existence of a luaentity")
|
||||
end
|
||||
|
@ -99,12 +101,13 @@ local function handle_cart_node_watches(staticdata, dtime)
|
|||
local watches = staticdata.node_watches or {}
|
||||
local new_watches = {}
|
||||
local luaentity = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
|
||||
for _,node_pos in ipairs(watches) do
|
||||
for i=1,#watches do
|
||||
local node_pos = watches[i]
|
||||
local node = minetest.get_node(node_pos)
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
if node_def then
|
||||
local hook = node_def._mcl_minecarts_node_on_step
|
||||
if hook and hook(node_pos, luaentity, dtime) then
|
||||
if hook and hook(node_pos, luaentity, dtime, staticdata) then
|
||||
new_watches[#new_watches+1] = node_pos
|
||||
end
|
||||
end
|
||||
|
|
|
@ -136,6 +136,47 @@ local function hopper_push_to_mc(mc_ent, dest_pos, inv_size)
|
|||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
mcl_log("No inv")
|
||||
return false
|
||||
end
|
||||
|
||||
local dest_meta = minetest.get_meta(dest_pos)
|
||||
local dest_inv = dest_meta:get_inventory()
|
||||
if not dest_inv then
|
||||
mcl_log("No dest inv")
|
||||
return false
|
||||
end
|
||||
|
||||
mcl_log("inv. size: " .. mc_ent._inv_size)
|
||||
for i = 1, mc_ent._inv_size, 1 do
|
||||
local stack = inv:get_stack("main", i)
|
||||
|
||||
mcl_log("i: " .. tostring(i))
|
||||
mcl_log("Name: [" .. tostring(stack:get_name()) .. "]")
|
||||
mcl_log("Count: " .. tostring(stack:get_count()))
|
||||
mcl_log("stack max: " .. tostring(stack:get_stack_max()))
|
||||
|
||||
if not stack:get_name() or stack:get_name() ~= "" then
|
||||
if dest_inv:room_for_item("main", stack:peek_item()) then
|
||||
mcl_log("Room so unload")
|
||||
dest_inv:add_item("main", stack:take_item())
|
||||
inv:set_stack("main", i, stack)
|
||||
|
||||
-- Take one item and stop until next time, report that we took something
|
||||
return true
|
||||
else
|
||||
mcl_log("no Room")
|
||||
end
|
||||
|
||||
else
|
||||
mcl_log("nothing there")
|
||||
end
|
||||
end
|
||||
end
|
||||
mcl_hoppers.pull_from_minecart = hopper_pull_from_mc
|
||||
|
||||
|
||||
-- Downwards hopper (base definition)
|
||||
|
@ -243,16 +284,29 @@ local def_hopper = {
|
|||
minetest.log("action", player:get_player_name() ..
|
||||
" takes stuff from mcl_hoppers at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
_mcl_minecarts_on_enter_above = function(pos, cart, next_dir)
|
||||
-- Only push to containers
|
||||
if cart.groups and (cart.groups.container or 0) ~= 0 then
|
||||
_mcl_minecarts_on_enter_below = function(pos, cart, next_dir)
|
||||
print("Cart entered above "..tostring(pos))
|
||||
-- Only pull to containers
|
||||
if cart and cart.groups and (cart.groups.container or 0) ~= 0 then
|
||||
cart:add_node_watch(pos)
|
||||
hopper_push_to_mc(cart, pos, 5)
|
||||
end
|
||||
end,
|
||||
_mcl_minecarts_on_enter_above = function(pos, cart, next_dir)
|
||||
print("Cart entered below "..tostring(pos))
|
||||
|
||||
-- Only push to containers
|
||||
if cart and cart.groups and (cart.groups.container or 0) ~= 0 then
|
||||
cart:add_node_watch(pos)
|
||||
hopper_pull_from_mc(cart, pos, 5)
|
||||
end
|
||||
end,
|
||||
_mcl_minecarts_on_leave_above = function(pos, cart, next_dir)
|
||||
if not cart then return end
|
||||
|
||||
cart:remove_node_watch(pos)
|
||||
end,
|
||||
_mcl_minecarts_node_on_step = function(pos, cart, dtime)
|
||||
_mcl_minecarts_node_on_step = function(pos, cart, dtime, cartdata)
|
||||
if not cart then
|
||||
minetest.log("warning", "trying to process hopper-to-minecart movement without luaentity")
|
||||
return
|
||||
|
@ -260,9 +314,18 @@ local def_hopper = {
|
|||
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
local cart_pos = mcl_minecarts.get_cart_position(cartdata)
|
||||
|
||||
local timer = meta:get_int("minecart_hopper_timer")
|
||||
if timer < dtime then
|
||||
hopper_push_to_mc(cart, pos, 5)
|
||||
if vector.direction(pos,cart_pos).y > 0 then
|
||||
-- The cart is above us, pull from minecart
|
||||
print("Pulling from cart above "..tostring(pos))
|
||||
hopper_pull_from_mc(cart, pos, 5)
|
||||
else
|
||||
print("Pushing to cart below "..tostring(pos))
|
||||
hopper_push_to_mc(cart, pos, 5)
|
||||
end
|
||||
timer = timer + 1
|
||||
else
|
||||
timer = timer - dtime
|
||||
|
@ -476,7 +539,23 @@ local def_hopper_side = {
|
|||
on_rotate = on_rotate,
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
|
||||
_mcl_minecarts_on_enter_below = function(pos, cart, next_dir)
|
||||
print("Cart entered above "..tostring(pos)..",cart="..tostring(cart))
|
||||
|
||||
-- Only push to containers
|
||||
if cart and cart.groups and (cart.groups.container or 0) ~= 0 then
|
||||
print("Pulling from cart above "..tostring(pos))
|
||||
cart:add_node_watch(pos)
|
||||
hopper_pull_from_mc(cart, pos, 5)
|
||||
end
|
||||
end,
|
||||
_mcl_minecarts_on_leave_below = function(pos, cart, next_dir)
|
||||
if not cart then return end
|
||||
cart:remove_node_watch(pos)
|
||||
end,
|
||||
_mcl_minecarts_on_enter_side = function(pos, cart, next_dir, rail_pos)
|
||||
if not cart then return end
|
||||
|
||||
-- Only try to push to minecarts when the spout position is pointed at the rail
|
||||
local face = minetest.get_node(pos).param2
|
||||
local dst_pos = {}
|
||||
|
@ -497,20 +576,37 @@ local def_hopper_side = {
|
|||
end
|
||||
end,
|
||||
_mcl_minecarts_on_leave_side = function(pos, cart, next_dir)
|
||||
if not cart then return end
|
||||
|
||||
cart:remove_node_watch(pos)
|
||||
end,
|
||||
_mcl_minecarts_node_on_step = function(pos, cart, dtime)
|
||||
local meta = minetest.get_meta(pos)
|
||||
_mcl_minecarts_node_on_step = function(pos, cart, dtime, cartdata)
|
||||
if not cart then return end
|
||||
|
||||
local tick = false
|
||||
local meta = minetest.get_meta(pos)
|
||||
local timer = meta:get_int("minecart_hopper_timer")
|
||||
print("dtime="..dtime..",timer="..timer)
|
||||
if timer < dtime then
|
||||
hopper_push_to_mc(cart, pos, 5)
|
||||
tick = true
|
||||
timer = timer + 1
|
||||
else
|
||||
timer = timer - dtime
|
||||
end
|
||||
meta:set_int("minecart_hopper_timer", timer)
|
||||
|
||||
if tick then
|
||||
local cart_pos = mcl_minecarts.get_cart_position(cartdata)
|
||||
if not cart_pos then return false end
|
||||
|
||||
print("uuid="..cartdata.uuid)
|
||||
if cart_pos.y == pos.y then
|
||||
hopper_push_to_mc(cart, pos, 5)
|
||||
elseif cart_pos.y > pos.y then
|
||||
hopper_pull_from_mc(cart, pos, 5)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
|
||||
|
@ -546,48 +642,6 @@ 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
|
||||
mcl_log("No inv")
|
||||
return false
|
||||
end
|
||||
|
||||
local dest_meta = minetest.get_meta(dest_pos)
|
||||
local dest_inv = dest_meta:get_inventory()
|
||||
if not dest_inv then
|
||||
mcl_log("No dest inv")
|
||||
return false
|
||||
end
|
||||
|
||||
mcl_log("inv. size: " .. mc_ent._inv_size)
|
||||
for i = 1, mc_ent._inv_size, 1 do
|
||||
local stack = inv:get_stack("main", i)
|
||||
|
||||
mcl_log("i: " .. tostring(i))
|
||||
mcl_log("Name: [" .. tostring(stack:get_name()) .. "]")
|
||||
mcl_log("Count: " .. tostring(stack:get_count()))
|
||||
mcl_log("stack max: " .. tostring(stack:get_stack_max()))
|
||||
|
||||
if not stack:get_name() or stack:get_name() ~= "" then
|
||||
if dest_inv:room_for_item("main", stack:peek_item()) then
|
||||
mcl_log("Room so unload")
|
||||
dest_inv:add_item("main", stack:take_item())
|
||||
inv:set_stack("main", i, stack)
|
||||
|
||||
-- Take one item and stop until next time, report that we took something
|
||||
return true
|
||||
else
|
||||
mcl_log("no Room")
|
||||
end
|
||||
|
||||
else
|
||||
mcl_log("nothing there")
|
||||
end
|
||||
end
|
||||
end
|
||||
mcl_hoppers.pull_from_minecart = hopper_pull_from_mc
|
||||
|
||||
--[[ BEGIN OF ABM DEFINITONS ]]
|
||||
|
||||
minetest.register_abm({
|
||||
|
|
Loading…
Reference in a new issue