From 335d9a3eddcb590c3ca5de9cba9b152e5e560af1 Mon Sep 17 00:00:00 2001 From: Vanessa Ezekowitz Date: Tue, 13 Feb 2018 14:05:34 -0500 Subject: removed boost_cart and carbone_mobs -- too many crashes updated blox, homedecor, plantlifed, cottages, farming_redo, framedglass, gloopblocks, mesecons, moreblocks, moretrees, pipeworks, player_textures, replacer, signs_lib, stained_glass, technic, travelnet, unified_inventory, unifieddyes, and worldedit. --- pipeworks/item_transport.lua | 132 +++++++++++++++++++++++++++++++++---------- 1 file changed, 101 insertions(+), 31 deletions(-) (limited to 'pipeworks/item_transport.lua') diff --git a/pipeworks/item_transport.lua b/pipeworks/item_transport.lua index 551db07..7219f7e 100644 --- a/pipeworks/item_transport.lua +++ b/pipeworks/item_transport.lua @@ -50,30 +50,44 @@ minetest.register_globalstep(function(dtime) end end) -local function go_next(pos, velocity, stack, owner) + + +-- tube overload mechanism: +-- when the tube's item count (tracked in the above tube_item_count table) +-- exceeds the limit configured per tube, replace it with a broken one. +local crunch_tube = function(pos, cnode, cmeta) + if enable_max_limit then + local h = minetest.hash_node_position(pos) + local itemcount = tube_item_count[h] or 0 + if itemcount > max_tube_limit then + cmeta:set_string("the_tube_was", minetest.serialize(cnode)) + print("[Pipeworks] Warning - a tube at "..minetest.pos_to_string(pos).." broke due to too many items ("..itemcount..")") + minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"}) + pipeworks.scan_for_tube_objects(pos) + end + end +end + + + +-- compatibility behaviour for the existing can_go() callbacks, +-- which can only specify a list of possible positions. +local function go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner) local next_positions = {} local max_priority = 0 - local cnode = minetest.get_node(pos) - local cmeta = minetest.get_meta(pos) local can_go - local speed = math.abs(velocity.x + velocity.y + velocity.z) - if speed == 0 then - speed = 1 - end - local vel = {x = velocity.x/speed, y = velocity.y/speed, z = velocity.z/speed,speed=speed} - if speed >= 4.1 then - speed = 4 - elseif speed >= 1.1 then - speed = speed - 0.1 - else - speed = 1 - end - vel.speed = speed + if minetest.registered_nodes[cnode.name] and minetest.registered_nodes[cnode.name].tube and minetest.registered_nodes[cnode.name].tube.can_go then can_go = minetest.registered_nodes[cnode.name].tube.can_go(pos, cnode, vel, stack) else can_go = pipeworks.notvel(adjlist, vel) end + -- can_go() is expected to return an array-like table of candidate offsets. + -- for each one, look at the node at that offset and determine if it can accept the item. + -- also note the prioritisation: + -- if any tube is found with a greater priority than previously discovered, + -- then the valid positions are reset and and subsequent positions under this are skipped. + -- this has the effect of allowing only equal priorities to co-exist. for _, vect in ipairs(can_go) do local npos = vector.add(pos, vect) pipeworks.load_position(npos) @@ -96,29 +110,70 @@ local function go_next(pos, velocity, stack, owner) end end - if enable_max_limit then - local h = minetest.hash_node_position(pos) - local itemcount = tube_item_count[h] or 0 - if itemcount > max_tube_limit then - cmeta:set_string("the_tube_was", minetest.serialize(cnode)) - print("[Pipeworks] Warning - a tube at "..minetest.pos_to_string(pos).." broke due to too many items ("..itemcount..")") - minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"}) - pipeworks.scan_for_tube_objects(pos) - end + -- indicate not found if no valid rules were picked up, + -- and don't change the counter. + if not next_positions[1] then + return cycledir, false, nil, nil end - if not next_positions[1] then - return false, nil + -- otherwise rotate to the next output direction and return that + local n = (cycledir % (#next_positions)) + 1 + local new_velocity = vector.multiply(next_positions[n].vect, vel.speed) + return n, true, new_velocity, nil +end + + + + +-- function called by the on_step callback of the pipeworks tube luaentity. +-- the routine is passed the current node position, velocity, itemstack, +-- and owner name. +-- returns three values: +-- * a boolean "found destination" status; +-- * a new velocity vector that the tubed item should use, or nil if not found; +-- * a "multi-mode" data table (or nil if N/A) where a stack was split apart. +-- if this is not nil, the luaentity spawns new tubed items for each new fragment stack, +-- then deletes itself (i.e. the original item stack). +local function go_next(pos, velocity, stack, owner) + local cnode = minetest.get_node(pos) + local cmeta = minetest.get_meta(pos) + local speed = math.abs(velocity.x + velocity.y + velocity.z) + if speed == 0 then + speed = 1 end + local vel = {x = velocity.x/speed, y = velocity.y/speed, z = velocity.z/speed,speed=speed} + if speed >= 4.1 then + speed = 4 + elseif speed >= 1.1 then + speed = speed - 0.1 + else + speed = 1 + end + vel.speed = speed + + crunch_tube(pos, cnode, cmeta) + -- cycling of outputs: + -- an integer counter is kept in each pipe's metadata, + -- which allows tracking which output was previously chosen. + -- note reliance on get_int returning 0 for uninitialised. + local cycledir = cmeta:get_int("tubedir") - local n = (cmeta:get_int("tubedir") % (#next_positions)) + 1 + -- pulled out and factored out into go_next_compat() above. + -- n is the new value of the cycle counter. + -- XXX: this probably needs cleaning up after being split out, + -- seven args is a bit too many + local n, found, new_velocity, multimode = go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner) + + -- if not using output cycling, + -- don't update the field so it stays the same for the next item. if pipeworks.enable_cyclic_mode then cmeta:set_int("tubedir", n) end - local new_velocity = vector.multiply(next_positions[n].vect, vel.speed) - return true, new_velocity + return found, new_velocity, multimode end + + minetest.register_entity("pipeworks:tubed_item", { initial_properties = { hp_max = 1, @@ -197,6 +252,12 @@ minetest.register_entity("pipeworks:color_entity", { on_activate = luaentity.on_activate, }) +-- see below for usage: +-- determine if go_next returned a multi-mode set. +local is_multimode = function(v) + return (type(v) == "table") and (v.__multimode) +end + luaentity.register_entity("pipeworks:tubed_item", { itemstring = '', item_entity = nil, @@ -277,7 +338,7 @@ luaentity.register_entity("pipeworks:tubed_item", { end if moved then - local found_next, new_velocity = go_next(self.start_pos, velocity, stack, self.owner) -- todo: color + local found_next, new_velocity, multimode = go_next(self.start_pos, velocity, stack, self.owner) -- todo: color local rev_vel = vector.multiply(velocity, -1) local rev_dir = vector.direction(self.start_pos,vector.add(self.start_pos,rev_vel)) local rev_node = minetest.get_node(vector.round(vector.add(self.start_pos,rev_dir))) @@ -297,6 +358,15 @@ luaentity.register_entity("pipeworks:tubed_item", { self:setpos(vector.subtract(self.start_pos, vector.multiply(vel, moved_by - 1))) self:setvelocity(velocity) end + elseif is_multimode(multimode) then + -- create new stacks according to returned data. + local s = self.start_pos + for _, split in ipairs(multimode) do + pipeworks.tube_inject_item(s, s, split.velocity, split.itemstack, self.owner) + end + -- remove ourself now the splits are sent + self:remove() + return end if new_velocity and not vector.equals(velocity, new_velocity) then -- cgit v1.2.3