From a8990da272104d0b39f00611a74d8ed840231e7a Mon Sep 17 00:00:00 2001 From: SushiCannibale Date: Wed, 6 Aug 2025 00:30:44 +0200 Subject: [PATCH 1/8] feat: flower crown model type + layers baking (WIP) --- .../client/model/FlowerCrownItemModel.java | 155 ++++++++++++++++++ .../textures/flowers/flower0.png | Bin 0 -> 104 bytes 2 files changed, 155 insertions(+) create mode 100644 src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flowers/flower0.png diff --git a/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java new file mode 100644 index 0000000..69fe5df --- /dev/null +++ b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java @@ -0,0 +1,155 @@ +package fr.sushi.charmsnfabrics.client.model; + +import com.mojang.math.Transformation; +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.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.model.ComposedModelState; +import net.neoforged.neoforge.client.model.UnbakedElementsHelper; +import org.jetbrains.annotations.Nullable; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; + +public class FlowerCrownItemModel implements ItemModel +{ + 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; + + public FlowerCrownItemModel(ItemModel bakedBase, BakingContext context) + { + this.bakedBase = bakedBase; + this.bakingContext = context; + ResolvedModel baseItemModel = bakingContext.blockModelBaker().getModel( + ResourceLocation.withDefaultNamespace("item/generated")); + this.baseTransform = baseItemModel.getTopTransforms(); + } + + private ResourceLocation getFlowerLocation(int layer) + { + return ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, + "flowers/flower" + layer); + } + + /* Prevent Z fighting */ + private Transformation getLayerTransform(int layer) + { + return new Transformation(new Vector3f(), new Quaternionf(), + new Vector3f(0.0f, 0.0f, 1.0f + (layer / 100f)), + new Quaternionf()); + } + + public ItemModel bakeForColors(List colors) + { + ModelState state = BlockModelRotation.X0_Y0; + SpriteGetter sprites = this.bakingContext.blockModelBaker().sprites(); + + List submodels = new ArrayList<>(); + submodels.add(this.bakedBase); + + 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); + + /* ***** 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); + } + + @Override + public void update(ItemStackRenderState renderState, ItemStack stack, + ItemModelResolver itemModelResolver, + ItemDisplayContext displayContext, @Nullable ClientLevel level, + @Nullable LivingEntity entity, int seed) + { + ItemStackRenderState.LayerRenderState freshLayer = + renderState.newLayer(); + } + + public record Unbaked( + ResourceLocation baseModel) implements ItemModel.Unbaked + { + + public static final MapCodec MAP_CODEC = + RecordCodecBuilder.mapCodec(unbaked -> unbaked + .group(ResourceLocation.CODEC.fieldOf("base").forGetter( + FlowerCrownItemModel.Unbaked::baseModel)) + .apply(unbaked, FlowerCrownItemModel.Unbaked::new)); + + @Override + public MapCodec type() + { + return MAP_CODEC; + } + + @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); + } + + @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); + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower0.png b/src/main/resources/assets/charmsnfabrics/textures/flowers/flower0.png new file mode 100644 index 0000000000000000000000000000000000000000..4d44cd0d8cf7faab79b9ee3b99b64131cbcf3c76 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|lssJ=Lo9le y6C_v{Cj>NI-v0m3a*xmdfgm`C Date: Fri, 8 Aug 2025 17:42:10 +0200 Subject: [PATCH 2/8] feat: flower layers texture --- .../charmsnfabrics/textures/flowers/flower0.png | Bin 104 -> 141 bytes .../charmsnfabrics/textures/flowers/flower1.png | Bin 0 -> 142 bytes .../charmsnfabrics/textures/flowers/flower2.png | Bin 0 -> 112 bytes .../charmsnfabrics/textures/flowers/flower3.png | Bin 0 -> 142 bytes .../charmsnfabrics/textures/flowers/flower4.png | Bin 0 -> 107 bytes .../charmsnfabrics/textures/flowers/flower5.png | Bin 0 -> 141 bytes .../charmsnfabrics/textures/flowers/flower6.png | Bin 0 -> 107 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flowers/flower1.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flowers/flower2.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flowers/flower3.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flowers/flower4.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flowers/flower5.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flowers/flower6.png diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower0.png b/src/main/resources/assets/charmsnfabrics/textures/flowers/flower0.png index 4d44cd0d8cf7faab79b9ee3b99b64131cbcf3c76..ca421822cfc21454c37d59e61d906b5961d230cb 100644 GIT binary patch delta 98 zcmV-o0GR delta 61 zcmeBW%$Q(kuH@o=L!-(C9e|9|QFIc)|HjUU`x`krTwkrU7Tb9WOe%3fMW p_9fg1{P^vEU)T00m5q7~3~X{rdS%}x`vA>k@O1TaS?83{1OV4JHR%8V literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower2.png b/src/main/resources/assets/charmsnfabrics/textures/flowers/flower2.png new file mode 100644 index 0000000000000000000000000000000000000000..e4748c0e8dfa660f272786a7debe29498051c16e GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|v^-rLLo9le z6C_v{Cny~F{{H@d<-drkY^OIC;%YU9{V6*$nTpf3V pH!CWB*SjB${$SaM^vbKn)C@u6{1-oD!M< D++QGR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower5.png b/src/main/resources/assets/charmsnfabrics/textures/flowers/flower5.png new file mode 100644 index 0000000000000000000000000000000000000000..c438b86719e6b7df1ae0d54604d633ac5f390d61 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|+&x_!Lo9le z6C_F={Qmy_|Ni>_|K>-0^?5PtzpPopgC9}{9o8snu-*CpV`3u^Jp8{pyuj?_gInF= n|JU!WaNHv9c2Gk?hJnFqj#AZ?)yKC1jb!k2^>bP0l+XkKAVoIk literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/charmsnfabrics/textures/flowers/flower6.png b/src/main/resources/assets/charmsnfabrics/textures/flowers/flower6.png new file mode 100644 index 0000000000000000000000000000000000000000..762765ba5a965881ad43063bc211794bbeec2c89 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|R6SiBLo9le z6C_xhIrdome{b(P>;L|b|LZevnt$S5= Date: Fri, 8 Aug 2025 22:51:18 +0200 Subject: [PATCH 3/8] feat: flower color data component --- .../charmsnfabrics/common/CnFRegistries.java | 25 +++++++++++++++++-- .../common/data/SavedColors.java | 24 ++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java diff --git a/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java b/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java index 33e439b..0fd89b3 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java +++ b/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java @@ -2,8 +2,10 @@ package fr.sushi.charmsnfabrics.common; import fr.sushi.charmsnfabrics.CharmsAndFabrics; import fr.sushi.charmsnfabrics.common.block.FloralWorkbench; +import fr.sushi.charmsnfabrics.common.data.SavedColors; import fr.sushi.charmsnfabrics.common.entities.block.FloralWorkbenchBlockEntity; import fr.sushi.charmsnfabrics.common.item.FlowerCrown; +import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; @@ -22,6 +24,7 @@ import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredItem; import net.neoforged.neoforge.registries.DeferredRegister; +import java.util.List; import java.util.Set; import java.util.function.Supplier; @@ -33,8 +36,11 @@ public class CnFRegistries DeferredRegister.createItems(CharmsAndFabrics.MODID); public static final DeferredItem FLOWER_CROWN = ITEMS.registerItem("flower_crown", - (properties) -> new FlowerCrown( - properties.stacksTo(1))); + (properties) -> new FlowerCrown(properties.stacksTo(1) + .component( + DataComponents.SAVED_FLOWERS, + new SavedColors( + List.of())))); /* BlockItems */ public static final DeferredItem FLORAL_WORKBENCH = ITEMS.registerItem("floral_workbench", @@ -100,11 +106,26 @@ public class CnFRegistries Set.of(Blocks.FLORAL_WORKBENCH.get()))); } + public static class DataComponents + { + public static final DeferredRegister.DataComponents COMPONENT_TYPES = + DeferredRegister.createDataComponents( + Registries.DATA_COMPONENT_TYPE, CharmsAndFabrics.MODID); + + public static final Supplier> + SAVED_FLOWERS = + COMPONENT_TYPES.registerComponentType("saved_flowers", + builder -> builder.persistent(SavedColors.CODEC) + .networkSynchronized( + SavedColors.STREAM_CODEC)); + } + public static void register(IEventBus bus) { Items.ITEMS.register(bus); Blocks.BLOCKS.register(bus); Tabs.CREATIVE_MODE_TABS.register(bus); Entities.BLOCK_ENTITY_TYPES.register(bus); + DataComponents.COMPONENT_TYPES.register(bus); } } diff --git a/src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java b/src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java new file mode 100644 index 0000000..5eb10b5 --- /dev/null +++ b/src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java @@ -0,0 +1,24 @@ +package fr.sushi.charmsnfabrics.common.data; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.item.DyeColor; + +import java.util.List; + +public record SavedColors(List flowers) +{ + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance + .group(DyeColor.CODEC.listOf().fieldOf("flowers") + .forGetter(SavedColors::flowers)) + .apply(instance, SavedColors::new)); + + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + DyeColor.STREAM_CODEC.apply(ByteBufCodecs.list(256)), + SavedColors::flowers, SavedColors::new); +} From f73affdb2c7d6ff052d2b6b8d33b928c708694e1 Mon Sep 17 00:00:00 2001 From: SushiCannibale Date: Mon, 11 Aug 2025 23:57:31 +0200 Subject: [PATCH 4/8] feat: dynamic flower crown model + other thingsss --- .../charmsnfabrics/client/CnFClient.java | 24 +++- .../client/model/FlowerCrownItemModel.java | 134 ++++++++---------- .../client/renderer/FlowerCrownRenderer.java | 16 ++- .../common/item/FlowerCrown.java | 26 +++- .../textures/{flowers => flower}/flower0.png | Bin .../textures/{flowers => flower}/flower1.png | Bin .../textures/{flowers => flower}/flower2.png | Bin .../textures/{flowers => flower}/flower3.png | Bin .../textures/{flowers => flower}/flower4.png | Bin .../textures/{flowers => flower}/flower5.png | Bin .../textures/{flowers => flower}/flower6.png | Bin .../gui/container/floral_workbench.png | Bin 1944 -> 0 bytes .../textures/item/flower_crown.png | Bin 362 -> 201 bytes .../textures/item/flower_crown_old.png | Bin 0 -> 362 bytes .../assets/minecraft/atlases/blocks.json | 9 ++ 15 files changed, 128 insertions(+), 81 deletions(-) rename src/main/resources/assets/charmsnfabrics/textures/{flowers => flower}/flower0.png (100%) rename src/main/resources/assets/charmsnfabrics/textures/{flowers => flower}/flower1.png (100%) rename src/main/resources/assets/charmsnfabrics/textures/{flowers => flower}/flower2.png (100%) rename src/main/resources/assets/charmsnfabrics/textures/{flowers => flower}/flower3.png (100%) rename src/main/resources/assets/charmsnfabrics/textures/{flowers => flower}/flower4.png (100%) rename src/main/resources/assets/charmsnfabrics/textures/{flowers => flower}/flower5.png (100%) rename src/main/resources/assets/charmsnfabrics/textures/{flowers => flower}/flower6.png (100%) delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/gui/container/floral_workbench.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/item/flower_crown_old.png create mode 100644 src/main/resources/assets/minecraft/atlases/blocks.json 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 de8290c346c423d688526d3483f90de4e4b810c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1944 zcmcIldsGru7{3t9NBKa_%m?^dWm(Y7$siS9C}C)7X=(UiYo<$=X4rIsYiYWymZeS; zEt`Voqhrey6)TN$qDCy|(l9;hlw(XBDxxr`Q`>Uu4w0MH5|dV7SVUYQwok3BTG zL2G2eyh%uAUo{OQ6?l8?_4E@P^Hvr3TA#9K<{G&J;M78@&hv-L{HTu+sgm3bZke#oZd8=PrznZuKWCcB=n z?9o)onv#-|d^0V}U#6$yZXK)*3lD$h0&~mw)W+6!`%nThERjmJE9Osp+g`c-TnfEh z&dzWCF1W8`$r{ORG)#7?BJ8?0{n3fvsycpe{+wgAfSj@10;9Av8>vI1%8Jqui4qQF znB)AlFG-fw(ay0SU1F$IYEQ)#M+m-FwkGrW1nLuA2n0Vfvkt0oraO?d)5o>||C;ta zX>!7lDz26uI7b_Z|FFc)>_|!xrlNF7_+9uJf z0b2+7^%ybO`WDG780Y)bb*lz^ZJ0KuOy}=*gW1xQxO&l(VIBwgf7g6z3 zT-QC%y5LxrJ_KFf)zy{RuI#?N74aj*u9RGL<_zZ8Xy+Wq1exHv_3-5RebPD~5-__+ zt_t3z5T9P`9V;VLJ#jb~Kbe~y-k0ly;;wr}W18e6L=+fU`=|;R$#e)ypY=&^X*7U>@sd*e^>w2#0X;-S^sXRu}n}2P0bd(Mn8jd_VBVSq;&ruONV@VU!v!l~U(b;%+ zIoj5?x3|}=Oj@RrKO%T{&X;cLs&Se-CiQhcGlL7rmCA@lz)Lv1*v4;{J$^bzUk{TB z4&p*vaSO!O`RqhV+%m=BHg5KQWQIF)c?CHe#c}Gjc}Y^^^WYz9r>xF2WSyr?y5(rl z)7=yz406-LN-Jp~z(r}IaSB4Fy8<$2i3^d?2s}2sWjI?2TE-3}F zCwbxZt#FI7VGCZrzCDP-Yp#kEDJaLWrPo^5-YHYl^;!A}lpA;c_^4Q=4FO)WeIg~Q z1qCUnFXSi_McBwog*qy!m>!VC;%IB?+)(JWJeEGogOAh^;$f0&K z6;>53%DZ>0Q3vy}!ugIfy{)vg^ypC9V#8)thK9MjPlh>4Nu(&DRaG-cG)P$wLEF#O z_etWU8G4doF0(~6=+2$LbN5tQv?;)JlNrf5CVml_tFj3=R!h zvQ{e^VgJ-v?@%C4Lv%FgqeFbHs@ZV3&t4NaT!cxzn}eSYxk{Gg;A?7X;P9KbZ=24J z_n}b_HS6u?j57&5#NRgXJ9RW|Z=5M)r&|$teFrA*=IHzy z5|vUNShWxmmBnLsXi)Q~9^d@;1SM~2z+SGu|0`x)5qm6TYlzXcVBCMK&~x1Qfi4EiH&B0r|I5JZtspVF7d%e6zuc`U NK=dJd*Lg;L^#`E0Fx>zE 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 79122903bb45386cd3260f164b37b9edd6884330..a79300ab5fd5c4b4e76995d5a6fd3746b7b2e360 100644 GIT binary patch delta 161 zcmV;S0ABy<0?7f8Fn<7pNkly%wfGinYLw3Q*;u{{F9m*RToSF{=b52i_G%dwJyzPDO?tS;}fPV)Op@^_OGpmM& z_tinwACR}9nOha2Vdlf)Kb8qiDJF5gRB4prEPi0q5)MY}>fS6NM!)eO^s zmNOW#Hio-$$~;CdsEuKm2JEM9TRLd3U7?q_EaHldUT{}VS;W=J8FgS&|CRVp@CDNS V<#Px$BuPX;R5*>zQ87!yP#C;O94by-lA+*OC^V~d@+TA`S^Om#G6?>Q{D3SOTtjxj z$>JLxogK;>8l0LB1anSLlQb>GLA>pK@9ur~?tp&>5uu2%Ju|C@hxmKqT{$JUONt1i zd``1!$nBCUs|O!(+6Qe6uhb1jlQGugN6dWR0RWZNd^o?x=evXZ%Vz*UaCgzs!b@C+ zX+UiZwK0R+R91gGw2saIAj;=_z5T$`o5sxd9lN=YjS`F|W7IEeY?O3EI`+>tinwAC zR}9nOha2Vdlf)Kb8qiDJF5gRB4prEPi0q5)MY}>fS6NM!)eO^smNOW#Hio-$%0@4! zjbWGu?5A#9I%uz5p_jNU;);!4a92)Q#MQ|ebzoEfmH1Ea1=9WHcuyU{egFUf07*qo IM6N<$f>k4(@&Et; literal 0 HcmV?d00001 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 From 9bcabeb8f751d5150bf753af50726569b85521d9 Mon Sep 17 00:00:00 2001 From: SushiCannibale Date: Tue, 12 Aug 2025 22:14:54 +0200 Subject: [PATCH 5/8] feat: flower_crown composite model --- .../client/model/FlowerCrownItemModel.java | 74 +++++++++++++++--- .../textures/flower/flower0.png | Bin 141 -> 0 bytes .../textures/flower/flower1.png | Bin 142 -> 0 bytes .../textures/flower/flower2.png | Bin 112 -> 0 bytes .../textures/flower/flower3.png | Bin 142 -> 0 bytes .../textures/flower/flower4.png | Bin 107 -> 0 bytes .../textures/flower/flower5.png | Bin 141 -> 0 bytes .../textures/flower/flower6.png | Bin 107 -> 0 bytes .../textures/flower/flower_large.png | Bin 0 -> 141 bytes .../textures/flower/flower_small.png | Bin 0 -> 112 bytes 10 files changed, 61 insertions(+), 13 deletions(-) delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower0.png delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower1.png delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower2.png delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower3.png delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower4.png delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower5.png delete mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower6.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower_large.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower_small.png 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 34192d1..d0adcc0 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java @@ -4,6 +4,8 @@ import com.mojang.math.Transformation; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import fr.sushi.charmsnfabrics.CharmsAndFabrics; +import fr.sushi.charmsnfabrics.common.CnFRegistries; +import fr.sushi.charmsnfabrics.common.data.SavedColors; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -14,6 +16,7 @@ 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; @@ -26,14 +29,49 @@ import org.joml.Quaternionf; import org.joml.Vector3f; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; 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 Map TRANSFORMS = + new HashMap<>(); + + static + { + TRANSFORMS.put(0, new Transformation( + new Vector3f(1f * 0.0625f, -4f * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), + new Quaternionf())); + TRANSFORMS.put(1, new Transformation( + new Vector3f(5f * 0.0625f, -3f * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), + new Quaternionf())); + TRANSFORMS.put(2, new Transformation( + new Vector3f(5f * 0.0625f, 2f * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), + new Quaternionf())); + TRANSFORMS.put(3, new Transformation( + new Vector3f(2f * 0.0625f, 4f * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), + new Quaternionf())); + TRANSFORMS.put(4, new Transformation( + new Vector3f(-3f * 0.0625f, 4f * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), + new Quaternionf())); + TRANSFORMS.put(5, new Transformation( + new Vector3f(-5f * 0.0625f, 0f * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), + new Quaternionf())); + TRANSFORMS.put(6, new Transformation( + new Vector3f(-4f * 0.0625f, -3f * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), + new Quaternionf())); + } + private static final ModelDebugName DEBUG_NAME = () -> "FlowerCrownItemModel"; @@ -49,8 +87,9 @@ public class FlowerCrownItemModel implements ItemModel private ResourceLocation getFlowerLocation(int layer) { + return ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, - "flower/flower" + layer); + "flower/flower_" + (layer % 2 == 0 ? "large" : "small")); } private static RenderTypeGroup getLayerRenderTypes(boolean unlit) @@ -78,7 +117,7 @@ public class FlowerCrownItemModel implements ItemModel return new BlockModelWrapper(List.of(), quads, this.renderProperties); } - private ItemModel bakeLayer(int layer) + private ItemModel bakeLayer(int layer, DyeColor color) { SpriteGetter sprites = this.context.blockModelBaker().sprites(); Material material = @@ -90,15 +129,18 @@ public class FlowerCrownItemModel implements ItemModel List quads = UnbakedElementsHelper.bakeElements(bits, $ -> sprite, new ComposedModelState(BlockModelRotation.X0_Y0, - TRANSFORM)); + TRANSFORMS.get(layer))); return new BlockModelWrapper(List.of(), quads, this.renderProperties); } - private CompositeModel composeModel() + private ItemModel composeModel(SavedColors colors) { List models = new ArrayList<>(); models.add(this.bakeBase()); - models.add(this.bakeLayer(0)); + for (int i = 0; i < colors.flowers().size(); i++) + { + models.add(this.bakeLayer(i, colors.flowers().get(i))); + } return new CompositeModel(models); } @@ -108,7 +150,13 @@ public class FlowerCrownItemModel implements ItemModel ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { - this.composeModel() + SavedColors comp = + stack.get(CnFRegistries.DataComponents.SAVED_FLOWERS.get()); + if (comp == null) + { + comp = new SavedColors(List.of()); + } + this.composeModel(comp) .update(renderState, stack, itemModelResolver, displayContext, level, entity, seed); } @@ -116,11 +164,11 @@ public class FlowerCrownItemModel implements ItemModel public record Unbaked(ResourceLocation base) implements ItemModel.Unbaked { - public static final MapCodec MAP_CODEC = + public static final MapCodec MAP_CODEC = RecordCodecBuilder.mapCodec(unbaked -> unbaked - .group(ResourceLocation.CODEC.fieldOf("base").forGetter( - FlowerCrownItemModel.Unbaked::base)) - .apply(unbaked, FlowerCrownItemModel.Unbaked::new)); + .group(ResourceLocation.CODEC.fieldOf("base") + .forGetter(Unbaked::base)) + .apply(unbaked, Unbaked::new)); @Override public MapCodec type() diff --git a/src/main/resources/assets/charmsnfabrics/textures/flower/flower0.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower0.png deleted file mode 100644 index ca421822cfc21454c37d59e61d906b5961d230cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|+&x_!Lo9le z6C_v{H{5#g`}_O<`|JPzn=fMPb7IziS+j%(Kco&ibSV}vzpMXq;s6kQ_o=L!-(C9e|9|QFIc)|HjUU`x`krTwkrU7Tb9WOe%3fMW p_9fg1{P^vEU)T00m5q7~3~X{rdS%}x`vA>k@O1TaS?83{1OV4JHR%8V diff --git a/src/main/resources/assets/charmsnfabrics/textures/flower/flower2.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower2.png deleted file mode 100644 index e4748c0e8dfa660f272786a7debe29498051c16e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|v^-rLLo9le z6C_v{Cny~F{{H@d<-drkY^OIC;%YU9{V6*$nTpf3V pH!CWB*SjB${$SaM^vbKn)C@u6{1-oD!M< D++QGR diff --git a/src/main/resources/assets/charmsnfabrics/textures/flower/flower5.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower5.png deleted file mode 100644 index c438b86719e6b7df1ae0d54604d633ac5f390d61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|+&x_!Lo9le z6C_F={Qmy_|Ni>_|K>-0^?5PtzpPopgC9}{9o8snu-*CpV`3u^Jp8{pyuj?_gInF= n|JU!WaNHv9c2Gk?hJnFqj#AZ?)yKC1jb!k2^>bP0l+XkKAVoIk diff --git a/src/main/resources/assets/charmsnfabrics/textures/flower/flower6.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower6.png deleted file mode 100644 index 762765ba5a965881ad43063bc211794bbeec2c89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|R6SiBLo9le z6C_xhIrdome{b(P>;L|b|LZevnt$S5=hr_ozje-mg11Mxo7x_*h-AvKI&(5Ge0?Lxrgf*J9jJ@J)78&q Iol`;+0487{w*UYD literal 0 HcmV?d00001 From 67ae714c6453d1e36916042ce0a22fb3ca81f750 Mon Sep 17 00:00:00 2001 From: SushiCannibale Date: Wed, 13 Aug 2025 19:19:50 +0200 Subject: [PATCH 6/8] feat: dynamic tinting --- .../charmsnfabrics/client/CnFClient.java | 14 ++++- .../client/model/FlowerCrownItemModel.java | 25 ++++----- .../client/renderer/FlowerCrownRenderer.java | 3 -- .../client/util/FlowersTint.java | 54 +++++++++++++++++++ .../charmsnfabrics/common/CnFRegistries.java | 16 +++--- .../common/data/FlowerCrownContent.java | 26 +++++++++ .../common/data/SavedColors.java | 24 --------- .../common/item/FlowerCrown.java | 51 ++++++++++-------- 8 files changed, 144 insertions(+), 69 deletions(-) create mode 100644 src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java create mode 100644 src/main/java/fr/sushi/charmsnfabrics/common/data/FlowerCrownContent.java delete mode 100644 src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java diff --git a/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java b/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java index eec3644..1dbef1a 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/CnFClient.java @@ -8,6 +8,7 @@ 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.client.util.FlowersTint; import fr.sushi.charmsnfabrics.common.CnFRegistries; import net.minecraft.data.loot.LootTableProvider; import net.minecraft.resources.ResourceLocation; @@ -19,6 +20,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.RegisterColorHandlersEvent; import net.neoforged.neoforge.client.event.RegisterItemModelsEvent; import net.neoforged.neoforge.client.gui.ConfigurationScreen; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; @@ -76,7 +78,8 @@ public class CnFClient } @SubscribeEvent - private static void onRegisterItemModels(final RegisterItemModelsEvent event) + private static void onRegisterItemModels( + final RegisterItemModelsEvent event) { event.register( ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, @@ -84,6 +87,15 @@ public class CnFClient FlowerCrownItemModel.Unbaked.MAP_CODEC); } + @SubscribeEvent + private static void onRegisterTinters( + RegisterColorHandlersEvent.ItemTintSources event) + { + event.register( + ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, + "flower_tint"), FlowersTint.MAP_CODEC); + } + // @SubscribeEvent // private static void onRegisterStandaloneModels( // ModelEvent.RegisterStandalone event) 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 d0adcc0..677495e 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java @@ -4,8 +4,9 @@ import com.mojang.math.Transformation; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import fr.sushi.charmsnfabrics.CharmsAndFabrics; +import fr.sushi.charmsnfabrics.client.util.FlowersTint; import fr.sushi.charmsnfabrics.common.CnFRegistries; -import fr.sushi.charmsnfabrics.common.data.SavedColors; +import fr.sushi.charmsnfabrics.common.data.FlowerCrownContent; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -16,7 +17,6 @@ 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; @@ -35,8 +35,6 @@ import java.util.Map; 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 Map TRANSFORMS = new HashMap<>(); @@ -117,29 +115,32 @@ public class FlowerCrownItemModel implements ItemModel return new BlockModelWrapper(List.of(), quads, this.renderProperties); } - private ItemModel bakeLayer(int layer, DyeColor color) + private ItemModel bakeLayer(int layer, ItemStack flower) { 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, TRANSFORMS.get(layer))); - return new BlockModelWrapper(List.of(), quads, this.renderProperties); + return new BlockModelWrapper(List.of(new FlowersTint(layer)), quads, + this.renderProperties); } - private ItemModel composeModel(SavedColors colors) + private ItemModel composeModel(FlowerCrownContent colors) { List models = new ArrayList<>(); models.add(this.bakeBase()); for (int i = 0; i < colors.flowers().size(); i++) { - models.add(this.bakeLayer(i, colors.flowers().get(i))); + if (!colors.flowers().get(i).isEmpty()) + { + models.add(this.bakeLayer(i, colors.flowers().get(i))); + } } return new CompositeModel(models); } @@ -150,11 +151,11 @@ public class FlowerCrownItemModel implements ItemModel ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { - SavedColors comp = - stack.get(CnFRegistries.DataComponents.SAVED_FLOWERS.get()); + FlowerCrownContent comp = + stack.get(CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); if (comp == null) { - comp = new SavedColors(List.of()); + comp = new FlowerCrownContent(List.of()); } this.composeModel(comp) .update(renderState, stack, itemModelResolver, displayContext, 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 4ddb010..7bbdfd0 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/renderer/FlowerCrownRenderer.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/renderer/FlowerCrownRenderer.java @@ -4,7 +4,6 @@ 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; @@ -15,8 +14,6 @@ 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; diff --git a/src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java b/src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java new file mode 100644 index 0000000..133576a --- /dev/null +++ b/src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java @@ -0,0 +1,54 @@ +package fr.sushi.charmsnfabrics.client.util; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import fr.sushi.charmsnfabrics.common.CnFRegistries; +import fr.sushi.charmsnfabrics.common.data.FlowerCrownContent; +import net.minecraft.client.color.item.ItemTintSource; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.jetbrains.annotations.Nullable; + +public record FlowersTint(int layer) implements ItemTintSource +{ + public static final MapCodec MAP_CODEC = + RecordCodecBuilder.mapCodec(instance -> instance + .group(Codec.INT.fieldOf("layer") + .forGetter(FlowersTint::layer)) + .apply(instance, FlowersTint::new)); + + @Override + public int calculate(ItemStack stack, @Nullable ClientLevel level, + @Nullable LivingEntity entity) + { + FlowerCrownContent data = + stack.get(CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); + if (data != null) + { + ItemStack flower = data.flowers().get(this.layer); + if (flower.is(ItemTags.FLOWERS)) { + + } + if (flower.is(Items.POPPY)) + { + return DyeColor.RED.getTextureDiffuseColor(); + } + else if (flower.is(Items.DANDELION)) + { + return DyeColor.YELLOW.getTextureDiffuseColor(); + } + } + return 0xFFFFFFFF; + } + + @Override + public MapCodec type() + { + return MAP_CODEC; + } +} diff --git a/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java b/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java index 0fd89b3..80f7d98 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java +++ b/src/main/java/fr/sushi/charmsnfabrics/common/CnFRegistries.java @@ -2,7 +2,7 @@ package fr.sushi.charmsnfabrics.common; import fr.sushi.charmsnfabrics.CharmsAndFabrics; import fr.sushi.charmsnfabrics.common.block.FloralWorkbench; -import fr.sushi.charmsnfabrics.common.data.SavedColors; +import fr.sushi.charmsnfabrics.common.data.FlowerCrownContent; import fr.sushi.charmsnfabrics.common.entities.block.FloralWorkbenchBlockEntity; import fr.sushi.charmsnfabrics.common.item.FlowerCrown; import net.minecraft.core.component.DataComponentType; @@ -38,8 +38,8 @@ public class CnFRegistries ITEMS.registerItem("flower_crown", (properties) -> new FlowerCrown(properties.stacksTo(1) .component( - DataComponents.SAVED_FLOWERS, - new SavedColors( + DataComponents.FLOWER_CROWN_CONTENT, + new FlowerCrownContent( List.of())))); /* BlockItems */ public static final DeferredItem FLORAL_WORKBENCH = @@ -112,12 +112,12 @@ public class CnFRegistries DeferredRegister.createDataComponents( Registries.DATA_COMPONENT_TYPE, CharmsAndFabrics.MODID); - public static final Supplier> - SAVED_FLOWERS = - COMPONENT_TYPES.registerComponentType("saved_flowers", - builder -> builder.persistent(SavedColors.CODEC) + public static final Supplier> + FLOWER_CROWN_CONTENT = + COMPONENT_TYPES.registerComponentType("flower_crown_content", + builder -> builder.persistent(FlowerCrownContent.CODEC) .networkSynchronized( - SavedColors.STREAM_CODEC)); + FlowerCrownContent.STREAM_CODEC)); } public static void register(IEventBus bus) diff --git a/src/main/java/fr/sushi/charmsnfabrics/common/data/FlowerCrownContent.java b/src/main/java/fr/sushi/charmsnfabrics/common/data/FlowerCrownContent.java new file mode 100644 index 0000000..a951a21 --- /dev/null +++ b/src/main/java/fr/sushi/charmsnfabrics/common/data/FlowerCrownContent.java @@ -0,0 +1,26 @@ +package fr.sushi.charmsnfabrics.common.data; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.item.ItemStack; + +import java.util.List; + +public record FlowerCrownContent(List flowers) +{ + public static final FlowerCrownContent EMPTY = + new FlowerCrownContent(List.of()); + public static final Codec CODEC = + ItemStack.CODEC.listOf().flatXmap((items) -> DataResult.success( + new FlowerCrownContent(items)), + content -> DataResult.success(content.flowers)); + public static final StreamCodec + STREAM_CODEC = ItemStack.STREAM_CODEC.apply(ByteBufCodecs.list()) + .map(FlowerCrownContent::new, + content -> content.flowers); + + public static int MAX_SIZE = 7; +} diff --git a/src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java b/src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java deleted file mode 100644 index 5eb10b5..0000000 --- a/src/main/java/fr/sushi/charmsnfabrics/common/data/SavedColors.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.sushi.charmsnfabrics.common.data; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import io.netty.buffer.ByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.world.item.DyeColor; - -import java.util.List; - -public record SavedColors(List flowers) -{ - public static final Codec CODEC = RecordCodecBuilder.create( - instance -> instance - .group(DyeColor.CODEC.listOf().fieldOf("flowers") - .forGetter(SavedColors::flowers)) - .apply(instance, SavedColors::new)); - - public static final StreamCodec STREAM_CODEC = - StreamCodec.composite( - DyeColor.STREAM_CODEC.apply(ByteBufCodecs.list(256)), - SavedColors::flowers, SavedColors::new); -} 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 6952ff9..5e2c636 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java +++ b/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java @@ -1,12 +1,19 @@ package fr.sushi.charmsnfabrics.common.item; import fr.sushi.charmsnfabrics.CharmsAndFabrics; +import fr.sushi.charmsnfabrics.common.CnFRegistries; +import fr.sushi.charmsnfabrics.common.data.FlowerCrownContent; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; import top.theillusivec4.curios.api.SlotContext; import top.theillusivec4.curios.api.type.capability.ICurioItem; +import java.util.ArrayList; +import java.util.List; + public class FlowerCrown extends Item implements ICurioItem { public FlowerCrown(Properties properties) @@ -32,25 +39,27 @@ public class FlowerCrown extends Item implements ICurioItem "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; -// } + @Override + public InteractionResult useOn(UseOnContext context) + { + var player = context.getPlayer(); + var hand = context.getHand(); + + ItemStack stack = player.getItemInHand(hand); + ItemStack offStack = player.getOffhandItem(); + + FlowerCrownContent content = stack.get( + CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); + if (content == null || + content.flowers().size() >= FlowerCrownContent.MAX_SIZE) + { + return InteractionResult.FAIL; + } + List list = new ArrayList<>(content.flowers()); + list.add(offStack); + stack.set(CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get(), + new FlowerCrownContent(list)); + + return InteractionResult.SUCCESS; + } } From d393812448f3fa55f06eab0438b7f82a0eac86be Mon Sep 17 00:00:00 2001 From: SushiCannibale Date: Thu, 14 Aug 2025 12:25:41 +0200 Subject: [PATCH 7/8] fine tuned transforms --- .../client/model/FlowerCrownItemModel.java | 74 +++++++------------ .../common/item/FlowerCrown.java | 5 ++ 2 files changed, 32 insertions(+), 47 deletions(-) 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 677495e..704d482 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java @@ -8,7 +8,6 @@ import fr.sushi.charmsnfabrics.client.util.FlowersTint; import fr.sushi.charmsnfabrics.common.CnFRegistries; import fr.sushi.charmsnfabrics.common.data.FlowerCrownContent; 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.TextureSlots; @@ -20,12 +19,11 @@ import net.minecraft.world.entity.LivingEntity; 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; import org.joml.Quaternionf; +import org.joml.Vector2f; import org.joml.Vector3f; import java.util.ArrayList; @@ -35,39 +33,20 @@ import java.util.Map; public class FlowerCrownItemModel implements ItemModel { - private static final Map TRANSFORMS = - new HashMap<>(); + private static final Map TRANSLATIONS = new HashMap<>(); + /* + * Position the flower on the item model based on the layer (anticlockwise) + */ static { - TRANSFORMS.put(0, new Transformation( - new Vector3f(1f * 0.0625f, -4f * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), - new Quaternionf())); - TRANSFORMS.put(1, new Transformation( - new Vector3f(5f * 0.0625f, -3f * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), - new Quaternionf())); - TRANSFORMS.put(2, new Transformation( - new Vector3f(5f * 0.0625f, 2f * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), - new Quaternionf())); - TRANSFORMS.put(3, new Transformation( - new Vector3f(2f * 0.0625f, 4f * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), - new Quaternionf())); - TRANSFORMS.put(4, new Transformation( - new Vector3f(-3f * 0.0625f, 4f * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), - new Quaternionf())); - TRANSFORMS.put(5, new Transformation( - new Vector3f(-5f * 0.0625f, 0f * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), - new Quaternionf())); - TRANSFORMS.put(6, new Transformation( - new Vector3f(-4f * 0.0625f, -3f * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.01f, 1.01f, 1.0625f), - new Quaternionf())); + TRANSLATIONS.put(0, new Vector2f(1, -4)); + TRANSLATIONS.put(1, new Vector2f(5, -3)); + TRANSLATIONS.put(2, new Vector2f(5, 2)); + TRANSLATIONS.put(3, new Vector2f(2, 4)); + TRANSLATIONS.put(4, new Vector2f(-3, 4)); + TRANSLATIONS.put(5, new Vector2f(-5, 0)); + TRANSLATIONS.put(6, new Vector2f(-4, -3)); } private static final ModelDebugName DEBUG_NAME = @@ -83,6 +62,14 @@ public class FlowerCrownItemModel implements ItemModel this.context = context; } + private Transformation getTransform(int layer) + { + Vector2f uv = TRANSLATIONS.get(layer); + return new Transformation( + new Vector3f(uv.x * 0.0625f, uv.y * 0.0625f, 0.0f), + new Quaternionf(), new Vector3f(1.002f), new Quaternionf()); + } + private ResourceLocation getFlowerLocation(int layer) { @@ -90,13 +77,6 @@ public class FlowerCrownItemModel implements ItemModel "flower/flower_" + (layer % 2 == 0 ? "large" : "small")); } - private static RenderTypeGroup getLayerRenderTypes(boolean unlit) - { - return new RenderTypeGroup(RenderType.translucent(), unlit ? - NeoForgeRenderTypes.ITEM_UNSORTED_UNLIT_TRANSLUCENT.get() : - NeoForgeRenderTypes.ITEM_UNSORTED_TRANSLUCENT.get()); - } - /** * Bakes the base and updates the LayerRenderState quads */ @@ -126,20 +106,20 @@ public class FlowerCrownItemModel implements ItemModel List quads = UnbakedElementsHelper.bakeElements(bits, $ -> sprite, new ComposedModelState(BlockModelRotation.X0_Y0, - TRANSFORMS.get(layer))); + this.getTransform(layer))); return new BlockModelWrapper(List.of(new FlowersTint(layer)), quads, this.renderProperties); } - private ItemModel composeModel(FlowerCrownContent colors) + private ItemModel composeModel(FlowerCrownContent content) { List models = new ArrayList<>(); models.add(this.bakeBase()); - for (int i = 0; i < colors.flowers().size(); i++) + for (int i = 0; i < content.flowers().size(); i++) { - if (!colors.flowers().get(i).isEmpty()) + if (!content.flowers().get(i).isEmpty()) { - models.add(this.bakeLayer(i, colors.flowers().get(i))); + models.add(this.bakeLayer(i, content.flowers().get(i))); } } return new CompositeModel(models); @@ -151,8 +131,8 @@ public class FlowerCrownItemModel implements ItemModel ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { - FlowerCrownContent comp = - stack.get(CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); + FlowerCrownContent comp = stack.get( + CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); if (comp == null) { comp = new FlowerCrownContent(List.of()); 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 5e2c636..3dd1fdf 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java +++ b/src/main/java/fr/sushi/charmsnfabrics/common/item/FlowerCrown.java @@ -48,6 +48,11 @@ public class FlowerCrown extends Item implements ICurioItem ItemStack stack = player.getItemInHand(hand); ItemStack offStack = player.getOffhandItem(); + if (stack.isEmpty() || offStack.isEmpty()) + { + return InteractionResult.PASS; + } + FlowerCrownContent content = stack.get( CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); if (content == null || From ad6d36fecb38430aa148256c0955ed030b69a970 Mon Sep 17 00:00:00 2001 From: SushiCannibale Date: Thu, 14 Aug 2025 17:43:00 +0200 Subject: [PATCH 8/8] feat: outline tinting --- .../client/model/FlowerCrownItemModel.java | 64 +++++++++++++----- .../client/util/FlowersTint.java | 20 +++--- .../textures/flower/flower_large.png | Bin 141 -> 108 bytes .../textures/flower/flower_outline_large.png | Bin 0 -> 123 bytes .../textures/flower/flower_outline_small.png | Bin 0 -> 103 bytes .../textures/flower/flower_small.png | Bin 112 -> 95 bytes 6 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower_outline_large.png create mode 100644 src/main/resources/assets/charmsnfabrics/textures/flower/flower_outline_small.png 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 704d482..89934ca 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/model/FlowerCrownItemModel.java @@ -67,7 +67,7 @@ public class FlowerCrownItemModel implements ItemModel Vector2f uv = TRANSLATIONS.get(layer); return new Transformation( new Vector3f(uv.x * 0.0625f, uv.y * 0.0625f, 0.0f), - new Quaternionf(), new Vector3f(1.002f), new Quaternionf()); + new Quaternionf(), new Vector3f(1.001f), new Quaternionf()); } private ResourceLocation getFlowerLocation(int layer) @@ -77,6 +77,21 @@ public class FlowerCrownItemModel implements ItemModel "flower/flower_" + (layer % 2 == 0 ? "large" : "small")); } + private ResourceLocation getOutlineLocation(int layer) + { + + return ResourceLocation.fromNamespaceAndPath(CharmsAndFabrics.MODID, + "flower/flower_outline_" + + (layer % 2 == 0 ? "large" : "small")); + } + + private TextureAtlasSprite getSprite(ResourceLocation textureLocation) + { + SpriteGetter sprites = this.context.blockModelBaker().sprites(); + Material material = ClientHooks.getBlockMaterial(textureLocation); + return sprites.get(material, DEBUG_NAME); + } + /** * Bakes the base and updates the LayerRenderState quads */ @@ -95,32 +110,48 @@ public class FlowerCrownItemModel implements ItemModel return new BlockModelWrapper(List.of(), quads, this.renderProperties); } - private ItemModel bakeLayer(int layer, ItemStack flower) + private List bakeModel(ResourceLocation textureLocation, + int layer) { - SpriteGetter sprites = this.context.blockModelBaker().sprites(); - Material material = - ClientHooks.getBlockMaterial(this.getFlowerLocation(layer)); - TextureAtlasSprite sprite = sprites.get(material, DEBUG_NAME); + TextureAtlasSprite sprite = this.getSprite(textureLocation); List bits = UnbakedElementsHelper.createUnbakedItemElements(0, sprite); + return UnbakedElementsHelper.bakeElements(bits, $ -> sprite, + new ComposedModelState(BlockModelRotation.X0_Y0, + this.getTransform(layer))); + } + + private ItemModel bakeOutline(int layer) + { List quads = - UnbakedElementsHelper.bakeElements(bits, $ -> sprite, - new ComposedModelState(BlockModelRotation.X0_Y0, - this.getTransform(layer))); + this.bakeModel(this.getOutlineLocation(layer), layer); return new BlockModelWrapper(List.of(new FlowersTint(layer)), quads, this.renderProperties); } - private ItemModel composeModel(FlowerCrownContent content) + private ItemModel bakeFlower(int layer) + { + List models = new ArrayList<>(); + models.add(this.bakeOutline(layer)); + + List quads = + this.bakeModel(this.getFlowerLocation(layer), layer); + models.add( + new BlockModelWrapper(List.of(), quads, this.renderProperties)); + return new CompositeModel(models); + } + + private ItemModel bakeFlowerCrown(FlowerCrownContent content) { List models = new ArrayList<>(); models.add(this.bakeBase()); for (int i = 0; i < content.flowers().size(); i++) { - if (!content.flowers().get(i).isEmpty()) + if (content.flowers().get(i).isEmpty()) { - models.add(this.bakeLayer(i, content.flowers().get(i))); + continue; } + models.add(this.bakeFlower(i)); } return new CompositeModel(models); } @@ -133,13 +164,12 @@ public class FlowerCrownItemModel implements ItemModel { FlowerCrownContent comp = stack.get( CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); - if (comp == null) + if (comp != null) { - comp = new FlowerCrownContent(List.of()); + this.bakeFlowerCrown(comp) + .update(renderState, stack, itemModelResolver, displayContext, + level, entity, seed); } - this.composeModel(comp) - .update(renderState, stack, itemModelResolver, displayContext, - level, entity, seed); } public record Unbaked(ResourceLocation base) implements ItemModel.Unbaked diff --git a/src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java b/src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java index 133576a..8fde5ec 100644 --- a/src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java +++ b/src/main/java/fr/sushi/charmsnfabrics/client/util/FlowersTint.java @@ -7,7 +7,6 @@ import fr.sushi.charmsnfabrics.common.CnFRegistries; import fr.sushi.charmsnfabrics.common.data.FlowerCrownContent; import net.minecraft.client.color.item.ItemTintSource; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.tags.ItemTags; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; @@ -26,21 +25,22 @@ public record FlowersTint(int layer) implements ItemTintSource public int calculate(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity) { - FlowerCrownContent data = - stack.get(CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); + FlowerCrownContent data = stack.get( + CnFRegistries.DataComponents.FLOWER_CROWN_CONTENT.get()); if (data != null) { ItemStack flower = data.flowers().get(this.layer); - if (flower.is(ItemTags.FLOWERS)) { - - } - if (flower.is(Items.POPPY)) + if (flower.is(Items.BLUE_ORCHID)) { - return DyeColor.RED.getTextureDiffuseColor(); + return DyeColor.LIGHT_BLUE.getTextureDiffuseColor(); } - else if (flower.is(Items.DANDELION)) + else if (flower.is(Items.LILY_OF_THE_VALLEY)) { - return DyeColor.YELLOW.getTextureDiffuseColor(); + return DyeColor.WHITE.getTextureDiffuseColor(); + } + else if (flower.is(Items.PINK_TULIP)) + { + return DyeColor.MAGENTA.getTextureDiffuseColor(); } } return 0xFFFFFFFF; diff --git a/src/main/resources/assets/charmsnfabrics/textures/flower/flower_large.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower_large.png index 40fa1b01fec8ef7015cbe0982702a11249493093..7f48c28f505bcdf3b40f03a82845f660ae2b5404 100644 GIT binary patch delta 65 zcmeBW%$Z)?C7-G?zoFKt^ShnWw(trQ|OaK4><%y)R0)iz)*IU V`cO954U? delta 98 zcmd1lWt?CbF=7-G?zoFKv4EK~FU-{1e=-{1fLIQVdj|L6UO*?45)l_fq%HeGJ` zEpKmR00e*PzjB>ZlZ>hU_~`#uas3Zfi6T5~3=A^_m8vEczE))b0#8>zmvv4FO#q^U BDV6{L diff --git a/src/main/resources/assets/charmsnfabrics/textures/flower/flower_outline_large.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower_outline_large.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd724b71925c6bc9c11f2e3a1538462cbdffbd2 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Og&v3Lo9le z6C_xhWorKa`}_a<`}_YVua%URmNj@dX~+MM%3)@n4{mjf|6jki!f~Fs8>1{EgOY_z V{H3{_aX^>bP0l+XkK-EJF_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/charmsnfabrics/textures/flower/flower_small.png b/src/main/resources/assets/charmsnfabrics/textures/flower/flower_small.png index a25efa437c7b5be914055797ead2308ff562b1e7..3f0646c342aaac1c96fd7008a193e2aa0e7f18c8 100644 GIT binary patch delta 51 zcmXSjpJ1pb>FMGaV$qwNAi;WAw&w2AfAtIQ8gR9-F)*kzGF|g;T#>;51fH&bF6*2U FngGiX5f1}%WV$qwNAi>%!Q}h4dUwcJUpC2awt#b|(ygka@)b@ZyBvX#nnUjIx X>l;Bftve;{3_#%N>gTe~DWM4fja3;r