-
Notifications
You must be signed in to change notification settings - Fork 56
Runtime Resource Packs
Generate textures, models, blockstates, recipes, tags and lang files while the game loads, and serve them from a virtual resource pack.
This is the flagship feature and the reason the library exists. If your mod registers blocks that depend on what other mods are installed, one per wood type, one per color, you can't ship files for all of them. So you build the assets at runtime out of the textures that are actually there.
Your generator reads the already loaded packs, so it sees the player's own resource pack too, and writes into a sink. The result sits below every other pack, so anyone can still override a generated file with a real one.
Extend DynamicClientResourceProvider (assets) or DynamicServerResourceProvider (data), and
register it on init:
RegHelper.registerDynamicResourceProvider(new MyModAssets());public class MyModAssets extends DynamicClientResourceProvider {
public MyModAssets() {
super(MyMod.res("example_pack"), PackGenerationStrategy.CACHED);
}
@Override
protected Collection<String> gatherSupportedNamespaces() {
return List.of("minecraft"); // must be known before anything is generated
}
@Override
public void regenerateDynamicAssets(Consumer<ResourceGenTask> executor) {
// split the work in a few tasks, they run in parallel
executor.accept((manager, sink) -> {
JsonObject json = new JsonObject();
json.addProperty("parent", "block/stone");
sink.addItemModel(MyMod.res("sturdy_stone_bricks"), json);
// only generate if no pack already provides it. The supplier isn't called otherwise
sink.addTextureIfNotPresent(manager, MyMod.res("block/sturdy_stone_bricks"),
() -> makeTexture(manager));
// take a vanilla file and string replace your way to a new one
StaticResource stone = StaticResource.getOrThrow(manager,
ResourceLocation.parse("models/block/stone_bricks.json"));
sink.addSimilarJsonResource(manager, stone, "stone_bricks", "sturdy_stone_bricks");
});
}
@Override
public void addDynamicTranslations(AfterLanguageLoadEvent event) {
event.addEntry("mymod.test.translation", "Hello World!");
}
}The ResourceSink has an addX for everything: textures, models, blockstates, lang, tags, recipes,
loot tables, or raw json and bytes. The IfNotPresent / UnlessPresent variants skip the work when
a real pack already has that file, use them for anything a pack author might want to hand-author.
Example: DynamicResourcesExample
The second constructor argument decides when the work is redone:
| Strategy | |
|---|---|
CACHED |
Generate once, cache to disk, reuse. The normal choice |
CACHED_ZIPPED |
Same, cached as a zip |
REGEN_ON_EVERY_RELOAD |
Rebuild on every F3+T, in memory |
runOnce() |
Once per launch, in memory |
NO_OP |
Never. For a pack you fill some other way |
Caches invalidate when the mod list changes, and when a config marked
affectsDynamicPacks() changes.
extra_debug in the common config dumps everything that was generated to .minecraft/debug/.
merge_dynamic_resource_packs (client, on by default) merges every mod's dynamic pack into one.
Turn it off to see them separately in the pack list.
See Texture Manipulation for building the images you feed into the sink, and Block Set API for what usually drives all of this.
Basics Platform Helpers Registration Networking Events Configs Config Screen
Resources Runtime Resource Packs Texture Manipulation Resource Helpers Block Set API
Client Custom Models Item Rendering Rendered Textures Post Shaders GUI Toolkit Colors
World Block and Item Interfaces Additional Item Placements Improved Entities Fake Levels World Data Dispenser Behaviors
Utilities Codec Utilities Misc Helpers Commands
Datapacks Villagers Soft Fluids Map Markers Spawn Boxes Global Datapack Folder