Page 1 of 1

Tip on Lua controlled Tube (use for sorting)

PostPosted: 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)

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

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

PostPosted: Sun Nov 11, 2018 09:41
by DS-minetest

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

PostPosted: 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)

PostPosted: 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)

PostPosted: 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)

PostPosted: Sat Jul 13, 2019 22:08
by DS-minetest

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

PostPosted: 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