item-with-tags, blueprints and custom config

Place to ask discuss and request the modding support of Factorio. Don't request mods here.
Post Reply
gheift
Fast Inserter
Fast Inserter
Posts: 188
Joined: Tue Mar 03, 2015 9:20 pm
Contact:

item-with-tags, blueprints and custom config

Post by gheift »

Hi,

with the new item-with-tags type, we can add data to items. Now I have a few questions/suggestions. In simple scenario we have a item-with-tag and a simple-entity-with-owner.

Code: Select all

data:extend{{
    type = "item-with-tags",
    name = "ght-item-with-tags",
    place_result = "ght-simple-entity-with-owner",
    -- rest omitted
}, {
    type = "simple-entity-with-owner",
    name = "ght-simple-entity-with-owner",
    minable = { result = "ght-item-with-tags" },
    -- rest omitted
}}
On mining this entity, I can add tags to the item, e.g. with an event handler like this:

Code: Select all

local function on_mined_entity(event)
    local robot = event.name == defines.events.on_robot_mined_entity
    local entity = event.entity
    local who = event.player_index and game.players[event.player_index] or entity.force
    local buffer = event.buffer
            
    local print = who.print
    local printf = function(...) print(string.format(...)) end
 
    printf("mined%s %s at (%d,%d)", robot and " by robot" or "", entity.name, entity.position.x, entity.position.y)
    for i = 1, #buffer do
        local stack = buffer[i]
        printf("stack: %s (%d)", stack.name, stack.count)
        if stack.name == "ght-item-with-tags" then
            stack.set_tag("pos-x", entity.position.x)
            stack.set_tag("pos-y", entity.position.y)
        end
    end
end

script.on_event(defines.events.on_player_mined_entity, on_mined_entity)
script.on_event(defines.events.on_robot_mined_entity, on_mined_entity)
The result is an item in my inventory, which says "item has tags". If this item is placed by a player, I can use these tags to modify the entity or do other things. Here I just print the distance to the last location:

Code: Select all

local function on_built_entity(event)
    local robot = event.name == defines.events.on_robot_built_entity
    local entity = event.created_entity
    local who = event.players_index and game.players[event.player_index] or entity.force
    local item = event.item
    local tags = event.tags
    
    local print = who.print
    local printf = function(...) print(string.format(...)) end
    
    printf("build%s %s at (%d,%d)", robot and " by robot" or "", entity.name, entity.position.x, entity.position.y)
    printf("item: %s", item or "[unknown]") 
    printf("tags: %s", serpent.dump(tags))
    
    if item == "ght-item-with-tags" and tags then
        local pos_x = tags["pos-x"]
        local pos_y = tags["pos-y"]
      
        if pos_x and pos_y then
            pos_x = pos_x - entity.position.x
            pos_y = pos_y - entity.position.y

            local dist = math.sqrt(pos_x * pos_x + pos_y * pos_y)
            printf("item moved %.1f tiles", dist)
        end
    end
end 
    
script.on_event(defines.events.on_built_entity, on_built_entity)
script.on_event(defines.events.on_robot_built_entity, on_built_entity)
Now the problems starts:
  • if I create a blueprint, I can't store any data to it
  • if I place a blueprint, the on_robot_built_entity has no event.item
  • if I place a blueprint, the robots uses items, which has tags, but those tags are "lost" after placing the item
Specially the last item prevents using the tags in its current state. If e.g. the item stores the data of a factorissimo factory (e.g. as blueprint or surface-id) and it is placed by a a robot, this information is lost.

I suggest the following extension to the modding interface:

An on_marked_for_blueprint event, with the following information:
  • player_index: the player, who marked the item for a blueprint
  • entity: the entity to be blueprinted
  • item: the name of the item, which will be stored in the blueprint -- can be changed by mod
  • tags: if item is a item-with-tags, then the table with tags
  • config: additional config for the entity, can be used for customization by mods
The system will then use the item, tags, and config stored in the event table for this entity to assemble the complete blueprint.

The LuaEntity object gets the following additional properties:
  • ghost_item: the item used to build the entity
  • ghost_tags: the tags associated with item to built this entity
  • ghost_config: the configuration stored for this entity
On building the entity by a robot the on_robot_built_entity will be extended to revive the following information in the event table:
  • item: the item used to build this entity
  • tags: the tags associated with this item
  • config: the configuration stored for this entity
The robots, which are dedicated to build ghosts with tags, should honor to only use items with identical tags, like the grouping is already in the inventory. E.g. a {name="inserter-with-tags", tags={"range" = 2}} must not be built with a {name="inserter-with-tags", tags={"range"=1}}.

To explain the difference between tags and config:
  • tags is to "permanetly" bind an information to an item/entity. e.g. if a "clean" object is modified by a process to be better/larger/faster, then this information should be preserved. Say you have an inserter and enlarge its reach with a recipe, then you can store a tag to the inserter.
  • config is to save/restore a configuration of an entity. E.g. bobs inserters can grab and place in various directions, this should be saved in the config for the blueprint. The mod, which stores this information can later make the necessary steps to restore its orignal behavior. But it is not a permanent information of this inserter. Its more like a recipe or direction.

Rseding91
Factorio Staff
Factorio Staff
Posts: 13209
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: item-with-tags, blueprints and custom config

Post by Rseding91 »

I'll fix the robots not eventing the tags of the item they used to build a ghost.

As for blueprints: I'll think about adding support for tags on entities in blueprints/ghosts that would then be sent in the same built event the robot sends when building them.

The final thing you mention though - robots only using specific items with specific tags to re-build entities: that's probably never going to happen. That would increase the complexity of robots trying to find items to build entities from O(1) to O(ContainersWithThisItemType * ItemsInEachContainer) and that would murder game performance.

The simplest solution for your use case is to disallow making blueprints/ghosts/deconstruction (through robots) of your buildings since you want such fine-grain control of how they're used and the core game is just never going to support that for performance reasons.
If you want to get ahold of me I'm almost always on Discord.

gheift
Fast Inserter
Fast Inserter
Posts: 188
Joined: Tue Mar 03, 2015 9:20 pm
Contact:

Re: item-with-tags, blueprints and custom config

Post by gheift »

Thanks for your feedback. I'm looking forward how this will be implemented.

I understand the complexity to search for the item with a matching tag, but perhaps a possible solution would be to exclude items which have tags set to be used by robots (at least as an option in the prototype of the item).

As a side question: how do robots decide which item will be used to build an entity if two different items have the same place_result?

Code: Select all

item-a: place_result = entity
item-b: place_result = entity
Kind regards,
Gerhard

Rseding91
Factorio Staff
Factorio Staff
Posts: 13209
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: item-with-tags, blueprints and custom config

Post by Rseding91 »

Anywhere something would need to decide "which one" in the list of place results we always use the first item.

It's something I've had on the back of my mind to fix for a while but nobody has complained about it yet so... :)
If you want to get ahold of me I'm almost always on Discord.

Post Reply

Return to “Modding interface requests”