NIMBY Rails devblog 2020-06

Internal development notes, very slightly cleaned up and commented a month later.

TL;DR: huge addition of map POIs, better station track links, and multiplayer!

More map POIs

While the current NIMBY Rails world map is very complete, some sacrifices had to be made to keep the size manageable. Amongst them is not storing a lot of textual data. OpenStreetMap has an immense amount of textual information mostly in the form of street names and POIs names. I decided to try to at least include more POI names to make the game map feel more complete, and so people can find more local names. It will also help the automatic station namer.

After studying the relevant OSM tags, I decided on a subset, and re-run a subset of map processing system to extract and create new POI information for the game map. The result: that the amount of named POIs and regions in the game went from 700K to 11M, at a cost of just 1GB extra space.

Before:

After:

Unfortunately the map loading and display performance also tanked at the same time. Up to this point, regions and POIs had been handled separately, with a traditional database design, and using the SQLite rtree spatial index extension. I realized this design wasn’t performant enough for what I wanted, so I decided to store POI information with the same tile system the rest of the game map uses. After this change, not only is the map fast again, it is actually faster than before. Thousands of region and POIs can be queried, processed and importance filtered per frame at 60FPS.

While evaluating the feedback from the Steam Festival demo, the way station links and branch links work were a common complaint. Indeed there was some usability issues with them, so I decided to address this now before I keep evolving stations beyond the current form. First I added a “forbidden” display to tracks that cannot have linked branches to them, which is the case of stations, but also of the connected tips of branches themselves:

But the main issue is the hackish way stations connect to normal tracks, by using a special, hidden branch. This was due be replaced with a proper track link. In the new implementation, the special “linear” behavior of track platforms is kept by the model and drawing rules, not as a side effect of how branches work (worked, since after this was implemented, I removed the hack). This enables stations to be just another track segment in a run of track, just one that behaves differently when one of its handles is moved. To achieve a proper link with the rest of the track run I now allow these links to have a second, automatic curve:

This special case is entirely handled as part of the track “tracer” code. The radius of the curves can be tweaked just by positioning the connected track handles closer or further:

Multiplayer!

The big development effort for June was to bring up the new networking and multiplayer code. And just as the month was ending, I managed it:

The changes required for this new version of multiplayer have been pilling up since March, starting with deep rewrites of some of the most core, delicate parts of the model code as detailed in the April post. The game editor is now working on top of what is essentially a distributed database, although it will work with client/server semantics to make it easier to develop and reason about. It essentially enables me to write code that deals with user-edited objects that get replicated to a server, and then replicated to clients. As long as some basic rules are followed, there is no need to introduce any special synchronization code, everything is handled automatically…

… With the exception of trains :) As mentioned this new multiplayer system deals with user-edited objects. These objects do not change every frame, but it’s supremely important that they are exactly replicated between clients. But trains are the opposite. Trains state change on every frame, for every train. Also, it’s not very important if clients are slightly out of sync when simulating the trains, as long as the server remains the ground truth. Thus a different replication system is required. But this is job for another month.