Mining drill for trees

This is the place to request new mods or give ideas about what could be done.
mg79
Burner Inserter
Burner Inserter
Posts: 18
Joined: Mon Apr 24, 2017 5:32 pm
Contact:

Mining drill for trees

Post by mg79 »

Is it possible to create a building that automatically harvests any tree around it? Like a mining drill except it affects a much larger area, removes trees within the affected area and outputs raw wood?

And before anyone says "just use bots" I'm picturing something early game that could be used as an early source of fuel before you have access to bots.

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Mining drill for trees

Post by darkfrei »

May be raw wood ore? Something like stone ore, that can be mined from stones or from fields.

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Mining drill for trees

Post by eradicator »

Anything's possible with scripts (:
  1. Cache a list of trees around the building in on_built
  2. Sort list by distance of each tree
  3. Every few ticks catch the first (closest) tree from the list, kill it and put the wood into the machine

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Mining drill for trees

Post by darkfrei »

eradicator wrote:Anything's possible with scripts (:
  1. Cache a list of trees around the building in on_built
  2. Sort list by distance of each tree
  3. Every few ticks catch the first (closest) tree from the list, kill it and put the wood into the machine
How to place the mining drill without ore patch?
Energy consumption?

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Mining drill for trees

Post by eradicator »

darkfrei wrote:How to place the mining drill without ore patch?
assembling-machine
darkfrei wrote:Energy consumption?
In step 3) substract energy from the assembling-machines energy buffer.

User avatar
Optera
Smart Inserter
Smart Inserter
Posts: 2915
Joined: Sat Jun 11, 2016 6:41 am
Contact:

Re: Mining drill for trees

Post by Optera »

Even if you said no bots, I say use bots.

Make the mining entity a roboport with an logistics area covering less than it's base so they don't connect.
Give it a hidden logistic chest as output and a hidden unkillable bot to mine.
Make a script that marks trees in the construction area for deconstruction when the entity is placed.

This should be a lot more lightweight on ups than a script running every n ticks removing trees and adding the wood.

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Mining drill for trees

Post by eradicator »

Treefarm-lite (from 0.13 times?) used robots to farm trees. It was horrible. With just one bot and one construction order it might be less bad but there's still problems with that:
  • You have a roboport with robot-docking-capability that will connect to your future robot network. Possible fix: Use a bot that requires no energy and remove the docking port.
  • And you use up part of the robot-task-queue. Possible fix don't mark all the trees at once, but then you're back to on_tick.
  • And you use a logistic chest that will connect to any other logistic network that happens to cover it when a normal roboport is "too close". Possible fix: Put it on a different force, and voila you're back to on_tick again.
  • Oh, and if your wood-chopping-robot-port loses power the hidden robot might migrate into your main network. Possible fix: on_tick check for lost robots.
Honestly. A script that kills a single tree every 5 seconds or so...is not a major UPS drain.

User avatar
Optera
Smart Inserter
Smart Inserter
Posts: 2915
Joined: Sat Jun 11, 2016 6:41 am
Contact:

Re: Mining drill for trees

Post by Optera »

All your points are valid if you use it in conjucture with roboports.
However the op explicitly wanted something for pre-roboport game so none of them matter.

By the time roboports become available this whole tree miner entity becomes obsoleted by vanilla roboports anyway regardless of implementation.

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Mining drill for trees

Post by eradicator »

Optera wrote:All your points are valid if you use it in conjucture with roboports.
However the op explicitly wanted something for pre-roboport game so none of them matter.
Doesn't matter. 1) and 4) will still mess with your network even if the entity already chopped up all trees. And you can't guarantee that the player will remove all wood-choppers before placing their first roboport.

User avatar
Optera
Smart Inserter
Smart Inserter
Posts: 2915
Joined: Sat Jun 11, 2016 6:41 am
Contact:

Re: Mining drill for trees

Post by Optera »

1) i explicitly wrote "make the logistic area smaller than entity size" that way it can never connect to another miner
4) set power consumption for the hidden bot to 0 if you're worried about that

mg79
Burner Inserter
Burner Inserter
Posts: 18
Joined: Mon Apr 24, 2017 5:32 pm
Contact:

Re: Mining drill for trees

Post by mg79 »

eradicator wrote:Anything's possible with scripts (:
  1. Cache a list of trees around the building in on_built
  2. Sort list by distance of each tree
  3. Every few ticks catch the first (closest) tree from the list, kill it and put the wood into the machine
Thanks, this seems like a workable way to do it. Since trees never grow back you can just check if the tree is still valid and skip to the next if it's been deleted, then disable the building when the list is empty.

Now to figure out how to actually code it as a complete newbie to Factorio modding. :)

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Mining drill for trees

Post by eradicator »

I was bored and wrote a simple control.lua only demonstration. It makes wooden chests slowly chop up trees around themselfs (one every 5 seconds configurable). It doesn't do any caching at all. It also doesn't do circles because that would require fetching all trees around each, instead of just one. I.e. it would be more expensive, though probably still insignificantly.

Pros:
  • Zero impact on savegame size when all trees in range have been chopped.
  • Zero impact on on_tick once all trees have been chopped.
  • Can be quickly changed to use a different entity.
  • Script impact <0.01ms while active (unless you really spam them)
  • Less than 60 lines of code.
  • Type/Range/Interval configurable in file header
  • Uses new and shiny on_nth_tick
  • It's called "Beavers!" :p.
Cons:
  • Won't work with mods that spawn in new trees (unless they spawn them fast enough).
  • Doesn't support energy consumption yet, though that's trivial to add.
  • Due to usage of on_nth_tick requires care when integrating into existing codebase.
  • All entities updated at once, makes it look less natural.
Code:

Code: Select all

--VERSION 0.0.1
--makes all entities of type beaver_species slowly collect trees around themselfs

local beaver_species   = 'wooden-chest' --this entity is a beaver (needs an inventory)
local beaver_max_range = 24   --in tiles
local beaver_interval  = 5*60 --in ticks

local function unleash_the_beavers(e)
  -- feeds each beaver one tree per interval
  -- print('There are ' .. #global.beavers .. ' beavers alive.')
  for b,beaver in pairs(global.beavers) do
    if not beaver.specimen.valid then
      table.remove(global.beavers,b)
    else
      local territory = {
        {beaver.specimen.position.x-beaver.range,beaver.specimen.position.y-beaver.range},
        {beaver.specimen.position.x+beaver.range,beaver.specimen.position.y+beaver.range}}
      local tree = beaver.specimen.surface.find_entities_filtered{type='tree',limit=1,area=territory}[1]
      if not tree then
        if beaver.range >= beaver_max_range then
          table.remove(global.beavers,b)
        else
          beaver.range = beaver.range + 1
          end
      else
        --can trees actually have more than one type of product?
        local twigs = tree.prototype.mineable_properties.products
        local eaten = 0
        for _,twig in pairs(twigs) do
          beaver.specimen.insert{name=twig.name,count=twig.amount}
          eaten = eaten + 1
          end
        --tree dies only if all twigs fit into the beaver
        --this coult be exploited to gain infinite resources from a single tree
        if #twigs == eaten then tree.die() end
        end
      end
    end
  if #global.beavers == 0 then
    --no more active beavers, get rid of the handler
    global.beavers = nil
    script.on_nth_tick(beaver_interval,nil)
    end
  end

local function prepare_the_beavers()
  if global.beavers then
    script.on_nth_tick(beaver_interval,unleash_the_beavers)
    end
  end

script.on_load(prepare_the_beavers)
script.on_init(prepare_the_beavers)
script.on_configuration_changed(prepare_the_beavers)

script.on_event(
  {defines.events.on_built_entity,
   defines.events.on_robot_built_entity},
  function(e)
    if not e.created_entity.name == beaver_species then return end
    -- print('I saw a beaver!')
    if not global.beavers then global.beavers = {} end
    global.beavers[#global.beavers+1] = {specimen = e.created_entity, range = 5}
    prepare_the_beavers()
    end)  
License: MIT (included in zip file)
Download:
er-beavers_0.0.1.zip
(2.35 KiB) Downloaded 105 times
@OP: If you're new to factorio be advised that i use a self-deactivating on_tick handler here, if done wrong this can quickly cause desyncs in multiplayer (which is also untested so it might already :p). So if you want to modify it's better to switch back to a static handler and accept the slight overhead that causes.

User avatar
dog80
Filter Inserter
Filter Inserter
Posts: 279
Joined: Thu Dec 08, 2016 11:57 pm
Contact:

Re: Mining drill for trees

Post by dog80 »

neat @era

mg79
Burner Inserter
Burner Inserter
Posts: 18
Joined: Mon Apr 24, 2017 5:32 pm
Contact:

Re: Mining drill for trees

Post by mg79 »

eradicator wrote:I was bored and wrote a simple control.lua only demonstration. It makes wooden chests slowly chop up trees around themselfs (one every 5 seconds configurable). It doesn't do any caching at all. It also doesn't do circles because that would require fetching all trees around each, instead of just one. I.e. it would be more expensive, though probably still insignificantly.
That code is a great help, thanks!

I was already hacking away at something, but my thinking had me use an assembler with a fixed recipe that created wood, and before starting each cycle would check if there was a tree within range and if so it would destroy that tree.

I then realized that a) not all trees are created equal, some give more wood than others, and b) there doesn't seem to be an event for when an assembler starts its cycle, so I'd have to check every tick if it was at the start of its cycle.

I think your solution is much more elegant.

edit: Tried installing your beavers and every building spawns beavers now. :)

This function doesn't behave as expected and never returns from the function. I can't see what's wrong with it though. I added some debugging and the strings are clearly not identical yet it's not caught by the if not clause.

Code: Select all

if not e.created_entity.name == beaver_species then return end

mg79
Burner Inserter
Burner Inserter
Posts: 18
Joined: Mon Apr 24, 2017 5:32 pm
Contact:

Re: Mining drill for trees

Post by mg79 »

I found another bug, the check to see if inventory is full doesn't work. I replaced that code with a call to can_insert() instead.

I've added an entity for a harvesting machine, extended from the container type. Is it possible to make a container require power? And is it possible to animate it and start/stop the animation from code? Or would I be better off extending another type?

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Mining drill for trees

Post by eradicator »

It's doing boolean comparison, which always ends in "if true == false". Adding brackets works, as does inequality:

Code: Select all

if not (e.created_entity.name == beaver_species) then return end
if e.created_entity.name ~= beaver_species then return end
mg79 wrote:I found another bug, the check to see if inventory is full doesn't work. I replaced that code with a call to can_insert() instead.
Define "doesn't work". I didn't use can_insert() because that can't check multiple items at once. And a mod can add additional results, like a tree that drops wood and seeds. Also i just noticed that the drop-getting logic doesn't handle probability.
prototype of rock-huge wrote:

Code: Select all

results = {{name = "stone", amount_min = 24, amount_max = 50}, {name = "coal", amount_min = 24, amount_max = 50}},
mg79 wrote:I've added an entity for a harvesting machine, extended from the container type. Is it possible to make a container require power? And is it possible to animate it and start/stop the animation from code? Or would I be better off extending another type?
Nope, containers can't consume energy or be animated. The original idea was to use an assembler and shove the stuff into the output slot. But with the possibility of multiple results...meh. Electric-energy-interface can animate and consume energy (or just supply a buffer). But then you'd need to do a complex entity because it doesn't have an inventory. An assembler with a recipe that turns 1 wood into 1 wood (just to animate)...would have worked, except meh multiple drops. EEI+container looks like the best way if you really want animation.
(Though i can think of some more ugly hacks, like sneakily spawning wood ore, because miners can multi-result...but then you need a seperate ore for every. possible. drop)

mg79
Burner Inserter
Burner Inserter
Posts: 18
Joined: Mon Apr 24, 2017 5:32 pm
Contact:

Re: Mining drill for trees

Post by mg79 »

eradicator wrote:It's doing boolean comparison, which always ends in "if true == false". Adding brackets works, as does inequality:
Define "doesn't work". I didn't use can_insert() because that can't check multiple items at once. And a mod can add additional results, like a tree that drops wood and seeds. Also i just noticed that the drop-getting logic doesn't handle probability.
prototype of rock-huge wrote:

Code: Select all

results = {{name = "stone", amount_min = 24, amount_max = 50}, {name = "coal", amount_min = 24, amount_max = 50}},
It would keep killing trees even if its inventory was full. I don't know if maybe the insert() calls always succeeds even if the inventory was full.

But yeah, multiple drops are a pain in the butt. It would be nice if there was a "generic-machine" type that extended CraftingMachine that was more flexible than the assembling-machine type and could have animation and stuff controlled from lua. :)

I think for now a wood->wood recipe is the least bad way to do it.

mg79
Burner Inserter
Burner Inserter
Posts: 18
Joined: Mon Apr 24, 2017 5:32 pm
Contact:

Re: Mining drill for trees

Post by mg79 »

Ok I got it the way I want it now, through a kludge.

I added a new "Timber" item. If the tree has raw wood, the assembler will add the same amount of timber and destroy the tree, but only if there's less than 5 units of timber in the machine already. It then has a fixed recipe that makes 1 raw wood from 1 timber and takes 1 second. This has the advantage that stumps and dead trees which normally only give 2 wood will also harvest faster. Now harvesting speed is dependent on the machine's crafting speed, so if you're low on power you'll also harvest slower. You could still cheat by taking the timber out of the machine's input to get it to harvest faster, but you still need to process the timber into wood anyway, and you can't just steal raw wood from the input.

The mod doesn't support multiple products from trees. It will simply ignore anything that isn't raw wood, so if you're using arborium or some other mod that adds seeds/saplings you have to harvest them manually. :)

Give it a try.

e: One thing that is still missing is having the building show how big the affected area is during placement. I don't know if it's possible to do that on an assembling-machine?

e2: New version, tiny bugfixes like the recipe not having stupid requirements any more. I still can't get it to sort properly in the crafting list, no matter what I try it places itself after the assembling machine 1...
Last edited by mg79 on Sun Jul 08, 2018 4:05 pm, edited 2 times in total.

mg79
Burner Inserter
Burner Inserter
Posts: 18
Joined: Mon Apr 24, 2017 5:32 pm
Contact:

Re: Mining drill for trees

Post by mg79 »

Now with working migrations scripts too!

https://mods.factorio.com/mod/WoodHarvester

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Mining drill for trees

Post by eradicator »

Factorio API wrote:When adding a mod to an existing save all migration scripts for that mod will be run.
Huh, i was sure they only run when the version changes :D. So many pitfalls...

Also there's a built-in module called "util" so you might want to use a different name in the future to avoid confusion.

Hm..also removed the "harvest closest trees first". The only beauty function i added to the original, because i thought it looked/felt really meh if it starts in some far away corner. Especially if the player is trying to see if it works and doesn't see the far-away trees vanishing.
mg79 wrote: It would keep killing trees even if its inventory was full. I don't know if maybe the insert() calls always succeeds even if the inventory was full.
Well. If you look very very closely... you'll notice that there's no actual check if insert() succeeded or not. I simply forgot that ;). Should check for return value of 0 i guess.

Showing an overlay for arbitrary entities... is a (one?two?...) pending interface request that's getting buried deeper every day. Plase bump if you manage to find it :)

The order string should probably be something like "a[items]-b[wood-harvester]" or "a[items]-b[electric-mining-drill]a". Order strings are just strings. Don't get distracted by the dashes and brackets, they have no special meaning.
mg79 wrote:The mod doesn't support multiple products from trees.
:sadface: Maybe you can drop them on the ground. surface.create_entity{name="item-on-ground",...}. Or spawn a chest alongside the harvester to collect them.

Anyways, congratulations on your first mod.
(Something around here smells like dead beaver ;)

Post Reply

Return to “Ideas and Requests For Mods”