Skip to content

Tree Packs

Harley O'Connor edited this page Mar 13, 2021 · 15 revisions

Tree packs are a new feature of Dynamic Trees for 1.16, allowing mod pack developers and the average user to add their own custom content like trees and species with just a set of Json files, as well as allowing add-on developers to add their content in the same way.

Tree packs work much like Vanilla's resource and data packs, but are both loaded on the initial game launch and reloaded when data packs are (on world load and when the /reload command is used). Below is the basis of the file structure:

trees/
  namespace/
    leaves_properties/
    families/
    species/
    jo_codes/
    world_gen/

A trees folder can be found in the Minecraft directory (subject to change), which is where the user/mod pack developer can create their custom entries. For add-on mods the trees folder should be located under their resources/assets directory, and it will be loaded automatically.

For guides on how to add leaves properties, families, etc, refer to the relevant guide on the side-bar.

Technicals

The below description is my early attempt at describing a complicated system... Hopefully it's understandable already, but I plan on improving (and extending) it over time. If you have any questions that aren't answered by the below or are confused by what I'm trying to communicate, please do ask on Discord.

The tree packs are controlled by an implementation of IResourceManager, which holds a List of TreeResourcePack objects and ReloadListener objects. TreeResourcePack is an extension of ResourcePack, holding the path of the pack of resources and handling collecting all resource locations and namespaces that are a part of the pack, as well as retrieving an InputStream from it. The ReloadListener is a custom abstract class, handling loading data from files on load/reload. It is mostly based on Vanilla's ReloadListener, except it handles data on game setup (the load function) too.

Extensions of ReloadListener include JsonReloadListener, which implements a method for the prepare method, returning a Map of resource locations and their JsonElement objects (which is collected from the top-most containing the resource location, much like how it works in Vanilla). The result of this method is then passed as an argument to apply (an abstract class of ReloadListener), which will be implemented in sub-classes like the SpeciesManager. Another extension is MultiJsonReloadListener, which grabs every file for the given resource location in the order of the resource pack, allowing data to be processed from multiple files, such as how the BiomeDatabaseManager works for collecting default.json so the default database can be modified by multiple different packs provided by multiple different mods.

Both of these extend JsonApplierReloadListener, which stores JsonPropertyApplierList objects. These store a list of JsonPropertyApplier objects, which hold the key of the relevant JsonElement, the class of the object being applied to (such as the Species class for SpeciesManager), the class of the value being applied, such as the Integer class for applying a maximum branch radius, and the IPropertyApplier to be called. This contains a method called applyIfShould, which checks the given key is correct, the given object to be applied to has the correct type, and the given JsonElement has the correct type. Only if all of these conditions are met will IPropertyApplier#apply be called, which, in the example of the maximum branch radius applier will call Species#setMaxBranchRadius with the given value.