1. Factorio
  2. News

Factorio News

Version 0.17.55 released

Bugfixes


  • Fixed that some of the textboxes didn't allow to write characters bound for different actions when focused. more
  • Fixed a desync related to removing rail signal that merges two rail blocks reserved by different trains into one.
  • Fixed that the belt-gap-fill logic could replace splitters/underground belts in some cases. more
Modding


  • Added LuaPlayer::connect_to_server().


You can get experimental releases by selecting the '0.17.x' beta branch under Factorio's properties in Steam.

Friday Facts #302 - The multiplayer megapacket

Read this post on our website.

The multiplayer megapacket


Last month I joined KatherineOfSky's MMO event as a player. I noticed that after we reached a certain number of players, every few minutes a bunch of them got dropped. Luckily for you (but unluckily for me), I was one of the players who got disconnected every, single. time, even though I had a decent connection. So I took the matter personally and started looking into the problem. After 3 weeks of debugging, testing and fixing, the issue is finally fixed, but the journey there was not that easy.

Multiplayer issues are very hard to track down. Usually they only happen under very specific network conditions, in very specific game conditions (in this case having more than 200 players). Even when you can reproduce the issue it's impossible to properly debug, since placing a breakpoint stops the game, messes up the timers and usually times out the connection. But through some perseverance and thanks to an awesome tool called clumsy, I managed to figure out what was happening.

The short version is: Because of a bug and an incomplete implementation of the latency state simulation, a client would sometimes end up in a situation where it would send a network package of about 400 entity selection input actions in one tick (what we called 'the megapacket'). The server then not only has to correctly receive those input actions but also send them to everyone else. That quickly becomes a problem when you have 200 clients. It quickly saturates the server upload, causes packet loss and causes a cascade of re-requested packets. Delayed input actions then cause more clients to send megapackets, cascading even further. The lucky clients manage to recover, the others end up being dropped.

The issue was quite fundamental and took 2 weeks to fix. It's quite technical so I'll explain in juicy technical details below. But what you need to know is that since Version 0.17.54 released yesterday, multiplayer will be more stable and latency hiding will be much less glitchy (less rubber banding and teleporting) when experiencing temporary connection problems. I also changed how latency hiding is handled in combat, hopefully making it look a bit smoother.

The multiplayer megapacket - The technical part

The basic way that our multiplayer works is that all clients simulate the game state and they only receive and send the player input (called Input Actions). The server's main responsibility is proxying Input Actions and making sure all clients execute the same actions in the same tick. More details in FFF-149

Since the server needs to arbitrate when actions are executed, a player action moves something like this: Player action -> Game Client -> Network -> Server -> Network-> Game client. This means every player action is only executed once it makes a round trip though the network. This would make the game feel really laggy, that's why latency hiding was a mechanism added in the game almost since the introduction of multiplayer. Latency hiding works by simulating the player input, without considering the actions of other players and without considering the server's arbitrage.

In Factorio we have the Game State, this is the full state of the map, player, entitites, everything. It's simulated deterministically on all clients based on the actions received from the server. This is sacred and if it's ever different from the server or any other client, a desync occurs.



On top of the Game State we have the Latency State. This contains a small subset of the main state. Latency State is not sacred and it just represents how we think the game state will look like in the future based on the Input Actions the player performed.

To do that, we keep a copy of the Input Actions we make, in a latency queue.



So in the end the process, on the client side, looks something like this:
  • Apply all the Input Actions of all players to the Game State, as received from the server.
  • Delete all the Input Actions from the latency queue that were applied to the Game State, according to the server.
  • Delete the Latency State and reset it to look the same as Game State.
  • Apply all the actions in the latency queue to the Latency State.
  • Render the game to the player, based on the information from the Game State and Latency State.
This is repeated every tick.

Getting complicated? Hold on to your pants. To account for the unreliable nature of internet connections, we have two mechanisms:
  • Skipped ticks: When the server decides what Input Actions will be executed in what game tick, if it does not have the Input Actions of a certain player (e.g. because of a lag spike), it will not wait, but instead tell that client "I did not include your Input Actions, I will try to include them in the next tick". This is so when a client has connection problems (or computer problems), they will not slow down the map update for everyone. Note that Input Actions are never ignored, they are only delayed.
  • Roundtrip Latency: The server tries to guess what's the roundtrip delay between the client and the server, for each client. Every 5 seconds it will negotiate a new latency with the client, if necessary, based on how the connection behaved in the past and the roundtrip latency will be increased and decreased accordingly.
By themselves they are pretty straightforward, but when they happen together (which is common when experiencing connection issues), the code logic starts becoming unwieldy, with a large amount of edge cases. Furthermore, the server and the latency queue need to properly inject a special Input Action called StopMovementInTheNextTick when the above mechanisms come into play. This prevents your character from running by himself (e.g. in front of a train) while experiencing connection problems.

Now it's time to explain how our entity selection works. One of the Input Action types we send is entity selection change, which tells everyone what entity each player has their mouse over. As you can imagine this is by far the most common input action sent by the clients, so it was optimized to use as little space as possible, to save bandwidth. The way this was done is that each entity selection, instead of saving absolute, high precision map coordinates, it saves a low precision relative offset to the previous selection. This works well, since a selection is usually very close to the previous selection. This creates 2 important requirements: Input Actions can never be skipped and the need to be executed in the correct order. These requirements are met for the Game State. But, since the purpose of the Latency state is to "look good enough" for the player, these requirements were not met. The Latency State didn't account for many edge cases related to tick skipping and roundtrip latency changing.

So you can probably see where this is going. Finally the issue of the megapacket started to show. The final problem was that the entity selection logic relied on the Latency State to decide if it should send a selection changed action, but the Latency State was sometimes not holding correct information. So, the megapacket got generated something like this:
  • Player has connection issues.
  • Skipped ticks and Roundtrip Latency adjustment mechanisms start to kick in.
  • Latency state queue doesn't account for these mechanisms. This leads to some action being deleted prematurely or executed in the wrong order, leading to an incorrect Latency State.
  • Player recovers from his connection issue and simulates up to 400 ticks in order to catch up to the server again.
  • For every tick, a new entity selection change action is generated and prepared to be sent to the server.
  • Client sends the server a megapacket with 400+ entity selection changes (and other actions also. Shooting state, walking state, etc also suffered from this problem).
  • Server receives 400 input actions. Since it's not allowed to skip any input action, it tells all clients to execute those actions and sends them over the network.


Ironically, the mechanism that was supposed to save some network bandwidth ended up creating massive network packets.

In this end this was solved by fixing all the edge cases of updating and maintaining the latency queue. While this took quite some time, in the end it was probably worth doing a proper fix instead of some quick hacks.

Clusterio - The Gridlock Cluster

Clusterio is a scenario/server system that adds communication of game data between different servers. For instance sending items between different servers, so you can have a 'mining server', which will mine all the iron ore you need, and send it to the 'smelter server' which will smelt it all and pass it further along.

Last year there was an event using the system which linked over 30 servers together to reach a combined goal of 60,000 Science per minute. MangledPork has a video of the start of last years event on YouTube.

The great minds and communities behind the last event have come together again to host another Clusterio event: The Gridlock Cluster. The goal this time is to push the limits even further, explore and colonise new nodes as they are generated, and enjoy the challenge of building a mega-factory across multiple servers.

If you are interested in participating in this community event, all the details are listed in the Reddit post, and you can join the Gridlock Cluster Discord server.

As always, let us know what you think on our forum.

Version 0.17.54 released

Changes


  • Removed the message of " is in the way" when building over the exact same entity with same direction and position as in cursor. more
  • Rails under trains can be marked for deconstruction. more
  • Better latency hiding in multiplayer when experiencing connection issues. Less issues with rubber-banding or character teleporting.
  • Latency hiding is no longer completely disabled when the character is shooting. Character position and animation are still not latency-hidden while the character is in combat (10 seconds after shooting or taking damage). This should make combat smoother in multiplayer.
  • The Linux version of the game now depends on PulseAudio.
Bugfixes


  • Fixed adding conditions to a train station after it was dragged. more
  • Improved drawing of a wall preview in some special cases. more
  • Fixed that the sync-mods-with-save could in some cases leave mods enabled. more
  • Added Right Control as secondary binding for "Temporary station modifier" controls. more
  • Fixed that migrating saves could in some cases mess up damage bonuses. more
  • Added a migration for unloadable saves because of invalid train paths caused by bugs in previous versions. more
  • Fixed that rails wouldn't build correctly if they had a fast_replaceable_group defined. more
  • Fixed flamethrower turret tooltip was missing info about created fire. more
  • Fixed that modded units with minimal attack range wouldn't try to get away from a target if they were too close. more
  • Fixed that train built from blueprint could miss a connection occasionally due the rail building order. more
  • Fixed that electric-energy-interface and heat-interface entity types didn't export properly in blueprint string format. more
  • Fixed Compilatron speech bubble hologram effect would cause entire screen to flicker when "Full color depth" graphics option was disabled. more
  • Fixed a map corruption issue related to building blueprints outside of the map through script. more
  • Fixed that too long description of shortcut tool could make the selection frame to be too big and unclosable. more
  • Fixed that undo doesn't work for trains. more
  • Fixed that reading 'disabled' from train stop control behaviors from Lua would report bad values in some cases. more
  • Fixed that rich text tooltips would flicker in multiplayer. more
  • Fixed possible crash in NPE when Compilatron builds an iron mining setup. more
  • Fixed multiplayer issue where a client and server would sometimes send a large amount of data, causing players with slower connection to disconnect (https://factorio.com/blog/post/fff-302)
  • Fixed that the wind sound would cut off abruptly when the technology screen was opened. more
  • Fixed that inserter tooltips would list pollution despite inserters being unable to produce pollution. more

  • Fixed that the bar of train wagon in blueprint was lost when the game was saved and loaded. more
  • Fixed that textfield selection wasn't removed when the focus was lost. more
Modding


  • Equipment with the "manual" shape now renders backgrounds/outlines automatically like equipment with the "full" shape.


You can get experimental releases by selecting the '0.17.x' beta branch under Factorio's properties in Steam.

Friday Facts #301 - Crash site: First state

Read this post on our website

Crash site: First state

For many weeks now the GFX department has been focused on preparing replacements for the placeholder graphics of the campaign crash site. The subject as usual is not that easy because we had to first solve the main concept of the crash site.

It happens that those new entities belong to the Factorio universe, but they come from a different reality than the usual DIY/diesel punk of the game. So we had to invent a new way to design machines that look like Factorio but that are not too familiar.

Here a proof of concept of the look:



The concept is that the big (medium) spaceship broke into pieces as it crash landed, and lost many components that the player, during the introduction, will repair and use for his own profit.

The look of the spaceship remnants are a little bit based on the designs of the 60’s/70’s pulp Sci-Fi. Fortunately we can keep the look of Factorio due the accident, which allows us to destroy and dirty up the machines show many inner mechanical details.

It is also part of the concept that all the machines that the player builds, are based on an existing technology from his home planet. So the machines that we see in the regular game are like 'cheap' versions of the original ones.



For the lab, we keep the dome shape and the beams inside in order to keep consistency with the regular laboratory. So slowly the player gets used to the meaning of the shapes.



The generator is similar to a substation -more or less-, connectable like a pole but it also produces electricity. Sometimes we really have to invent.



This works like an assembling machine. The design is more based in the (yet unshown) redesign of the assembling machines, rather than on the actual 'classic' ones.



These cylinders are like chests. We decided to make them cylindrical instead of a box for this difference in technology level that we are speaking about. The player will recognize them for the shape, color, and they also always have a number printed. You don’t really want to know the meaning of the numbers.

All this new content is a work in progress, and we made these new entities first for the testing of the campaign. Based on feedback with testers we will have the chance to tweak and adapt whatever is necessary. In the case of the introduction, the positioning of the entities can have a large impact on the flow of the gameplay. Once we are more sure of the final placement, we can see how all the pieces will fit together.

The next round for the crash site is the main crashed spaceship, and some other assets that converts the scene into a full composition, more proper for the introduction of the game.

Mods do crazy things

I've heard it many times and said it myself: "It's only ..., there aren't a lot of them in the base game so it should be fine." And then mods come along and bring a slap of reality: if a mod *can* do something a mod *will* do something.

The other week I got a bug report that the game was using a large amount of memory and took an excessive amount of time to exit. After reading over the bug report I had my theories as to why it might be happening but first I needed to reproduce it. A few failed attempts later I got the correct set of mods and mod settings to make it happen. To my surprise (well not really - it happens almost every time with these things now) - it wasn't what I thought it was going to be.

Sprites.
Not the video-texture kind but the internal wrapper class we use to store information about the video-texture. The game was creating an insane amount of them due to what the mod was doing. Specifically: the mod was making a lot of variations of each biter, spitter, worm, biter nest, and spitter nest. Normally that's not a problem - the game can do that easily. The problem came from how worms work. Worms have multiple directions with multiple animations for each direction. The end result is each base game worm creates 7668 sprites. ... "It's only 7668 sprites per worm, there aren't a lot of them in the base game so it should be fine." The base game has 4 worms: small, medium, large, behemoth. This mod was asking the game to make 3020.

The base game:
  • 188'056 sprites on the main menu
  • 1.281 seconds from launch to the main menu
  • 245 MB idling on the main menu
  • 0.1 seconds to exit


The mods:
  • 41'071'478 sprites on the main menu
  • 47.395 seconds from launch to the main menu
  • 15'791 MB idling on the main menu
  • 47.5 seconds to exit


Many ideas and attempts later (plus fixing all the broken stuff introduced by those changes with the assistance of Oxyd) I had reduced the time complexity of making and destroying the sprites by a significant amount and found that some just weren't needed.

The result:
  • 23'681'677 sprites on the main menu
  • 37.444 seconds from launch to the main menu
  • 5'484 MB idling on the main menu
  • 2.9 seconds to exit


A significant improvement on every measurement. I always love working on these kinds of problems because they almost always involve a lot of thinking and experiments.

As always, let us know what you think on our forum.

Version 0.17.52

Bugfixes


  • Fixed a crash related to equipment rendering.
  • Fixed a crash related to tile building. more

You can get experimental releases by selecting the 'experimental' beta branch under Factorio's properties in Steam.