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.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<ResolvedModel> getResolvedModel(ResourceLocation 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(() -> {
try (BufferedReader reader = resourceManager.openAsReader(location.withPrefix("models/").withSuffix(".json"))) {
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.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 <T> ResourceLocation getId(ExtraCodecs.LateBoundIdMapper<ResourceLocation, T> mapper,
T type) {
//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) {
@@ -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;
}

View File

@@ -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 -> {

View File

@@ -38,7 +38,7 @@ public record BedrockGeometryContext(Optional<Supplier<StitchedGeometry>> 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<Supplier<StitchedGeometry>> 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);

View File

@@ -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<NativeImage>> supplier) {
public record TextureHolder(ResourceLocation location, Optional<Supplier<NativeImage>> supplier, boolean existsInResources) {
public TextureHolder(ResourceLocation location, Supplier<NativeImage> supplier) {
this(location, Optional.of(supplier));
public Optional<byte[]> 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<NativeImage> 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);
}
}

View File

@@ -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<TextureHolder, CompletableFuture<?>> 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));
};