1
0
mirror of https://github.com/GeyserMC/Rainbow.git synced 2025-12-19 14:59:16 +00:00

Get rid of intermediary names in reports, don't export 3D icon if there is no renderer

This commit is contained in:
Eclipse
2025-10-16 15:09:04 +00:00
parent 6e1d6067d4
commit 8c57701176
6 changed files with 56 additions and 29 deletions

View File

@@ -7,6 +7,7 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.client.data.models.model.ModelInstance; import net.minecraft.client.data.models.model.ModelInstance;
import net.minecraft.client.renderer.block.model.BlockModel; 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.renderer.item.ClientItem;
import net.minecraft.client.resources.model.EquipmentClientInfo; import net.minecraft.client.resources.model.EquipmentClientInfo;
import net.minecraft.client.resources.model.ResolvedModel; import net.minecraft.client.resources.model.ResolvedModel;
@@ -153,7 +154,13 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
@Override @Override
public Optional<ResolvedModel> getResolvedModel(ResourceLocation location) { public Optional<ResolvedModel> getResolvedModel(ResourceLocation location) {
return resolvedModelCache.computeIfAbsent(location, key -> Optional.ofNullable(models.get(location)) return resolvedModelCache.computeIfAbsent(location, key -> Optional.ofNullable(models.get(location))
.map(instance -> BlockModel.fromStream(new StringReader(instance.get().toString()))) .<UnbakedModel>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(() -> { .or(() -> RainbowIO.safeIO(() -> {
try (BufferedReader reader = resourceManager.openAsReader(location.withPrefix("models/").withSuffix(".json"))) { try (BufferedReader reader = resourceManager.openAsReader(location.withPrefix("models/").withSuffix(".json"))) {
return BlockModel.fromStream(reader); return BlockModel.fromStream(reader);

View File

@@ -8,23 +8,27 @@ import net.minecraft.client.renderer.item.ItemModels;
import net.minecraft.client.renderer.item.RangeSelectItemModel; import net.minecraft.client.renderer.item.RangeSelectItemModel;
import net.minecraft.client.renderer.item.SelectItemModel; import net.minecraft.client.renderer.item.SelectItemModel;
import net.minecraft.client.renderer.item.properties.conditional.Broken; 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.CustomModelDataProperty;
import net.minecraft.client.renderer.item.properties.conditional.Damaged; 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.FishingRodCast;
import net.minecraft.client.renderer.item.properties.conditional.HasComponent; 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.BundleFullness;
import net.minecraft.client.renderer.item.properties.numeric.Count; 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.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.numeric.RangeSelectItemModelProperty;
import net.minecraft.client.renderer.item.properties.select.Charge; 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.ContextDimension;
import net.minecraft.client.renderer.item.properties.select.DisplayContext; 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.client.renderer.item.properties.select.TrimMaterialProperty;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags; import net.minecraft.tags.ItemTags;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.ProblemReporter; import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.attributes.Attributes;
@@ -59,9 +63,10 @@ public class BedrockItemMapper {
.map(ResourceLocation::withDefaultNamespace) .map(ResourceLocation::withDefaultNamespace)
.toList(); .toList();
private static ResourceLocation getModelId(ItemModel.Unbaked model) { private static <T> ResourceLocation getId(ExtraCodecs.LateBoundIdMapper<ResourceLocation, T> mapper,
T type) {
//noinspection unchecked //noinspection unchecked
return ((LateBoundIdMapperAccessor<ResourceLocation, ?>) ItemModels.ID_MAPPER).getIdToValue().inverse().get(model.type()); return ((LateBoundIdMapperAccessor<ResourceLocation, ?>) mapper).getIdToValue().inverse().get(type);
} }
public static void tryMapStack(ItemStack stack, ResourceLocation modelLocation, ProblemReporter reporter, PackContext context) { 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 ConditionalItemModel.Unbaked conditional -> mapConditionalModel(conditional, context.child("condition model "));
case RangeSelectItemModel.Unbaked rangeSelect -> mapRangeSelectModel(rangeSelect, context.child("range select model ")); case RangeSelectItemModel.Unbaked rangeSelect -> mapRangeSelectModel(rangeSelect, context.child("range select model "));
case SelectItemModel.Unbaked select -> mapSelectModel(select, context.child("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) { private static void mapConditionalModel(ConditionalItemModel.Unbaked model, MappingContext context) {
ItemModelPropertyTest property = model.property(); ConditionalItemModelProperty property = model.property();
GeyserConditionPredicate.Property predicateProperty = switch (property) { GeyserConditionPredicate.Property predicateProperty = switch (property) {
case Broken ignored -> GeyserConditionPredicate.BROKEN; case Broken ignored -> GeyserConditionPredicate.BROKEN;
case Damaged ignored -> GeyserConditionPredicate.DAMAGED; case Damaged ignored -> GeyserConditionPredicate.DAMAGED;
@@ -146,7 +151,7 @@ public class BedrockItemMapper {
ItemModel.Unbaked onFalse = model.onFalse(); ItemModel.Unbaked onFalse = model.onFalse();
if (predicateProperty == null) { 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)")); mapItem(onFalse, context.child("condition on_false (unsupported property)"));
return; return;
} }
@@ -167,7 +172,7 @@ public class BedrockItemMapper {
}; };
if (predicateProperty == null) { 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 { } else {
for (RangeSelectItemModel.Entry entry : model.entries()) { for (RangeSelectItemModel.Entry entry : model.entries()) {
mapItem(entry.model(), context.with(new GeyserRangeDispatchPredicate(predicateProperty, entry.threshold(), model.scale()), "threshold " + entry.threshold())); 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) "))); model.fallback().ifPresent(fallback -> mapItem(fallback, context.child("select fallback case (unsupported property) ")));
return; return;
} }

View File

@@ -34,7 +34,7 @@ public class AttachableMapper {
.filter(assetInfo -> !assetInfo.getSecond().isEmpty()) .filter(assetInfo -> !assetInfo.getSecond().isEmpty())
.map(assetInfo -> { .map(assetInfo -> {
ResourceLocation equipmentTexture = getTexture(assetInfo.getSecond(), getLayer(assetInfo.getFirst())); 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()); return BedrockAttachable.equipment(bedrockIdentifier, assetInfo.getFirst(), equipmentTexture.getPath());
})) }))
.map(attachable -> { .map(attachable -> {

View File

@@ -38,7 +38,7 @@ public record BedrockGeometryContext(Optional<Supplier<StitchedGeometry>> geomet
if (layer0Texture != null) { if (layer0Texture != null) {
geometry = Optional.empty(); geometry = Optional.empty();
animation = Optional.empty(); animation = Optional.empty();
icon = new TextureHolder(layer0Texture.texture()); icon = TextureHolder.createFromResources(layer0Texture.texture());
} else { } else {
// Unknown model (doesn't use layer0), so we immediately assume the geometry is custom // 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) // This check should probably be done differently (actually check if the model is 2D or 3D)
@@ -49,11 +49,12 @@ public record BedrockGeometryContext(Optional<Supplier<StitchedGeometry>> geomet
geometry = Optional.of(Suppliers.memoize(() -> { geometry = Optional.of(Suppliers.memoize(() -> {
StitchedTextures stitchedTextures = StitchedTextures.stitchModelTextures(textures, context); StitchedTextures stitchedTextures = StitchedTextures.stitchModelTextures(textures, context);
BedrockGeometry mappedGeometry = GeometryMapper.mapGeometry(safeIdentifier, "bone", model, stitchedTextures); 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())); 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); return new BedrockGeometryContext(geometry, animation, icon, handheld);

View File

@@ -2,17 +2,41 @@ package org.geysermc.rainbow.mapping.geometry;
import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.resources.ResourceLocation; 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.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
public record TextureHolder(ResourceLocation location, Optional<Supplier<NativeImage>> supplier) { public record TextureHolder(ResourceLocation location, Optional<Supplier<NativeImage>> supplier, boolean existsInResources) {
public TextureHolder(ResourceLocation location, Supplier<NativeImage> supplier) { public Optional<byte[]> load(AssetResolver assetResolver, ProblemReporter reporter) {
this(location, Optional.of(supplier)); 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) { public static TextureHolder createProvided(ResourceLocation location, Supplier<NativeImage> supplier) {
this(location, Optional.empty()); 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);
} }
} }

View File

@@ -14,7 +14,6 @@ import org.geysermc.rainbow.CodecUtil;
import org.geysermc.rainbow.PackConstants; import org.geysermc.rainbow.PackConstants;
import org.geysermc.rainbow.Rainbow; import org.geysermc.rainbow.Rainbow;
import org.geysermc.rainbow.RainbowIO; import org.geysermc.rainbow.RainbowIO;
import org.geysermc.rainbow.image.NativeImageUtil;
import org.geysermc.rainbow.mapping.AssetResolver; import org.geysermc.rainbow.mapping.AssetResolver;
import org.geysermc.rainbow.mapping.BedrockItemMapper; import org.geysermc.rainbow.mapping.BedrockItemMapper;
import org.geysermc.rainbow.mapping.PackContext; 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.geysermc.rainbow.mapping.geometry.TextureHolder;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@@ -36,7 +33,6 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
public class BedrockPack { public class BedrockPack {
@@ -131,13 +127,7 @@ public class BedrockPack {
Function<TextureHolder, CompletableFuture<?>> textureSaver = texture -> { Function<TextureHolder, CompletableFuture<?>> textureSaver = texture -> {
ResourceLocation textureLocation = Rainbow.decorateTextureLocation(texture.location()); ResourceLocation textureLocation = Rainbow.decorateTextureLocation(texture.location());
return texture.supplier() return texture.load(context.assetResolver(), reporter)
.flatMap(image -> RainbowIO.safeIO(() -> NativeImageUtil.writeToByteArray(image.get())))
.or(() -> RainbowIO.safeIO(() -> {
try (InputStream textureStream = context.assetResolver().openAsset(textureLocation)) {
return textureStream.readAllBytes();
}
}))
.map(bytes -> serializer.saveTexture(bytes, paths.packRoot().resolve(textureLocation.getPath()))) .map(bytes -> serializer.saveTexture(bytes, paths.packRoot().resolve(textureLocation.getPath())))
.orElse(CompletableFuture.completedFuture(null)); .orElse(CompletableFuture.completedFuture(null));
}; };