Factorio - posila87
Graphics
  • Fixed player character shadow didn't animate in idle state when not facing north.
Bugfixes
  • Fixed that LuaEntity::splitter_filter would reject a LuaItemPrototype. more
  • Fixed smart entity collision mode in tile editor did not work with offshore pump. more
  • Fixed that modded shortcuts that spawned items not visible in the blueprint library didn't work. more
  • Fixed that technology tooltips didn't show debug tooltip data the same as other tooltips. more
  • Fixed that crafting machines would report as supporting backer names through the Lua API. more
  • Fixed that un-researched recipes couldn't be used while in the map editor. more
  • Fixed that the removed-content GUI didn't include some translations. more
  • Fixed a desync related to invalid rail signal requested to be closed by circuit network. more
Modding
  • Added InserterPrototype::chases_belt_items. more
Scripting
  • Added LuaEntityPrototype::inserter_chases_belt_items read.
  • Added surface to the selected-area events.
  • Changed LuaSurface::spill_item_stack() to return the created entities if any.

You can get experimental releases by selecting the '0.18.x' beta branch under Factorio's properties in Steam.
Factorio - Klonan
Read this post on our website.

Statistics GUI (Klonan, Oxyd)
The statistics GUI (electric network stats, production stats, etc.) is one of the GUIs that has been in the game for a very long time, and has had its functionality fleshed out reasonably over the years. It was not long ago when Twinsen added hovering and highlighting to the graphs.

Given that, and the relatively short timeframe for 1.0 release, the update of the statistics GUI has really just been a style update, no new features or heavy logic rewriting. Oxyd has most of the work done, so we are happy to show some real in-game screenshots of how it looks:



A notable change with the electric stats is that the Satisfaction/Production/Accumulator charge are next to each other in a single row, as opposed to each in a separate row. The label for the exact amount has also been moved to inside of the progress bar, which itself is much thicker.





The production stats are pretty much the same functionality wise. One new button you might spot is the search button.



However there are some problems with the search feature. As you can see, production and consumption frames have a different search box independent from each other. The main problem is when pressing CTRL+F to perform a regular search: How do we know which frame to open? Of course this could lead to different solutions like the use of a cycle for the focus of the search, in which the second time you press CTRL+F the other frame gets the focus. Or both of the search boxes open at the same time but only one gets the focus. Or only one frame gets the focus and the other one works only by pressing the button. But let's face it, these "solutions" are not solid at all and create inconsistency in the main design.

To solve this issue we decided that the simplest way to go is the use of just one search box on the header of the panel. This new location works as a general feature for the entire panel. One single search gives you 2 results, one on each frame. This solution is used in the new character window -to come soon- making it consistent with the whole design of the GUI.



You can also see we took this opportunity to integrate the Kill statistics in with the rest, instead of being its own window with its own hotkey.

The Statistics GUIs will need a few tweaks and polishings here and there before it is ready for release, but unless something unexpected happens you can expect it coming out in a release soon.

Community spotlight - Mod Debugging and Instrument Mode (justarandomgeek)
This topic is a guest post by our community member and mod maker justarandomgeek.

Historically, while developing Factorio mods, you just had to write some code and try it, until you get one of these:



Then you go back and find that spot in your code and try to figure out what went wrong. If the error is particularly confusing, you start sprinkling <tt>log()</tt> or <tt>game.print()</tt> around to try and figure out what the heck is going on. And, of course, when you find the problem, you inevitably forget to clean all of these up, and now you're spamming the log or chat forever.


Well there's your problem! Perhaps a bit constructed...

For the last few months I've been working on a debugger to improve this experience. The first step was to spend some time with the Lua debug library and VSCode's Debug Adapter Protocol making introductions to get them talking to each other. Factorio doesn't give me many options, but Lua's <tt>debug.debug()</tt> and <tt>print()</tt> functions are enough to interact with the (normally invisible) console.

VSCode can launch Factorio and attach itself to this console to inject commands as needed to read and manipulate the state of the running code. This gets us VSCode's debugger interface, with all the pre-built tools for displaying variables, setting breakpoints and stepping through code. Wrapping some of the game's APIs like <tt>remote.call()</tt> and most of <tt>script</tt> to add a little extra special handling, we get nice labels on event handlers in the call stack and a first version of break-on-exception for when things go wrong. I even built some nice detailed variable views for the most common LuaObjects:



But there's a catch, and it's a big one: because of the way Factorio sandboxes mods, the debugger (which is itself a mod, in part) can't actually get to your mod to install all these hooks! The first solution to this is to simply add a line to load the debugger, but this puts us right back where we started with <tt>log()</tt> - you put something in for debugging and forget to remove it.

To solve this problem we need a little help from the API, a way for a mod to hook every other mod. Unfortunately, this level of hooks is too powerful of a capability to be generally available to mods, so it can't really be added to the normal mod API (it allows you to fairly trivially break nearly all assumptions about data lifecycle and mod sandboxing). After some discussion with Rseding, we eventually arrived at Instrument Mode (released with 0.18.10), a special mode which allows a selected mod to hook all the Lua instances Factorio creates, at the cost of disabling multiplayer and only allowing one Instrument at once. This also provides a hook for a better version of break-on-exception.

This gets us all the way to the rich debugger experience: When you run under the debugger, all loaded mods automatically get debug hooks installed for the session (but not permanently), and you can step through the code and examine all your variables!

While I was building tools, I also added some highlighters for locale and changelog files, and validation for changelogs:





And of course, it's a game about automation, so we need some modding workflow automation too:



Modders, please give it a try and let me know what you think!
Factorio - wheybags
Graphics
  • New offshore pump graphics.
Changes
  • Removed the sound effect from the console-only electric-energy-interface.
  • Item localised name takes priority over place-result localised name when showing item's tooltip. more
  • Offshore pump is now buildable on ground tile adjacent to water instead of water tile adjacent to ground.
Bugfixes
  • Fixed that the map generator GUI didn't reset to the correct defaults when changing presets. more
  • Fixed blueprint window sizing for wide blueprints.
  • Fixed some cases of not considering dark background icon when drawing alt mode overlay. more
  • Fixed that burner generator idle_animation and animation could have different frame counts.
  • Fixed icons with overlays were drawn incorrectly when used in sprite widget. more
  • Fixed crash when loading map after removing fluid recipes with indexes. more
  • Fixed spitters would not break from attacking an obstacle when the obstacle moved away. more
Modding
  • Added Instrument Mode to support mod development tools.
  • Added optional burner generator prototype properties always_draw_idle_animation, performance_to_sound_speedup and min_perceived_performance.
  • Added optional offshore pump prototype properties min_perceived_performance, adjacent_tile_collision_box, adjacent_tile_collision_mask and center_collision_mask.
  • Changed offshore pump graphics definition. Old definition will still be accepted, but is deprecated.
Scripting
  • Added optional parameters daytime and water_tick to LuaGameScript::take_screenshot() function.

You can get experimental releases by selecting the 'experimental' beta branch under Factorio's properties in Steam.
Factorio - Klonan
Read this post on our website.

Offshore pump redesign (V453000, Albert)
As one of the last entities which do not have high resolution graphics, the time has come for the offshore pump.

The offshore pump is practically a 1-tile entity, but they must have a 1 tile gap between each other. It is also the only entity placed on a water tile at the moment.

When we changed the way how terrain to water transitions work, we moved the offshore pump to be placed on the water tile. This can result in the pump drawing over terrain in ugly ways.



With the redesign, we took the oppourtunity to move the offshore back onto land, and additionally the pump checks a 2x3 tile water area in order to be buildable.



The new placement rules only applies to newly built pumps. Offshore pumps on existing maps will keep functioning, they’ll just be shifted out from the shore.

There is no blue colour for water integration at the tip of the offshore pump, so the offshore pump will look correct even with unexpected water types (not a big problem in vanilla). The water integration is split to an underwater layer which does not show when the pump gets landfilled over.



In the basic concept, the offshore pump is another type of a pump, so it should be similar to the other pump entity Albert made a few years ago, including the animation and visible fluid in it.

The obvious difference is the connection to water. However we felt that is not different enough and needs more visual balance, so we added a pair of supportive legs.

https://cdn.factorio.com/assets/img/blog/fff-336-offshore-pump.mp4

We are planning to release the new offshore pump graphics with the next release, likely next week.

Mod spotlight - Built in beacons (V453000)
Beacons strongly motivate building in rectangular repeatable patterns. The results generally look clean, but also very predictable and boring. Furthermore, the differences between different recipe builds are only minimal, so the visual difference between builds is minimal.



The issue is, I like to build the opposite of clean and predictable. The factory looking increasingly complicated and harder to expand over time is what keeps me engaged to continue playing a map. When it starts looking easy, I lose interest.

I’ve been trying to solve this for myself by either restricting myself from using Beacons (which is a massive sacrifice of productivity and speed), or by putting the sub-factories with high Beacon counts outside of the starting area, as keeping the organic starting area is key for me.



Eventually I thought about creating a mod that makes machines behave as if they had the maximum possible amount of beacons around them - allowing me to upgrade the starting base, but that also causes higher demand on the throughput of logistics, which the most interesting part - snaking more belts, fitting in more rails.



The mod defines 3 tiers for every producer to simulate beacons with tier 1, 2 or 3 of Speed modules in them. These machines cannot be further affected by normal Beacons and only accept special productivity modules defined by the mod.



Creating the mod was a ton of fun. I rewrote it about 3 times as I was learning how to do it better. I hacked together some basic graphics for it from some special passes (height and Ambient Occlusion) that we use for postproduction in our gfx workflow.

I played with the mod and got some interesting results (imgur album) as I was able to continue building in the starting area instead of refactoring it for Beacons.

Click to view full resolution

Lastly, I wrote a timelapse-screenshot tool. It can either be used by taking a screenshot each N ticks automatically, or in my case I give it a folder with savegames and it takes X number of screenshots, then moves to the next savegame. It's quite crude so I won't release it on the mod portal for now.



Making Beacons disappear into producer machines to allow for more organic bases fits my perverted playstyle, but Beacons actually do bring a lot of interesting motivations to the base game, and it can be a lot of fun to mess with the building rules that Beacons force.

You can find the mod on the mod portal if you are interested.
Factorio - posila87
Features
  • Added Rocket rush scenario. more
Changes
  • Changed Team production team joining system and cleaned up the map sets.
  • Changed Wave defense bounty system and refactored unit spawning logic.
  • Changed fire sticker to deal damage only once per 10 ticks.
Graphics
  • Added big scorch mark which is now used by atomic rocket and nuclear reactor meltdown.
Bugfixes
  • Fixed that fluid energy source effectivity was not shown in the tooltip. more
  • Fixed that the default column ordering in the update-mods GUI didn't match the visual ordering. more
  • Fixed that train could accelerate for one tick into wrong direction when train stop is disabled. more
  • Fixed that minimap would not allow setting temporary train stop when train would have to change movement direction. more
  • Fixed damage value in sticker tooltip was 60 times too small.
  • Fixed icons with overlays were drawn incorrectly when used in rich text. more
  • Fixed PvP error when DEFCON was active alongside normal labs. more
  • Fixed that modded recipes with no products or no ingredients still showed those sections in the recipe tooltip. more
  • Fixed that modded burner generator equipment didn't show pollution in the tooltip. more
  • Fixed teleporting or changing the force of an entity with a control behavior that was connected to the logistic network. more
  • Reverted optimisation that caused inserters picking up items from belts to be slower.
Modding
  • Added support to filter on-damaged trigger effects through the trigger prototype definition.
  • Added secondary_draw_order property to simple-entity prototypes.
  • Added StickerPrototype::damage_interval, defaults to 1.
Gui
  • Updated the window of creating/editing blueprint.
Scripting
  • Added LuaTile::surface read.
  • Added event filtering support to on_sector_scanned and on_entity_cloned.
  • Added "original-damage-amount", "final-damage-amount" and "damage-type" filters to the on_entity_damaged event filters.
  • Added LuaGameScript::is_valid_sprite_path().
  • Removed the required argument from LuaEnity::to_be_deconstructed() because it did nothing.

You can get experimental releases by selecting the '0.18.x' beta branch under Factorio's properties in Steam.
Factorio - Klonan
Read this post on our website.

Team production changes
Improving the Team production challenge was prompted by this Reddit post. Team production was made back in 2016 to test the multiplayer networking of the 0.14 update with a larger number of players without the overhead of having a large factory. Since then it has not really had much love.

So after 4 years of accruing wisdom, I started making some general improvements.

Choose your teams
I think this is one of the main suggestions people had for team production. The scenario just shuffled the players and assigned people randomly, and you could end up all alone playing against your two best friends.

Now I believe anybodies first choice would be to add a GUI to handle this. I will go on about GUIs later, but short story is, I didn't want to add a GUI. They add a lot of complexity, and my development mood these days is to keep things simple and small in scope.

So I added little colored launchpads!



I think it is quite intuitive, you will instantly be able to see which team has which players, you will see what map position you will be in when the round starts, etc. Another benefit is that if you want to spectate, you can simply just not walk onto a launchpad, and use the map view to see what's going on (before, there was a button you would press to join the spectators team).

The idea to use tinted concrete came from Albert, as originally it was just a tinted square rendering over the tiles (which didn't need any new prototypes defined) and it looked very janky. A consequence of this is that we now have colored concrete tiles in the game. There is no item available to place color concrete, but players will be able to access them in the editor mode.

General cleanup
This is the not so glamorous but still important polishing we need to make. Things such as fixing GUI styles, switching the loaders to stack inserters, making sure the map sets are making sense, etc.

I also spent some time making the challenges more predictable, the logic before could give a lot of variance to the difficulty of the production objectives, and make things hard to balance. One problem I see in the future, is that the production challenges are 'hardcoded' for the base game. If I find some more time later I might work on a system to more procedurally create the objectives.

Wave defense changes
I was inspired by some comments a few weeks ago, saying that the Wave defense scenario was a bit of a pushover, especially with a couple of players working together. So I thought an easy adjustment would be to scale the 'wave power' somehow to the number of players. It was a simple change and we released it with 0.18.4 a few weeks ago. Jobs a good'un right?

Well after play-testing it more extensively over the weekend, I realised it wasn't quite so simple...

More biters; more money
A major problem is that the players earn bounty for every biter that it killed. So if I make the waves bigger, then the players earn so much more money, and can buy so many more upgrades, that the scenario is even less challenging than before.

The solution to this is quite abrupt, I just remove the bounty from the units, and this makes the design work better in my eyes:
  • Bounty is only earned from spawners and worms.
  • You can't sit inside your walls and earn money for upgrades; You need to actively go out of your base to earn upgrades.
  • Players could set up infinite money farms by spawn camping the biters; This is no longer possible.

A consequence of this is that the upgrade prices and bounties needed to be rebalanced, which was actually a little bit easier since the number of spawners and worms is way more predictable.

Predictable attack locations
I also noticed that biters spawning would always hit the base defences at the same places very reliably. This is great if you are the player and only want to invest 1 flamethrower turret to repel all the attacks.

https://cdn.factorio.com/assets/img/blog/fff-335-waves-before.mp4

So I added an extra command to the biters orders, that tells them to first go to a random point within the base, and from there go and attack the silo. This means that the positions where biters intersect your defences will be less predictable.

https://cdn.factorio.com/assets/img/blog/fff-335-waves-after.mp4

More wave power; same wave size
Another observation I made is that even though I increased the 'wave power', the number of biters was still being limited by the number of nearby spawners. This was due in part to a mix of me being clever with optimization and wanting to not make the groups too big. In short the spawning would work something like this:
  • Determine the wave power, bases on factors such as wave number, player count, difficulty.
  • Determine how many spawners we spawn from, something between 4 and 15 typically.
  • For each spawner, pick a random number of biters to spawn, between 20 and 30.
  • Spawn the biters, and remove their 'cost' from the wave power. If we have no more wave power we stop.
  • Once we have gone through all spawners, we are done (even if there is a lot of wave power left).
The problem here, is that we are constrained by the spawner count and unit count. Even if wave power was 10x higher, the logic could still just decide to spawn 50 small biters from 4 bases and call it done.

Well okay I was a clever boy, and now lets remove all this complicated logic and keep it simple:
  • Determine the wave power, bases on factors such as wave number, player count, difficulty.
  • Determine how many spawners we spawn from, something between 5 and 20 typically.
  • Divide the wave power by how many spawners we have.
  • Keep spawning units at the spawners until all the wave power is used up.
This way, if we have 10x more wave power, no matter how many bases we spawn from, the wave will be 10x more powerful.

Infinite map option
I had a few requests for this, and it wasn't so hard to add. If enabled, the Wave defense map will be infinite instead of an island, and the only way to win will be to launch a rocket.

New scenario - Rocket rush
Adding a new scenario at this point of development is a surprise to be sure, but hopefully a welcome one. The concept for this is that you are on the 'space platform', and you are preparing to land on the surface, and once on the planet you need to launch a rocket as fast as possible. You start with all technologies unlocked, and some money to buy starting equipment.



Once you and your friends are prepped, you head down to the launchpad to start.



And then that is pretty much it, you get teleported to the surface, and play the game as usual. We can afford to add this scenario because it is so small in scope and so simple, and it took less time to make this new scenario from scratch than updating what we already have. Maybe it is not the best thing since sliced bread, but I am hoping that my small investment of a few weekends will at least give some players a few more hours of enjoyment. I would be interested in adding more 'small scope simple scenarios' in the coming months, if we have enough time. If you have ideas that might fit this definition, please let me know (but no promises).

Damage effect filtering
It is the classic problem, we optimise a system so its 5x faster, and then we use it 5x more. This time it is the case of flamethrowers and particles again. With 0.18 we added the damage effects for entities, and we generally like the way it works. However when this is combined with flamethrowers, we encounter some problems.

https://cdn.factorio.com/assets/img/blog/fff-335-biter-damage.mp4

First you might say, "It doesn't make sense that a burning biter will spurt blood", and I would agree. Second you might say "That is a lot of blood", and I would agree with that too. In fact it is 1,416 damage events worth of blood particles. The way flamethrowers currently work means they do a small amount of damage very frequently, in contrast to say a grenade which does a high amount of damage in a single action. Even with all the particle optimizations, the performance would once again suffer due to the sheer quantity of particles being created.

So Rseding has gone ahead and killed 2/3 birds with 1 stone, and added damage type filtering to the entity damaged and entity died trigger effects. This means for our immediate problem of bloody burning biters, we can just filter the damage effect to not occur if the damage type is fire, which solves it perfectly. In the longer term the benefits are even greater, as we now have the capability to for instance, make custom dying effects for being run over, or damaged by laser, or dying by poison etc.

Well that solves half the problem, but still, 1,400 damage events is still going to cause problems in other cases. A big part of this comes from the 'fire sticker', which applies damage every single tick. Since it lives for 30 seconds, that is 1,800 damage events. So a nice easy change posila has done, is to add a 'damage interval' to the sticker, so that damage is only applied every n ticks. For now we have set the fire sticker to do 10x the damage, but only every 10 ticks, reducing the number of total events for the sticker from 1,800 to 180, a lot more reasonable. (Note, changing this frequency can affect the damage balancing, as the resistances system in Factorio has an absolute reduction and a percentage reduction. In our case, the entities affected by the fire sticker had no absolute fire resistance, so the result is the same.)

All the changes you see here should be released soon, we are in a rhythm now of doing 1 release every week (typically on a Tuesday), and everything you see here is pretty much done (but anything can change!).
Factorio - posila87
Graphics
  • New visuals for poison capsule effect.
  • New dying effect and remnants for flying robots.
Sounds
  • Entity destroyed alert - Sound softened and lowered in volume.
  • Weapon sounds (WIP) - new Pistol, Submachine gun, Gun turret, Laser turret.
  • Logistic chests open sound (WIP).
  • Poison capsule cloud (WIP).
Bugfixes
  • Fixed that reordering heat buffers during the same tick a different heat buffer was built would leave the heat buffer state corrupted. more
  • Fixed that entity sounds with probabilities would loop forever once they started playing. more
  • Fixed rocket silo tooltip did not include contents of the rocket result inventory. more
  • Fixed that styles were applied to wrong slot in a filtered train view. more
  • Fixed that server authentication would fail if both the token and username and password were provided. more
  • Fixed that changing inserter pickup/dropoff through mods didn't work correctly. more
  • Fixed that combat robots had their fire resistance overwritten. more
  • Fixed that rolling stocks were not pulled correctly when train was moving through curved rails. more
  • Fixed that LuaEntityPrototype::burner_prototype didn't work for the burner-generator entity type. more
  • Fixed janky construction robot flying animation during repair work. more
Scripting
  • Added optional LuaItemStack::build_blueprint raise_built.
  • Added LuaInventory::find_empty_stack(), count_empty_stacks(), and get_insertable_count().
  • Added LuaEntityPrototype::heat_energy_source_prototype, fluid_energy_source_prototype, and void_energy_source_prototype read.
  • Added LuaGameScript::encode_string() and decode_string().
  • Added on_player_set_quick_bar_slot.
  • Added on_pre_player_toggled_map_editor.
  • Removed LuaPlayer::name write. more
  • Removed core lualib util.encode() and util.decode().

You can get experimental releases by selecting the '0.18.x' beta branch under Factorio's properties in Steam.
Factorio - Klonan
Read this post on our website.

Poison cloud (Ernestas, posila)
The poison cloud animation is a placeholder spritesheet (that kovarex found somewhere on the internet), we have wanted to improve it for a long time, but since it was always such a small detail other things took priority. Well now is the time to finish everything, big and small.

https://cdn.factorio.com/assets/img/blog/fff-334-old-cloud.mp4

Some of the problems we see with the old placeholder animation:
  • The edge (where damage will apply) is not clearly defined
  • The center strongly obstructs vision underneath the animation
  • It breaks the perspective/height illusion with its very circular shape

The new animation was done quickly and without the need of any large changes to the Factorio engine. This is the mindset we are in these days, use the engine features we already have to finish things quickly and without trouble, and we try to stop ourselves going crazy with more detail.

https://cdn.factorio.com/assets/img/blog/fff-334-new-cloud.mp4

The smoke capsule itself spawns a bunch of smaller dummy entities which do the smoke drawing, while the damage is kept consistent by only using the central smoke cloud to apply damage.

Flying robot die effect (Dom, Klonan)
Unlike the poison cloud, the flying robots dying was never something that we felt strongly about changing, they just exploded and poofed out of existence. With the new particle system we had an idea of using a particle to show the robot falling to the ground. The experimentation was quick and effective, and we liked the effect. Using the 16 directions of the flying robot sprites, we can create a 16 frame animation of the robot spinning for free, which is a good trick.

https://cdn.factorio.com/assets/img/blog/fff-334-robot-dying.mp4

To complete the effect we needed to pay a bit of a price by creating some remnants on the ground. Dom didn't take long to model and render 3 remnant variations for each robot. Even if you don't see the robots falling and dying actively, the corpses on the ground can really add to the battlefield.



These new effects have been merged in our master branch now, so you can expect to play with them with the next 0.18 experimental release, likely early next week.
Factorio - posila87
Bugfixes
  • Fixed a crash related to multiple blocks reserved for different trains but later merged by placing a rail. more
  • Fixed that construction robots were missing their working animation. more
  • Fixed circuit network debug visualization text overlap. more
  • Fixed the circuit network tooltip backgrounds didn't highlight correctly. more
  • Fixed that script.active_mods wouldn't be accurate when loading save files in some cases. more
  • Fixed that the sync-mods-with-save feature would try to download mods it didn't need to in some cases. more
  • Fixed that trains pathfinder could create non contiguous path in case of single segment cycle with a junction. more
  • Fixed possible crash when units were attacking rails with train on them. more
  • Fixed pump would consume energy and play animation when it tried to transfer very small amount of fluid but failed to do so. more
  • Fixed creating fire entity by trigger effect invoked by a particle would crash the game.
  • Fixed overriding LuaSurface::brightness_visual_weight would cause light map to appear in map view. more
Scripting
  • Building entities with from items with 0 health will set the entity to 1 health instead of 0. more
  • Added LuaGameScript::reset_time_played() which will reset the 'Time played' to 0.

You can get experimental releases by selecting the '0.18.x' beta branch under Factorio's properties in Steam.
Factorio - Klonan
Read this post on our website.

Hello,
We released 0.18.4 this week, same old same old, more bugfixes, more bugs, more changes. At this stage of development, not many interesting things are happening, we are just polishing what we have.

Minor terrain render optimization (posila)
Just a couple days before the release of 0.18.0 I had an epiphany about a terrain rendering problem that was bugging me for a really long time. When rendering terrain, we reuse the texture from the previous frame. How this was always done, is that we would render the texture shifted to the new position, fill up the gap, and then copy the final result back into the texture for reuse in next frame. So what was bugging me about this? This simple operation would result in rasterizing 2 screens worth of pixels. While that is not a problem for at least half decent GPUs from the past decade, it's a significant work load for integrated GPUs, which in general have an order of magnitude lower memory bandwidth than dedicated GPUs. It could also be equally bad for old low-end dedicated GPUs.

One of the extreme examples is the Intel HD Graphics 3000 - an integrated GPU on the Sandy Bridge CPU architecture. When you sit still and the terrain can be reused without shifting, it would take 'just' 2 milliseconds to copy it to the game view. But when you started to move, the GPU time to render the terrain could go up to 5 milliseconds. And that is only at 1600x900 resolution. Not even 1080p. So, it was bothering me we were spending nearly 1/3rd of a frame time (16.66 ms) to render the terrain, when the engine has much more work to do to render the rest of the game (for comparison GeForce GTX 750Ti or Radeon R7 360 would do the same under 0.5 ms at 1080p).

The realization I had, was that I can 'scroll' the buffer texture. If I remember the offset of the top left corner, I can un-scroll it to the game view, and then instead of copying all the terrain back to the buffer, we can just adjust the offset and update the parts that changed. So, the number of pixels copied is proportional to how much the terrain scrolled. It is so simple I am embarrassed not to have figured this out years ago.

https://cdn.factorio.com/assets/img/blog/fff-333-tile-buffer.mp4

Most people could not have noticed this optimization, as most GPUs people have nowadays did the un-optimal thing in a fraction of a millisecond already. But it still made me very happy to be finally able to remove this inefficiency. Contemporary integrated GPUs are also significantly faster, and while it might not be as much of a challenge to render the game for them, they do share some resources with the CPU - be it the last level of cache, or CPU cooler, so the integrated GPU working hard may cause the CPU to slow down.

However, the point I wanted to illustrate by this post is how broad a range of GPUs there is. People see a 2D game and expect to be able to play it on essentially anything. If we want to live up to that expectations, we have to impose a lot of limitations on ourselves, because 'anything' also includes a couple orders of magnitude slower GPU than is found in an average gaming computer of today. CPUs got a lot faster in the last decade too, but mostly due to increasing the number of cores and adding wider vector computation units. They didn't get that much faster when executing serial code, which is unfortunately most of Factorio's game code. So if you play the game on a laptop with a Core 2 Duo and GeForce 320M, you'll run into framerate issues due to the weak GPU much sooner than a UPS slowdown due to the old CPU.

Side note: You might ask, why do we bother with caching the terrain in the first place and not just re-render it from scratch every frame. Short answer is - because Factorio's terrain rendering is insane due to its complicated tile transition rules, and re-rendering it every frame is just not fast enough.
...