2017-04-04 10:25:27 +03:00
|
|
|
local luaentity = pipeworks.luaentity
|
2022-01-07 05:42:08 +03:00
|
|
|
local enable_max_limit = minetest.settings:get_bool("pipeworks_enable_items_per_tube_limit")
|
2017-05-18 12:33:56 +03:00
|
|
|
local max_tube_limit = tonumber(minetest.settings:get("pipeworks_max_items_per_tube")) or 30
|
2017-04-06 07:15:16 +03:00
|
|
|
if enable_max_limit == nil then enable_max_limit = true end
|
2017-04-05 09:57:22 +03:00
|
|
|
|
2024-03-03 14:48:27 +03:00
|
|
|
if pipeworks.enable_item_tags then
|
|
|
|
local max_tag_length = tonumber(minetest.settings:get("pipeworks_max_item_tag_length")) or 32
|
|
|
|
local max_tags = tonumber(minetest.settings:get("pipeworks_max_item_tags")) or 16
|
|
|
|
|
|
|
|
function pipeworks.sanitize_tags(tags)
|
|
|
|
if type(tags) == "string" then
|
|
|
|
tags = tags:split(",")
|
|
|
|
end
|
|
|
|
local sanitized = {}
|
|
|
|
for i, tag in ipairs(tags) do
|
|
|
|
if type(tag) == "string" then
|
|
|
|
tag = tag:gsub("[%s,]", "") -- Remove whitespace and commas
|
|
|
|
tag = tag:gsub("%$%b%{%}", "") -- Remove special ${key} values
|
|
|
|
if tag ~= "" then
|
|
|
|
table.insert(sanitized, tag:sub(1, max_tag_length))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if #sanitized >= max_tags then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return sanitized
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-15 00:59:15 +04:00
|
|
|
function pipeworks.tube_item(pos, item)
|
|
|
|
error("obsolete pipeworks.tube_item() called; change caller to use pipeworks.tube_inject_item() instead")
|
|
|
|
end
|
|
|
|
|
2024-03-03 14:48:27 +03:00
|
|
|
function pipeworks.tube_inject_item(pos, start_pos, velocity, item, owner, tags)
|
2013-12-15 14:35:11 +04:00
|
|
|
-- Take item in any format
|
|
|
|
local stack = ItemStack(item)
|
2014-08-14 18:22:03 +04:00
|
|
|
local obj = luaentity.add_entity(pos, "pipeworks:tubed_item")
|
|
|
|
obj:set_item(stack:to_string())
|
|
|
|
obj.start_pos = vector.new(start_pos)
|
2018-07-03 23:30:44 +03:00
|
|
|
obj:set_velocity(velocity)
|
2017-08-21 01:05:08 +03:00
|
|
|
obj.owner = owner
|
2024-03-03 14:48:27 +03:00
|
|
|
obj.tags = tags
|
2014-08-14 18:22:03 +04:00
|
|
|
--obj:set_color("red") -- todo: this is test-only code
|
2013-12-15 14:35:11 +04:00
|
|
|
return obj
|
|
|
|
end
|
|
|
|
|
Multiple updates:
1) Refactor autoplace,
There was a lot of redundant code and like a dozen unneccessary string
scans for every node next to every tube placed! I put it all into
indexed tables and loops instead of bizarre and unexplainable variable
names and copy and pasted code. There was also no support for notifying
a chest when an item has been taken from it by a filter, so I added
something for that.
I also thought it prudent to fall back on the
allow_metadata_inventory_take function should a special can_remove not
exist. In fact if can_insert doesn't exist, it calls
allow_metadata_inventory_put instead.
I also added a thing for allowing pipes to attach to nodes of other
modules, without having to hard code type all those node names into
autoplace.lua. Basically node.tube.collects(i,param2) and i is the
direction from the pipe and param2 is the param2 of what it's pointing
at.
I also abstracted the inscrutable correlation between i and
param2 by trial and error (and the paramwand mod) into understandable
functions. There was no pipeworks namespace so I created it, and put
these functions into pipeworks.collects (as distinguished from a
node.tube.collects function, which uses those functions)
And now it's too late to cart my old clothes to the thrift store,
dangit.
2) My "node.tube.collects" idea might be redundant with the
node.tube.connect_sides thing, though possibly more versatile so I'll
leave it in.
3) I was using node.tube.connects and fancy functions for checking if it's
the sides or top or whatnot, and this connect_side thing came in. This
should make both my way and the way using connect_side work.
Also removed some debugging cruft
2013-10-15 07:45:07 +04:00
|
|
|
-- adding two tube functions
|
2014-01-11 11:04:11 +04:00
|
|
|
-- can_remove(pos,node,stack,dir) returns the maximum number of items of that stack that can be removed
|
Multiple updates:
1) Refactor autoplace,
There was a lot of redundant code and like a dozen unneccessary string
scans for every node next to every tube placed! I put it all into
indexed tables and loops instead of bizarre and unexplainable variable
names and copy and pasted code. There was also no support for notifying
a chest when an item has been taken from it by a filter, so I added
something for that.
I also thought it prudent to fall back on the
allow_metadata_inventory_take function should a special can_remove not
exist. In fact if can_insert doesn't exist, it calls
allow_metadata_inventory_put instead.
I also added a thing for allowing pipes to attach to nodes of other
modules, without having to hard code type all those node names into
autoplace.lua. Basically node.tube.collects(i,param2) and i is the
direction from the pipe and param2 is the param2 of what it's pointing
at.
I also abstracted the inscrutable correlation between i and
param2 by trial and error (and the paramwand mod) into understandable
functions. There was no pipeworks namespace so I created it, and put
these functions into pipeworks.collects (as distinguished from a
node.tube.collects function, which uses those functions)
And now it's too late to cart my old clothes to the thrift store,
dangit.
2) My "node.tube.collects" idea might be redundant with the
node.tube.connect_sides thing, though possibly more versatile so I'll
leave it in.
3) I was using node.tube.connects and fancy functions for checking if it's
the sides or top or whatnot, and this connect_side thing came in. This
should make both my way and the way using connect_side work.
Also removed some debugging cruft
2013-10-15 07:45:07 +04:00
|
|
|
-- remove_items(pos,node,stack,dir,count) removes count items and returns them
|
|
|
|
-- both optional w/ sensible defaults and fallback to normal allow_* function
|
|
|
|
-- XXX: possibly change insert_object to insert_item
|
|
|
|
|
2020-06-22 09:41:30 +03:00
|
|
|
local default_adjlist={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=0,y=1,z=0},{x=0,y=-1,z=0},{x=1,y=0,z=0},{x=-1,y=0,z=0}}
|
2013-12-15 14:35:11 +04:00
|
|
|
|
2013-12-21 13:16:58 +04:00
|
|
|
function pipeworks.notvel(tbl, vel)
|
2013-12-15 14:35:11 +04:00
|
|
|
local tbl2={}
|
|
|
|
for _,val in ipairs(tbl) do
|
2013-12-21 13:16:58 +04:00
|
|
|
if val.x ~= -vel.x or val.y ~= -vel.y or val.z ~= -vel.z then table.insert(tbl2, val) end
|
2013-12-15 14:35:11 +04:00
|
|
|
end
|
|
|
|
return tbl2
|
|
|
|
end
|
|
|
|
|
2017-04-05 04:31:57 +03:00
|
|
|
local tube_item_count = {}
|
|
|
|
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
if not luaentity.entities then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
tube_item_count = {}
|
2021-02-05 19:17:50 +03:00
|
|
|
for _, entity in pairs(luaentity.entities) do
|
2017-04-05 04:31:57 +03:00
|
|
|
if entity.name == "pipeworks:tubed_item" then
|
|
|
|
local h = minetest.hash_node_position(vector.round(entity._pos))
|
|
|
|
tube_item_count[h] = (tube_item_count[h] or 0) + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2017-12-19 02:07:40 +03:00
|
|
|
|
|
|
|
|
|
|
|
-- 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.
|
2021-03-28 03:51:23 +03:00
|
|
|
|
|
|
|
function pipeworks.break_tube(pos)
|
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
meta:set_string("the_tube_was", minetest.serialize(node))
|
|
|
|
minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"})
|
|
|
|
pipeworks.scan_for_tube_objects(pos)
|
|
|
|
end
|
|
|
|
|
2017-12-19 02:07:40 +03:00
|
|
|
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
|
2020-02-18 20:34:52 +03:00
|
|
|
pipeworks.logger("Warning - a tube at "..minetest.pos_to_string(pos).." broke due to too many items ("..itemcount..")")
|
2021-03-28 03:51:23 +03:00
|
|
|
pipeworks.break_tube(pos)
|
2017-12-19 02:07:40 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-12-20 02:15:44 +03:00
|
|
|
-- compatibility behaviour for the existing can_go() callbacks,
|
|
|
|
-- which can only specify a list of possible positions.
|
2024-03-03 14:48:27 +03:00
|
|
|
local function go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner, tags)
|
2014-08-14 18:22:03 +04:00
|
|
|
local next_positions = {}
|
|
|
|
local max_priority = 0
|
2013-12-15 14:35:11 +04:00
|
|
|
local can_go
|
2017-12-19 21:17:22 +03:00
|
|
|
|
2024-03-03 14:48:27 +03:00
|
|
|
local def = minetest.registered_nodes[cnode.name]
|
|
|
|
if def and def.tube and def.tube.can_go then
|
|
|
|
can_go = def.tube.can_go(pos, cnode, vel, stack, tags)
|
2013-12-15 14:35:11 +04:00
|
|
|
else
|
2020-06-22 09:41:30 +03:00
|
|
|
local adjlist_string = minetest.get_meta(pos):get_string("adjlist")
|
|
|
|
local adjlist = minetest.deserialize(adjlist_string) or default_adjlist -- backward compat: if not found, use old behavior: all directions
|
|
|
|
|
2013-12-21 13:16:58 +04:00
|
|
|
can_go = pipeworks.notvel(adjlist, vel)
|
2013-12-15 14:35:11 +04:00
|
|
|
end
|
2017-12-20 02:15:44 +03:00
|
|
|
-- 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.
|
2014-08-14 18:22:03 +04:00
|
|
|
for _, vect in ipairs(can_go) do
|
|
|
|
local npos = vector.add(pos, vect)
|
2017-04-04 10:25:27 +03:00
|
|
|
pipeworks.load_position(npos)
|
2013-12-21 11:46:55 +04:00
|
|
|
local node = minetest.get_node(npos)
|
2014-08-24 19:51:43 +04:00
|
|
|
local reg_node = minetest.registered_nodes[node.name]
|
|
|
|
if reg_node then
|
|
|
|
local tube_def = reg_node.tube
|
|
|
|
local tubedevice = minetest.get_item_group(node.name, "tubedevice")
|
|
|
|
local tube_priority = (tube_def and tube_def.priority) or 100
|
|
|
|
if tubedevice > 0 and tube_priority >= max_priority then
|
|
|
|
if not tube_def or not tube_def.can_insert or
|
2017-08-21 01:05:08 +03:00
|
|
|
tube_def.can_insert(npos, node, stack, vect, owner) then
|
2014-08-24 19:51:43 +04:00
|
|
|
if tube_priority > max_priority then
|
|
|
|
max_priority = tube_priority
|
|
|
|
next_positions = {}
|
|
|
|
end
|
|
|
|
next_positions[#next_positions + 1] = {pos = npos, vect = vect}
|
2014-08-14 18:22:03 +04:00
|
|
|
end
|
2013-12-15 14:35:11 +04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2014-08-14 18:22:03 +04:00
|
|
|
|
2017-12-20 02:15:44 +03:00
|
|
|
-- indicate not found if no valid rules were picked up,
|
|
|
|
-- and don't change the counter.
|
2014-08-14 18:22:03 +04:00
|
|
|
if not next_positions[1] then
|
2017-12-20 02:15:44 +03:00
|
|
|
return cycledir, false, nil, nil
|
2014-08-14 18:22:03 +04:00
|
|
|
end
|
2015-11-17 11:09:07 +03:00
|
|
|
|
2017-12-20 02:15:44 +03:00
|
|
|
-- otherwise rotate to the next output direction and return that
|
2017-12-20 01:53:18 +03:00
|
|
|
local n = (cycledir % (#next_positions)) + 1
|
2017-12-20 02:15:44 +03:00
|
|
|
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).
|
2024-03-03 14:48:27 +03:00
|
|
|
local function go_next(pos, velocity, stack, owner, tags)
|
2017-12-20 02:15:44 +03:00
|
|
|
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")
|
|
|
|
|
|
|
|
-- 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
|
2024-03-03 14:48:27 +03:00
|
|
|
local n, found, new_velocity, multimode = go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner, tags)
|
2017-12-20 02:15:44 +03:00
|
|
|
|
2017-12-20 01:53:18 +03:00
|
|
|
-- if not using output cycling,
|
|
|
|
-- don't update the field so it stays the same for the next item.
|
2014-08-14 18:22:03 +04:00
|
|
|
if pipeworks.enable_cyclic_mode then
|
|
|
|
cmeta:set_int("tubedir", n)
|
2013-12-15 14:35:11 +04:00
|
|
|
end
|
2017-12-20 02:15:44 +03:00
|
|
|
return found, new_velocity, multimode
|
2013-12-15 14:35:11 +04:00
|
|
|
end
|
|
|
|
|
2017-12-19 21:38:02 +03:00
|
|
|
|
|
|
|
|
2013-01-14 21:36:28 +04:00
|
|
|
minetest.register_entity("pipeworks:tubed_item", {
|
2013-01-14 06:45:03 +04:00
|
|
|
initial_properties = {
|
|
|
|
hp_max = 1,
|
|
|
|
physical = false,
|
2014-07-01 20:42:52 +04:00
|
|
|
collisionbox = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1},
|
2014-07-03 05:22:55 +04:00
|
|
|
visual = "wielditem",
|
|
|
|
visual_size = {x = 0.15, y = 0.15},
|
2013-01-14 06:45:03 +04:00
|
|
|
textures = {""},
|
2014-07-01 20:42:52 +04:00
|
|
|
spritediv = {x = 1, y = 1},
|
|
|
|
initial_sprite_basepos = {x = 0, y = 0},
|
2013-01-14 06:45:03 +04:00
|
|
|
is_visible = false,
|
|
|
|
},
|
2014-08-14 18:22:03 +04:00
|
|
|
|
2013-01-14 06:45:03 +04:00
|
|
|
physical_state = false,
|
|
|
|
|
2014-08-14 18:22:03 +04:00
|
|
|
from_data = function(self, itemstring)
|
2013-01-14 06:45:03 +04:00
|
|
|
local stack = ItemStack(itemstring)
|
2021-02-03 20:06:56 +03:00
|
|
|
--[[
|
2014-08-14 18:22:03 +04:00
|
|
|
local itemtable = stack:to_table()
|
|
|
|
local itemname = nil
|
|
|
|
if itemtable then
|
|
|
|
itemname = stack:to_table().name
|
|
|
|
end
|
|
|
|
local item_texture = nil
|
|
|
|
local item_type = ""
|
|
|
|
if minetest.registered_items[itemname] then
|
|
|
|
item_texture = minetest.registered_items[itemname].inventory_image
|
|
|
|
item_type = minetest.registered_items[itemname].type
|
|
|
|
end
|
2021-02-03 20:06:56 +03:00
|
|
|
--]]
|
2014-07-03 05:22:55 +04:00
|
|
|
self.object:set_properties({
|
2013-01-14 06:45:03 +04:00
|
|
|
is_visible = true,
|
2014-08-14 18:22:03 +04:00
|
|
|
textures = {stack:get_name()}
|
2014-07-03 05:22:55 +04:00
|
|
|
})
|
|
|
|
local def = stack:get_definition()
|
2018-07-03 23:30:44 +03:00
|
|
|
self.object:set_yaw((def and def.type == "node") and 0 or math.pi * 0.25)
|
2013-01-14 06:45:03 +04:00
|
|
|
end,
|
|
|
|
|
2014-08-14 18:22:03 +04:00
|
|
|
get_staticdata = luaentity.get_staticdata,
|
2014-08-14 23:18:48 +04:00
|
|
|
on_activate = function(self, staticdata) -- Legacy code, should be replaced later by luaentity.on_activate
|
|
|
|
if staticdata == "" or staticdata == nil then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if staticdata == "toremove" then
|
|
|
|
self.object:remove()
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local item = minetest.deserialize(staticdata)
|
2018-07-03 23:30:44 +03:00
|
|
|
pipeworks.tube_inject_item(self.object:get_pos(), item.start_pos, item.velocity, item.itemstring)
|
2014-08-14 23:18:48 +04:00
|
|
|
self.object:remove()
|
|
|
|
end,
|
2014-08-14 18:22:03 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_entity("pipeworks:color_entity", {
|
|
|
|
initial_properties = {
|
|
|
|
hp_max = 1,
|
|
|
|
physical = false,
|
|
|
|
collisionbox = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1},
|
|
|
|
visual = "cube",
|
|
|
|
visual_size = {x = 3.5, y = 3.5, z = 3.5}, -- todo: find correct size
|
|
|
|
textures = {""},
|
|
|
|
is_visible = false,
|
|
|
|
},
|
|
|
|
|
|
|
|
physical_state = false,
|
|
|
|
|
|
|
|
from_data = function(self, color)
|
|
|
|
local t = "pipeworks_color_"..color..".png"
|
|
|
|
local prop = {
|
|
|
|
is_visible = true,
|
|
|
|
visual = "cube",
|
|
|
|
textures = {t, t, t, t, t, t} -- todo: textures
|
|
|
|
}
|
|
|
|
self.object:set_properties(prop)
|
2013-01-14 06:45:03 +04:00
|
|
|
end,
|
|
|
|
|
2014-08-14 18:22:03 +04:00
|
|
|
get_staticdata = luaentity.get_staticdata,
|
|
|
|
on_activate = luaentity.on_activate,
|
|
|
|
})
|
|
|
|
|
2017-12-19 01:38:24 +03:00
|
|
|
-- 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
|
|
|
|
|
2014-08-14 18:22:03 +04:00
|
|
|
luaentity.register_entity("pipeworks:tubed_item", {
|
|
|
|
itemstring = '',
|
|
|
|
item_entity = nil,
|
|
|
|
color_entity = nil,
|
|
|
|
color = nil,
|
|
|
|
start_pos = nil,
|
2024-03-03 14:48:27 +03:00
|
|
|
tags = nil,
|
2014-08-14 18:22:03 +04:00
|
|
|
|
|
|
|
set_item = function(self, item)
|
|
|
|
local itemstring = ItemStack(item):to_string() -- Accept any input format
|
|
|
|
if self.itemstring == itemstring then
|
|
|
|
return
|
2013-01-14 06:45:03 +04:00
|
|
|
end
|
2014-08-14 18:22:03 +04:00
|
|
|
if self.item_entity then
|
|
|
|
self:remove_attached_entity(self.item_entity)
|
2013-01-14 06:45:03 +04:00
|
|
|
end
|
2014-08-14 18:22:03 +04:00
|
|
|
self.itemstring = itemstring
|
|
|
|
self.item_entity = self:add_attached_entity("pipeworks:tubed_item", itemstring)
|
2013-01-14 06:45:03 +04:00
|
|
|
end,
|
2015-11-17 11:09:07 +03:00
|
|
|
|
2014-08-14 18:22:03 +04:00
|
|
|
set_color = function(self, color)
|
|
|
|
if self.color == color then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
self.color = color
|
|
|
|
if self.color_entity then
|
|
|
|
self:remove_attached_entity(self.color_entity)
|
|
|
|
end
|
|
|
|
if color then
|
|
|
|
self.color_entity = self:add_attached_entity("pipeworks:color_entity", color)
|
|
|
|
else
|
|
|
|
self.color_entity = nil
|
|
|
|
end
|
2014-07-01 20:42:52 +04:00
|
|
|
end,
|
2013-01-14 06:45:03 +04:00
|
|
|
|
|
|
|
on_step = function(self, dtime)
|
2018-07-03 23:30:44 +03:00
|
|
|
local pos = self:get_pos()
|
2014-07-01 20:42:52 +04:00
|
|
|
if self.start_pos == nil then
|
2014-08-14 18:22:03 +04:00
|
|
|
self.start_pos = vector.round(pos)
|
2018-07-03 23:30:44 +03:00
|
|
|
self:set_pos(pos)
|
2014-04-13 11:25:17 +04:00
|
|
|
end
|
2015-11-17 11:09:07 +03:00
|
|
|
|
2018-07-03 23:30:44 +03:00
|
|
|
local velocity = self:get_velocity()
|
2015-11-17 11:09:07 +03:00
|
|
|
|
2014-04-13 11:25:17 +04:00
|
|
|
local moved = false
|
2014-07-01 20:42:52 +04:00
|
|
|
local speed = math.abs(velocity.x + velocity.y + velocity.z)
|
2014-08-14 18:22:03 +04:00
|
|
|
if speed == 0 then
|
|
|
|
speed = 1
|
|
|
|
moved = true
|
|
|
|
end
|
2014-07-01 20:42:52 +04:00
|
|
|
local vel = {x = velocity.x / speed, y = velocity.y / speed, z = velocity.z / speed, speed = speed}
|
2017-04-06 06:13:40 +03:00
|
|
|
local moved_by = vector.distance(pos, self.start_pos)
|
2015-11-17 11:09:07 +03:00
|
|
|
|
2017-04-06 06:13:40 +03:00
|
|
|
if moved_by >= 1 then
|
2014-08-14 18:22:03 +04:00
|
|
|
self.start_pos = vector.add(self.start_pos, vel)
|
|
|
|
moved = true
|
2013-01-14 21:36:28 +04:00
|
|
|
end
|
2015-11-17 11:09:07 +03:00
|
|
|
|
2022-05-15 17:58:35 +03:00
|
|
|
if not moved then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local stack = ItemStack(self.itemstring)
|
|
|
|
|
2017-04-04 10:25:27 +03:00
|
|
|
pipeworks.load_position(self.start_pos)
|
2014-08-14 18:22:03 +04:00
|
|
|
local node = minetest.get_node(self.start_pos)
|
2022-05-15 17:58:35 +03:00
|
|
|
if minetest.get_item_group(node.name, "tubedevice_receiver") == 1 then
|
2014-08-14 18:22:03 +04:00
|
|
|
local leftover
|
2024-03-03 14:48:27 +03:00
|
|
|
local def = minetest.registered_nodes[node.name]
|
|
|
|
if def.tube and def.tube.insert_object then
|
|
|
|
leftover = def.tube.insert_object(self.start_pos, node, stack, vel, self.owner)
|
2014-04-13 11:25:17 +04:00
|
|
|
else
|
|
|
|
leftover = stack
|
|
|
|
end
|
|
|
|
if leftover:is_empty() then
|
2014-07-01 20:42:52 +04:00
|
|
|
self:remove()
|
2014-04-13 11:25:17 +04:00
|
|
|
return
|
|
|
|
end
|
2014-08-14 18:22:03 +04:00
|
|
|
velocity = vector.multiply(velocity, -1)
|
2018-07-03 23:30:44 +03:00
|
|
|
self:set_pos(vector.subtract(self.start_pos, vector.multiply(vel, moved_by - 1)))
|
|
|
|
self:set_velocity(velocity)
|
2014-04-13 11:25:17 +04:00
|
|
|
self:set_item(leftover:to_string())
|
2013-01-14 06:45:03 +04:00
|
|
|
return
|
2013-01-14 21:36:28 +04:00
|
|
|
end
|
2015-11-17 11:09:07 +03:00
|
|
|
|
2024-03-03 14:48:27 +03:00
|
|
|
local tags
|
|
|
|
if pipeworks.enable_item_tags then
|
|
|
|
tags = self.tags or {}
|
|
|
|
end
|
|
|
|
local found_next, new_velocity, multimode = go_next(self.start_pos, velocity, stack, self.owner, tags) -- todo: color
|
|
|
|
if pipeworks.enable_item_tags then
|
2024-03-07 06:56:19 +03:00
|
|
|
self.tags = #tags > 0 and tags or nil
|
2024-03-03 14:48:27 +03:00
|
|
|
end
|
2022-05-15 17:58:35 +03:00
|
|
|
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)))
|
|
|
|
local tube_present = minetest.get_item_group(rev_node.name,"tubedevice") == 1
|
|
|
|
if not found_next then
|
|
|
|
if pipeworks.drop_on_routing_fail or not tube_present or
|
|
|
|
minetest.get_item_group(rev_node.name,"tube") ~= 1 then
|
|
|
|
-- Using add_item instead of item_drop since this makes pipeworks backward
|
|
|
|
-- compatible with Minetest 0.4.13.
|
|
|
|
-- Using item_drop here makes Minetest 0.4.13 crash.
|
|
|
|
local dropped_item = minetest.add_item(self.start_pos, stack)
|
|
|
|
if dropped_item then
|
|
|
|
dropped_item:set_velocity(vector.multiply(velocity, 5))
|
|
|
|
self:remove()
|
2014-04-13 11:25:17 +04:00
|
|
|
end
|
2017-12-19 01:38:24 +03:00
|
|
|
return
|
2022-05-15 17:58:35 +03:00
|
|
|
else
|
|
|
|
velocity = vector.multiply(velocity, -1)
|
|
|
|
self:set_pos(vector.subtract(self.start_pos, vector.multiply(vel, moved_by - 1)))
|
|
|
|
self:set_velocity(velocity)
|
2013-01-14 06:45:03 +04:00
|
|
|
end
|
2022-05-15 17:58:35 +03:00
|
|
|
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)
|
2014-08-14 18:22:03 +04:00
|
|
|
end
|
2022-05-15 17:58:35 +03:00
|
|
|
-- remove ourself now the splits are sent
|
|
|
|
self:remove()
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if new_velocity and not vector.equals(velocity, new_velocity) then
|
|
|
|
local nvelr = math.abs(new_velocity.x + new_velocity.y + new_velocity.z)
|
|
|
|
self:set_pos(vector.add(self.start_pos, vector.multiply(new_velocity, (moved_by - 1) / nvelr)))
|
|
|
|
self:set_velocity(new_velocity)
|
2014-04-13 11:25:17 +04:00
|
|
|
end
|
2013-01-14 06:45:03 +04:00
|
|
|
end
|
|
|
|
})
|
|
|
|
|
2014-08-14 18:22:03 +04:00
|
|
|
if minetest.get_modpath("mesecons_mvps") then
|
2014-11-22 21:55:54 +03:00
|
|
|
mesecon.register_mvps_unmov("pipeworks:tubed_item")
|
|
|
|
mesecon.register_mvps_unmov("pipeworks:color_entity")
|
|
|
|
mesecon.register_on_mvps_move(function(moved_nodes)
|
2014-08-14 18:22:03 +04:00
|
|
|
local moved = {}
|
2014-01-03 16:29:38 +04:00
|
|
|
for _, n in ipairs(moved_nodes) do
|
2014-08-14 18:22:03 +04:00
|
|
|
moved[minetest.hash_node_position(n.oldpos)] = vector.subtract(n.pos, n.oldpos)
|
2014-01-03 16:29:38 +04:00
|
|
|
end
|
2021-02-05 19:17:50 +03:00
|
|
|
for _, entity in pairs(luaentity.entities) do
|
2014-08-14 18:22:03 +04:00
|
|
|
if entity.name == "pipeworks:tubed_item" then
|
2018-07-03 23:30:44 +03:00
|
|
|
local pos = entity:get_pos()
|
2014-08-14 18:22:03 +04:00
|
|
|
local rpos = vector.round(pos)
|
|
|
|
local dir = moved[minetest.hash_node_position(rpos)]
|
|
|
|
if dir then
|
2018-07-03 23:30:44 +03:00
|
|
|
entity:set_pos(vector.add(pos, dir))
|
2014-08-14 18:22:03 +04:00
|
|
|
entity.start_pos = vector.add(entity.start_pos, dir)
|
|
|
|
end
|
2014-01-03 16:29:38 +04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|