From 0589d18f154d406a3e5559d2f1e9abdaf7336557 Mon Sep 17 00:00:00 2001 From: covers1624 Date: Mon, 13 Nov 2023 04:05:38 +1030 Subject: [PATCH] Add 'ClassModelLoader' - Instantiates a specific class for the model. --- .../lib/datagen/ItemModelProvider.java | 44 ++++++++++++++++ .../codechicken/lib/internal/ClientInit.java | 2 + .../lib/model/ClassModelLoader.java | 51 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/main/java/codechicken/lib/model/ClassModelLoader.java diff --git a/src/main/java/codechicken/lib/datagen/ItemModelProvider.java b/src/main/java/codechicken/lib/datagen/ItemModelProvider.java index a91a4d8a..96b21847 100644 --- a/src/main/java/codechicken/lib/datagen/ItemModelProvider.java +++ b/src/main/java/codechicken/lib/datagen/ItemModelProvider.java @@ -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; @@ -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; @@ -138,6 +141,18 @@ protected void simpleItemBlock(Block block) { .parent(new ModelFile.UncheckedModelFile(modLoc("block/" + name(block)))) .noTexture(); } + + protected SimpleItemModelBuilder clazz(Supplier item, Class clazz) { + return clazz(item.get(), clazz); + } + + protected SimpleItemModelBuilder clazz(ItemLike item, Class clazz) { + return generated(item) + .noTexture() + .customLoader(ClassCustomLoaderBuilder::new) + .clazz(clazz) + .end(); + } //endregion private SimpleItemModelBuilder makeNested(ItemLike item) { @@ -328,6 +343,35 @@ protected JsonObject toJson(JsonObject json) { } } + public static class ClassCustomLoaderBuilder extends CustomLoaderBuilder { + + private @Nullable Class clazz; + + protected ClassCustomLoaderBuilder(SimpleItemModelBuilder parent) { + super(new ResourceLocation(MOD_ID, "class"), parent); + } + + public ClassCustomLoaderBuilder clazz(Class 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 children = new LinkedHashMap<>(); diff --git a/src/main/java/codechicken/lib/internal/ClientInit.java b/src/main/java/codechicken/lib/internal/ClientInit.java index ed96cd2c..a0186ba8 100644 --- a/src/main/java/codechicken/lib/internal/ClientInit.java +++ b/src/main/java/codechicken/lib/internal/ClientInit.java @@ -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; @@ -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()); } } diff --git a/src/main/java/codechicken/lib/model/ClassModelLoader.java b/src/main/java/codechicken/lib/model/ClassModelLoader.java new file mode 100644 index 00000000..8238e397 --- /dev/null +++ b/src/main/java/codechicken/lib/model/ClassModelLoader.java @@ -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 { + + @Override + public Geometry read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) throws JsonParseException { + try { + Class clazz = Class.forName(JsonUtils.getString(jsonObject, "class")); + Constructor ctor = unsafeCast(clazz.getConstructor()); + return new Geometry(ctor); + } catch (ClassNotFoundException | NoSuchMethodException ex) { + throw new RuntimeException(ex); + } + } + + public record Geometry(Constructor ctor) implements IUnbakedGeometry { + + @Override + public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation) { + try { + return ctor.newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) { + throw new RuntimeException("Failed to construct class.", ex); + } + } + } +}