I’ve spent the last ~3 months working on my GSoC project for Terasology. I’ve recorded my progress on the project in several places: the code (along with some discussion) is presented in GitHub PRs that are linked throughout the rest of this article; there’s an introduction to my project in a previous blog post; and I documented my progress over the summer in a series of forum posts.
The first part of this project was implementing pools. These are an extension of the game’s entity-component system which allow entities to be stored in multiple locations, in preparation for splitting the game into multiple worlds, or splitting servers across multiple machines.
They also lay the groundwork for the next part of the project, sectors, by allowing sector-scope entities to be stored in their own pool.
The terminology between sectors/pools can get confusing, because the main reason for implementing pools is to allow multiple sector pools, so they are often discussed together under the name ‘sectors’.
The second part of this project was sector-scope simulation, allowing entities to undergo simulation that is based on the time between simulation events rather than the number of events that are sent. This allows the simulation rate to be decreased, especially when the chunks that the entity affects aren’t loaded, to improve performance scaling with lots of entities.
- Sector simulation
- PR that merged pools work, and the first sector simulation PR
- Add SectorRegionComponent to allow sector entities to span multiple chunks
- Convert alwaysRelevant to entity scope
- Allow sector entities to simulate at a different rate when loaded
The final part of the project was zones (initially called surfaces). Zones allow the world to be split into different areas for world generation, and allow those different areas to have their own section on the world preview.
The most useful type of zone at the moment is the layered zone (or just layer). Layers are a special type of zone that lie horizontally in the world, and don’t overlap with each other. They are used to split up each of the layers in the world into separate areas, which allows each one to be provided by its own module (increasing the modularity and customisation of the game), and will open up further options in the future (such as splitting the sectors in the world according to the layers that exist).
Zones also provide a way of improving the world preview system, which allows the player to see what a world will look like before loading the world. Previously there was only one preview screen for the whole world, so you couldn’t show multiple separate parts of the world. Each zone has the option to act as a preview screen, so each part of the world (e.g. a layer of deep lava lakes, a cave layer, the surface of the world, and some floating islands) can have its own display screen.
To showcase the changes listed above, I updated some of the existing Terasology modules to use these new features.
The first module I updated was Dynamic Cities, which was created for last year’s GSoC. I updated the cities to use sector simulation, so the cities grow at a predictable rate even in games with different framerates, and to allow the simulation to be performed at a lower rate when the city is unloaded. This means that when no players are near the city, fewer updates need to be done, while still having the city grow at a consistent rate.
I also updated Inferno’s world generation to be a layered zone, and turned it into a world plugin. This means that it can be added as a layer to any world, instead of needing its own custom world generator.
The final module update was adding an example generator to TutorialWorldGeneration which was based on layers and zones. This shows how the features can be used in a complete world generator, and how they can interact with each other, and with the normal world generation features.
Comparison to original proposal
My original proposal focused only on pools and sectors, and included more advanced features such as allowing sectors to dynamically split or merge depending on which entities were interacting with each other. However, it was decided that these features wouldn’t provide many advantages until multi-world games or multi-machine servers were being worked on, so they were not implemented as part of this project. Instead of these I added zones, which will have a more immediate impact than the features that were pushed back to a later time.
The features I have implemented during this project are already fit for use, and have been merged into the v2.0.0 staging branch ready for inclusion in the next major version of the game.
However, there are still changes and improvements that can be made to the work I’ve done, and long-term projects that can build off this work:
- Improve the ordering of layers, to allow blank space between them and to be able to specify a desired depth for the layer
- Fix bug where “Entity x doesn’t have an assigned pool” appears repeatedly when the game is saved
- Fix bug with Dynamic Cities not properly reloading after being saved
- Implement multiple sectors, and sector splitting/merging
- Add non-overlapping, tiling, columnar zones (to allow each natural region to be its own zone)
- Convert existing world generators to use layers and zones
- Add connectors between zones so they can interact or merge at the edges
- Allow zone world plugins to be nested zones (so that zones can be added to a specific layer in the world)
- Allow each game save to consist of multiple worlds
- Allow game servers to be split across multiple physical machines
Overall, the project has been absolutely fantastic; I’ve learned a huge amount about contributing to an open source project with a large existing codebase, and about programming in general. I had a lot of fun doing the project, and I hope that my contributions are valuable and help developers and players of the game in the future.
I want to say a huge thank you to my mentors: they have been extremely helpful, both guiding the project and helping me learn a huge amount of new skills along the way. I also want to thank Google for running the program, which allowed me to spend my summer working on a great open source project while learning far more than I could by coding alone.