From 9e80f74663bd3ea4a11193cf67b2c586e087b910 Mon Sep 17 00:00:00 2001 From: Albazavr Date: Wed, 24 Jun 2026 15:44:32 +0300 Subject: [PATCH 1/6] Client classes port --- .../client/BakedMultiPartRenderers.java | 18 +- .../client/FoliageColorHandler.java | 10 +- .../client/LockedBiomeToast.java | 43 +++-- .../client/MagicPaintingAtlasInfo.java | 4 +- .../client/MissingAdvancementToast.java | 4 - .../client/MovingCicadaSoundInstance.java | 16 +- .../client/OptifineWarningScreen.java | 36 ++-- .../java/twilightforest/client/TFShaders.java | 144 +++------------- .../TextureGeneratorReloadListener.java | 118 ------------- .../client/TwilightForestRenderInfo.java | 35 +--- .../client/UncraftingRecipeBookComponent.java | 91 +++++++++- .../client/UncraftingScreen.java | 157 ++++++++++-------- .../client/particle/GhastTearParticle.java | 24 +-- .../client/particle/LogCoreParticle.java | 8 +- .../client/particle/SortingParticle.java | 8 +- .../particle/TransformationParticle.java | 8 +- .../client/properties/PotionFlaskDamage.java | 5 +- 17 files changed, 296 insertions(+), 433 deletions(-) delete mode 100644 src/main/java/twilightforest/client/TextureGeneratorReloadListener.java diff --git a/src/main/java/twilightforest/client/BakedMultiPartRenderers.java b/src/main/java/twilightforest/client/BakedMultiPartRenderers.java index 3cf0f0e96c..5d9e5d3b67 100644 --- a/src/main/java/twilightforest/client/BakedMultiPartRenderers.java +++ b/src/main/java/twilightforest/client/BakedMultiPartRenderers.java @@ -1,10 +1,11 @@ package twilightforest.client; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.NoopRenderer; import net.minecraft.resources.Identifier; -import net.minecraft.util.LazyLoadedValue; import twilightforest.client.model.TFModelLayers; import twilightforest.client.model.entity.HydraHeadModel; import twilightforest.client.model.entity.HydraNeckModel; @@ -19,19 +20,18 @@ import java.util.HashMap; import java.util.Map; -@SuppressWarnings("deprecation") public class BakedMultiPartRenderers { - private static final Map>> renderers = new HashMap<>(); + private static final Map>> renderers = new HashMap<>(); public static void bakeMultiPartRenderers(EntityRendererProvider.Context context) { - renderers.put(TFPart.RENDERER, new LazyLoadedValue<>(() -> new NoopRenderer<>(context))); - renderers.put(HydraHead.RENDERER, new LazyLoadedValue<>(() -> new HydraHeadRenderer<>(context, new HydraHeadModel<>(context.bakeLayer(TFModelLayers.HYDRA_HEAD))))); - renderers.put(HydraNeck.RENDERER, new LazyLoadedValue<>(() -> new HydraNeckRenderer<>(context, new HydraNeckModel(context.bakeLayer(TFModelLayers.HYDRA_NECK))))); - renderers.put(SnowQueenIceShield.RENDERER, new LazyLoadedValue<>(() -> new SnowQueenIceShieldRenderer<>(context))); - renderers.put(NagaSegment.RENDERER, new LazyLoadedValue<>(() -> new NagaSegmentRenderer<>(context, new NagaModel<>(context.bakeLayer(TFModelLayers.NAGA_BODY))))); + renderers.put(TFPart.RENDERER, Suppliers.memoize(() -> new NoopRenderer<>(context))); + renderers.put(HydraHead.RENDERER, Suppliers.memoize(() -> new HydraHeadRenderer(context, new HydraHeadModel(context.bakeLayer(TFModelLayers.HYDRA_HEAD))))); + renderers.put(HydraNeck.RENDERER, Suppliers.memoize(() -> new HydraNeckRenderer(context, new HydraNeckModel(context.bakeLayer(TFModelLayers.HYDRA_NECK))))); + renderers.put(SnowQueenIceShield.RENDERER, Suppliers.memoize(() -> new SnowQueenIceShieldRenderer(context))); + renderers.put(NagaSegment.RENDERER, Suppliers.memoize(() -> new NagaSegmentRenderer(context, new NagaModel<>(context.bakeLayer(TFModelLayers.NAGA_BODY))))); } - public static EntityRenderer lookup(Identifier location) { + public static EntityRenderer lookup(Identifier location) { return renderers.get(location).get(); } } diff --git a/src/main/java/twilightforest/client/FoliageColorHandler.java b/src/main/java/twilightforest/client/FoliageColorHandler.java index ad4911e80d..357bee7dd4 100644 --- a/src/main/java/twilightforest/client/FoliageColorHandler.java +++ b/src/main/java/twilightforest/client/FoliageColorHandler.java @@ -2,12 +2,12 @@ import com.google.common.collect.MapMaker; import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.biome.Biome; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.event.entity.EntityLeaveLevelEvent; +import org.jetbrains.annotations.NotNull; import tamaized.beanification.Autowired; import tamaized.beanification.Component; import tamaized.beanification.PostConstruct; @@ -23,7 +23,7 @@ public final class FoliageColorHandler { @Autowired private BiomeColorAlgorithms biomeColorAlgorithms; - private final Map, Handler> REGISTRY = new HashMap<>() {{ + private final Map, Handler> REGISTRY = new HashMap<>() {{ put(TFBiomes.SPOOKY_FOREST, (o, x, z) -> biomeColorAlgorithms.spookyFoliage(x, z)); put(TFBiomes.ENCHANTED_FOREST, (o, x, z) -> biomeColorAlgorithms.enchanted(o, (int) x, (int) z)); put(TFBiomes.DARK_FOREST_CENTER, (o, x, z) -> biomeColorAlgorithms.darkForestCenterFoliage(x, z)); @@ -47,17 +47,13 @@ public int get(int o, Biome biome, double x, double z) { if (handler == null) { handler = REGISTRY.getOrDefault( Minecraft.getInstance().level == null ? null : - Minecraft.getInstance().level.registryAccess().registryOrThrow(Registries.BIOME).getResourceKey(biome).orElse(null), + Minecraft.getInstance().level.registryAccess().lookupOrThrow(Registries.BIOME).getResourceKey(biome).orElse(null), Handler.DEFAULT); HANDLES.put(biome, handler); } return handler.apply(o, x, z); } - public static int getTintColorAtPosition(BlockPos pos) { - - } - @FunctionalInterface private interface Handler { Handler DEFAULT = (o, x, z) -> o; diff --git a/src/main/java/twilightforest/client/LockedBiomeToast.java b/src/main/java/twilightforest/client/LockedBiomeToast.java index 6d367b7415..ae28c3bf5a 100644 --- a/src/main/java/twilightforest/client/LockedBiomeToast.java +++ b/src/main/java/twilightforest/client/LockedBiomeToast.java @@ -1,25 +1,48 @@ package twilightforest.client; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.toasts.Toast; -import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.gui.components.toasts.ToastManager; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; -public record LockedBiomeToast(ItemStack item) implements Toast { - +public class LockedBiomeToast implements Toast { private static final Component TITLE = Component.translatable("misc.twilightforest.biome_locked"); private static final Component DESCRIPTION = Component.translatable("misc.twilightforest.biome_locked_2"); private static final Identifier BACKGROUND_SPRITE = Identifier.withDefaultNamespace("toast/advancement"); + private final ItemStack item; + private Toast.Visibility wantedVisibility = Toast.Visibility.SHOW; + + public LockedBiomeToast(ItemStack item) { + this.item = item; + } + + public ItemStack item() { + return this.item; + } + + @Override + public Toast.Visibility getWantedVisibility() { + return this.wantedVisibility; + } + + @Override + public void update(ToastManager toastManager, long timer) { + if (timer >= 10000L) { + this.wantedVisibility = Toast.Visibility.HIDE; + } + } + @Override - public Visibility render(GuiGraphics graphics, ToastComponent component, long timer) { - graphics.blitSprite(BACKGROUND_SPRITE, 0, 0, this.width(), this.height()); - graphics.renderFakeItem(this.item(), 6, 8); - graphics.drawString(component.getMinecraft().font, TITLE, 25, 7, -256, false); - graphics.drawString(component.getMinecraft().font, DESCRIPTION, 25, 18, 16777215, false); + public void extractRenderState(GuiGraphicsExtractor graphics, Font font, long timer) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, BACKGROUND_SPRITE, 0, 0, this.width(), this.height()); - return timer >= 10000L ? Toast.Visibility.HIDE : Toast.Visibility.SHOW; + graphics.fakeItem(this.item(), 6, 8); + graphics.text(font, TITLE, 25, 7, -256, false); + graphics.text(font, DESCRIPTION, 25, 18, 16777215, false); } } diff --git a/src/main/java/twilightforest/client/MagicPaintingAtlasInfo.java b/src/main/java/twilightforest/client/MagicPaintingAtlasInfo.java index 15ea50fdba..bc9d38f8de 100644 --- a/src/main/java/twilightforest/client/MagicPaintingAtlasInfo.java +++ b/src/main/java/twilightforest/client/MagicPaintingAtlasInfo.java @@ -5,7 +5,7 @@ public class MagicPaintingAtlasInfo { public final static String MAGIC_PAINTING_PATH = "magic_paintings"; - public static final Identifier ATLAS_LOCATION = TwilightForestMod.prefix("textures/atlas/magic_paintings.png"); - public static final Identifier ATLAS_INFO_LOCATION = Identifier.withDefaultNamespace(MAGIC_PAINTING_PATH); + public static final Identifier ATLAS_LOCATION = TwilightForestMod.prefix(MAGIC_PAINTING_PATH); + public static final Identifier ATLAS_INFO_LOCATION = TwilightForestMod.prefix(MAGIC_PAINTING_PATH); public static final Identifier BACK_SPRITE_LOCATION = TwilightForestMod.prefix(MAGIC_PAINTING_PATH + "/back"); } \ No newline at end of file diff --git a/src/main/java/twilightforest/client/MissingAdvancementToast.java b/src/main/java/twilightforest/client/MissingAdvancementToast.java index 56820a60fa..50cb63291e 100644 --- a/src/main/java/twilightforest/client/MissingAdvancementToast.java +++ b/src/main/java/twilightforest/client/MissingAdvancementToast.java @@ -1,17 +1,13 @@ package twilightforest.client; -import com.mojang.blaze3d.pipeline.RenderPipeline; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.toasts.Toast; -import net.minecraft.client.gui.components.toasts.ToastComponent; import net.minecraft.client.gui.components.toasts.ToastManager; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ItemStackTemplate; import twilightforest.init.TFBlocks; public class MissingAdvancementToast implements Toast { diff --git a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java index 5c520903ff..a4d68f7e65 100644 --- a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java +++ b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java @@ -27,13 +27,15 @@ public MovingCicadaSoundInstance(LivingEntity entity) { @Override public void tick() { - if (!this.wearer.isRemoved() && (this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem()) || this.isWearingCicadaCurio())) { - this.x = (float) this.wearer.getX(); - this.y = (float) this.wearer.getY(); - this.z = (float) this.wearer.getZ(); - } else { - this.stop(); - } + if (!this.wearer.isRemoved() && (this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem()) || this.isWearingCicadaCurio())) { + if (!this.wearer.isRemoved() && (this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem()))) { + this.x = (float) this.wearer.getX(); + this.y = (float) this.wearer.getY(); + this.z = (float) this.wearer.getZ(); + } else { + this.stop(); + } + } } private boolean isWearingCicadaCurio() { diff --git a/src/main/java/twilightforest/client/OptifineWarningScreen.java b/src/main/java/twilightforest/client/OptifineWarningScreen.java index 464599b477..08175f8e24 100644 --- a/src/main/java/twilightforest/client/OptifineWarningScreen.java +++ b/src/main/java/twilightforest/client/OptifineWarningScreen.java @@ -2,21 +2,24 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.TextAlignment; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineLabel; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.network.chat.*; import org.jetbrains.annotations.Nullable; -public class OptifineWarningScreen extends Screen { +import java.net.URI; +public class OptifineWarningScreen extends Screen { private final Screen lastScreen; private int ticksUntilEnable = 20 * 10; private MultiLineLabel message = MultiLineLabel.EMPTY; private MultiLineLabel suggestions = MultiLineLabel.EMPTY; private static final Component text = Component.translatable("gui.twilightforest.optifine.message"); - private static final MutableComponent url = Component.translatable("gui.twilightforest.optifine.suggestions").withStyle(style -> style.withColor(ChatFormatting.GREEN).applyFormat(ChatFormatting.UNDERLINE).withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://github.com/NordicGamerFE/usefulmods"))); + private static final MutableComponent url = Component.translatable("gui.twilightforest.optifine.suggestions").withStyle(style -> style.withColor(ChatFormatting.GREEN).applyFormat(ChatFormatting.UNDERLINE).withClickEvent(new ClickEvent.OpenUrl(URI.create("https://github.com/NordicGamerFE/usefulmods")))); private Button exitButton; public OptifineWarningScreen(Screen screen) { @@ -32,7 +35,7 @@ public Component getNarrationMessage() { @Override protected void init() { super.init(); - this.exitButton = this.addRenderableWidget(Button.builder(CommonComponents.GUI_PROCEED, (pressed) -> Minecraft.getInstance().setScreen(this.lastScreen)).bounds(this.width / 2 - 75, this.height * 3 / 4, 150, 20).build()); + this.exitButton = this.addRenderableWidget(Button.builder(CommonComponents.GUI_PROCEED, (_) -> Minecraft.getInstance().setScreen(this.lastScreen)).bounds(this.width / 2 - 75, this.height * 3 / 4, 150, 20).build()); this.exitButton.active = false; this.message = MultiLineLabel.create(this.font, text, this.width - 50); @@ -40,14 +43,14 @@ protected void init() { } @Override - public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(graphics, mouseX, mouseY, partialTicks); - graphics.drawCenteredString(this.font, this.title, this.width / 2, 30, 16777215); - this.message.renderCentered(graphics, this.width / 2, 70); - this.suggestions.renderCentered(graphics, this.width / 2, 160); - super.render(graphics, mouseX, mouseY, partialTicks); + public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float partialTicks) { + this.extractBackground(graphics, mouseX, mouseY, partialTicks); + graphics.centeredText(this.font, this.title, this.width / 2, 30, 16777215); + this.message.visitLines(TextAlignment.CENTER, this.width / 2, 70, this.font.lineHeight, graphics.textRenderer()); + this.suggestions.visitLines(TextAlignment.CENTER, this.width / 2, 160, this.font.lineHeight, graphics.textRenderer()); + super.extractRenderState(graphics, mouseX, mouseY, partialTicks); - this.exitButton.render(graphics, mouseX, mouseY, partialTicks); + this.exitButton.extractRenderState(graphics, mouseX, mouseY, partialTicks); } @Override @@ -69,16 +72,17 @@ public void onClose() { } @Override - public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) { + double pMouseX = event.x(); + double pMouseY = event.y(); if (pMouseY > 160 && pMouseY < 170) { Style style = this.getClickedComponentStyleAt((int) pMouseX); - if (style != null && style.getClickEvent() != null && style.getClickEvent().getAction() == ClickEvent.Action.OPEN_URL) { - this.handleComponentClicked(style); + if (style != null && style.getClickEvent() != null && style.getClickEvent().action() == ClickEvent.Action.OPEN_URL) { return false; } } - return super.mouseClicked(pMouseX, pMouseY, pButton); + return super.mouseClicked(event, doubleClick); } @Nullable @@ -86,6 +90,6 @@ private Style getClickedComponentStyleAt(int xPos) { int wid = Minecraft.getInstance().font.width(url); int left = this.width / 2 - wid / 2; int right = this.width / 2 + wid / 2; - return xPos >= left && xPos <= right ? Minecraft.getInstance().font.getSplitter().componentStyleAtWidth(url, xPos - left) : null; + return xPos >= left && xPos <= right ? url.getStyle() : null; } } diff --git a/src/main/java/twilightforest/client/TFShaders.java b/src/main/java/twilightforest/client/TFShaders.java index 7952d1178e..acc3fe1786 100644 --- a/src/main/java/twilightforest/client/TFShaders.java +++ b/src/main/java/twilightforest/client/TFShaders.java @@ -1,124 +1,34 @@ package twilightforest.client; -import com.mojang.blaze3d.shaders.Uniform; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; -import net.minecraft.client.renderer.ShaderInstance; +import com.mojang.blaze3d.pipeline.DepthStencilState; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.platform.CompareOp; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.client.renderer.rendertype.RenderSetup; +import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.resources.Identifier; -import net.minecraft.server.packs.resources.ResourceProvider; -import net.neoforged.neoforge.client.event.RegisterShadersEvent; -import org.jetbrains.annotations.Nullable; -import twilightforest.TwilightForestMod; +import twilightforest.client.renderer.TFRenderPipelines; -import java.io.IOException; +import java.util.Optional; public class TFShaders { - - public static ShaderInstance RED_THREAD; - public static PositionAwareShaderInstance AURORA; - - public static void registerShaders(RegisterShadersEvent event) { - try { - event.registerShader(new ShaderInstance(event.getResourceProvider(), TwilightForestMod.prefix("red_thread/red_thread"), DefaultVertexFormat.BLOCK), - shader -> RED_THREAD = shader); - event.registerShader(new PositionAwareShaderInstance(event.getResourceProvider(), TwilightForestMod.prefix("aurora/aurora"), DefaultVertexFormat.POSITION_COLOR), - shader -> AURORA = (PositionAwareShaderInstance) shader); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static class BindableShaderInstance extends ShaderInstance { - - private ShaderInstance last; - - public BindableShaderInstance(ResourceProvider p_173336_, Identifier shaderLocation, VertexFormat p_173338_) throws IOException { - super(p_173336_, shaderLocation, p_173338_); - } - - ShaderInstance getSelf() { - return this; - } - - public final void bind(@Nullable Runnable exec) { - last = RenderSystem.getShader(); - RenderSystem.setShader(this::getSelf); - if (exec != null) - exec.run(); - apply(); - } - - public final void runThenClear(Runnable exec) { - exec.run(); - clear(); - RenderSystem.setShader(() -> last); - last = null; - } - - public final void invokeThenClear(@Nullable Runnable execBind, Runnable execPost) { - bind(execBind); - runThenClear(execPost); - } - - public final void invokeThenClear(Runnable execPost) { - invokeThenClear(null, execPost); - } - - public final void invokeThenEndTesselator(@Nullable Runnable execBind, BufferBuilder builder) { - invokeThenClear(execBind, () -> BufferUploader.drawWithShader(builder.buildOrThrow())); - } - - public final void invokeThenEndTesselator(BufferBuilder builder) { - invokeThenClear(() -> BufferUploader.drawWithShader(builder.buildOrThrow())); - } - - } - - public static class PositionAwareShaderInstance extends BindableShaderInstance { - - @Nullable - public final Uniform SEED; - - @Nullable - public final Uniform POSITION; - - public PositionAwareShaderInstance(ResourceProvider p_173336_, Identifier shaderLocation, VertexFormat p_173338_) throws IOException { - super(p_173336_, shaderLocation, p_173338_); - SEED = getUniform("SeedContext"); - POSITION = getUniform("PositionContext"); - } - - public final void setValue(int seed, float x, float y, float z) { - if (SEED != null) { - SEED.set(seed); - } - if (POSITION != null) { - POSITION.set(x, y, z); - } - } - - public final void setValueBindApply(int seed, float x, float y, float z) { - bind(() -> setValue(seed, x, y, z)); - } - - public final void reset() { - setValue(0, 0, 0, 0); - } - - public final void resetClear() { - runThenClear(this::reset); - } - - public final void invokeThenClear(int seed, float x, float y, float z, Runnable exec) { - setValueBindApply(seed, x, y, z); - exec.run(); - resetClear(); - } - - public final void invokeThenEndTesselator(int seed, float x, float y, float z, BufferBuilder builder) { - invokeThenClear(seed, x, y, z, () -> BufferUploader.drawWithShader(builder.buildOrThrow())); - } - - } - + private static final DepthStencilState TRANSLUCENT_DEPTH = new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, false); + + private static final RenderPipeline AURORA_PIPELINE = RenderPipeline.builder(RenderPipelines.DEBUG_FILLED_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath("twilightforest", "aurora/aurora")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withDepthStencilState(Optional.of(TRANSLUCENT_DEPTH)) + .build(); + + public static final RenderType AURORA = RenderType.create( + "twilightforest_aurora", + RenderSetup.builder(AURORA_PIPELINE).createRenderSetup() + ); + + public static final RenderType RED_THREAD = RenderType.create( + "twilightforest_red_thread", + RenderSetup.builder(TFRenderPipelines.RED_THREAD).createRenderSetup() + ); } diff --git a/src/main/java/twilightforest/client/TextureGeneratorReloadListener.java b/src/main/java/twilightforest/client/TextureGeneratorReloadListener.java deleted file mode 100644 index 1b965eb8ce..0000000000 --- a/src/main/java/twilightforest/client/TextureGeneratorReloadListener.java +++ /dev/null @@ -1,118 +0,0 @@ -package twilightforest.client; - -import com.mojang.blaze3d.platform.NativeImage; -import com.mojang.blaze3d.platform.TextureUtil; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.texture.AbstractTexture; -import net.minecraft.resources.Identifier; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.server.packs.resources.ResourceManagerReloadListener; -import net.minecraft.world.entity.vehicle.Boat; -import twilightforest.TwilightForestMod; - -import java.io.IOException; -import java.io.InputStream; -import java.util.EnumMap; -import java.util.concurrent.atomic.AtomicReference; - -public class TextureGeneratorReloadListener implements ResourceManagerReloadListener { - public static final TextureGeneratorReloadListener INSTANCE = new TextureGeneratorReloadListener(); - private static final EnumMap BOAT_CACHE = new EnumMap<>(Boat.Type.class); - private static final AtomicReference ref = new AtomicReference<>(); - - @Override - public void onResourceManagerReload(ResourceManager manager) { - // Get a default boat chest texture - Identifier oak = getTextureLocation(Boat.Type.OAK); - - manager.getResource(oak).ifPresent(vanillaResource -> { - try (InputStream vanillaStream = vanillaResource.open()) { - try (NativeImage vanillaImage = NativeImage.read(vanillaStream)) { - int defaultScale = 128; - int vanillaScale = vanillaImage.getWidth() / defaultScale; - for (Boat.Type type : Boat.Type.values()) { - Identifier location = getTextureLocation(type); - if (location.getNamespace().equals(TwilightForestMod.ID)) { // We only want to do this to our boats - manager.getResource(location).ifPresent(tfResource -> { - try (InputStream tfStream = tfResource.open()) { - try (NativeImage tfImage = NativeImage.read(tfStream)) { - int tfScale = tfImage.getWidth() / defaultScale; - - for (int x = 0; x < 48 * tfScale; x++) { - for (int y = 58 * tfScale; y < 96 * tfScale; y++) { - // If the loaded tf boat chest texture has non-transparent pixels below the boat section of the texture, return - if (tfImage.getPixelRGBA(x, y) != 0x00000000) return; - } - } - - if (vanillaScale > tfScale) { - try (NativeImage newImage = new NativeImage(defaultScale * vanillaScale, defaultScale * vanillaScale, false)) { - newImage.copyFrom(vanillaImage); - for (int x = 0; x < 102 * vanillaScale; x++) { - for (int y = 0; y < 52 * vanillaScale; y++) { - newImage.setPixelRGBA(x, y, tfImage.getPixelRGBA(x / (vanillaScale / tfScale), y / (vanillaScale / tfScale))); - } - } - - ref.set(newImage); - - if (BOAT_CACHE.containsKey(type)) { - BOAT_CACHE.get(type).load(manager); - } else { - AbstractTexture texture = new AbstractTexture() { - @Override - public void load(ResourceManager resourceManager) { - if (ref.get() == null) - return; - TextureUtil.prepareImage(this.getId(), 0, ref.get().getWidth(), ref.get().getHeight()); - ref.get().upload(0, 0, 0, 0, 0, ref.get().getWidth(), ref.get().getHeight(), false, false, false, true); - } - }; - Minecraft.getInstance().getTextureManager().register(location, texture); - BOAT_CACHE.put(type, texture); - } - } - } else { - for (int x = 0; x < 48 * tfScale; x++) { - for (int y = 58 * tfScale; y < 96 * tfScale; y++) { - tfImage.setPixelRGBA(x, y, vanillaImage.getPixelRGBA(x / (tfScale / vanillaScale), y / (tfScale / vanillaScale))); - } - } - - ref.set(tfImage); - - if (BOAT_CACHE.containsKey(type)) { - BOAT_CACHE.get(type).load(manager); - } else { - AbstractTexture texture = new AbstractTexture() { - @Override - public void load(ResourceManager resourceManager) { - if (ref.get() == null) - return; - TextureUtil.prepareImage(this.getId(), 0, ref.get().getWidth(), ref.get().getHeight()); - ref.get().upload(0, 0, 0, 0, 0, ref.get().getWidth(), ref.get().getHeight(), false, false, false, true); - } - }; - Minecraft.getInstance().getTextureManager().register(location, texture); - BOAT_CACHE.put(type, texture); - } - } - } - } catch (IOException e) { - // Fail silently, no boat texture bullshit here - } - }); - } - } - } - } catch (IOException e) { - // Fail silently, no boat texture bullshit here - } - }); - ref.set(null); - } - - private static Identifier getTextureLocation(Boat.Type type) { - return Identifier.parse(type.getName()).withPrefix("textures/entity/chest_boat/").withSuffix(".png"); - } -} diff --git a/src/main/java/twilightforest/client/TwilightForestRenderInfo.java b/src/main/java/twilightforest/client/TwilightForestRenderInfo.java index 6404162481..6ede74a48b 100644 --- a/src/main/java/twilightforest/client/TwilightForestRenderInfo.java +++ b/src/main/java/twilightforest/client/TwilightForestRenderInfo.java @@ -3,26 +3,17 @@ import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.DimensionSpecialEffects; -import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.client.renderer.state.level.SkyRenderState; import net.minecraft.client.renderer.state.level.WeatherRenderState; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.biome.Biome; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.client.CustomSkyboxRenderer; import net.neoforged.neoforge.client.CustomWeatherEffectRenderer; import org.jetbrains.annotations.Nullable; -import org.joml.Matrix4f; import org.joml.Matrix4fc; import twilightforest.client.renderer.TFSkyRenderer; import twilightforest.client.renderer.TFWeatherRenderer; -import twilightforest.init.TFBiomes; - -import java.util.Optional; public class TwilightForestRenderInfo implements CustomSkyboxRenderer, CustomWeatherEffectRenderer { @@ -42,28 +33,6 @@ public class TwilightForestRenderInfo implements CustomSkyboxRenderer, CustomWea // return biomeFogColor.multiply(daylight * 0.94F + 0.06F, (daylight * 0.94F + 0.06F), (daylight * 0.91F + 0.09F)); // } - @Override - public boolean isFoggyAt(int x, int y) { // true = nearFog - Player player = Minecraft.getInstance().player; - - if (player != null) { - Optional> biome = player.level().getBiome(player.blockPosition()).unwrapKey(); - if (biome.isPresent()) { - boolean spooky = biome.get() == TFBiomes.SPOOKY_FOREST; - - if (player.position().y > 20 && !spooky) { - return false; // If player is above the dark forest then no need to make it so spooky. The darkwood leaves cover everything as low as y42. - } - - return spooky || biome.get() == TFBiomes.DARK_FOREST || biome.get() == TFBiomes.DARK_FOREST_CENTER; - } - } - - return false; - - //Make the fog on these biomes much much darker, maybe pitch black even. Do we keep this harsher fog underground too? - } - @Override public boolean renderSky(LevelRenderState levelRenderState, SkyRenderState skyRenderState, Matrix4fc modelViewMatrix, Runnable setupFog) { if (this.skyRenderer == null) { @@ -74,11 +43,11 @@ public boolean renderSky(LevelRenderState levelRenderState, SkyRenderState skyRe @Override public boolean renderSnowAndRain(LevelRenderState levelRenderState, WeatherRenderState weatherRenderState, MultiBufferSource bufferSource, Vec3 camPos) { - return TFWeatherRenderer.renderSnowAndRain(level, ticks, partialTick, lightTexture, new Vec3(camX, camY, camZ)); + return TFWeatherRenderer.renderSnowAndRain(Minecraft.getInstance().level, Minecraft.getInstance().levelRenderer.getTicks(), Minecraft.getInstance().getDeltaTracker().getGameTimeDeltaTicks(), camPos); } @Override public boolean tickRain(ClientLevel level, int ticks, Camera camera) { - return TFWeatherRenderer.tickRain(level, ticks, camera.getBlockPosition()); + return TFWeatherRenderer.tickRain(level, ticks, camera.blockPosition()); } } diff --git a/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java b/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java index be413f853b..d3ec16906c 100644 --- a/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java +++ b/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java @@ -1,21 +1,98 @@ package twilightforest.client; +import net.minecraft.client.gui.components.WidgetSprites; +import net.minecraft.client.gui.screens.recipebook.GhostSlots; import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; +import net.minecraft.client.gui.screens.recipebook.RecipeCollection; +import net.minecraft.core.Holder; +import net.minecraft.network.chat.Component; +import net.minecraft.util.context.ContextMap; +import net.minecraft.world.entity.player.StackedItemContents; +import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import twilightforest.inventory.UncraftingPlaceRecipe; import java.util.List; -public class UncraftingRecipeBookComponent extends RecipeBookComponent implements UncraftingPlaceRecipe { +public class UncraftingRecipeBookComponent extends RecipeBookComponent<@NotNull RecipeBookMenu> implements UncraftingPlaceRecipe { + @Nullable + private GhostSlots currentGhostSlots = new GhostSlots(() -> 0); + + public UncraftingRecipeBookComponent(RecipeBookMenu menu, List list) { + super(menu, list); + } + + @Override + protected WidgetSprites getFilterButtonTextures() { + return RecipeBookComponent.RECIPE_BUTTON_SPRITES; + } + + + @Override + protected boolean isCraftingSlot(Slot slot) { + return slot.index >= 11 && slot.index <= 19; + } + + @Override + protected void selectMatchingRecipes(RecipeCollection recipeCollection, StackedItemContents stackedItemContents) { + recipeCollection.selectRecipes(stackedItemContents, _ -> true); + this.recipesUpdated(); + } + + + @Override + protected Component getRecipeFilterName() { + return Component.translatable("gui.recipebook.toggleRecipes.craftable"); + } + + @Override + protected void fillGhostRecipe(GhostSlots ghostSlots, RecipeDisplay recipeDisplay, ContextMap contextMap) { + this.currentGhostSlots = ghostSlots; + + Slot resultSlot = this.menu.slots.get(1); + SlotDisplay resultDisplay = recipeDisplay.result(); + + ghostSlots.setResult(resultSlot, contextMap, resultDisplay); + + List ingredients = recipeDisplay.craftingStation().resolveForStacks(contextMap); + int matrixStartSlot = 11; + + for (int i = 0; i < ingredients.size(); i++) { + if (i >= 9) break; + + Slot inputSlot = this.menu.slots.get(matrixStartSlot + i); + ItemStack ingredientDisplay = ingredients.get(i); + + if (!ingredientDisplay.isEmpty()) { + ghostSlots.setInput(inputSlot, contextMap, new SlotDisplay.ItemStackSlotDisplay(ItemStackTemplate.fromNonEmptyStack(ingredientDisplay))); + } + } + + this.currentGhostSlots = null; + } @Override - public void setupGhostRecipe(RecipeHolder recipe, List slots) { - ItemStack itemstack = recipe.value().getResultItem(this.minecraft.level.registryAccess()); - this.ghostRecipe.setRecipe(recipe); - this.ghostRecipe.addIngredient(Ingredient.of(itemstack), slots.get(1).x, slots.get(1).y); - this.placeRecipe(this.menu.getGridWidth(), this.menu.getGridHeight(), this.menu.getResultSlotIndex(), recipe, recipe.value().getIngredients().iterator(), 0); + public void addItemToSlot(Ingredient ingredient, int slotIndex, int maxAmount, int gridY, int gridX) { + if (currentGhostSlots != null && !ingredient.isEmpty()) { + Slot targetSlot = this.menu.slots.get(slotIndex); + + List> items = ingredient.getValues().stream().toList(); + if (!items.isEmpty()) { + Item item = items.getFirst().value(); + ItemStack stack = new ItemStack(item); + ItemStackTemplate template = ItemStackTemplate.fromNonEmptyStack(stack); + SlotDisplay.ItemStackSlotDisplay display = new SlotDisplay.ItemStackSlotDisplay(template); + + this.currentGhostSlots.setInput(targetSlot, ContextMap.EMPTY, display); + } + } } } diff --git a/src/main/java/twilightforest/client/UncraftingScreen.java b/src/main/java/twilightforest/client/UncraftingScreen.java index c40a68fe65..3df97f80fa 100644 --- a/src/main/java/twilightforest/client/UncraftingScreen.java +++ b/src/main/java/twilightforest/client/UncraftingScreen.java @@ -1,32 +1,41 @@ package twilightforest.client; -import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.ImageButton; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; +import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; import net.minecraft.client.gui.screens.recipebook.RecipeUpdateListener; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.Identifier; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; +import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.network.PacketDistributor; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.neoforged.neoforge.client.network.ClientPacketDistributor; +import org.jetbrains.annotations.NotNull; import twilightforest.TwilightForestMod; import twilightforest.config.TFConfig; -import twilightforest.data.tags.ItemTagGenerator; import twilightforest.inventory.UncraftingMenu; import twilightforest.network.UncraftingGuiPacket; +import twilightforest.tags.TFItemTags; -public class UncraftingScreen extends AbstractContainerScreen implements RecipeUpdateListener { +import java.util.List; + +public class UncraftingScreen extends AbstractContainerScreen<@NotNull UncraftingMenu> implements RecipeUpdateListener { private static final Identifier TEXTURE = TwilightForestMod.getGuiTexture("guigoblintinkering.png"); - private final RecipeBookComponent recipeBookComponent = new UncraftingRecipeBookComponent(); + private final RecipeBookComponent<@NotNull RecipeBookMenu> recipeBookComponent = new UncraftingRecipeBookComponent(menu, List.of()); private boolean widthTooNarrow; public UncraftingScreen(UncraftingMenu container, Inventory player, Component name) { @@ -38,7 +47,7 @@ protected void init() { super.init(); this.widthTooNarrow = this.width < 379; - this.recipeBookComponent.init(this.width, this.height, this.minecraft, this.widthTooNarrow, this.menu); + this.recipeBookComponent.init(this.width, this.height, this.minecraft, this.widthTooNarrow); this.leftPos = this.recipeBookComponent.updateScreenPosition(this.width, this.imageWidth); this.addRenderableWidget(new ImageButton(this.leftPos + 145, this.topPos + 7, 20, 18, RecipeBookComponent.RECIPE_BUTTON_SPRITES, button -> { this.recipeBookComponent.toggleVisibility(); @@ -48,36 +57,36 @@ protected void init() { this.setInitialFocus(this.recipeBookComponent); this.addRenderableWidget(new CycleButton(this.leftPos + 40, this.topPos + 22, true, button -> { - PacketDistributor.sendToServer(new UncraftingGuiPacket(0)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(0)); this.menu.unrecipeInCycle++; this.menu.slotsChanged(this.menu.tinkerInput); }, Component.translatable("container.twilightforest.uncrafting_table.cycle_next_uncraft"))); this.addRenderableWidget(new CycleButton(this.leftPos + 40, this.topPos + 55, false, button -> { - PacketDistributor.sendToServer(new UncraftingGuiPacket(1)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(1)); this.menu.unrecipeInCycle--; this.menu.slotsChanged(this.menu.tinkerInput); }, Component.translatable("container.twilightforest.uncrafting_table.cycle_back_uncraft"))); if (!TFConfig.disableIngredientSwitching) { this.addRenderableWidget(new CycleButtonMini(this.leftPos + 27, this.topPos + 56, true, button -> { - PacketDistributor.sendToServer(new UncraftingGuiPacket(2)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(2)); this.menu.ingredientsInCycle++; this.menu.slotsChanged(this.menu.tinkerInput); }, Component.translatable("container.twilightforest.uncrafting_table.cycle_next_ingredient"))); this.addRenderableWidget(new CycleButtonMini(this.leftPos + 27, this.topPos + 63, false, button -> { - PacketDistributor.sendToServer(new UncraftingGuiPacket(3)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(3)); this.menu.ingredientsInCycle--; this.menu.slotsChanged(this.menu.tinkerInput); }, Component.translatable("container.twilightforest.uncrafting_table.cycle_back_ingredient"))); } this.addRenderableWidget(new CycleButton(this.leftPos + 121, this.topPos + 22, true, button -> { - PacketDistributor.sendToServer(new UncraftingGuiPacket(4)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(4)); this.menu.recipeInCycle++; this.menu.slotsChanged(this.menu.assemblyMatrix); }, Component.translatable("container.twilightforest.uncrafting_table.cycle_next_recipe"))); this.addRenderableWidget(new CycleButton(this.leftPos + 121, this.topPos + 55, false, button -> { - PacketDistributor.sendToServer(new UncraftingGuiPacket(5)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(5)); this.menu.recipeInCycle--; this.menu.slotsChanged(this.menu.assemblyMatrix); }, Component.translatable("container.twilightforest.uncrafting_table.cycle_back_recipe"))); @@ -97,10 +106,10 @@ public boolean mouseScrolled(double x, double y, double vertScroll, double horiz if (!TFConfig.disableIngredientSwitching) { if (x > this.leftPos + 27 && x < this.leftPos + 33 && y > this.topPos + 56 && y < this.topPos + 69) { if (vertScroll > 0) { - PacketDistributor.sendToServer(new UncraftingGuiPacket(2)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(2)); this.menu.ingredientsInCycle++; } else { - PacketDistributor.sendToServer(new UncraftingGuiPacket(3)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(3)); this.menu.ingredientsInCycle--; } this.menu.slotsChanged(this.menu.tinkerInput); @@ -110,10 +119,10 @@ public boolean mouseScrolled(double x, double y, double vertScroll, double horiz //uncrafting recipe buttons if (x > this.leftPos + 40 && x < this.leftPos + 54 && y > this.topPos + 22 && y < this.topPos + 64) { if (vertScroll > 0) { - PacketDistributor.sendToServer(new UncraftingGuiPacket(0)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(0)); this.menu.unrecipeInCycle++; } else { - PacketDistributor.sendToServer(new UncraftingGuiPacket(1)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(1)); this.menu.unrecipeInCycle--; } this.menu.slotsChanged(this.menu.tinkerInput); @@ -122,10 +131,10 @@ public boolean mouseScrolled(double x, double y, double vertScroll, double horiz //recrafting recipe buttons if (x > this.leftPos + 121 && x < this.leftPos + 135 && y > this.topPos + 22 && y < this.topPos + 64) { if (vertScroll > 0) { - PacketDistributor.sendToServer(new UncraftingGuiPacket(4)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(4)); this.menu.recipeInCycle++; } else { - PacketDistributor.sendToServer(new UncraftingGuiPacket(5)); + ClientPacketDistributor.sendToServer(new UncraftingGuiPacket(5)); this.menu.recipeInCycle--; } this.menu.slotsChanged(this.menu.assemblyMatrix); @@ -135,41 +144,40 @@ public boolean mouseScrolled(double x, double y, double vertScroll, double horiz } @Override - public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float partialTicks) { if (this.recipeBookComponent.isVisible() && this.widthTooNarrow) { - this.renderBackground(graphics, mouseX, mouseY, partialTicks); - this.recipeBookComponent.render(graphics, mouseX, mouseY, partialTicks); + this.extractBackground(graphics, mouseX, mouseY, partialTicks); + this.recipeBookComponent.extractRenderState(graphics, mouseX, mouseY, partialTicks); } else { - super.render(graphics, mouseX, mouseY, partialTicks); - this.recipeBookComponent.render(graphics, mouseX, mouseY, partialTicks); - this.recipeBookComponent.renderGhostRecipe(graphics, this.leftPos, this.topPos, true, partialTicks); + super.extractRenderState(graphics, mouseX, mouseY, partialTicks); + this.recipeBookComponent.extractRenderState(graphics, mouseX, mouseY, partialTicks); + this.recipeBookComponent.extractGhostRecipe(graphics, true); } - this.renderTooltip(graphics, mouseX, mouseY); - this.recipeBookComponent.renderTooltip(graphics, this.leftPos, this.topPos, mouseX, mouseY); + this.extractTooltip(graphics, mouseX, mouseY); + this.recipeBookComponent.extractTooltip(graphics, mouseX, mouseY, this.hoveredSlot); } @Override - protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { - graphics.drawString(this.font, this.title, 6, 6, 4210752, false); + protected void extractLabels(GuiGraphicsExtractor graphics, int mouseX, int mouseY) { + graphics.text(this.font, this.title, 6, 6, 4210752, false); if (TFConfig.disableUncraftingOnly) { - graphics.drawString(this.font, Component.translatable("container.twilightforest.uncrafting_table.uncrafting_disabled").withStyle(ChatFormatting.DARK_RED), 6, this.imageHeight - 96 + 2, 4210752, false); + graphics.text(this.font, Component.translatable("container.twilightforest.uncrafting_table.uncrafting_disabled").withStyle(ChatFormatting.DARK_RED), 6, this.imageHeight - 96 + 2, 4210752, false); } else { - graphics.drawString(this.font, I18n.get("container.inventory"), 7, this.imageHeight - 96 + 2, 4210752, false); + graphics.text(this.font, I18n.get("container.inventory"), 7, this.imageHeight - 96 + 2, 4210752, false); } } @Override - protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { + public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float partialTicks) { int frameX = this.leftPos; int frameY = (this.height - this.imageHeight) / 2; - graphics.blit(TEXTURE, frameX, frameY, 0, 0, this.imageWidth, this.imageHeight); + graphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, frameX, frameY, 0, 0, this.imageWidth, this.imageHeight, 256, 256); UncraftingMenu tfContainer = this.menu; - // show uncrafting ingredients as background - graphics.pose().pushPose(); - graphics.pose().translate(this.leftPos, this.topPos, 0); + graphics.pose().pushMatrix(); + graphics.pose().translate(this.leftPos, this.topPos); for (int i = 0; i < 9; i++) { Slot uncrafting = tfContainer.getSlot(2 + i); @@ -179,7 +187,7 @@ protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, in this.drawSlotAsBackground(graphics, uncrafting, assembly); } } - graphics.pose().popPose(); + graphics.pose().popMatrix(); int costVal = tfContainer.getUncraftingCost(); if (costVal > 0) { @@ -190,7 +198,7 @@ protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, in } else { color = 0x80FF20; } - graphics.drawString(this.font, cost, frameX + 48 - this.font.width(cost), frameY + 38, color); + graphics.text(this.font, cost, frameX + 48 - this.font.width(cost), frameY + 38, color); } costVal = tfContainer.getRecraftingCost(); @@ -202,7 +210,7 @@ protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, in } else { color = 0x80FF20; } - graphics.drawString(this.font, cost, frameX + 130 - this.font.width(cost), frameY + 38, color); + graphics.text(this.font, cost, frameX + 130 - this.font.width(cost), frameY + 38, color); } } @@ -212,60 +220,71 @@ protected boolean isHovering(int x, int y, int width, int height, double mouseX, } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (this.recipeBookComponent.mouseClicked(mouseX, mouseY, button)) { + public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) { + if (this.recipeBookComponent.mouseClicked(event, doubleClick)) { this.setFocused(this.recipeBookComponent); return true; } else { - return this.widthTooNarrow && this.recipeBookComponent.isVisible() || super.mouseClicked(mouseX, mouseY, button); + return this.widthTooNarrow && this.recipeBookComponent.isVisible() || super.mouseClicked(event, doubleClick); } } @Override - protected boolean hasClickedOutside(double mouseX, double mouseY, int guiLeft, int guiTop, int mouseButton) { - return this.recipeBookComponent.hasClickedOutside(mouseX, mouseY, this.leftPos, this.topPos, this.imageWidth, this.imageHeight, mouseButton) && super.hasClickedOutside(mouseX, mouseY, guiLeft, guiTop, mouseButton); + protected boolean hasClickedOutside(double mouseX, double mouseY, int guiLeft, int guiTop) { + return this.recipeBookComponent.hasClickedOutside(mouseX, mouseY, this.leftPos, this.topPos, this.imageWidth, this.imageHeight) && super.hasClickedOutside(mouseX, mouseY, guiLeft, guiTop); } - private void drawSlotAsBackground(GuiGraphics graphics, Slot backgroundSlot, Slot appearSlot) { - + private void drawSlotAsBackground(GuiGraphicsExtractor graphics, Slot backgroundSlot, Slot appearSlot) { int screenX = appearSlot.x; int screenY = appearSlot.y; ItemStack itemStackToRender = backgroundSlot.getItem(); - graphics.renderFakeItem(itemStackToRender, screenX, screenY); + graphics.fakeItem(itemStackToRender, screenX, screenY); boolean itemBroken = UncraftingMenu.isMarked(itemStackToRender); - // draw 50% gray rectangle over the item - RenderSystem.disableDepthTest(); - graphics.pose().pushPose(); - graphics.pose().translate(0.0D, 0.0D, 200.0D); + graphics.pose().pushMatrix(); + graphics.pose().translate(0.0F, 0.0F); graphics.fill(appearSlot.x, appearSlot.y, appearSlot.x + 16, appearSlot.y + 16, itemBroken ? 0x80FF8b8b : 0x9f8b8b8b); - graphics.pose().popPose(); - RenderSystem.enableDepthTest(); + graphics.pose().popMatrix(); } @Override - protected void renderTooltip(GuiGraphics graphics, int pX, int pY) { + protected void extractTooltip(GuiGraphicsExtractor graphics, int pX, int pY) { UncraftingMenu container = this.menu; + ClientTooltipPositioner positioner = DefaultTooltipPositioner.INSTANCE; for (int i = 0; i < 9; i++) { - if (container.getCarried().isEmpty() && container.slots.get(2 + i).hasItem() && this.hoveredSlot == container.slots.get(11 + i) && !container.slots.get(11 + i).hasItem()) { - graphics.renderTooltip(this.font, container.slots.get(2 + i).getItem(), pX, pY); + if (container.getCarried().isEmpty() + && container.slots.get(2 + i).hasItem() + && this.hoveredSlot == container.slots.get(11 + i) + && !container.slots.get(11 + i).hasItem()) { + + ItemStack itemStack = container.slots.get(2 + i).getItem(); + List lines = getTooltipFromItem(minecraft, itemStack).stream().map(Component::getVisualOrderText).map(ClientTooltipComponent::create).toList(); + + graphics.tooltip(this.font, lines, pX, pY, positioner, null); + return; } } - //check if we're hovering over a banned uncraftable item - if (container.slots.getFirst().hasItem() && container.slots.getFirst().getItem().is(ItemTagGenerator.BANNED_UNCRAFTABLES) && container.slots.getFirst().equals(this.hoveredSlot)) { - graphics.renderTooltip(this.font, Component.translatable("container.twilightforest.uncrafting_table.disabled_item").withStyle(ChatFormatting.RED), pX, pY); + if (container.slots.getFirst().hasItem() + && container.slots.getFirst().getItem().is(TFItemTags.BANNED_UNCRAFTABLES) + && container.slots.getFirst().equals(this.hoveredSlot)) { + + Component alertText = Component.translatable("container.twilightforest.uncrafting_table.disabled_item").withStyle(ChatFormatting.RED); + List lines = List.of(ClientTooltipComponent.create(alertText.getVisualOrderText())); + + graphics.tooltip(this.font, lines, pX, pY, positioner, null); } else { - super.renderTooltip(graphics, pX, pY); + super.extractTooltip(graphics, pX, pY); } } + @Override - protected void slotClicked(Slot slot, int slotId, int mouseButton, ClickType type) { - super.slotClicked(slot, slotId, mouseButton, type); + protected void slotClicked(Slot slot, int slotId, int mouseButton, ContainerInput containerInput) { + super.slotClicked(slot, slotId, mouseButton, containerInput); this.recipeBookComponent.slotClicked(slot); } @@ -275,8 +294,8 @@ public void recipesUpdated() { } @Override - public RecipeBookComponent getRecipeBookComponent() { - return this.recipeBookComponent; + public void fillGhostRecipe(RecipeDisplay recipeDisplay) { + } private static class CycleButton extends Button { @@ -289,7 +308,7 @@ private static class CycleButton extends Button { } @Override - public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + protected void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float partialTicks) { if (this.visible) { this.isHovered = mouseX >= this.getX() && mouseY >= this.getY() && mouseX < this.getX() + this.width && mouseY < this.getY() + this.height; @@ -301,7 +320,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float par // what's up if (!this.up) textureY += this.height; - graphics.blit(TEXTURE, this.getX(), this.getY(), textureX, textureY, this.width, this.height); + graphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, this.getX(), this.getY(), textureX, textureY, this.width, this.height, 256, 256); } } } @@ -316,7 +335,7 @@ private static class CycleButtonMini extends Button { } @Override - public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + public void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float partialTicks) { if (this.visible) { this.isHovered = mouseX >= this.getX() && mouseY >= this.getY() && mouseX < this.getX() + this.width && mouseY < this.getY() + this.height; @@ -328,7 +347,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float par // what's up if (!this.up) textureY += this.height; - graphics.blit(TEXTURE, this.getX(), this.getY(), textureX, textureY, this.width, this.height); + graphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, this.getX(), this.getY(), textureX, textureY, this.width, this.height, 256, 256); } } } diff --git a/src/main/java/twilightforest/client/particle/GhastTearParticle.java b/src/main/java/twilightforest/client/particle/GhastTearParticle.java index ba422a59b3..af745f88df 100644 --- a/src/main/java/twilightforest/client/particle/GhastTearParticle.java +++ b/src/main/java/twilightforest/client/particle/GhastTearParticle.java @@ -5,23 +5,21 @@ import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.SingleQuadParticle; -import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.particles.ItemParticleOption; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.data.AtlasIds; +import net.minecraft.resources.Identifier; import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; -import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.Items; +import org.jetbrains.annotations.NotNull; import twilightforest.init.TFSounds; public class GhastTearParticle extends SingleQuadParticle { - public GhastTearParticle(ClientLevel level, double x, double y, double z, TextureAtlasSprite sprite) { super(level, x, y, z, 0.0D, 0.0D, 0.0D, sprite); this.rCol = this.gCol = this.bCol = 1.0F; @@ -56,24 +54,12 @@ public void tick() { super.tick(); } - public static class Factory implements ParticleProvider { + public static class Factory implements ParticleProvider<@NotNull SimpleParticleType> { @Override public Particle createParticle(SimpleParticleType type, ClientLevel level, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, RandomSource random) { - TextureAtlasSprite textureatlassprite = this.calculateState(new ItemStack(Items.GHAST_TEAR), level).pickParticleIcon(random); - - if (textureatlassprite == null) { - textureatlassprite = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(MissingTextureAtlasSprite.getLocation()); - } + TextureAtlasSprite textureatlassprite = Minecraft.getInstance().getAtlasManager().getAtlasOrThrow(AtlasIds.BLOCKS).getSprite(Identifier.withDefaultNamespace("item/ghast_tear")); return new GhastTearParticle(level, x, y, z, textureatlassprite); } - - protected ItemStackRenderState calculateState(ItemStack stack, ClientLevel level) { - var state = new ItemStackRenderState(); - Minecraft.getInstance() - .getItemModelResolver() - .updateForTopItem(state, stack, ItemDisplayContext.GROUND, level, null, 0); - return state; - } } } diff --git a/src/main/java/twilightforest/client/particle/LogCoreParticle.java b/src/main/java/twilightforest/client/particle/LogCoreParticle.java index fccd349b4d..e0e116ec77 100644 --- a/src/main/java/twilightforest/client/particle/LogCoreParticle.java +++ b/src/main/java/twilightforest/client/particle/LogCoreParticle.java @@ -7,6 +7,7 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.phys.AABB; +import org.jetbrains.annotations.NotNull; public class LogCoreParticle extends RisingParticle { LogCoreParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, TextureAtlasSprite sprite) { @@ -56,16 +57,15 @@ public void tick() { this.alpha = Math.min(f * 1.35F, 1F); } - public record Factory(SpriteSet sprite) implements ParticleProvider { + public record Factory(SpriteSet sprite) implements ParticleProvider<@NotNull SimpleParticleType> { @Override public Particle createParticle(SimpleParticleType particleType, ClientLevel level, double x, double y, double z, double x2, double y2, double z2, RandomSource random) { - LogCoreParticle logCoreParticle = new LogCoreParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); - return logCoreParticle; + return new LogCoreParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); } } @Override - public AABB getRenderBoundingBox(float partialTicks) { + public AABB getBoundingBox() { return AABB.INFINITE; } } \ No newline at end of file diff --git a/src/main/java/twilightforest/client/particle/SortingParticle.java b/src/main/java/twilightforest/client/particle/SortingParticle.java index 90073a83e2..bb931ae624 100644 --- a/src/main/java/twilightforest/client/particle/SortingParticle.java +++ b/src/main/java/twilightforest/client/particle/SortingParticle.java @@ -7,6 +7,7 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.phys.AABB; +import org.jetbrains.annotations.NotNull; public class SortingParticle extends SingleQuadParticle { private final double xStart; @@ -82,16 +83,15 @@ public void tick() { } } - public record Factory(SpriteSet sprite) implements ParticleProvider { + public record Factory(SpriteSet sprite) implements ParticleProvider<@NotNull SimpleParticleType> { @Override public Particle createParticle(SimpleParticleType particleType, ClientLevel level, double x, double y, double z, double x2, double y2, double z2, RandomSource random) { - SortingParticle sortingParticle = new SortingParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); - return sortingParticle; + return new SortingParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); } } @Override - public AABB getRenderBoundingBox(float partialTicks) { + public AABB getBoundingBox() { return AABB.INFINITE; } } \ No newline at end of file diff --git a/src/main/java/twilightforest/client/particle/TransformationParticle.java b/src/main/java/twilightforest/client/particle/TransformationParticle.java index 773b713371..5b7b5d01d8 100644 --- a/src/main/java/twilightforest/client/particle/TransformationParticle.java +++ b/src/main/java/twilightforest/client/particle/TransformationParticle.java @@ -7,6 +7,7 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.phys.AABB; +import org.jetbrains.annotations.NotNull; public class TransformationParticle extends SingleQuadParticle { private final double xStart; @@ -82,16 +83,15 @@ public void tick() { } } - public record Factory(SpriteSet sprite) implements ParticleProvider { + public record Factory(SpriteSet sprite) implements ParticleProvider<@NotNull SimpleParticleType> { @Override public Particle createParticle(SimpleParticleType particleType, ClientLevel level, double x, double y, double z, double x2, double y2, double z2, RandomSource random) { - TransformationParticle sortingParticle = new TransformationParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); - return sortingParticle; + return new TransformationParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); } } @Override - public AABB getRenderBoundingBox(float partialTicks) { + public AABB getBoundingBox() { return AABB.INFINITE; } } \ No newline at end of file diff --git a/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java b/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java index edf93e58ef..326516ff7f 100644 --- a/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java +++ b/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java @@ -7,12 +7,11 @@ import net.minecraft.client.renderer.item.properties.numeric.RangeSelectItemModelProperty; import net.minecraft.util.Mth; import net.minecraft.world.entity.ItemOwner; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import twilightforest.components.item.PotionFlaskComponent; import twilightforest.init.TFDataComponents; -import twilightforest.item.BrittleFlaskItem; import twilightforest.item.PotionFlaskItem; public record PotionFlaskDamage(boolean normalize) implements RangeSelectItemModelProperty { @@ -29,7 +28,7 @@ public float get(ItemStack stack, @Nullable ClientLevel level, @Nullable ItemOwn } @Override - public MapCodec type() { + public @NotNull MapCodec type() { return TYPE; } } From 72dc82a6b6e248632c1c87acf520523978d811f7 Mon Sep 17 00:00:00 2001 From: Albazavr <110563872+albazavr-alba@users.noreply.github.com> Date: Wed, 24 Jun 2026 23:02:13 +0300 Subject: [PATCH 2/6] fix review comments for MovingCicadaSoundInstance.java --- .../client/MovingCicadaSoundInstance.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java index a4d68f7e65..0c43365b72 100644 --- a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java +++ b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java @@ -27,15 +27,13 @@ public MovingCicadaSoundInstance(LivingEntity entity) { @Override public void tick() { - if (!this.wearer.isRemoved() && (this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem()) || this.isWearingCicadaCurio())) { - if (!this.wearer.isRemoved() && (this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem()))) { - this.x = (float) this.wearer.getX(); - this.y = (float) this.wearer.getY(); - this.z = (float) this.wearer.getZ(); - } else { - this.stop(); - } - } + if (!this.wearer.isRemoved() && this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem())) { + this.x = (float) this.wearer.getX(); + this.y = (float) this.wearer.getY(); + this.z = (float) this.wearer.getZ(); + } else { + this.stop(); + } } private boolean isWearingCicadaCurio() { From bb021fdf6416a991e93aaa9cffcc035943740c3f Mon Sep 17 00:00:00 2001 From: Albazavr <110563872+albazavr-alba@users.noreply.github.com> Date: Sun, 28 Jun 2026 21:15:59 +0300 Subject: [PATCH 3/6] accidently removed condition returned in MovingCicadaSoundInstance.java --- .../java/twilightforest/client/MovingCicadaSoundInstance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java index 0c43365b72..c7f0c04b60 100644 --- a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java +++ b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java @@ -31,7 +31,7 @@ public void tick() { this.x = (float) this.wearer.getX(); this.y = (float) this.wearer.getY(); this.z = (float) this.wearer.getZ(); - } else { + } else if (this.isWearingCicadaCurio()) { this.stop(); } } From 5d36725e9fea0b250e6183f063f1335213bc6ba5 Mon Sep 17 00:00:00 2001 From: Albazavr Date: Sun, 5 Jul 2026 04:15:32 +0300 Subject: [PATCH 4/6] Resolved review comments --- src/main/java/twilightforest/client/FoliageColorHandler.java | 3 +-- src/main/java/twilightforest/client/LockedBiomeToast.java | 1 + .../twilightforest/client/MovingCicadaSoundInstance.java | 4 ++-- src/main/java/twilightforest/client/TFShaders.java | 1 + .../twilightforest/client/UncraftingRecipeBookComponent.java | 5 ++--- src/main/java/twilightforest/client/UncraftingScreen.java | 5 ++--- .../twilightforest/client/particle/GhastTearParticle.java | 4 ++-- .../java/twilightforest/client/particle/LogCoreParticle.java | 3 +-- .../java/twilightforest/client/particle/SortingParticle.java | 3 +-- .../client/particle/TransformationParticle.java | 3 +-- .../twilightforest/client/properties/PotionFlaskDamage.java | 3 +-- 11 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/main/java/twilightforest/client/FoliageColorHandler.java b/src/main/java/twilightforest/client/FoliageColorHandler.java index 357bee7dd4..ae5b84fd89 100644 --- a/src/main/java/twilightforest/client/FoliageColorHandler.java +++ b/src/main/java/twilightforest/client/FoliageColorHandler.java @@ -7,7 +7,6 @@ import net.minecraft.world.level.biome.Biome; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.event.entity.EntityLeaveLevelEvent; -import org.jetbrains.annotations.NotNull; import tamaized.beanification.Autowired; import tamaized.beanification.Component; import tamaized.beanification.PostConstruct; @@ -23,7 +22,7 @@ public final class FoliageColorHandler { @Autowired private BiomeColorAlgorithms biomeColorAlgorithms; - private final Map, Handler> REGISTRY = new HashMap<>() {{ + private final Map, Handler> REGISTRY = new HashMap<>() {{ put(TFBiomes.SPOOKY_FOREST, (o, x, z) -> biomeColorAlgorithms.spookyFoliage(x, z)); put(TFBiomes.ENCHANTED_FOREST, (o, x, z) -> biomeColorAlgorithms.enchanted(o, (int) x, (int) z)); put(TFBiomes.DARK_FOREST_CENTER, (o, x, z) -> biomeColorAlgorithms.darkForestCenterFoliage(x, z)); diff --git a/src/main/java/twilightforest/client/LockedBiomeToast.java b/src/main/java/twilightforest/client/LockedBiomeToast.java index ae28c3bf5a..8ca8a328e7 100644 --- a/src/main/java/twilightforest/client/LockedBiomeToast.java +++ b/src/main/java/twilightforest/client/LockedBiomeToast.java @@ -10,6 +10,7 @@ import net.minecraft.world.item.ItemStack; public class LockedBiomeToast implements Toast { + private static final Component TITLE = Component.translatable("misc.twilightforest.biome_locked"); private static final Component DESCRIPTION = Component.translatable("misc.twilightforest.biome_locked_2"); private static final Identifier BACKGROUND_SPRITE = Identifier.withDefaultNamespace("toast/advancement"); diff --git a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java index c7f0c04b60..5c520903ff 100644 --- a/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java +++ b/src/main/java/twilightforest/client/MovingCicadaSoundInstance.java @@ -27,11 +27,11 @@ public MovingCicadaSoundInstance(LivingEntity entity) { @Override public void tick() { - if (!this.wearer.isRemoved() && this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem())) { + if (!this.wearer.isRemoved() && (this.wearer.getItemBySlot(EquipmentSlot.HEAD).is(TFBlocks.CICADA.asItem()) || this.isWearingCicadaCurio())) { this.x = (float) this.wearer.getX(); this.y = (float) this.wearer.getY(); this.z = (float) this.wearer.getZ(); - } else if (this.isWearingCicadaCurio()) { + } else { this.stop(); } } diff --git a/src/main/java/twilightforest/client/TFShaders.java b/src/main/java/twilightforest/client/TFShaders.java index acc3fe1786..c10b6a6bb2 100644 --- a/src/main/java/twilightforest/client/TFShaders.java +++ b/src/main/java/twilightforest/client/TFShaders.java @@ -14,6 +14,7 @@ import java.util.Optional; public class TFShaders { + private static final DepthStencilState TRANSLUCENT_DEPTH = new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, false); private static final RenderPipeline AURORA_PIPELINE = RenderPipeline.builder(RenderPipelines.DEBUG_FILLED_SNIPPET) diff --git a/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java b/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java index d3ec16906c..8019258377 100644 --- a/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java +++ b/src/main/java/twilightforest/client/UncraftingRecipeBookComponent.java @@ -16,13 +16,12 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.display.RecipeDisplay; import net.minecraft.world.item.crafting.display.SlotDisplay; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import twilightforest.inventory.UncraftingPlaceRecipe; import java.util.List; -public class UncraftingRecipeBookComponent extends RecipeBookComponent<@NotNull RecipeBookMenu> implements UncraftingPlaceRecipe { +public class UncraftingRecipeBookComponent extends RecipeBookComponent implements UncraftingPlaceRecipe { @Nullable private GhostSlots currentGhostSlots = new GhostSlots(() -> 0); @@ -84,7 +83,7 @@ public void addItemToSlot(Ingredient ingredient, int slotIndex, int maxAmount, i if (currentGhostSlots != null && !ingredient.isEmpty()) { Slot targetSlot = this.menu.slots.get(slotIndex); - List> items = ingredient.getValues().stream().toList(); + List> items = ingredient.getValues().stream().toList(); if (!items.isEmpty()) { Item item = items.getFirst().value(); ItemStack stack = new ItemStack(item); diff --git a/src/main/java/twilightforest/client/UncraftingScreen.java b/src/main/java/twilightforest/client/UncraftingScreen.java index cd0bbbe35f..e903b667b8 100644 --- a/src/main/java/twilightforest/client/UncraftingScreen.java +++ b/src/main/java/twilightforest/client/UncraftingScreen.java @@ -24,7 +24,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.display.RecipeDisplay; import net.neoforged.neoforge.client.network.ClientPacketDistributor; -import org.jetbrains.annotations.NotNull; import twilightforest.TwilightForestMod; import twilightforest.config.TFConfig; import twilightforest.tags.TFItemTags; @@ -33,9 +32,9 @@ import java.util.List; -public class UncraftingScreen extends AbstractContainerScreen<@NotNull UncraftingMenu> implements RecipeUpdateListener { +public class UncraftingScreen extends AbstractContainerScreen implements RecipeUpdateListener { private static final Identifier TEXTURE = TwilightForestMod.getGuiTexture("guigoblintinkering.png"); - private final RecipeBookComponent<@NotNull RecipeBookMenu> recipeBookComponent = new UncraftingRecipeBookComponent(menu, List.of()); + private final RecipeBookComponent recipeBookComponent = new UncraftingRecipeBookComponent(menu, List.of()); private boolean widthTooNarrow; public UncraftingScreen(UncraftingMenu container, Inventory player, Component name) { diff --git a/src/main/java/twilightforest/client/particle/GhastTearParticle.java b/src/main/java/twilightforest/client/particle/GhastTearParticle.java index af745f88df..1b10786eef 100644 --- a/src/main/java/twilightforest/client/particle/GhastTearParticle.java +++ b/src/main/java/twilightforest/client/particle/GhastTearParticle.java @@ -16,10 +16,10 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.Items; -import org.jetbrains.annotations.NotNull; import twilightforest.init.TFSounds; public class GhastTearParticle extends SingleQuadParticle { + public GhastTearParticle(ClientLevel level, double x, double y, double z, TextureAtlasSprite sprite) { super(level, x, y, z, 0.0D, 0.0D, 0.0D, sprite); this.rCol = this.gCol = this.bCol = 1.0F; @@ -54,7 +54,7 @@ public void tick() { super.tick(); } - public static class Factory implements ParticleProvider<@NotNull SimpleParticleType> { + public static class Factory implements ParticleProvider { @Override public Particle createParticle(SimpleParticleType type, ClientLevel level, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, RandomSource random) { TextureAtlasSprite textureatlassprite = Minecraft.getInstance().getAtlasManager().getAtlasOrThrow(AtlasIds.BLOCKS).getSprite(Identifier.withDefaultNamespace("item/ghast_tear")); diff --git a/src/main/java/twilightforest/client/particle/LogCoreParticle.java b/src/main/java/twilightforest/client/particle/LogCoreParticle.java index e0e116ec77..b9c0e90c7c 100644 --- a/src/main/java/twilightforest/client/particle/LogCoreParticle.java +++ b/src/main/java/twilightforest/client/particle/LogCoreParticle.java @@ -7,7 +7,6 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.phys.AABB; -import org.jetbrains.annotations.NotNull; public class LogCoreParticle extends RisingParticle { LogCoreParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, TextureAtlasSprite sprite) { @@ -57,7 +56,7 @@ public void tick() { this.alpha = Math.min(f * 1.35F, 1F); } - public record Factory(SpriteSet sprite) implements ParticleProvider<@NotNull SimpleParticleType> { + public record Factory(SpriteSet sprite) implements ParticleProvider { @Override public Particle createParticle(SimpleParticleType particleType, ClientLevel level, double x, double y, double z, double x2, double y2, double z2, RandomSource random) { return new LogCoreParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); diff --git a/src/main/java/twilightforest/client/particle/SortingParticle.java b/src/main/java/twilightforest/client/particle/SortingParticle.java index bb931ae624..5f746ff2fc 100644 --- a/src/main/java/twilightforest/client/particle/SortingParticle.java +++ b/src/main/java/twilightforest/client/particle/SortingParticle.java @@ -7,7 +7,6 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.phys.AABB; -import org.jetbrains.annotations.NotNull; public class SortingParticle extends SingleQuadParticle { private final double xStart; @@ -83,7 +82,7 @@ public void tick() { } } - public record Factory(SpriteSet sprite) implements ParticleProvider<@NotNull SimpleParticleType> { + public record Factory(SpriteSet sprite) implements ParticleProvider { @Override public Particle createParticle(SimpleParticleType particleType, ClientLevel level, double x, double y, double z, double x2, double y2, double z2, RandomSource random) { return new SortingParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); diff --git a/src/main/java/twilightforest/client/particle/TransformationParticle.java b/src/main/java/twilightforest/client/particle/TransformationParticle.java index 5b7b5d01d8..186d3efc2f 100644 --- a/src/main/java/twilightforest/client/particle/TransformationParticle.java +++ b/src/main/java/twilightforest/client/particle/TransformationParticle.java @@ -7,7 +7,6 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.phys.AABB; -import org.jetbrains.annotations.NotNull; public class TransformationParticle extends SingleQuadParticle { private final double xStart; @@ -83,7 +82,7 @@ public void tick() { } } - public record Factory(SpriteSet sprite) implements ParticleProvider<@NotNull SimpleParticleType> { + public record Factory(SpriteSet sprite) implements ParticleProvider { @Override public Particle createParticle(SimpleParticleType particleType, ClientLevel level, double x, double y, double z, double x2, double y2, double z2, RandomSource random) { return new TransformationParticle(level, x, y, z, x2, y2, z2, this.sprite.get(random)); diff --git a/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java b/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java index 326516ff7f..307cb1dab5 100644 --- a/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java +++ b/src/main/java/twilightforest/client/properties/PotionFlaskDamage.java @@ -8,7 +8,6 @@ import net.minecraft.util.Mth; import net.minecraft.world.entity.ItemOwner; import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import twilightforest.components.item.PotionFlaskComponent; import twilightforest.init.TFDataComponents; @@ -28,7 +27,7 @@ public float get(ItemStack stack, @Nullable ClientLevel level, @Nullable ItemOwn } @Override - public @NotNull MapCodec type() { + public MapCodec type() { return TYPE; } } From df00fc6cd594b80fe7f3f8e6eeb176424d7f05bc Mon Sep 17 00:00:00 2001 From: Albazavr Date: Thu, 16 Jul 2026 00:52:29 +0300 Subject: [PATCH 5/6] Fixed GhastTearParticle and LockedBiomeToast --- .../client/LockedBiomeToast.java | 1 - .../client/particle/GhastTearParticle.java | 24 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/twilightforest/client/LockedBiomeToast.java b/src/main/java/twilightforest/client/LockedBiomeToast.java index 8ca8a328e7..95853028f6 100644 --- a/src/main/java/twilightforest/client/LockedBiomeToast.java +++ b/src/main/java/twilightforest/client/LockedBiomeToast.java @@ -41,7 +41,6 @@ public void update(ToastManager toastManager, long timer) { @Override public void extractRenderState(GuiGraphicsExtractor graphics, Font font, long timer) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, BACKGROUND_SPRITE, 0, 0, this.width(), this.height()); - graphics.fakeItem(this.item(), 6, 8); graphics.text(font, TITLE, 25, 7, -256, false); graphics.text(font, DESCRIPTION, 25, 18, 16777215, false); diff --git a/src/main/java/twilightforest/client/particle/GhastTearParticle.java b/src/main/java/twilightforest/client/particle/GhastTearParticle.java index 1b10786eef..e83126cf8e 100644 --- a/src/main/java/twilightforest/client/particle/GhastTearParticle.java +++ b/src/main/java/twilightforest/client/particle/GhastTearParticle.java @@ -5,14 +5,17 @@ import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.SingleQuadParticle; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.sprite.Material; import net.minecraft.core.particles.ItemParticleOption; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.data.AtlasIds; -import net.minecraft.resources.Identifier; import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.Items; @@ -57,9 +60,24 @@ public void tick() { public static class Factory implements ParticleProvider { @Override public Particle createParticle(SimpleParticleType type, ClientLevel level, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, RandomSource random) { - TextureAtlasSprite textureatlassprite = Minecraft.getInstance().getAtlasManager().getAtlasOrThrow(AtlasIds.BLOCKS).getSprite(Identifier.withDefaultNamespace("item/ghast_tear")); + Material.Baked material = this.calculateState(new ItemStack(Items.GHAST_TEAR), level).pickParticleMaterial(random); + TextureAtlasSprite textureatlassprite; + + if (material != null) { + textureatlassprite = material.sprite(); + } else { + textureatlassprite = Minecraft.getInstance().getAtlasManager().getAtlasOrThrow(TextureAtlas.LOCATION_BLOCKS).getSprite(MissingTextureAtlasSprite.getLocation()); + } return new GhastTearParticle(level, x, y, z, textureatlassprite); } + + protected ItemStackRenderState calculateState(ItemStack stack, ClientLevel level) { + var state = new ItemStackRenderState(); + Minecraft.getInstance() + .getItemModelResolver() + .updateForTopItem(state, stack, ItemDisplayContext.GROUND, level, null, 0); + return state; + } } } From 8be3fa2ae1f0836694e0fb7071a454b9beb1f7cc Mon Sep 17 00:00:00 2001 From: Albazavr Date: Tue, 21 Jul 2026 17:41:50 +0300 Subject: [PATCH 6/6] Remove changes from TwilightForestRenderInfo --- .../client/TwilightForestRenderInfo.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/twilightforest/client/TwilightForestRenderInfo.java b/src/main/java/twilightforest/client/TwilightForestRenderInfo.java index 6ede74a48b..6404162481 100644 --- a/src/main/java/twilightforest/client/TwilightForestRenderInfo.java +++ b/src/main/java/twilightforest/client/TwilightForestRenderInfo.java @@ -3,17 +3,26 @@ import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.DimensionSpecialEffects; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.client.renderer.state.level.SkyRenderState; import net.minecraft.client.renderer.state.level.WeatherRenderState; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.biome.Biome; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.client.CustomSkyboxRenderer; import net.neoforged.neoforge.client.CustomWeatherEffectRenderer; import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; import org.joml.Matrix4fc; import twilightforest.client.renderer.TFSkyRenderer; import twilightforest.client.renderer.TFWeatherRenderer; +import twilightforest.init.TFBiomes; + +import java.util.Optional; public class TwilightForestRenderInfo implements CustomSkyboxRenderer, CustomWeatherEffectRenderer { @@ -33,6 +42,28 @@ public class TwilightForestRenderInfo implements CustomSkyboxRenderer, CustomWea // return biomeFogColor.multiply(daylight * 0.94F + 0.06F, (daylight * 0.94F + 0.06F), (daylight * 0.91F + 0.09F)); // } + @Override + public boolean isFoggyAt(int x, int y) { // true = nearFog + Player player = Minecraft.getInstance().player; + + if (player != null) { + Optional> biome = player.level().getBiome(player.blockPosition()).unwrapKey(); + if (biome.isPresent()) { + boolean spooky = biome.get() == TFBiomes.SPOOKY_FOREST; + + if (player.position().y > 20 && !spooky) { + return false; // If player is above the dark forest then no need to make it so spooky. The darkwood leaves cover everything as low as y42. + } + + return spooky || biome.get() == TFBiomes.DARK_FOREST || biome.get() == TFBiomes.DARK_FOREST_CENTER; + } + } + + return false; + + //Make the fog on these biomes much much darker, maybe pitch black even. Do we keep this harsher fog underground too? + } + @Override public boolean renderSky(LevelRenderState levelRenderState, SkyRenderState skyRenderState, Matrix4fc modelViewMatrix, Runnable setupFog) { if (this.skyRenderer == null) { @@ -43,11 +74,11 @@ public boolean renderSky(LevelRenderState levelRenderState, SkyRenderState skyRe @Override public boolean renderSnowAndRain(LevelRenderState levelRenderState, WeatherRenderState weatherRenderState, MultiBufferSource bufferSource, Vec3 camPos) { - return TFWeatherRenderer.renderSnowAndRain(Minecraft.getInstance().level, Minecraft.getInstance().levelRenderer.getTicks(), Minecraft.getInstance().getDeltaTracker().getGameTimeDeltaTicks(), camPos); + return TFWeatherRenderer.renderSnowAndRain(level, ticks, partialTick, lightTexture, new Vec3(camX, camY, camZ)); } @Override public boolean tickRain(ClientLevel level, int ticks, Camera camera) { - return TFWeatherRenderer.tickRain(level, ticks, camera.blockPosition()); + return TFWeatherRenderer.tickRain(level, ticks, camera.getBlockPosition()); } }