Page 1 of 1

Tip on Lua controlled Tube (use for sorting)

Posted: Sat Sep 01, 2018 14:51
by Ruggila
When playing minetest, I like to have an automatic sorter:
  • * I put all my mined thing into a chest
    * a stackwise Filter-Injector pulls them out, powered by a blinky plant
    * then things go into a sorter network
    * exits are of course grinder, furnace, centrifuge, battery box (to recharge), workshop
    * and of course lots of chests
I've seen similar setups by other players. However, most of the other players just used the "Sorting Pneumatic Tube Segment". I use them, too. But I also use "Lua controlled Tube". And here is how:

The tubes are event driven, so I need to react to events. Here is an example of my first Lua controlled tube after my incoming chest:

Code: Select all

if event.type == "item" then
   local s = event.item.name

   -- grinder
   if s == "default:copper_lump" or
      s == "default:gold_lump" or
      s == "default:iron_lump" or
      s == "forge:slag" or
      s == "moreores:mithril_lump" or
      s == "moreores:silver_lump" or
      s == "moreores:tin_lump" or
      s == "technic:chromium_lump" or
      s == "technic:uranium_lump" or
      s == "technic:zinc_lump" or
      s == "technic_aluminum:alumina_lump" then
       return "green"
   end

   -- furnace
   if s == "forge:slag" or
      s == "mobs:rotten_flesh" or
      s == "technic:chromium_dust" or
      s == "technic:copper_dust" or
      s == "technic:gold_dust" or
      s == "technic:mithril_dust" or
      s == "technic:silver_dust" or
      s == "technic:tin_dust" or
      s == "technic:wrought_iron_dust" or
      s == "technic:zinc_dust" or
      s == "technic_aluminum:aluminum_dust" or
      s == "technic_aluminum:bauxite_lump" then
       return "black"
   end

   -- small centrifuge
   if s == "technic_aluminum:alumina_dust" then
       return "yellow"
   end

   return "red"
end
The Lua controlled tubes have colored connections, and you simply return the color of where you want the specific item to end up.

The second Lua controlled tube is done like this:

Code: Select all

if event.type == "item" then
   local s = event.item.name

   -- workshop
   if s == "bones:bone_scythe" or
      s == "cottages:hammer" or
      s == "default:axe_diamond" or
      s == "default:axe_mese" or
      s == "default:pick_diamond" or
      s == "default:pick_mese" or
      s == "default:axe_diamond" or
      s == "default:axe_mese" or
      s == "default:hoe_diamond" or
      s == "default:hoe_mese" or
      s == "default:shovel_diamond" or
      s == "default:shovel_mese" or
      s == "default:sword_diamond" or      
      s == "default:sword_mese" or
      s == "technic:treetap" or
      s == "technic_aluminum:sword_aluminum" or
      s == "screwdriver:screwdriver" or
      s:sub(1,8) == "3d_armor" or
      s:sub(1,6) == "shield" or
      s:sub(1,9) == "stairpick" then
       return "black"
   end

   -- charger
   if s == "technic:chainsaw" or
      s == "technic:prospector" or
      s == "technic:sonic_screwdriver" or
      s == "teletool:teletool_technic" or
      s:sub(1,13) == "technic:laser" or
      s:sub(1,20) == "technic:mining_drill" then
      return "yellow"
   end

   -- go-box
   if s == "bridgetool:bridge_tool" or
      s == "carts:cart" or
      s == "default:torch" or
      s == "default:ladder_wood" or
      s == "farming:corn" or
      s == "landrush:landclaim" or
      s == "more_chests:wifi" or
      s == "protector:protect" or
      s == "travelnet:elevator" or
      s:sub(1,11) == "bridgetool:" then
       return "white"
   end

   --- sort1
   return "red"
end
Here you already see the use of

Code: Select all

s:sub(start,end)
idiom to test on substrings. I use this because them item name sometimes changes, e.g. the drill has several modes of operation. So I only search at the start of the string for the decision if the item should go to the battery box for recharging.

Substrings can also be used to have chests that get items from a whole mod. With normal pneumatic sorter tubes this is almost impossible, they only can select by 6 items. But to check if an item is from a mod is a single instruction in Lua:

Code: Select all

if event.type == "item" then
   local s = event.item.name

   if s:sub(1,7) == "technic" then
     return "black"
   end

   return "red"
end

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Fri Oct 12, 2018 22:32
by silvery_magnus
Thanks for this very clear explanation!

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sun Nov 11, 2018 09:41
by Desour

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Jul 13, 2019 10:17
by Vince
This was great to get me started. I wanted to expand upon the idea using pattern matching for what I think of as a Tree Chest, but I can't seem to get it working. I have some experience with regular expressions and I did some reading to get the syntax right. I even did some basic testing using an online repl. But I just can't get it to work. Everything goes in the chest attached to the blue output.

Here's the latest iteration of what I've been trying:

Code: Select all

-- Tree Box
if event.type == "item" then
  local itemName = event.item.name
  if (string.match(itemName, 'default:.*tree') ~= nil) or
    (string.match(itemName, 'default:.*wood') ~= nil) or
    (string.match(itemName, 'moretrees:.*planks') ~= nil) or
    (string.match(itemName, 'default:.*sapling') ~= nil) or
    (string.match(itemName, 'moretrees:.*sapling') ~= nil) or
    itemName == 'bakedclay:thistle' or
    itemName == 'bakedclay:lazarus' or
    itemName == 'bakedclay:mannagrass' or
    itemName == 'bakedclay:delphinium' or
    (string.match(itemName, '^flowers:') ~= nil)
  then
    return "blue"
  end
  return "white"
end

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Jul 13, 2019 18:23
by ShadMOrdre
Vince,

It looks like you are trying to find a substring that includes the "wildcard" charcter.

The following

Code: Select all

string.match(itemName, 'default:.*tree')
is actually looking for the substring "default:.*tree" which always returns nil, because there is no node named "default:.*tree". "default:tree", AFAIK, is the name of the default tree trunk node, so you should be able to just:

Code: Select all

string.match(itemName, 'tree')
There may be other issues, and I have not really coded for the Lua controller, but the above seemed an obvious Lua syntax issue.

Hope this helps.

Shad

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Jul 13, 2019 20:12
by Vince
ShadMOrdre wrote:Vince,

It looks like you are trying to find a substring that includes the "wildcard" charcter.

The following

Code: Select all

string.match(itemName, 'default:.*tree')
is actually looking for the substring "default:.*tree" which always returns nil, because there is no node named "default:.*tree". "default:tree", AFAIK, is the name of the default tree trunk node, so you should be able to just:

Code: Select all

string.match(itemName, 'tree')
There may be other issues, and I have not really coded for the Lua controller, but the above seemed an obvious Lua syntax issue.

Hope this helps.

Shad
Thanks Shad.

According to the documentation for string.match, the second argument isn't just a regular string. It's a pattern. This is known as a "regular expression", or regex in many programming languages. In this context, .* isn't a wildcard as it is in the DOS / Windows command line. These characters are special in a pattern. The dot represents one of any character and the asterisk means 0 or more of the preceding character.

The result should match default:tree as well as default:aspen_tree and default:pine_tree.

I think that the Lua syntax used for the in-game controllers and tubes may be a little bit different from what the documentation shows and what works in a REPL. I should have realized it when I saw s:sub(1,13) instead of string.sub(s, 1, 13). I might be able to correct my first attempt using this syntax, but I haven't tried yet because I found sort of a work-around:

Code: Select all

-- Tree Box, substrings
if event.type == 'item'
then
  local itemName = event.item.name

  if
    -- trunks
    (itemName:sub(1,7) == 'default' and itemName:sub(-4) == 'tree') or
    (itemName:sub(1,9) == 'moretrees' and itemName:sub(-5) == 'trunk') or

    -- planks
    (itemName:sub(1,7) == 'default' and itemName:sub(-4) == 'wood') or
    (itemName:sub(1,9) == 'moretrees' and itemName:sub(-6) == 'planks') or

    -- saplings
    itemName:sub(-7) == 'sapling' or

    -- flowers
    itemName == 'bakedclay:thistle' or
    itemName == 'bakedclay:lazarus' or
    itemName == 'bakedclay:mannagrass' or
    itemName == 'bakedclay:delphinium' or
    itemName:sub(1,7) == 'flowers' or

    -- grass
    itemName:sub(1,13) == 'default:grass' or
    itemName:sub(1,17) == 'default:dry_grass' or
    itemName == 'default:junglegrass' or

    -- bonemeal
    itemName:sub(1,8) == 'bonemeal' or
    itemName == 'bones:bones' or

    -- farming (includes seeds)
    itemName:sub(1,7) == 'farming' or

    -- dyes
    itemName:sub(1,3) == 'dye'
  then
    return 'blue'
  end
  return 'white'
end

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Jul 13, 2019 22:08
by Desour
It is possible that pattern matching is disallowed by luacontroller env. (See https://github.com/minetest-mods/meseco ... t.lua#L436.)

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sun Jul 14, 2019 00:59
by Vince
I figured out pattern matching for the Lua tubes. The second argument to the match is indeed a pattern rather than a regular string. I was just using the wrong syntax.

It might be something peculiar about the Lua implementation in Minetest, but I suspect it's just that Minetest's Lua implementation doesn't include the String Manipulation standard library.

I have experience with some other programming languages, but this was my first attempt at writing anything in Lua.

I did read the code comments regarding the DoS potential for pattern matching with find, but it wasn't clear to me whether or not that extended to match. In any case, the pattern matching with match does seem to work for the server I'm playing on.

Here's the code that works with pattern matching:

Code: Select all

-- Tree Box
if event.type == "item"
then
  local itemName = event.item.name
  if
    -- trunks
    itemName:match('default:.*tree') ~= nil or
    itemName:match('moretrees:.*trunk') ~= nil or

    -- planks
    itemName:match('default:.*wood') ~= nil or
    itemName:match('moretrees:.*planks') ~= nil or

    -- saplings
    itemName:match('sapling$') ~= nil or

    -- flowers
    itemName == 'bakedclay:thistle' or
    itemName == 'bakedclay:lazarus' or
    itemName == 'bakedclay:mannagrass' or
    itemName == 'bakedclay:delphinium' or
    itemName:match('^flowers:') ~= nil or

    -- grass
    itemName:match('^default:grass') or
    itemName:match('^default:dry_grass') or
    itemName == 'default:junglegrass' or

    -- bonemeal
    itemName:match('^bonemeal') or
    itemName == 'bones:bones' or

    -- farming (includes seeds)
    itemName:match('^farming:') or

    -- dyes
    itemName:match('^dye:')
  then
    return "blue"
  end
  return "white"
end

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Wed Dec 11, 2019 10:08
by ulla
Hi i have create a sistem tube ,work fine but i have an ask LCT accept table? i have tried this

Code: Select all

local ore_list = {
	{ "gold"},
	{ "copper"},
  { "iron"},
	{ "silver"},
	{ "tin"},
	{ "silicon"},
	{ "mithril"},
	{ "clay"},
	{ "steel"}
	{ "diamond"}
	{ "coal"}
	
}

for i in ipairs(ore_list) do
	local ore = ore_list[i][1]
if event.type == "item"
then
  local itemName = event.item.name
 if  
itemName:match('default:diamond')or
itemName:match('^caverealms:')or
itemName:match('mese_crystal_fragment')or
itemName:match('mese_crystal')or
itemName:match('glowstone')or

itemName:match(''..ore..'_ingot')or
itemName:match(''..ore..'_lump')or
itemName:match(''..ore..'block')
then
return "green"
end


return"blue"
end
end
work but sometime item not return green but blue . Is the table hard for LCT? Creates delay in sort?
i tryed too

Code: Select all


itemName:match(""..ore.."_ingot")or
itemName:match(""..ore.."_lump")or
itemName:match(""..ore.."block")
but is the same

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Thu Jan 02, 2020 12:58
by Miniontoby
Cool, I didn't knew that you could use them for sorting

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Mar 12, 2022 15:57
by texnofobix
Could you use the lua controller tube to detect if the stack is even or odd? If so, can someone provide an example?

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Mar 12, 2022 17:17
by Desour
new link to wiki: https://github.com/mt-mods/pipeworks/wi ... lled-tubes

@texnofobix:
Something like this maybe:
if event.type == "item" then
local count = event.item.count or 1
local even = count % 2 == 0
digiline_send("mychan", even)
return nil -- send back
end

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Mar 12, 2022 17:46
by texnofobix
Thanks! DS-minetest. I was thinking along those lines but wasn't sure of what was exposed at the time the lua has it.

I currently have the following.

Code: Select all

if event.type == "item" then
  local name = event.item.name
  local count = event.item.count

  if (count % 2 == 0) then
    -- even
    return "black"
  end
  return "white"
end

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Mar 12, 2022 18:59
by texnofobix
Is it possible to split item stacks?

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Sat Mar 12, 2022 22:19
by Desour
texnofobix wrote:
Sat Mar 12, 2022 18:59
Is it possible to split item stacks?
Not via the lua tube. You can use (digiline) chest and digiline filter tough.

Re: Tip on Lua controlled Tube (use for sorting)

Posted: Tue Feb 27, 2024 12:30
by Stonee
Vince wrote:
Sat Jul 13, 2019 20:12
...

I think that the Lua syntax used for the in-game controllers and tubes may be a little bit different from what the documentation shows and what works in a REPL. I should have realized it when I saw s:sub(1,13) instead of string.sub(s, 1, 13). I might be able to correct my first attempt using this syntax, but I haven't tried yet because I found sort of a work-around:
Vince, you are right. I found out that match cannot be used in lua controlled tube, but find with plain parameter true can be used. No regular expression, but at least something better than the sub. Check:

Code: Select all

if event.type == 'item'
then
	local i = event.item.name


	if	i:find('tree',1,true) or
		i:find('trunk',1,true) or
		i:find('plank',1,true) or
		i:find('stick',1,true) or
		i:find('chest',1,true)
	then
		return "blue"
	end
	if i:find('ingot',1,true) or
		i:find('lump',1,true) or
		i:find('raw',1,true) or
		i:find('sapphire',1,true) or
		i:find('Ruby',1,true) or
		i:find('crystal',1,true) or
		i:find('slag',1,true) or
		i:find('crystal',1,true) or
		i:find('crystal',1,true) then
		return "yellow"
	end
	if	i:find('axe',1,true) or
		i:find('pick',1,true) or
		i:find('scythe',1,true) or
		i:find('hammer',1,true) or
		i:find('hoe',1,true) or
		i:find('shovel',1,true) or
		i:find('sword',1,true) or
		i:find('treetap',1,true) or
		i:find('3d_armor',1,true) or
		i:find('shield',1,true) or
		i:find('treetap',1,true) or
		i:find('chainsaw',1,true) or
		i:find('screwdriver',1,true) or
		i:find('drill',1,true) or
		i:find('laser',1,true)
	then
		return "green"
	end
	if	i:find('mese',1,true) or
		i:find('tube',1,true) or
		i:find('filter',1,true) or
		i:find('blinky',1,true) or
		i:find('control',1,true) or
		i:find('wood',1,true)
	then
		return "red"
	end
	if	i:find('gravel',1,true) or
		i:find('sand',1,true) or
		i:find('stone',1,true) or
		i:find('marble',1,true) or
		i:find('rubble',1,true) or
		i:find('granite',1,true) or
		i:find('block',1,true) or
		i:find('dirt',1,true) or
		i:find('ice',1,true)
	then
		return "white"
	end
	return 'black'
end