Skip to content

Commit

Permalink
[1.21.4] Expose vanilla model generators for modded usages (#1725)
Browse files Browse the repository at this point in the history
  • Loading branch information
ApexModder authored Dec 24, 2024
1 parent 17ebc64 commit e613b59
Show file tree
Hide file tree
Showing 217 changed files with 2,323 additions and 6,423 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--- a/net/minecraft/client/data/models/BlockModelGenerators.java
+++ b/net/minecraft/client/data/models/BlockModelGenerators.java
@@ -5819,4 +_,16 @@
return this;
}
}
+
+ /**
+ * Neo: create a {@link BlockModelGenerators.BlockFamilyProvider} which re-uses the existing model of the given full
+ * block instead of creating a model and blockstate file for it. Intended for use cases where the full block is
+ * separately generated or otherwise exists such as when a dummy {@link BlockFamily} is used to create additional
+ * variants for existing vanilla block families
+ */
+ public BlockModelGenerators.BlockFamilyProvider familyWithExistingFullBlock(Block fullBlock) {
+ var provider = new BlockModelGenerators.BlockFamilyProvider(TextureMapping.cube(fullBlock));
+ provider.fullBlock = ModelLocationUtils.getModelLocation(fullBlock);
+ return provider;
+ }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--- a/net/minecraft/client/data/models/EquipmentAssetProvider.java
+++ b/net/minecraft/client/data/models/EquipmentAssetProvider.java
@@ -26,6 +_,10 @@
this.pathProvider = p_387559_.createPathProvider(PackOutput.Target.RESOURCE_PACK, "equipment");
}

+ protected void registerModels(BiConsumer<ResourceKey<EquipmentAsset>, EquipmentClientInfo> output) {
+ bootstrap(output);
+ }
+
private static void bootstrap(BiConsumer<ResourceKey<EquipmentAsset>, EquipmentClientInfo> p_387865_) {
p_387865_.accept(
EquipmentAssets.LEATHER,
@@ -106,7 +_,7 @@
@Override
public CompletableFuture<?> run(CachedOutput p_387304_) {
Map<ResourceKey<EquipmentAsset>, EquipmentClientInfo> map = new HashMap<>();
- bootstrap((p_386976_, p_388942_) -> {
+ registerModels((p_386976_, p_388942_) -> {
if (map.putIfAbsent(p_386976_, p_388942_) != null) {
throw new IllegalStateException("Tried to register equipment asset twice for id: " + p_386976_);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--- a/net/minecraft/client/data/models/ItemModelOutput.java
+++ b/net/minecraft/client/data/models/ItemModelOutput.java
@@ -10,4 +_,10 @@
void accept(Item p_387543_, ItemModel.Unbaked p_386880_);

void copy(Item p_387316_, Item p_387995_);
+
+ /**
+ * Neo: Pulled up from {@link ModelProvider.ItemInfoCollector} to give modders full control over the {@link net.minecraft.client.renderer.item.ClientItem} instead of just the {@link ItemModel.Unbaked} in {@link #accept(Item, ItemModel.Unbaked)
+ */
+ default void register(Item item, net.minecraft.client.renderer.item.ClientItem clientItem) {
+ }
}
140 changes: 140 additions & 0 deletions patches/net/minecraft/client/data/models/ModelProvider.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
--- a/net/minecraft/client/data/models/ModelProvider.java
+++ b/net/minecraft/client/data/models/ModelProvider.java
@@ -34,20 +_,58 @@
private final PackOutput.PathProvider blockStatePathProvider;
private final PackOutput.PathProvider itemInfoPathProvider;
private final PackOutput.PathProvider modelPathProvider;
+ public final String modId;

+ // Neo: Use the constructor which accepts a mod ID.
+ @Deprecated
public ModelProvider(PackOutput p_388260_) {
+ this(p_388260_, ResourceLocation.DEFAULT_NAMESPACE);
+ }
+
+ public ModelProvider(PackOutput p_388260_, String modId) {
this.blockStatePathProvider = p_388260_.createPathProvider(PackOutput.Target.RESOURCE_PACK, "blockstates");
this.itemInfoPathProvider = p_388260_.createPathProvider(PackOutput.Target.RESOURCE_PACK, "items");
this.modelPathProvider = p_388260_.createPathProvider(PackOutput.Target.RESOURCE_PACK, "models");
+ this.modId = modId;
+ }
+
+ protected void registerModels(BlockModelGenerators blockModels, ItemModelGenerators itemModels) {
+ blockModels.run();
+ itemModels.run();
+ }
+
+ /**
+ * Returns a {@link Stream stream} containing all {@link Block blocks} which must have their models/block states generated or {@link Stream#empty() empty} if none are desired.
+ * <p>
+ * When using providers for specific {@link Block block} usages, it is best to override this method returning the exact {@link Block blocks} which must be generated,
+ * or {@link Stream#empty() empty} if generating only {@link Item item} models.
+ * <p>
+ * Default implementation generates models for {@link Block blocks} matching the given {@code modId}.
+ * @see #getKnownItems()
+ */
+ protected Stream<? extends Holder<Block>> getKnownBlocks() {
+ return BuiltInRegistries.BLOCK.listElements().filter(holder -> holder.getKey().location().getNamespace().equals(modId));
+ }
+
+ /**
+ * Returns a {@link Stream stream} containing all {@link Item items} which must have their models/client items generated or {@link Stream#empty() empty} if none are desired.
+ * <p>
+ * When using providers for specific {@link Item item} usages, it is best to override this method returning the exact {@link Item items} which must be generated,
+ * or {@link Stream#empty() empty} if generating only {@link Block block} models (which have no respective {@link Item item}).
+ * <p>
+ * Default implementation generates models for {@link Item items} matching the given {@code modId}.
+ * @see #getKnownBlocks()
+ */
+ protected Stream<? extends Holder<Item>> getKnownItems() {
+ return BuiltInRegistries.ITEM.listElements().filter(holder -> holder.getKey().location().getNamespace().equals(modId));
}

@Override
public CompletableFuture<?> run(CachedOutput p_387857_) {
- ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector();
- ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector();
+ ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector(this::getKnownItems);
+ ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector(this::getKnownBlocks);
ModelProvider.SimpleModelCollector modelprovider$simplemodelcollector = new ModelProvider.SimpleModelCollector();
- new BlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
- new ItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
+ registerModels(new BlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector), new ItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector));
modelprovider$blockstategeneratorcollector.validate();
modelprovider$iteminfocollector.finalizeAndValidate();
return CompletableFuture.allOf(
@@ -63,12 +_,22 @@

@Override
public String getName() {
- return "Model Definitions";
+ return "Model Definitions - " + modId;
}

@OnlyIn(Dist.CLIENT)
static class BlockStateGeneratorCollector implements Consumer<BlockStateGenerator> {
private final Map<Block, BlockStateGenerator> generators = new HashMap<>();
+ private final Supplier<Stream<? extends Holder<Block>>> knownBlocks;
+
+ public BlockStateGeneratorCollector(Supplier<Stream<? extends Holder<Block>>> knownBlocks) {
+ this.knownBlocks = knownBlocks;
+ }
+
+ @Deprecated // Neo: Provided for vanilla/multi-loader compatibility. Use constructor with Supplier parameter.
+ public BlockStateGeneratorCollector() {
+ this(BuiltInRegistries.BLOCK::listElements);
+ }

public void accept(BlockStateGenerator p_388748_) {
Block block = p_388748_.getBlock();
@@ -79,9 +_,9 @@
}

public void validate() {
- Stream<Holder.Reference<Block>> stream = BuiltInRegistries.BLOCK.listElements().filter(p_388333_ -> true);
+ Stream<? extends Holder<Block>> stream = knownBlocks.get();
List<ResourceLocation> list = stream.filter(p_386843_ -> !this.generators.containsKey(p_386843_.value()))
- .map(p_386823_ -> p_386823_.key().location())
+ .map(p_386823_ -> p_386823_.unwrapKey().orElseThrow().location())
.toList();
if (!list.isEmpty()) {
throw new IllegalStateException("Missing blockstate definitions for: " + list);
@@ -97,6 +_,16 @@
static class ItemInfoCollector implements ItemModelOutput {
private final Map<Item, ClientItem> itemInfos = new HashMap<>();
private final Map<Item, Item> copies = new HashMap<>();
+ private final Supplier<Stream<? extends Holder<Item>>> knownItems;
+
+ public ItemInfoCollector(Supplier<Stream<? extends Holder<Item>>> knownItems) {
+ this.knownItems = knownItems;
+ }
+
+ @Deprecated // Neo: Provided for vanilla/multi-loader compatibility. Use constructor with Supplier parameter.
+ public ItemInfoCollector() {
+ this(BuiltInRegistries.ITEM::listElements);
+ }

@Override
public void accept(Item p_387063_, ItemModel.Unbaked p_388578_) {
@@ -116,7 +_,7 @@
}

public void finalizeAndValidate() {
- BuiltInRegistries.ITEM.forEach(p_388426_ -> {
+ knownItems.get().map(Holder::value).forEach(p_388426_ -> {
if (!this.copies.containsKey(p_388426_)) {
if (p_388426_ instanceof BlockItem blockitem && !this.itemInfos.containsKey(blockitem)) {
ResourceLocation resourcelocation = ModelLocationUtils.getModelLocation(blockitem.getBlock());
@@ -132,10 +_,9 @@
this.register(p_386494_, clientitem);
}
});
- List<ResourceLocation> list = BuiltInRegistries.ITEM
- .listElements()
+ List<ResourceLocation> list = knownItems.get()
.filter(p_388636_ -> !this.itemInfos.containsKey(p_388636_.value()))
- .map(p_388278_ -> p_388278_.key().location())
+ .map(p_388278_ -> p_388278_.unwrapKey().orElseThrow().location())
.toList();
if (!list.isEmpty()) {
throw new IllegalStateException("Missing item model definitions for: " + list);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--- a/net/minecraft/client/data/models/model/ModelLocationUtils.java
+++ b/net/minecraft/client/data/models/model/ModelLocationUtils.java
@@ -11,11 +_,13 @@
public class ModelLocationUtils {
@Deprecated
public static ResourceLocation decorateBlockModelLocation(String p_388520_) {
- return ResourceLocation.withDefaultNamespace("block/" + p_388520_);
+ // Neo: Use ResourceLocation.parse to support modded paths
+ return ResourceLocation.parse(p_388520_).withPrefix("block/");
}

public static ResourceLocation decorateItemModelLocation(String p_387226_) {
- return ResourceLocation.withDefaultNamespace("item/" + p_387226_);
+ // Neo: Use ResourceLocation.parse to support modded paths
+ return ResourceLocation.parse(p_387226_).withPrefix("item/");
}

public static ResourceLocation getModelLocation(Block p_387758_, String p_388221_) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--- a/net/minecraft/client/data/models/model/ModelTemplate.java
+++ b/net/minecraft/client/data/models/model/ModelTemplate.java
@@ -52,6 +_,13 @@
public ResourceLocation create(ResourceLocation p_388380_, TextureMapping p_387099_, BiConsumer<ResourceLocation, ModelInstance> p_387748_) {
Map<TextureSlot, ResourceLocation> map = this.createMap(p_387099_);
p_387748_.accept(p_388380_, () -> {
+ return createBaseTemplate(p_388380_, map);
+ });
+ return p_388380_;
+ }
+
+ // Neo: Reintroduced to allow subclasses to customize the serialization logic, many implementations just delegating
+ public JsonObject createBaseTemplate(ResourceLocation p_388380_, Map<TextureSlot, ResourceLocation> map) {
JsonObject jsonobject = new JsonObject();
this.model.ifPresent(p_388657_ -> jsonobject.addProperty("parent", p_388657_.toString()));
if (!map.isEmpty()) {
@@ -61,11 +_,14 @@
}

return jsonobject;
- });
- return p_388380_;
}

private Map<TextureSlot, ResourceLocation> createMap(TextureMapping p_387972_) {
return Streams.concat(this.requiredSlots.stream(), p_387972_.getForced()).collect(ImmutableMap.toImmutableMap(Function.identity(), p_387972_::get));
+ }
+
+ // Neo: Allows modders to modify this template by adding new elements, custom loader, render types and other modifiers
+ public net.neoforged.neoforge.client.model.generators.template.ExtendedModelTemplateBuilder extend() {
+ return net.neoforged.neoforge.client.model.generators.template.ExtendedModelTemplateBuilder.of(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--- a/net/minecraft/client/data/models/model/ModelTemplates.java
+++ b/net/minecraft/client/data/models/model/ModelTemplates.java
@@ -203,18 +_,18 @@
}

public static ModelTemplate create(String p_386521_, TextureSlot... p_388561_) {
- return new ModelTemplate(Optional.of(ResourceLocation.withDefaultNamespace("block/" + p_386521_)), Optional.empty(), p_388561_);
+ return new ModelTemplate(Optional.of(ModelLocationUtils.decorateBlockModelLocation(p_386521_)), Optional.empty(), p_388561_);
}

public static ModelTemplate createItem(String p_388248_, TextureSlot... p_386756_) {
- return new ModelTemplate(Optional.of(ResourceLocation.withDefaultNamespace("item/" + p_388248_)), Optional.empty(), p_386756_);
+ return new ModelTemplate(Optional.of(ModelLocationUtils.decorateItemModelLocation(p_388248_)), Optional.empty(), p_386756_);
}

public static ModelTemplate createItem(String p_386727_, String p_387707_, TextureSlot... p_387856_) {
- return new ModelTemplate(Optional.of(ResourceLocation.withDefaultNamespace("item/" + p_386727_)), Optional.of(p_387707_), p_387856_);
+ return new ModelTemplate(Optional.of(ModelLocationUtils.decorateItemModelLocation(p_386727_)), Optional.of(p_387707_), p_387856_);
}

public static ModelTemplate create(String p_386833_, String p_386662_, TextureSlot... p_387086_) {
- return new ModelTemplate(Optional.of(ResourceLocation.withDefaultNamespace("block/" + p_386833_)), Optional.of(p_386662_), p_387086_);
+ return new ModelTemplate(Optional.of(ModelLocationUtils.decorateBlockModelLocation(p_386833_)), Optional.of(p_386662_), p_387086_);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--- a/net/minecraft/client/data/models/model/TextureMapping.java
+++ b/net/minecraft/client/data/models/model/TextureMapping.java
@@ -412,4 +_,12 @@
ResourceLocation resourcelocation = BuiltInRegistries.ITEM.getKey(p_386842_);
return resourcelocation.withPath(p_387396_ -> "item/" + p_387396_ + p_386898_);
}
+
+ // Neo: Added to allow easier texture map copying
+ public TextureMapping copy() {
+ TextureMapping texturemapping = new TextureMapping();
+ texturemapping.slots.putAll(this.slots);
+ texturemapping.forcedSlots.addAll(this.forcedSlots);
+ return texturemapping;
+ }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.client.extensions;

import java.util.function.UnaryOperator;
import net.minecraft.client.data.models.model.ModelTemplate;
import net.minecraft.client.data.models.model.TexturedModel;

public interface ITexturedModelExtension {
/**
* Returns a new textured model holding the modified {@link ModelTemplate}
*/
default TexturedModel updateTemplate(UnaryOperator<ModelTemplate> modifier) {
return new TexturedModel(self().getMapping(), modifier.apply(self().getTemplate()));
}

private TexturedModel self() {
return (TexturedModel) this;
}

interface Provider {
/**
* Returns a new provider which mutates the backing {@link ModelTemplate}
*/
default TexturedModel.Provider updateTemplate(UnaryOperator<ModelTemplate> modifier) {
return block -> self().get(block).updateTemplate(modifier);
}

private TexturedModel.Provider self() {
return (TexturedModel.Provider) this;
}
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit e613b59

Please sign in to comment.