Skip to content

Commit

Permalink
Add 'ClassModelLoader' - Instantiates a specific class for the model.
Browse files Browse the repository at this point in the history
  • Loading branch information
covers1624 committed Nov 13, 2023
1 parent fa868eb commit 0589d18
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/main/java/codechicken/lib/datagen/ItemModelProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
Expand All @@ -17,6 +18,8 @@
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
Expand Down Expand Up @@ -138,6 +141,18 @@ protected void simpleItemBlock(Block block) {
.parent(new ModelFile.UncheckedModelFile(modLoc("block/" + name(block))))
.noTexture();
}

protected SimpleItemModelBuilder clazz(Supplier<? extends Item> item, Class<? extends BakedModel> clazz) {
return clazz(item.get(), clazz);
}

protected SimpleItemModelBuilder clazz(ItemLike item, Class<? extends BakedModel> clazz) {
return generated(item)
.noTexture()
.customLoader(ClassCustomLoaderBuilder::new)
.clazz(clazz)
.end();
}
//endregion

private SimpleItemModelBuilder makeNested(ItemLike item) {
Expand Down Expand Up @@ -328,6 +343,35 @@ protected JsonObject toJson(JsonObject json) {
}
}

public static class ClassCustomLoaderBuilder extends CustomLoaderBuilder {

private @Nullable Class<? extends BakedModel> clazz;

protected ClassCustomLoaderBuilder(SimpleItemModelBuilder parent) {
super(new ResourceLocation(MOD_ID, "class"), parent);
}

public ClassCustomLoaderBuilder clazz(Class<? extends BakedModel> clazz) {
try {
Constructor<?> ctor = clazz.getConstructor();
if (!Modifier.isPublic(ctor.getModifiers())) {
throw new IllegalArgumentException("Expected single no-args public constructor.");
}
} catch (NoSuchMethodException ex) {
throw new IllegalStateException("Expected single no-args public constructor.", ex);
}
this.clazz = clazz;
return this;
}

@Override
protected JsonObject toJson(JsonObject json) {
super.toJson(json);
json.addProperty("class", Objects.requireNonNull(clazz).getName());
return json;
}
}

public static class CompositeLoaderBuilder extends CustomLoaderBuilder {

private final Map<String, SimpleItemModelBuilder> children = new LinkedHashMap<>();
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/codechicken/lib/internal/ClientInit.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import codechicken.lib.config.ConfigCategory;
import codechicken.lib.config.ConfigSyncManager;
import codechicken.lib.model.CompositeItemModel;
import codechicken.lib.model.ClassModelLoader;
import codechicken.lib.render.CCRenderEventHandler;
import codechicken.lib.render.block.BlockRenderingRegistry;
import net.covers1624.quack.util.CrashLock;
Expand Down Expand Up @@ -71,5 +72,6 @@ private static void onClientDisconnected(ClientPlayerNetworkEvent.LoggingOut eve

private static void onRegisterGeometryLoaders(ModelEvent.RegisterGeometryLoaders event) {
event.register("item_composite", new CompositeItemModel());
event.register("class", new ClassModelLoader());
}
}
51 changes: 51 additions & 0 deletions src/main/java/codechicken/lib/model/ClassModelLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package codechicken.lib.model;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.covers1624.quack.gson.JsonUtils;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
import net.minecraftforge.client.model.geometry.IGeometryLoader;
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.function.Function;

import static net.covers1624.quack.util.SneakyUtils.unsafeCast;

/**
* Created by covers1624 on 13/11/23.
*/
public class ClassModelLoader implements IGeometryLoader<ClassModelLoader.Geometry> {

@Override
public Geometry read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) throws JsonParseException {
try {
Class<?> clazz = Class.forName(JsonUtils.getString(jsonObject, "class"));
Constructor<? extends BakedModel> ctor = unsafeCast(clazz.getConstructor());
return new Geometry(ctor);
} catch (ClassNotFoundException | NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
}

public record Geometry(Constructor<? extends BakedModel> ctor) implements IUnbakedGeometry<Geometry> {

@Override
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation) {
try {
return ctor.newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException("Failed to construct class.", ex);
}
}
}
}

0 comments on commit 0589d18

Please sign in to comment.