BioInd.writeDebug("Entered control_arboretum.lua") ---Arboretum Stuff local Event = require('__kry_stdlib__/stdlib/event/event').set_protected_mode(false) -- If a recipe with NORMAL FERTILIZER is used, don't fertilize tiles set have "true" -- set! (Fertile tiles set to true in this table can't be made more fertile with -- normal fertilizer, and nothing should grow on the other tiles.) local Terrain_Check_1 = { ["grass-1"] = true, -- Fertility: 100% ["grass-3"] = true, -- Fertility: 85% ["vegetation-green-grass-1"] = true, -- Fertility: 100% ["vegetation-green-grass-3"] = true, -- Fertility: 85% } -- If a recipe with ADVANCED FERTILIZER is used, don't fertilize tiles set have "true" set! -- (Fertile tiles in this table can't be made more fertile, and nothing should grow on the -- the others tiles!) local Terrain_Check_2 = { ["grass-1"] = true, -- Fertility: 100% ["vegetation-green-grass-1"] = true, -- Fertility: 100% } local plant_radius = 75 -- Different tiles are used if AlienBiomes is active local AB, terrain_name_g1, terrain_name_g3 -- OmniFluid replaces all fluids with items, so the arboretum won't have a fluidbox! local function get_new_position(pos) pos = BioInd.normalize_position(pos) or BioInd.arg_err("nil", position) local xxx = math.random(-plant_radius, plant_radius) local yyy = math.random(-plant_radius, plant_radius) return { x = pos.x + xxx, y = pos.y + yyy } end -- Check that all ingredients are available! local function check_ingredients(arboretum) local recipe = arboretum.get_recipe() if not recipe then --game.print("No recipe set on arboretum") return nil end --game.print("Recipe name: " .. recipe.name) local need = storage.bi_arboretum_recipe_table[recipe.name] if not need then --game.print("No recipe data found for " .. recipe.name) return nil end local function check(need, have) for name, amount in pairs(need or {}) do if not (have and have[name]) or (have[name] < amount) then --game.print("Missing ingredient " .. name .. " (have " .. (have[name] or 0) .. " of " .. amount .. ")") return false end end return true end local inventory = arboretum.get_inventory(defines.inventory.assembling_machine_input) local inv_contents_raw = inventory and inventory.get_contents() or {} -- Check if inv_contents_raw is a map or list, convert if needed local function is_map(t) if type(t) ~= "table" then return false end for k, v in pairs(t) do if type(k) ~= "string" or type(v) ~= "number" then return false end end return true end local inv_contents if is_map(inv_contents_raw) then inv_contents = inv_contents_raw else -- Convert list of item stacks to map inv_contents = {} for _, item in pairs(inv_contents_raw) do inv_contents[item.name] = (inv_contents[item.name] or 0) + item.count end end local fluid_contents = arboretum.get_fluid_contents() or {} --game.print("Inventory contents (map): " .. serpent.line(inv_contents)) --game.print("Fluid contents: " .. serpent.line(fluid_contents)) return need and check(need.items, inv_contents) and check(need.fluids, fluid_contents) and { ingredients = need, name = recipe.name } or nil end local function consume_ingredients(arboretum, need) local inventory = arboretum.get_inventory(defines.inventory.assembling_machine_input) for item, i in pairs(need.items or {}) do inventory.remove({ name = item, count = i }) BioInd.writeDebug("Removed %s (%s)", { item, i }) end BioInd.show("Inventory", inventory.get_contents() or "nil") for fluid, f in pairs(need.fluids or {}) do arboretum.remove_fluid({ name = fluid, amount = f }) BioInd.writeDebug("Removed %s (%s)", { fluid, f }) end BioInd.show("Fluid contents", arboretum.get_fluid_contents() or "nil") end local function set_tile(current, target, surface, position) if current ~= target then surface.set_tiles( { { name = target, position = position } }, true, -- correct_tiles true, -- remove_colliding_entities true, -- remove_colliding_decoratives true -- raise_event ) end end function Get_Arboretum_Recipe(ArboretumTable, event) BioInd.writeDebug("Entered function Get_Arboretum_Recipe(%s, %s)", { ArboretumTable, event }) if not ArboretumTable then BioInd.writeDebug("%s is not a valid ArboretumTable. Leaving immediately!") return end local arboretum = ArboretumTable.base local new_position, currentTilename local pos, surface, Inventory, stack -- 'AlienBiomes' is a bool value -- we don't want to read it again if it's false, -- but only if it hasn't been set yet! AB = storage.compatible.AlienBiomes terrain_name_g1 = terrain_name_g1 or (AB and "vegetation-green-grass-1" or "grass-1") terrain_name_g3 = terrain_name_g3 or (AB and "vegetation-green-grass-3" or "grass-3") local check = check_ingredients(arboretum) local ingredients, recipe_name if check then --game.print("There are ingredients") ingredients, recipe_name = check.ingredients, check.name else --game.print("No ingredients") end if ingredients then local create_seedling, new_plant pos = BioInd.normalize_position(arboretum.position) or BioInd.arg_err("nil", "position") surface = arboretum.surface -- Just plant a tree and hope the ground is fertile! if recipe_name == "bi-arboretum-r1" then BioInd.writeDebug(tostring(recipe_name) .. ": Just plant a tree") --- 10 attempts to find a random spot to plant a tree and/or change terrain for k = 1, 10 do new_position = get_new_position(pos) new_plant = { name = "seedling", position = new_position, force = "neutral" } if surface.can_place_entity(new_plant) then consume_ingredients(arboretum, ingredients) create_seedling = surface.create_entity(new_plant) seed_planted_arboretum(event, create_seedling) --- After sucessfully planting a tree, break out of the loop. break else BioInd.writeDebug("Can't plant here (attempt %s)", k) end end -- Fertilize the ground with normal fertilizer. Ignore tiles listed in Terrain_Check_1! elseif recipe_name == "bi-arboretum-r2" then BioInd.writeDebug(tostring(recipe_name) .. ": Just change terrain to grass-3 (basic)") for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain new_position = get_new_position(pos) currentTilename = surface.get_tile(new_position.x, new_position.y).name -- We need to fertilize the ground! if Bi_Industries.fertility[currentTilename] and not Terrain_Check_1[currentTilename] then consume_ingredients(arboretum, ingredients) BioInd.writeDebug("%s: Changing terrain from %s to %s (%s)", { k, currentTilename or "unknown tile", terrain_name_g3, serpent.line(new_position) }) set_tile(currentTilename, terrain_name_g3, surface, new_position) --- After sucessfully changing the terrain, break out of the loop. break else BioInd.writeDebug("%s: Can't change terrain (%s)", { k, currentTilename or "unknown tile" }) end end -- Fertilize the ground with advanced fertilizer. Ignore tiles listed in Terrain_Check_2! elseif recipe_name == "bi-arboretum-r3" then BioInd.writeDebug(tostring(recipe_name) .. ": Just change terrain to grass-1 (advanced)") for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain new_position = get_new_position(pos) currentTilename = surface.get_tile(new_position.x, new_position.y).name if Bi_Industries.fertility[currentTilename] and currentTilename ~= terrain_name_g1 then consume_ingredients(arboretum, ingredients) BioInd.writeDebug("%s: Changing terrain from %s to %s (%s)", { k, currentTilename or "unknown tile", terrain_name_g1, serpent.line(new_position) }) set_tile(currentTilename, terrain_name_g1, surface, new_position) --- After sucessfully changing the terrain, break out of the loop. break else BioInd.writeDebug("%s: Can't change terrain (%s)", { k, currentTilename or "unknown tile" }) end end -- Fertilize the ground with normal fertilizer. Ignore tiles listed in Terrain_Check_1! -- Also plant a tree. elseif recipe_name == "bi-arboretum-r4" then BioInd.writeDebug(tostring(recipe_name) .. ": Plant Tree AND change the terrain to grass-3 (basic)") for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain new_position = get_new_position(pos) currentTilename = surface.get_tile(new_position.x, new_position.y).name new_plant = { name = "seedling", position = new_position, force = "neutral" } -- Test to see if we can plant if surface.can_place_entity(new_plant) and Bi_Industries.fertility[currentTilename] then consume_ingredients(arboretum, ingredients) -- Refund fertilizer -- no need to waste it on fertile ground! if Terrain_Check_1[currentTilename] then arboretum.insert({ name = "fertilizer", count = ingredients.items.fertilizer }) BioInd.writeDebug("Refunded fertilizer!") end set_tile(currentTilename, terrain_name_g3, surface, new_position) create_seedling = surface.create_entity(new_plant) seed_planted_arboretum(event, create_seedling) --- After sucessfully planting a tree or changing the terrain, break out of the loop. break else BioInd.writeDebug("%s: Can't change terrain and plant a tree (%s)", { k, currentTilename or "unknown tile" }) end end -- Fertilize the ground with advanced fertilizer. Ignore tiles listed in Terrain_Check_2! -- Also plant a tree. elseif recipe_name == "bi-arboretum-r5" then BioInd.writeDebug(tostring(recipe_name) .. ": Plant Tree and change the terrain to grass-1 (advanced)") for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain new_position = get_new_position(pos) currentTilename = surface.get_tile(new_position.x, new_position.y).name new_plant = { name = "seedling", position = new_position, force = "neutral" } if surface.can_place_entity(new_plant) and Bi_Industries.fertility[currentTilename] then consume_ingredients(arboretum, ingredients) -- Refund fertilizer -- no need to waste it on fertile ground! if Terrain_Check_2[currentTilename] then arboretum.insert({ name = "bi-adv-fertilizer", count = ingredients.items["bi-adv-fertilizer"] }) BioInd.writeDebug("Refunded advanced fertilizer!") end set_tile(currentTilename, terrain_name_g1, surface, new_position) create_seedling = surface.create_entity(new_plant) seed_planted_arboretum(event, create_seedling) --- After sucessfully planting a tree or changing the terrain, break out of the loop. break else BioInd.writeDebug("%s: Can't change terrain and plant a tree (%s)", { k, currentTilename or "unknown tile" }) end end else BioInd.writeDebug("Terraformer has no recipe!") end end end