/* * Copyright (C) 2022 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates is free software: you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * NotEnoughUpdates is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.dungeons; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.SpecialColour; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.shader.Framebuffer; import net.minecraft.util.ResourceLocation; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GL30; import java.nio.FloatBuffer; import java.util.HashMap; import java.util.HashSet; import java.util.Map; public class DungeonBlocks { private static Framebuffer framebufferBlocksTo = null; private static Framebuffer framebufferBlocksFrom = null; private static final HashMap framebuffersDynamicTo = new HashMap<>(); public static HashMap framebuffersDynamicFrom = new HashMap<>(); private static final HashSet dynamicUpdated = new HashSet<>(); private static final FloatBuffer projectionMatrixOld = BufferUtils.createFloatBuffer(16); private static final FloatBuffer modelviewMatrixOld = BufferUtils.createFloatBuffer(16); public static boolean textureExists() { return framebufferBlocksFrom != null && isOverriding(); } public static void bindTextureIfExists() { if (textureExists()) { framebufferBlocksFrom.bindFramebufferTexture(); } } public static boolean isOverriding() { return OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.dungeons.enableDungBlockOverlay && (NotEnoughUpdates.INSTANCE.config.dungeons.dungeonBlocksEverywhere || (SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("dungeon"))); } public static boolean bindModifiedTexture(ResourceLocation location, int colour) { if (!isOverriding()) { return false; } if (Utils.disableCustomDungColours) { return false; } if (((colour >> 24) & 0xFF) < 10) { return false; } String id = location.getResourceDomain() + ":" + location.getResourcePath(); if (dynamicUpdated.contains(id) && framebuffersDynamicFrom.containsKey(id)) { framebuffersDynamicFrom.get(id).bindFramebufferTexture(); return true; } Minecraft.getMinecraft().getTextureManager().bindTexture(location); int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH); int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT); Framebuffer to = checkFramebufferSizes(framebuffersDynamicTo.get(id), w, h); dynamicUpdated.add(id); try { GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrixOld); GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelviewMatrixOld); GL11.glPushMatrix(); GlStateManager.matrixMode(GL11.GL_PROJECTION); GlStateManager.loadIdentity(); GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D); GlStateManager.matrixMode(GL11.GL_MODELVIEW); GlStateManager.loadIdentity(); GlStateManager.translate(0.0F, 0.0F, -2000.0F); to.bindFramebuffer(true); GlStateManager.clearColor(0, 1, 0, 1); GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); GlStateManager.disableBlend(); GlStateManager.disableLighting(); GlStateManager.disableFog(); Minecraft.getMinecraft().getTextureManager().bindTexture(location); GlStateManager.color(1, 1, 1, 1); Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR); GlStateManager.enableBlend(); GL14.glBlendFuncSeparate( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA ); Utils.drawRectNoBlend(0, 0, w, h, colour); GL11.glPopMatrix(); to.bindFramebufferTexture(); if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) { GL11.glTexParameteri( GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, Minecraft.getMinecraft().gameSettings.mipmapLevels ); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F); GL11.glTexParameterf( GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, (float) Minecraft.getMinecraft().gameSettings.mipmapLevels ); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F); GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); } GlStateManager.matrixMode(GL11.GL_PROJECTION); GL11.glLoadMatrix(projectionMatrixOld); GlStateManager.matrixMode(GL11.GL_MODELVIEW); GL11.glLoadMatrix(modelviewMatrixOld); Framebuffer from = checkFramebufferSizes(framebuffersDynamicFrom.get(id), w, h); framebuffersDynamicFrom.put(id, to); framebuffersDynamicTo.put(id, from); to.bindFramebufferTexture(); Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); GlStateManager.disableBlend(); GlStateManager.enableLighting(); return true; } catch (Exception e) { e.printStackTrace(); } Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); GlStateManager.disableBlend(); GlStateManager.enableLighting(); return false; } private static final HashMap dynamicPreloadMap = new HashMap() {{ put(new ResourceLocation("textures/entity/bat.png"), NotEnoughUpdates.INSTANCE.config.dungeons.dungBatColour); put( new ResourceLocation("textures/entity/chest/normal.png"), NotEnoughUpdates.INSTANCE.config.dungeons.dungChestColour ); put( new ResourceLocation("textures/entity/chest/normal_double.png"), NotEnoughUpdates.INSTANCE.config.dungeons.dungChestColour ); put( new ResourceLocation("textures/entity/chest/trapped.png"), NotEnoughUpdates.INSTANCE.config.dungeons.dungTrappedChestColour ); put( new ResourceLocation("textures/entity/chest/trapped_double.png"), NotEnoughUpdates.INSTANCE.config.dungeons.dungTrappedChestColour ); }}; public static void tick() { if (!isOverriding() || Minecraft.getMinecraft().theWorld == null) { return; } dynamicUpdated.clear(); for (Map.Entry entry : dynamicPreloadMap.entrySet()) { bindModifiedTexture(entry.getKey(), SpecialColour.specialToChromaRGB(entry.getValue())); } Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH); int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT); Framebuffer to = checkFramebufferSizes(framebufferBlocksTo, w, h); try { GL11.glPushMatrix(); GlStateManager.matrixMode(5889); GlStateManager.loadIdentity(); GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D); GlStateManager.matrixMode(5888); GlStateManager.loadIdentity(); GlStateManager.translate(0.0F, 0.0F, -2000.0F); to.bindFramebuffer(true); GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); GlStateManager.disableBlend(); GlStateManager.disableLighting(); GlStateManager.disableFog(); Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); GlStateManager.color(1, 1, 1, 1); Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR); HashMap spriteMap = new HashMap() {{ put( Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/stonebrick_cracked"), SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungCrackedColour) ); put( Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/dispenser_front_horizontal"), SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungDispenserColour) ); put( Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/lever"), SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungLeverColour) ); put( Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/trip_wire"), SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungTripWireColour) ); }}; for (Map.Entry entry : spriteMap.entrySet()) { if (((entry.getValue() >> 24) & 0xFF) < 10) continue; TextureAtlasSprite tas = entry.getKey(); Gui.drawRect((int) (w * tas.getMinU()), h - (int) (h * tas.getMaxV()) - 1, (int) (w * tas.getMaxU()) + 1, h - (int) (h * tas.getMinV()), entry.getValue() ); } ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); GlStateManager.matrixMode(5889); GlStateManager.loadIdentity(); GlStateManager.ortho(0.0D, scaledResolution.getScaledWidth_double(), scaledResolution.getScaledHeight_double(), 0.0D, 1000.0D, 3000.0D ); GlStateManager.matrixMode(5888); GlStateManager.loadIdentity(); GlStateManager.translate(0.0F, 0.0F, -2000.0F); GL11.glPopMatrix(); to.bindFramebufferTexture(); if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) { GL11.glTexParameteri( GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, Minecraft.getMinecraft().gameSettings.mipmapLevels ); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F); GL11.glTexParameterf( GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, (float) Minecraft.getMinecraft().gameSettings.mipmapLevels ); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F); GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); } Framebuffer from = checkFramebufferSizes(framebufferBlocksFrom, w, h); framebufferBlocksFrom = to; framebufferBlocksTo = from; } catch (Exception e) { e.printStackTrace(); } Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); GlStateManager.enableBlend(); } private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { if (framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { if (framebuffer == null) { framebuffer = new Framebuffer(width, height, false); framebuffer.framebufferColor[0] = 1f; framebuffer.framebufferColor[1] = 0f; framebuffer.framebufferColor[2] = 0f; framebuffer.framebufferColor[3] = 0; } else { framebuffer.createBindFramebuffer(width, height); } framebuffer.setFramebufferFilter(GL11.GL_NEAREST); } return framebuffer; } }