diff --git a/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java b/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java index 56c634d..1a78547 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java +++ b/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java @@ -1,5 +1,6 @@ package org.geysermc.rainbow.client; +import com.mojang.blaze3d.platform.NativeImage; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.item.ClientItem; import net.minecraft.client.renderer.texture.SpriteContents; @@ -8,26 +9,31 @@ import net.minecraft.client.resources.model.EquipmentAssetManager; import net.minecraft.client.resources.model.EquipmentClientInfo; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ResolvedModel; -import net.minecraft.data.AtlasIds; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.item.equipment.EquipmentAsset; +import org.geysermc.rainbow.Rainbow; +import org.geysermc.rainbow.RainbowIO; import org.geysermc.rainbow.client.accessor.ResolvedModelAccessor; import org.geysermc.rainbow.client.mixin.EntityRenderDispatcherAccessor; import org.geysermc.rainbow.mapping.AssetResolver; import org.geysermc.rainbow.mapping.texture.TextureResource; import org.geysermc.rainbow.mixin.SpriteContentsAccessor; +import java.io.InputStream; import java.util.Optional; public class MinecraftAssetResolver implements AssetResolver { private final ModelManager modelManager; private final EquipmentAssetManager equipmentAssetManager; + private final ResourceManager resourceManager; private final AtlasManager atlasManager; public MinecraftAssetResolver(Minecraft minecraft) { modelManager = minecraft.getModelManager(); equipmentAssetManager = ((EntityRenderDispatcherAccessor) minecraft.getEntityRenderDispatcher()).getEquipmentAssets(); + resourceManager = minecraft.getResourceManager(); atlasManager = minecraft.getAtlasManager(); } @@ -47,8 +53,19 @@ public class MinecraftAssetResolver implements AssetResolver { } @Override - public Optional getBlockTexture(ResourceLocation location) { - SpriteContents contents = atlasManager.getAtlasOrThrow(AtlasIds.BLOCKS).getSprite(location).contents(); - return Optional.of(new TextureResource(((SpriteContentsAccessor) contents).getOriginalImage(), contents.width(), contents.height())); + public Optional getTexture(ResourceLocation atlas, ResourceLocation location) { + if (atlas == null) { + // Not in an atlas - so not animated, probably? + return RainbowIO.safeIO(() -> { + try (InputStream textureStream = resourceManager.open(Rainbow.decorateTextureLocation(location))) { + return new TextureResource(NativeImage.read(textureStream)); + } + }); + } + SpriteContents contents = atlasManager.getAtlasOrThrow(atlas).getSprite(location).contents(); + NativeImage original = ((SpriteContentsAccessor) contents).getOriginalImage(); + NativeImage textureCopy = new NativeImage(original.getWidth(), original.getHeight(), false); + textureCopy.copyFrom(original); + return Optional.of(new TextureResource(textureCopy, contents.width(), contents.height())); } } diff --git a/client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java b/client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java index f7fdbaa..2799c1e 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java +++ b/client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java @@ -28,7 +28,7 @@ public class MinecraftPackSerializer implements PackSerializer { @Override public CompletableFuture saveJson(Codec codec, T object, Path path) { DynamicOps ops = RegistryOps.create(JsonOps.INSTANCE, registries); - return CompletableFuture.runAsync(() -> RainbowIO.safeIO(() -> CodecUtil.trySaveJson(codec, object, path.resolveSibling(path.getFileName() + ".json"), ops)), + return CompletableFuture.runAsync(() -> RainbowIO.safeIO(() -> CodecUtil.trySaveJson(codec, object, path, ops)), Util.backgroundExecutor().forName("PackSerializer-saveJson")); } diff --git a/client/src/main/java/org/geysermc/rainbow/client/PackManager.java b/client/src/main/java/org/geysermc/rainbow/client/PackManager.java index 172e576..b00253d 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/PackManager.java +++ b/client/src/main/java/org/geysermc/rainbow/client/PackManager.java @@ -35,7 +35,7 @@ public final class PackManager { private static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir().resolve(Rainbow.MOD_ID); private static final Path PACK_DIRECTORY = Path.of("pack"); - private static final Path MAPPINGS_FILE = Path.of("geyser_mappings"); + private static final Path MAPPINGS_FILE = Path.of("geyser_mappings.json"); private static final Path PACK_ZIP_FILE = Path.of("pack.zip"); private static final Path REPORT_FILE = Path.of("report.txt"); 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 7766ec9..98e7a4b 100644 --- a/datagen/src/main/java/org/geysermc/rainbow/datagen/RainbowModelProvider.java +++ b/datagen/src/main/java/org/geysermc/rainbow/datagen/RainbowModelProvider.java @@ -216,7 +216,8 @@ public abstract class RainbowModelProvider extends FabricModelProvider { } @Override - public Optional getBlockTexture(ResourceLocation location) { + public Optional getTexture(ResourceLocation atlas, ResourceLocation location) { + // We don't care about atlas since there are none loaded at datagen return resourceManager.getResource(Rainbow.decorateTextureLocation(location)) .flatMap(resource -> RainbowIO.safeIO(() -> { Optional animationMetadata = resource.metadata().getSection(AnimationMetadataSection.TYPE); diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java index 58a985a..5dfd86e 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java @@ -18,5 +18,5 @@ public interface AssetResolver { Optional getEquipmentInfo(ResourceKey key); - Optional getBlockTexture(ResourceLocation location); + Optional getTexture(ResourceLocation atlas, ResourceLocation location); } 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 57f8ce7..10a858e 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 @@ -10,7 +10,6 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.equipment.Equippable; import org.geysermc.rainbow.mapping.AssetResolver; import org.geysermc.rainbow.mapping.geometry.BedrockGeometryContext; -import org.geysermc.rainbow.mapping.geometry.MappedGeometry; import org.geysermc.rainbow.mapping.texture.TextureHolder; import org.geysermc.rainbow.pack.attachable.BedrockAttachable; @@ -34,7 +33,7 @@ public class AttachableMapper { .filter(assetInfo -> !assetInfo.getSecond().isEmpty()) .map(assetInfo -> { ResourceLocation equipmentTexture = getTexture(assetInfo.getSecond(), getLayer(assetInfo.getFirst())); - textureConsumer.accept(TextureHolder.createBuiltIn(equipmentTexture)); + textureConsumer.accept(TextureHolder.createBuiltIn(null, 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 1b57233..8feec4d 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 @@ -3,6 +3,7 @@ package org.geysermc.rainbow.mapping.geometry; import net.minecraft.client.renderer.block.model.TextureSlots; import net.minecraft.client.resources.model.Material; import net.minecraft.client.resources.model.ResolvedModel; +import net.minecraft.data.AtlasIds; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import org.geysermc.rainbow.Rainbow; @@ -36,7 +37,7 @@ public record BedrockGeometryContext(Optional geometry, if (layer0Texture != null) { geometry = Optional.empty(); animation = Optional.empty(); - icon = TextureHolder.createBuiltIn(layer0Texture.texture()); + icon = TextureHolder.createBuiltIn(AtlasIds.BLOCKS, 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) diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/BuiltInTextureHolder.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/BuiltInTextureHolder.java index c90126e..1f5df9c 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/BuiltInTextureHolder.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/BuiltInTextureHolder.java @@ -11,17 +11,19 @@ import java.util.Objects; import java.util.Optional; public class BuiltInTextureHolder extends TextureHolder { + private final ResourceLocation atlas; private final ResourceLocation source; - public BuiltInTextureHolder(ResourceLocation location, ResourceLocation source) { + public BuiltInTextureHolder(ResourceLocation location, ResourceLocation atlas, ResourceLocation source) { super(location); + this.atlas = atlas; this.source = source; } @Override public Optional load(AssetResolver assetResolver, ProblemReporter reporter) { return RainbowIO.safeIO(() -> { - try (TextureResource texture = assetResolver.getBlockTexture(source).orElse(null)) { + try (TextureResource texture = assetResolver.getTexture(atlas, source).orElse(null)) { Objects.requireNonNull(texture); try (NativeImage firstFrame = texture.getFirstFrame(false)) { return NativeImageUtil.writeToByteArray(firstFrame); diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/StitchedTextures.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/StitchedTextures.java index e03c361..c3e8f9c 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/StitchedTextures.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/StitchedTextures.java @@ -55,7 +55,7 @@ public record StitchedTextures(Map sprites, Supplier private static Optional readSpriteContents(ResourceLocation location, PackContext context) { return RainbowIO.safeIO(() -> { - try (TextureResource texture = context.assetResolver().getBlockTexture(location).orElse(null)) { + try (TextureResource texture = context.assetResolver().getTexture(AtlasIds.BLOCKS, location).orElse(null)) { if (texture != null) { return new SpriteContents(location, texture.sizeOfFrame(), texture.getFirstFrame(true)); } diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureHolder.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureHolder.java index e7c821f..3e98019 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureHolder.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureHolder.java @@ -30,12 +30,12 @@ public abstract class TextureHolder { return new CustomTextureHolder(location, supplier); } - public static TextureHolder createBuiltIn(ResourceLocation location, ResourceLocation source) { - return new BuiltInTextureHolder(location, source); + public static TextureHolder createBuiltIn(ResourceLocation location, ResourceLocation atlas, ResourceLocation source) { + return new BuiltInTextureHolder(location, atlas, source); } - public static TextureHolder createBuiltIn(ResourceLocation location) { - return createBuiltIn(location, location); + public static TextureHolder createBuiltIn(ResourceLocation atlas, ResourceLocation location) { + return createBuiltIn(location, atlas, location); } public static TextureHolder createNonExistent(ResourceLocation location) { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureResource.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureResource.java index dbaad8f..862c3d3 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureResource.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/texture/TextureResource.java @@ -11,13 +11,17 @@ public record TextureResource(NativeImage texture, Optional frameSize this(texture, texture.getWidth() != width || texture.getHeight() != height ? Optional.of(new FrameSize(width, height)) : Optional.empty()); } + public TextureResource(NativeImage texture) { + this(texture, Optional.empty()); + } + public NativeImage getFirstFrame(boolean copy) { if (frameSize.isEmpty() && !copy) { return texture; } FrameSize size = sizeOfFrame(); NativeImage firstFrame = new NativeImage(size.width(), size.height(), false); - texture.copyRect(firstFrame, 0, 0, 0, 0, size.width(), size.height(), false, false); + firstFrame.copyFrom(texture); return firstFrame; }