Skip to content
18 changes: 9 additions & 9 deletions src/main/java/twilightforest/client/BakedMultiPartRenderers.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -19,19 +20,18 @@
import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("deprecation")
public class BakedMultiPartRenderers {
private static final Map<Identifier, LazyLoadedValue<EntityRenderer<?>>> renderers = new HashMap<>();
private static final Map<Identifier, Supplier<EntityRenderer<?, ?>>> 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();
}
}
7 changes: 1 addition & 6 deletions src/main/java/twilightforest/client/FoliageColorHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

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;
Expand Down Expand Up @@ -47,17 +46,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;
Expand Down
41 changes: 32 additions & 9 deletions src/main/java/twilightforest/client/LockedBiomeToast.java
Original file line number Diff line number Diff line change
@@ -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 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 Toast.Visibility getWantedVisibility() {
return this.wantedVisibility;
}

return timer >= 10000L ? Toast.Visibility.HIDE : Toast.Visibility.SHOW;
@Override
public void update(ToastManager toastManager, long timer) {
if (timer >= 10000L) {
this.wantedVisibility = Toast.Visibility.HIDE;
Comment thread
Tamaized marked this conversation as resolved.
}
}

@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);
}
}
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
36 changes: 20 additions & 16 deletions src/main/java/twilightforest/client/OptifineWarningScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -32,22 +35,22 @@ 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);
this.suggestions = MultiLineLabel.create(this.font, url, this.width - 50);
}

@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
Expand All @@ -69,23 +72,24 @@ 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
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;
}
}
137 changes: 24 additions & 113 deletions src/main/java/twilightforest/client/TFShaders.java
Original file line number Diff line number Diff line change
@@ -1,124 +1,35 @@
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;
private static final DepthStencilState TRANSLUCENT_DEPTH = new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, false);

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();
}
}
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 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()));
}

}
public static final RenderType AURORA = RenderType.create(
"twilightforest_aurora",
RenderSetup.builder(AURORA_PIPELINE).createRenderSetup()
Comment thread
albazavr-alba marked this conversation as resolved.
Outdated
);

public static final RenderType RED_THREAD = RenderType.create(
"twilightforest_red_thread",
RenderSetup.builder(TFRenderPipelines.RED_THREAD).createRenderSetup()
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.EnumMap;
import java.util.concurrent.atomic.AtomicReference;

// FIXME
public class TextureGeneratorReloadListener implements ResourceManagerReloadListener {
public static final TextureGeneratorReloadListener INSTANCE = new TextureGeneratorReloadListener();
private static final EnumMap<Boat.Type, AbstractTexture> BOAT_CACHE = new EnumMap<>(Boat.Type.class);
Expand Down
Loading
Loading