item-on-ground, grouped entities

This commit is contained in:
Neel Kant
2025-09-02 11:04:23 -07:00
parent ca76e2c5d8
commit 5a5cf20474
7 changed files with 72 additions and 43 deletions

View File

@@ -94,7 +94,6 @@ end
--end)
script.on_event(defines.events.on_script_path_request_finished, function(event)
game.print("Path request finished for ID: " .. event.id)
local request_data = global.path_requests[event.id]
if not request_data then
game.print("No request data found for ID: " .. event.id)
@@ -109,7 +108,6 @@ script.on_event(defines.events.on_script_path_request_finished, function(event)
if event.path then
global.paths[event.id] = event.path
game.print("Path found for request ID: " .. event.id)
elseif event.try_again_later then
global.paths[event.id] = "busy"
game.print("Pathfinder busy for request ID: " .. event.id)

View File

@@ -109,6 +109,33 @@ class ConnectEntities(Tool):
)
def __call__(self, *args, **kwargs):
"""Wrapper method with retry logic for specific Lua errors."""
max_retries = 2
retry_count = 0
while retry_count <= max_retries:
try:
return self.__call_impl__(*args, **kwargs)
except Exception as e:
error_message = str(e)
# Check if the error contains the specific Lua error we want to retry on
if "attempt to index field ? (a nil value)" in error_message:
retry_count += 1
if retry_count <= max_retries:
print(
f"ConnectEntities retry {retry_count}/{max_retries} due to Lua indexing error: {error_message}"
)
continue
else:
print(
f"ConnectEntities failed after {max_retries} retries: {error_message}"
)
raise
else:
# For any other error, don't retry - just re-raise immediately
raise
def __call_impl__(self, *args, **kwargs):
connection_types = set()
waypoints = []
if "connection_type" in kwargs:

View File

@@ -543,6 +543,13 @@ def agglomerate_groupable_entities(
if not connected_entities:
return []
# Check if entities are already grouped - if so, return them as-is
if hasattr(connected_entities[0], "__class__") and connected_entities[
0
].__class__.__name__ in ["BeltGroup", "PipeGroup", "ElectricityGroup", "WallGroup"]:
# Entities are already grouped, return them directly
return connected_entities
if hasattr(connected_entities[0], "prototype"):
prototype = connected_entities[0].prototype

View File

@@ -38,7 +38,7 @@ class GetEntities(Tool):
for entity in entities:
if entity == Prototype.BeltGroup:
# For belt groups, search for all belt types
# For belt groups, search for all belt types and group them
belt_types = {
Prototype.TransportBelt,
Prototype.FastTransportBelt,
@@ -50,12 +50,12 @@ class GetEntities(Tool):
expanded_entities.update(belt_types)
group_requests.add(Prototype.BeltGroup)
elif entity == Prototype.PipeGroup:
# For pipe groups, search for pipe types
# For pipe groups, search for pipe types and group them
pipe_types = {Prototype.Pipe, Prototype.UndergroundPipe}
expanded_entities.update(pipe_types)
group_requests.add(Prototype.PipeGroup)
elif entity == Prototype.ElectricityGroup:
# For electricity groups, search for pole types
# For electricity groups, search for pole types and group them
pole_types = {
Prototype.SmallElectricPole,
Prototype.MediumElectricPole,
@@ -117,8 +117,12 @@ class GetEntities(Tool):
)
continue
# Apply standard filtering
if entities and matching_prototype not in entities:
# Apply standard filtering - check against expanded entities too
if (
entities
and matching_prototype not in entities
and matching_prototype not in expanded_entities
):
continue
metaclass = matching_prototype.value[1]
@@ -167,9 +171,6 @@ class GetEntities(Tool):
or (
entities and position is not None
) # Individual entities with position filter = group for convenience
or any(
proto in pole_types for proto in entities
) # Individual pole entities - always group
)
if should_group:
@@ -231,15 +232,11 @@ class GetEntities(Tool):
filtered_entities = []
for entity in entities_list:
# Check entity prototype or group type
if hasattr(entity, "prototype") and entity.prototype in entities:
# Exclude power poles from individual handling - they should be handled as groups
pole_types = {
Prototype.SmallElectricPole,
Prototype.MediumElectricPole,
Prototype.BigElectricPole,
}
if entity.prototype not in pole_types:
filtered_entities.append(entity)
if hasattr(entity, "prototype") and (
entity.prototype in entities
or entity.prototype in expanded_entities
):
filtered_entities.append(entity)
elif hasattr(entity, "__class__"):
# Handle group entities
if entity.__class__.__name__ == "ElectricityGroup":
@@ -272,17 +269,10 @@ class GetEntities(Tool):
):
# Individual pipes requested with position - return group for convenience
filtered_entities.append(entity)
elif (
any(pipe_type in entities for pipe_type in pipe_types)
and position is None
):
# Individual pipes requested without position - extract individual pipes from group
for pipe in entity.pipes:
if (
hasattr(pipe, "prototype")
and pipe.prototype in entities
):
filtered_entities.append(pipe)
elif any(pipe_type in entities for pipe_type in pipe_types):
# Individual pipes requested - return group (restores original behavior)
# Pipes are inherently networked, so groups are more useful than individuals
filtered_entities.append(entity)
elif entity.__class__.__name__ == "BeltGroup":
belt_types = {
Prototype.TransportBelt,

View File

@@ -25,7 +25,6 @@ end
global.actions.move_to = function(player_index, path_handle, trailing_entity, is_trailing)
--local player = global.agent_characters[player_index]
local player = global.agent_characters[player_index]
game.print("Moving to path with handle: " .. path_handle)
local path = global.paths[path_handle]
local surface = player.surface

View File

@@ -382,6 +382,21 @@ global.actions.place_entity_next_to = function(player_index, entity, ref_x, ref_
local is_belt = is_transport_belt(entity)
local new_position = calculate_position(direction, ref_position, ref_entity, gap, is_belt, entity)
-- Helper function to clear item-on-ground entities at a position
local function clear_items_on_ground(position, radius)
local items = player.surface.find_entities_filtered{
position = position,
radius = radius or 0.5,
name = "item-on-ground"
}
for _, item in ipairs(items) do
item.destroy()
end
end
-- Clear any item-on-ground entities at the target position before collision check
clear_items_on_ground(new_position)
local function player_collision(player, target_area)
local character_box = {
@@ -435,6 +450,9 @@ global.actions.place_entity_next_to = function(player_index, entity, ref_x, ref_
alt_pos.x = math.ceil(alt_pos.x * 2) / 2
alt_pos.y = math.ceil(alt_pos.y * 2) / 2
-- Clear items at alternative position before checking if it's clear
clear_items_on_ground(alt_pos)
-- Check if this position is clear
local alt_nearby_entities = player.surface.find_entities_filtered({
position = alt_pos,
@@ -556,10 +574,9 @@ global.actions.place_entity_next_to = function(player_index, entity, ref_x, ref_
player.teleport(new_player_position)
end
-- First clean up any items-on-ground at the target position
local area = {{new_position.x - entity_width / 2, new_position.y - entity_height / 2}, {new_position.x + entity_width / 2, new_position.y + entity_height / 2}}
-- Show bounding box
-- Show bounding box for debugging
rendering.draw_rectangle({
only_in_alt_mode=true,
color = {r = 0, g = 1, b = 0},
@@ -588,15 +605,6 @@ global.actions.place_entity_next_to = function(player_index, entity, ref_x, ref_
time_to_live = 60000
})
local items = player.surface.find_entities_filtered{
area = area,
name = "item-on-ground"
}
for _, item in ipairs(items) do
item.destroy()
end
global.utils.avoid_entity(player_index, entity, new_position, direction)
local can_build = player.surface.can_place_entity({

View File

@@ -1,6 +1,6 @@
[
{
"env_id": "steel_plate_throughput",
"model": "claude-4-opus-20250514"
"model": "claude-sonnet-4-20250514"
}
]