From 76450cb5c5cabbce8aa85d462390634549491a07 Mon Sep 17 00:00:00 2001 From: pizzacalz0ne Date: Thu, 11 Sep 2025 22:45:29 +1100 Subject: [PATCH 1/5] 1.21.8 yippee --- build.gradle | 5 +- gradle.properties | 18 +-- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/io/wispforest/lavender/Lavender.java | 27 ++-- .../wispforest/lavender/LavenderCommands.java | 3 +- .../wispforest/lavender/book/BookLoader.java | 7 +- .../lavender/book/LavenderBookItem.java | 10 +- .../lavender/book/LavenderClientStorage.java | 18 ++- .../lavender/book/StructureComponent.java | 48 ++----- .../book/StructureComponentRenderState.java | 113 +++++++++++++++ .../AssociatedEntryTooltipComponent.java | 5 +- .../lavender/client/BlitAlphaProgram.java | 31 ---- .../lavender/client/BlitCutoutProgram.java | 17 --- .../lavender/client/BookBakedModel.java | 20 +-- .../GuiRendererFramebufferOverride.java | 8 ++ .../lavender/client/LavenderBookScreen.java | 58 ++------ .../lavender/client/LavenderClient.java | 20 +-- .../lavender/client/LavenderFramebuffer.java | 57 ++++++++ .../lavender/client/OffhandBookRenderer.java | 132 ++++++++---------- .../client/StructureOverlayRenderer.java | 74 +++++----- .../client/UnreadNotificationComponent.java | 6 +- .../lavender/md/compiler/BookCompiler.java | 16 ++- .../lavender/md/features/RecipeFeature.java | 4 +- .../md/features/SpecialLinkFeature.java | 86 ++++++++++++ .../lavender/mixin/DrawContextMixin.java | 6 +- .../lavender/mixin/FramebufferMixin.java | 46 ------ .../lavender/mixin/GameRendererMixin.java | 53 +++++++ .../lavender/mixin/GuiRendererMixin.java | 33 +++++ .../lavender/mixin/MinecraftClientMixin.java | 46 ------ .../lavender/mixin/RenderPhaseMixin.java | 6 +- .../mixin/SimpleResourceReloadMixin.java | 5 +- .../lavender/mixin/TextureUtilMixin.java | 19 --- .../pond/LavenderFramebufferExtension.java | 11 -- .../lavender/shaders/core/blit_alpha.fsh | 3 +- .../lavender/shaders/core/blit_alpha.json | 10 -- .../lavender/shaders/core/blit_cutout.json | 8 -- src/main/resources/lavender.mixins.json | 5 +- 37 files changed, 565 insertions(+), 471 deletions(-) create mode 100644 src/main/java/io/wispforest/lavender/book/StructureComponentRenderState.java delete mode 100644 src/main/java/io/wispforest/lavender/client/BlitAlphaProgram.java delete mode 100644 src/main/java/io/wispforest/lavender/client/BlitCutoutProgram.java create mode 100644 src/main/java/io/wispforest/lavender/client/GuiRendererFramebufferOverride.java create mode 100644 src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java create mode 100644 src/main/java/io/wispforest/lavender/md/features/SpecialLinkFeature.java delete mode 100644 src/main/java/io/wispforest/lavender/mixin/FramebufferMixin.java create mode 100644 src/main/java/io/wispforest/lavender/mixin/GameRendererMixin.java create mode 100644 src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java delete mode 100644 src/main/java/io/wispforest/lavender/mixin/MinecraftClientMixin.java delete mode 100644 src/main/java/io/wispforest/lavender/mixin/TextureUtilMixin.java delete mode 100644 src/main/java/io/wispforest/lavender/pond/LavenderFramebufferExtension.java delete mode 100644 src/main/resources/assets/lavender/shaders/core/blit_alpha.json delete mode 100644 src/main/resources/assets/lavender/shaders/core/blit_cutout.json diff --git a/build.gradle b/build.gradle index dc97b19..4da8a6c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.8-SNAPSHOT' + id 'fabric-loom' version '1.11-SNAPSHOT' id 'maven-publish' } @@ -41,6 +41,9 @@ repositories { // modmenu maven { url "https://maven.terraformersmc.com/releases/" } + + // TEMP: lavender-md for 1.21.5 explodes 1.21.8 dev env by trying to load 1.21.5 FAPI modules for some reason???? + mavenLocal() } dependencies { diff --git a/gradle.properties b/gradle.properties index deeabcd..0574fcb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,10 +3,10 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_base_version=1.21.4 - minecraft_version=1.21.4 - yarn_mappings=1.21.4+build.2 - loader_version=0.16.9 + minecraft_base_version=1.21.8 + minecraft_version=1.21.8 + yarn_mappings=1.21.8+build.1 + loader_version=0.17.2 # Mod Properties mod_version = 0.1.15 @@ -15,16 +15,16 @@ org.gradle.jvmargs=-Xmx1G # Dependencies # check this on https://fabricmc.net/develop - fabric_version=0.112.0+1.21.4 + fabric_version=0.133.4+1.21.8 # https://maven.shedaniel.me/me/shedaniel/RoughlyEnoughItems-fabric/ - rei_version=18.0.796 + rei_version=20.0.811 # https://maven.wispforest.io/#/releases/io/wispforest/owo-lib/ - owo_version=0.12.20+1.21.4 + owo_version=0.12.22+1.21.8 # https://maven.terraformersmc.com/releases/com/terraformersmc/modmenu - modmenu_version=13.0.0-beta.1 + modmenu_version=15.0.0 # https://maven.wispforest.io/#/releases/io/wispforest/lavender-md/core/ - lavender_md_version=0.1.2+1.21.2 + lavender_md_version=0.1.2+1.21.8 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1adfb4..5c82cb0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/io/wispforest/lavender/Lavender.java b/src/main/java/io/wispforest/lavender/Lavender.java index 777019f..723dd57 100644 --- a/src/main/java/io/wispforest/lavender/Lavender.java +++ b/src/main/java/io/wispforest/lavender/Lavender.java @@ -1,6 +1,8 @@ package io.wispforest.lavender; import com.mojang.logging.LogUtils; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import io.wispforest.endec.Endec; import io.wispforest.endec.impl.BuiltInEndecs; import io.wispforest.endec.impl.StructEndecBuilder; @@ -11,15 +13,14 @@ import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.datafixer.DataFixTypes; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; import net.minecraft.network.packet.CustomPayload; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; -import net.minecraft.registry.RegistryWrapper; import net.minecraft.sound.SoundEvent; import net.minecraft.util.Identifier; +import net.minecraft.util.Uuids; import net.minecraft.world.PersistentState; +import net.minecraft.world.PersistentStateType; import org.slf4j.Logger; import java.util.UUID; @@ -40,7 +41,7 @@ public void onInitialize() { PayloadTypeRegistry.playS2C().register(WorldUUIDPayload.ID, CodecUtils.toPacketCodec(WorldUUIDPayload.ENDEC)); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - sender.sendPacket(new WorldUUIDPayload(server.getOverworld().getPersistentStateManager().getOrCreate(WorldUUIDState.TYPE, "lavender_world_id").id)); + sender.sendPacket(new WorldUUIDPayload(server.getOverworld().getPersistentStateManager().getOrCreate(WorldUUIDState.TYPE).id)); }); LavenderClientRecipeCache.initialize(); @@ -52,27 +53,21 @@ public static Identifier id(String path) { public static class WorldUUIDState extends PersistentState { - public static final PersistentState.Type TYPE = new Type<>(() -> { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.ap(WorldUUIDState::new, Uuids.INT_STREAM_CODEC.fieldOf("UUID").forGetter(w -> w.id)) + ); + + public static final PersistentStateType TYPE = new PersistentStateType<>("lavender_world_id", () -> { var state = new WorldUUIDState(UUID.randomUUID()); state.markDirty(); return state; - }, WorldUUIDState::read, DataFixTypes.LEVEL); + }, CODEC, DataFixTypes.LEVEL); public final UUID id; private WorldUUIDState(UUID id) { this.id = id; } - - @Override - public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { - nbt.putUuid("UUID", id); - return nbt; - } - - public static WorldUUIDState read(NbtCompound nbt, RegistryWrapper.WrapperLookup lookup) { - return new WorldUUIDState(nbt.contains("UUID", NbtElement.INT_ARRAY_TYPE) ? nbt.getUuid("UUID") : null); - } } public record WorldUUIDPayload(UUID worldUuid) implements CustomPayload { diff --git a/src/main/java/io/wispforest/lavender/LavenderCommands.java b/src/main/java/io/wispforest/lavender/LavenderCommands.java index d7093e1..5179cd6 100644 --- a/src/main/java/io/wispforest/lavender/LavenderCommands.java +++ b/src/main/java/io/wispforest/lavender/LavenderCommands.java @@ -15,6 +15,7 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.network.ClientCommandSource; import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; import net.minecraft.command.argument.IdentifierArgumentType; @@ -89,7 +90,7 @@ private static int executeGetLavenderBook(CommandContext dispatcher, CommandRegistryAccess access) { - dispatcher.register(literal("get-lavender-book").requires(source -> source.hasPermissionLevel(2)) + dispatcher.register(literal("get-lavender-book").requires(source -> ((ClientCommandSource)source).hasPermissionLevel(2)) .then(argument("book_id", IdentifierArgumentType.identifier()).suggests(LOADED_BOOKS) .executes(context -> executeGetLavenderBook(context, false)) .then(argument("force_dynamic_book", BoolArgumentType.bool()) diff --git a/src/main/java/io/wispforest/lavender/book/BookLoader.java b/src/main/java/io/wispforest/lavender/book/BookLoader.java index 4bc0bf9..b90835c 100644 --- a/src/main/java/io/wispforest/lavender/book/BookLoader.java +++ b/src/main/java/io/wispforest/lavender/book/BookLoader.java @@ -4,8 +4,6 @@ import com.google.gson.reflect.TypeToken; import com.mojang.serialization.JsonOps; import io.wispforest.lavender.Lavender; -import io.wispforest.lavender.client.BookBakedModel; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; import net.minecraft.registry.Registries; import net.minecraft.resource.ResourceFinder; import net.minecraft.resource.ResourceManager; @@ -23,7 +21,7 @@ public class BookLoader { - private static final Gson GSON = new GsonBuilder().setLenient().disableHtmlEscaping().create(); + private static final Gson GSON = new GsonBuilder().setStrictness(Strictness.LENIENT).disableHtmlEscaping().create(); private static final TypeToken> MACROS_TOKEN = new TypeToken<>() {}; private static final ResourceFinder BOOK_FINDER = ResourceFinder.json("lavender/books"); @@ -31,12 +29,15 @@ public class BookLoader { private static final Map VISIBLE_BOOKS = new HashMap<>(); public static void initialize() { + // Seemingly unnecessary + /* ModelLoadingPlugin.register(context -> { for (var book : VISIBLE_BOOKS.values()) { if (book.dynamicBookModel() == null) return; context.addModels(book.dynamicBookModel()); } }); + */ } public static @Nullable Book get(Identifier bookId) { diff --git a/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java b/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java index 5529823..6bd2bf5 100644 --- a/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java +++ b/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java @@ -8,6 +8,7 @@ import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.component.ComponentType; +import net.minecraft.component.type.TooltipDisplayComponent; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -26,8 +27,8 @@ import org.jetbrains.annotations.Nullable; import java.util.HashMap; -import java.util.List; import java.util.Map; +import java.util.function.Consumer; public class LavenderBookItem extends Item { @@ -162,16 +163,17 @@ private static void openBookScreen(Book book) { MinecraftClient.getInstance().setScreen(new LavenderBookScreen(book)); } + @SuppressWarnings("deprecation") @Override - public void appendTooltip(ItemStack stack, TooltipContext context, List tooltip, TooltipType type) { + public void appendTooltip(ItemStack stack, Item.TooltipContext context, TooltipDisplayComponent displayComponent, Consumer textConsumer, TooltipType type) { var bookId = bookIdOf(stack); if (bookId == null) { - tooltip.add(TextOps.withFormatting("⚠ §No associated book", Formatting.RED, Formatting.DARK_GRAY)); + textConsumer.accept(TextOps.withFormatting("⚠ §No associated book", Formatting.RED, Formatting.DARK_GRAY)); } else { var book = BookLoader.get(bookId); if (book != null) return; - tooltip.add(TextOps.withFormatting("⚠ §Unknown book \"" + bookId + "\"", Formatting.RED, Formatting.DARK_GRAY)); + textConsumer.accept(TextOps.withFormatting("⚠ §Unknown book \"" + bookId + "\"", Formatting.RED, Formatting.DARK_GRAY)); } } } diff --git a/src/main/java/io/wispforest/lavender/book/LavenderClientStorage.java b/src/main/java/io/wispforest/lavender/book/LavenderClientStorage.java index c118840..abaa801 100644 --- a/src/main/java/io/wispforest/lavender/book/LavenderClientStorage.java +++ b/src/main/java/io/wispforest/lavender/book/LavenderClientStorage.java @@ -1,16 +1,16 @@ package io.wispforest.lavender.book; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonObject; +import com.google.gson.*; import com.google.gson.reflect.TypeToken; import io.wispforest.lavender.Lavender; import io.wispforest.lavender.client.LavenderClient; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.util.Identifier; +import net.minecraft.util.JsonHelper; import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.lang.reflect.Type; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -26,7 +26,17 @@ public class LavenderClientStorage { private static final TypeToken>>> VIEWED_ENTRIES_TYPE = new TypeToken<>() {}; private static Map>> viewedEntries; - private static final Gson GSON = new GsonBuilder().registerTypeAdapter(Identifier.class, new Identifier.Serializer()).setPrettyPrinting().create(); + private static final Gson GSON = new GsonBuilder().registerTypeAdapter(Identifier.class, new IdentifierSerializer()).setPrettyPrinting().create(); + + private static class IdentifierSerializer implements JsonDeserializer, JsonSerializer { + public Identifier deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + return Identifier.of(JsonHelper.asString(jsonElement, "location")); + } + + public JsonElement serialize(Identifier identifier, Type type, JsonSerializationContext jsonSerializationContext) { + return new JsonPrimitive(identifier.toString()); + } + } static { try { diff --git a/src/main/java/io/wispforest/lavender/book/StructureComponent.java b/src/main/java/io/wispforest/lavender/book/StructureComponent.java index 576080d..b74557d 100644 --- a/src/main/java/io/wispforest/lavender/book/StructureComponent.java +++ b/src/main/java/io/wispforest/lavender/book/StructureComponent.java @@ -10,15 +10,12 @@ import io.wispforest.owo.ui.parsing.UIModelParsingException; import io.wispforest.owo.ui.parsing.UIParsing; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.ScreenRect; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.render.DiffuseLighting; -import net.minecraft.client.render.LightmapTextureManager; -import net.minecraft.client.render.OverlayTexture; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; -import net.minecraft.util.math.RotationAxis; import org.lwjgl.glfw.GLFW; import org.w3c.dom.Element; @@ -54,42 +51,15 @@ public void update(float delta, int mouseX, int mouseY) { @Override public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) { var client = MinecraftClient.getInstance(); - var entityBuffers = client.getBufferBuilders().getEntityVertexConsumers(); - float scale = Math.min(this.width, this.height); - scale /= Math.max(structure.xSize, Math.max(structure.ySize, structure.zSize)); - scale /= 1.625f; - - var matrices = context.getMatrices(); - - matrices.push(); - matrices.translate(this.x + this.width / 2f, this.y + this.height / 2f, 100); - matrices.scale(scale, -scale, scale); - - matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(this.displayAngle)); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(this.rotation)); - matrices.translate(this.structure.xSize / -2f, this.structure.ySize / -2f, this.structure.zSize / -2f); - - structure.forEachPredicate((blockPos, predicate) -> { - if (this.visibleLayer != -1 && this.visibleLayer != blockPos.getY()) return; - - matrices.push(); - matrices.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - - client.getBlockRenderManager().renderBlockAsEntity( - predicate.preview(), matrices, entityBuffers, - LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE, - OverlayTexture.DEFAULT_UV - ); - - matrices.pop(); - }); - - matrices.pop(); - - DiffuseLighting.disableGuiDepthLighting(); - entityBuffers.draw(); - DiffuseLighting.enableGuiDepthLighting(); + context.state.addSpecialElement(new StructureComponentRenderState( + structure, + displayAngle, + rotation, + visibleLayer, + new ScreenRect(this.x, this.y, this.width, this.height), + context.scissorStack.peekLast() + )); if (this.placeable) { if (StructureOverlayRenderer.isShowingOverlay(this.structure.id)) { diff --git a/src/main/java/io/wispforest/lavender/book/StructureComponentRenderState.java b/src/main/java/io/wispforest/lavender/book/StructureComponentRenderState.java new file mode 100644 index 0000000..3edc4cd --- /dev/null +++ b/src/main/java/io/wispforest/lavender/book/StructureComponentRenderState.java @@ -0,0 +1,113 @@ +package io.wispforest.lavender.book; + +import io.wispforest.lavender.structure.StructureTemplate; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.ScreenRect; +import net.minecraft.client.gui.render.SpecialGuiElementRenderer; +import net.minecraft.client.gui.render.state.special.SpecialGuiElementRenderState; +import net.minecraft.client.render.DiffuseLighting; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.RotationAxis; +import org.jetbrains.annotations.Nullable; + +public record StructureComponentRenderState( + StructureTemplate structure, + int displayAngle, + float rotation, + int visibleLayer, + ScreenRect bounds, + ScreenRect scissorArea +) implements SpecialGuiElementRenderState { + @Override + public int x1() { + return this.bounds.getLeft(); + } + + @Override + public int x2() { + return this.bounds.getRight(); + } + + @Override + public int y1() { + return this.bounds.getTop(); + } + + @Override + public int y2() { + return this.bounds.getBottom(); + } + + @Override + public float scale() { + return 1; + } + + @Override + public @Nullable ScreenRect scissorArea() { + return this.scissorArea; + } + + @Override + public @Nullable ScreenRect bounds() { + return this.scissorArea != null ? this.scissorArea.intersection(this.bounds) : this.bounds; + } + + public static class Renderer extends SpecialGuiElementRenderer { + + public Renderer(VertexConsumerProvider.Immediate vertexConsumers) { + super(vertexConsumers); + } + + @Override + public Class getElementClass() { + return StructureComponentRenderState.class; + } + + @Override + protected void render(StructureComponentRenderState state, MatrixStack matrices) { + MinecraftClient.getInstance().gameRenderer.getDiffuseLighting().setShaderLights(DiffuseLighting.Type.ITEMS_3D); + + var width = state.bounds.width(); + var height = state.bounds.height(); + + var structure = state.structure; + float scale = Math.min(width, height); + scale /= Math.max(structure.xSize, Math.max(structure.ySize, structure.zSize)); + scale /= 1.625f; + + matrices.translate(0, -height / 2f, 100); + matrices.scale(scale, -scale, scale); + + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(state.displayAngle)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(state.rotation)); + + matrices.translate(structure.xSize / -2f, structure.ySize / -2f, structure.zSize / -2f); + + var client = MinecraftClient.getInstance(); + + structure.forEachPredicate((blockPos, predicate) -> { + if (state.visibleLayer != -1 && state.visibleLayer != blockPos.getY()) return; + + matrices.push(); + matrices.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + + client.getBlockRenderManager().renderBlockAsEntity( + predicate.preview(), matrices, vertexConsumers, + LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE, + OverlayTexture.DEFAULT_UV + ); + + matrices.pop(); + }); + } + + @Override + protected String getName() { + return "lavender_structure"; + } + } +} diff --git a/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java b/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java index dcc3cc7..ccc4f0e 100644 --- a/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java +++ b/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java @@ -47,13 +47,12 @@ public AssociatedEntryTooltipComponent(ItemStack book, Entry entry, float progre @Override public void drawItems(TextRenderer textRenderer, int x, int y, int width, int height, DrawContext context) { context = OwoUIDrawContext.of(context); - context.getMatrices().push(); - context.getMatrices().translate(0, 0, 1000); + context.getMatrices().pushMatrix(); this.layout.moveTo(x, y); this.layout.draw((OwoUIDrawContext) context, 0, 0, 0, 0); - context.getMatrices().pop(); + context.getMatrices().popMatrix(); } @Override diff --git a/src/main/java/io/wispforest/lavender/client/BlitAlphaProgram.java b/src/main/java/io/wispforest/lavender/client/BlitAlphaProgram.java deleted file mode 100644 index a41e582..0000000 --- a/src/main/java/io/wispforest/lavender/client/BlitAlphaProgram.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.wispforest.lavender.client; - -import io.wispforest.lavender.Lavender; -import io.wispforest.owo.shader.GlProgram; -import net.minecraft.client.gl.ShaderProgram; -import net.minecraft.client.gl.ShaderProgramKey; -import net.minecraft.client.gl.Uniform; -import net.minecraft.client.render.VertexFormats; - -public class BlitAlphaProgram extends GlProgram { - - private Uniform alpha; - - public BlitAlphaProgram() { - super(Lavender.id("blit_alpha"), VertexFormats.BLIT_SCREEN); - } - - @Override - protected void setup() { - super.setup(); - this.alpha = this.findUniform("Alpha"); - } - - public void setAlpha(float alpha) { - this.alpha.set(alpha); - } - - public ShaderProgramKey key() { - return this.programKey; - } -} diff --git a/src/main/java/io/wispforest/lavender/client/BlitCutoutProgram.java b/src/main/java/io/wispforest/lavender/client/BlitCutoutProgram.java deleted file mode 100644 index 978b065..0000000 --- a/src/main/java/io/wispforest/lavender/client/BlitCutoutProgram.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.wispforest.lavender.client; - -import io.wispforest.lavender.Lavender; -import io.wispforest.owo.shader.GlProgram; -import net.minecraft.client.gl.ShaderProgramKey; -import net.minecraft.client.render.VertexFormats; - -public class BlitCutoutProgram extends GlProgram { - - public BlitCutoutProgram() { - super(Lavender.id("blit_cutout"), VertexFormats.BLIT_SCREEN); - } - - public ShaderProgramKey key() { - return this.programKey; - } -} diff --git a/src/main/java/io/wispforest/lavender/client/BookBakedModel.java b/src/main/java/io/wispforest/lavender/client/BookBakedModel.java index c0b3ee5..998ff3c 100644 --- a/src/main/java/io/wispforest/lavender/client/BookBakedModel.java +++ b/src/main/java/io/wispforest/lavender/client/BookBakedModel.java @@ -7,8 +7,8 @@ import net.minecraft.client.render.item.model.ItemModel; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemDisplayContext; import net.minecraft.item.ItemStack; -import net.minecraft.item.ModelTransformationMode; import org.jetbrains.annotations.Nullable; public class BookBakedModel implements ItemModel { @@ -19,15 +19,15 @@ public BookBakedModel(ItemModel defaultModel) { this.defaultModel = defaultModel; } - @Override - public void update(ItemRenderState state, ItemStack stack, ItemModelManager resolver, ModelTransformationMode transformationMode, @Nullable ClientWorld world, @Nullable LivingEntity user, int seed) { - var book = LavenderBookItem.bookOf(stack); - if (book != null && book.dynamicBookModel() != null) { - MinecraftClient.getInstance().getBakedModelManager().getItemModel(book.dynamicBookModel()).update(state, stack, resolver, transformationMode, world, user, seed); - } else { - this.defaultModel.update(state, stack, resolver, transformationMode, world, user, seed); - } - } + @Override + public void update(ItemRenderState state, ItemStack stack, ItemModelManager resolver, ItemDisplayContext displayContext, @Nullable ClientWorld world, @Nullable LivingEntity user, int seed) { + var book = LavenderBookItem.bookOf(stack); + if (book != null && book.dynamicBookModel() != null) { + MinecraftClient.getInstance().getBakedModelManager().getItemModel(book.dynamicBookModel()).update(state, stack, resolver, displayContext, world, user, seed); + } else { + this.defaultModel.update(state, stack, resolver, displayContext, world, user, seed); + } + } // private final ModelOverrideList overrides = new ModelOverrideList() { // @Override diff --git a/src/main/java/io/wispforest/lavender/client/GuiRendererFramebufferOverride.java b/src/main/java/io/wispforest/lavender/client/GuiRendererFramebufferOverride.java new file mode 100644 index 0000000..2e22a53 --- /dev/null +++ b/src/main/java/io/wispforest/lavender/client/GuiRendererFramebufferOverride.java @@ -0,0 +1,8 @@ +package io.wispforest.lavender.client; + +import net.minecraft.client.gl.Framebuffer; + +public interface GuiRendererFramebufferOverride { + void lavender$setOverride(Framebuffer override); + Framebuffer lavender$getOverride(); +} diff --git a/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java b/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java index 80b7b45..4b5b180 100644 --- a/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java +++ b/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java @@ -1,8 +1,6 @@ package io.wispforest.lavender.client; import com.google.common.collect.Iterables; -import com.mojang.blaze3d.systems.ProjectionType; -import com.mojang.blaze3d.systems.RenderSystem; import io.wispforest.lavender.Lavender; import io.wispforest.lavender.book.*; import io.wispforest.lavender.md.ItemListComponent; @@ -44,7 +42,6 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.joml.Matrix4f; import org.lwjgl.glfw.GLFW; import java.util.*; @@ -89,7 +86,7 @@ public LavenderBookScreen(Book book, boolean isOverlay) { .copyWith(() -> new BookCompiler(this.bookComponentSource)) .copyWith( new ImageFeature(), new BlockStateFeature(), new ItemStackFeature(MinecraftClient.getInstance().world.getRegistryManager()), new EntityFeature(), - new PageBreakFeature(), new OwoUITemplateFeature(this.bookComponentSource), + new SpecialLinkFeature(), new PageBreakFeature(), new OwoUITemplateFeature(this.bookComponentSource), new RecipeFeature(this.bookComponentSource, RECIPE_HANDLERS.get(this.book.id())), new StructureFeature(this.bookComponentSource), new KeybindFeature(), new ItemTagFeature(), new OwoUIModelFeature(), new TranslationsFeature() @@ -108,8 +105,12 @@ public LavenderBookScreen(Book book) { @Override protected void init() { - this.window = this.client.getWindow(); - double gameScale = this.window.getScaleFactor(); + this.window = this.client.getWindow(); + this.scaleFactor = this.window.getScaleFactor(); + + // Why is this even a thing? It messes up the book screen scaling. + /* + int gameScale = this.window.getScaleFactor(); this.scaleFactor = this.window.calculateScaleFactor(!this.isOverlay ? this.client.options.getGuiScale().getValue() : 0, true); this.window.setScaleFactor(this.scaleFactor); @@ -120,6 +121,9 @@ protected void init() { super.init(); this.window.setScaleFactor(gameScale); + */ + + super.init(); } protected C template(Class expectedComponentClass, String name) { @@ -346,52 +350,18 @@ public void navPop() { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - mouseX = (int) (mouseX * this.window.getScaleFactor() / this.scaleFactor); - mouseY = (int) (mouseY * this.window.getScaleFactor() / this.scaleFactor); - - double gameScale = this.window.getScaleFactor(); - this.window.setScaleFactor(this.scaleFactor); - - RenderSystem.backupProjectionMatrix(); - RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho( - 0, - this.window.getFramebufferWidth() / (float) this.scaleFactor, - this.window.getFramebufferHeight() / (float) this.scaleFactor, - 0, - 1000, - 21000 - ), ProjectionType.ORTHOGRAPHIC); + mouseX = mouseX * this.window.getScaleFactor() / this.scaleFactor; + mouseY = mouseY * this.window.getScaleFactor() / this.scaleFactor; super.render(context, mouseX, mouseY, delta); - context.draw(); - - RenderSystem.restoreProjectionMatrix(); - this.window.setScaleFactor(gameScale); } @Override protected void drawComponentTooltip(DrawContext drawContext, int mouseX, int mouseY, float tickDelta) { - mouseX = (int) (mouseX * this.window.getScaleFactor() / this.scaleFactor); - mouseY = (int) (mouseY * this.window.getScaleFactor() / this.scaleFactor); - - double gameScale = this.window.getScaleFactor(); - this.window.setScaleFactor(this.scaleFactor); - - RenderSystem.backupProjectionMatrix(); - RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho( - 0, - this.window.getFramebufferWidth() / (float) this.scaleFactor, - this.window.getFramebufferHeight() / (float) this.scaleFactor, - 0, - 1000, - 21000 - ), ProjectionType.ORTHOGRAPHIC); + mouseX = mouseX * this.window.getScaleFactor() / this.scaleFactor; + mouseY = mouseY * this.window.getScaleFactor() / this.scaleFactor; super.drawComponentTooltip(drawContext, mouseX, mouseY, tickDelta); - drawContext.draw(); - - RenderSystem.restoreProjectionMatrix(); - this.window.setScaleFactor(gameScale); } @Override public boolean charTyped(char chr, int modifiers) { diff --git a/src/main/java/io/wispforest/lavender/client/LavenderClient.java b/src/main/java/io/wispforest/lavender/client/LavenderClient.java index 754a5c8..71abc10 100644 --- a/src/main/java/io/wispforest/lavender/client/LavenderClient.java +++ b/src/main/java/io/wispforest/lavender/client/LavenderClient.java @@ -15,16 +15,14 @@ import io.wispforest.owo.ui.core.Sizing; import io.wispforest.owo.ui.hud.Hud; import io.wispforest.owo.ui.parsing.UIParsing; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.client.rendering.v1.SpecialGuiElementRegistry; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; @@ -37,16 +35,11 @@ import net.minecraft.util.hit.BlockHitResult; import org.jetbrains.annotations.Nullable; -import java.util.Objects; import java.util.UUID; @Environment(EnvType.CLIENT) public class LavenderClient implements ClientModInitializer { - public static final BlitCutoutProgram BLIT_CUTOUT_PROGRAM = new BlitCutoutProgram(); - public static final BlitAlphaProgram BLIT_ALPHA_PROGRAM = new BlitAlphaProgram(); - - private static final Int2ObjectMap TEXTURE_SIZES = new Int2ObjectOpenHashMap<>(); private static final Identifier ENTRY_HUD_ID = Lavender.id("entry_hud"); private static UUID currentWorldId = null; @@ -71,6 +64,8 @@ public void onInitializeClient() { // // }); // }); + SpecialGuiElementRegistry.register(ctx -> new StructureComponentRenderState.Renderer(ctx.vertexConsumers())); + StructureOverlayRenderer.initialize(); OffhandBookRenderer.initialize(); @@ -156,11 +151,10 @@ public static UUID currentWorldId() { return currentWorldId; } - public static void registerTextureSize(int textureId, int width, int height) { - TEXTURE_SIZES.put(textureId, Size.of(width, height)); - } + public static @Nullable Size getTextureSize(Identifier id) { + var texture = MinecraftClient.getInstance().getTextureManager().getTexture(id).getGlTexture(); - public static @Nullable Size getTextureSize(Identifier texture) { - return TEXTURE_SIZES.get(MinecraftClient.getInstance().getTextureManager().getTexture(texture).getGlId()); + if (texture != null) return Size.of(texture.getWidth(0), texture.getHeight(0)); + return null; } } diff --git a/src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java b/src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java new file mode 100644 index 0000000..02ae210 --- /dev/null +++ b/src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java @@ -0,0 +1,57 @@ +package io.wispforest.lavender.client; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.systems.RenderPass; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gl.SimpleFramebuffer; +import org.jetbrains.annotations.Nullable; + +import java.util.OptionalInt; + +public class LavenderFramebuffer extends SimpleFramebuffer { + protected final RenderPipeline pipeline; + + public LavenderFramebuffer(@Nullable String name, int width, int height, boolean useDepthAttachment, RenderPipeline pipeline) { + super(name, width, height, useDepthAttachment); + this.pipeline = pipeline; + } + + public LavenderFramebuffer(@Nullable String name, int width, int height, boolean useDepthAttachment) { + this(name, width, height, useDepthAttachment, RenderPipelines.ENTITY_OUTLINE_BLIT); + } + + public void clear() { + if (this.useDepthAttachment) { + RenderSystem.getDevice() + .createCommandEncoder() + .clearColorAndDepthTextures(colorAttachment, 0, depthAttachment, 1.0); + } else { + RenderSystem.getDevice().createCommandEncoder().clearColorTexture(colorAttachment, 0); + } + + RenderSystem.getDevice() + .createCommandEncoder() + .clearColorAndDepthTextures(colorAttachment, 0, depthAttachment, 1.0); + } + + @Override + public void drawBlit(GpuTextureView texture) { + RenderSystem.assertOnRenderThread(); + RenderSystem.ShapeIndexBuffer shapeIndexBuffer = RenderSystem.getSequentialBuffer(VertexFormat.DrawMode.QUADS); + GpuBuffer indexBuffer = shapeIndexBuffer.getIndexBuffer(6); + GpuBuffer vertexBuffer = RenderSystem.getQuadVertexBuffer(); + + try (RenderPass renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(() -> "Blit render target", texture, OptionalInt.empty())) { + renderPass.setPipeline(pipeline); + RenderSystem.bindDefaultUniforms(renderPass); + renderPass.setVertexBuffer(0, vertexBuffer); + renderPass.setIndexBuffer(indexBuffer, shapeIndexBuffer.getIndexType()); + renderPass.bindSampler("InSampler", this.colorAttachmentView); + renderPass.drawIndexed(0, 0, 6, 1); + } + } +} diff --git a/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java b/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java index 89c5ff8..547dcbf 100644 --- a/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java +++ b/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java @@ -1,20 +1,18 @@ package io.wispforest.lavender.client; import com.google.common.base.Suppliers; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; import io.wispforest.lavender.Lavender; import io.wispforest.lavender.book.Book; -import io.wispforest.lavender.pond.LavenderFramebufferExtension; import io.wispforest.owo.ui.event.WindowResizeCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; -import net.minecraft.client.gl.SimpleFramebuffer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.render.*; +import net.minecraft.client.gui.render.state.GuiRenderState; import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.fog.FogRenderer; import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.resource.ResourceManager; import net.minecraft.util.Arm; import net.minecraft.util.math.RotationAxis; import org.jetbrains.annotations.Nullable; @@ -23,99 +21,82 @@ public class OffhandBookRenderer { - public static boolean rendering = false; - - private static final Supplier BACK_BUFFER = Suppliers.memoize(() -> { - var window = MinecraftClient.getInstance().getWindow(); - - var framebuffer = new SimpleFramebuffer(window.getFramebufferWidth(), window.getFramebufferHeight(), true); - ((LavenderFramebufferExtension) framebuffer).lavender$setBlitProgram(() -> { - GlStateManager._colorMask(true, true, true, true); - return LavenderClient.BLIT_CUTOUT_PROGRAM.key(); - }); - framebuffer.setClearColor(0f, 0f, 0f, 0f); - return framebuffer; - }); - - private static final Supplier DISPLAY_BUFFER = Suppliers.memoize(() -> { - var window = MinecraftClient.getInstance().getWindow(); - - var framebuffer = new SimpleFramebuffer(window.getFramebufferWidth(), window.getFramebufferHeight(), true); - framebuffer.setClearColor(0f, 0f, 0f, 0f); - return framebuffer; - }); + // Seems to render just fine without this pipeline. Also, Iris Shaders doesn't like it. + // So, I just got rid of the double buffering. I'll keep it here just in case though. + /* + private static final RenderPipeline BACK_PIPELINE = RenderPipelines.register( + RenderPipeline.builder() + .withLocation(Lavender.id("pipeline/back_buffer")) + .withVertexShader("core/blit_screen") + .withFragmentShader(Lavender.id("core/blit_cutout")) + .withSampler("InSampler") + .withBlend(BlendFunction.ENTITY_OUTLINE_BLIT) + .withDepthWrite(false) + .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) + .withColorWrite(true, true) + .withVertexFormat(VertexFormats.POSITION, VertexFormat.DrawMode.QUADS) + .build() + ); + */ + + private static final Supplier SCREEN_BUFFER = Suppliers.memoize(() -> { + var window = MinecraftClient.getInstance().getWindow(); + + return new LavenderFramebuffer("Lavender Book Screen Buffer", window.getFramebufferWidth(), window.getFramebufferHeight(), true); + }); private static LavenderBookScreen cachedScreen = null; private static boolean cacheExpired = true; public static void initialize() { WindowResizeCallback.EVENT.register((client, window) -> { - DISPLAY_BUFFER.get().resize(window.getFramebufferWidth(), window.getFramebufferHeight()); - BACK_BUFFER.get().resize(window.getFramebufferWidth(), window.getFramebufferHeight()); + SCREEN_BUFFER.get().resize(window.getFramebufferWidth(), window.getFramebufferHeight()); cachedScreen = null; }); } - public static void beginFrame(@Nullable Book book) { - cacheExpired = true; + public static void beginFrame(@Nullable Book book, MinecraftClient client, GuiRenderState guiState, GuiRenderer guiRenderer, FogRenderer fogRenderer) { + cacheExpired = false; if (book == null) return; - var client = MinecraftClient.getInstance(); - - rendering = true; - var backBuffer = BACK_BUFFER.get(); - - try { - // --- render book screen to separate framebuffer --- + var screenBuffer = SCREEN_BUFFER.get(); - var screen = cachedScreen; - if (screen == null || screen.book != book) { - cachedScreen = screen = new LavenderBookScreen(book, true); - screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight()); + // --- render book screen to separate framebuffer --- - // we dispose the ui adapter here to - // stop it from messing with and/or - // leaking GLFW cursor objects - screen.adapter().dispose(); - } + var screen = cachedScreen; + if (screen == null || screen.book != book) { + cachedScreen = screen = new LavenderBookScreen(book, true); + screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight()); - var modelView = RenderSystem.getModelViewStack(); - modelView.pushMatrix(); - modelView.identity(); - modelView.translate(0, 0, -2000); + // we dispose the ui adapter here to + // stop it from messing with and/or + // leaking GLFW cursor objects + screen.adapter().dispose(); + } - backBuffer.clear(); - backBuffer.beginWrite(false); - LavenderClient.mainTargetOverride = backBuffer; + var override = (GuiRendererFramebufferOverride) guiRenderer; - screen.render(new DrawContext(client, client.getBufferBuilders().getEntityVertexConsumers()), -69, -69, 0); - RenderSystem.disableDepthTest(); + LavenderClient.mainTargetOverride = screenBuffer; + override.lavender$setOverride(screenBuffer); + screenBuffer.clear(); - modelView.popMatrix(); + screen.render(new DrawContext(client, guiState), -69, -69, 0); + guiRenderer.render(fogRenderer.getFogBuffer(FogRenderer.FogType.NONE)); - var displayBuffer = DISPLAY_BUFFER.get(); - displayBuffer.clear(); - displayBuffer.beginWrite(false); - LavenderClient.mainTargetOverride = displayBuffer; - - backBuffer.drawInternal(backBuffer.textureWidth, backBuffer.textureHeight); - - client.getFramebuffer().beginWrite(false); - LavenderClient.mainTargetOverride = null; - } finally { - rendering = false; - } + guiState.clear(); + override.lavender$setOverride(null); + LavenderClient.mainTargetOverride = null; } public static void render(MatrixStack matrices, int light) { - cacheExpired = false; + cacheExpired = true; var client = MinecraftClient.getInstance(); // --- draw color attachment in place of map texture --- - var framebuffer = DISPLAY_BUFFER.get(); + var framebuffer = SCREEN_BUFFER.get(); - var texture = new FramebufferTexture(framebuffer.getColorAttachment()); + var texture = new FramebufferTexture(framebuffer); client.getTextureManager().registerTexture(Lavender.id("offhand_book_framebuffer"), texture); var rightHanded = client.player.getMainArm() == Arm.RIGHT; @@ -146,11 +127,12 @@ public static void endFrame() { private static class FramebufferTexture extends AbstractTexture { - private FramebufferTexture(int textureId) { - this.glId = textureId; - } + public FramebufferTexture(Framebuffer framebuffer) { + this.glTexture = framebuffer.getColorAttachment(); + this.glTextureView = framebuffer.getColorAttachmentView(); + } @Override - public void clearGlId() {} + public void close() {} } } diff --git a/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java b/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java index 51d2005..cfd1640 100644 --- a/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java +++ b/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java @@ -1,10 +1,11 @@ package io.wispforest.lavender.client; import com.google.common.base.Suppliers; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.pipeline.BlendFunction; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.platform.DepthTestFunction; +import com.mojang.blaze3d.vertex.VertexFormat; import io.wispforest.lavender.Lavender; -import io.wispforest.lavender.pond.LavenderFramebufferExtension; import io.wispforest.lavender.structure.BlockStatePredicate; import io.wispforest.lavender.structure.LavenderStructures; import io.wispforest.lavender.structure.StructureTemplate; @@ -18,12 +19,8 @@ import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gl.Framebuffer; -import net.minecraft.client.gl.SimpleFramebuffer; -import net.minecraft.client.render.LightmapTextureManager; -import net.minecraft.client.render.OverlayTexture; -import net.minecraft.client.render.OverlayVertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.render.*; import net.minecraft.client.render.model.ModelBaker; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; @@ -37,7 +34,6 @@ import net.minecraft.util.math.Vec3i; import org.apache.commons.lang3.mutable.MutableBoolean; import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.GL30C; import java.util.HashMap; import java.util.Map; @@ -45,17 +41,24 @@ public class StructureOverlayRenderer { - private static final Supplier FRAMEBUFFER = Suppliers.memoize(() -> { + private static final RenderPipeline PIPELINE = RenderPipelines.register( + RenderPipeline.builder() + .withLocation(Lavender.id("pipeline/structure_overlay")) + .withVertexShader("core/blit_screen") + .withFragmentShader(Lavender.id("core/blit_alpha")) + .withSampler("InSampler") + .withBlend(BlendFunction.TRANSLUCENT) + .withDepthWrite(false) + .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST) + .withColorWrite(true, true) + .withVertexFormat(VertexFormats.POSITION, VertexFormat.DrawMode.QUADS) + .build() + ); + + private static final Supplier FRAMEBUFFER = Suppliers.memoize(() -> { var window = MinecraftClient.getInstance().getWindow(); - var framebuffer = new SimpleFramebuffer(window.getFramebufferWidth(), window.getFramebufferHeight(), true); - ((LavenderFramebufferExtension) framebuffer).lavender$enableDepthTest(); - ((LavenderFramebufferExtension) framebuffer).lavender$setBlitProgram(() -> { - LavenderClient.BLIT_ALPHA_PROGRAM.setAlpha(.5f); - return LavenderClient.BLIT_ALPHA_PROGRAM.key(); - }); - framebuffer.setClearColor(0f, 0f, 0f, 0f); - return framebuffer; + return new LavenderFramebuffer("Lavender Structure Overlay Framebuffer", window.getFramebufferWidth(), window.getFramebufferHeight(), true, PIPELINE); }); private static final Map ACTIVE_OVERLAYS = new HashMap<>(); @@ -139,16 +142,21 @@ public static void initialize() { matrices.translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z); var client = MinecraftClient.getInstance(); + // prefer targeting the translucent framebuffer + // to make sure the translucent structure is properly handled as translucent down the line + var targetFramebuffer = client.worldRenderer.getTranslucentFramebuffer() != null + ? client.worldRenderer.getTranslucentFramebuffer() + : client.getFramebuffer(); + var effectConsumers = client.getBufferBuilders().getEffectVertexConsumers(); var testPos = new BlockPos.Mutable(); var framebuffer = FRAMEBUFFER.get(); - framebuffer.clear(); - framebuffer.beginWrite(false); + framebuffer.clear(); + LavenderClient.mainTargetOverride = framebuffer; - GL30C.glBindFramebuffer(GL30C.GL_READ_FRAMEBUFFER, client.getFramebuffer().fbo); - GL30C.glBlitFramebuffer(0, 0, framebuffer.textureWidth, framebuffer.textureHeight, 0, 0, client.getFramebuffer().textureWidth, client.getFramebuffer().textureHeight, GL30C.GL_DEPTH_BUFFER_BIT, GL30C.GL_NEAREST); + framebuffer.copyDepthFrom(targetFramebuffer); hudComponent.configure(layout -> { layout.clearChildren().padding(Insets.bottom((client.getWindow().getScaledWidth() - 182) / 2 < 200 ? 50 : 5)); @@ -208,7 +216,7 @@ public static void initialize() { var renderTickCounter = client.getRenderTickCounter(); - entry.visualCompleteness += Delta.compute(entry.visualCompleteness, valid / (float) total, renderTickCounter.getLastFrameDuration()); + entry.visualCompleteness += Delta.compute(entry.visualCompleteness, valid / (float) total, renderTickCounter.getDynamicDeltaTicks()); layout.child(Containers.verticalFlow(Sizing.content(), Sizing.content()) .child(Components.label(Text.translatable("text.lavender.structure_hud.completion", Text.translatable(Util.createTranslationKey("structure", entry.structureId)), valid, total)).shadow(true)) .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) @@ -217,13 +225,13 @@ public static void initialize() { .child(Components.texture(BARS_TEXTURE, 0, 30, 182, 5, 256, 48).blend(true).positioning(Positioning.absolute(0, 0)))) .gap(2) .horizontalAlignment(HorizontalAlignment.CENTER) - .margins(Insets.bottom((int) (Easing.CUBIC.apply((Math.max(0, entry.decayTime - 30) + renderTickCounter.getTickDelta(false)) / 20f) * -32)))); + .margins(Insets.bottom((int) (Easing.CUBIC.apply((Math.max(0, entry.decayTime - 30) + renderTickCounter.getTickProgress(false)) / 20f) * -32)))); if (entry.decayTime < 0 && complete) { entry.decayTime = 0; client.player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1f); } else if (entry.decayTime >= 0) { - entry.decayTime += renderTickCounter.getLastFrameDuration(); + entry.decayTime += renderTickCounter.getDynamicDeltaTicks(); } return entry.decayTime >= 50; @@ -233,7 +241,7 @@ public static void initialize() { if (PENDING_OVERLAY != null) { var structure = PENDING_OVERLAY.fetchStructure(); if (structure != null) { - if (client.player.raycast(5, client.getRenderTickCounter().getTickDelta(false), false) instanceof BlockHitResult target) { + if (client.player.raycast(5, client.getRenderTickCounter().getTickProgress(false), false) instanceof BlockHitResult target) { var targetPos = target.getBlockPos().add(getPendingOffset(structure)); if (!client.player.isSneaking()) targetPos = targetPos.offset(target.getSide()); @@ -247,19 +255,13 @@ public static void initialize() { matrices.pop(); - GlStateManager._depthMask(true); CONSUMERS.draw(); effectConsumers.draw(); - client.getFramebuffer().beginWrite(false); LavenderClient.mainTargetOverride = null; - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - - RenderSystem.backupProjectionMatrix(); - framebuffer.drawInternal(framebuffer.textureWidth, framebuffer.textureHeight); - RenderSystem.restoreProjectionMatrix(); + targetFramebuffer.copyDepthFrom(framebuffer); + framebuffer.drawBlit(targetFramebuffer.getColorAttachmentView()); }); WindowResizeCallback.EVENT.register((client, window) -> { @@ -300,7 +302,7 @@ private static void renderOverlayBlock(MatrixStack matrices, VertexConsumerProvi matrices.translate(offsetInStructure.getX(), offsetInStructure.getY(), offsetInStructure.getZ()); matrices.translate(.5, .5, .5); - matrices.scale(1.0001f, 1.0001f, 1.0001f); + matrices.scale(1.004f, 1.004f, 1.004f); matrices.translate(-.5, -.5, -.5); MinecraftClient.getInstance().getBlockRenderManager().renderBlockAsEntity( diff --git a/src/main/java/io/wispforest/lavender/client/UnreadNotificationComponent.java b/src/main/java/io/wispforest/lavender/client/UnreadNotificationComponent.java index dfabc0c..40433c7 100644 --- a/src/main/java/io/wispforest/lavender/client/UnreadNotificationComponent.java +++ b/src/main/java/io/wispforest/lavender/client/UnreadNotificationComponent.java @@ -4,7 +4,7 @@ import io.wispforest.owo.ui.core.OwoUIDrawContext; import io.wispforest.owo.ui.core.Sizing; import io.wispforest.owo.ui.parsing.UIParsing; -import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.gl.RenderPipelines; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.w3c.dom.Element; @@ -30,9 +30,9 @@ protected int determineVerticalContentSize(Sizing sizing) { @Override public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) { - context.push().translate(0, 0, 200); + context.push(); context.drawTexture( - RenderLayer::getGuiTextured, + RenderPipelines.GUI_TEXTURED, this.bookTexture, this.x, this.y, diff --git a/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java b/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java index 4ca677d..29c2531 100644 --- a/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java +++ b/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java @@ -14,12 +14,15 @@ import io.wispforest.owo.ui.parsing.UIModel; import io.wispforest.owo.ui.parsing.UIModelLoader; import net.minecraft.client.MinecraftClient; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtString; import net.minecraft.text.*; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; +import java.util.Optional; import java.util.function.Supplier; public class BookCompiler extends OwoUICompiler { @@ -86,6 +89,8 @@ public static class BookLabelComponent extends LabelComponent { private @Nullable LavenderBookScreen owner; + public static Identifier LINK = Lavender.id("link"); + protected BookLabelComponent(Text text) { super(text); this.margins(Insets.horizontal(1)); @@ -93,8 +98,9 @@ protected BookLabelComponent(Text text) { if (style == null || this.owner == null) return false; var clickEvent = style.getClickEvent(); - if (clickEvent != null && clickEvent.getAction() == ClickEvent.Action.OPEN_URL && clickEvent.getValue().startsWith("^")) { - var linkTarget = this.resolveLinkTarget(clickEvent.getValue()); + if (clickEvent instanceof ClickEvent.Custom(Identifier ce, Optional payload) + && ce.equals(LINK) && payload.orElse(null) instanceof NbtString(String value)) { + var linkTarget = this.resolveLinkTarget(value); if (linkTarget != null && linkTarget.supplier != null) { this.owner.navPush(linkTarget.supplier.get()); return true; @@ -160,11 +166,11 @@ protected Style styleAt(int mouseX, int mouseY) { if (style == null) return null; var event = style.getHoverEvent(); - if (this.owner != null && event != null && event.getAction() == HoverEvent.Action.SHOW_TEXT && event.getValue(HoverEvent.Action.SHOW_TEXT).getString().startsWith("^")) { - var rawLink = event.getValue(HoverEvent.Action.SHOW_TEXT).getString(); + if (this.owner != null && event != null && event instanceof HoverEvent.ShowText(Text value) && value.getString().startsWith("^")) { + var rawLink = value.getString(); var linkTarget = this.resolveLinkTarget(rawLink); - style = style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, linkTarget != null + style = style.withHoverEvent(new HoverEvent.ShowText(linkTarget != null ? linkTarget.supplier != null ? linkTarget.title : Text.translatable("text.lavender.locked_internal_link") : Text.translatable("text.lavender.invalid_internal_link", rawLink) )); diff --git a/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java b/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java index 80b7917..7c8234c 100644 --- a/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java +++ b/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java @@ -68,7 +68,7 @@ public class RecipeFeature implements MarkdownFeature { var recipeComponent = componentSource.builtinTemplate(ParentComponent.class, "smithing-recipe"); recipe.template().ifPresent(ingredient -> recipeComponent.childById(ItemListComponent.class, "input-1").ingredient(ingredient)); - recipe.base().ifPresent(ingredient -> recipeComponent.childById(ItemListComponent.class, "input-2").ingredient(ingredient)); + recipeComponent.childById(ItemListComponent.class, "input-2").ingredient(recipe.base()); recipe.addition().ifPresent(ingredient -> recipeComponent.childById(ItemListComponent.class, "input-3").ingredient(ingredient)); recipeComponent.childById(ItemComponent.class, "output").stack(recipe.getDisplays().getFirst().result().getFirst(slotContext)); @@ -156,7 +156,7 @@ public RecipeNode(RecipeEntry> recipe) { } @Override - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("rawtypes") protected void visitStart(MarkdownCompiler compiler) { var previewBuilder = (RecipePreviewBuilder) RecipeFeature.this.previewBuilders.get(this.recipe.value().getType()); if (previewBuilder != null) { diff --git a/src/main/java/io/wispforest/lavender/md/features/SpecialLinkFeature.java b/src/main/java/io/wispforest/lavender/md/features/SpecialLinkFeature.java new file mode 100644 index 0000000..edbc1c4 --- /dev/null +++ b/src/main/java/io/wispforest/lavender/md/features/SpecialLinkFeature.java @@ -0,0 +1,86 @@ +package io.wispforest.lavender.md.features; + + +import io.wispforest.lavender.md.compiler.BookCompiler; +import io.wispforest.lavendermd.Lexer; +import io.wispforest.lavendermd.MarkdownFeature; +import io.wispforest.lavendermd.Parser; +import io.wispforest.lavendermd.compiler.MarkdownCompiler; +import net.minecraft.nbt.NbtString; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.jetbrains.annotations.NotNull; + +import java.net.URI; +import java.util.Optional; + +// Workaround to prevent the Lavender-MD feature from exploding when parsing a string that starts with ^ into a URI +public class SpecialLinkFeature implements MarkdownFeature { + + @Override + public String name() { + return "lavender:links"; + } + + @Override + public boolean supportsCompiler(MarkdownCompiler compiler) { + return true; + } + + @Override + public void registerTokens(TokenRegistrar registrar) { + registrar.registerToken(Lexer.Token.lexFromChar(OpenLinkToken::new), '['); + registrar.registerToken((nibbler, tokens) -> { + nibbler.skip(); + if (!nibbler.tryConsume('(')) return false; + + var link = nibbler.consumeUntil(')'); + if (link == null) return false; + + tokens.add(new CloseLinkToken(link)); + return true; + }, ']'); + } + + @Override + public void registerNodes(NodeRegistrar registrar) { + registrar.registerNode((parser, left, tokens) -> { + int pointer = tokens.pointer(); + var content = parser.parseUntil(tokens, CloseLinkToken.class); + + if (tokens.peek() instanceof CloseLinkToken right) { + tokens.nibble(); + return new Parser.FormattingNode(style -> style.withClickEvent( + right.link.startsWith("^") + ? new ClickEvent.Custom(BookCompiler.BookLabelComponent.LINK, Optional.of(NbtString.of(right.link))) + : new ClickEvent.OpenUrl(URI.create(right.link)) + ).withHoverEvent( + new HoverEvent.ShowText(Text.literal(right.link)) + ).withColor(Formatting.BLUE)).addChild(content); + } else { + tokens.setPointer(pointer); + return new Parser.TextNode(left.content()); + } + }, (token, tokens) -> token instanceof OpenLinkToken link ? link : null); + } + + // --- tokens --- + + private static final class OpenLinkToken extends Lexer.Token { + public OpenLinkToken() { + super("["); + } + } + + private static final class CloseLinkToken extends Lexer.Token { + + public final @NotNull String link; + + public CloseLinkToken(@NotNull String link) { + super("](" + link + ")"); + this.link = link; + } + } +} diff --git a/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java b/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java index 76c74d4..47d9d70 100644 --- a/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java +++ b/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java @@ -28,7 +28,7 @@ @Mixin(DrawContext.class) public class DrawContextMixin { - @Inject(method = "drawTooltip(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;IILnet/minecraft/client/gui/tooltip/TooltipPositioner;Lnet/minecraft/util/Identifier;)V", at = @At("HEAD")) + @Inject(method = "drawTooltipImmediately(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;IILnet/minecraft/client/gui/tooltip/TooltipPositioner;Lnet/minecraft/util/Identifier;)V", at = @At("HEAD")) private void injectTooltipComponents(TextRenderer textRenderer, List components, int x, int y, TooltipPositioner positioner, @Nullable Identifier texture, CallbackInfo ci, @Local(argsOnly = true) LocalRef> componentsRef) { var client = MinecraftClient.getInstance(); @@ -58,14 +58,14 @@ private void injectTooltipComponents(TextRenderer textRenderer, List= .95) { LavenderBookScreen.pushEntry(book, associatedEntry); client.setScreen(new LavenderBookScreen(book)); if (bookIndex >= 0) { - client.player.getInventory().selectedSlot = bookIndex; + client.player.getInventory().setSelectedSlot(bookIndex); } entryTriggerProgress = 0f; diff --git a/src/main/java/io/wispforest/lavender/mixin/FramebufferMixin.java b/src/main/java/io/wispforest/lavender/mixin/FramebufferMixin.java deleted file mode 100644 index 6a3d8df..0000000 --- a/src/main/java/io/wispforest/lavender/mixin/FramebufferMixin.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.wispforest.lavender.mixin; - -import com.mojang.blaze3d.platform.GlStateManager; -import io.wispforest.lavender.pond.LavenderFramebufferExtension; -import net.minecraft.client.gl.Framebuffer; -import net.minecraft.client.gl.ShaderProgramKey; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.function.Supplier; - -@Mixin(Framebuffer.class) -public class FramebufferMixin implements LavenderFramebufferExtension { - - @Unique - private Supplier blitProgram = null; - - @Unique - private boolean enableDepthTest = false; - - @Override - public void lavender$setBlitProgram(Supplier blitProgram) { - this.blitProgram = blitProgram; - } - - @Override - public void lavender$enableDepthTest() { - this.enableDepthTest = true; - } - - @Inject(method = "drawInternal", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_disableDepthTest()V")) - private void weDeep(int width, int height, CallbackInfo ci) { - if (!this.enableDepthTest) return; - GlStateManager._enableDepthTest(); - } - - @ModifyArg(method = "drawInternal", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;setShader(Lnet/minecraft/client/gl/ShaderProgramKey;)Lnet/minecraft/client/gl/ShaderProgram;")) - private ShaderProgramKey applyBlitProgram(ShaderProgramKey shaderProgramKey) { - if (this.blitProgram == null) return shaderProgramKey; - return this.blitProgram.get(); - } -} diff --git a/src/main/java/io/wispforest/lavender/mixin/GameRendererMixin.java b/src/main/java/io/wispforest/lavender/mixin/GameRendererMixin.java new file mode 100644 index 0000000..d35d996 --- /dev/null +++ b/src/main/java/io/wispforest/lavender/mixin/GameRendererMixin.java @@ -0,0 +1,53 @@ +package io.wispforest.lavender.mixin; + +import io.wispforest.lavender.book.Book; +import io.wispforest.lavender.book.LavenderBookItem; +import io.wispforest.lavender.client.LavenderBookScreen; +import io.wispforest.lavender.client.OffhandBookRenderer; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.render.GuiRenderer; +import net.minecraft.client.gui.render.state.GuiRenderState; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.client.render.fog.FogRenderer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GameRenderer.class) +public class GameRendererMixin { + @Shadow + @Final + private MinecraftClient client; + + @Shadow + @Final + private GuiRenderState guiState; + + @Shadow + @Final + private GuiRenderer guiRenderer; + + @Shadow + @Final + private FogRenderer fogRenderer; + + @Inject(method = "render", at = @At(value = "NEW", target = "net/minecraft/client/gui/DrawContext")) + private void onFrameStart(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) { + var client = this.client; + if (client.player == null) return; + + var offhandStack = client.player.getOffHandStack(); + if (offhandStack.getItem() instanceof LavenderBookItem && LavenderBookItem.bookOf(offhandStack) instanceof Book book && !(client.currentScreen instanceof LavenderBookScreen)) { + OffhandBookRenderer.beginFrame(book, client, guiState, guiRenderer, fogRenderer); + } + } + + @Inject(method = "render", at = @At("RETURN")) + private void onFrameEnd(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) { + OffhandBookRenderer.endFrame(); + } +} diff --git a/src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java b/src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java new file mode 100644 index 0000000..0d1816c --- /dev/null +++ b/src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java @@ -0,0 +1,33 @@ +package io.wispforest.lavender.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import io.wispforest.lavender.client.GuiRendererFramebufferOverride; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.gui.render.GuiRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(GuiRenderer.class) +public class GuiRendererMixin implements GuiRendererFramebufferOverride { + @Unique + private Framebuffer override; + + @Override + public void lavender$setOverride(Framebuffer override) { + this.override = override; + } + + @Override + public Framebuffer lavender$getOverride() { + return override; + } + + @WrapOperation(method = "renderPreparedDraws", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getFramebuffer()Lnet/minecraft/client/gl/Framebuffer;")) + private Framebuffer overrideRenderFramebuffer(MinecraftClient instance, Operation original) { + if (override != null) return override; + return instance.getFramebuffer(); + } +} diff --git a/src/main/java/io/wispforest/lavender/mixin/MinecraftClientMixin.java b/src/main/java/io/wispforest/lavender/mixin/MinecraftClientMixin.java deleted file mode 100644 index b829073..0000000 --- a/src/main/java/io/wispforest/lavender/mixin/MinecraftClientMixin.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.wispforest.lavender.mixin; - -import io.wispforest.lavender.book.Book; -import io.wispforest.lavender.book.LavenderBookItem; -import io.wispforest.lavender.client.LavenderBookScreen; -import io.wispforest.lavender.client.OffhandBookRenderer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.network.ClientPlayerEntity; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MinecraftClient.class) -public class MinecraftClientMixin { - - @Shadow - @Nullable - public ClientPlayerEntity player; - - @Shadow - @Nullable - public Screen currentScreen; - - @Inject(method = "render", at = @At("HEAD")) - private void onFrameStart(boolean tick, CallbackInfo ci) { - if (this.player == null) return; - - Book bookToRender = null; - var offhandStack = this.player.getOffHandStack(); - if (offhandStack.getItem() instanceof LavenderBookItem && LavenderBookItem.bookOf(offhandStack) != null && !(this.currentScreen instanceof LavenderBookScreen)) { - bookToRender = LavenderBookItem.bookOf(offhandStack); - } - - OffhandBookRenderer.beginFrame(bookToRender); - } - - @Inject(method = "render", at = @At("TAIL")) - private void onFrameEnd(boolean tick, CallbackInfo ci) { - if (this.player == null) return; - OffhandBookRenderer.endFrame(); - } -} diff --git a/src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java b/src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java index 0bf16b1..1471760 100644 --- a/src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java +++ b/src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java @@ -1,6 +1,6 @@ package io.wispforest.lavender.mixin; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import io.wispforest.lavender.client.LavenderClient; import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.render.RenderPhase; @@ -9,8 +9,7 @@ @Mixin(RenderPhase.class) public class RenderPhaseMixin { - - @ModifyExpressionValue(method = {"method_62272", "method_34555", "method_29377"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getFramebuffer()Lnet/minecraft/client/gl/Framebuffer;")) + @ModifyReturnValue(method = {"method_68490", "method_68488", "method_68485"}, at = @At("RETURN")) private static Framebuffer injectProperRenderTarget(Framebuffer original) { if (LavenderClient.mainTargetOverride != null) { return LavenderClient.mainTargetOverride; @@ -18,5 +17,4 @@ private static Framebuffer injectProperRenderTarget(Framebuffer original) { return original; } - } diff --git a/src/main/java/io/wispforest/lavender/mixin/SimpleResourceReloadMixin.java b/src/main/java/io/wispforest/lavender/mixin/SimpleResourceReloadMixin.java index 371fc00..89d5c3f 100644 --- a/src/main/java/io/wispforest/lavender/mixin/SimpleResourceReloadMixin.java +++ b/src/main/java/io/wispforest/lavender/mixin/SimpleResourceReloadMixin.java @@ -4,6 +4,7 @@ import io.wispforest.lavender.pond.LavenderLifecycledResourceManagerExtension; import net.minecraft.client.MinecraftClient; import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourceReloader; import net.minecraft.resource.ResourceType; import net.minecraft.resource.SimpleResourceReload; import org.spongepowered.asm.mixin.Mixin; @@ -19,8 +20,8 @@ @Mixin(SimpleResourceReload.class) public class SimpleResourceReloadMixin { - @Inject(method = "", at = @At(value = "INVOKE_ASSIGN", target = "Lcom/google/common/collect/Sets;newHashSet(Ljava/lang/Iterable;)Ljava/util/HashSet;")) - private void loadLavenderBooks(Executor prepareExecutor, Executor applyExecutor, ResourceManager manager, List reloaders, @Coerce Object factory, CompletableFuture initialStage, CallbackInfo ci) { + @Inject(method = "start(Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Lnet/minecraft/resource/ResourceManager;Ljava/util/List;Lnet/minecraft/resource/SimpleResourceReload$Factory;Ljava/util/concurrent/CompletableFuture;)V", at = @At("HEAD")) + private void loadLavenderBooks(Executor prepareExecutor, Executor applyExecutor, ResourceManager manager, List reloaders, @Coerce Object factory, CompletableFuture initialStage, CallbackInfo ci) { if (!(manager instanceof LavenderLifecycledResourceManagerExtension extension) || extension.lavender$resourceType() != ResourceType.CLIENT_RESOURCES) return; if (MinecraftClient.getInstance().world == null) return; diff --git a/src/main/java/io/wispforest/lavender/mixin/TextureUtilMixin.java b/src/main/java/io/wispforest/lavender/mixin/TextureUtilMixin.java deleted file mode 100644 index 3525837..0000000 --- a/src/main/java/io/wispforest/lavender/mixin/TextureUtilMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.wispforest.lavender.mixin; - -import com.mojang.blaze3d.platform.TextureUtil; -import io.wispforest.lavender.client.LavenderClient; -import net.minecraft.client.texture.NativeImage; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(TextureUtil.class) -public class TextureUtilMixin { - - @Inject(method = "prepareImage(Lnet/minecraft/client/texture/NativeImage$InternalFormat;IIII)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/TextureUtil;bind(I)V")) - private static void captureTextureSize(NativeImage.InternalFormat internalFormat, int id, int maxLevel, int width, int height, CallbackInfo ci) { - LavenderClient.registerTextureSize(id, width, height); - } - -} diff --git a/src/main/java/io/wispforest/lavender/pond/LavenderFramebufferExtension.java b/src/main/java/io/wispforest/lavender/pond/LavenderFramebufferExtension.java deleted file mode 100644 index 02f87bd..0000000 --- a/src/main/java/io/wispforest/lavender/pond/LavenderFramebufferExtension.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.wispforest.lavender.pond; - -import net.minecraft.client.gl.ShaderProgramKey; - -import java.util.function.Supplier; - -public interface LavenderFramebufferExtension { - void lavender$setBlitProgram(Supplier blitProgram); - - void lavender$enableDepthTest(); -} diff --git a/src/main/resources/assets/lavender/shaders/core/blit_alpha.fsh b/src/main/resources/assets/lavender/shaders/core/blit_alpha.fsh index a8303f1..0944509 100644 --- a/src/main/resources/assets/lavender/shaders/core/blit_alpha.fsh +++ b/src/main/resources/assets/lavender/shaders/core/blit_alpha.fsh @@ -1,7 +1,6 @@ #version 150 uniform sampler2D InSampler; -uniform float Alpha; in vec2 texCoord; @@ -9,7 +8,7 @@ out vec4 fragColor; void main() { vec4 color = texture(InSampler, texCoord); - color.a *= Alpha; + color.a *= .5f; // There's only one usage of this shader in this mod and it uses this constant. fragColor = color; } diff --git a/src/main/resources/assets/lavender/shaders/core/blit_alpha.json b/src/main/resources/assets/lavender/shaders/core/blit_alpha.json deleted file mode 100644 index 92e3206..0000000 --- a/src/main/resources/assets/lavender/shaders/core/blit_alpha.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "vertex": "core/blit_screen", - "fragment": "lavender:core/blit_alpha", - "samplers": [ - { "name": "InSampler" } - ], - "uniforms": [ - { "name": "Alpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] -} diff --git a/src/main/resources/assets/lavender/shaders/core/blit_cutout.json b/src/main/resources/assets/lavender/shaders/core/blit_cutout.json deleted file mode 100644 index 6e71b7e..0000000 --- a/src/main/resources/assets/lavender/shaders/core/blit_cutout.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "vertex": "core/blit_screen", - "fragment": "lavender:core/blit_cutout", - "samplers": [ - { "name": "InSampler" } - ], - "uniforms": [] -} diff --git a/src/main/resources/lavender.mixins.json b/src/main/resources/lavender.mixins.json index c46fecd..1f5661e 100644 --- a/src/main/resources/lavender.mixins.json +++ b/src/main/resources/lavender.mixins.json @@ -11,14 +11,13 @@ "ClientAdvancementManagerMixin", "CreativeInventoryScreenMixin", "DrawContextMixin", - "FramebufferMixin", + "GameRendererMixin", + "GuiRendererMixin", "HeldItemRendererMixin", - "MinecraftClientMixin", "MouseMixin", "RenderPhaseMixin", "ScreenMixin", "SimpleResourceReloadMixin", - "TextureUtilMixin", "access.ClientAdvancementManagerAccessor" ], "injectors": { From 2319a9f80b99d6853dba7ecc0f401ba42ec53821 Mon Sep 17 00:00:00 2001 From: pizzacalz0ne Date: Tue, 16 Sep 2025 20:59:00 +1100 Subject: [PATCH 2/5] nit: use RenderSystem overrides instead of making our own --- .../lavender/client/LavenderClient.java | 3 --- .../lavender/client/OffhandBookRenderer.java | 7 +++++-- .../client/StructureOverlayRenderer.java | 7 +++++-- .../lavender/mixin/RenderPhaseMixin.java | 20 ------------------- src/main/resources/lavender.mixins.json | 1 - 5 files changed, 10 insertions(+), 28 deletions(-) delete mode 100644 src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java diff --git a/src/main/java/io/wispforest/lavender/client/LavenderClient.java b/src/main/java/io/wispforest/lavender/client/LavenderClient.java index 71abc10..38e8f1c 100644 --- a/src/main/java/io/wispforest/lavender/client/LavenderClient.java +++ b/src/main/java/io/wispforest/lavender/client/LavenderClient.java @@ -25,7 +25,6 @@ import net.fabricmc.fabric.api.client.rendering.v1.SpecialGuiElementRegistry; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.item.model.ItemModelTypes; import net.minecraft.item.Items; @@ -44,8 +43,6 @@ public class LavenderClient implements ClientModInitializer { private static UUID currentWorldId = null; - public static @Nullable Framebuffer mainTargetOverride = null; - @Override public void onInitializeClient() { ClientCommandRegistrationCallback.EVENT.register(LavenderCommands.Client::register); diff --git a/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java b/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java index 547dcbf..c3f7a2b 100644 --- a/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java +++ b/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java @@ -1,6 +1,7 @@ package io.wispforest.lavender.client; import com.google.common.base.Suppliers; +import com.mojang.blaze3d.systems.RenderSystem; import io.wispforest.lavender.Lavender; import io.wispforest.lavender.book.Book; import io.wispforest.owo.ui.event.WindowResizeCallback; @@ -76,7 +77,8 @@ public static void beginFrame(@Nullable Book book, MinecraftClient client, GuiRe var override = (GuiRendererFramebufferOverride) guiRenderer; - LavenderClient.mainTargetOverride = screenBuffer; + RenderSystem.outputColorTextureOverride = screenBuffer.getColorAttachmentView(); + RenderSystem.outputDepthTextureOverride = screenBuffer.getDepthAttachmentView(); override.lavender$setOverride(screenBuffer); screenBuffer.clear(); @@ -85,7 +87,8 @@ public static void beginFrame(@Nullable Book book, MinecraftClient client, GuiRe guiState.clear(); override.lavender$setOverride(null); - LavenderClient.mainTargetOverride = null; + RenderSystem.outputColorTextureOverride = null; + RenderSystem.outputDepthTextureOverride = null; } public static void render(MatrixStack matrices, int light) { diff --git a/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java b/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java index cfd1640..b3a1f30 100644 --- a/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java +++ b/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.pipeline.BlendFunction; import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.platform.DepthTestFunction; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexFormat; import io.wispforest.lavender.Lavender; import io.wispforest.lavender.structure.BlockStatePredicate; @@ -154,7 +155,8 @@ public static void initialize() { var framebuffer = FRAMEBUFFER.get(); framebuffer.clear(); - LavenderClient.mainTargetOverride = framebuffer; + RenderSystem.outputColorTextureOverride = framebuffer.getColorAttachmentView(); + RenderSystem.outputDepthTextureOverride = framebuffer.getDepthAttachmentView(); framebuffer.copyDepthFrom(targetFramebuffer); @@ -258,7 +260,8 @@ public static void initialize() { CONSUMERS.draw(); effectConsumers.draw(); - LavenderClient.mainTargetOverride = null; + RenderSystem.outputColorTextureOverride = null; + RenderSystem.outputDepthTextureOverride = null; targetFramebuffer.copyDepthFrom(framebuffer); framebuffer.drawBlit(targetFramebuffer.getColorAttachmentView()); diff --git a/src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java b/src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java deleted file mode 100644 index 1471760..0000000 --- a/src/main/java/io/wispforest/lavender/mixin/RenderPhaseMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.wispforest.lavender.mixin; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import io.wispforest.lavender.client.LavenderClient; -import net.minecraft.client.gl.Framebuffer; -import net.minecraft.client.render.RenderPhase; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(RenderPhase.class) -public class RenderPhaseMixin { - @ModifyReturnValue(method = {"method_68490", "method_68488", "method_68485"}, at = @At("RETURN")) - private static Framebuffer injectProperRenderTarget(Framebuffer original) { - if (LavenderClient.mainTargetOverride != null) { - return LavenderClient.mainTargetOverride; - } - - return original; - } -} diff --git a/src/main/resources/lavender.mixins.json b/src/main/resources/lavender.mixins.json index 1f5661e..915622d 100644 --- a/src/main/resources/lavender.mixins.json +++ b/src/main/resources/lavender.mixins.json @@ -15,7 +15,6 @@ "GuiRendererMixin", "HeldItemRendererMixin", "MouseMixin", - "RenderPhaseMixin", "ScreenMixin", "SimpleResourceReloadMixin", "access.ClientAdvancementManagerAccessor" From be4cd81583477563fe5f6c5fadd3ab382f222484 Mon Sep 17 00:00:00 2001 From: pizzacalz0ne Date: Wed, 17 Sep 2025 21:44:38 +1100 Subject: [PATCH 3/5] oopsie daisy --- .../java/io/wispforest/lavender/mixin/GuiRendererMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java b/src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java index 0d1816c..6f17aee 100644 --- a/src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java +++ b/src/main/java/io/wispforest/lavender/mixin/GuiRendererMixin.java @@ -28,6 +28,6 @@ public class GuiRendererMixin implements GuiRendererFramebufferOverride { @WrapOperation(method = "renderPreparedDraws", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getFramebuffer()Lnet/minecraft/client/gl/Framebuffer;")) private Framebuffer overrideRenderFramebuffer(MinecraftClient instance, Operation original) { if (override != null) return override; - return instance.getFramebuffer(); + return original.call(instance); } } From a57241f82a5df33349520427486a5fc041db9d40 Mon Sep 17 00:00:00 2001 From: pizzacalz0ne Date: Mon, 3 Nov 2025 16:09:21 +1100 Subject: [PATCH 4/5] 1.21.10 --- build.gradle | 5 +- gradle.properties | 19 ++--- .../wispforest/lavender/LavenderCommands.java | 2 +- .../lavender/book/BookContentLoader.java | 4 +- .../lavender/book/LavenderBookItem.java | 2 +- .../lavender/book/StructureComponent.java | 35 +++++---- .../AssociatedEntryTooltipComponent.java | 5 +- .../lavender/client/BookBakedModel.java | 4 +- .../lavender/client/LavenderBookScreen.java | 75 ++++++++++--------- .../lavender/client/LavenderClient.java | 2 +- .../lavender/client/LavenderFramebuffer.java | 7 +- .../lavender/client/NewEntriesToast.java | 5 +- .../lavender/client/OffhandBookRenderer.java | 18 ++--- .../client/StructureOverlayRenderer.java | 20 ++--- .../lavender/md/compiler/BookCompiler.java | 2 +- .../lavender/md/features/RecipeFeature.java | 3 +- .../lavender/mixin/DrawContextMixin.java | 2 +- .../lavender/mixin/HeldItemRendererMixin.java | 6 +- .../mixin/access/WorldRendererAccessor.java | 13 ++++ src/main/resources/fabric.mod.json | 74 +++++++++--------- src/main/resources/lavender.mixins.json | 3 +- 21 files changed, 158 insertions(+), 148 deletions(-) create mode 100644 src/main/java/io/wispforest/lavender/mixin/access/WorldRendererAccessor.java diff --git a/build.gradle b/build.gradle index 4da8a6c..a28e83d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.11-SNAPSHOT' + id 'fabric-loom' version '1.12-SNAPSHOT' id 'maven-publish' } @@ -58,9 +58,6 @@ dependencies { modImplementation "io.wispforest:owo-lib:${project.owo_version}" include "io.wispforest:owo-sentinel:${project.owo_version}" -// modLocalRuntime "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}" - modCompileOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}" - include modApi("io.wispforest.lavender-md:core:${project.lavender_md_version}") include modApi("io.wispforest.lavender-md:owo-ui:${project.lavender_md_version}") diff --git a/gradle.properties b/gradle.properties index 0574fcb..c6e313d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,10 +3,10 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_base_version=1.21.8 - minecraft_version=1.21.8 - yarn_mappings=1.21.8+build.1 - loader_version=0.17.2 + minecraft_base_version=1.21.10 + minecraft_version=1.21.10 + yarn_mappings=1.21.10+build.2 + loader_version=0.17.3 # Mod Properties mod_version = 0.1.15 @@ -15,16 +15,13 @@ org.gradle.jvmargs=-Xmx1G # Dependencies # check this on https://fabricmc.net/develop - fabric_version=0.133.4+1.21.8 - - # https://maven.shedaniel.me/me/shedaniel/RoughlyEnoughItems-fabric/ - rei_version=20.0.811 + fabric_version=0.137.0+1.21.10 # https://maven.wispforest.io/#/releases/io/wispforest/owo-lib/ - owo_version=0.12.22+1.21.8 + owo_version=0.12.24+1.21.9 # https://maven.terraformersmc.com/releases/com/terraformersmc/modmenu - modmenu_version=15.0.0 + modmenu_version=16.0.0-rc.1 # https://maven.wispforest.io/#/releases/io/wispforest/lavender-md/core/ - lavender_md_version=0.1.2+1.21.8 + lavender_md_version=0.1.3+1.21.10 diff --git a/src/main/java/io/wispforest/lavender/LavenderCommands.java b/src/main/java/io/wispforest/lavender/LavenderCommands.java index 5179cd6..3003313 100644 --- a/src/main/java/io/wispforest/lavender/LavenderCommands.java +++ b/src/main/java/io/wispforest/lavender/LavenderCommands.java @@ -83,7 +83,7 @@ private static int executeGetLavenderBook(CommandContext { - context.getSource().getClient().setScreen(new ChatScreen(jAvAsE)); + context.getSource().getClient().setScreen(new ChatScreen(jAvAsE, true)); }); return 0; diff --git a/src/main/java/io/wispforest/lavender/book/BookContentLoader.java b/src/main/java/io/wispforest/lavender/book/BookContentLoader.java index a36a626..cf92dc2 100644 --- a/src/main/java/io/wispforest/lavender/book/BookContentLoader.java +++ b/src/main/java/io/wispforest/lavender/book/BookContentLoader.java @@ -16,6 +16,8 @@ import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditions; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.TexturedRenderLayers; +import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.command.argument.ItemStringReader; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -258,7 +260,7 @@ private static Function getIcon(JsonObject meta) { var id = Identifier.tryParse(JsonHelper.getString(meta, "icon_sprite")); if (id == null) return null; - return sizing -> Components.sprite(MinecraftClient.getInstance().getGuiAtlasManager().getSprite(id)).sizing(sizing); + return sizing -> Components.sprite(new SpriteIdentifier(TexturedRenderLayers.GUI_ATLAS_TEXTURE, id)).sizing(sizing); } else { return sizing -> Containers.stack(sizing, sizing); } diff --git a/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java b/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java index 6bd2bf5..60d5e2c 100644 --- a/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java +++ b/src/main/java/io/wispforest/lavender/book/LavenderBookItem.java @@ -146,7 +146,7 @@ public ActionResult use(World world, PlayerEntity user, Hand hand) { var bookId = bookIdOf(playerStack); if (bookId == null) return ActionResult.SUCCESS; - if (!world.isClient) return ActionResult.SUCCESS; + if (!world.isClient()) return ActionResult.SUCCESS; var book = BookLoader.get(bookId); if (book == null) { diff --git a/src/main/java/io/wispforest/lavender/book/StructureComponent.java b/src/main/java/io/wispforest/lavender/book/StructureComponent.java index b74557d..a88bb26 100644 --- a/src/main/java/io/wispforest/lavender/book/StructureComponent.java +++ b/src/main/java/io/wispforest/lavender/book/StructureComponent.java @@ -10,8 +10,8 @@ import io.wispforest.owo.ui.parsing.UIModelParsingException; import io.wispforest.owo.ui.parsing.UIParsing; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Click; import net.minecraft.client.gui.ScreenRect; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -71,27 +71,26 @@ public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partial } } - @Override - public boolean onMouseDown(double mouseX, double mouseY, int button) { - var result = super.onMouseDown(mouseX, mouseY, button); - if (!this.placeable || button != GLFW.GLFW_MOUSE_BUTTON_LEFT || !Screen.hasShiftDown()) return result; - - if (StructureOverlayRenderer.isShowingOverlay(this.structure.id)) { - StructureOverlayRenderer.removeAllOverlays(this.structure.id); - } else { - StructureOverlayRenderer.addPendingOverlay(this.structure.id); - StructureOverlayRenderer.restrictVisibleLayer(this.structure.id, this.visibleLayer); + @Override + public boolean onMouseDown(Click click, boolean doubled) { + var result = super.onMouseDown(click, doubled); + if (!this.placeable || click.button() != GLFW.GLFW_MOUSE_BUTTON_LEFT || !click.hasShift()) return result; - MinecraftClient.getInstance().setScreen(null); - } + if (StructureOverlayRenderer.isShowingOverlay(this.structure.id)) { + StructureOverlayRenderer.removeAllOverlays(this.structure.id); + } else { + StructureOverlayRenderer.addPendingOverlay(this.structure.id); + StructureOverlayRenderer.restrictVisibleLayer(this.structure.id, this.visibleLayer); - return true; - } + MinecraftClient.getInstance().setScreen(null); + } + return true; + } @Override - public boolean onMouseDrag(double mouseX, double mouseY, double deltaX, double deltaY, int button) { - var result = super.onMouseDrag(mouseX, mouseY, deltaX, deltaY, button); - if (button != GLFW.GLFW_MOUSE_BUTTON_LEFT) return result; + public boolean onMouseDrag(Click click, double deltaX, double deltaY) { + var result = super.onMouseDrag(click, deltaX, deltaY); + if (click.button() != GLFW.GLFW_MOUSE_BUTTON_LEFT) return result; this.rotation += (float) deltaX; this.lastInteractionTime = Util.getMeasuringTimeMs(); diff --git a/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java b/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java index ccc4f0e..9b9512a 100644 --- a/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java +++ b/src/main/java/io/wispforest/lavender/client/AssociatedEntryTooltipComponent.java @@ -9,7 +9,6 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -30,7 +29,7 @@ public AssociatedEntryTooltipComponent(ItemStack book, Entry entry, float progre this.layout.child(Containers.verticalFlow(Sizing.content(), Sizing.content()) .child(entry.iconFactory().apply(Sizing.fixed(16)).margins(Insets.of(2))) - .child(Components.item(book).sizing(Sizing.fixed(8)).positioning(Positioning.absolute(11, 11)).zIndex(50))); + .child(Components.item(book).sizing(Sizing.fixed(8)).positioning(Positioning.absolute(11, 11)))); this.layout.child(Containers.verticalFlow(Sizing.content(), Sizing.content()) .child(Components.label(Text.literal(entry.title()).formatted(Formatting.GRAY))) @@ -67,7 +66,7 @@ public int getWidth(TextRenderer textRenderer) { static { ClientTickEvents.END_CLIENT_TICK.register(client -> { - if (Screen.hasAltDown()) return; + if (client.isAltPressed()) return; entryTriggerProgress += Delta.compute(entryTriggerProgress, 0f, .125f); }); } diff --git a/src/main/java/io/wispforest/lavender/client/BookBakedModel.java b/src/main/java/io/wispforest/lavender/client/BookBakedModel.java index 998ff3c..86ceb3d 100644 --- a/src/main/java/io/wispforest/lavender/client/BookBakedModel.java +++ b/src/main/java/io/wispforest/lavender/client/BookBakedModel.java @@ -6,9 +6,9 @@ import net.minecraft.client.render.item.ItemRenderState; import net.minecraft.client.render.item.model.ItemModel; import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemDisplayContext; import net.minecraft.item.ItemStack; +import net.minecraft.util.HeldItemContext; import org.jetbrains.annotations.Nullable; public class BookBakedModel implements ItemModel { @@ -20,7 +20,7 @@ public BookBakedModel(ItemModel defaultModel) { } @Override - public void update(ItemRenderState state, ItemStack stack, ItemModelManager resolver, ItemDisplayContext displayContext, @Nullable ClientWorld world, @Nullable LivingEntity user, int seed) { + public void update(ItemRenderState state, ItemStack stack, ItemModelManager resolver, ItemDisplayContext displayContext, @Nullable ClientWorld world, @Nullable HeldItemContext user, int seed) { var book = LavenderBookItem.bookOf(stack); if (book != null && book.dynamicBookModel() != null) { MinecraftClient.getInstance().getBakedModelManager().getItemModel(book.dynamicBookModel()).update(state, stack, resolver, displayContext, world, user, seed); diff --git a/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java b/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java index 4b5b180..3b17644 100644 --- a/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java +++ b/src/main/java/io/wispforest/lavender/client/LavenderBookScreen.java @@ -23,16 +23,19 @@ import io.wispforest.owo.ui.util.CommandOpenedScreen; import io.wispforest.owo.ui.util.UISounds; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.input.CharInput; +import net.minecraft.client.input.KeyInput; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.util.Window; import net.minecraft.recipe.Recipe; import net.minecraft.recipe.RecipeType; import net.minecraft.sound.SoundEvent; import net.minecraft.text.Style; +import net.minecraft.text.StyleSpriteSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; @@ -148,7 +151,6 @@ protected Identifier bookTexture() { @Override protected @NotNull C component(Class expectedClass, String id) { - //noinspection DataFlowIssue return super.component(expectedClass, id); } @@ -164,7 +166,7 @@ protected void build(FlowLayout rootComponent) { (this.previousButton = this.component(ButtonComponent.class, "previous-button")).onPress(button -> this.turnPage(true)); (this.nextButton = this.component(ButtonComponent.class, "next-button")).onPress(button -> this.turnPage(false)); (this.returnButton = this.component(ButtonComponent.class, "back-button")).onPress(button -> { - if (Screen.hasShiftDown()) { + if (MinecraftClient.getInstance().isShiftPressed()) { while (this.navStack.size() > 1) this.navStack.pop(); this.rebuildContent(this.book.flippingSound()); } else { @@ -266,7 +268,7 @@ public void rebuildContent(@Nullable SoundEvent sound) { bookmarkComponent.childById(StackLayout.class, "bookmark-preview").child(element.iconFactory().apply(Sizing.fill()).cursorStyle(CursorStyle.HAND)); bookmarkComponent.childById(ButtonComponent.class, "bookmark-button").configure(bookmarkButton -> { bookmarkButton.onPress($ -> { - if (Screen.hasShiftDown()) { + if (MinecraftClient.getInstance().isShiftPressed()) { LavenderClientStorage.removeBookmark(this.book, bookmark); this.rebuildContent(null); } else if (element instanceof Entry entry) { @@ -363,25 +365,26 @@ protected void drawComponentTooltip(DrawContext drawContext, int mouseX, int mou super.drawComponentTooltip(drawContext, mouseX, mouseY, tickDelta); } - @Override - public boolean charTyped(char chr, int modifiers) { - if (super.charTyped(chr, modifiers)) return true; + @Override + public boolean charTyped(CharInput input) { + if (super.charTyped(input)) return true; - if (chr == 'e' && (modifiers & GLFW.GLFW_MOD_ALT) != 0) { + if (input.codepoint() == 'e' && (input.modifiers() & GLFW.GLFW_MOD_ALT) != 0) { this.navPush(new EditorPageSupplier(this)); return true; } this.searchBox.focusHandler().focus(this.searchBox, Component.FocusSource.MOUSE_CLICK); - this.searchBox.charTyped(chr, modifiers); + this.searchBox.charTyped(input); return true; } @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (super.keyPressed(keyCode, scanCode, modifiers)) return true; + public boolean keyPressed(KeyInput input) { + if (super.keyPressed(input)) return true; + final int keyCode = input.key(); if (keyCode == GLFW.GLFW_KEY_BACKSPACE) { this.navPop(); } else if (keyCode == GLFW.GLFW_KEY_LEFT || keyCode == GLFW.GLFW_KEY_PAGE_DOWN) { @@ -400,13 +403,15 @@ public Optional hoveredElement(double mouseX, double mouseY) { return super.hoveredElement(mouseX, mouseY).flatMap(element -> element != this.uiAdapter ? Optional.of(element) : Optional.empty()); } - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - mouseX = mouseX * this.window.getScaleFactor() / this.scaleFactor; - mouseY = mouseY * this.window.getScaleFactor() / this.scaleFactor; + @Override + public boolean mouseClicked(Click click, boolean doubled) { + final var mouseX = click.x() * this.window.getScaleFactor() / this.scaleFactor; + final var mouseY = click.y() * this.window.getScaleFactor() / this.scaleFactor; + click = new Click(mouseX, mouseY, click.buttonInfo()); - if (this.uiAdapter.mouseClicked(mouseX, mouseY, button) || super.mouseClicked(mouseX, mouseY, button)) return true; + if (this.uiAdapter.mouseClicked(click, doubled) || super.mouseClicked(click, doubled)) return true; + final int button = click.button(); if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { this.navPop(); } else if (button == GLFW.GLFW_MOUSE_BUTTON_4) { @@ -421,17 +426,19 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - mouseX = mouseX * this.window.getScaleFactor() / this.scaleFactor; - mouseY = mouseY * this.window.getScaleFactor() / this.scaleFactor; - return this.uiAdapter.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) || super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + public boolean mouseDragged(Click click, double deltaX, double deltaY) { + final var mouseX = click.x() * this.window.getScaleFactor() / this.scaleFactor; + final var mouseY = click.y() * this.window.getScaleFactor() / this.scaleFactor; + click = new Click(mouseX, mouseY, click.buttonInfo()); + return this.uiAdapter.mouseDragged(click, deltaX, deltaY) || super.mouseDragged(click, deltaX, deltaY); } @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - mouseX = mouseX * this.window.getScaleFactor() / this.scaleFactor; - mouseY = mouseY * this.window.getScaleFactor() / this.scaleFactor; - return super.mouseReleased(mouseX, mouseY, button); + public boolean mouseReleased(Click click) { + final var mouseX = click.x() * this.window.getScaleFactor() / this.scaleFactor; + final var mouseY = click.y() * this.window.getScaleFactor() / this.scaleFactor; + click = new Click(mouseX, mouseY, click.buttonInfo()); + return super.mouseReleased(click); } @Override @@ -570,8 +577,8 @@ protected ParentComponent parseMarkdown(String markdown) { item.tooltip(newTooltip); } - item.mouseDown().subscribe((mouseX, mouseY, button) -> { - if (button != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; + item.mouseDown().subscribe((click, doubled) -> { + if (click.button() != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; this.context.navPush(new EntryPageSupplier(this.context, entry)); UISounds.playInteractionSound(); @@ -624,9 +631,9 @@ protected List buildEntryIndex(Collection entries, boolean re var label = indexItem.childById(LabelComponent.class, "index-label"); - label.text(Text.literal(entry.title()).styled($ -> $.withFont(MinecraftClient.UNICODE_FONT_ID).withItalic(false && hasUnreadNotification))); - label.mouseDown().subscribe((mouseX, mouseY, button) -> { - if (button != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; + label.text(Text.literal(entry.title()).styled($ -> $.withFont(new StyleSpriteSource.Font(MinecraftClient.UNICODE_FONT_ID)).withItalic(false && hasUnreadNotification))); + label.mouseDown().subscribe((click, doubled) -> { + if (click.button() != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; this.context.navPush(new EntryPageSupplier(this.context, entry)); UISounds.playInteractionSound(); @@ -677,8 +684,8 @@ protected FlowLayout buildCategoryIndex(Stream categories) { .margins(Insets.of(4)) .cursorStyle(CursorStyle.HAND); - categoryButton.mouseDown().subscribe((mouseX, mouseY, button) -> { - if (button != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; + categoryButton.mouseDown().subscribe((click, doubled) -> { + if (click.button() != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; this.context.navPush(new CategoryPageSupplier(this.context, category_)); UISounds.playInteractionSound(); @@ -705,7 +712,7 @@ protected FlowLayout buildCategoryIndex(Stream categories) { } protected int lineCount(String entryTitle, boolean hasNotification) { - return this.context.client.textRenderer.getTextHandler().wrapLines(entryTitle, hasNotification ? 90 : 98, Style.EMPTY.withFont(MinecraftClient.UNICODE_FONT_ID)).size(); + return this.context.client.textRenderer.getTextHandler().wrapLines(entryTitle, hasNotification ? 90 : 98, Style.EMPTY.withFont(new StyleSpriteSource.Font(MinecraftClient.UNICODE_FONT_ID))).size(); } public interface Bookmarkable { @@ -761,8 +768,8 @@ public LandingPageSupplier(LavenderBookScreen context) { .margins(Insets.of(4)) .cursorStyle(CursorStyle.HAND); - categoryButton.mouseDown().subscribe((mouseX, mouseY, button) -> { - if (button != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; + categoryButton.mouseDown().subscribe((click, doubled) -> { + if (click.button() != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false; this.context.navPush(new IndexPageSupplier(this.context)); UISounds.playInteractionSound(); diff --git a/src/main/java/io/wispforest/lavender/client/LavenderClient.java b/src/main/java/io/wispforest/lavender/client/LavenderClient.java index 38e8f1c..c5a5ad5 100644 --- a/src/main/java/io/wispforest/lavender/client/LavenderClient.java +++ b/src/main/java/io/wispforest/lavender/client/LavenderClient.java @@ -95,7 +95,7 @@ public void onInitializeClient() { container.child(Containers.verticalFlow(Sizing.content(), Sizing.content()) .child(associatedEntry.iconFactory().apply(Sizing.fixed(16)).margins(Insets.of(0, 1, 0, 1))) - .child(Components.item(LavenderBookItem.itemOf(book)).sizing(Sizing.fixed(8)).positioning(Positioning.absolute(9, 9)).zIndex(50))); + .child(Components.item(LavenderBookItem.itemOf(book)).sizing(Sizing.fixed(8)).positioning(Positioning.absolute(9, 9)))); container.child(Containers.verticalFlow(Sizing.content(), Sizing.content()) .child(Components.label(Text.literal(associatedEntry.title())).shadow(true)) .child(Components.label(Text.translatable(client.player.isSneaking() ? "text.lavender.entry_hud.click_to_view" : "text.lavender.entry_hud.sneak_to_view")))); diff --git a/src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java b/src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java index 02ae210..028e72a 100644 --- a/src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java +++ b/src/main/java/io/wispforest/lavender/client/LavenderFramebuffer.java @@ -41,17 +41,12 @@ public void clear() { @Override public void drawBlit(GpuTextureView texture) { RenderSystem.assertOnRenderThread(); - RenderSystem.ShapeIndexBuffer shapeIndexBuffer = RenderSystem.getSequentialBuffer(VertexFormat.DrawMode.QUADS); - GpuBuffer indexBuffer = shapeIndexBuffer.getIndexBuffer(6); - GpuBuffer vertexBuffer = RenderSystem.getQuadVertexBuffer(); try (RenderPass renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(() -> "Blit render target", texture, OptionalInt.empty())) { renderPass.setPipeline(pipeline); RenderSystem.bindDefaultUniforms(renderPass); - renderPass.setVertexBuffer(0, vertexBuffer); - renderPass.setIndexBuffer(indexBuffer, shapeIndexBuffer.getIndexType()); renderPass.bindSampler("InSampler", this.colorAttachmentView); - renderPass.drawIndexed(0, 0, 6, 1); + renderPass.draw(0, 3); } } } diff --git a/src/main/java/io/wispforest/lavender/client/NewEntriesToast.java b/src/main/java/io/wispforest/lavender/client/NewEntriesToast.java index d403485..04eec36 100644 --- a/src/main/java/io/wispforest/lavender/client/NewEntriesToast.java +++ b/src/main/java/io/wispforest/lavender/client/NewEntriesToast.java @@ -9,7 +9,8 @@ import io.wispforest.owo.ui.core.Insets; import io.wispforest.owo.ui.core.Sizing; import io.wispforest.owo.ui.core.VerticalAlignment; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.TexturedRenderLayers; +import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -21,7 +22,7 @@ public class NewEntriesToast extends BaseOwoToast { public NewEntriesToast(Book.ToastSettings settings) { super( () -> Containers.stack(Sizing.content(), Sizing.content()).configure(component -> component - .child(Components.sprite(MinecraftClient.getInstance().getGuiAtlasManager().getSprite(settings.backgroundSprite() != null ? settings.backgroundSprite() : TEXTURE))) + .child(Components.sprite(new SpriteIdentifier(TexturedRenderLayers.GUI_ATLAS_TEXTURE, settings.backgroundSprite() != null ? settings.backgroundSprite() : TEXTURE))) .child(Containers.horizontalFlow(Sizing.content(), Sizing.content()) .child(Components.item(settings.iconStack()).margins(Insets.of(0, 0, 8, 6))) .child(Components.label(Text.translatable("text.lavender.toast.new_entries", settings.bookName()))) diff --git a/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java b/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java index c3f7a2b..3f974bd 100644 --- a/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java +++ b/src/main/java/io/wispforest/lavender/client/OffhandBookRenderer.java @@ -11,6 +11,7 @@ import net.minecraft.client.gui.render.*; import net.minecraft.client.gui.render.state.GuiRenderState; import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.render.fog.FogRenderer; import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.util.math.MatrixStack; @@ -91,7 +92,7 @@ public static void beginFrame(@Nullable Book book, MinecraftClient client, GuiRe RenderSystem.outputDepthTextureOverride = null; } - public static void render(MatrixStack matrices, int light) { + public static void render(MatrixStack matrices, OrderedRenderCommandQueue queue, int light) { cacheExpired = true; var client = MinecraftClient.getInstance(); @@ -111,15 +112,12 @@ public static void render(MatrixStack matrices, int light) { matrices.scale(1 * (framebuffer.textureWidth / (float) framebuffer.textureHeight), 1f, 1f); matrices.translate(rightHanded ? -.4f : -.6f, -.35f, -.165f); - var buffer = client.getBufferBuilders().getEntityVertexConsumers().getBuffer(RenderLayer.getText(Lavender.id("offhand_book_framebuffer"))); - var matrix = matrices.peek().getPositionMatrix(); - - buffer.vertex(matrix, 0, 1, 0).color(1f, 1f, 1f, 1f).texture(0, 1).light(light); - buffer.vertex(matrix, 0, 0, 0).color(1f, 1f, 1f, 1f).texture(0, 0).light(light); - buffer.vertex(matrix, 1, 0, 0).color(1f, 1f, 1f, 1f).texture(1, 0).light(light); - buffer.vertex(matrix, 1, 1, 0).color(1f, 1f, 1f, 1f).texture(1, 1).light(light); - - client.getBufferBuilders().getEntityVertexConsumers().draw(); + queue.submitCustom(matrices, RenderLayer.getText(Lavender.id("offhand_book_framebuffer")), (matrix, buffer) -> { + buffer.vertex(matrix, 0, 1, 0).color(1f, 1f, 1f, 1f).texture(0, 1).light(light); + buffer.vertex(matrix, 0, 0, 0).color(1f, 1f, 1f, 1f).texture(0, 0).light(light); + buffer.vertex(matrix, 1, 0, 0).color(1f, 1f, 1f, 1f).texture(1, 0).light(light); + buffer.vertex(matrix, 1, 1, 0).color(1f, 1f, 1f, 1f).texture(1, 1).light(light); + }); matrices.pop(); } diff --git a/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java b/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java index b3a1f30..f5d7c5e 100644 --- a/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java +++ b/src/main/java/io/wispforest/lavender/client/StructureOverlayRenderer.java @@ -7,6 +7,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexFormat; import io.wispforest.lavender.Lavender; +import io.wispforest.lavender.mixin.access.WorldRendererAccessor; import io.wispforest.lavender.structure.BlockStatePredicate; import io.wispforest.lavender.structure.LavenderStructures; import io.wispforest.lavender.structure.StructureTemplate; @@ -17,7 +18,7 @@ import io.wispforest.owo.ui.event.WindowResizeCallback; import io.wispforest.owo.ui.hud.Hud; import io.wispforest.owo.ui.util.Delta; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.RenderPipelines; @@ -45,14 +46,14 @@ public class StructureOverlayRenderer { private static final RenderPipeline PIPELINE = RenderPipelines.register( RenderPipeline.builder() .withLocation(Lavender.id("pipeline/structure_overlay")) - .withVertexShader("core/blit_screen") + .withVertexShader("core/screenquad") .withFragmentShader(Lavender.id("core/blit_alpha")) .withSampler("InSampler") .withBlend(BlendFunction.TRANSLUCENT) .withDepthWrite(false) .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST) .withColorWrite(true, true) - .withVertexFormat(VertexFormats.POSITION, VertexFormat.DrawMode.QUADS) + .withVertexFormat(VertexFormats.EMPTY, VertexFormat.DrawMode.TRIANGLES) .build() ); @@ -132,15 +133,14 @@ public static boolean hasPending() { public static void initialize() { Hud.add(HUD_COMPONENT_ID, () -> Containers.verticalFlow(Sizing.content(), Sizing.content()).gap(15).positioning(Positioning.relative(5, 100))); - WorldRenderEvents.LAST.register(context -> { + WorldRenderEvents.END_MAIN.register(context -> { if (!(Hud.getComponent(HUD_COMPONENT_ID) instanceof FlowLayout hudComponent)) { return; } - var matrices = context.matrixStack(); + var matrices = context.matrices(); matrices.push(); - - matrices.translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z); + matrices.translate(context.worldState().cameraRenderState.pos.negate()); var client = MinecraftClient.getInstance(); // prefer targeting the translucent framebuffer @@ -181,8 +181,10 @@ public static void initialize() { matrices.push(); matrices.translate(anchor.getX(), anchor.getY(), anchor.getZ()); + var world = ((WorldRendererAccessor)context.worldRenderer()).getWorld(); + structure.forEachPredicate((pos, predicate) -> { - var state = context.world().getBlockState(testPos.set(anchor).move(pos)).rotate(StructureTemplate.inverse(entry.rotation)); + var state = world.getBlockState(testPos.set(anchor).move(pos)).rotate(StructureTemplate.inverse(entry.rotation)); var result = predicate.test(state); if (result == BlockStatePredicate.Result.STATE_MATCH) { @@ -192,7 +194,7 @@ public static void initialize() { matrices.push(); matrices.translate(pos.getX(), pos.getY(), pos.getZ()); - client.getBlockRenderManager().renderDamage(state, testPos, context.world(), matrices, overlayConsumer); + client.getBlockRenderManager().renderDamage(state, testPos, world, matrices, overlayConsumer); matrices.pop(); } diff --git a/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java b/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java index 29c2531..7427801 100644 --- a/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java +++ b/src/main/java/io/wispforest/lavender/md/compiler/BookCompiler.java @@ -27,7 +27,7 @@ public class BookCompiler extends OwoUICompiler { - private static final Style UNICODE_FONT_STYLE = Style.EMPTY.withFont(MinecraftClient.UNICODE_FONT_ID); + private static final Style UNICODE_FONT_STYLE = Style.EMPTY.withFont(new StyleSpriteSource.Font(MinecraftClient.UNICODE_FONT_ID)); private final FlowLayout resultContainer = Containers.verticalFlow(Sizing.content(), Sizing.content()); private final ComponentSource bookComponentSource; diff --git a/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java b/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java index 7c8234c..30a4b89 100644 --- a/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java +++ b/src/main/java/io/wispforest/lavender/md/features/RecipeFeature.java @@ -123,8 +123,7 @@ public void registerTokens(TokenRegistrar registrar) { var recipe = LavenderClientRecipeCache.getOrFetchRecipe(recipeId); if (recipe.isEmpty()) return false; - //noinspection unchecked - tokens.add(new RecipeToken(recipeIdString, (RecipeEntry>) recipe.get())); + tokens.add(new RecipeToken(recipeIdString, (RecipeEntry>) recipe.get())); return true; }, '<'); } diff --git a/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java b/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java index 47d9d70..313aa87 100644 --- a/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java +++ b/src/main/java/io/wispforest/lavender/mixin/DrawContextMixin.java @@ -58,7 +58,7 @@ private void injectTooltipComponents(TextRenderer textRenderer, List= .95) { LavenderBookScreen.pushEntry(book, associatedEntry); diff --git a/src/main/java/io/wispforest/lavender/mixin/HeldItemRendererMixin.java b/src/main/java/io/wispforest/lavender/mixin/HeldItemRendererMixin.java index 8a4704c..b5ccfbb 100644 --- a/src/main/java/io/wispforest/lavender/mixin/HeldItemRendererMixin.java +++ b/src/main/java/io/wispforest/lavender/mixin/HeldItemRendererMixin.java @@ -6,7 +6,7 @@ import io.wispforest.lavender.client.OffhandBookRenderer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; @@ -29,11 +29,11 @@ private boolean injectMap(boolean original, AbstractClientPlayerEntity player, f } @Inject(method = "renderFirstPersonMap", at = @At("HEAD"), cancellable = true) - private void injectBook(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, ItemStack stack, CallbackInfo ci) { + private void injectBook(MatrixStack matrices, OrderedRenderCommandQueue queue, int light, ItemStack stack, CallbackInfo ci) { if (!(stack.getItem() instanceof LavenderBookItem)) return; ci.cancel(); - OffhandBookRenderer.render(matrices, light); + OffhandBookRenderer.render(matrices, queue, light); } } diff --git a/src/main/java/io/wispforest/lavender/mixin/access/WorldRendererAccessor.java b/src/main/java/io/wispforest/lavender/mixin/access/WorldRendererAccessor.java new file mode 100644 index 0000000..09472da --- /dev/null +++ b/src/main/java/io/wispforest/lavender/mixin/access/WorldRendererAccessor.java @@ -0,0 +1,13 @@ +package io.wispforest.lavender.mixin.access; + +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.world.ClientWorld; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(WorldRenderer.class) +public interface WorldRendererAccessor { + @Accessor("world") + @Nullable ClientWorld getWorld(); +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index de47a03..4074a0c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,39 +1,39 @@ { - "schemaVersion": 1, - "id": "lavender", - "version": "${version}", - "name": "Lavender", - "description": "Apparently Lavender and Patchouli are really similar-looking flowers. Oh yeah, also this is a Guidebook API", - "authors": [ - "glisco" - ], - "contact": { - "repo": "https://github.com/wisp-forest/lavender", - "homepage": "https://modrinth.com/project/lavender", - "sources": "https://github.com/wisp-forest/lavender", - "issues": "https://github.com/wisp-forest/lavender/issues" - }, - "license": "MIT", - "icon": "assets/lavender/icon.png", - "environment": "*", - "entrypoints": { - "client": [ - "io.wispforest.lavender.client.LavenderClient" - ], - "main": [ - "io.wispforest.lavender.Lavender" - ] - }, - "accessWidener": "lavender.accesswidener", - "mixins": [ - "lavender.mixins.json" - ], - "depends": { - "fabricloader": ">=0.15.0", - "fabric": "*", - "minecraft": ">=1.21.2", - "owo-lib": "*", - "lavender-md": ">=0.1.2", - "lavender-md-owo-ui": "*" - } + "schemaVersion": 1, + "id": "lavender", + "version": "${version}", + "name": "Lavender", + "description": "Apparently Lavender and Patchouli are really similar-looking flowers. Oh yeah, also this is a Guidebook API", + "authors": [ + "glisco" + ], + "contact": { + "repo": "https://github.com/wisp-forest/lavender", + "homepage": "https://modrinth.com/project/lavender", + "sources": "https://github.com/wisp-forest/lavender", + "issues": "https://github.com/wisp-forest/lavender/issues" + }, + "license": "MIT", + "icon": "assets/lavender/icon.png", + "environment": "*", + "entrypoints": { + "client": [ + "io.wispforest.lavender.client.LavenderClient" + ], + "main": [ + "io.wispforest.lavender.Lavender" + ] + }, + "accessWidener": "lavender.accesswidener", + "mixins": [ + "lavender.mixins.json" + ], + "depends": { + "fabricloader": ">=0.15.0", + "fabric": "*", + "minecraft": ">=1.21.2", + "owo-lib": "*", + "lavender-md": ">=0.1.2", + "lavender-md-owo-ui": "*" + } } diff --git a/src/main/resources/lavender.mixins.json b/src/main/resources/lavender.mixins.json index 915622d..75c069d 100644 --- a/src/main/resources/lavender.mixins.json +++ b/src/main/resources/lavender.mixins.json @@ -17,7 +17,8 @@ "MouseMixin", "ScreenMixin", "SimpleResourceReloadMixin", - "access.ClientAdvancementManagerAccessor" + "access.ClientAdvancementManagerAccessor", + "access.WorldRendererAccessor" ], "injectors": { "defaultRequire": 1 From 1afa69a4e8a7880cc144ab3e52a7bb84ff71d9df Mon Sep 17 00:00:00 2001 From: pizzacalz0ne Date: Sun, 23 Nov 2025 14:14:39 +1100 Subject: [PATCH 5/5] bump versions --- build.gradle | 2 +- gradle.properties | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a28e83d..d6906e8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.12-SNAPSHOT' + id 'fabric-loom' version '1.13-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index c6e313d..01f0525 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.jvmargs=-Xmx1G minecraft_base_version=1.21.10 minecraft_version=1.21.10 yarn_mappings=1.21.10+build.2 - loader_version=0.17.3 + loader_version=0.18.1 # Mod Properties mod_version = 0.1.15 @@ -15,7 +15,7 @@ org.gradle.jvmargs=-Xmx1G # Dependencies # check this on https://fabricmc.net/develop - fabric_version=0.137.0+1.21.10 + fabric_version=0.138.3+1.21.10 # https://maven.wispforest.io/#/releases/io/wispforest/owo-lib/ owo_version=0.12.24+1.21.9 @@ -24,4 +24,4 @@ org.gradle.jvmargs=-Xmx1G modmenu_version=16.0.0-rc.1 # https://maven.wispforest.io/#/releases/io/wispforest/lavender-md/core/ - lavender_md_version=0.1.3+1.21.10 + lavender_md_version=0.1.2+1.21.10