Event on_chunk_generated

Place to get help with not working mods / modding interface.
Post Reply
silenceko
Burner Inserter
Burner Inserter
Posts: 10
Joined: Mon Apr 11, 2016 12:07 pm
Contact:

Event on_chunk_generated

Post by silenceko »

Hi guys, I have a question and hope you can help me:


How is the event on_chunk_generated called?

I expected it to be called once a chunk is generated for the first time. Not, if a chunk is updated.
I wrote the following code:

Code: Select all

script.on_event(defines.events.on_chunk_generated, function(event)
    local entities = game.surfaces[1].find_entities_filtered{area = event.area, name = global.Ore} 

    for i=1,#entities,1 do
       table.insert(global.oreList, entities[i])
    end
	
	global.numChunks = global.numChunks + 1 
	
	-- DebugInfo
	if global.TDebug == true then
		game.print("Number of Chunks: "..tostring(global.numChunks))
	end
	
end) -- .on_chunk_generated
I was just standing after gameload und the counter for the chunks seemed to raise endlessly. I quit the game with a count of 400+
I expected it to stop somewhere. Because no more chunks should be generated without any movement of the player to the fog of war?
Actually, it seems that the counter raised every second.

I am aming for a chunkiteration, while my calculations are restricted to work in one chunk at a time only.

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

Re: Event on_chunk_generated

Post by eradicator »

When you start a new map the game will generate the map in background for a while, instead of doing it all before you can start to play. You can force immediate generation of all outstanding chunks with LuaSurface.force_generate_chunk_requests()

If you want to iterate over all chunks you should use
https://lua-api.factorio.com/latest/Lua ... get_chunks
https://lua-api.factorio.com/latest/Lua ... rator.html

If your logic only processes one chunk at a time anyway you should do it directly in the event to evenly distribute the processing cost and prevent micro-stutter.
silenceko wrote:
Sat Jun 15, 2019 6:42 pm
Because no more chunks should be generated without any movement of the player to the fog of war?.
Yes. But staying within the same chunk all the time makes the game pretty boring :p
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

silenceko
Burner Inserter
Burner Inserter
Posts: 10
Joined: Mon Apr 11, 2016 12:07 pm
Contact:

Re: Event on_chunk_generated

Post by silenceko »

When you start a new map the game will generate the map in background for a while, instead of doing it all before you can start to play.
So this seems to be the point then. THX!
If you want to iterate over all chunks you should use
https://lua-api.factorio.com/latest/Lua ... get_chunks
https://lua-api.factorio.com/latest/Lua ... rator.html
That was the plan ;)
If your logic only processes one chunk at a time anyway you should do it directly in the event to evenly distribute the processing cost and prevent micro-stutter.
Which event are you talking about? I need to constantly update the chunks while playing. But I dont need an instand update of all. Therefore cycling through chunks seems to be the best (in sense of performance) way.

TheSAguy
Smart Inserter
Smart Inserter
Posts: 1449
Joined: Mon Jan 13, 2014 6:17 pm
Contact:

Re: Event on_chunk_generated

Post by TheSAguy »

I'm glad I saw this post.
I basically have to do something similar.

There are two things I'd like the do.
1. Each time a new chunk is generated, see if the're is Copper on it and if so, create a enemy spawner on it.
2. Once every 10 min, get a total of all the copper on the map. (so that would be on revealed chunks.)

So for Nr 1. I assume I should use the code silenceko has, correct?

Code: Select all

script.on_event(defines.events.on_chunk_generated, function(event)
    look_for_copper = game.surfaces[1].find_entities_filtered{area = event.area, name = "copper-ore"} 

        for i=1,#look_for_copper ,1 do
      spawn_spawner = game.surfaces[1].create_entity({name = "biter-spawner", position = look_for_copper[i].position? , force = game.forces.enemy})
    end
	
end) -- .on_chunk_generated
Not exactly sure how it find the center of the ore patch for position?
Is this the best way to handle #1?

Not sure what to do with #2. Will it cause lag to run through all chunks at once counting the ore?

Any help appreciated.
Thanks.

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

Re: Event on_chunk_generated

Post by eradicator »

silenceko wrote:
Sat Jun 15, 2019 7:28 pm
If your logic only processes one chunk at a time anyway you should do it directly in the event to evenly distribute the processing cost and prevent micro-stutter.
Which event are you talking about? I need to constantly update the chunks while playing. But I dont need an instand update of all. Therefore cycling through chunks seems to be the best (in sense of performance) way.
I meant on_chunk_generated. But if you need to process each chunk more than once afterwards that doesn't help. If this is some kind of ore-remaining-counter i'd recommend to ignore which resource entity is in what chunk and just iterate over the entities directly.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

silenceko
Burner Inserter
Burner Inserter
Posts: 10
Joined: Mon Apr 11, 2016 12:07 pm
Contact:

Re: Event on_chunk_generated

Post by silenceko »

TheSAguy wrote:
Sun Jun 16, 2019 12:36 am

There are two things I'd like the do.
1. Each time a new chunk is generated, see if the're is Copper on it and if so, create a enemy spawner on it.
2. Once every 10 min, get a total of all the copper on the map. (so that would be on revealed chunks.)

So for Nr 1. I assume I should use the code silenceko has, correct?

Code: Select all

script.on_event(defines.events.on_chunk_generated, function(event)
    look_for_copper = game.surfaces[1].find_entities_filtered{area = event.area, name = "copper-ore"} 

        for i=1,#look_for_copper ,1 do
      spawn_spawner = game.surfaces[1].create_entity({name = "biter-spawner", position = look_for_copper[i].position? , force = game.forces.enemy})
    end
	
end) -- .on_chunk_generated
Not exactly sure how it find the center of the ore patch for position?
Is this the best way to handle #1?

Not sure what to do with #2. Will it cause lag to run through all chunks at once counting the ore?
#1
the found ore will not be identified as patch. You will get tilepositions. so you could look for adjacent similar tiles and calculate the size of the patch by yourself. Or, what would be my compromise, define an area or offset to the found tile, create a spawner and set a range to ignore other tiles. The array of tiles stored seems not to be ordered, so that you create the spawners on different positions randomly by itself.
Or, since chunks aren't that big, just leave the one spawner there.

#2
this is a big problem. When I do this with just the gamestart, I loose 20 FPS! (with event.onTick and updating all tiles at once every tick)
But, cycling through the array with tiles takes way too long to update all. That is why I am looking for a method to update chunks. But I couldn't figure out yet how to do this.
But if you just want to get the number of oretiles, this works good.

The chunkIterator isn't working how I want it to.

Code: Select all

for chunk in game.surfaces[1].get_chunks() do
	global.chunkCounter = global.chunkCounter + 1
	rendering.draw_text{text=tostring(global.chunkCounter), surface = "nauvis", target = {chunk.x, chunk.y},color = global.cred}
	game.print("chunk drawn")
end -- chunkIterator
This results in following problems:

Image

The tiles are not aligned with the chunks and the amount is too low to fill a chunk, but numbered correctly

Image

with the next iterations, the same tiles are updated plus a few more at the top right
and the FPS drop below 1 after seconds
It seems, that the numbering of the tiles wants to cycle clockwise. That would still not be what I want :/

TheSAguy
Smart Inserter
Smart Inserter
Posts: 1449
Joined: Mon Jan 13, 2014 6:17 pm
Contact:

Re: Event on_chunk_generated

Post by TheSAguy »

silenceko wrote:
Sun Jun 16, 2019 2:51 pm
TheSAguy wrote:
Sun Jun 16, 2019 12:36 am

There are two things I'd like the do.
1. Each time a new chunk is generated, see if the're is Copper on it and if so, create a enemy spawner on it.
2. Once every 10 min, get a total of all the copper on the map. (so that would be on revealed chunks.)

So for Nr 1. I assume I should use the code silenceko has, correct?

Code: Select all

script.on_event(defines.events.on_chunk_generated, function(event)
    look_for_copper = game.surfaces[1].find_entities_filtered{area = event.area, name = "copper-ore"} 

        for i=1,#look_for_copper ,1 do
      spawn_spawner = game.surfaces[1].create_entity({name = "biter-spawner", position = look_for_copper[i].position? , force = game.forces.enemy})
    end
	
end) -- .on_chunk_generated
Not exactly sure how it find the center of the ore patch for position?
Is this the best way to handle #1?

Not sure what to do with #2. Will it cause lag to run through all chunks at once counting the ore?
#1
the found ore will not be identified as patch. You will get tilepositions. so you could look for adjacent similar tiles and calculate the size of the patch by yourself. Or, what would be my compromise, define an area or offset to the found tile, create a spawner and set a range to ignore other tiles. The array of tiles stored seems not to be ordered, so that you create the spawners on different positions randomly by itself.
Or, since chunks aren't that big, just leave the one spawner there.
I got #1 working.

For #2. The game knows how much resources are in each patch if you hover over them. Is there a way to tap into that?
Just add up all the patches of a certain ore the game already tracks??

silenceko
Burner Inserter
Burner Inserter
Posts: 10
Joined: Mon Apr 11, 2016 12:07 pm
Contact:

Re: Event on_chunk_generated

Post by silenceko »

This should work:

Code: Select all

Local amountAllCopper=0
look_for_copper = game.surfaces[1].find_entities_filtered{name = "copper-ore"} -- without area, whole map ist searched, even undiscovered

        for i=1,#look_for_copper ,1 do
               allCopperAmount = allCopperAmount + look_for_copper[i].amount
    end
	
But this is not limited to chunks or patches.
An easy way could be, to create an area as range of the first found oretile. The range should then be large enough - maybe, +- 50 tiles?
A range depending on the mapsettings for patchsizes would be great, this should cover RSO too.
But several tiles could slip through then.

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

Re: Event on_chunk_generated

Post by eradicator »

@silenceko

> Loose 20 UPS
Well, that's just the reality. If you do a huge load of work every tick it's gonna cost performance. And if you do it distributed it's gonna be slow. There's no method around it. If your mod is not secret then telling what you're actually trying to do would make helping easier.

> Tiles not aligned with chunks.
The chunk iterator returns chunk coordinates, not positions. You'll have to multiply with 32 (tiles per chunk) to get positions.

> Cover RSO
Not so sure. I think i heared RSO has a delay after on_chunk_generated until it creates ores.

@TheSAguy

> To me it looks like the game doesn't know how large a patch is. But it is really really fast at counting tiles. You can see the map counter increasing if you have a very large ore patch. I.e. if you paint a 10x10 chunks sized patch with the editor.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

mrvn
Smart Inserter
Smart Inserter
Posts: 5709
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: Event on_chunk_generated

Post by mrvn »

Some more info about the starting chunks:

At first an area around the player is charted because that part is directly visible where the player stands. This doesn't cover all of the minimap though. After that chunks are charted in a spiral over time in the background. Firs this covers more chunks for the minimap that will be actually visible. But the game doesn't stop there. Pollution spreads beyond the visible part of the map. And aliens spawn outside the visible parts of the map too. Those chunks need to be generated for both of those to work even though on the map the chunks remain black.

This gives a rather large area around the starting position that needs to be generated. As said only a small area is force generated at the start and the rest in the background. One chunk every X ticks. That causes the chunk count to increase for quite a while after the game started even if the player doesn't move. If he does some chunks will be force generated (if not already done in the background) and even more chunks will be queued up for generation in the background.

So be prepared to stand around quite a while before chunk generation finishes or force the generation.

silenceko
Burner Inserter
Burner Inserter
Posts: 10
Joined: Mon Apr 11, 2016 12:07 pm
Contact:

Re: Event on_chunk_generated

Post by silenceko »

eradicator wrote:
Mon Jun 17, 2019 7:04 am
@silenceko

If your mod is not secret then telling what you're actually trying to do would make helping easier.
Here it is:
viewtopic.php?f=25&t=72141&p=437064#p437064

Post Reply

Return to “Modding help”