From 80ca16e3edcd5c487f8323432910893d67b8913e Mon Sep 17 00:00:00 2001 From: Neel Kant Date: Wed, 27 Aug 2025 00:24:07 -0700 Subject: [PATCH] changes for get_entities (groups) and connect_entities error logging; --- fle/env/mods/utils.lua | 2 +- .../tools/agent/connect_entities/server.lua | 20 ++- fle/env/tools/agent/get_entities/client.py | 149 +++++++++++------- .../agent/place_entity_next_to/server.lua | 2 +- 4 files changed, 116 insertions(+), 57 deletions(-) diff --git a/fle/env/mods/utils.lua b/fle/env/mods/utils.lua index a7b3ca2b..5368e8c6 100644 --- a/fle/env/mods/utils.lua +++ b/fle/env/mods/utils.lua @@ -63,7 +63,7 @@ global.utils.get_closest_entity = function(player, position) local entities = player.surface.find_entities_filtered{ position = position, force = "player", - radius = 3 + radius = 5 -- Increased from 3 to 5 to better handle large entities like 3x3 drills } for _, entity in ipairs(entities) do diff --git a/fle/env/tools/agent/connect_entities/server.lua b/fle/env/tools/agent/connect_entities/server.lua index cac4a546..2319c489 100644 --- a/fle/env/tools/agent/connect_entities/server.lua +++ b/fle/env/tools/agent/connect_entities/server.lua @@ -748,8 +748,16 @@ local function connect_entities(player_index, source_x, source_y, target_x, targ -- game.print("Path length "..#raw_path) -- game.print(serpent.line(start_position).." - "..serpent.line(end_position)) - if not raw_path or type(raw_path) ~= "table" or #raw_path == 0 then - error("Invalid path: " .. serpent.line(path)) + if not raw_path then + error("No path found for handle " .. path_handle .. ". Pathfinding may have failed.") + elseif raw_path == "not_found" then + error("Pathfinding failed: no valid path exists between source and target positions.") + elseif raw_path == "busy" then + error("Pathfinder is busy, try again later.") + elseif type(raw_path) ~= "table" then + error("Invalid path type: " .. type(raw_path) .. " (value: " .. serpent.line(raw_path) .. ")") + elseif #raw_path == 0 then + error("Empty path returned from pathfinder.") end -- game.print("Normalising", {print_skip=defines.print_skip.never}) @@ -793,6 +801,14 @@ local function connect_entities(player_index, source_x, source_y, target_x, targ -- Get source and target entities local source_entity = global.utils.get_closest_entity(player, {x = source_x, y = source_y}) local target_entity = global.utils.get_closest_entity(player, {x = target_x, y = target_y}) + + -- Validate that entities were found + if not source_entity then + error("No entity found at source position x=" .. source_x .. " y=" .. source_y .. " within radius 3") + end + if not target_entity then + error("No entity found at target position x=" .. target_x .. " y=" .. target_y .. " within radius 3") + end if #connection_types == 1 and connection_types[1] == 'pipe-to-ground' then diff --git a/fle/env/tools/agent/get_entities/client.py b/fle/env/tools/agent/get_entities/client.py index 034c32f5..1cfe5e1c 100644 --- a/fle/env/tools/agent/get_entities/client.py +++ b/fle/env/tools/agent/get_entities/client.py @@ -78,8 +78,10 @@ class GetEntities(Tool): ) continue - if matching_prototype not in entities and entities: + # Apply standard filtering + if entities and matching_prototype not in entities: continue + metaclass = matching_prototype.value[1] while isinstance(metaclass, tuple): metaclass = metaclass[1] @@ -89,7 +91,7 @@ class GetEntities(Tool): if isinstance(value, dict): entity_data[key] = self.process_nested_dict(value) - entity_data["prototype"] = prototype + entity_data["prototype"] = matching_prototype # remove all empty values from the entity_data dictionary entity_data = { @@ -102,58 +104,99 @@ class GetEntities(Tool): except Exception as e1: print(f"Could not create {entity_data['name']} object: {e1}") - # get all pipes into a list - pipes = [ - entity - for entity in entities_list - if hasattr(entity, "prototype") - and entity.prototype in (Prototype.Pipe, Prototype.UndergroundPipe) - ] - group = agglomerate_groupable_entities(pipes) - [entities_list.remove(pipe) for pipe in pipes] - entities_list.extend(group) - - poles = [ - entity - for entity in entities_list - if hasattr(entity, "prototype") - and entity.prototype - in ( - Prototype.SmallElectricPole, - Prototype.BigElectricPole, - Prototype.MediumElectricPole, - ) - ] - group = agglomerate_groupable_entities(poles) - [entities_list.remove(pole) for pole in poles] - entities_list.extend(group) - - walls = [ - entity - for entity in entities_list - if hasattr(entity, "prototype") - and entity.prototype == Prototype.StoneWall - ] - group = agglomerate_groupable_entities(walls) - [entities_list.remove(wall) for wall in walls] - entities_list.extend(group) - - belt_types = ( - Prototype.TransportBelt, - Prototype.FastTransportBelt, - Prototype.ExpressTransportBelt, - Prototype.UndergroundBelt, - Prototype.FastUndergroundBelt, - Prototype.ExpressUndergroundBelt, + # Only group entities if user is looking for group types or no specific filter + should_group = not entities or any( + proto + in { + Prototype.ElectricityGroup, + Prototype.PipeGroup, + Prototype.BeltGroup, + } + for proto in entities ) - belts = [ - entity - for entity in entities_list - if hasattr(entity, "prototype") and entity.prototype in belt_types - ] - group = agglomerate_groupable_entities(belts) - [entities_list.remove(belt) for belt in belts] - entities_list.extend(group) + + if should_group: + # get all pipes into a list + pipes = [ + entity + for entity in entities_list + if hasattr(entity, "prototype") + and entity.prototype in (Prototype.Pipe, Prototype.UndergroundPipe) + ] + group = agglomerate_groupable_entities(pipes) + [entities_list.remove(pipe) for pipe in pipes] + entities_list.extend(group) + + poles = [ + entity + for entity in entities_list + if hasattr(entity, "prototype") + and entity.prototype + in ( + Prototype.SmallElectricPole, + Prototype.BigElectricPole, + Prototype.MediumElectricPole, + ) + ] + group = agglomerate_groupable_entities(poles) + [entities_list.remove(pole) for pole in poles] + entities_list.extend(group) + + walls = [ + entity + for entity in entities_list + if hasattr(entity, "prototype") + and entity.prototype == Prototype.StoneWall + ] + group = agglomerate_groupable_entities(walls) + [entities_list.remove(wall) for wall in walls] + entities_list.extend(group) + + belt_types = ( + Prototype.TransportBelt, + Prototype.FastTransportBelt, + Prototype.ExpressTransportBelt, + Prototype.UndergroundBelt, + Prototype.FastUndergroundBelt, + Prototype.ExpressUndergroundBelt, + ) + belts = [ + entity + for entity in entities_list + if hasattr(entity, "prototype") and entity.prototype in belt_types + ] + group = agglomerate_groupable_entities(belts) + [entities_list.remove(belt) for belt in belts] + entities_list.extend(group) + + # Final filtering after grouping is complete + if entities: + filtered_entities = [] + for entity in entities_list: + # Check entity prototype or group type + if hasattr(entity, "prototype") and entity.prototype in entities: + filtered_entities.append(entity) + elif hasattr(entity, "__class__"): + # Check for group types + if ( + entity.__class__.__name__ == "ElectricityGroup" + and Prototype.ElectricityGroup in entities + ): + filtered_entities.append(entity) + elif ( + entity.__class__.__name__ == "PipeGroup" + and Prototype.PipeGroup in entities + ): + filtered_entities.append(entity) + elif ( + entity.__class__.__name__ == "BeltGroup" + and Prototype.BeltGroup in entities + ): + filtered_entities.append(entity) + elif entity.__class__.__name__ == "WallGroup": + # WallGroup doesn't have a corresponding Prototype, but include if present + filtered_entities.append(entity) + entities_list = filtered_entities return entities_list diff --git a/fle/env/tools/agent/place_entity_next_to/server.lua b/fle/env/tools/agent/place_entity_next_to/server.lua index 28c2f632..f237f2e5 100644 --- a/fle/env/tools/agent/place_entity_next_to/server.lua +++ b/fle/env/tools/agent/place_entity_next_to/server.lua @@ -289,7 +289,7 @@ global.actions.place_entity_next_to = function(player_index, entity, ref_x, ref_ local items = player.surface.find_entities_filtered{ area = area, - type = "item-on-ground" + name = "item-on-ground" } for _, item in ipairs(items) do item.destroy()