2424package aztech .modern_industrialization .machines .models ;
2525
2626import aztech .modern_industrialization .MI ;
27+ import com .google .gson .Gson ;
28+ import com .google .gson .GsonBuilder ;
2729import com .google .gson .JsonObject ;
2830import java .util .HashMap ;
2931import java .util .Map ;
3638import net .minecraft .client .resources .model .ModelState ;
3739import net .minecraft .resources .ResourceLocation ;
3840import net .minecraft .util .GsonHelper ;
41+ import net .minecraft .world .inventory .InventoryMenu ;
3942import net .neoforged .neoforge .client .model .geometry .IGeometryBakingContext ;
4043import net .neoforged .neoforge .client .model .geometry .IGeometryLoader ;
4144import net .neoforged .neoforge .client .model .geometry .IUnbakedGeometry ;
45+ import org .jetbrains .annotations .Nullable ;
4246
43- public class MachineUnbakedModel < O extends MachineOverlaysJson > implements IUnbakedGeometry <MachineUnbakedModel < O > > {
47+ public class MachineUnbakedModel implements IUnbakedGeometry <MachineUnbakedModel > {
4448 public static final ResourceLocation LOADER_ID = MI .id ("machine" );
45- public static final IGeometryLoader <MachineUnbakedModel < MachineOverlaysJson > > LOADER = (jsonObject , deserializationContext ) -> {
46- return new MachineUnbakedModel (OverlaysJson . class , MachineBakedModel :: new , jsonObject );
49+ public static final IGeometryLoader <MachineUnbakedModel > LOADER = (jsonObject , deserializationContext ) -> {
50+ return new MachineUnbakedModel (jsonObject );
4751 };
4852
49- private final MachineModelBaker modelBaker ;
53+ private static final Gson GSON = new GsonBuilder ().registerTypeAdapter (ResourceLocation .class , new ResourceLocation .Serializer ()).create ();
54+
5055 private final MachineCasing baseCasing ;
51- private final int [] outputOverlayIndexes ;
5256 private final Material [] defaultOverlays ;
5357 private final Map <ResourceLocation , Material []> tieredOverlays = new HashMap <>();
5458
55- public MachineUnbakedModel (Class <O > overlayClass , MachineModelBaker modelBaker , JsonObject obj ) {
56- this .modelBaker = modelBaker ;
57-
59+ private MachineUnbakedModel (JsonObject obj ) {
5860 this .baseCasing = MachineCasings .get (GsonHelper .getAsString (obj , "casing" ));
5961
60- var defaultOverlaysJson = MachineOverlaysJson .parse (overlayClass , GsonHelper .getAsJsonObject (obj , "default_overlays" ), null );
61- this .outputOverlayIndexes = defaultOverlaysJson .getOutputSpriteIndexes ();
62+ var defaultOverlaysJson = OverlaysJson .parse (GsonHelper .getAsJsonObject (obj , "default_overlays" ), null );
6263 this .defaultOverlays = defaultOverlaysJson .toSpriteIds ();
6364
6465 var tieredOverlays = GsonHelper .getAsJsonObject (obj , "tiered_overlays" , new JsonObject ());
6566 for (var casingTier : tieredOverlays .keySet ()) {
66- var casingOverlaysJson = MachineOverlaysJson .parse (overlayClass , GsonHelper .getAsJsonObject (tieredOverlays , casingTier ),
67- defaultOverlaysJson );
67+ var casingOverlaysJson = OverlaysJson .parse (GsonHelper .getAsJsonObject (tieredOverlays , casingTier ), defaultOverlaysJson );
6868 this .tieredOverlays .put (ResourceLocation .parse (casingTier ), casingOverlaysJson .toSpriteIds ());
6969 }
7070 }
@@ -77,7 +77,7 @@ public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Functio
7777 for (var entry : this .tieredOverlays .entrySet ()) {
7878 tieredOverlays .put (entry .getKey (), loadSprites (spriteGetter , entry .getValue ()));
7979 }
80- return modelBaker . bake (baseCasing , outputOverlayIndexes , defaultOverlays , tieredOverlays );
80+ return new MachineBakedModel (baseCasing , defaultOverlays , tieredOverlays );
8181 }
8282
8383 private static TextureAtlasSprite [] loadSprites (Function <Material , TextureAtlasSprite > textureGetter , Material [] ids ) {
@@ -90,7 +90,7 @@ private static TextureAtlasSprite[] loadSprites(Function<Material, TextureAtlasS
9090 return sprites ;
9191 }
9292
93- private static class OverlaysJson implements MachineOverlaysJson {
93+ private static class OverlaysJson {
9494 // All fields are nullable.
9595 private ResourceLocation top ;
9696 private ResourceLocation top_active ;
@@ -126,13 +126,31 @@ private static class OverlaysJson implements MachineOverlaysJson {
126126 private ResourceLocation item_auto ;
127127 private ResourceLocation fluid_auto ;
128128
129+ private static OverlaysJson parse (JsonObject json , @ Nullable OverlaysJson defaultOverlay ) {
130+ var overlays = GSON .fromJson (json , OverlaysJson .class );
131+
132+ if (defaultOverlay != null ) {
133+ // Copy null fields from the default.
134+ try {
135+ for (var field : OverlaysJson .class .getDeclaredFields ()) {
136+ if (field .get (overlays ) == null ) {
137+ field .set (overlays , field .get (defaultOverlay ));
138+ }
139+ }
140+ } catch (IllegalAccessException ex ) {
141+ throw new RuntimeException ("Failed to copy fields from default overlay" , ex );
142+ }
143+ }
144+
145+ return overlays ;
146+ }
147+
129148 /**
130149 * Order is as follows:
131150 * Active and inactive: front, left, back, right, top S/W/N/E, bottom S/W/N/E,
132151 * output, item auto, fluid auto
133152 */
134- @ Override
135- public Material [] toSpriteIds () {
153+ private Material [] toSpriteIds () {
136154 return new Material [] {
137155 select (front , side ),
138156 select (front_active , front , side_active , side ),
@@ -164,9 +182,17 @@ public Material[] toSpriteIds() {
164182 };
165183 }
166184
167- @ Override
168- public int [] getOutputSpriteIndexes () {
169- return new int [] { 24 , 25 , 26 };
185+ /**
186+ * Select first non-null id, and convert it to a sprite id.
187+ */
188+ @ Nullable
189+ private static Material select (@ Nullable ResourceLocation ... candidates ) {
190+ for (var id : candidates ) {
191+ if (id != null ) {
192+ return new Material (InventoryMenu .BLOCK_ATLAS , id );
193+ }
194+ }
195+ return null ;
170196 }
171197 }
172198}
0 commit comments