Updates Metal Renegades: Terrain Generation Improvements

Lorxu

New Member
Project progress board: https://trello.com/b/HKc9QHQl/metal-renegades-gsoc-2021
Project proposal:
Overview:
This project concerns implementing a new terrain generator for Metal Renegades. Currently, the world of Metal Renegades is an endless desert, but I'll add more interesting terrain typical of the Old West: mesas where rock around a plateau has eroded away, canyons where rivers have cut deep into the rock, mountains made of rock instead of sand, and more. I'll also try to create a realistic distribution of flora and fauna, and include as much realism as I can while still remaining performant and fun to play.
 

Lorxu

New Member
Progress Update:

This week, I worked on adding rivers to Metal Renegades, and updating the Tutorial World Generator, which was previously broken and outdated. The tutorial works now, and rivers look pretty good. I implemented rivers specifically for Metal Renegades instead of reusing the rivers from CoreWorlds because at high elevations like in mountains, those rivers would just carve 16 blocks or so into the ground, not get to sea level, and not generate any water. Instead, the new rivers carve all the way down to sea level, with varying steepness so that sometimes it generates canyons, and sometimes gentle slopes:



Meeting overview:
  • I gave an overview of my progress as described above.
  • We had a lot of discussion on improving the performance of world generation, especially optimizing the order in which chunks are generated, but didn't really come to any conclusions. I plan to look into it more this week, and hopefully do some profiling as well.
  • We discussed some issues arising from the river implementation, specifically that wells, houses, and the player could spawn underwater, and decided to add them to a new section of the Trello board.
  • Next week, I'll be focusing on biomes, adding four new biomes with associated surface block and plant generation. They'll be mostly placed according to terrain features, for example a rocky biome on mountainsides, and a wetter biome along rivers.
 

Lorxu

New Member
Progress update:

This week, I worked on two different things:
  • First, I reworked some of the chunk processing code so that chunks always generate in order of distance to the player. This change is still in progress, so players won't see any improvement on the main branch of the engine quite yet.
  • Second, I added new biomes to Metal Renegades. There are four new biomes, but only three actually generate: a rocky biome for mountains, which are now made of stone instead of sand; a riparian biome with lots of plants for near rivers; a scrubland biome which replaces some of the flat desert, with dry dirt and a few plants; and a steppe biome, which will eventually be a forested biome that generates on flat areas at high altitudes, but currently doesn't actually generate anywhere since there aren't any flat areas in mountains yet. It will be added in when I add mesas.
Meeting overview:
  • We discussed the change to the chunk processing order, including some design discussion and clarification of the way some things currently work. I plan to test it some more next week, including trying out chunk level-of-detail to make sure it hasn't been affected.
  • I explained the way I implemented the new biomes: there's a base biome provider which just generates desert and scrubland, then the providers that change the elevation to make rivers and mountains also change the biome in those areas to match.
  • We looked at the open pull requests relating to the biomes, including one which fixes a mistake I made where I used a relative position instead of a world position. We talked about how to avoid similar bugs in the future: making wrapper classes for types of positions would work, but isn't worth it at this point due to performance issues with too many wrappers and also the amount of code that would need to be changed; I'll make a unit test for this particular case, but that won't really help avoid future bugs, so we didn't really find a good solution to that problem.
  • I'll be out of town for a lot of next week, so I won't be able to get as much done, but I'll use the time I have to start working on adding terrain features like mesas and strata.
 

Lorxu

New Member
Progress update:

I didn't have that much time this week, but I continued work on the things from last week. I participated in some discussion and review of changes to improve world generation performance, and polished biomes. Here's a screenshot with all four currently generating biomes (desert, river, mountain, and a very small patch of scrubland), which also shows the noisy blending that now occurs on biome borders:



Meeting overview:
  • We discussed concurrency mechanisms: the codebase currently uses several ad-hoc concurrency mechanisms, but it makes sense to try to unify at least some of them. There's a currently open PR which uses the RxJava library for concurrency, which may be the way it's done in the future. My PR on chunk ordering will probably wait until that is merged or another standard concurrency method is decided upon, because it currently manually creates and manages threads.
  • I mentioned the main biome-related issues that remain, which is that rivers and river biomes are too frequent and too wide.
  • Next week, I'll finish up a PR fixing a problem in the engine which is needed for my biome implementation, and fix the tests in the chunk ordering PR. I'll also start working on rock strata and mesas, which will probably involve some new block types from another module.
 

Lorxu

New Member
Progress update:

I forgot to post here last week, so there's two weeks worth of updates here:
  • Rivers were reworked a bit more to fix some problems. They should now be a consistent fairly narrow size, and nothing should spawn underwater.
  • Rock strata were added to mountains:
  • I started working on mesas, but they're still a work in progress.
  • I fixed a bug where the advanced world setup screen, including a preview map of the world, would crash. This was a side effect of the changes I made earlier to the biome system.
Meeting overview:
  • We discussed what I worked on in the past week, as seen above.
  • We talked about plans for the future:
    • I'm going to add trees to steppes, and will probably want to add a new tree type for something like a juniper pine. That will use the GrowingFlora module, so I'll need to learn about L-systems and potentially update the module as well.
    • Scrublands should eventually have some sort of dry-looking grass instead of dirt. That could be accomplished with a new block, but there's also a block tinting feature which Terasology used to support which it might be worth it to bring back.
    • This week, though, I'm focusing on finishing mesas. I'm also redoing my chunk ordering changes with the new system we're planning on using for concurrency, the Project Reactor library.
 

Lorxu

New Member
Progress update:
  • I continued working on mesas. They now usually look pretty good, the main remaining thing is figuring out how they should interact with mountain ranges.
  • I rewrote my chunk ordering PR to use Reactor for concurrency.
  • I fixed a bug where rivers would sometimes generate upside-down, so that it looks like a little grassy hill instead of being filled with water.
  • I added some colors for the new biomes to the world preview screen, so that it's a better preview of what the world will actually look like.
  • I fixed the minimap in Metal Renegades, which was previously showing the wrong colors and weird grid artifacts but now looks right:
2708


Meeting overview:
  • I went over my progress above.
  • We talked about a bug where sometimes an area of the world will never generate unless you go far enough away that it unloads and then come back. We're still not sure what's causing it.
  • We talked about some other problems which are easier to fix, like that mesas are too rare and that sometimes the messy transition zones between biomes are way too big.
  • The plan for next week:
    • Fix the two small problems in the point above, and merge mesas into Metal Renegades. I'll work on the integration with mountains separately.
    • Fix the outstanding problems with the rewritten chunk ordering PR.
    • Try to figure out what's going on with the chunks that never generate.
    • If I have time after those, I'll start working on trees for steppes.
 

Lorxu

New Member
Progress update:
  • A couple finishing touches on mesas, and they were merged into Metal Renegades this week, so they're officially there. I'd still ideally like to work on the interaction with mountains, but I'm waiting until later for that.
  • I almost fixed all the problems with the rewritten chunk ordering PR - I'm still having concurrency bugs causing the tests to fail sometimes in Jenkins, but otherwise it works.
    • That includes figuring out the problem with stuck chunks and fixing it.
  • I brought back block tinting: the game used to change colors of grass and foliage based on the biome, but it was removed when biomes were extracted into a separate module, so I added it back with a new API. This is still in-progress, there's an open PR, but it does work at this point.
2709


Meeting overview:
  • We discussed the above progress, including some design questions regarding the API changes in block tinting.
  • We had a long discussion about how to make the order of facet providers that update existing facets deterministic and controllable. For example, the river provider should modify elevation to carve out riverbeds after the mountain provider has modified it to raise up mountains. We settled on adding a priority value in the Updates annotation, similar to a mechanism used by event handlers, so that any provider can control its order relative to other providers which update the same facet, so I'll work on adding that next week.
  • Other plans for next week:
    • I'm going to fix the tests of the rewritten chunk ordering PR for the last time.
    • There are a few improvements to the block tinting PR to make it more reliable, and I'll be testing it thoroughly as well.
    • I'll make use of the block tinting in Metal Renegades by making scrubland have a dry-looking grass surface instead of dirt. I'll also switch it to using the proper facet provider ordering mechanism once that's done.
 

Lorxu

New Member
Progress update:
  • Block tinting was finished up and merged, so the scrubland biome now has dry grass instead of dirt.
  • I added priority to facet providers which update facets like I described, and simplified the provider ordering calculation. This hasn't been merged yet, and there's now a circular dependency in CoreWorlds which needs to be fixed, but it's mostly done.
  • The tests for the chunk ordering PR now all pass; unfortunately they're not really testing the concurrency because multithreading doesn't work terribly well on the CI server. We're now waiting for some other Reactor infrastructure to be finished so it can be reevaluated.
  • I've started experimenting with trees for Metal Renegades; there are currently about two and a half implementations of tree generation, none of which really work that well for MR, so I'll be looking into merging and improving them.
Meeting overview:
  • We talked a lot about the tree-related infrastructure like I mentioned above.
  • We look at the chunk ordering PR and the facet provider priority PR and came up with some next steps:
    • Chunk ordering is waiting on other Reactor changes.
    • Facet priority is probably done for now, but I'm going to make a minor change to CoreWorlds to fix the circular dependency first.
    • I'm going to attempt to extract the tree generation system from the GrowingFlora module, which is much more sophisticated than the tree generation used by CoreWorlds, into another module; this is important because GrowingFlora depends on a bunch of other things which we don't want in Metal Renegades.
    • I'm going to try enabling chunk level-of-detail in Metal Renegades, and figure out what, if any, changes need to be made to get them working.
    • For something so important to the gameplay, cities are pretty hard to find, so I'll try to make them more common.
 

Lorxu

New Member
Progress update:
  • The biggest thing I worked on this week was trees. I removed the dependency on AnotherWorlds from GrowingFlora, so it's able to be used in Metal Renegades, and added two tree types using it: cypress trees in steppes, and baobabs in scrublands. There's still some work to be done to make the dependencies work out, but it works.
  • The facet priority PR was merged, and I updated CoreWorlds to work with it (although it still doesn't actually use it much, it just doesn't crash.) I also updated the world generation tutorial to incorporate facet priority and the biome API changes made during this project.
  • With Skaldarnar's help, LOD chunks now work in Metal Renegades. Block tinting doesn't work in LOD chunks, and they don't respect changes the player made to the environment, but they make it possible to see much farther.
2715


Meeting overview:
  • We talked about whether city generation was good enough. It usually generates cities pretty quickly when I'm playing by myself, but it has problems when some nearby chunks aren't loaded, which means that sometimes it won't generate cities at all when there are problems with chunk loading (which is often, especially on multiplayer). It might be worth decreasing the amount of space it requires to generate a city.
  • We discussed about some other problems with DynamicCities, which are mostly outside of the scope of this project but which cause some problems and are worth fixing at some point. For example, it tries to remove trees to build things, but the way it does that has lots of problems and doesn't work with the new GrowingFlora-based trees.
  • There's only one week left, so here's what's left to do:
    • Finish working out the dependencies of GrowingFlora and get trees in MR. This has a couple parts - I'm going to move some utility classes GrowingFlora needs into the engine, and make ClimateConditions an optional dependency. I'd also like to get trees to actually grow, but I'm not sure whether I'll have time this week.
    • Make block tinting work in LOD chunks.
    • Make animals spawn in the right places (i.e. no sheep in the desert).
    • Some other minor tweaks to polish the feel of the world generation - for example, I'd like ore to generate in strata other than stone, and more grass would be nice in scrublands.
 

Lorxu

New Member
Final Report - GSOC 2021
Terrain Generation Improvements for Metal Renegades


The goal of this project was to make the Metal Renegades game mode more immersive and interesting by adding new terrain generation that fits the Wild West theme of Metal Renegades. This includes biomes and plants as well as features like mesas, canyons, and rivers.


Some of the features added during the project

Outline

TutorialWorldGeneration

There’s a repository with a Terasology module and an online tutorial that goes over how to use Terasology’s world generation infrastructure. It’s pretty useful but unfortunately was fairly out of date, so I helped update it to work again, and added some information about some of the API changes I made as part of this project.

PRs:
Rivers
Terasology already has a simple implementation of rivers in the CoreWorlds module, part of the core world generator. But it’s not really sophisticated enough to use in Metal Renegades, so I wrote a new implementation of rivers. The most important difference is that if a CoreWorlds river generates in a mountain or other area with high elevation, it will carve out a riverbed that doesn’t reach sea level, and it won’t be filled with water; but in MR, rivers carve all the way down to sea level, in a way that’s engineered to generate decent canyons. Sometimes the rivers don’t quite reach sea level, and thus don’t have any water - this is a dry riverbed, and occurs in dry areas. Speaking of humidity, rivers in MR increase the humidity near them, and riverbanks are in a riparian biome with high humidity and plenty of plants.

A river

A dry canyon, created by the same mechanism

PRs:
Biomes
Instead of just an endless desert, I added four new biomes to make the landscape of Metal Renegades more interesting: a rocky biome for mountains, a scrubland biome with dry grass and some trees, a riparian biome for riverbanks, and a steppe biome for the tops of mesas. Over the course of the project I improved the biomes, adding features like trees to certain biomes, and I made some changes to the biome API so that it’s all implemented in a way that’s modular and maintainable.

A few of the biomes in Metal Renegades
API changes:
It used to be that a biome itself was just a biome ID, and other parts of the world generation pipeline had code to deal with specific biomes - for example, the primary rasterizer in CoreWorlds had a switch statement over the CoreWorlds biomes to determine which block to place. There’s still some of that, but I changed it so that some parts, like what blocks a biome is made of, are determined by the biome object itself, meaning that the new biomes from MR can be used in any gamemode and would still look mostly the same. (Plants still wouldn’t transfer, though.)
Block tinting:
Terasology used to have block tinting for grass, leaves, and other plants, where the color would change based on the biome; this was removed when the biome API was refactored a couple years ago, but I brought it back in a slightly different form so that, for example, scrublands can have dry-looking grass.
Trees:
I added two new kinds of trees, using the GrowingFlora module so that they’re varied and can grow over time. This required some changes to GrowingFlora as well, to remove some dependencies on things that Metal Renegades doesn’t want to depend on, and to fix some bugs.

A baobab tree in a scrubland biome

A juniper tree in a steppe biome

Other biome PRs:
Mesas
Mesas are a kind of mountain with very steep sides and a mostly flat top, which appear most often in dry areas. I implemented them in Metal Renegades, using a noise function with some fancy scaling. Another thing I had to implement to make them look nice is strata, the layers of different kinds of rock that you can see in the images below.



PRs:
Chunk generation ordering
When testing these features, I was often flying around generating lots of terrain. One thing that I sometimes found frustrating was that the chunks around me would take a very long time to generate, because the game was trying to generate chunks in other places. So, I changed the way chunks are generated to use the correct order, which updates whenever the player moves. This isn’t too much of a problem playing normally in single player, but playing on that PR (Terasology#4822) made it a lot easier to test world generation.

Other stuff
I made a bunch of smaller changes, mostly fixing minor bugs in various different modules:
My experience
I had a lot of fun on this project! Procedural generation is really interesting and rewarding, and my mentors and the community were really supportive. This was my first time programming as part of a team, so I learned a lot about how to coordinate with other developers, review other people’s code, and other relevant skills.
 
Last edited:
Top