Some improvements on the robot (still WIP)

First draft of tubelib_addons3 (still WIP)
This commit is contained in:
Joachim Stolberg 2018-08-08 01:06:16 +02:00
parent 4b3a5d3e01
commit e8bad31a17
41 changed files with 1035 additions and 74 deletions

@ -14,6 +14,15 @@
]]--
-- constrict value to the given range
local function range(val, min, max)
val = tonumber(val)
if val < min then return min end
if val > max then return max end
return val
end
sl_robot.register_action("get_ms_time", {
cmnd = function(self)
@ -25,7 +34,7 @@ sl_robot.register_action("get_ms_time", {
sl_robot.register_action("forward", {
cmnd = function(self, steps)
steps = math.min(tonumber(steps or 1), 100)
steps = range(steps, 1, 100)
local idx = 1
while idx <= steps do
local meta = minetest.get_meta(self.meta.pos)
@ -49,7 +58,7 @@ sl_robot.register_action("forward", {
sl_robot.register_action("backward", {
cmnd = function(self, steps)
steps = math.min(tonumber(steps or 1), 100)
steps = range(steps, 1, 100)
local idx = 1
while idx <= steps do
local meta = minetest.get_meta(self.meta.pos)
@ -140,8 +149,8 @@ sl_robot.register_action("down", {
sl_robot.register_action("take", {
cmnd = function(self, num, slot)
num = math.min(tonumber(num or 1), 99)
slot = math.min(tonumber(slot or 1), 8)
num = range(num, 1, 99)
slot = range(slot, 1, 8)
local meta = minetest.get_meta(self.meta.pos)
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
local robot_param2 = meta:get_int("robot_param2")
@ -159,8 +168,8 @@ sl_robot.register_action("take", {
sl_robot.register_action("add", {
cmnd = function(self, num, slot)
num = math.min(tonumber(num or 1), 99)
slot = math.min(tonumber(slot or 1), 8)
num = range(num, 1, 99)
slot = range(slot, 1, 8)
local meta = minetest.get_meta(self.meta.pos)
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
local robot_param2 = meta:get_int("robot_param2")
@ -177,7 +186,7 @@ sl_robot.register_action("add", {
sl_robot.register_action("place", {
cmnd = function(self, slot, dir)
slot = math.min(tonumber(slot or 1), 8)
slot = range(slot, 1, 8)
local meta = minetest.get_meta(self.meta.pos)
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
local robot_param2 = meta:get_int("robot_param2")
@ -193,7 +202,7 @@ sl_robot.register_action("place", {
sl_robot.register_action("dig", {
cmnd = function(self, slot, dir)
slot = math.min(tonumber(slot or 1), 8)
slot = range(slot, 1, 8)
local meta = minetest.get_meta(self.meta.pos)
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
local robot_param2 = meta:get_int("robot_param2")
@ -215,17 +224,3 @@ sl_robot.register_action("stop", {
end,
help = "tbd"
})
--sl_robot.register_action("run", {
-- cmnd = function(self, sCmd, reverse)
-- slot = math.min(tonumber(slot or 1), 8)
-- local meta = minetest.get_meta(self.meta.pos)
-- local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
-- local robot_param2 = meta:get_int("robot_param2")
-- for cmnd in sCmd:gmatch("%w+") do
-- if cmnd:byte()
-- end
-- end,
-- help = " "
--})

@ -16,3 +16,4 @@ sl_robot = {}
dofile(minetest.get_modpath("sl_robot") .. "/robot.lua")
dofile(minetest.get_modpath("sl_robot") .. "/base.lua")
dofile(minetest.get_modpath("sl_robot") .. "/commands.lua")
dofile(minetest.get_modpath("sl_robot") .. "/run_cmnd.lua")

@ -23,40 +23,38 @@ local Face2Dir = {[0]=
local Inventories = {
["default:chest"] = {take = "main", add = "main", fuel = "main"},
["default:chest_locked"] = {take = "main", add = "main", fuel = "main"},
["default:chest_locked"] = {take = "main", add = "main", fuel = "main"},
["default:furnace"] = {take = "dst", add = "src", fuel = "fuel"},
["default:furnace_active"] = {take = "dst", add = "src", fuel = "fuel"},
["tubelib:distributor"] = {take = "src", add = "src", fuel = "src"},
["gravelsieve:sieve"] = {take = "dst", add = "src", fuel = "src"},
["gravelsieve:auto_sieve0"] = {take = "dst", add = "src", fuel = "src"},
["gravelsieve:auto_sieve1"] = {take = "dst", add = "src", fuel = "src"},
["gravelsieve:auto_sieve2"] = {take = "dst", add = "src", fuel = "src"},
["gravelsieve:auto_sieve3"] = {take = "dst", add = "src", fuel = "src"},
["tubelib_addons1:autocrafter"] = {take = "dst", add = "src", fuel = "src"},
["tubelib_addons1:autocrafter_active"] = {take = "dst", add = "src", fuel = "src"},
["tubelib_addons1:chest"] = {take = "main", add = "main", fuel = "main"},
["tubelib_addons1:fermenter"] = {take = "dst", add = "src", fuel = "src"},
["tubelib_addons1:reformer"] = {take = "dst", add = "src", fuel = "src"},
["tubelib_addons1:funnel"] = {take = "main", add = "main", fuel = "main"},
["tubelib_addons1:grinder"] = {take = "dst", add = "src", fuel = "src"},
["tubelib_addons1:grinder_active"] = {take = "dst", add = "src", fuel = "src"},
["tubelib_addons1:harvester_base"] = {take = "main", add = "main", fuel = "fuel"},
["tubelib_addons1:quarry"] = {take = "main", add = "main", fuel = "fuel"},
["tubelib_addons1:quarry_active"] = {take = "main", add = "main", fuel = "fuel"},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
-- [""] = {take = "", add = "", fuel = ""},
["tubelib:distributor"] = {take = "src", add = "src"},
["tubelib_addons1:harvester_base"] = {take = "main", add = "fuel"},
["tubelib_addons1:quarry"] = {take = "main", add = "fuel"},
["tubelib_addons1:quarry_active"] = {take = "main", add = "fuel"},
-- [""] = {take = "", add = ""},
-- [""] = {take = "", add = ""},
-- [""] = {take = "", add = ""},
}
local function inv_list_add(inv, name)
if Inventories[name] then
return inv:get_list(Inventories[name].add)
elseif inv:get_list("src") then
return inv:get_list("src")
elseif inv:get_list("main") then
return inv:get_list("main")
end
return nil
end
local function inv_list_take(inv, name)
if Inventories[name] then
return inv:get_list(Inventories[name].take)
elseif inv:get_list("dst") then
return inv:get_list("dst")
elseif inv:get_list("main") then
return inv:get_list("main")
end
return nil
end
-- return the largest stack
local function peek(src_list)
local max_val = 0
@ -264,19 +262,13 @@ function sl_robot.robot_take(base_pos, robot_pos, param2, owner, num, slot)
return
end
local node = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
if Inventories[node.name] then
local listname = Inventories[node.name].take
local src_inv = minetest.get_inventory({type="node", pos=pos1})
if src_inv:is_empty(listname) then
return
end
local src_list = src_inv:get_list(listname)
local dst_inv = minetest.get_inventory({type="node", pos=base_pos})
local dst_list = dst_inv:get_list("main")
if take_num_items(src_list, num, dst_list[slot]) then
src_inv:set_list(listname, src_list)
dst_inv:set_list("main", dst_list)
end
local src_inv = minetest.get_inventory({type="node", pos=pos1})
local src_list = inv_list_take(src_inv, node.name)
local dst_inv = minetest.get_inventory({type="node", pos=base_pos})
local dst_list = dst_inv:get_list("main")
if src_list and take_num_items(src_list, num, dst_list[slot]) then
src_inv:set_list(listname, src_list)
dst_inv:set_list("main", dst_list)
end
end
@ -286,12 +278,11 @@ function sl_robot.robot_add(base_pos, robot_pos, param2, owner, num, slot)
return
end
local node = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
if Inventories[node.name] then
local listname = Inventories[node.name].take
local dst_inv = minetest.get_inventory({type="node", pos=pos1})
local dst_list = dst_inv:get_list(listname)
local src_inv = minetest.get_inventory({type="node", pos=base_pos})
local src_list = src_inv:get_list("main")
local dst_inv = minetest.get_inventory({type="node", pos=pos1})
local dst_list = inv_list_add(dst_inv, node.name)
local src_inv = minetest.get_inventory({type="node", pos=base_pos})
local src_list = src_inv:get_list("main")
if dst_list then
local taken = src_list[slot]:take_item(num)
if dst_inv:room_for_item(listname, taken) then
dst_inv:add_item(listname, taken)

122
sl_robot/run_cmnd.lua Normal file

@ -0,0 +1,122 @@
--[[
sl_robot
========
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
run_cmnd.lua:
Register the run command
]]--
local function Reverse(arr)
local i, j = 1, #arr
while i < j do
arr[i], arr[j] = arr[j], arr[i]
i = i + 1
j = j - 1
end
end
local switch = {
f = function(cmnd)
local num = (cmnd:byte(2) or 0x31) - 0x30
print("forward("..num..")")
end,
b = function(cmnd)
local num = (cmnd:byte(2) or 0x31) - 0x30
print("backward("..num..")")
end,
l = function(cmnd, reverse)
if reverse then
print("right()")
else
print("left()")
end
end,
r = function(cmnd, reverse)
if reverse then
print("left()")
else
print("right()")
end
end,
u = function(cmnd)
print("up()")
end,
d = function(cmnd)
print("down()")
end,
t = function(cmnd)
local num, slot
if cmnd:sub(2,2) == "s" then
num = 99
slot = (cmnd:byte(3) or 0x31) - 0x30
else
num = 1
slot = (cmnd:byte(2) or 0x31) - 0x30
end
print("take("..num..","..slot..")")
end,
a = function(cmnd)
local num, slot
if cmnd:sub(2,2) == "s" then
num = 99
slot = (cmnd:byte(3) or 0x31) - 0x30
else
num = 1
slot = (cmnd:byte(2) or 0x31) - 0x30
end
print("add("..num..","..slot..")")
end,
p = function(cmnd)
local num, slot
if cmnd:sub(2,2) == "u" then
slot = (cmnd:byte(3) or 0x31) - 0x30
print("place("..slot..",U)")
elseif cmnd:sub(2,2) == "d" then
slot = (cmnd:byte(3) or 0x31) - 0x30
print("place("..slot..",D)")
else
slot = (cmnd:byte(2) or 0x31) - 0x30
print("place("..slot..")")
end
end,
e = function(cmnd)
print(cmnd.." is a invalid command")
end,
}
local function run(task, reverse)
task = task:gsub("\n", " ")
task = task:gsub("\t", " ")
local cmnds = task:split(" ")
if reverse then
Reverse(cmnds)
end
for i,cmnd in ipairs(cmnds) do
(switch[cmnd:sub(1,1)] or switch["e"])(cmnd, reverse)
end
end
sl_robot.register_action("run", {
cmnd = function(self, sCmndList, reverse)
sCmndList = sCmndList:gsub("\n", " ")
sCmndList = sCmndList:gsub("\t", " ")
local cmnds = sCmndList:split(" ")
if reverse then
Reverse(cmnds)
end
for i,cmnd in ipairs(cmnds) do
(switch[cmnd:sub(1,1)] or switch["e"])(cmnd, reverse)
end
end,
help = " "
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 B

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

137
tubelib_addons3/chest.lua Normal file

@ -0,0 +1,137 @@
--[[
Tubelib Addons 3
================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
chest.lua
A high performance chest
]]--
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
minetest.log("action", player:get_player_name().." moves "..stack:get_name()..
" to chest at "..minetest.pos_to_string(pos))
return stack:get_count()
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
minetest.log("action", player:get_player_name().." takes "..stack:get_name()..
" from chest at "..minetest.pos_to_string(pos))
return stack:get_count()
end
local function get_stack(meta, list)
local inv = meta:get_inventory()
local item = tubelib.get_item(meta, list)
if item and inv:contains_item(list, item) then
-- try to remove a complete stack
item:set_count(98)
local taken = inv:remove_item(list, item)
-- add the already removed
taken:set_count(taken:get_count() + 1)
return taken
end
return item
end
local function formspec()
return "size[12,10]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[context;main;0,0;12,6;]"..
"list[current_player;main;2,6.3;8,4;]"..
"listring[context;main]"..
"listring[current_player;main]"
end
minetest.register_node("tubelib_addons3:chest", {
description = "HighPerf Chest",
tiles = {
-- up, down, right, left, back, front
'tubelib_addons3_chest_bottom.png',
'tubelib_addons3_chest_bottom.png',
"tubelib_addons3_chest_side.png",
"tubelib_addons3_chest_side.png",
"tubelib_addons3_chest_side.png",
"tubelib_addons3_chest_front.png",
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size('main', 72)
end,
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec())
meta:set_string("infotext", "HighPerf Chest")
end,
can_dig = function(pos,player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("main")
end,
on_dig = function(pos, node, puncher, pointed_thing)
minetest.node_dig(pos, node, puncher, pointed_thing)
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib_addons3:chest",
recipe = {
{"", "default:steel_ingot", ""},
{"tubelib_addons1:chest", "default:gold_ingot", "tubelib_addons1:chest"},
{"", "default:tin_ingot", ""},
}
})
tubelib.register_node("tubelib_addons3:chest", {}, {
on_pull_item = function(pos, side)
local meta = minetest.get_meta(pos)
return get_stack(meta, "main")
end,
on_push_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
tubelib.put_item(meta, "main", item)
end,
on_unpull_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "main", item)
end,
on_recv_message = function(pos, topic, payload)
return "unsupported"
end,
})

@ -0,0 +1,3 @@
tubelib
tubelib_addons1
default

@ -0,0 +1,2 @@
Tubelib Extension with High Performance nodes

@ -0,0 +1,491 @@
--[[
Tubelib Addons 3
================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
distributor.lua:
A high performance distributor
]]--
local NUM_FILTER_ELEM = 6
local NUM_FILTER_SLOTS = 4
local TICKS_TO_SLEEP = 5
local CYCLE_TIME = 2
local STOP_STATE = 0
local STANDBY_STATE = -1
-- Get one item-stack from the given ItemList, specified by stack number (1..n).
-- Returns nil if ItemList is empty.
local function get_this_stack(meta, listname, number)
if meta == nil or meta.get_inventory == nil then return nil end
local inv = meta:get_inventory()
if inv:is_empty(listname) then
return nil
end
local items = inv:get_stack(listname, number)
if items:get_count() > 0 then
return inv:remove_item(listname, items)
end
return nil
end
-- Return a key/value table with all items and the corresponding stack numbers
local function invlist_content_as_kvlist(list)
local res = {}
for idx,items in ipairs(list) do
local name = items:get_name()
if name ~= "" then
res[name] = idx
end
end
return res
end
-- Return the total number of list entries
local function invlist_num_entries(list)
local res = 0
for _,items in ipairs(list) do
local name = items:get_name()
if name ~= "" then
res = res + items:get_count()
end
end
return res
end
-- Return a flat table with all items
local function invlist_entries_as_list(list)
local res = {}
for _,items in ipairs(list) do
local name = items:get_name()
local count = items:get_count()
if name ~= "" then
for i = 1,count do
res[#res+1] = name
end
end
end
return res
end
local function AddToTbl(kvTbl, new_items)
for _, l in ipairs(new_items) do
kvTbl[l] = true
end
return kvTbl
end
local function distributor_formspec(state, filter)
return "size[10,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[context;src;0,0;2,4;]"..
"image[2,1.5;1,1;tubelib_gui_arrow.png]"..
"image_button[2,3;1,1;".. tubelib.state_button(state) ..";button;]"..
"checkbox[3,0;filter1;On;"..dump(filter[1]).."]"..
"checkbox[3,1;filter2;On;"..dump(filter[2]).."]"..
"checkbox[3,2;filter3;On;"..dump(filter[3]).."]"..
"checkbox[3,3;filter4;On;"..dump(filter[4]).."]"..
"image[3.6,0;0.3,1;tubelib_red.png]"..
"image[3.6,1;0.3,1;tubelib_green.png]"..
"image[3.6,2;0.3,1;tubelib_blue.png]"..
"image[3.6,3;0.3,1;tubelib_yellow.png]"..
"list[context;red;4,0;6,1;]"..
"list[context;green;4,1;6,1;]"..
"list[context;blue;4,2;6,1;]"..
"list[context;yellow;4,3;6,1;]"..
"list[current_player;main;1,4.5;8,4;]"..
"listring[context;src]"..
"listring[current_player;main]"
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local list = inv:get_list(listname)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
if listname == "src" then
return stack:get_count()
elseif invlist_num_entries(list) < NUM_FILTER_ELEM then
return 1
end
return 0
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
return stack:get_count()
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack(from_list, from_index)
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
end
local SlotColors = {"red", "green", "blue", "yellow"}
local Num2Ascii = {"B", "L", "F", "R"} -- color to side translation
local FilterCache = {} -- local cache for filter settings
local function filter_settings(pos)
local hash = minetest.hash_node_position(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
local kvFilterItemNames = {} -- {<item:name> = true,...}
local kvSide2ItemNames = {} -- {"F" = {<item:name>,...},...}
-- collect all filter settings
for idx,slot in ipairs(SlotColors) do
local side = Num2Ascii[idx]
if filter[idx] == true then
local list = inv:get_list(slot)
local filter = invlist_entries_as_list(list)
AddToTbl(kvFilterItemNames, filter)
kvSide2ItemNames[side] = filter
end
end
FilterCache[hash] = {
kvFilterItemNames = kvFilterItemNames,
kvSide2ItemNames = kvSide2ItemNames
}
end
local function start_the_machine(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", TICKS_TO_SLEEP)
node.name = "tubelib_addons3:distributor_active"
minetest.swap_node(pos, node)
meta:set_string("infotext", "HighPerf Distributor "..number..": running")
local filter = minetest.deserialize(meta:get_string("filter"))
meta:set_string("formspec", distributor_formspec(tubelib.RUNNING, filter))
minetest.get_node_timer(pos):start(CYCLE_TIME)
return false
end
local function stop_the_machine(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", STOP_STATE)
node.name = "tubelib_addons3:distributor"
minetest.swap_node(pos, node)
meta:set_string("infotext", "HighPerf Distributor "..number..": stopped")
local filter = minetest.deserialize(meta:get_string("filter"))
meta:set_string("formspec", distributor_formspec(tubelib.STOPPED, filter))
minetest.get_node_timer(pos):stop()
return false
end
local function goto_sleep(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", STANDBY_STATE)
node.name = "tubelib_addons3:distributor"
minetest.swap_node(pos, node)
meta:set_string("infotext", "HighPerf Distributor "..number..": standby")
local filter = minetest.deserialize(meta:get_string("filter"))
meta:set_string("formspec", distributor_formspec(tubelib.STANDBY, filter))
minetest.get_node_timer(pos):start(CYCLE_TIME * TICKS_TO_SLEEP)
return false
end
-- move items to the output slots
local function keep_running(pos, elapsed)
local meta = minetest.get_meta(pos)
local running = meta:get_int("running") - 1
local player_name = meta:get_string("player_name")
--print("running", running)
local slot_idx = meta:get_int("slot_idx") or 1
meta:set_int("slot_idx", (slot_idx + 1) % NUM_FILTER_SLOTS)
local side = Num2Ascii[slot_idx+1]
local listname = SlotColors[slot_idx+1]
local inv = meta:get_inventory()
local list = inv:get_list("src")
local kvSrc = invlist_content_as_kvlist(list)
local counter = minetest.deserialize(meta:get_string("item_counter")) or
{red=0, green=0, blue=0, yellow=0}
-- calculate the filter settings only once
local hash = minetest.hash_node_position(pos)
if FilterCache[hash] == nil then
filter_settings(pos)
end
-- read data from Cache
-- all filter items as key/value {<item:name> = true,...}
local kvFilterItemNames = FilterCache[hash].kvFilterItemNames
-- filter items of one slot as list {<item:name>,...}
local names = FilterCache[hash].kvSide2ItemNames[side]
if names == nil then
-- this slot is empty
return true
end
local busy = false
-- move items from configured filters to the output
if next(names) then
for _,name in ipairs(names) do
if kvSrc[name] then
local item = get_this_stack(meta, "src", kvSrc[name])
if item then
if not tubelib.push_items(pos, side, item, player_name) then
tubelib.put_item(meta, "src", item)
else
counter[listname] = counter[listname] + 1
busy = true
end
end
end
end
end
-- move additional items from unconfigured filters to the output
if next(names) == nil then
for name,_ in pairs(kvSrc) do
if kvFilterItemNames[name] == nil then -- not in the filter so far?
local item = get_this_stack(meta, "src", kvSrc[name])
if item then
if not tubelib.push_items(pos, side, item, player_name) then
tubelib.put_item(meta, "src", item)
else
counter[listname] = counter[listname] + 1
busy = true
end
end
end
end
end
if busy == true then
if running <= 0 then
return start_the_machine(pos)
else
running = TICKS_TO_SLEEP
end
else
if running <= 0 then
return goto_sleep(pos)
end
end
meta:set_string("item_counter", minetest.serialize(counter))
meta:set_int("running", running)
return true
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
local running = meta:get_int("running")
local filter = minetest.deserialize(meta:get_string("filter"))
if fields.filter1 ~= nil then
filter[1] = fields.filter1 == "true"
elseif fields.filter2 ~= nil then
filter[2] = fields.filter2 == "true"
elseif fields.filter3 ~= nil then
filter[3] = fields.filter3 == "true"
elseif fields.filter4 ~= nil then
filter[4] = fields.filter4 == "true"
end
meta:set_string("filter", minetest.serialize(filter))
filter_settings(pos)
if fields.button ~= nil then
if running > STOP_STATE then
stop_the_machine(pos)
else
start_the_machine(pos)
end
else
meta:set_string("formspec", distributor_formspec(tubelib.state(running), filter))
end
end
-- tubelib command to turn on/off filter channels
local function change_filter_settings(pos, slot, val)
local slots = {["red"] = 1, ["green"] = 2, ["blue"] = 3, ["yellow"] = 4}
local meta = minetest.get_meta(pos)
local filter = minetest.deserialize(meta:get_string("filter"))
local num = slots[slot] or 1
if num >= 1 and num <= 4 then
filter[num] = val == "on"
end
meta:set_string("filter", minetest.serialize(filter))
filter_settings(pos)
local running = meta:get_int("running")
meta:set_string("formspec", distributor_formspec(tubelib.state(running), filter))
return true
end
minetest.register_node("tubelib_addons3:distributor", {
description = "HighPerf Distributor",
tiles = {
-- up, down, right, left, back, front
'tubelib_distributor.png^tubelib_addons3_node_frame.png',
'tubelib_distributor.png^tubelib_addons3_node_frame.png',
'tubelib_distributor_yellow.png^tubelib_addons3_node_frame.png',
'tubelib_distributor_green.png^tubelib_addons3_node_frame.png',
"tubelib_distributor_red.png^tubelib_addons3_node_frame.png",
"tubelib_distributor_blue.png^tubelib_addons3_node_frame.png",
},
after_place_node = function(pos, placer)
local number = tubelib.add_node(pos, "tubelib_addons3:distributor")
local meta = minetest.get_meta(pos)
meta:set_string("player_name", placer:get_player_name())
local filter = {false,false,false,false}
meta:set_string("formspec", distributor_formspec(tubelib.STOPPED, filter))
meta:set_string("filter", minetest.serialize(filter))
meta:set_string("number", number)
meta:set_string("infotext", "HighPerf Distributor "..number..": stopped")
local inv = meta:get_inventory()
inv:set_size('src', 8)
inv:set_size('yellow', 6)
inv:set_size('green', 6)
inv:set_size('red', 6)
inv:set_size('blue', 6)
meta:set_string("item_counter", minetest.serialize({red=0, green=0, blue=0, yellow=0}))
end,
on_receive_fields = on_receive_fields,
on_dig = function(pos, node, puncher, pointed_thing)
if minetest.is_protected(pos, puncher:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if inv:is_empty("src") then
minetest.node_dig(pos, node, puncher, pointed_thing)
tubelib.remove_node(pos)
end
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
allow_metadata_inventory_move = allow_metadata_inventory_move,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("tubelib_addons3:distributor_active", {
description = "HighPerf Distributor",
tiles = {
-- up, down, right, left, back, front
{
image = "tubelib_addons3_distributor_active.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 2.0,
},
},
'tubelib_distributor.png^tubelib_addons3_node_frame.png',
'tubelib_distributor_yellow.png^tubelib_addons3_node_frame.png',
'tubelib_distributor_green.png^tubelib_addons3_node_frame.png',
"tubelib_distributor_red.png^tubelib_addons3_node_frame.png",
"tubelib_distributor_blue.png^tubelib_addons3_node_frame.png",
},
on_receive_fields = on_receive_fields,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
allow_metadata_inventory_move = allow_metadata_inventory_move,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {crumbly=0, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib_addons3:distributor",
recipe = {
{"", "default:steel_ingot", ""},
{"default:gold_ingot", "tubelib:distributor", "default:tin_ingot"},
{"", "default:steel_ingot", ""},
},
})
tubelib.register_node("tubelib_addons3:distributor", {"tubelib_addons3:distributor_active"}, {
on_pull_item = function(pos, side)
local meta = minetest.get_meta(pos)
return tubelib.get_item(meta, "src")
end,
on_push_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "src", item)
end,
on_unpull_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "src", item)
end,
on_recv_message = function(pos, topic, payload)
if topic == "on" then
return start_the_machine(pos)
elseif topic == "off" then
return stop_the_machine(pos)
elseif topic == "state" then
local meta = minetest.get_meta(pos)
local running = meta:get_int("running")
return tubelib.statestring(running)
elseif topic == "filter" then
return change_filter_settings(pos, payload.slot, payload.val)
elseif topic == "counter" then
local meta = minetest.get_meta(pos)
return minetest.deserialize(meta:get_string("item_counter")) or
{red=0, green=0, blue=0, yellow=0}
elseif topic == "clear_counter" then
local meta = minetest.get_meta(pos)
meta:set_string("item_counter", minetest.serialize({red=0, green=0, blue=0, yellow=0}))
else
return "unsupported"
end
end,
})

15
tubelib_addons3/init.lua Normal file

@ -0,0 +1,15 @@
--[[
Tubelib Addons 3
================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
]]--
dofile(minetest.get_modpath("tubelib_addons3") .. '/pushing_chest.lua')
dofile(minetest.get_modpath("tubelib_addons3") .. '/chest.lua')
dofile(minetest.get_modpath("tubelib_addons3") .. '/distributor.lua')

1
tubelib_addons3/mod.conf Normal file

@ -0,0 +1 @@
name=tubelib_addons3

@ -0,0 +1,203 @@
--[[
Tubelib Addons 3
================
Copyright (C) 2017-2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
pushing_chest.lua
A high performance pushing chest
]]--
local Cache = {}
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
Cache[minetest.get_meta(pos):get_string("number")] = nil
minetest.log("action", player:get_player_name().." moves "..stack:get_name()..
" to chest at "..minetest.pos_to_string(pos))
return stack:get_count()
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
Cache[minetest.get_meta(pos):get_string("number")] = nil
minetest.log("action", player:get_player_name().." takes "..stack:get_name()..
" from chest at "..minetest.pos_to_string(pos))
return stack:get_count()
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
Cache[minetest.get_meta(pos):get_string("number")] = nil
return count
end
local function configured(pos, item)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local number = meta:get_string("number")
if not Cache[number] then
Cache[number] = {}
for _,items in ipairs(inv:get_list("main")) do
Cache[number][items:get_name()] = true
end
end
return Cache[number][item:get_name()] == true
end
local function shift_items(pos, elapsed)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if not inv:is_empty("shift") then
local number = meta:get_string("number")
local player_name = meta:get_string("player_name")
local offs = meta:get_int("offs")
meta:set_int("offs", offs + 1)
for i = 0,7 do
local idx = ((i + offs) % 8) + 1
local stack = inv:get_stack("shift", idx)
if stack:get_count() > 0 then
if tubelib.push_items(pos, "R", stack, player_name) then
inv:set_stack("shift", idx, nil)
return true
end
end
end
end
return true
end
local function formspec()
return "size[9,9.2]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[context;shift;0.5,0;8,1;]"..
"list[context;main;0.5,1.2;8,4;]"..
"image[0.5,0;1,1;tubelib_gui_arrow.png]"..
"image[7.5,0;1,1;tubelib_gui_arrow.png]"..
"list[current_player;main;0.5,5.5;8,4;]"..
"image[0.5,1.2;1,1;tubelib_gui_arrow.png^[transformR270]"..
"listring[context;main]"..
"listring[current_player;main]"
end
minetest.register_node("tubelib_addons3:pushing_chest", {
description = "HighPerf Pushing Chest",
tiles = {
-- up, down, right, left, back, front
{
image = "tubelib_addons3_pushing_chest.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 2.0,
},
},
'tubelib_addons3_chest_bottom.png',
"tubelib_addons3_chest_out.png",
"tubelib_addons3_chest_side.png",
"tubelib_addons3_chest_side.png",
"tubelib_addons3_chest_front.png",
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size('main', 32)
inv:set_size('shift', 8)
end,
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
local number = tubelib.add_node(pos, "tubelib_addons3:pushing_chest")
meta:set_string("player_name", placer:get_player_name())
meta:set_string("number", number)
meta:set_string("formspec", formspec())
meta:set_string("infotext", "HighPerf Pushing Chest "..number)
minetest.get_node_timer(pos):start(2)
end,
can_dig = function(pos,player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("main") and inv:is_empty("shift")
end,
on_dig = function(pos, node, puncher, pointed_thing)
minetest.node_dig(pos, node, puncher, pointed_thing)
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
allow_metadata_inventory_move = allow_metadata_inventory_move,
on_timer = shift_items,
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib_addons3:pushing_chest",
recipe = {
{ "", "default:tin_ingot", ""},
{"default:chest", "default:gold_ingot", "tubelib:distributor"},
{"", "default:steel_ingot", ""},
}
})
tubelib.register_node("tubelib_addons3:pushing_chest", {}, {
on_pull_item = function(pos, side)
local meta = minetest.get_meta(pos)
local item = tubelib.get_item(meta, "main")
-- check if one remaining item is left
if meta:get_inventory():contains_item("main", item) then
return item
else
-- don't remove the last item (recipe)
tubelib.put_item(meta, "main", item)
return nil
end
end,
on_push_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
if configured(pos, item) then
return tubelib.put_item(meta, "main", item)
else
return tubelib.put_item(meta, "shift", item)
end
end,
on_unpull_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "main", item)
end,
on_recv_message = function(pos, topic, payload)
return "unsupported"
end,
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B