From 1fdf7354a74bbd7847ccfbe2a151f0cdef028ac0 Mon Sep 17 00:00:00 2001 From: protocol_1903 <67478786+protocol-1903@users.noreply.github.com> Date: Wed, 28 Jan 2026 22:30:36 -0700 Subject: [PATCH] Fixed smart farms not working with most plants on new saves Removed part of the smart farm remote API due to engine constraints --- changelog.txt | 2 + control.lua | 1 - scripts/smart-farm/mega-farm.lua | 175 --------------------------- scripts/smart-farm/smart-farm.lua | 191 ++++++++++++++++++++++++++---- 4 files changed, 170 insertions(+), 199 deletions(-) delete mode 100644 scripts/smart-farm/mega-farm.lua diff --git a/changelog.txt b/changelog.txt index 4aa3752c8..db9648f73 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,6 +5,8 @@ Date: ???? - Allowed sea sponges mk02+ from sea sponge sprouts mk02+ to accept productivity. Resolves https://github.com/pyanodon/pybugreports/issues/1335 - Fixed cadaveric arum smart farm recipe 2 being the same as recipe 3. Resolves https://github.com/pyanodon/pybugreports/issues/1358 - Switched smart farm autolaunch hotfix to proper runtime API call introduced in 2.0.73 + - Fixed smart farms not working with most plants on new saves + - Removed part of the smart farm remote API due to engine constraints - Fixed parts of the caravan interrupt GUI being hidden if too many conditions or targets were added. Resolves https://github.com/pyanodon/pybugreports/issues/1325 --------------------------------------------------------------------------------------------------- Version: 3.0.62 diff --git a/control.lua b/control.lua index 64acbb738..f7376125b 100644 --- a/control.lua +++ b/control.lua @@ -21,7 +21,6 @@ require "scripts.ocula.ocula" ---@diagnostic disable-next-line: different-requires require "scripts.farming.farming" require "scripts.smart-farm.smart-farm" -require "scripts.smart-farm.mega-farm" require "scripts.worm.worm" require "scripts.turd.turd" require "scripts.vatbrain.vatbrain" diff --git a/scripts/smart-farm/mega-farm.lua b/scripts/smart-farm/mega-farm.lua deleted file mode 100644 index f3479e61f..000000000 --- a/scripts/smart-farm/mega-farm.lua +++ /dev/null @@ -1,175 +0,0 @@ --- function to run when smart farm launched -local function on_launch(silo, crop_results) - local surface = silo.surface - local position = silo.position - position.y = position.y - 15 - local yield - local recipe_name = silo.get_recipe().name - for _, recipe in pairs(crop_results.recipes) do - if recipe.recipe_name == recipe_name then - yield = recipe.crop_output - break - end - end - if not yield then return end - - local is_alien_biomes = script.active_mods["alien-biomes"] or script.active_mods["combat-mechanics-overhaul"] - for x = -11, 11 do - for y = -11, 11 do - local ore_location = {position.x + x, position.y + y} - ---@diagnostic disable-next-line: missing-parameter, param-type-mismatch - if is_alien_biomes or not surface.get_tile(ore_location).collides_with("resource") then - local ore = surface.find_entity(crop_results.crop, ore_location) - - if ore then - ore.amount = ore.amount + yield - else - surface.create_entity { - name = crop_results.crop, - position = ore_location, - amount = yield, - force = "neutral" - } - end - end - end - end - - for _, harvester in pairs(surface.find_entities_filtered { - area = {{position.x - 12, position.y - 12}, {position.x + 12, position.y + 12}}, - name = {"harvester", "flora-collector-mk01", "flora-collector-mk02", "flora-collector-mk03", "flora-collector-mk04"} - }) do - harvester.update_connections() - local control_behavior = harvester.get_or_create_control_behavior() --[[@as LuaControlBehavior]] - if control_behavior.circuit_read_resources then - control_behavior.circuit_read_resources = false - control_behavior.circuit_read_resources = true - end - end -end - -local function get_fence_positions(entity) - local position = entity.position - position.y = position.y - 15 - local fence_positions = {} - for x = -12, 12 do - fence_positions[#fence_positions+1] = {position.x + x, position.y + 13} - fence_positions[#fence_positions+1] = {position.x + x, position.y - 13} - end - for y = -13, 13 do - fence_positions[#fence_positions+1] = {position.x + 13, position.y + y} - fence_positions[#fence_positions+1] = {position.x - 13, position.y + y} - end - return fence_positions -end - -local function get_landfill_positions(entity) - local position = entity.position - position.y = position.y - 15 - local landfill_positions = {} - for x = -12, 12 do - for y = -12, 12 do - landfill_positions[#landfill_positions+1] = {position.x + x, position.y + y} - end - end - return landfill_positions -end - -local function on_built(entity) - local surface = entity.surface - - for _, position in pairs(get_fence_positions(entity)) do - if not surface.entity_prototype_collides("wood-fence", position, false) then - surface.create_entity { - name = "wood-fence", - position = position, - force = entity.force - } - end - end - - local landfill_tiles = {} - for _, position in pairs(get_landfill_positions(entity)) do - local x, y = position[1], position[2] - - local previous_tile = surface.get_tile(position) - if not previous_tile.valid or previous_tile.prototype.collision_mask.layers.water_tile then goto continue end - if previous_tile.name == "sut-panel" then goto continue end - - landfill_tiles[#landfill_tiles+1] = {name = "landfill", position = position} - - storage.smart_farm_landfill_data[x] = storage.smart_farm_landfill_data[x] or {} - if storage.smart_farm_landfill_data[x][y] then - storage.smart_farm_landfill_data[x][y].depth = storage.smart_farm_landfill_data[x][y].depth + 1 - else - storage.smart_farm_landfill_data[x][y] = {depth = 1, name = previous_tile.name} - end - - ::continue:: - end - surface.set_tiles(landfill_tiles) -end - -local function on_destroyed(entity) - local surface = entity.surface - - for _, position in pairs(get_fence_positions(entity)) do - local fence = surface.find_entity("wood-fence", position) - if fence and fence.force_index == entity.force_index then - fence.destroy() - end - end - - local tiles_to_reset = {} - for _, position in pairs(get_landfill_positions(entity)) do - local x, y = position[1], position[2] - - if not storage.smart_farm_landfill_data[x] or not storage.smart_farm_landfill_data[x][y] then goto continue end - - local data = storage.smart_farm_landfill_data[x][y] - data.depth = data.depth - 1 - - if data.depth > 0 then goto continue end - tiles_to_reset[#tiles_to_reset + 1] = {name = data.name, position = position} - - storage.smart_farm_landfill_data[x][y] = nil - if table_size(storage.smart_farm_landfill_data[x]) == 0 then - storage.smart_farm_landfill_data[x] = nil - end - - ::continue:: - end - - if #tiles_to_reset == 0 then return end - surface.set_tiles(tiles_to_reset, true, false, false, true) -end - -local farm_data = { - require "farm-ralesia", - require "farm-rennea", - require "farm-tuuphra", - require "farm-grod", - require "farm-yotoi", - require "farm-kicalk", - require "farm-arum", - require "farm-yotoi-fruit", - require "farm-bioreserve", -} - -py.on_event(py.events.on_init(), function() - storage.smart_farm_landfill_data = storage.smart_farm_landfill_data or {} -end) - -script.on_load(function() - -- add launch products for later reference - for _, launch_products in pairs(farm_data) do - remote.call("py_smart_farming", "add_launch_products", launch_products) - end - - remote.call("py_smart_farming", "add_rocket_silo", { - entity = "mega-farm", - on_built = on_built, - on_destroyed = on_destroyed, - on_launch = on_launch - }) -end) \ No newline at end of file diff --git a/scripts/smart-farm/smart-farm.lua b/scripts/smart-farm/smart-farm.lua index d3ce9c1f5..ee36b5e25 100644 --- a/scripts/smart-farm/smart-farm.lua +++ b/scripts/smart-farm/smart-farm.lua @@ -1,50 +1,195 @@ --- actual runtime scripting for smart farm type entities - local launch_results = {} -local rocket_silos = {} -local function add_rocket_silo(silo_data) - rocket_silos[silo_data.entity] = silo_data -end +remote.add_interface("py_smart_farming", { + add_launch_products = function(product_data) + launch_results[product_data.name] = product_data + end +}) + +local farm_data = { + require "farm-ralesia", + require "farm-rennea", + require "farm-tuuphra", + require "farm-grod", + require "farm-yotoi", + require "farm-kicalk", + require "farm-arum", + require "farm-yotoi-fruit", + require "farm-bioreserve", +} -local function add_launch_products(product_data) - launch_results[product_data.name] = product_data +py.on_event(py.events.on_init(), function() + storage.smart_farm_landfill_data = storage.smart_farm_landfill_data or {} + -- add launch products for later reference + for _, launch_products in pairs(farm_data) do + remote.call("py_smart_farming", "add_launch_products", launch_products) + end +end) + +script.on_load(function() + -- add launch products for later reference + for _, launch_products in pairs(farm_data) do + remote.call("py_smart_farming", "add_launch_products", launch_products) + end +end) + +local function get_fence_positions(entity) + local position = entity.position + position.y = position.y - 15 + local fence_positions = {} + for x = -12, 12 do + fence_positions[#fence_positions+1] = {position.x + x, position.y + 13} + fence_positions[#fence_positions+1] = {position.x + x, position.y - 13} + end + for y = -13, 13 do + fence_positions[#fence_positions+1] = {position.x + 13, position.y + y} + fence_positions[#fence_positions+1] = {position.x - 13, position.y + y} + end + return fence_positions end -remote.add_interface("py_smart_farming", { - add_rocket_silo = add_rocket_silo, - add_launch_products = add_launch_products -}) +local function get_landfill_positions(entity) + local position = entity.position + position.y = position.y - 15 + local landfill_positions = {} + for x = -12, 12 do + for y = -12, 12 do + landfill_positions[#landfill_positions+1] = {position.x + x, position.y + y} + end + end + return landfill_positions +end py.on_event(py.events.on_built(), function(event) local entity = event.entity - if not rocket_silos[entity.name] then return end + if entity.name ~= "mega-farm" then return end -- finally, added in 2.0.73 entity.send_to_orbit_automatically = true - -- run the on_built function, if exists - if rocket_silos[entity.name].on_built then - rocket_silos[entity.name].on_built(entity) + local surface = entity.surface + + for _, position in pairs(get_fence_positions(entity)) do + if not surface.entity_prototype_collides("wood-fence", position, false) then + surface.create_entity { + name = "wood-fence", + position = position, + force = entity.force + } + end end + + local landfill_tiles = {} + for _, position in pairs(get_landfill_positions(entity)) do + local x, y = position[1], position[2] + + local previous_tile = surface.get_tile(position) + if not previous_tile.valid or previous_tile.prototype.collision_mask.layers.water_tile then goto continue end + if previous_tile.name == "sut-panel" then goto continue end + + landfill_tiles[#landfill_tiles+1] = {name = "landfill", position = position} + + storage.smart_farm_landfill_data[x] = storage.smart_farm_landfill_data[x] or {} + if storage.smart_farm_landfill_data[x][y] then + storage.smart_farm_landfill_data[x][y].depth = storage.smart_farm_landfill_data[x][y].depth + 1 + else + storage.smart_farm_landfill_data[x][y] = {depth = 1, name = previous_tile.name} + end + + ::continue:: + end + surface.set_tiles(landfill_tiles) end) py.on_event(py.events.on_destroyed(), function(event) local entity = event.entity - if not rocket_silos[entity.name] then return end + if entity.name ~= "mega-farm" then return end + + local surface = entity.surface + + for _, position in pairs(get_fence_positions(entity)) do + local fence = surface.find_entity("wood-fence", position) + if fence and fence.force_index == entity.force_index then + fence.destroy() + end + end + + local tiles_to_reset = {} + for _, position in pairs(get_landfill_positions(entity)) do + local x, y = position[1], position[2] + + if not storage.smart_farm_landfill_data[x] or not storage.smart_farm_landfill_data[x][y] then goto continue end + + local data = storage.smart_farm_landfill_data[x][y] + data.depth = data.depth - 1 - -- run the on_destroyed function, if exists - if rocket_silos[entity.name].on_destroyed then - rocket_silos[entity.name].on_destroyed(entity) + if data.depth > 0 then goto continue end + tiles_to_reset[#tiles_to_reset + 1] = {name = data.name, position = position} + + storage.smart_farm_landfill_data[x][y] = nil + if table_size(storage.smart_farm_landfill_data[x]) == 0 then + storage.smart_farm_landfill_data[x] = nil + end + + ::continue:: end + + if #tiles_to_reset == 0 then return end + surface.set_tiles(tiles_to_reset, true, false, false, true) end) ---@param event EventData.on_rocket_launched py.on_event(defines.events.on_rocket_launched, function(event) local silo = event.rocket_silo --[[@as LuaEntity]] if not silo or not silo.valid then return end -- silo died after launch started - if not rocket_silos[silo.name] then return end + if silo.name ~= "mega-farm" then return end local satellite = event.rocket.cargo_pod.get_inventory(defines.inventory.cargo_unit).get_contents()[1] if not satellite then return end - rocket_silos[silo.name].on_launch(silo, launch_results[satellite.name]) -end) + local crop_results = launch_results[satellite.name] + local surface = silo.surface + local position = silo.position + position.y = position.y - 15 + local yield + local recipe_name = silo.get_recipe().name + for _, recipe in pairs(crop_results.recipes) do + if recipe.recipe_name == recipe_name then + yield = recipe.crop_output + break + end + end + if not yield then return end + + local is_alien_biomes = script.active_mods["alien-biomes"] or script.active_mods["combat-mechanics-overhaul"] + for x = -11, 11 do + for y = -11, 11 do + local ore_location = {position.x + x, position.y + y} + ---@diagnostic disable-next-line: missing-parameter, param-type-mismatch + if is_alien_biomes or not surface.get_tile(ore_location).collides_with("resource") then + local ore = surface.find_entity(crop_results.crop, ore_location) + + if ore then + ore.amount = ore.amount + yield + else + surface.create_entity { + name = crop_results.crop, + position = ore_location, + amount = yield, + force = "neutral" + } + end + end + end + end + + for _, harvester in pairs(surface.find_entities_filtered { + area = {{position.x - 12, position.y - 12}, {position.x + 12, position.y + 12}}, + name = {"harvester", "flora-collector-mk01", "flora-collector-mk02", "flora-collector-mk03", "flora-collector-mk04"} + }) do + harvester.update_connections() + local control_behavior = harvester.get_or_create_control_behavior() --[[@as LuaControlBehavior]] + if control_behavior.circuit_read_resources then + control_behavior.circuit_read_resources = false + control_behavior.circuit_read_resources = true + end + end +end) \ No newline at end of file