How to filter an entity iterator?

Started by alexgleason, September 24, 2018, 12:03:15 AM

Previous topic - Next topic
So I've used:

Code ( lua) Select
map:get_entities_in_rectangle(x, y, width, height)

which gave me back a nice entity iterator.

The problem is, I only want some of those entities. For example, I might want only entities where:

Code ( lua) Select
entity:get_type() == "custom_entity" and entity:get_model() == "trash"

I know how to loop through it and build a new array, but I'd like to learn how to create a new entity iterator. Is it possible to do this without dumping the contents of the first iterator into an array first? I'm new to Lua and trying to figure this out. :)

Thanks!
RIP Aaron Swartz

The best way to do that is exactly the way you are doing it:
Code (Lua) Select
for entity in map:get_entities_in_rectangle(x, y, width, height) do
  if entity:get_type() == "custom_entity" and entity:get_model() == "trash" then
    -- blablabla cats meow meow!
  end
end

Always put the stronger condition in the outer built-in iterator, because that one is optimized. (For instance, getting first the custom entities and later the "rectangle overlapping" condition would be slightly slower). In this case you cannot do it with only 1 loop (you need to filter with "if" conditions).
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 24, 2018, 12:55:36 AM #2 Last Edit: September 24, 2018, 01:18:27 AM by alexgleason
What I'm trying to do is actually return a new entity iterator. For context, I'm making an item similar to the gust jar in Minish Cap. I'm wanting item:get_suckable_entities() to return an entity iterator containing items of a certain type in a certain region so I can loop over it.

I just managed to finish writing this code:

Code ( lua) Select
-- Get suckable entities
function item:get_suckable_entities()

  local map  = self:get_map()

  -- Get entities in suckable rectangle
  local entities = map:get_entities_in_rectangle(self:get_suckable_rectangle())

  -- Filter only suckable types
  filtered = {}
  for entity in entities do
    for model in item:get_suckable_models() do
      if entity:get_type() == "custom_entity" and entity:get_model() == model then
        table.insert(filtered, entity)
      end
    end
  end

  function filtered_entities()
    local i = 0
    local n = table.getn(filtered)
    return function()
      i = i + 1
      if i <= n then return filtered[i] end
    end
  end

  return filtered_entities()
end


It totally works, but I was hoping there would be a way to achieve this without dumping everything into a filtered table first and then creating a new iterator out of that table.

Thanks for your reply. :)

EDIT: My full code is now here for context https://gitlab.com/voadi/voadi/blob/master/data/items/vacuum.lua
RIP Aaron Swartz

This library seems to do what I want, but it doesn't look possible in normal Lua: https://github.com/starwing/luaiter

It has a fitlerout(func, iter) function.
RIP Aaron Swartz