From 8c5770117632c5ac18651bd465357f9361950ea2 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Thu, 16 Oct 2025 15:09:04 +0000 Subject: [PATCH] Get rid of intermediary names in reports, don't export 3D icon if there is no renderer --- .../rainbow/datagen/RainbowModelProvider.java | 9 ++++- .../rainbow/mapping/BedrockItemMapper.java | 21 +++++++----- .../mapping/attachable/AttachableMapper.java | 2 +- .../geometry/BedrockGeometryContext.java | 7 ++-- .../mapping/geometry/TextureHolder.java | 34 ++++++++++++++++--- .../geysermc/rainbow/pack/BedrockPack.java | 12 +------ 6 files changed, 56 insertions(+), 29 deletions(-) diff --git a/datagen/src/main/java/org/geysermc/rainbow/datagen/RainbowModelProvider.java b/datagen/src/main/java/org/geysermc/rainbow/datagen/RainbowModelProvider.java index b009858..b6496d2 100644 --- a/datagen/src/main/java/org/geysermc/rainbow/datagen/RainbowModelProvider.java +++ b/datagen/src/main/java/org/geysermc/rainbow/datagen/RainbowModelProvider.java @@ -7,6 +7,7 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.minecraft.Util; import net.minecraft.client.data.models.model.ModelInstance; import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.client.renderer.block.model.ItemModelGenerator; import net.minecraft.client.renderer.item.ClientItem; import net.minecraft.client.resources.model.EquipmentClientInfo; import net.minecraft.client.resources.model.ResolvedModel; @@ -153,7 +154,13 @@ public abstract class RainbowModelProvider extends FabricModelProvider { @Override public Optional getResolvedModel(ResourceLocation location) { return resolvedModelCache.computeIfAbsent(location, key -> Optional.ofNullable(models.get(location)) - .map(instance -> BlockModel.fromStream(new StringReader(instance.get().toString()))) + .map(instance -> BlockModel.fromStream(new StringReader(instance.get().toString()))) + .or(() -> { + if (location.equals(ItemModelGenerator.GENERATED_ITEM_MODEL_ID)) { + return Optional.of(new ItemModelGenerator()); + } + return Optional.empty(); + }) .or(() -> RainbowIO.safeIO(() -> { try (BufferedReader reader = resourceManager.openAsReader(location.withPrefix("models/").withSuffix(".json"))) { return BlockModel.fromStream(reader); diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java index c911d19..8d7747a 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java @@ -8,23 +8,27 @@ import net.minecraft.client.renderer.item.ItemModels; import net.minecraft.client.renderer.item.RangeSelectItemModel; import net.minecraft.client.renderer.item.SelectItemModel; import net.minecraft.client.renderer.item.properties.conditional.Broken; +import net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperties; +import net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperty; import net.minecraft.client.renderer.item.properties.conditional.CustomModelDataProperty; import net.minecraft.client.renderer.item.properties.conditional.Damaged; import net.minecraft.client.renderer.item.properties.conditional.FishingRodCast; import net.minecraft.client.renderer.item.properties.conditional.HasComponent; -import net.minecraft.client.renderer.item.properties.conditional.ItemModelPropertyTest; import net.minecraft.client.renderer.item.properties.numeric.BundleFullness; import net.minecraft.client.renderer.item.properties.numeric.Count; import net.minecraft.client.renderer.item.properties.numeric.Damage; +import net.minecraft.client.renderer.item.properties.numeric.RangeSelectItemModelProperties; import net.minecraft.client.renderer.item.properties.numeric.RangeSelectItemModelProperty; import net.minecraft.client.renderer.item.properties.select.Charge; import net.minecraft.client.renderer.item.properties.select.ContextDimension; import net.minecraft.client.renderer.item.properties.select.DisplayContext; +import net.minecraft.client.renderer.item.properties.select.SelectItemModelProperties; import net.minecraft.client.renderer.item.properties.select.TrimMaterialProperty; import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; +import net.minecraft.util.ExtraCodecs; import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; @@ -59,9 +63,10 @@ public class BedrockItemMapper { .map(ResourceLocation::withDefaultNamespace) .toList(); - private static ResourceLocation getModelId(ItemModel.Unbaked model) { + private static ResourceLocation getId(ExtraCodecs.LateBoundIdMapper mapper, + T type) { //noinspection unchecked - return ((LateBoundIdMapperAccessor) ItemModels.ID_MAPPER).getIdToValue().inverse().get(model.type()); + return ((LateBoundIdMapperAccessor) mapper).getIdToValue().inverse().get(type); } public static void tryMapStack(ItemStack stack, ResourceLocation modelLocation, ProblemReporter reporter, PackContext context) { @@ -107,7 +112,7 @@ public class BedrockItemMapper { case ConditionalItemModel.Unbaked conditional -> mapConditionalModel(conditional, context.child("condition model ")); case RangeSelectItemModel.Unbaked rangeSelect -> mapRangeSelectModel(rangeSelect, context.child("range select model ")); case SelectItemModel.Unbaked select -> mapSelectModel(select, context.child("select model ")); - default -> context.report("unsupported item model " + getModelId(model)); + default -> context.report("unsupported item model " + getId(ItemModels.ID_MAPPER, model.type())); } } @@ -133,7 +138,7 @@ public class BedrockItemMapper { } private static void mapConditionalModel(ConditionalItemModel.Unbaked model, MappingContext context) { - ItemModelPropertyTest property = model.property(); + ConditionalItemModelProperty property = model.property(); GeyserConditionPredicate.Property predicateProperty = switch (property) { case Broken ignored -> GeyserConditionPredicate.BROKEN; case Damaged ignored -> GeyserConditionPredicate.DAMAGED; @@ -146,7 +151,7 @@ public class BedrockItemMapper { ItemModel.Unbaked onFalse = model.onFalse(); if (predicateProperty == null) { - context.report("unsupported conditional model property " + property + ", only mapping on_false"); + context.report("unsupported conditional model property " + getId(ConditionalItemModelProperties.ID_MAPPER, property.type()) + ", only mapping on_false"); mapItem(onFalse, context.child("condition on_false (unsupported property)")); return; } @@ -167,7 +172,7 @@ public class BedrockItemMapper { }; if (predicateProperty == null) { - context.report("unsupported range dispatch model property " + property + ", only mapping fallback, if it is present"); + context.report("unsupported range dispatch model property " + getId(RangeSelectItemModelProperties.ID_MAPPER, property.type()) + ", only mapping fallback, if it is present"); } else { for (RangeSelectItemModel.Entry entry : model.entries()) { mapItem(entry.model(), context.with(new GeyserRangeDispatchPredicate(predicateProperty, entry.threshold(), model.scale()), "threshold " + entry.threshold())); @@ -201,7 +206,7 @@ public class BedrockItemMapper { } } } - context.report("unsupported select model property " + unbakedSwitch.property() + ", only mapping fallback, if present"); + context.report("unsupported select model property " + getId(SelectItemModelProperties.ID_MAPPER, unbakedSwitch.property().type()) + ", only mapping fallback, if present"); model.fallback().ifPresent(fallback -> mapItem(fallback, context.child("select fallback case (unsupported property) "))); return; } diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/attachable/AttachableMapper.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/attachable/AttachableMapper.java index 80a4a61..7b9579b 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/attachable/AttachableMapper.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/attachable/AttachableMapper.java @@ -34,7 +34,7 @@ public class AttachableMapper { .filter(assetInfo -> !assetInfo.getSecond().isEmpty()) .map(assetInfo -> { ResourceLocation equipmentTexture = getTexture(assetInfo.getSecond(), getLayer(assetInfo.getFirst())); - textureConsumer.accept(new TextureHolder(equipmentTexture)); + textureConsumer.accept(TextureHolder.createFromResources(equipmentTexture)); return BedrockAttachable.equipment(bedrockIdentifier, assetInfo.getFirst(), equipmentTexture.getPath()); })) .map(attachable -> { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/BedrockGeometryContext.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/BedrockGeometryContext.java index 3d306b1..25730ff 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/BedrockGeometryContext.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/BedrockGeometryContext.java @@ -38,7 +38,7 @@ public record BedrockGeometryContext(Optional> geomet if (layer0Texture != null) { geometry = Optional.empty(); animation = Optional.empty(); - icon = new TextureHolder(layer0Texture.texture()); + icon = TextureHolder.createFromResources(layer0Texture.texture()); } else { // Unknown model (doesn't use layer0), so we immediately assume the geometry is custom // This check should probably be done differently (actually check if the model is 2D or 3D) @@ -49,11 +49,12 @@ public record BedrockGeometryContext(Optional> geomet geometry = Optional.of(Suppliers.memoize(() -> { StitchedTextures stitchedTextures = StitchedTextures.stitchModelTextures(textures, context); BedrockGeometry mappedGeometry = GeometryMapper.mapGeometry(safeIdentifier, "bone", model, stitchedTextures); - return new StitchedGeometry(mappedGeometry, new TextureHolder(modelLocation.withSuffix("_stitched"), stitchedTextures.stitched())); + return new StitchedGeometry(mappedGeometry, TextureHolder.createProvided(modelLocation.withSuffix("_stitched"), stitchedTextures.stitched())); })); animation = Optional.of(AnimationMapper.mapAnimation(safeIdentifier, "bone", model.getTopTransforms())); - icon = new TextureHolder(modelLocation, context.geometryRenderer().map(renderer -> () -> renderer.render(stackToRender))); + icon = context.geometryRenderer().isPresent() ? TextureHolder.createProvided(modelLocation, () -> context.geometryRenderer().orElseThrow().render(stackToRender)) + : TextureHolder.createNonExistent(modelLocation); } return new BedrockGeometryContext(geometry, animation, icon, handheld); diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/TextureHolder.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/TextureHolder.java index 10813ca..c209741 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/TextureHolder.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/geometry/TextureHolder.java @@ -2,17 +2,41 @@ package org.geysermc.rainbow.mapping.geometry; import com.mojang.blaze3d.platform.NativeImage; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ProblemReporter; +import org.geysermc.rainbow.Rainbow; +import org.geysermc.rainbow.RainbowIO; +import org.geysermc.rainbow.image.NativeImageUtil; +import org.geysermc.rainbow.mapping.AssetResolver; +import java.io.InputStream; import java.util.Optional; import java.util.function.Supplier; -public record TextureHolder(ResourceLocation location, Optional> supplier) { +public record TextureHolder(ResourceLocation location, Optional> supplier, boolean existsInResources) { - public TextureHolder(ResourceLocation location, Supplier supplier) { - this(location, Optional.of(supplier)); + public Optional load(AssetResolver assetResolver, ProblemReporter reporter) { + if (existsInResources) { + return RainbowIO.safeIO(() -> { + try (InputStream texture = assetResolver.openAsset(Rainbow.decorateTextureLocation(location))) { + return texture.readAllBytes(); + } + }); + } else if (supplier.isPresent()) { + return RainbowIO.safeIO(() -> NativeImageUtil.writeToByteArray(supplier.get().get())); + } + reporter.report(() -> "missing texture for " + location + "; please provide it manually"); + return Optional.empty(); } - public TextureHolder(ResourceLocation location) { - this(location, Optional.empty()); + public static TextureHolder createProvided(ResourceLocation location, Supplier supplier) { + return new TextureHolder(location, Optional.of(supplier), false); + } + + public static TextureHolder createFromResources(ResourceLocation location) { + return new TextureHolder(location, Optional.empty(), true); + } + + public static TextureHolder createNonExistent(ResourceLocation location) { + return new TextureHolder(location, Optional.empty(), false); } } diff --git a/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java b/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java index 5959868..9a38d69 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java @@ -14,7 +14,6 @@ import org.geysermc.rainbow.CodecUtil; import org.geysermc.rainbow.PackConstants; import org.geysermc.rainbow.Rainbow; import org.geysermc.rainbow.RainbowIO; -import org.geysermc.rainbow.image.NativeImageUtil; import org.geysermc.rainbow.mapping.AssetResolver; import org.geysermc.rainbow.mapping.BedrockItemMapper; import org.geysermc.rainbow.mapping.PackContext; @@ -24,8 +23,6 @@ import org.geysermc.rainbow.definition.GeyserMappings; import org.geysermc.rainbow.mapping.geometry.TextureHolder; import org.jetbrains.annotations.NotNull; -import java.io.IOException; -import java.io.InputStream; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashSet; @@ -36,7 +33,6 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; -import java.util.function.Supplier; import java.util.function.UnaryOperator; public class BedrockPack { @@ -131,13 +127,7 @@ public class BedrockPack { Function> textureSaver = texture -> { ResourceLocation textureLocation = Rainbow.decorateTextureLocation(texture.location()); - return texture.supplier() - .flatMap(image -> RainbowIO.safeIO(() -> NativeImageUtil.writeToByteArray(image.get()))) - .or(() -> RainbowIO.safeIO(() -> { - try (InputStream textureStream = context.assetResolver().openAsset(textureLocation)) { - return textureStream.readAllBytes(); - } - })) + return texture.load(context.assetResolver(), reporter) .map(bytes -> serializer.saveTexture(bytes, paths.packRoot().resolve(textureLocation.getPath()))) .orElse(CompletableFuture.completedFuture(null)); };