mirror of
https://github.com/GeyserMC/Rainbow.git
synced 2025-12-19 14:59:16 +00:00
Split the mod in half
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("rainbow.base-conventions")
|
id("rainbow.base-conventions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Implement namedElements so IntelliJ can use it correctly, but include the remapped build
|
||||||
|
implementation(project(path = ":rainbow", configuration = "namedElements"))
|
||||||
|
include(project(":rainbow"))
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package org.geysermc.rainbow.client;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.item.ClientItem;
|
||||||
|
import net.minecraft.client.resources.model.EquipmentClientInfo;
|
||||||
|
import net.minecraft.client.resources.model.ResolvedModel;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.equipment.EquipmentAsset;
|
||||||
|
import org.geysermc.rainbow.mapping.AssetResolver;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class MinecraftAssetResolver implements AssetResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ResolvedModel> getResolvedModel(ResourceLocation location) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ClientItem> getClientItem(ResourceLocation location) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EquipmentClientInfo getEquipmentInfo(ResourceKey<EquipmentAsset> key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getTexture(ResourceLocation location) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HolderLookup.Provider registries() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow;
|
package org.geysermc.rainbow.client;
|
||||||
|
|
||||||
import org.geysermc.rainbow.pack.BedrockPack;
|
import org.geysermc.rainbow.pack.BedrockPack;
|
||||||
|
|
||||||
@@ -6,7 +6,6 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public final class PackManager {
|
public final class PackManager {
|
||||||
|
|
||||||
@@ -17,7 +16,7 @@ public final class PackManager {
|
|||||||
throw new IllegalStateException("Already started a pack (" + currentPack.get().name() + ")");
|
throw new IllegalStateException("Already started a pack (" + currentPack.get().name() + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPack = Optional.of(new BedrockPack(name));
|
currentPack = Optional.of(new BedrockPack(name, new MinecraftAssetResolver()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run(Consumer<BedrockPack> consumer) {
|
public void run(Consumer<BedrockPack> consumer) {
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package org.geysermc.rainbow.client;
|
||||||
|
|
||||||
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
||||||
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
|
import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry;
|
||||||
|
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
|
||||||
|
import org.geysermc.rainbow.Rainbow;
|
||||||
|
import org.geysermc.rainbow.client.command.CommandSuggestionsArgumentType;
|
||||||
|
import org.geysermc.rainbow.client.command.PackGeneratorCommand;
|
||||||
|
import org.geysermc.rainbow.client.mapper.PackMapper;
|
||||||
|
|
||||||
|
public class RainbowClient implements ClientModInitializer {
|
||||||
|
|
||||||
|
private final PackManager packManager = new PackManager();
|
||||||
|
private final PackMapper packMapper = new PackMapper(packManager);
|
||||||
|
|
||||||
|
// TODO export language overrides
|
||||||
|
@Override
|
||||||
|
public void onInitializeClient() {
|
||||||
|
ClientCommandRegistrationCallback.EVENT.register((dispatcher, buildContext) -> PackGeneratorCommand.register(dispatcher, packManager, packMapper));
|
||||||
|
ClientTickEvents.START_CLIENT_TICK.register(packMapper::tick);
|
||||||
|
|
||||||
|
ArgumentTypeRegistry.registerArgumentType(Rainbow.getModdedLocation("command_suggestions"),
|
||||||
|
CommandSuggestionsArgumentType.class, SingletonArgumentInfo.contextFree(CommandSuggestionsArgumentType::new));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.accessor;
|
package org.geysermc.rainbow.client.accessor;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.item.ClientItem;
|
import net.minecraft.client.renderer.item.ClientItem;
|
||||||
import net.minecraft.client.resources.model.ResolvedModel;
|
import net.minecraft.client.resources.model.ResolvedModel;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.command;
|
package org.geysermc.rainbow.client.command;
|
||||||
|
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.command;
|
package org.geysermc.rainbow.client.command;
|
||||||
|
|
||||||
import com.mojang.brigadier.Command;
|
import com.mojang.brigadier.Command;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
@@ -10,9 +10,9 @@ import net.minecraft.network.chat.ClickEvent;
|
|||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.geysermc.rainbow.PackManager;
|
import org.geysermc.rainbow.client.PackManager;
|
||||||
import org.geysermc.rainbow.mapper.InventoryMapper;
|
import org.geysermc.rainbow.client.mapper.InventoryMapper;
|
||||||
import org.geysermc.rainbow.mapper.PackMapper;
|
import org.geysermc.rainbow.client.mapper.PackMapper;
|
||||||
import org.geysermc.rainbow.pack.BedrockPack;
|
import org.geysermc.rainbow.pack.BedrockPack;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mapper;
|
package org.geysermc.rainbow.client.mapper;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mapper;
|
package org.geysermc.rainbow.client.mapper;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mapper;
|
package org.geysermc.rainbow.client.mapper;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
package org.geysermc.rainbow.mapper;
|
package org.geysermc.rainbow.client.mapper;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import org.geysermc.rainbow.PackManager;
|
import org.geysermc.rainbow.client.PackManager;
|
||||||
import org.geysermc.rainbow.pack.BedrockPack;
|
import org.geysermc.rainbow.pack.BedrockPack;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class PackMapper {
|
public class PackMapper {
|
||||||
private final PackManager packManager;
|
private final PackManager packManager;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mixin;
|
package org.geysermc.rainbow.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||||
import net.minecraft.client.resources.model.EquipmentAssetManager;
|
import net.minecraft.client.resources.model.EquipmentAssetManager;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mixin;
|
package org.geysermc.rainbow.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.gui.render.state.GuiItemRenderState;
|
import net.minecraft.client.gui.render.state.GuiItemRenderState;
|
||||||
import net.minecraft.client.gui.render.state.ScreenArea;
|
import net.minecraft.client.gui.render.state.ScreenArea;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mixin;
|
package org.geysermc.rainbow.client.mixin;
|
||||||
|
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
@@ -9,7 +9,7 @@ import net.minecraft.client.resources.model.ModelManager;
|
|||||||
import net.minecraft.client.resources.model.ResolvedModel;
|
import net.minecraft.client.resources.model.ResolvedModel;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||||
import org.geysermc.rainbow.accessor.ResolvedModelAccessor;
|
import org.geysermc.rainbow.client.accessor.ResolvedModelAccessor;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mixin;
|
package org.geysermc.rainbow.client.mixin;
|
||||||
|
|
||||||
import com.mojang.blaze3d.textures.GpuTexture;
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package org.geysermc.rainbow.mixin;
|
package org.geysermc.rainbow.client.mixin;
|
||||||
|
|
||||||
import com.mojang.blaze3d.textures.GpuTexture;
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
||||||
import org.geysermc.rainbow.render.PictureInPictureCopyRenderer;
|
import org.geysermc.rainbow.client.render.PictureInPictureCopyRenderer;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.mixin;
|
package org.geysermc.rainbow.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.gui.components.SplashRenderer;
|
import net.minecraft.client.gui.components.SplashRenderer;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package org.geysermc.rainbow.client.render;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
||||||
|
import net.minecraft.client.gui.render.pip.OversizedItemRenderer;
|
||||||
|
import net.minecraft.client.gui.render.state.GuiItemRenderState;
|
||||||
|
import net.minecraft.client.gui.render.state.GuiRenderState;
|
||||||
|
import net.minecraft.client.gui.render.state.pip.OversizedItemRenderState;
|
||||||
|
import net.minecraft.client.renderer.item.TrackingItemStackRenderState;
|
||||||
|
import net.minecraft.world.item.ItemDisplayContext;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.geysermc.rainbow.CodecUtil;
|
||||||
|
import org.geysermc.rainbow.mapping.geometry.GeometryRenderer;
|
||||||
|
import org.geysermc.rainbow.client.mixin.PictureInPictureRendererAccessor;
|
||||||
|
import org.joml.Matrix3x2fStack;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
// TODO maybe just use this even for normal 2D items, not sure, could be useful for composite models and stuff
|
||||||
|
// TODO output in a size bedrock likes
|
||||||
|
public class MinecraftGeometryRenderer implements GeometryRenderer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean render(ItemStack stack, Path path) {
|
||||||
|
TrackingItemStackRenderState itemRenderState = new TrackingItemStackRenderState();
|
||||||
|
Minecraft.getInstance().getItemModelResolver().updateForTopItem(itemRenderState, stack, ItemDisplayContext.GUI, null, null, 0);
|
||||||
|
itemRenderState.setOversizedInGui(true);
|
||||||
|
|
||||||
|
GuiItemRenderState guiItemRenderState = new GuiItemRenderState("geometry_render", new Matrix3x2fStack(16), itemRenderState, 0, 0, null);
|
||||||
|
ScreenRectangle sizeBounds = guiItemRenderState.oversizedItemBounds();
|
||||||
|
Objects.requireNonNull(sizeBounds);
|
||||||
|
OversizedItemRenderState oversizedRenderState = new OversizedItemRenderState(guiItemRenderState, sizeBounds.left(), sizeBounds.top(), sizeBounds.right() + 4, sizeBounds.bottom() + 4);
|
||||||
|
|
||||||
|
try (OversizedItemRenderer itemRenderer = new OversizedItemRenderer(Minecraft.getInstance().renderBuffers().bufferSource())) {
|
||||||
|
//noinspection DataFlowIssue
|
||||||
|
((PictureInPictureCopyRenderer) itemRenderer).rainbow$allowTextureCopy();
|
||||||
|
itemRenderer.prepare(oversizedRenderState, new GuiRenderState(), 4);
|
||||||
|
writeAsPNG(path, ((PictureInPictureRendererAccessor) itemRenderer).getTexture());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simplified TextureUtil#writeAsPNG with some modifications to flip the image and just generate it at full size
|
||||||
|
private static void writeAsPNG(Path path, GpuTexture texture) {
|
||||||
|
RenderSystem.assertOnRenderThread();
|
||||||
|
int width = texture.getWidth(0);
|
||||||
|
int height = texture.getHeight(0);
|
||||||
|
int bufferSize = texture.getFormat().pixelSize() * width * height;
|
||||||
|
|
||||||
|
GpuBuffer buffer = RenderSystem.getDevice().createBuffer(() -> "Texture output buffer", GpuBuffer.USAGE_COPY_DST | GpuBuffer.USAGE_MAP_READ, bufferSize);
|
||||||
|
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
|
||||||
|
|
||||||
|
Runnable writer = () -> {
|
||||||
|
try (GpuBuffer.MappedView mappedView = commandEncoder.mapBuffer(buffer, true, false)) {
|
||||||
|
try (NativeImage nativeImage = new NativeImage(width, height, false)) {
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
int colour = mappedView.data().getInt((x + y * width) * texture.getFormat().pixelSize());
|
||||||
|
nativeImage.setPixelABGR(x, height - y - 1, colour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecUtil.ensureDirectoryExists(path.getParent());
|
||||||
|
nativeImage.writeToFile(path);
|
||||||
|
} catch (IOException var19) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.close();
|
||||||
|
};
|
||||||
|
commandEncoder.copyTextureToBuffer(texture, buffer, 0, writer, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.geysermc.rainbow.render;
|
package org.geysermc.rainbow.client.render;
|
||||||
|
|
||||||
public interface PictureInPictureCopyRenderer {
|
public interface PictureInPictureCopyRenderer {
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 282 B |
38
client/src/main/resources/fabric.mod.json
Normal file
38
client/src/main/resources/fabric.mod.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "rainbow-client",
|
||||||
|
"version": "${version}",
|
||||||
|
"name": "Rainbow",
|
||||||
|
"description": "Rainbow is a mod to generate Geyser item mappings and bedrock resourcepacks for use with Geyser's custom item API (v2)",
|
||||||
|
"authors": [
|
||||||
|
"GeyserMC contributors"
|
||||||
|
],
|
||||||
|
"contact": {
|
||||||
|
"homepage": "https://github.com/GeyserMC/rainbow",
|
||||||
|
"issues": "https://github.com/GeyserMC/rainbow/issues",
|
||||||
|
"sources": "https://github.com/GeyserMC/rainbow"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"icon": "assets/rainbow/icon.png",
|
||||||
|
"environment": "client",
|
||||||
|
"entrypoints": {
|
||||||
|
"client": [
|
||||||
|
"org.geysermc.rainbow.client.RainbowClient"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mixins": [
|
||||||
|
"rainbow-client.mixins.json"
|
||||||
|
],
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": ">=${loader_version}",
|
||||||
|
"fabric-api": "*",
|
||||||
|
"minecraft": "${supported_versions}"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"modmenu": {
|
||||||
|
"links": {
|
||||||
|
"modmenu.discord": "https://discord.gg/GeyserMC"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
client/src/main/resources/rainbow-client.mixins.json
Normal file
18
client/src/main/resources/rainbow-client.mixins.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"minVersion": "0.8",
|
||||||
|
"package": "org.geysermc.rainbow.client.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_21",
|
||||||
|
"mixins": [],
|
||||||
|
"client": [
|
||||||
|
"EntityRenderDispatcherAccessor",
|
||||||
|
"GuiItemRenderStateMixin",
|
||||||
|
"ModelManagerMixin",
|
||||||
|
"PictureInPictureRendererAccessor",
|
||||||
|
"PictureInPictureRendererMixin",
|
||||||
|
"SplashRendererAccessor"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +1,15 @@
|
|||||||
package org.geysermc.rainbow;
|
package org.geysermc.rainbow;
|
||||||
|
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
|
||||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
|
||||||
import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry;
|
|
||||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.geysermc.rainbow.command.CommandSuggestionsArgumentType;
|
|
||||||
import org.geysermc.rainbow.command.PackGeneratorCommand;
|
|
||||||
import org.geysermc.rainbow.mapper.PackMapper;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
public class Rainbow implements ClientModInitializer {
|
public class Rainbow {
|
||||||
|
|
||||||
public static final String MOD_ID = "rainbow";
|
public static final String MOD_ID = "rainbow";
|
||||||
public static final String MOD_NAME = "Rainbow";
|
public static final String MOD_NAME = "Rainbow";
|
||||||
public static final Logger LOGGER = LogUtils.getLogger();
|
public static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
|
||||||
private final PackManager packManager = new PackManager();
|
|
||||||
private final PackMapper packMapper = new PackMapper(packManager);
|
|
||||||
|
|
||||||
// TODO export language overrides
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, buildContext) -> PackGeneratorCommand.register(dispatcher, packManager, packMapper));
|
|
||||||
ClientTickEvents.START_CLIENT_TICK.register(packMapper::tick);
|
|
||||||
|
|
||||||
ArgumentTypeRegistry.registerArgumentType(getModdedLocation("command_suggestions"),
|
|
||||||
CommandSuggestionsArgumentType.class, SingletonArgumentInfo.contextFree(CommandSuggestionsArgumentType::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceLocation getModdedLocation(String path) {
|
public static ResourceLocation getModdedLocation(String path) {
|
||||||
return ResourceLocation.fromNamespaceAndPath(MOD_ID, path);
|
return ResourceLocation.fromNamespaceAndPath(MOD_ID, path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.geysermc.rainbow.mapping;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.item.ClientItem;
|
||||||
|
import net.minecraft.client.resources.model.EquipmentClientInfo;
|
||||||
|
import net.minecraft.client.resources.model.ResolvedModel;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.equipment.EquipmentAsset;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface AssetResolver {
|
||||||
|
|
||||||
|
Optional<ResolvedModel> getResolvedModel(ResourceLocation location);
|
||||||
|
|
||||||
|
Optional<ClientItem> getClientItem(ResourceLocation location);
|
||||||
|
|
||||||
|
EquipmentClientInfo getEquipmentInfo(ResourceKey<EquipmentAsset> key);
|
||||||
|
|
||||||
|
InputStream getTexture(ResourceLocation location);
|
||||||
|
|
||||||
|
HolderLookup.Provider registries();
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.geysermc.rainbow.mapping;
|
package org.geysermc.rainbow.mapping;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.item.BlockModelWrapper;
|
import net.minecraft.client.renderer.item.BlockModelWrapper;
|
||||||
import net.minecraft.client.renderer.item.ClientItem;
|
import net.minecraft.client.renderer.item.ClientItem;
|
||||||
import net.minecraft.client.renderer.item.ConditionalItemModel;
|
import net.minecraft.client.renderer.item.ConditionalItemModel;
|
||||||
@@ -38,13 +37,11 @@ import net.minecraft.world.item.component.ItemAttributeModifiers;
|
|||||||
import net.minecraft.world.item.equipment.trim.TrimMaterial;
|
import net.minecraft.world.item.equipment.trim.TrimMaterial;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.geysermc.rainbow.accessor.ResolvedModelAccessor;
|
|
||||||
import org.geysermc.rainbow.mapping.animation.AnimationMapper;
|
import org.geysermc.rainbow.mapping.animation.AnimationMapper;
|
||||||
import org.geysermc.rainbow.mapping.animation.BedrockAnimationContext;
|
import org.geysermc.rainbow.mapping.animation.BedrockAnimationContext;
|
||||||
import org.geysermc.rainbow.mapping.attachable.AttachableMapper;
|
import org.geysermc.rainbow.mapping.attachable.AttachableMapper;
|
||||||
import org.geysermc.rainbow.mapping.geometry.BedrockGeometryContext;
|
import org.geysermc.rainbow.mapping.geometry.BedrockGeometryContext;
|
||||||
import org.geysermc.rainbow.mapping.geometry.GeometryMapper;
|
import org.geysermc.rainbow.mapping.geometry.GeometryMapper;
|
||||||
import org.geysermc.rainbow.mapping.geometry.GeometryRenderer;
|
|
||||||
import org.geysermc.rainbow.mapping.geyser.GeyserBaseDefinition;
|
import org.geysermc.rainbow.mapping.geyser.GeyserBaseDefinition;
|
||||||
import org.geysermc.rainbow.mapping.geyser.GeyserItemDefinition;
|
import org.geysermc.rainbow.mapping.geyser.GeyserItemDefinition;
|
||||||
import org.geysermc.rainbow.mapping.geyser.GeyserLegacyDefinition;
|
import org.geysermc.rainbow.mapping.geyser.GeyserLegacyDefinition;
|
||||||
@@ -72,23 +69,19 @@ public class BedrockItemMapper {
|
|||||||
.map(ResourceLocation::withDefaultNamespace)
|
.map(ResourceLocation::withDefaultNamespace)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
private static ResolvedModelAccessor getModels() {
|
|
||||||
return (ResolvedModelAccessor) Minecraft.getInstance().getModelManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ResourceLocation getModelId(ItemModel.Unbaked model) {
|
private static ResourceLocation getModelId(ItemModel.Unbaked model) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return ((LateBoundIdMapperAccessor<ResourceLocation, ?>) ItemModels.ID_MAPPER).getIdToValue().inverse().get(model.type());
|
return ((LateBoundIdMapperAccessor<ResourceLocation, ?>) ItemModels.ID_MAPPER).getIdToValue().inverse().get(model.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) {
|
||||||
getModels().rainbow$getClientItem(modelLocation).map(ClientItem::model)
|
context.assetResolver().getClientItem(modelLocation).map(ClientItem::model)
|
||||||
.ifPresentOrElse(model -> mapItem(model, stack, reporter.forChild(() -> "client item definition " + modelLocation + " "), base -> new GeyserSingleDefinition(base, Optional.of(modelLocation)), context),
|
.ifPresentOrElse(model -> mapItem(model, stack, reporter.forChild(() -> "client item definition " + modelLocation + " "), base -> new GeyserSingleDefinition(base, Optional.of(modelLocation)), context),
|
||||||
() -> reporter.report(() -> "missing client item definition " + modelLocation));
|
() -> reporter.report(() -> "missing client item definition " + modelLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tryMapStack(ItemStack stack, int customModelData, ProblemReporter reporter, PackContext context) {
|
public static void tryMapStack(ItemStack stack, int customModelData, ProblemReporter reporter, PackContext context) {
|
||||||
ItemModel.Unbaked vanillaModel = getModels().rainbow$getClientItem(stack.get(DataComponents.ITEM_MODEL)).map(ClientItem::model).orElseThrow();
|
ItemModel.Unbaked vanillaModel = context.assetResolver().getClientItem(stack.get(DataComponents.ITEM_MODEL)).map(ClientItem::model).orElseThrow();
|
||||||
ProblemReporter childReporter = reporter.forChild(() -> "item model " + vanillaModel + " with custom model data " + customModelData + " ");
|
ProblemReporter childReporter = reporter.forChild(() -> "item model " + vanillaModel + " with custom model data " + customModelData + " ");
|
||||||
if (vanillaModel instanceof RangeSelectItemModel.Unbaked(RangeSelectItemModelProperty property, float scale, List<RangeSelectItemModel.Entry> entries, Optional<ItemModel.Unbaked> fallback)) {
|
if (vanillaModel instanceof RangeSelectItemModel.Unbaked(RangeSelectItemModelProperty property, float scale, List<RangeSelectItemModel.Entry> entries, Optional<ItemModel.Unbaked> fallback)) {
|
||||||
// WHY, Mojang?
|
// WHY, Mojang?
|
||||||
@@ -130,7 +123,7 @@ public class BedrockItemMapper {
|
|||||||
private static void mapBlockModelWrapper(BlockModelWrapper.Unbaked model, MappingContext context) {
|
private static void mapBlockModelWrapper(BlockModelWrapper.Unbaked model, MappingContext context) {
|
||||||
ResourceLocation itemModelLocation = model.model();
|
ResourceLocation itemModelLocation = model.model();
|
||||||
|
|
||||||
getModels().rainbow$getResolvedModel(itemModelLocation)
|
context.packContext().assetResolver().getResolvedModel(itemModelLocation)
|
||||||
.ifPresentOrElse(itemModel -> {
|
.ifPresentOrElse(itemModel -> {
|
||||||
ResolvedModel parentModel = itemModel.parent();
|
ResolvedModel parentModel = itemModel.parent();
|
||||||
// debugName() returns the resource location of the model as a string
|
// debugName() returns the resource location of the model as a string
|
||||||
@@ -290,13 +283,15 @@ public class BedrockItemMapper {
|
|||||||
boolean exportTexture = true;
|
boolean exportTexture = true;
|
||||||
if (customModel.isPresent()) {
|
if (customModel.isPresent()) {
|
||||||
texture = texture.withPath(path -> path + "_icon");
|
texture = texture.withPath(path -> path + "_icon");
|
||||||
GeometryRenderer.render(stack, packContext.packPath().resolve(BedrockTextures.TEXTURES_FOLDER + texture.getPath() + ".png"));
|
// FIXME Bit of a hack, preferably render geometry at a later stage
|
||||||
exportTexture = false;
|
exportTexture = !packContext.geometryRenderer().render(stack, packContext.packPath().resolve(BedrockTextures.TEXTURES_FOLDER + texture.getPath() + ".png"));
|
||||||
packContext.additionalTextureConsumer().accept(geometryTexture);
|
packContext.additionalTextureConsumer().accept(geometryTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
packContext.itemConsumer().accept(new BedrockItem(bedrockIdentifier, base.textureName(), texture, exportTexture,
|
packContext.itemConsumer().accept(new BedrockItem(bedrockIdentifier, base.textureName(), texture, exportTexture,
|
||||||
AttachableMapper.mapItem(stack.getComponentsPatch(), bedrockIdentifier, bedrockGeometry, bedrockAnimation, packContext.additionalTextureConsumer()),
|
AttachableMapper.mapItem(stack.getComponentsPatch(), bedrockIdentifier, bedrockGeometry, bedrockAnimation,
|
||||||
|
packContext.assetResolver(),
|
||||||
|
packContext.additionalTextureConsumer()),
|
||||||
bedrockGeometry.map(BedrockGeometryContext::geometry), bedrockAnimation.map(BedrockAnimationContext::animation)));
|
bedrockGeometry.map(BedrockGeometryContext::geometry), bedrockAnimation.map(BedrockAnimationContext::animation)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package org.geysermc.rainbow.mapping;
|
package org.geysermc.rainbow.mapping;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.geysermc.rainbow.mapping.geometry.GeometryRenderer;
|
||||||
import org.geysermc.rainbow.mapping.geyser.GeyserMappings;
|
import org.geysermc.rainbow.mapping.geyser.GeyserMappings;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public record PackContext(GeyserMappings mappings, Path packPath, BedrockItemConsumer itemConsumer, Consumer<ResourceLocation> additionalTextureConsumer) {
|
public record PackContext(GeyserMappings mappings, Path packPath, BedrockItemConsumer itemConsumer, AssetResolver assetResolver,
|
||||||
|
GeometryRenderer geometryRenderer, Consumer<ResourceLocation> additionalTextureConsumer) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.geysermc.rainbow.mapping.attachable;
|
package org.geysermc.rainbow.mapping.attachable;
|
||||||
|
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.resources.model.EquipmentAssetManager;
|
import net.minecraft.client.resources.model.EquipmentAssetManager;
|
||||||
import net.minecraft.client.resources.model.EquipmentClientInfo;
|
import net.minecraft.client.resources.model.EquipmentClientInfo;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
import net.minecraft.core.component.DataComponentPatch;
|
||||||
@@ -9,9 +8,9 @@ import net.minecraft.core.component.DataComponents;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.EquipmentSlot;
|
import net.minecraft.world.entity.EquipmentSlot;
|
||||||
import net.minecraft.world.item.equipment.Equippable;
|
import net.minecraft.world.item.equipment.Equippable;
|
||||||
|
import org.geysermc.rainbow.mapping.AssetResolver;
|
||||||
import org.geysermc.rainbow.mapping.animation.BedrockAnimationContext;
|
import org.geysermc.rainbow.mapping.animation.BedrockAnimationContext;
|
||||||
import org.geysermc.rainbow.mapping.geometry.BedrockGeometryContext;
|
import org.geysermc.rainbow.mapping.geometry.BedrockGeometryContext;
|
||||||
import org.geysermc.rainbow.mixin.EntityRenderDispatcherAccessor;
|
|
||||||
import org.geysermc.rainbow.pack.attachable.BedrockAttachable;
|
import org.geysermc.rainbow.pack.attachable.BedrockAttachable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -21,17 +20,14 @@ import java.util.function.Consumer;
|
|||||||
public class AttachableMapper {
|
public class AttachableMapper {
|
||||||
|
|
||||||
public static Optional<BedrockAttachable> mapItem(DataComponentPatch components, ResourceLocation bedrockIdentifier, Optional<BedrockGeometryContext> customGeometry,
|
public static Optional<BedrockAttachable> mapItem(DataComponentPatch components, ResourceLocation bedrockIdentifier, Optional<BedrockGeometryContext> customGeometry,
|
||||||
Optional<BedrockAnimationContext> customAnimation, Consumer<ResourceLocation> textureConsumer) {
|
Optional<BedrockAnimationContext> customAnimation, AssetResolver assetResolver, Consumer<ResourceLocation> textureConsumer) {
|
||||||
// Crazy optional statement
|
// Crazy optional statement
|
||||||
// Unfortunately we can't have both equippables and custom models, so we prefer the latter :(
|
// Unfortunately we can't have both equippables and custom models, so we prefer the latter :(
|
||||||
return customGeometry
|
return customGeometry
|
||||||
.map(geometry -> BedrockAttachable.geometry(bedrockIdentifier, geometry.geometry().definitions().getFirst(), geometry.texture().getPath()))
|
.map(geometry -> BedrockAttachable.geometry(bedrockIdentifier, geometry.geometry().definitions().getFirst(), geometry.texture().getPath()))
|
||||||
.or(() -> Optional.ofNullable(components.get(DataComponents.EQUIPPABLE))
|
.or(() -> Optional.ofNullable(components.get(DataComponents.EQUIPPABLE))
|
||||||
.flatMap(optional -> (Optional<Equippable>) optional)
|
.flatMap(optional -> (Optional<Equippable>) optional)
|
||||||
.flatMap(equippable -> {
|
.flatMap(equippable -> equippable.assetId().map(asset -> Pair.of(equippable.slot(), assetResolver.getEquipmentInfo(asset))))
|
||||||
EquipmentAssetManager equipmentAssets = ((EntityRenderDispatcherAccessor) Minecraft.getInstance().getEntityRenderDispatcher()).getEquipmentAssets();
|
|
||||||
return equippable.assetId().map(asset -> Pair.of(equippable.slot(), equipmentAssets.get(asset)));
|
|
||||||
})
|
|
||||||
.filter(assetInfo -> assetInfo.getSecond() != EquipmentAssetManager.MISSING)
|
.filter(assetInfo -> assetInfo.getSecond() != EquipmentAssetManager.MISSING)
|
||||||
.map(assetInfo -> assetInfo
|
.map(assetInfo -> assetInfo
|
||||||
.mapSecond(info -> info.getLayers(getLayer(assetInfo.getFirst()))))
|
.mapSecond(info -> info.getLayers(getLayer(assetInfo.getFirst()))))
|
||||||
|
|||||||
@@ -1,79 +1,10 @@
|
|||||||
package org.geysermc.rainbow.mapping.geometry;
|
package org.geysermc.rainbow.mapping.geometry;
|
||||||
|
|
||||||
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
|
||||||
import com.mojang.blaze3d.systems.CommandEncoder;
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.textures.GpuTexture;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
|
||||||
import net.minecraft.client.gui.render.pip.OversizedItemRenderer;
|
|
||||||
import net.minecraft.client.gui.render.state.GuiItemRenderState;
|
|
||||||
import net.minecraft.client.gui.render.state.GuiRenderState;
|
|
||||||
import net.minecraft.client.gui.render.state.pip.OversizedItemRenderState;
|
|
||||||
import net.minecraft.client.renderer.item.TrackingItemStackRenderState;
|
|
||||||
import net.minecraft.world.item.ItemDisplayContext;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.geysermc.rainbow.CodecUtil;
|
|
||||||
import org.geysermc.rainbow.mixin.PictureInPictureRendererAccessor;
|
|
||||||
import org.geysermc.rainbow.render.PictureInPictureCopyRenderer;
|
|
||||||
import org.joml.Matrix3x2fStack;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
// TODO maybe just use this even for normal 2D items, not sure, could be useful for composite models and stuff
|
public interface GeometryRenderer {
|
||||||
// TODO output in a size bedrock likes
|
|
||||||
public class GeometryRenderer {
|
|
||||||
|
|
||||||
public static void render(ItemStack stack, Path path) {
|
boolean render(ItemStack stack, Path path);
|
||||||
TrackingItemStackRenderState itemRenderState = new TrackingItemStackRenderState();
|
|
||||||
Minecraft.getInstance().getItemModelResolver().updateForTopItem(itemRenderState, stack, ItemDisplayContext.GUI, null, null, 0);
|
|
||||||
itemRenderState.setOversizedInGui(true);
|
|
||||||
|
|
||||||
GuiItemRenderState guiItemRenderState = new GuiItemRenderState("geometry_render", new Matrix3x2fStack(16), itemRenderState, 0, 0, null);
|
|
||||||
ScreenRectangle sizeBounds = guiItemRenderState.oversizedItemBounds();
|
|
||||||
Objects.requireNonNull(sizeBounds);
|
|
||||||
OversizedItemRenderState oversizedRenderState = new OversizedItemRenderState(guiItemRenderState, sizeBounds.left(), sizeBounds.top(), sizeBounds.right() + 4, sizeBounds.bottom() + 4);
|
|
||||||
|
|
||||||
try (OversizedItemRenderer itemRenderer = new OversizedItemRenderer(Minecraft.getInstance().renderBuffers().bufferSource())) {
|
|
||||||
//noinspection DataFlowIssue
|
|
||||||
((PictureInPictureCopyRenderer) itemRenderer).rainbow$allowTextureCopy();
|
|
||||||
itemRenderer.prepare(oversizedRenderState, new GuiRenderState(), 4);
|
|
||||||
writeAsPNG(path, ((PictureInPictureRendererAccessor) itemRenderer).getTexture());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simplified TextureUtil#writeAsPNG with some modifications to flip the image and just generate it at full size
|
|
||||||
private static void writeAsPNG(Path path, GpuTexture texture) {
|
|
||||||
RenderSystem.assertOnRenderThread();
|
|
||||||
int width = texture.getWidth(0);
|
|
||||||
int height = texture.getHeight(0);
|
|
||||||
int bufferSize = texture.getFormat().pixelSize() * width * height;
|
|
||||||
|
|
||||||
GpuBuffer buffer = RenderSystem.getDevice().createBuffer(() -> "Texture output buffer", GpuBuffer.USAGE_COPY_DST | GpuBuffer.USAGE_MAP_READ, bufferSize);
|
|
||||||
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
|
|
||||||
|
|
||||||
Runnable writer = () -> {
|
|
||||||
try (GpuBuffer.MappedView mappedView = commandEncoder.mapBuffer(buffer, true, false)) {
|
|
||||||
try (NativeImage nativeImage = new NativeImage(width, height, false)) {
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
int colour = mappedView.data().getInt((x + y * width) * texture.getFormat().pixelSize());
|
|
||||||
nativeImage.setPixelABGR(x, height - y - 1, colour);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CodecUtil.ensureDirectoryExists(path.getParent());
|
|
||||||
nativeImage.writeToFile(path);
|
|
||||||
} catch (IOException var19) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.close();
|
|
||||||
};
|
|
||||||
commandEncoder.copyTextureToBuffer(texture, buffer, 0, writer, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.geysermc.rainbow.mapping.geometry;
|
||||||
|
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class NoopGeometryRenderer implements GeometryRenderer {
|
||||||
|
public static final NoopGeometryRenderer INSTANCE = new NoopGeometryRenderer();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean render(ItemStack stack, Path path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,6 @@ import com.mojang.serialization.JsonOps;
|
|||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.gui.components.SplashRenderer;
|
|
||||||
import net.minecraft.core.component.DataComponents;
|
import net.minecraft.core.component.DataComponents;
|
||||||
import net.minecraft.resources.RegistryOps;
|
import net.minecraft.resources.RegistryOps;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@@ -18,10 +16,11 @@ import org.apache.commons.io.IOUtils;
|
|||||||
import org.geysermc.rainbow.CodecUtil;
|
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.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;
|
||||||
|
import org.geysermc.rainbow.mapping.geometry.NoopGeometryRenderer;
|
||||||
import org.geysermc.rainbow.mapping.geyser.GeyserMappings;
|
import org.geysermc.rainbow.mapping.geyser.GeyserMappings;
|
||||||
import org.geysermc.rainbow.mixin.SplashRendererAccessor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@@ -74,7 +73,9 @@ public class BedrockPack {
|
|||||||
|
|
||||||
private final ProblemReporter.Collector reporter;
|
private final ProblemReporter.Collector reporter;
|
||||||
|
|
||||||
public BedrockPack(String name) throws IOException {
|
private final PackContext context;
|
||||||
|
|
||||||
|
public BedrockPack(String name, AssetResolver assetResolver) throws IOException {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
// Not reading existing item mappings/texture atlas for now since that doesn't work all that well yet
|
// Not reading existing item mappings/texture atlas for now since that doesn't work all that well yet
|
||||||
@@ -88,6 +89,14 @@ public class BedrockPack {
|
|||||||
itemTextures = BedrockTextures.builder();
|
itemTextures = BedrockTextures.builder();
|
||||||
|
|
||||||
reporter = new ProblemReporter.Collector(() -> "Bedrock pack " + name + " ");
|
reporter = new ProblemReporter.Collector(() -> "Bedrock pack " + name + " ");
|
||||||
|
|
||||||
|
context = new PackContext(mappings, packPath, item -> {
|
||||||
|
itemTextures.withItemTexture(item);
|
||||||
|
if (item.exportTexture()) {
|
||||||
|
texturesToExport.add(item.texture());
|
||||||
|
}
|
||||||
|
bedrockItems.add(item);
|
||||||
|
}, assetResolver, NoopGeometryRenderer.INSTANCE, texturesToExport::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public String name() {
|
||||||
@@ -113,13 +122,6 @@ public class BedrockPack {
|
|||||||
reporter.report(problem);
|
reporter.report(problem);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PackContext context = new PackContext(mappings, packPath, item -> {
|
|
||||||
itemTextures.withItemTexture(item);
|
|
||||||
if (item.exportTexture()) {
|
|
||||||
texturesToExport.add(item.texture());
|
|
||||||
}
|
|
||||||
bedrockItems.add(item);
|
|
||||||
}, texturesToExport::add);
|
|
||||||
|
|
||||||
Optional<? extends ResourceLocation> patchedModel = stack.getComponentsPatch().get(DataComponents.ITEM_MODEL);
|
Optional<? extends ResourceLocation> patchedModel = stack.getComponentsPatch().get(DataComponents.ITEM_MODEL);
|
||||||
//noinspection OptionalAssignedToNull - annoying Mojang
|
//noinspection OptionalAssignedToNull - annoying Mojang
|
||||||
@@ -148,7 +150,7 @@ public class BedrockPack {
|
|||||||
boolean success = true;
|
boolean success = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve(MAPPINGS_FILE), RegistryOps.create(JsonOps.INSTANCE, Minecraft.getInstance().level.registryAccess()));
|
CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve(MAPPINGS_FILE), RegistryOps.create(JsonOps.INSTANCE, context.assetResolver().registries()));
|
||||||
CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve(MANIFEST_FILE));
|
CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve(MANIFEST_FILE));
|
||||||
CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), packPath.resolve(ITEM_ATLAS_FILE));
|
CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), packPath.resolve(ITEM_ATLAS_FILE));
|
||||||
} catch (IOException | NullPointerException exception) {
|
} catch (IOException | NullPointerException exception) {
|
||||||
@@ -165,8 +167,8 @@ public class BedrockPack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (ResourceLocation texture : texturesToExport) {
|
for (ResourceLocation texture : texturesToExport) {
|
||||||
texture = texture.withPath(path -> "textures/" + path + ".png");
|
texture = texture.withPath(path -> "textures/" + path + ".png"); // FIXME
|
||||||
try (InputStream inputTexture = Minecraft.getInstance().getResourceManager().open(texture)) {
|
try (InputStream inputTexture = context.assetResolver().getTexture(texture)) {
|
||||||
Path texturePath = packPath.resolve(texture.getPath());
|
Path texturePath = packPath.resolve(texture.getPath());
|
||||||
CodecUtil.ensureDirectoryExists(texturePath.getParent());
|
CodecUtil.ensureDirectoryExists(texturePath.getParent());
|
||||||
try (OutputStream outputTexture = new FileOutputStream(texturePath.toFile())) {
|
try (OutputStream outputTexture = new FileOutputStream(texturePath.toFile())) {
|
||||||
@@ -227,11 +229,11 @@ Textures tried to export: %d
|
|||||||
|
|
||||||
private static String randomSummaryComment() {
|
private static String randomSummaryComment() {
|
||||||
if (RANDOM.nextDouble() < 0.6) {
|
if (RANDOM.nextDouble() < 0.6) {
|
||||||
SplashRenderer splash = Minecraft.getInstance().getSplashManager().getSplash();
|
/*SplashRenderer splash = Minecraft.getInstance().getSplashManager().getSplash();
|
||||||
if (splash == null) {
|
if (splash == null) {
|
||||||
return "Undefined Undefined :(";
|
return "Undefined Undefined :(";
|
||||||
}
|
}
|
||||||
return ((SplashRendererAccessor) splash).getSplash();
|
return ((SplashRendererAccessor) splash).getSplash();*/ // TODO
|
||||||
}
|
}
|
||||||
return randomBuiltinSummaryComment();
|
return randomBuiltinSummaryComment();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,8 @@
|
|||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "JAVA_21",
|
||||||
"mixins": [],
|
"mixins": [],
|
||||||
"client": [
|
"client": [
|
||||||
"EntityRenderDispatcherAccessor",
|
|
||||||
"GuiItemRenderStateMixin",
|
|
||||||
"LateBoundIdMapperAccessor",
|
"LateBoundIdMapperAccessor",
|
||||||
"ModelManagerMixin",
|
|
||||||
"PictureInPictureRendererAccessor",
|
|
||||||
"PictureInPictureRendererMixin",
|
|
||||||
"RangeSelectItemModelAccessor",
|
"RangeSelectItemModelAccessor",
|
||||||
"SplashRendererAccessor",
|
|
||||||
"TextureSlotsAccessor"
|
"TextureSlotsAccessor"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
|
|||||||
Reference in New Issue
Block a user