-- autorouting for pneumatic tubes
-local function in_table(table,element)
- for _,el in ipairs(table) do
- if el==element then return true end
- end
- return false
-end
-
local function is_tube(nodename)
- return in_table(pipeworks.tubenodes,nodename)
-end
-
-if pipeworks == nil then
- pipeworks = {}
+ return table.contains(pipeworks.tubenodes, nodename)
end
--a function for determining which side of the node we are on
local function nodeside(node, tubedir)
- if node and (node.param2 < 0 or node.param2 > 23) then node.param2 = 0 end
+ if node.param2 < 0 or node.param2 > 23 then
+ node.param2 = 0
+ end
- --get a vector pointing back
local backdir = minetest.facedir_to_dir(node.param2)
-
- --check whether the vector is equivalent to the tube direction; if it is, the tube's on the backside
- if backdir.x == tubedir.x and backdir.y == tubedir.y and backdir.z == tubedir.z then
+ local back = vector.dot(backdir, tubedir)
+ if back == 1 then
return "back"
- end
-
- --check whether the vector is antiparallel with the tube direction; that indicates the front
- if backdir.x == -tubedir.x and backdir.y == -tubedir.y and backdir.z == -tubedir.z then
+ elseif back == -1 then
return "front"
end
- --facedir is defined in terms of the top-bottom axis of the node; we'll take advantage of that
- local topdir = ({[0]={x=0, y=1, z=0},
- {x=0, y=0, z=1},
- {x=0, y=0, z=-1},
- {x=1, y=0, z=0},
- {x=-1, y=0, z=0},
- {x=0, y=-1, z=0}})[math.floor(node.param2/4)]
-
- --is this the top?
- if topdir.x == tubedir.x and topdir.y == tubedir.y and topdir.z == tubedir.z then
+ local topdir = minetest.facedir_to_top_dir(node.param2)
+ local top = vector.dot(topdir, tubedir)
+ if top == 1 then
return "top"
- end
-
- --or the bottom?
- if topdir.x == -tubedir.x and topdir.y == -tubedir.y and topdir.z == -tubedir.z then
+ elseif top == -1 then
return "bottom"
end
- --we shall apply some maths to obtain the right-facing vector
- local rightdir = {x=topdir.y*backdir.z - backdir.y*topdir.z,
- y=topdir.z*backdir.x - backdir.z*topdir.x,
- z=topdir.x*backdir.y - backdir.x*topdir.y}
-
- --is this the right side?
- if rightdir.x == tubedir.x and rightdir.y == tubedir.y and rightdir.z == tubedir.z then
+ local rightdir = minetest.facedir_to_right_dir(node.param2)
+ local right = vector.dot(rightdir, tubedir)
+ if right == 1 then
return "right"
- end
-
- --or the left?
- if rightdir.x == -tubedir.x and rightdir.y == -tubedir.y and rightdir.z == -tubedir.z then
+ else
return "left"
end
-
- --we should be done by now; initiate panic mode
- minetest.log("error", "nodeside has been confused by its parameters; see pipeworks autoplace_tubes.lua, line 78")
end
local vts = {0, 3, 1, 4, 2, 5}
if not is_tube(nctr.name) then return end
local adjustments = {
- { x=-1, y=0, z=0 },
- { x=1, y=0, z=0 },
- { x=0, y=-1, z=0 },
- { x=0, y=1, z=0 },
- { x=0, y=0, z=-1 },
- { x=0, y=0, z=1 }
+ {x = -1, y = 0, z = 0},
+ {x = 1, y = 0, z = 0},
+ {x = 0, y = -1, z = 0},
+ {x = 0, y = 1, z = 0},
+ {x = 0, y = 0, z = -1},
+ {x = 0, y = 0, z = 1}
}
-- xm = 1, xp = 2, ym = 3, yp = 4, zm = 5, zp = 6
local positions = {}
local nodes = {}
- for i,adj in ipairs(adjustments) do
- positions[i] = {x=pos.x+adj.x, y=pos.y+adj.y, z=pos.z+adj.z}
+ for i, adj in ipairs(adjustments) do
+ positions[i] = vector.add(pos, adj)
nodes[i] = minetest.get_node(positions[i])
end
- for i,node in ipairs(nodes) do
+ for i, node in ipairs(nodes) do
local idef = minetest.registered_nodes[node.name]
-- handle the tubes themselves
if is_tube(node.name) then
-- handle new style connectors
elseif idef and idef.tube and idef.tube.connect_sides then
local dir = adjustments[i]
- if idef.tube.connect_sides[nodeside(node, {x=-dir.x, y=-dir.y, z=-dir.z})] then active[i] = 1 end
+ if idef.tube.connect_sides[nodeside(node, vector.multiply(dir, -1))] then
+ active[i] = 1
+ end
end
end
local nodedef = minetest.registered_nodes[nctr.name]
local basename = nodedef.basename
- local newname
if nodedef.style == "old" then
local nsurround = ""
- for i,n in ipairs(active) do
- nsurround = nsurround .. n
+ for i, n in ipairs(active) do
+ nsurround = nsurround..n
end
nctr.name = basename.."_"..nsurround
elseif nodedef.style == "6d" then
local s = 0
- for i,n in ipairs(active) do
+ for i, n in ipairs(active) do
if n == 1 then
- s = s+2^vts[i]
+ s = s + 2^vts[i]
end
end
nctr.name = basename.."_"..tube_table[s]
end
function pipeworks.scan_for_tube_objects(pos)
- if not pos or not pos.x or not pos.y or not pos.z then return end
- tube_autoroute({ x=pos.x-1, y=pos.y , z=pos.z })
- tube_autoroute({ x=pos.x+1, y=pos.y , z=pos.z })
- tube_autoroute({ x=pos.x , y=pos.y-1, z=pos.z })
- tube_autoroute({ x=pos.x , y=pos.y+1, z=pos.z })
- tube_autoroute({ x=pos.x , y=pos.y , z=pos.z-1 })
- tube_autoroute({ x=pos.x , y=pos.y , z=pos.z+1 })
- tube_autoroute(pos)
+ for side = 0, 6 do
+ tube_autoroute(vector.add(pos, directions.side_to_dir(side)))
+ end
end
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack)
end
end)
-if minetest.get_modpath("mesecons_mvps") ~= nil then
+if minetest.get_modpath("mesecons_mvps") then
mesecon:register_on_mvps_move(function(moved_nodes)
for _, n in ipairs(moved_nodes) do
pipeworks.scan_for_tube_objects(n.pos)
--- /dev/null
+----------------------
+-- Vector functions --
+----------------------
+
+function vector.cross(a, b)
+ return {
+ x = a.y * b.z - a.z * b.y,
+ y = a.z * b.x - a.x * b.z,
+ z = a.x * b.y - a.y * b.x
+ }
+end
+
+function vector.dot(a, b)
+ return a.x * b.x + a.y * b.y + a.z * b.z
+end
+
+-----------------------
+-- Facedir functions --
+-----------------------
+
+function minetest.facedir_to_top_dir(facedir)
+ return ({[0] = {x = 0, y = 1, z = 0},
+ {x = 0, y = 0, z = 1},
+ {x = 0, y = 0, z = -1},
+ {x = 1, y = 0, z = 0},
+ {x = -1, y = 0, z = 0},
+ {x = 0, y = -1, z = 0}})
+ [math.floor(facedir / 4)]
+end
+
+function minetest.facedir_to_right_dir(facedir)
+ return vector.cross(
+ minetest.facedir_to_top_dir(facedir),
+ minetest.facedir_to_dir(facedir)
+ )
+end
+
+directions = {}
+function directions.side_to_dir(side)
+ return ({[0] = vector.new(),
+ vector.new( 0, 1, 0),
+ vector.new( 0, -1, 0),
+ vector.new( 1, 0, 0),
+ vector.new(-1, 0, 0),
+ vector.new( 0, 0, 1),
+ vector.new( 0, 0, -1)
+ })[side]
+end
+
+function directions.dir_to_side(dir)
+ local c = vector.dot(dir, vector.new(1, 2, 3)) + 4
+ return ({6, 2, 4, 0, 3, 1, 5})[c]
+end
+
+----------------------
+-- String functions --
+----------------------
+
+--[[function string.split(str, sep)
+ local fields = {}
+ local index = 1
+ local expr = "([^"..sep.."])+"
+ string.gsub(str, expr, function(substring)
+ fields[index] = substring
+ index = index + 1
+ end)
+ return fields
+end]]
+
+function string.startswith(str, substr)
+ return str:sub(1, substr:len()) == substr
+end
+
+---------------------
+-- Table functions --
+---------------------
+
+function table.contains(tbl, element)
+ for _, elt in pairs(tbl) do
+ if elt == element then
+ return true
+ end
+ end
+ return false
+end
+
+function table.extend(tbl, tbl2)
+ local index = #tbl + 1
+ for _, elt in ipairs(tbl2) do
+ tbl[index] = elt
+ index = index + 1
+ end
+end
+
+function table.recursive_replace(tbl, pattern, replace_with)
+ if type(tbl) == "table" then
+ local tbl2 = {}
+ for key, value in pairs(tbl) do
+ tbl2[key] = table.recursive_replace(value, pattern, replace_with)
+ end
+ return tbl2
+ elseif type(tbl) == "string" then
+ return tbl:gsub(pattern, replace_with)
+ else
+ return tbl
+ end
+end
+
+------------------------
+-- Formspec functions --
+------------------------
+
+fs_helpers = {}
+function fs_helpers.on_receive_fields(pos, fields)
+ local meta = minetest.get_meta(pos)
+ for field, value in pairs(fields) do
+ if field:startswith("fs_helpers_cycling:") then
+ local l = field:split(":")
+ local new_value = tonumber(l[2])
+ local meta_name = l[3]
+ meta:set_int(meta_name, new_value)
+ end
+ end
+end
+
+function fs_helpers.cycling_button(meta, base, meta_name, values)
+ local current_value = meta:get_int(meta_name)
+ local new_value = (current_value + 1) % (#values)
+ local text = values[current_value + 1]
+ local field = "fs_helpers_cycling:"..new_value..":"..meta_name
+ return base..";"..field..";"..text.."]"
+end
+
+---------
+-- Env --
+---------
+
+function minetest.load_position(pos)
+ if minetest.get_node_or_nil(pos) then
+ return
+ end
+ local vm = minetest.get_voxel_manip()
+ vm:read_from_map(pos, pos)
+end
\ No newline at end of file
-------------------------------------------
-- Load the various other parts of the mod
+dofile(pipeworks.modpath.."/common.lua")
dofile(pipeworks.modpath.."/models.lua")
dofile(pipeworks.modpath.."/autoplace_pipes.lua")
dofile(pipeworks.modpath.."/autoplace_tubes.lua")
+dofile(pipeworks.modpath.."/luaentity.lua")
dofile(pipeworks.modpath.."/item_transport.lua")
dofile(pipeworks.modpath.."/flowing_logic.lua")
dofile(pipeworks.modpath.."/crafts.lua")
-dofile(pipeworks.modpath.."/compat.lua")
-
---and an extra function for getting the right-facing vector
-local function facedir_to_right_dir(facedir)
-
- --find the other directions
- local backdir = minetest.facedir_to_dir(facedir)
- local topdir = ({[0]={x=0, y=1, z=0},
- {x=0, y=0, z=1},
- {x=0, y=0, z=-1},
- {x=1, y=0, z=0},
- {x=-1, y=0, z=0},
- {x=0, y=-1, z=0}})[math.floor(facedir/4)]
-
- --return a cross product
- return {x=topdir.y*backdir.z - backdir.y*topdir.z,
- y=topdir.z*backdir.x - backdir.z*topdir.x,
- z=topdir.x*backdir.y - backdir.x*topdir.y}
-end
-
local fakePlayer = {
get_player_name = function() return ":pipeworks" end,
-- any other player functions called by allow_metadata_inventory_take anywhere...
-- perhaps a custom metaclass that errors specially when fakePlayer.<property> is not found?
}
-function pipeworks.tube_item(pos, item)
+function pipeworks.tube_item(pos, start_pos, velocity, item)
-- Take item in any format
local stack = ItemStack(item)
- local obj = minetest.add_entity(pos, "pipeworks:tubed_item")
- obj:get_luaentity():set_item(stack:to_string())
+ local obj = luaentity.add_entity(pos, "pipeworks:tubed_item")
+ obj:set_item(stack:to_string())
+ obj.start_pos = vector.new(start_pos)
+ obj:setvelocity(velocity)
+ --obj:set_color("red") -- todo: this is test-only code
return obj
end
"item_image[0,0;1,1;pipeworks:"..data.name.."]"..
"label[1,0;"..minetest.formspec_escape(itemname).."]"..
"label[0,1;Prefer item types:]"..
- "list[current_name;main;0,1.5;8,2;]"
- local slotseq_mode = meta:get_int("slotseq_mode")
- if slotseq_mode == 1 then
- formspec = formspec .. "button[0,3.5;4,1;slotseq_mode2;Sequence slots Randomly]"
- elseif slotseq_mode == 2 then
- formspec = formspec .. "button[0,3.5;4,1;slotseq_mode0;Sequence slots by Rotation]"
- else
- formspec = formspec .. "button[0,3.5;4,1;slotseq_mode1;Sequence slots by Priority]"
- end
- formspec = formspec .. "list[current_player;main;0,4.5;8,4;]"
+ "list[current_name;main;0,1.5;8,2;]"..
+ fs_helpers.cycling_button(meta, "button[0,3.5;4,1", "slotseq_mode",
+ {"Sequence slots by Priority",
+ "Sequence slots Randomly",
+ "Sequence slots by Rotation"})..
+ "list[current_player;main;0,4.5;8,4;]"
meta:set_string("formspec", formspec)
end
+-- todo SOON: this function has *way too many* parameters
local function grabAndFire(data,slotseq_mode,filtmeta,frominv,frominvname,frompos,fromnode,filtername,fromtube,fromdef,dir,all)
local sposes = {}
for spos,stack in ipairs(frominv:get_list(frominvname)) do
fromdef.on_metadata_inventory_take(frompos, frominvname, spos, item, fakePlayer)
end
end
- local item1 = pipeworks.tube_item(vector.add(frompos, vector.multiply(dir, 1.4)), item)
- item1:get_luaentity().start_pos = vector.add(frompos, dir)
- item1:setvelocity(dir)
- item1:setacceleration({x=0, y=0, z=0})
+ local pos = vector.add(frompos, vector.multiply(dir, 1.4))
+ local start_pos = vector.add(frompos, dir)
+ local item1 = pipeworks.tube_item(pos, start_pos, dir, item)
return true-- only fire one item, please
end
end
local function punch_filter(data, filtpos, filtnode)
local filtmeta = minetest.get_meta(filtpos)
local filtinv = filtmeta:get_inventory()
- local dir = facedir_to_right_dir(filtnode.param2)
- local frompos = {x=filtpos.x - dir.x, y=filtpos.y - dir.y, z=filtpos.z - dir.z}
+ local dir = minetest.facedir_to_right_dir(filtnode.param2)
+ local frompos = vector.subtract(filtpos, dir)
local fromnode = minetest.get_node(frompos)
if not fromnode then return end
local fromdef = minetest.registered_nodes[fromnode.name]
"pipeworks_"..data.name.."_top.png",
},
paramtype2 = "facedir",
- groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,tubedevice=1,mesecon=2},
+ groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, mesecon = 2},
legacy_facedir_simple = true,
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
inv:set_size("main", 8*2)
end,
on_receive_fields = function(pos, formname, fields, sender)
+ fs_helpers.on_receive_fields(pos, fields)
local meta = minetest.get_meta(pos)
- for k, _ in pairs(fields) do
- if k:sub(1, 12) == "slotseq_mode" then
- local mode = tonumber(k:sub(13, 13))
- meta:set_int("slotseq_mode", mode)
- meta:set_int("slotseq_index", mode == 2 and 1 or 0)
- end
- end
+ meta:set_int("slotseq_index", 1)
set_filter_formspec(data, meta)
set_filter_infotext(data, meta)
end,
- can_dig = function(pos,player)
+ can_dig = function(pos, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("main")
end,
- after_place_node = function(pos)
- pipeworks.scan_for_tube_objects(pos)
- end,
- after_dig_node = function(pos)
- pipeworks.scan_for_tube_objects(pos)
- end,
mesecons = {
effector = {
action_on = function(pos, node)
end,
},
},
- tube={connect_sides={right=1}},
+ tube = {connect_sides = {right = 1}},
on_punch = function (pos, node, puncher)
punch_filter(data, pos, node)
end,
})
end
-local function roundpos(pos)
- return {x=math.floor(pos.x+0.5),y=math.floor(pos.y+0.5),z=math.floor(pos.z+0.5)}
-end
-
-local function addVect(pos,vect)
- return {x=pos.x+vect.x,y=pos.y+vect.y,z=pos.z+vect.z}
-end
-
local 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}}
function pipeworks.notvel(tbl, vel)
end
local function go_next(pos, velocity, stack)
- local chests = {}
- local tubes = {}
+ local next_positions = {}
+ local max_priority = 0
local cnode = minetest.get_node(pos)
local cmeta = minetest.get_meta(pos)
- local n
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
+ speed = speed - 0.1
else
speed = 1
end
else
can_go = pipeworks.notvel(adjlist, vel)
end
- local meta = nil
- for _,vect in ipairs(can_go) do
- local npos = addVect(pos,vect)
+ for _, vect in ipairs(can_go) do
+ local npos = vector.add(pos, vect)
local node = minetest.get_node(npos)
- local tube_receiver = minetest.get_item_group(node.name,"tubedevice_receiver")
- meta = minetest.get_meta(npos)
- local tubelike = meta:get_int("tubelike")
- if tube_receiver == 1 then
- if minetest.registered_nodes[node.name].tube and
- minetest.registered_nodes[node.name].tube.can_insert and
- minetest.registered_nodes[node.name].tube.can_insert(npos, node, stack, vect) then
- local i = #chests + 1
- chests[i] = {}
- chests[i].pos = npos
- chests[i].vect = vect
+ local tubedevice = minetest.get_item_group(node.name, "tubedevice")
+ local tube_def = minetest.registered_nodes[node.name].tube
+ 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
+ tubedef.can_insert(npos, node, stack, vect) then
+ if tube_priority > max_priority then
+ max_priority = tube_priority
+ next_positions = {}
+ end
+ next_positions[#next_positions + 1] = {pos = npos, vect = vect}
end
- elseif tubelike == 1 then
- local i = #tubes + 1
- tubes[i] = {}
- tubes[i].pos = npos
- tubes[i].vect = vect
end
end
- if chests[1] == nil then--no chests found
- if tubes[1] == nil then
- return 0
- else
- n = (cmeta:get_int("tubedir")%(#tubes)) + 1
- if pipeworks.enable_cyclic_mode then
- cmeta:set_int("tubedir",n)
- end
- velocity.x = tubes[n].vect.x*vel.speed
- velocity.y = tubes[n].vect.y*vel.speed
- velocity.z = tubes[n].vect.z*vel.speed
- end
- else
- n = (cmeta:get_int("tubedir")%(#chests))+1
- if pipeworks.enable_cyclic_mode then
- cmeta:set_int("tubedir",n)
- end
- velocity.x = chests[n].vect.x*speed
- velocity.y = chests[n].vect.y*speed
- velocity.z = chests[n].vect.z*speed
+
+ if not next_positions[1] then
+ return false, nil
+ end
+
+ local n = (cmeta:get_int("tubedir") % (#next_positions)) + 1
+ if pipeworks.enable_cyclic_mode then
+ cmeta:set_int("tubedir", n)
end
- return 1
+ local new_velocity = vector.multiply(next_positions[n].vect, vel.speed)
+ return true, new_velocity
end
minetest.register_entity("pipeworks:tubed_item", {
initial_properties = {
hp_max = 1,
physical = false,
--- collisionbox = {0,0,0,0,0,0},
collisionbox = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1},
visual = "wielditem",
visual_size = {x = 0.15, y = 0.15},
spritediv = {x = 1, y = 1},
initial_sprite_basepos = {x = 0, y = 0},
is_visible = false,
- start_pos = {},
- route = {},
- removed = false
},
-
- itemstring = '',
+
physical_state = false,
- set_item = function(self, itemstring)
- self.itemstring = itemstring
+ from_data = function(self, itemstring)
local stack = ItemStack(itemstring)
+ 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
self.object:set_properties({
is_visible = true,
- textures = { stack:get_name() },
+ textures = {stack:get_name()}
})
local def = stack:get_definition()
self.object:setyaw((def and def.type == "node") and 0 or math.pi * 0.25)
end,
- get_staticdata = function(self)
- if self.start_pos == nil or self.removed then
- return
- end
- local velocity = self.object:getvelocity()
- self.object:setpos(self.start_pos)
- return minetest.serialize({
- itemstring = self.itemstring,
- velocity = velocity,
- start_pos = self.start_pos
- })
+ get_staticdata = luaentity.get_staticdata,
+ on_activate = luaentity.on_activate,
+})
+
+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)
end,
- on_activate = function(self, staticdata)
- if staticdata=="" or staticdata==nil then return end
- local item = minetest.deserialize(staticdata)
- local stack = ItemStack(item.itemstring)
- local itemtable = stack:to_table()
- local itemname = nil
- if itemtable then
- itemname = stack:to_table().name
+ get_staticdata = luaentity.get_staticdata,
+ on_activate = luaentity.on_activate,
+})
+
+luaentity.register_entity("pipeworks:tubed_item", {
+ itemstring = '',
+ item_entity = nil,
+ color_entity = nil,
+ color = nil,
+ start_pos = nil,
+
+ set_item = function(self, item)
+ local itemstring = ItemStack(item):to_string() -- Accept any input format
+ if self.itemstring == itemstring then
+ return
end
-
- if itemname then
- self.start_pos=item.start_pos
- self.object:setvelocity(item.velocity)
- self.object:setacceleration({x=0, y=0, z=0})
- self.object:setpos(item.start_pos)
+ if self.item_entity then
+ self:remove_attached_entity(self.item_entity)
end
- self:set_item(item.itemstring)
+ self.itemstring = itemstring
+ self.item_entity = self:add_attached_entity("pipeworks:tubed_item", itemstring)
end,
- remove = function(self)
- self.object:remove()
- self.removed = true
- self.itemstring = ''
+ 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
end,
on_step = function(self, dtime)
- if self.removed then
- return
- end
if self.start_pos == nil then
- local pos = self.object:getpos()
- self.start_pos = roundpos(pos)
+ local pos = self:getpos()
+ self.start_pos = vector.round(pos)
+ self:setpos(pos)
end
- local pos = self.object:getpos()
- local node = minetest.get_node(pos)
- local meta = minetest.get_meta(pos)
- local tubelike = meta:get_int("tubelike")
+
+ local pos = self:getpos()
local stack = ItemStack(self.itemstring)
- local drop_pos = nil
+ local drop_pos
- local velocity = self.object:getvelocity()
-
- if velocity == nil then return end
-
- local velocitycopy = {x = velocity.x, y = velocity.y, z = velocity.z}
+ local velocity = self:getvelocity()
local moved = false
local speed = math.abs(velocity.x + velocity.y + velocity.z)
+ if speed == 0 then
+ speed = 1
+ moved = true
+ end
local vel = {x = velocity.x / speed, y = velocity.y / speed, z = velocity.z / speed, speed = speed}
- if math.abs(vel.x) == 1 then
- local next_node = math.abs(pos.x - self.start_pos.x)
- if next_node >= 1 then
- self.start_pos.x = self.start_pos.x + vel.x
- moved = true
- end
- elseif math.abs(vel.y) == 1 then
- local next_node = math.abs(pos.y - self.start_pos.y)
- if next_node >= 1 then
- self.start_pos.y = self.start_pos.y + vel.y
- moved = true
- end
- elseif math.abs(vel.z) == 1 then
- local next_node = math.abs(pos.z - self.start_pos.z)
- if next_node >= 1 then
- self.start_pos.z = self.start_pos.z + vel.z
- moved = true
- end
+ if vector.distance(pos, self.start_pos) >= 1 then
+ self.start_pos = vector.add(self.start_pos, vel)
+ moved = true
end
- local sposcopy = {x = self.start_pos.x, y = self.start_pos.y, z = self.start_pos.z}
-
- node = minetest.get_node(self.start_pos)
+ minetest.load_position(self.start_pos)
+ local node = minetest.get_node(self.start_pos)
if moved and minetest.get_item_group(node.name, "tubedevice_receiver") == 1 then
- local leftover = nil
+ local leftover
if minetest.registered_nodes[node.name].tube and minetest.registered_nodes[node.name].tube.insert_object then
leftover = minetest.registered_nodes[node.name].tube.insert_object(self.start_pos, node, stack, vel)
else
self:remove()
return
end
- velocity.x = -velocity.x
- velocity.y = -velocity.y
- velocity.z = -velocity.z
- self.object:setvelocity(velocity)
+ velocity = vector.multiply(velocity, -1)
+ self:setvelocity(velocity)
self:set_item(leftover:to_string())
return
end
if moved then
- if go_next (self.start_pos, velocity, stack) == 0 then
+ local found_next, new_velocity = go_next(self.start_pos, velocity, stack) -- todo: color
+ if not found_next then
drop_pos = minetest.find_node_near(vector.add(self.start_pos, velocity), 1, "air")
if drop_pos then
minetest.item_drop(stack, "", drop_pos)
self:remove()
+ return
end
end
- end
-
- if velocity.x~=velocitycopy.x or velocity.y~=velocitycopy.y or velocity.z~=velocitycopy.z or
- self.start_pos.x~=sposcopy.x or self.start_pos.y~=sposcopy.y or self.start_pos.z~=sposcopy.z then
- self.object:setpos(self.start_pos)
- self.object:setvelocity(velocity)
+
+ if new_velocity and not vector.equals(velocity, new_velocity) then
+ self:setpos(self.start_pos)
+ self:setvelocity(new_velocity)
+ end
end
end
})
-if minetest.get_modpath("mesecons_mvps") ~= nil then
- local function add_table(table,toadd)
- local i = 1
- while true do
- o = table[i]
- if o == toadd then return end
- if o == nil then break end
- i = i+1
- end
- table[i] = toadd
- end
+if minetest.get_modpath("mesecons_mvps") then
mesecon:register_mvps_unmov("pipeworks:tubed_item")
+ mesecon:register_mvps_unmov("pipeworks:color_entity")
mesecon:register_on_mvps_move(function(moved_nodes)
- local objects_to_move = {}
+ local moved = {}
for _, n in ipairs(moved_nodes) do
- local objects = minetest.get_objects_inside_radius(n.oldpos, 1)
- for _, obj in ipairs(objects) do
- local entity = obj:get_luaentity()
- if entity and entity.name == "pipeworks:tubed_item" then
- --objects_to_move[#objects_to_move+1] = obj
- add_table(objects_to_move, obj)
- end
- end
+ moved[minetest.hash_node_position(n.oldpos)] = vector.subtract(n.pos, n.oldpos)
end
- if #objects_to_move > 0 then
- local dir = vector.subtract(moved_nodes[1].pos, moved_nodes[1].oldpos)
- for _, obj in ipairs(objects_to_move) do
- local entity = obj:get_luaentity()
- obj:setpos(vector.add(obj:getpos(), dir))
- entity.start_pos = vector.add(entity.start_pos, dir)
+ for id, entity in pairs(luaentity.entities) do
+ if entity.name == "pipeworks:tubed_item" then
+ local pos = entity:getpos()
+ local rpos = vector.round(pos)
+ local dir = moved[minetest.hash_node_position(rpos)]
+ if dir then
+ entity:setpos(vector.add(pos, dir))
+ entity.start_pos = vector.add(entity.start_pos, dir)
+ end
end
end
end)
--- /dev/null
+local max_entity_id = 1000000000000 -- If you need more, there's a problem with your code
+
+luaentity = {}
+
+luaentity.registered_entities = {}
+
+local filename = minetest.get_worldpath().."/luaentities"
+local function read_file()
+ local f = io.open(filename, "r")
+ if f == nil then return {} end
+ local t = f:read("*all")
+ f:close()
+ if t == "" or t == nil then return {} end
+ return minetest.deserialize(t)
+end
+
+local function write_file(tbl)
+ local f = io.open(filename, "w")
+ f:write(minetest.serialize(tbl))
+ f:close()
+end
+
+local function read_entities()
+ local t = read_file()
+ for _, entity in pairs(t) do
+ setmetatable(entity, luaentity.registered_entities[entity.name])
+ end
+ return t
+end
+
+local function write_entities()
+ for _, entity in pairs(luaentity.entities) do
+ setmetatable(entity, nil)
+ for _, attached in pairs(entity._attached_entities) do
+ if attached.entity then
+ attached.entity:remove()
+ attached.entity = nil
+ end
+ end
+ entity._attached_entities_master = nil
+ end
+ write_file(luaentity.entities)
+end
+
+minetest.after(0, function()
+ luaentity.entities = read_entities()
+end)
+minetest.register_on_shutdown(write_entities)
+ -- todo: load that from file (datastorage?) -> don't forget about metatables (are those serialized?) / do not blindly save -> the attached_entities have to be removed
+luaentity.entities_index = 0
+
+local function get_blockpos(pos)
+ return {x = math.floor(pos.x / 16),
+ y = math.floor(pos.y / 16),
+ z = math.floor(pos.z / 16)}
+end
+
+local active_blocks = {} -- These only contain active blocks near players (i.e., not forceloaded ones)
+local handle_active_blocks_step = 2
+local handle_active_blocks_timer = 0
+minetest.register_globalstep(function(dtime)
+ handle_active_blocks_timer = handle_active_blocks_timer + dtime
+ if handle_active_blocks_timer >= handle_active_blocks_step then
+ handle_active_blocks_timer = handle_active_blocks_timer - handle_active_blocks_step
+ local active_block_range = tonumber(minetest.setting_get("active_block_range"))
+ local new_active_blocks = {}
+ for _, player in ipairs(minetest.get_connected_players()) do
+ local blockpos = get_blockpos(player:getpos())
+ local minp = vector.subtract(blockpos, active_block_range)
+ local maxp = vector.add(blockpos, active_block_range)
+
+ for x = minp.x, maxp.x do
+ for y = minp.y, maxp.y do
+ for z = minp.z, maxp.z do
+ local pos = {x = x, y = y, z = z}
+ new_active_blocks[minetest.hash_node_position(pos)] = pos
+ end
+ end
+ end
+ end
+ active_blocks = new_active_blocks
+ -- todo: callbacks on block load/unload
+ end
+end)
+
+local function is_active(pos)
+ return active_blocks[minetest.hash_node_position(get_blockpos(pos))] ~= nil
+end
+
+local entitydef_default = {
+ _attach = function(self, attached, attach_to)
+ local attached_def = self._attached_entities[attached]
+ local attach_to_def = self._attached_entities[attach_to]
+ attached_def.entity:set_attach(
+ attach_to_def.entity, "",
+ vector.subtract(attached_def.offset, attach_to_def.offset), -- todo: Does not work because is object space
+ vector.new(0, 0, 0)
+ )
+ end,
+ _set_master = function(self, index)
+ self._attached_entities_master = index
+ if not index then
+ return
+ end
+ local def = self._attached_entities[index]
+ if not def.entity then
+ return
+ end
+ def.entity:setpos(vector.add(self._pos, def.offset))
+ def.entity:setvelocity(self._velocity)
+ def.entity:setacceleration(self._acceleration)
+ end,
+ _attach_all = function(self)
+ local master = self._attached_entities_master
+ if not master then
+ return
+ end
+ for id, entity in pairs(self._attached_entities) do
+ if id ~= master and entity.entity then
+ self:_attach(id, master)
+ end
+ end
+ end,
+ _detach_all = function(self)
+ local master = self._attached_entities_master
+ for id, entity in pairs(self._attached_entities) do
+ if id ~= master and entity.entity then
+ entity.entity:set_detach()
+ end
+ end
+ end,
+ _add_attached = function(self, index)
+ local entity = self._attached_entities[index]
+ if entity.entity then
+ return
+ end
+ local entity_pos = vector.add(self._pos, entity.offset)
+ if not is_active(entity_pos) then
+ return
+ end
+ local ent = minetest.add_entity(entity_pos, entity.name):get_luaentity()
+ ent:from_data(entity.data)
+ ent.parent_id = self._id
+ ent.attached_id = index
+ entity.entity = ent.object
+ local master = self._attached_entities_master
+ if master then
+ self:_attach(index, master)
+ else
+ self:_set_master(index)
+ end
+ end,
+ _remove_attached = function(self, index)
+ local master = self._attached_entities_master
+ local entity = self._attached_entities[index]
+ local ent = entity.entity
+ entity.entity = nil
+ if index == master then
+ self:_detach_all()
+ local newmaster
+ for id, attached in pairs(self._attached_entities) do
+ if id ~= master and attached.entity then
+ newmaster = id
+ break
+ end
+ end
+ self:_set_master(newmaster)
+ self:_attach_all()
+ elseif master and ent then
+ ent:set_detach()
+ end
+ if ent then
+ ent:remove()
+ end
+ end,
+ _add_loaded = function(self)
+ for id, _ in pairs(self._attached_entities) do
+ self:_add_attached(id)
+ end
+ end,
+ getid = function(self)
+ return self._id
+ end,
+ getpos = function(self)
+ return vector.new(self._pos)
+ end,
+ setpos = function(self, pos)
+ self._pos = vector.new(pos)
+ --for _, entity in pairs(self._attached_entities) do
+ -- if entity.entity then
+ -- entity.entity:setpos(vector.add(self._pos, entity.offset))
+ -- end
+ --end
+ local master = self._attached_entities_master
+ if master then
+ local master_def = self._attached_entities[master]
+ master_def.entity:setpos(vector.add(self._pos, master_def.offset))
+ end
+ end,
+ getvelocity = function(self)
+ return vector.new(self._velocity)
+ end,
+ setvelocity = function(self, velocity)
+ self._velocity = vector.new(velocity)
+ local master = self._attached_entities_master
+ if master then
+ self._attached_entities[master].entity:setvelocity(self._velocity)
+ end
+ end,
+ getacceleration = function(self)
+ return vector.new(self._acceleration)
+ end,
+ setacceleration = function(self, acceleration)
+ self._acceleration = vector.new(acceleration)
+ local master = self._attached_entities_master
+ if master then
+ self._attached_entities[master].entity:setacceleration(self._acceleration)
+ end
+ end,
+ remove = function(self)
+ self:_detach_all()
+ for _, entity in pairs(self._attached_entities) do
+ if entity.entity then
+ entity.entity:remove()
+ end
+ end
+ luaentity.entities[self._id] = nil
+ end,
+ add_attached_entity = function(self, name, data, offset)
+ local index = #self._attached_entities + 1
+ self._attached_entities[index] = {
+ name = name,
+ data = data,
+ offset = vector.new(offset),
+ }
+ self:_add_attached(index)
+ return index
+ end,
+ remove_attached_entity = function(self, index)
+ self:_remove_attached(index)
+ self._attached_entities[index] = nil
+ end,
+}
+
+function luaentity.register_entity(name, prototype)
+ -- name = check_modname_prefix(name)
+ prototype.name = name
+ setmetatable(prototype, {__index = entitydef_default})
+ prototype.__index = prototype -- Make it possible to use it as metatable
+ luaentity.registered_entities[name] = prototype
+end
+
+-- function luaentity.get_entity_definition(entity)
+-- return luaentity.registered_entities[entity.name]
+-- end
+
+function luaentity.add_entity(pos, name)
+ local index = luaentity.entities_index
+ while luaentity.entities[index] do
+ index = index + 1
+ if index >= max_entity_id then
+ index = 0
+ end
+ end
+ luaentity.entities_index = index
+
+ local entity = {
+ name = name,
+ _id = index,
+ _pos = vector.new(pos),
+ _velocity = {x = 0, y = 0, z = 0},
+ _acceleration = {x = 0, y = 0, z = 0},
+ _attached_entities = {},
+ }
+
+ local prototype = luaentity.registered_entities[name]
+ setmetatable(entity, prototype) -- Default to prototype for other methods
+ luaentity.entities[index] = entity
+
+ if entity.on_activate then
+ entity:on_activate()
+ end
+ return entity
+end
+
+-- todo: check if remove in get_staticdata works
+function luaentity.get_staticdata(self)
+ local parent = luaentity.entities[self.parent_id]
+ if parent and parent._remove_attached then
+ parent:_remove_attached(self.attached_id)
+ end
+ return "toremove"
+end
+
+function luaentity.on_activate(self, staticdata)
+ if staticdata == "toremove" then
+ self.object:remove()
+ end
+end
+
+function luaentity.get_objects_inside_radius(pos, radius)
+ local objects = {}
+ local index = 1
+ for id, entity in pairs(luaentity.entities) do
+ if vector.distance(pos, entity:getpos()) <= radius then
+ objects[index] = entity
+ index = index + 1
+ end
+ end
+end
+
+minetest.register_globalstep(function(dtime)
+ for id, entity in pairs(luaentity.entities) do
+ local master = entity._attached_entities_master
+ if master then
+ local master_def = entity._attached_entities[master]
+ local master_entity = master_def.entity
+ entity._pos = vector.subtract(master_entity:getpos(), master_def.offset)
+ entity._velocity = master_entity:getvelocity()
+ entity._acceleration = master_entity:getacceleration()
+ else
+ entity._pos = vector.add(vector.add(
+ entity._pos,
+ vector.multiply(entity._velocity, dtime)),
+ vector.multiply(entity._acceleration, 0.5 * dtime * dtime))
+ entity._velocity = vector.add(
+ entity._velocity,
+ vector.multiply(entity._acceleration, dtime))
+ end
+ entity:_add_loaded()
+ if entity.on_step then
+ entity:on_step(dtime)
+ end
+ end
+end)
"pipeworks_trashcan_side.png",
"pipeworks_trashcan_side.png",
},
- groups = { snappy = 3, tubedevice = 1, tubedevice_receiver = 1 },
+ groups = {snappy = 3, tubedevice = 1, tubedevice_receiver = 1},
tube = {
insert_object = function(pos, node, stack, direction)
return ItemStack("")
- end,
- can_insert = function(pos, node, stack, direction)
- return true
- end,
- connect_sides = { left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1 },
+ end,
+ connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1},
+ priority = 1, -- Lower than anything else
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
end
for _, v in ipairs(connects) do
- pipeworks.add_node_box(outboxes, pipeworks.tube_boxes[v])
+ table.extend(outboxes, pipeworks.tube_boxes[v])
table.insert(outsel, pipeworks.tube_selectboxes[v])
outimgs[vti[v]] = noctrs[v]
end
outimgs[vti[v]] = ends[v]
end
- local tgroups = {snappy = 3, tube = 1, not_in_creative_inventory = 1}
+ local tgroups = {snappy = 3, tube = 1, tubedevice = 1, not_in_creative_inventory = 1}
local tubedesc = desc.." "..dump(connects).."... You hacker, you."
local iimg = plain[1]
local wscale = {x = 1, y = 1, z = 1}
if #connects == 0 then
- tgroups = {snappy = 3, tube = 1}
+ tgroups = {snappy = 3, tube = 1, tubedevice = 1}
tubedesc = desc
iimg=inv
outimgs = {
wscale = {x = 1, y = 1, z = 0.01}
end
- table.insert(pipeworks.tubenodes, name.."_"..tname)
+ local rname = name.."_"..tname
+ table.insert(pipeworks.tubenodes, rname)
local nodedef = {
description = tubedesc,
wield_scale = wscale,
paramtype = "light",
selection_box = {
- type = "fixed",
+ type = "fixed",
fixed = outsel
},
node_box = {
style = style,
drop = name.."_"..dropname,
tubelike = 1,
- tube = {connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1}},
- on_construct = function(pos)
- local meta = minetest.get_meta(pos)
- meta:set_int("tubelike", 1)
- if minetest.registered_nodes[name.."_"..tname].on_construct_ then
- minetest.registered_nodes[name.."_"..tname].on_construct_(pos)
- end
- end,
- after_place_node = function(pos)
+ tube = {
+ connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1},
+ priority = 50
+ },
+ --[[after_place_node = function(pos)
pipeworks.scan_for_tube_objects(pos)
- if minetest.registered_nodes[name.."_"..tname].after_place_node_ then
- minetest.registered_nodes[name.."_"..tname].after_place_node_(pos)
+ if minetest.registered_nodes[rname].after_place_node_ then
+ minetest.registered_nodes[rname].after_place_node_(pos)
end
end,
after_dig_node = function(pos)
pipeworks.scan_for_tube_objects(pos)
- if minetest.registered_nodes[name.."_"..tname].after_dig_node_ then
- minetest.registered_nodes[name.."_"..tname].after_dig_node_(pos)
+ if minetest.registered_nodes[rname].after_dig_node_ then
+ minetest.registered_nodes[rname].after_dig_node_(pos)
end
- end
+ end]]
}
if style == "6d" then
nodedef.paramtype2 = "facedir"
if special == nil then special = {} end
for key, value in pairs(special) do
- if key == "on_construct" or key == "after_dig_node" or key == "after_place_node" then
- nodedef[key.."_"] = value
- elseif key == "groups" then
+ --if key == "after_dig_node" or key == "after_place_node" then
+ -- nodedef[key.."_"] = value
+ if key == "groups" then
for group, val in pairs(value) do
nodedef.groups[group] = val
end
for key, val in pairs(value) do
nodedef.tube[key] = val
end
- elseif type(value) == "table" then
- nodedef[key] = pipeworks.replace_name(value, "#id", tname)
- elseif type(value) == "string" then
- nodedef[key] = string.gsub(value, "#id", tname)
else
- nodedef[key] = value
+ nodedef[key] = table.recursive_replace(value, "#id", tname)
end
end
- local prefix = ":"
- if string.find(name, "pipeworks:") then prefix = "" end
-
- minetest.register_node(prefix..name.."_"..tname, nodedef)
+ minetest.register_node(rname, nodedef)
end
pipeworks.register_tube = function(name, desc, plain, noctrs, ends, short, inv, special, old_registration)
wield_image = inv,
paramtype = "light",
sunlight_propagates = true,
- description = desc.." (legacy)",
- on_construct = function(pos)
- local meta = minetest.get_meta(pos)
- meta:set_int("tubelike", 1)
- end,
- after_place_node = function(pos)
+ description = "Pneumatic tube segment (legacy)",
+ --[[after_place_node = function(pos)
pipeworks.scan_for_tube_objects(pos)
if minetest.registered_nodes[name.."_1"].after_place_node_ then
minetest.registered_nodes[name.."_1"].after_place_node_(pos)
end
- end,
- groups = {not_in_creative_inventory = 1, tube_to_update = 1},
+ end,]]
+ groups = {not_in_creative_inventory = 1, tube_to_update = 1, tube = 1},
tube = {connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1}},
drop = name.."_1",
})
- table.insert(pipeworks.tubenodes,cname)
+ table.insert(pipeworks.tubenodes, cname)
for xm = 0, 1 do
for xp = 0, 1 do
for ym = 0, 1 do
interval = 1,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
- local minp = {x = pos.x-1, y = pos.y-1, z = pos.z-1}
- local maxp = {x = pos.x+1, y = pos.y+1, z = pos.z+1}
+ local minp = vector.subtract(pos, 1)
+ local maxp = vector.add(pos, 1)
if table.getn(minetest.find_nodes_in_area(minp, maxp, "ignore")) == 0 then
pipeworks.scan_for_tube_objects(pos)
end
local short_texture = "pipeworks_tube_short.png"
local inv_texture = "pipeworks_tube_inv.png"
-pipeworks.register_tube("pipeworks:tube", "Pneumatic Tube Segment", plain_textures, noctr_textures, end_textures, short_texture, inv_texture)
+pipeworks.register_tube("pipeworks:tube", "Pneumatic tube segment", plain_textures, noctr_textures, end_textures, short_texture, inv_texture)
if pipeworks.enable_mese_tube then
local mese_noctr_textures = {"pipeworks_mese_tube_noctr_1.png", "pipeworks_mese_tube_noctr_2.png", "pipeworks_mese_tube_noctr_3.png",
"pipeworks_mese_tube_end.png", "pipeworks_mese_tube_end.png", "pipeworks_mese_tube_end.png"}
local mese_short_texture = "pipeworks_mese_tube_short.png"
local mese_inv_texture = "pipeworks_mese_tube_inv.png"
+ local function update_formspec(pos)
+ local meta = minetest.get_meta(pos)
+ local old_formspec = meta:get_string("formspec")
+ if string.find(old_formspec, "button0") then -- Old version
+ local inv = meta:get_inventory()
+ for i = 1, 6 do
+ for _, stack in ipairs(inv:get_list("line"..i)) do
+ minetest.item_drop(stack, "", pos)
+ end
+ end
+ end
+ meta:set_string("formspec",
+ "size[8,11]"..
+ "list[current_name;line1;1,0;6,1;]"..
+ "list[current_name;line2;1,1;6,1;]"..
+ "list[current_name;line3;1,2;6,1;]"..
+ "list[current_name;line4;1,3;6,1;]"..
+ "list[current_name;line5;1,4;6,1;]"..
+ "list[current_name;line6;1,5;6,1;]"..
+ "image[0,0;1,1;pipeworks_white.png]"..
+ "image[0,1;1,1;pipeworks_black.png]"..
+ "image[0,2;1,1;pipeworks_green.png]"..
+ "image[0,3;1,1;pipeworks_yellow.png]"..
+ "image[0,4;1,1;pipeworks_blue.png]"..
+ "image[0,5;1,1;pipeworks_red.png]"..
+ fs_helpers.cycling_button(meta, "button[7,0;1,1", "b1s", {"Off", "On"})..
+ fs_helpers.cycling_button(meta, "button[7,1;1,1", "b2s", {"Off", "On"})..
+ fs_helpers.cycling_button(meta, "button[7,2;1,1", "b3s", {"Off", "On"})..
+ fs_helpers.cycling_button(meta, "button[7,3;1,1", "b4s", {"Off", "On"})..
+ fs_helpers.cycling_button(meta, "button[7,4;1,1", "b5s", {"Off", "On"})..
+ fs_helpers.cycling_button(meta, "button[7,5;1,1", "b6s", {"Off", "On"})..
+ "list[current_player;main;0,7;8,4;]")
+ end
pipeworks.register_tube("pipeworks:mese_tube", "Sorting Pneumatic Tube Segment", mese_plain_textures, mese_noctr_textures,
mese_end_textures, mese_short_texture, mese_inv_texture,
{tube = {can_go = function(pos, node, velocity, stack)
if st:get_name() == name then
found = true
table.insert(tbl, vect)
+ break
end
end
end
meta:set_int("l"..tostring(i).."s", 1)
inv:set_size("line"..tostring(i), 6*1)
end
- meta:set_string("formspec",
- "size[8,11]"..
- "list[current_name;line1;1,0;6,1;]"..
- "list[current_name;line2;1,1;6,1;]"..
- "list[current_name;line3;1,2;6,1;]"..
- "list[current_name;line4;1,3;6,1;]"..
- "list[current_name;line5;1,4;6,1;]"..
- "list[current_name;line6;1,5;6,1;]"..
- "image[0,0;1,1;pipeworks_white.png]"..
- "image[0,1;1,1;pipeworks_black.png]"..
- "image[0,2;1,1;pipeworks_green.png]"..
- "image[0,3;1,1;pipeworks_yellow.png]"..
- "image[0,4;1,1;pipeworks_blue.png]"..
- "image[0,5;1,1;pipeworks_red.png]"..
- "button[7,0;1,1;button10;On]"..
- "button[7,1;1,1;button20;On]"..
- "button[7,2;1,1;button30;On]"..
- "button[7,3;1,1;button40;On]"..
- "button[7,4;1,1;button50;On]"..
- "button[7,5;1,1;button60;On]"..
- "list[current_player;main;0,7;8,4;]")
- meta:set_string("infotext", "Sorting Pneumatic Tube Segment")
+ update_formspec(pos)
+ meta:set_string("infotext", "Mese pneumatic tube")
end,
+ on_punch = update_formspec,
on_receive_fields = function(pos, formname, fields, sender)
- local meta = minetest.get_meta(pos)
- local i
- if fields.quit then return end
- for key, _ in pairs(fields) do
- if key:sub(1, 6) == "button" then
- local i = key:sub(7, 7)
- local s = key:sub(8, 8)
- if s == "" then s = 1 - meta:get_int("l"..i.."s") end
- meta:set_int("l"..i.."s", s)
- end
- end
- local frm = "size[8,11]"..
- "list[current_name;line1;1,0;6,1;]"..
- "list[current_name;line2;1,1;6,1;]"..
- "list[current_name;line3;1,2;6,1;]"..
- "list[current_name;line4;1,3;6,1;]"..
- "list[current_name;line5;1,4;6,1;]"..
- "list[current_name;line6;1,5;6,1;]"..
- "image[0,0;1,1;pipeworks_white.png]"..
- "image[0,1;1,1;pipeworks_black.png]"..
- "image[0,2;1,1;pipeworks_green.png]"..
- "image[0,3;1,1;pipeworks_yellow.png]"..
- "image[0,4;1,1;pipeworks_blue.png]"..
- "image[0,5;1,1;pipeworks_red.png]"
- for i = 1, 6 do
- local st = meta:get_int("l"..tostring(i).."s")
- if st == 0 then
- frm = frm.."button[7,"..tostring(i-1)..";1,1;button"..tostring(i).."1;Off]"
- else
- frm = frm.."button[7,"..tostring(i-1)..";1,1;button"..tostring(i).."0;On]"
- end
- end
- frm = frm.."list[current_player;main;0,7;8,4;]"
- meta:set_string("formspec", frm)
+ fs_helpers.on_receive_fields(pos, fields)
+ update_formspec(pos)
end,
can_dig = function(pos, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return (inv:is_empty("line1") and inv:is_empty("line2") and inv:is_empty("line3") and
inv:is_empty("line4") and inv:is_empty("line5") and inv:is_empty("line6"))
- end
+ end,
+ allow_metadata_inventory_put = function(pos, listname, index, stack, player)
+ local inv = minetest.get_meta(pos):get_inventory()
+ local stack_copy = ItemStack(stack)
+ stack_copy:set_count(1)
+ inv:set_stack(listname, index, stack_copy)
+ return 0
+ end,
+ allow_metadata_inventory_take = function(pos, listname, index, stack, player)
+ local inv = minetest.get_meta(pos):get_inventory()
+ inv:set_stack(listname, index, ItemStack(""))
+ return 0
+ end,
+ allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
+ local inv = minetest.get_meta(pos):get_inventory()
+ inv:set_stack(from_list, from_index, ItemStack(""))
+ return 0
+ end,
}, true) -- Must use old tubes, since the textures are rotated with 6d ones
end
local detector_plain_textures = {"pipeworks_detector_tube_plain.png", "pipeworks_detector_tube_plain.png", "pipeworks_detector_tube_plain.png",
"pipeworks_detector_tube_plain.png", "pipeworks_detector_tube_plain.png", "pipeworks_detector_tube_plain.png"}
local detector_inv_texture = "pipeworks_detector_tube_inv.png"
+ local detector_tube_step = 2 * tonumber(minetest.setting_get("dedicated_server_step"))
pipeworks.register_tube("pipeworks:detector_tube_on", "Detecting Pneumatic Tube Segment on (you hacker you)", detector_plain_textures, noctr_textures,
end_textures, short_texture, detector_inv_texture,
{tube = {can_go = function(pos, node, velocity, stack)
local name = minetest.get_node(pos).name
local nitems = meta:get_int("nitems")+1
meta:set_int("nitems", nitems)
- local saved_pos = { x = pos.x, y = pos.y, z = pos.z }
- minetest.after(0, function ()
- minetest.after(0, function ()
- minetest.after(0, minetest.registered_nodes[name].item_exit, saved_pos)
- end)
- end)
+ local saved_pos = vector.new(pos)
+ minetest.after(detector_tube_step, minetest.registered_nodes[name].item_exit, saved_pos)
return pipeworks.notvel(pipeworks.meseadjlist,velocity)
end},
groups = {mesecon = 2, not_in_creative_inventory = 1},
local meta = minetest.get_meta(pos)
meta:set_int("nitems", 1)
local name = minetest.get_node(pos).name
- local saved_pos = { x = pos.x, y = pos.y, z = pos.z }
- minetest.after(0, function ()
- minetest.after(0, function ()
- minetest.after(0, minetest.registered_nodes[name].item_exit, saved_pos)
- end)
- end)
- end})
+ local saved_pos = vector.new(pos)
+ minetest.after(detector_tube_step, minetest.registered_nodes[name].item_exit, saved_pos)
+
+ end
+ })
pipeworks.register_tube("pipeworks:detector_tube_off", "Detecting Pneumatic Tube Segment", detector_plain_textures, noctr_textures,
end_textures, short_texture, detector_inv_texture,
{tube = {can_go = function(pos, node, velocity, stack)
end
if pipeworks.enable_crossing_tube then
- -- FIXME: The textures are not the correct ones
local crossing_noctr_textures = {"pipeworks_crossing_tube_noctr.png", "pipeworks_crossing_tube_noctr.png", "pipeworks_crossing_tube_noctr.png",
"pipeworks_crossing_tube_noctr.png", "pipeworks_crossing_tube_noctr.png", "pipeworks_crossing_tube_noctr.png"}
local crossing_plain_textures = {"pipeworks_crossing_tube_plain.png" ,"pipeworks_crossing_tube_plain.png", "pipeworks_crossing_tube_plain.png",
for _, object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do
if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then
if object:get_luaentity().itemstring ~= "" then
- local titem = pipeworks.tube_item(pos,object:get_luaentity().itemstring)
- titem:get_luaentity().start_pos = {x = pos.x, y = pos.y-1, z = pos.z}
- titem:setvelocity({x = 0.01, y = 1, z = -0.01})
- titem:setacceleration({x = 0, y = 0, z = 0})
+ pipeworks.tube_item(pos, pos, vector.new(0, 0, 0), object:get_luaentity().itemstring)
end
object:get_luaentity().itemstring = ""
object:remove()
for _,object in ipairs(get_objects_with_square_radius(pos, minetest.env:get_meta(pos):get_int("dist"))) do
if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then
if object:get_luaentity().itemstring ~= "" then
- local titem = pipeworks.tube_item(pos, object:get_luaentity().itemstring)
- titem:get_luaentity().start_pos = {x = pos.x, y = pos.y-1, z = pos.z}
- titem:setvelocity({x = 0.01, y = 1, z = -0.01})
- titem:setacceleration({x = 0, y = 0, z = 0})
+ pipeworks.tube_item(pos, pos, vector.new(0, 0, 0), object:get_luaentity().itemstring)
end
object:get_luaentity().itemstring = ""
object:remove()
})
end
-local function facedir_to_right_dir(facedir)
-
- --find the other directions
- local backdir = minetest.facedir_to_dir(facedir)
- local topdir = ({[0] = {x = 0, y = 1, z = 0},
- {x = 0, y = 0, z = 1},
- {x = 0, y = 0, z = -1},
- {x = 1, y = 0, z = 0},
- {x = -1, y = 0, z = 0},
- {x = 0, y = -1, z = 0}})[math.floor(facedir/4)]
-
- --return a cross product
- return {x = topdir.y*backdir.z - backdir.y*topdir.z,
- y = topdir.z*backdir.x - backdir.z*topdir.x,
- z = topdir.x*backdir.y - backdir.x*topdir.y}
-end
-
if pipeworks.enable_one_way_tube then
minetest.register_node("pipeworks:one_way_tube", {
- description = "One-way Pneumatic Tube Segment",
+ description = "One way tube",
tiles = {"pipeworks_one_way_tube_top.png", "pipeworks_one_way_tube_top.png", "pipeworks_one_way_tube_output.png",
"pipeworks_one_way_tube_input.png", "pipeworks_one_way_tube_side.png", "pipeworks_one_way_tube_top.png"},
paramtype2 = "facedir",
paramtype = "light",
node_box = {type = "fixed",
fixed = {{-1/2, -9/64, -9/64, 1/2, 9/64, 9/64}}},
- groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, tubedevice = 1, tubedevice_receiver = 1},
+ groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, tubedevice = 1},
legacy_facedir_simple = true,
sounds = default.node_sound_wood_defaults(),
- on_construct = function(pos)
- minetest.get_meta(pos):set_int("tubelike", 1)
- end,
- after_place_node = function(pos)
- pipeworks.scan_for_tube_objects(pos)
- end,
- after_dig_node = function(pos)
- pipeworks.scan_for_tube_objects(pos)
- end,
- tube = {connect_sides = {left = 1, right = 1},
+ tube = {
+ connect_sides = {left = 1, right = 1},
can_go = function(pos, node, velocity, stack)
- return velocity
- end,
- insert_object = function(pos, node, stack, direction)
- item1 = pipeworks.tube_item(pos, stack)
- item1:get_luaentity().start_pos = pos
- item1:setvelocity({x = direction.x*direction.speed, y = direction.y*direction.speed, z = direction.z*direction.speed})
- item1:setacceleration({x = 0, y = 0, z = 0})
- return ItemStack("")
+ return {velocity}
end,
can_insert = function(pos, node, stack, direction)
- local dir = facedir_to_right_dir(node.param2)
- if dir.x == direction.x and dir.y == direction.y and dir.z == direction.z then
- return true
- end
- return false
- end},
+ local dir = minetest.facedir_to_right_dir(node.param2)
+ return vector.equals(dir, direction)
+ end,
+ priority = 75 -- Higher than normal tubes, but lower than receivers
+ },
})
end