diff --git a/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java b/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java index 1792c08..eec3644 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java @@ -4,11 +4,13 @@ import fr.sushi.charmsnfabrics.CharmsAndFabrics; import fr.sushi.charmsnfabrics.client.datagen.CnFBlockLootProvider; import fr.sushi.charmsnfabrics.client.datagen.CnFBlockTagsProvider; import fr.sushi.charmsnfabrics.client.datagen.CnFModelProvider; +import fr.sushi.charmsnfabrics.client.model.FlowerCrownItemModel; import fr.sushi.charmsnfabrics.client.model.FlowerCrownModel; import fr.sushi.charmsnfabrics.client.renderer.FloralWorkbenchRenderer; import fr.sushi.charmsnfabrics.client.renderer.FlowerCrownRenderer; import fr.sushi.charmsnfabrics.common.CnFRegistries; import net.minecraft.data.loot.LootTableProvider; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; @@ -17,6 +19,7 @@ import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.client.event.EntityRenderersEvent; +import net.neoforged.neoforge.client.event.RegisterItemModelsEvent; import net.neoforged.neoforge.client.gui.ConfigurationScreen; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.data.event.GatherDataEvent; @@ -39,7 +42,8 @@ public class CnFClient private static void onClientSetup(final FMLClientSetupEvent event) { ICurioRenderer.register(CnFRegistries.Items.FLOWER_CROWN.get(), - FlowerCrownRenderer::new); + () -> new FlowerCrownRenderer( + FlowerCrownRenderer.createModel())); } @SubscribeEvent @@ -70,4 +74,22 @@ public class CnFClient LootContextParamSets.BLOCK)), lookup)); event.createProvider(CnFBlockTagsProvider::new); } + + @SubscribeEvent + private static void onRegisterItemModels(final RegisterItemModelsEvent event) + { + event.register( + ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, + "flower_crown_loader"), + FlowerCrownItemModel.Unbaked.MAP_CODEC); + } + + // @SubscribeEvent + // private static void onRegisterStandaloneModels( + // ModelEvent.RegisterStandalone event) + // { + // event.register(new StandaloneModelKey<>( + // ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, + // "item/flower")), StandaloneModelBaker.quadCollection()); + // } } diff --git a/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java index 69fe5df..34192d1 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java @@ -5,19 +5,20 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import fr.sushi.charmsnfabrics.CharmsAndFabrics; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.BlockElement; -import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.block.model.TextureSlots; import net.minecraft.client.renderer.item.*; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.client.ClientHooks; +import net.neoforged.neoforge.client.NeoForgeRenderTypes; +import net.neoforged.neoforge.client.RenderTypeGroup; import net.neoforged.neoforge.client.model.ComposedModelState; import net.neoforged.neoforge.client.model.UnbakedElementsHelper; import org.jetbrains.annotations.Nullable; @@ -29,70 +30,76 @@ import java.util.List; public class FlowerCrownItemModel implements ItemModel { + /* TODO: Center flower0&1 textures and play with transform to get them at the right place for every layer */ + private static final Transformation TRANSFORM = + new Transformation(new Vector3f(), new Quaternionf(), + new Vector3f(1.0f, 1.0f, 1.004f), new Quaternionf()); private static final ModelDebugName DEBUG_NAME = () -> "FlowerCrownItemModel"; - // private final FlowerCrownItemModel.Unbaked unbakedModel; - // private final ItemTransforms transforms; - private final ItemModel bakedBase; - private final BakingContext bakingContext; - private final ItemTransforms baseTransform; + private final Unbaked rawModel; + private final BakingContext context; + private ModelRenderProperties renderProperties; - public FlowerCrownItemModel(ItemModel bakedBase, BakingContext context) + public FlowerCrownItemModel(Unbaked rawModel, BakingContext context) { - this.bakedBase = bakedBase; - this.bakingContext = context; - ResolvedModel baseItemModel = bakingContext.blockModelBaker().getModel( - ResourceLocation.withDefaultNamespace("item/generated")); - this.baseTransform = baseItemModel.getTopTransforms(); + this.rawModel = rawModel; + this.context = context; } private ResourceLocation getFlowerLocation(int layer) { return ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, - "flowers/flower" + layer); + "flower/flower" + layer); } - /* Prevent Z fighting */ - private Transformation getLayerTransform(int layer) + private static RenderTypeGroup getLayerRenderTypes(boolean unlit) { - return new Transformation(new Vector3f(), new Quaternionf(), - new Vector3f(0.0f, 0.0f, 1.0f + (layer / 100f)), - new Quaternionf()); + return new RenderTypeGroup(RenderType.translucent(), unlit ? + NeoForgeRenderTypes.ITEM_UNSORTED_UNLIT_TRANSLUCENT.get() : + NeoForgeRenderTypes.ITEM_UNSORTED_TRANSLUCENT.get()); } - public ItemModel bakeForColors(List colors) + /** + * Bakes the base and updates the LayerRenderState quads + */ + private ItemModel bakeBase() { - ModelState state = BlockModelRotation.X0_Y0; - SpriteGetter sprites = this.bakingContext.blockModelBaker().sprites(); + ModelBaker baker = this.context.blockModelBaker(); + ResolvedModel resolvedModel = baker.getModel(this.rawModel.base); + TextureSlots slots = resolvedModel.getTopTextureSlots(); - List submodels = new ArrayList<>(); - submodels.add(this.bakedBase); + List quads = resolvedModel + .bakeTopGeometry(slots, baker, BlockModelRotation.X0_Y0) + .getAll(); + this.renderProperties = + ModelRenderProperties.fromResolvedModel(baker, resolvedModel, + slots); + return new BlockModelWrapper(List.of(), quads, this.renderProperties); + } - for (int layer = 0; layer < colors.size(); layer++) - { - ResourceLocation texture = this.getFlowerLocation(layer); - Material material = ClientHooks.getBlockMaterial(texture); - TextureAtlasSprite sprite = sprites.get(material, DEBUG_NAME); + private ItemModel bakeLayer(int layer) + { + SpriteGetter sprites = this.context.blockModelBaker().sprites(); + Material material = + ClientHooks.getBlockMaterial(this.getFlowerLocation(layer)); + TextureAtlasSprite sprite = sprites.get(material, DEBUG_NAME); + /* Create all the bits that makes the model */ + List bits = + UnbakedElementsHelper.createUnbakedItemElements(0, sprite); + List quads = + UnbakedElementsHelper.bakeElements(bits, $ -> sprite, + new ComposedModelState(BlockModelRotation.X0_Y0, + TRANSFORM)); + return new BlockModelWrapper(List.of(), quads, this.renderProperties); + } - /* ***** TODO: Multiply pixels with dye color **** */ - - List unbaked = - UnbakedElementsHelper.createUnbakedItemElements(0, sprite); - List quads = - UnbakedElementsHelper.bakeElements(unbaked, mat -> sprite, - new ComposedModelState(state, - this.getLayerTransform(layer))); - - ModelRenderProperties renderProperties = - new ModelRenderProperties(false, sprite, - this.baseTransform); - submodels.add( - new BlockModelWrapper(List.of(), quads, renderProperties)); - } - - /* ****************************************************************** */ - return new CompositeModel(submodels); + private CompositeModel composeModel() + { + List models = new ArrayList<>(); + models.add(this.bakeBase()); + models.add(this.bakeLayer(0)); + return new CompositeModel(models); } @Override @@ -101,18 +108,18 @@ public class FlowerCrownItemModel implements ItemModel ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { - ItemStackRenderState.LayerRenderState freshLayer = - renderState.newLayer(); + this.composeModel() + .update(renderState, stack, itemModelResolver, displayContext, + level, entity, seed); } - public record Unbaked( - ResourceLocation baseModel) implements ItemModel.Unbaked + public record Unbaked(ResourceLocation base) implements ItemModel.Unbaked { public static final MapCodec MAP_CODEC = RecordCodecBuilder.mapCodec(unbaked -> unbaked .group(ResourceLocation.CODEC.fieldOf("base").forGetter( - FlowerCrownItemModel.Unbaked::baseModel)) + FlowerCrownItemModel.Unbaked::base)) .apply(unbaked, FlowerCrownItemModel.Unbaked::new)); @Override @@ -124,32 +131,13 @@ public class FlowerCrownItemModel implements ItemModel @Override public ItemModel bake(BakingContext context) { - ModelBaker modelbaker = context.blockModelBaker(); - ResolvedModel resolved = modelbaker.getModel(this.baseModel); - List quads = resolved - .bakeTopGeometry(resolved.getTopTextureSlots(), modelbaker, - BlockModelRotation.X0_Y0).getAll(); - - ItemModel bakedBase = new BlockModelWrapper(List.of(), quads, - this.getRenderProperties(context)); - return new FlowerCrownItemModel(bakedBase, context); + return new FlowerCrownItemModel(this, context); } @Override public void resolveDependencies(Resolver resolver) { - resolver.markDependency(this.baseModel); - } - - /* A vérifier, pas sûr sûr de celle là Y-Y */ - private ModelRenderProperties getRenderProperties( - ItemModel.BakingContext context) - { - ModelBaker modelbaker = context.blockModelBaker(); - ResolvedModel resolvedmodel = modelbaker.getModel(this.baseModel); - TextureSlots textureslots = resolvedmodel.getTopTextureSlots(); - return ModelRenderProperties.fromResolvedModel(modelbaker, - resolvedmodel, textureslots); + resolver.markDependency(this.base); } } } \ No newline at end of file diff --git a/src/main/java/fr/sushi/charmsnfabrics/client/renderer/FlowerCrownRenderer.java b/src/main/java/fr/sushi/charmsnfabrics/client/renderer/FlowerCrownRenderer.java index 8afa348..4ddb010 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/renderer/FlowerCrownRenderer.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/renderer/FlowerCrownRenderer.java @@ -4,15 +4,19 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import fr.sushi.charmsnfabrics.client.CnFLayers; import fr.sushi.charmsnfabrics.client.model.FlowerCrownModel; +import fr.sushi.charmsnfabrics.common.data.SavedColors; import fr.sushi.charmsnfabrics.common.item.FlowerCrown; import net.minecraft.client.Minecraft; import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; +import net.minecraft.client.renderer.item.BlockModelWrapper; +import net.minecraft.client.renderer.item.ItemModel; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; @@ -24,11 +28,15 @@ public class FlowerCrownRenderer implements ICurioRenderer { private final FlowerCrownModel model; - public FlowerCrownRenderer() + public FlowerCrownRenderer(FlowerCrownModel model) { - this.model = new FlowerCrownModel( - Minecraft.getInstance().getEntityModels() - .bakeLayer(CnFLayers.CROWN_LAYER)); + this.model = model; + } + + public static FlowerCrownModel createModel() + { + EntityModelSet modelSet = Minecraft.getInstance().getEntityModels(); + return new FlowerCrownModel(modelSet.bakeLayer(CnFLayers.CROWN_LAYER)); } @Override diff --git a/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java b/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java index 80bb504..6952ff9 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java +++ b/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java @@ -2,8 +2,6 @@ package fr.sushi.charmsnfabrics.common.item; import fr.sushi.charmsnfabrics.CharmsAndFabrics; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import top.theillusivec4.curios.api.SlotContext; @@ -31,6 +29,28 @@ public class FlowerCrown extends Item implements ICurioItem public ResourceLocation getModelTexture() { return ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, - "textures/models/accessory/flower_crown.png"); + "textures/models/accessory/flower_crown.png"); } + +// @Override +// public InteractionResult useOn(UseOnContext context) +// { +// var player = context.getPlayer(); +// var level = context.getLevel(); +// var hand = context.getHand(); +// +// ItemStack stack = player.getItemInHand(hand); +// SavedColors comp = +// stack.get(CnFRegistries.DataComponents.SAVED_FLOWERS.get()); +// +// stack.set(CnFRegistries.DataComponents.SAVED_FLOWERS.get(), +// new SavedColors(List.of(DyeColor.PURPLE, DyeColor.LIME))); +// if (comp != null && !comp.flowers().isEmpty()) +// { +// player.displayClientMessage(Component.literal( +// comp.flowers().stream().map(DyeColor::toString) +// .collect(Collectors.joining(" "))), false); +// } +// return InteractionResult.SUCCESS; +// } } diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower0.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower0.png similarity index 100% rename from src/main/resources/assets/charmsnfabrics/textures/flowers/flower0.png rename to src/main/resources/assets/charmsnfabrics/textures/flower/flower0.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower1.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower1.png similarity index 100% rename from src/main/resources/assets/charmsnfabrics/textures/flowers/flower1.png rename to src/main/resources/assets/charmsnfabrics/textures/flower/flower1.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower2.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower2.png similarity index 100% rename from src/main/resources/assets/charmsnfabrics/textures/flowers/flower2.png rename to src/main/resources/assets/charmsnfabrics/textures/flower/flower2.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower3.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower3.png similarity index 100% rename from src/main/resources/assets/charmsnfabrics/textures/flowers/flower3.png rename to src/main/resources/assets/charmsnfabrics/textures/flower/flower3.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower4.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower4.png similarity index 100% rename from src/main/resources/assets/charmsnfabrics/textures/flowers/flower4.png rename to src/main/resources/assets/charmsnfabrics/textures/flower/flower4.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower5.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower5.png similarity index 100% rename from src/main/resources/assets/charmsnfabrics/textures/flowers/flower5.png rename to src/main/resources/assets/charmsnfabrics/textures/flower/flower5.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower6.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower6.png similarity index 100% rename from src/main/resources/assets/charmsnfabrics/textures/flowers/flower6.png rename to src/main/resources/assets/charmsnfabrics/textures/flower/flower6.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/gui/container/floral_workbench.png b/src/main/resources/assets/charmsnfabrics/textures/gui/container/floral_workbench.png deleted file mode 100644 index de8290c..0000000 Binary files a/src/main/resources/assets/charmsnfabrics/textures/gui/container/floral_workbench.png and /dev/null differ diff --git a/src/main/resources/assets/charmsnfabrics/textures/item/flower_crown.png b/src/main/resources/assets/charmsnfabrics/textures/item/flower_crown.png index 7912290..a79300a 100644 Binary files a/src/main/resources/assets/charmsnfabrics/textures/item/flower_crown.png and b/src/main/resources/assets/charmsnfabrics/textures/item/flower_crown.png differ diff --git a/src/main/resources/assets/charmsnfabrics/textures/item/flower_crown_old.png b/src/main/resources/assets/charmsnfabrics/textures/item/flower_crown_old.png new file mode 100644 index 0000000..7912290 Binary files /dev/null and b/src/main/resources/assets/charmsnfabrics/textures/item/flower_crown_old.png differ diff --git a/src/main/resources/assets/minecraft/atlases/blocks.json b/src/main/resources/assets/minecraft/atlases/blocks.json new file mode 100644 index 0000000..6b18f8b --- /dev/null +++ b/src/main/resources/assets/minecraft/atlases/blocks.json @@ -0,0 +1,9 @@ +{ + "sources": [ + { + "type": "minecraft:directory", + "prefix": "flower/", + "source": "flower" + } + ] +} \ No newline at end of file