33import com .gregtechceu .gtceu .GTCEu ;
44import com .gregtechceu .gtceu .api .block .MaterialBlock ;
55import com .gregtechceu .gtceu .api .data .chemical .material .Material ;
6- import com .gregtechceu .gtceu .api .data .chemical .material .properties . OreProperty ;
7- import com .gregtechceu .gtceu .api .data .chemical .material .properties . PropertyKey ;
6+ import com .gregtechceu .gtceu .api .data .chemical .material .info . MaterialIconSet ;
7+ import com .gregtechceu .gtceu .api .data .chemical .material .info . MaterialIconType ;
88import com .gregtechceu .gtceu .api .data .tag .TagPrefix ;
99import com .gregtechceu .gtceu .data .pack .GTDynamicResourcePack ;
10+ import com .gregtechceu .gtceu .utils .memoization .GTMemoizer ;
11+ import com .gregtechceu .gtceu .utils .memoization .function .MemoizedBiFunction ;
1012
1113import net .minecraft .MethodsReturnNonnullByDefault ;
1214import net .minecraft .client .Minecraft ;
1315import net .minecraft .core .registries .BuiltInRegistries ;
1416import net .minecraft .data .models .BlockModelGenerators ;
1517import net .minecraft .data .models .model .*;
1618import net .minecraft .resources .ResourceLocation ;
19+ import net .minecraft .server .packs .resources .Resource ;
20+ import net .minecraft .server .packs .resources .ResourceManager ;
1721import net .minecraft .util .GsonHelper ;
1822
19- import com .google .common .base .Preconditions ;
2023import com .google .gson .JsonObject ;
24+ import org .jetbrains .annotations .ApiStatus ;
2125
2226import java .io .BufferedReader ;
2327import java .io .IOException ;
2428import java .util .HashSet ;
29+ import java .util .Optional ;
2530import java .util .Set ;
2631
2732@ MethodsReturnNonnullByDefault
2833public class OreBlockRenderer {
2934
30- private static final Set <OreBlockRenderer > MODELS = new HashSet <>();
35+ protected static final Set <OreBlockRenderer > MODELS = new HashSet <>();
3136
32- private final MaterialBlock block ;
37+ protected static final JsonObject NULL_ELEMENT_MARKER = new JsonObject ();
38+ protected static final MemoizedBiFunction <MaterialIconType , MaterialIconSet , JsonObject > TEMPLATE_MODEL_CACHE = GTMemoizer
39+ .memoizeFunctionWeakIdent (OreBlockRenderer ::loadTemplateOreModel );
40+
41+ // First format key is material set name, 2nd is stone type prefix's name, 3rd is icon type's name
42+ public static final String ORE_MODEL_NAME_FORMAT = "block/material_sets/%s/ores/%s/%s" ;
43+
44+ protected final MaterialBlock block ;
3345
3446 public static void create (MaterialBlock block ) {
3547 MODELS .add (new OreBlockRenderer (block ));
@@ -39,56 +51,81 @@ public OreBlockRenderer(MaterialBlock block) {
3951 this .block = block ;
4052 }
4153
54+ @ ApiStatus .Internal
4255 public static void reinitModels () {
56+ // first set up all the stone types for all tag prefixes
57+ for (MaterialIconSet iconSet : MaterialIconSet .ICON_SETS .values ()) {
58+ for (var entry : TagPrefix .ORES .entrySet ()) {
59+ copyOreModelWithBaseStone (entry .getKey (), entry .getValue (), MaterialIconType .ore , iconSet );
60+ copyOreModelWithBaseStone (entry .getKey (), entry .getValue (), MaterialIconType .oreEmissive , iconSet );
61+ // TODO uncomment if/when small ores are added
62+ // copyOreModelWithBaseStone(entry.getKey(), entry.getValue(), MaterialIconType.oreSmall, iconSet);
63+ }
64+ }
65+
66+ // then create block state JSONs for all ore blocks with those models
4367 for (OreBlockRenderer model : MODELS ) {
68+ Material material = model .block .material ;
69+ TagPrefix tagPrefix = model .block .tagPrefix ;
70+ MaterialIconSet iconSet = material .getMaterialIconSet ();
71+ MaterialIconType iconType = tagPrefix .getMaterialIconType (material );
72+
4473 ResourceLocation blockId = BuiltInRegistries .BLOCK .getKey (model .block );
45- ResourceLocation modelId = blockId .withPrefix ("block/" );
46- OreBlockRenderer .cloneBlockModel (blockId , model .block .tagPrefix , model .block .material );
74+ ResourceLocation modelId = GTCEu .id (ORE_MODEL_NAME_FORMAT
75+ .formatted (iconSet .name , tagPrefix .name , iconType .name ()));
76+
4777 GTDynamicResourcePack .addBlockState (blockId , BlockModelGenerators .createSimpleBlock (model .block , modelId ));
4878 GTDynamicResourcePack .addItemModel (BuiltInRegistries .ITEM .getKey (model .block .asItem ()),
49- new DelegatedModel (ModelLocationUtils . getModelLocation ( model . block ) ));
79+ new DelegatedModel (modelId ));
5080 }
51- }
5281
53- /**
54- * Clones & modifies the base JSON for a single ore block.
55- *
56- * @param modelId the model id (usually {@code gtceu:block/<block id path>})
57- * @param prefix the TagPrefix of the block being added.
58- * @param material the material of the block being added. must have an ore property.
59- */
60- public static void cloneBlockModel (ResourceLocation modelId , TagPrefix prefix , Material material ) {
61- OreProperty prop = material .getProperty (PropertyKey .ORE );
62- Preconditions .checkNotNull (prop ,
63- "material %s has no ore property, but needs one for an ore model!" .formatted (material .getName ()));
82+ TEMPLATE_MODEL_CACHE .getCache ().clear ();
83+ }
6484
85+ /// This is called for every combination of tag prefix + icon type + icon set
86+ protected static void copyOreModelWithBaseStone (TagPrefix tagPrefix , TagPrefix .OreType oreType ,
87+ MaterialIconType iconType , MaterialIconSet iconSet ) {
6588 // read the base ore model JSON
6689 JsonObject original ;
67- try (BufferedReader reader = Minecraft .getInstance ().getResourceManager ()
68- .openAsReader (GTCEu .id ("models/block/ore%s.json" .formatted (prop .isEmissive () ? "_emissive" : "" )))) {
69- original = GsonHelper .parse (reader , true );
70- } catch (IOException e ) {
71- throw new RuntimeException (e );
90+ try {
91+ original = TEMPLATE_MODEL_CACHE .apply (iconType , iconSet );
92+ } catch (RuntimeException e ) {
93+ GTCEu .LOGGER .error ("Could not load template block model for ore type {}, icon type '{}', icon set '{}'" ,
94+ tagPrefix .name , iconType .name (), iconSet .name , e );
95+ return ;
96+ }
97+ if (original == NULL_ELEMENT_MARKER ) {
98+ // if the icon set doesn't have an ore model (somehow...), skip it
99+ return ;
72100 }
73101
74- // clone it
102+ // copy it
75103 JsonObject newJson = original .deepCopy ();
76- JsonObject children = newJson . getAsJsonObject ( "children" );
77- // add the base stone texture.
78- children .getAsJsonObject ("base_stone" )
79- .addProperty ("parent" , TagPrefix . ORES . get ( prefix ) .baseModelLocation ().toString ());
104+ // add the base stone model.
105+ newJson . getAsJsonObject ( "children" )
106+ .getAsJsonObject ("base_stone" )
107+ .addProperty ("parent" , oreType .baseModelLocation ().toString ());
80108
81- ResourceLocation layer0 = prefix .materialIconType ()
82- .getBlockTexturePath (material .getMaterialIconSet (), true );
83- ResourceLocation layer1 = prefix .materialIconType ()
84- .getBlockTexturePath (material .getMaterialIconSet (), "layer2" , true );
109+ GTDynamicResourcePack .addBlockModel (
110+ GTCEu .id (ORE_MODEL_NAME_FORMAT .formatted (iconSet .name , tagPrefix .name , iconType .name ())), newJson );
111+ }
85112
86- JsonObject oresTextures = children . getAsJsonObject ( "ore_texture" ). getAsJsonObject ( "textures" );
87- oresTextures . addProperty ( "layer0" , layer0 . toString () );
88- oresTextures . addProperty ( "layer1" , layer1 . toString () );
113+ private static JsonObject loadTemplateOreModel ( MaterialIconType iconType , MaterialIconSet iconSet ) {
114+ ResourceLocation baseModelPath = iconType . getBlockModelPath ( iconSet , true );
115+ baseModelPath = GTDynamicResourcePack . MODEL_ID_CONVERTER . idToFile ( baseModelPath );
89116
90- newJson .getAsJsonObject ("textures" ).addProperty ("particle" , layer0 .toString ());
117+ ResourceManager resourceManager = Minecraft .getInstance ().getResourceManager ();
118+ Optional <Resource > modelResource = resourceManager .getResource (baseModelPath );
91119
92- GTDynamicResourcePack .addBlockModel (modelId , newJson );
120+ if (modelResource .isEmpty ()) {
121+ // if the icon set doesn't have an ore model (somehow...), skip it gracefully
122+ return NULL_ELEMENT_MARKER ;
123+ }
124+ // read & cache the base ore model JSON
125+ try (BufferedReader reader = modelResource .get ().openAsReader ()) {
126+ return GsonHelper .parse (reader , true );
127+ } catch (IOException e ) {
128+ throw new RuntimeException (e );
129+ }
93130 }
94131}
0 commit comments