diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..8a2b94292 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true + +[*.json] +indent_size = 2 +indent_style = space + +[*.java] +indent_size = 4 +indent_style = tab +tab_width = 4 diff --git a/build.gradle b/build.gradle index 292261058..77d8bcce8 100644 --- a/build.gradle +++ b/build.gradle @@ -60,6 +60,11 @@ minecraft { args << '-Dmixin.checks.interfaces=true' args << '-Dmixin.debug.export=true' } + if (project.debug_class_loading.toBoolean()) { + args << '-Dlegacy.debugClassLoading=true' + args << '-Dlegacy.debugClassLoadingFiner=true' + args << '-Dlegacy.debugClassLoadingSave=true' + } extraRunJvmArguments.addAll(args) // Include and use dependencies' Access Transformer files @@ -133,6 +138,14 @@ dependencies { //compileOnly group: 'info.openmods', name: 'calc', version: '0.2' compileOnly "info.computercraft:ComputerCraft-API:1.80pr0" compileOnly "info.openmods:OpenPeripheralCore-API:3.5-unstable" + + // debug stuff + compileOnly rfg.deobf("curse.maven:renderlib-624967:6461209") + compileOnly rfg.deobf("curse.maven:nothirium-624960:7207682") + //runtimeOnly rfg.deobf("curse.maven:renderlib-624967:6461209") + //runtimeOnly rfg.deobf("curse.maven:nothirium-624960:7207682") + + //runtimeOnly rfg.deobf("curse.maven:spark-361579:3542217") } // Adds Access Transformer files to tasks diff --git a/gradle.properties b/gradle.properties index 6c537565e..d5febc434 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ maven_group = info.openmods # If any properties changes below this line, run `gradlew setupDecompWorkspace` and refresh gradle again to ensure everything is working correctly. # Boilerplate Options -use_mixins = false +use_mixins = true use_coremod = true use_assetmover = false @@ -24,3 +24,6 @@ use_access_transformer = true # Coremod Arguments include_mod = true coremod_plugin_class_name = openmods.core.OpenModsCorePlugin + +# Debug options, always disable before committing +debug_class_loading = false diff --git a/src/main/java/openblocks/OpenBlocks.java b/src/main/java/openblocks/OpenBlocks.java index f7fde7c9f..8dc5d8b88 100644 --- a/src/main/java/openblocks/OpenBlocks.java +++ b/src/main/java/openblocks/OpenBlocks.java @@ -176,7 +176,6 @@ import openblocks.common.tileentity.TileEntityPaintCan; import openblocks.common.tileentity.TileEntityPaintMixer; import openblocks.common.tileentity.TileEntityProjector; -import openblocks.common.tileentity.TileEntitySky; import openblocks.common.tileentity.TileEntitySprinkler; import openblocks.common.tileentity.TileEntityTank; import openblocks.common.tileentity.TileEntityTarget; @@ -382,7 +381,7 @@ public static class Blocks implements BlockInstances { @RegisterBlock(type = BlockDrawingTable.class, id = "drawing_table", tileEntity = TileEntityDrawingTable.class, legacyIds = "drawingtable") public static Block drawingTable; - @RegisterBlock(type = BlockSky.class, id = "sky", tileEntity = TileEntitySky.class, itemBlock = ItemSkyBlock.class, unlocalizedName = "sky.normal") + @RegisterBlock(type = BlockSky.class, id = "sky", itemBlock = ItemSkyBlock.class, unlocalizedName = "sky.normal") public static Block sky; @RegisterBlock(type = BlockXPShower.class, id = "xp_shower", tileEntity = TileEntityXPShower.class, legacyIds = "xpshower") diff --git a/src/main/java/openblocks/client/ClientProxy.java b/src/main/java/openblocks/client/ClientProxy.java index 7e1a06c56..c5b60b35e 100644 --- a/src/main/java/openblocks/client/ClientProxy.java +++ b/src/main/java/openblocks/client/ClientProxy.java @@ -30,7 +30,6 @@ import openblocks.client.bindings.KeyInputHandler; import openblocks.client.fx.FXLiquidSpray; import openblocks.client.model.ModelCraneBackpack; -import openblocks.client.renderer.SkyBlockRenderer; import openblocks.client.renderer.TextureUploader; import openblocks.client.renderer.block.PathModel; import openblocks.client.renderer.block.canvas.CanvasTextureManager; @@ -47,6 +46,7 @@ import openblocks.client.renderer.item.stencil.ModelStencil; import openblocks.client.renderer.item.stencil.StencilItemOverride; import openblocks.client.renderer.item.stencil.StencilTextureManager; +import openblocks.client.renderer.skyblock.SkyBlockRenderer; import openblocks.client.renderer.tileentity.TileEntityAutoEnchantmentTableRenderer; import openblocks.client.renderer.tileentity.TileEntityBearTrapRenderer; import openblocks.client.renderer.tileentity.TileEntityCannonRenderer; @@ -56,7 +56,6 @@ import openblocks.client.renderer.tileentity.TileEntityImaginaryRenderer; import openblocks.client.renderer.tileentity.TileEntityPaintMixerRenderer; import openblocks.client.renderer.tileentity.TileEntityProjectorRenderer; -import openblocks.client.renderer.tileentity.TileEntitySkyRenderer; import openblocks.client.renderer.tileentity.TileEntitySprinklerRenderer; import openblocks.client.renderer.tileentity.TileEntityTankRenderer; import openblocks.client.renderer.tileentity.TileEntityTrophyRenderer; @@ -83,7 +82,6 @@ import openblocks.common.tileentity.TileEntityImaginary; import openblocks.common.tileentity.TileEntityPaintMixer; import openblocks.common.tileentity.TileEntityProjector; -import openblocks.common.tileentity.TileEntitySky; import openblocks.common.tileentity.TileEntitySprinkler; import openblocks.common.tileentity.TileEntityTank; import openblocks.common.tileentity.TileEntityTrophy; @@ -204,7 +202,6 @@ public void preInit() { ClientRegistry.bindTileEntitySpecialRenderer(TileEntityVillageHighlighter.class, new TileEntityVillageHighlighterRenderer()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityAutoEnchantmentTable.class, new TileEntityAutoEnchantmentTableRenderer()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityPaintMixer.class, new TileEntityPaintMixerRenderer()); - ClientRegistry.bindTileEntitySpecialRenderer(TileEntitySky.class, new TileEntitySkyRenderer()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityGoldenEgg.class, new TileEntityGoldenEggRenderer()); if (OpenBlocks.Blocks.projector != null) { diff --git a/src/main/java/openblocks/client/renderer/SkyBlockRenderer.java b/src/main/java/openblocks/client/renderer/SkyBlockRenderer.java deleted file mode 100644 index 51f9cd256..000000000 --- a/src/main/java/openblocks/client/renderer/SkyBlockRenderer.java +++ /dev/null @@ -1,200 +0,0 @@ -package openblocks.client.renderer; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.resources.IResourceManager; -import net.minecraft.client.resources.IResourceManagerReloadListener; -import net.minecraft.client.shader.Framebuffer; -import net.minecraftforge.client.MinecraftForgeClient; -import net.minecraftforge.fml.client.FMLClientHandler; -import openblocks.Config; -import openmods.Log; -import openmods.reflection.MethodAccess; -import openmods.reflection.MethodAccess.Function0; -import openmods.renderer.PreWorldRenderHookVisitor; -import openmods.utils.render.FramebufferBlitter; -import openmods.utils.render.RenderUtils; -import org.lwjgl.opengl.GL11; - -public class SkyBlockRenderer implements IResourceManagerReloadListener { - - public static final SkyBlockRenderer INSTANCE = new SkyBlockRenderer(); - - private Framebuffer skyFb; - - private boolean isActive; - - private int stencilBit = -1; - - private int stencilMask; - - private int lastRenderUsers; - - private boolean skyCaptured; - - public boolean hasSkyTexture() { - return isActive && skyCaptured; - } - - public int getStencilMask() { - return stencilMask; - } - - private static Runnable NULL_HOOK = () -> {}; - - private class SkyCapture implements Runnable { - - @Override - public void run() { - // There may be single frame, when we have users, but no sky. That's acceptable IMO - skyCaptured = lastRenderUsers > 0; - if (!skyCaptured) return; - lastRenderUsers = 0; - - final Framebuffer mcFb = Minecraft.getMinecraft().getFramebuffer(); - - if (skyFb == null) { - skyFb = new Framebuffer(mcFb.framebufferWidth, mcFb.framebufferHeight, false); - } else if (skyFb.framebufferWidth != mcFb.framebufferWidth || - skyFb.framebufferHeight != mcFb.framebufferHeight) { - skyFb.createBindFramebuffer(mcFb.framebufferWidth, mcFb.framebufferHeight); - } - - FramebufferBlitter.INSTANCE.blitFramebuffer(mcFb, skyFb); - - mcFb.bindFramebuffer(false); - } - } - - public void incrementUsers() { - lastRenderUsers++; - } - - @Override - public void onResourceManagerReload(IResourceManager resourceManager) { - final boolean canActivate = checkActivationConditions(); - - if (canActivate) { - if (!isActive) { - isActive = activate(); - } - } else { - if (isActive) { - deactivate(); - isActive = false; - } - } - } - - private static boolean checkActivationConditions() { - if (!Config.renderSkyBlocks) { - Log.info("Disabled by config"); - return false; - } - - if (FMLClientHandler.instance().hasOptifine() && optifineShadersEnabled()) { - if (Config.skyBlocksOptifineOverride) { - Log.warn("Optifine detected: skyblocks + shaders may hang your game"); - } else { - Log.info("Disabled due to Optifine shaders (use `optifineOverride` config to override)"); - return false; - } - } - - if (!OpenGlHelper.isFramebufferEnabled()) { - Log.info("Framebuffer not enabled"); - return false; - } - - if (!FramebufferBlitter.INSTANCE.isValid()) { - Log.info("Framebuffer blit not enabled"); - return false; - } - - if (!PreWorldRenderHookVisitor.isActive()) { - Log.info("Pre-world render hook not active"); - return false; - } - - final Framebuffer mcFb = Minecraft.getMinecraft().getFramebuffer(); - - if (!mcFb.isStencilEnabled() && !mcFb.enableStencil()) { - Log.info("Stencil not enabled"); - return false; - } - - return true; - } - - private static boolean optifineShadersEnabled() { - try { - final Class config = Class.forName("Config"); - final Function0 isShaders = MethodAccess.create(boolean.class, config, "isShaders"); - return isShaders.call(null); - } catch (Exception e) { - Log.info(e, "Failed to read Optifine config"); - } - - // can't tell, assume the worst - return true; - } - - private boolean activate() { - stencilBit = MinecraftForgeClient.reserveStencilBit(); - if (stencilBit < 0) { - Log.info("All stencil bits reserved"); - return false; - } - - PreWorldRenderHookVisitor.setHook(new SkyCapture()); - Log.debug("Sky block rendering initialized correctly, stencilBit = %d", stencilBit); - stencilMask = 1 << stencilBit; - - return true; - } - - private void deactivate() { - PreWorldRenderHookVisitor.setHook(NULL_HOOK); - - if (stencilBit >= 0) { - MinecraftForgeClient.releaseStencilBit(stencilBit); - stencilBit = -1; - } - - Log.debug("Sky block rendering deactivated"); - } - - public void bindSkyTexture() { - skyFb.bindFramebufferTexture(); - } - - public void renderSkyTexture() { - if (!isActive) return; - - final Minecraft mc = Minecraft.getMinecraft(); - final Framebuffer mcFb = mc.getFramebuffer(); - - GlStateManager.disableFog(); - RenderUtils.disableLightmap(); - - GlStateManager.matrixMode(GL11.GL_PROJECTION); - GlStateManager.pushMatrix(); - GlStateManager.matrixMode(GL11.GL_MODELVIEW); - GlStateManager.pushMatrix(); - - GlStateManager.depthMask(false); - skyFb.framebufferRender(mc.displayWidth, mc.displayHeight); - GlStateManager.enableDepth(); - GlStateManager.viewport(0, 0, mcFb.framebufferWidth, mcFb.framebufferHeight); - - GlStateManager.popMatrix(); - GlStateManager.matrixMode(GL11.GL_PROJECTION); - GlStateManager.popMatrix(); - GlStateManager.matrixMode(GL11.GL_MODELVIEW); - - RenderUtils.enableLightmap(); - GlStateManager.enableFog(); - } - -} diff --git a/src/main/java/openblocks/client/renderer/skyblock/SkyBlockCustomLayer.java b/src/main/java/openblocks/client/renderer/skyblock/SkyBlockCustomLayer.java new file mode 100644 index 000000000..7972205d3 --- /dev/null +++ b/src/main/java/openblocks/client/renderer/skyblock/SkyBlockCustomLayer.java @@ -0,0 +1,64 @@ +package openblocks.client.renderer.skyblock; + +import net.minecraft.util.BlockRenderLayer; +import openmods.renderer.renderlayer.ICustomRenderLayer; +import openmods.renderer.shaders.ShaderProgram; + +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; + +public class SkyBlockCustomLayer implements ICustomRenderLayer { + private static SkyBlockCustomLayer INSTANCE; + private final Map>, Integer> ORDINALS = Collections.synchronizedMap(new WeakHashMap<>()); + + private BlockRenderLayer layer; + private boolean layerInitialized = false; + + public SkyBlockCustomLayer() { + INSTANCE = this; + } + + public static SkyBlockCustomLayer instance() { + return INSTANCE; + } + + @Override + public ShaderProgram shader() { + return SkyBlockRenderer.INSTANCE.shader(); + } + + @Override + public String variantName() { + return "SKY_BLOCK"; + } + + @Override + public > void setOrdinal(Class enumClass, int ordinal) { + ORDINALS.put(enumClass, ordinal); + } + + @Override + public > int ordinal(Class enumClass) { + return ORDINALS.getOrDefault(enumClass, -1); + } + + public BlockRenderLayer getBlockRenderLayer() { + if (!layerInitialized) { + layerInitialized = true; + int ordinal = ordinal(BlockRenderLayer.class); + layer = ordinal == -1 ? null : BlockRenderLayer.values()[ordinal]; + } + return layer; + } + + @Override + public boolean preRenderLayer() { + return SkyBlockRenderer.INSTANCE.preRenderLayer(); + } + + @Override + public void postRenderLayer() { + SkyBlockRenderer.INSTANCE.postRenderLayer(); + } +} diff --git a/src/main/java/openblocks/client/renderer/skyblock/SkyBlockRenderer.java b/src/main/java/openblocks/client/renderer/skyblock/SkyBlockRenderer.java new file mode 100644 index 000000000..b706cd413 --- /dev/null +++ b/src/main/java/openblocks/client/renderer/skyblock/SkyBlockRenderer.java @@ -0,0 +1,147 @@ +package openblocks.client.renderer.skyblock; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.client.FMLClientHandler; +import openblocks.Config; +import openblocks.OpenBlocks; +import openmods.Log; +import openmods.mixins.Mods; +import openmods.reflection.MethodAccess; +import openmods.reflection.MethodAccess.Function0; +import openmods.renderer.shaders.ShaderProgram; +import openmods.renderer.shaders.ShaderProgramBuilder; +import openmods.utils.render.FramebufferBlitter; +import org.lwjgl.opengl.GL20; + +public class SkyBlockRenderer implements IResourceManagerReloadListener { + public static final SkyBlockRenderer INSTANCE = new SkyBlockRenderer(); + private static final ResourceLocation VERTEX_SOURCE_LOC = OpenBlocks.location("shaders/skyblock/" + renderBackend() + "/skyblock.vert"); + private static final ResourceLocation FRAGMENT_SOURCE_LOC = OpenBlocks.location("shaders/skyblock/" + renderBackend() + "/skyblock.frag"); + + private Framebuffer skyFb; + private boolean isActive; + + private ShaderProgram shader; + + public ShaderProgram shader() { + return shader; + } + + @Override + public void onResourceManagerReload(IResourceManager resourceManager) { + isActive = checkActivationConditions(); + if (isActive) { + ShaderProgramBuilder builder = new ShaderProgramBuilder(); + builder.addShader(VERTEX_SOURCE_LOC, GL20.GL_VERTEX_SHADER); + builder.addShader(FRAGMENT_SOURCE_LOC, GL20.GL_FRAGMENT_SHADER); + if (Mods.Loaded.nothirium()) { + builder.addAttribute("a_Pos", 0); + builder.addAttribute("a_Offset", 4); + } + shader = builder.build(); + Log.info("Sky block renderer activated using %s backend", renderBackend()); + } + } + + public boolean isActive() { + return isActive; + } + + private static String renderBackend() { + return Mods.Loaded.nothirium() ? Mods.NOTHIRIUM : Mods.MINECRAFT; + } + + private static boolean checkActivationConditions() { + if (!Config.renderSkyBlocks) { + Log.info("Disabled by config"); + return false; + } + + // force class load + BlockRenderLayer ignored = BlockRenderLayer.SOLID; + + if (SkyBlockCustomLayer.instance() == null) { + Log.info("Custom sky block render layer was not initialized, did you enable custom_render_layers and sky_block_rendering?"); + return false; + } + + if (SkyBlockCustomLayer.instance().getBlockRenderLayer() == null) { + Log.severe("Custom sky block render layer is missing, this is not a good sign"); + return false; + } + + if (FMLClientHandler.instance().hasOptifine() && optifineShadersEnabled()) { + if (Config.skyBlocksOptifineOverride) { + Log.warn("Optifine detected: skyblocks + shaders may hang your game"); + } else { + Log.info("Disabled due to Optifine shaders (use `optifineOverride` config to override)"); + return false; + } + } + + if (!OpenGlHelper.isFramebufferEnabled()) { + Log.info("Framebuffer not enabled"); + return false; + } + + if (!FramebufferBlitter.INSTANCE.isValid()) { + Log.info("Framebuffer blit not enabled"); + return false; + } + + return true; + } + + private static boolean optifineShadersEnabled() { + try { + final Class config = Class.forName("Config"); + final Function0 isShaders = MethodAccess.create(boolean.class, config, "isShaders"); + return isShaders.call(null); + } catch (Exception e) { + Log.info(e, "Failed to read Optifine config"); + } + + // can't tell, assume the worst + return true; + } + + public void preTerrainRenderHook() { + final Framebuffer fb = Minecraft.getMinecraft().getFramebuffer(); + + if (skyFb == null) { + skyFb = new Framebuffer(fb.framebufferWidth, fb.framebufferHeight, false); + } else if (skyFb.framebufferWidth != fb.framebufferWidth || skyFb.framebufferHeight != fb.framebufferHeight) { + skyFb.createBindFramebuffer(fb.framebufferWidth, fb.framebufferHeight); + } + + FramebufferBlitter.INSTANCE.blitFramebuffer(fb, skyFb); + + fb.bindFramebuffer(false); + } + + public boolean preRenderLayer() { + if (!isActive) return false; + + shader.bind(); + final Minecraft mc = Minecraft.getMinecraft(); + shader.uniform1i("skyboxTexture", 0); + shader.uniform2f("screenSize", mc.displayWidth, mc.displayHeight); + + GlStateManager.disableAlpha(); + skyFb.bindFramebufferTexture(); + return true; + } + + public void postRenderLayer() { + shader.release(); + + GlStateManager.enableAlpha(); + } +} diff --git a/src/main/java/openblocks/client/renderer/tileentity/TileEntitySkyRenderer.java b/src/main/java/openblocks/client/renderer/tileentity/TileEntitySkyRenderer.java deleted file mode 100644 index 789f91024..000000000 --- a/src/main/java/openblocks/client/renderer/tileentity/TileEntitySkyRenderer.java +++ /dev/null @@ -1,174 +0,0 @@ -package openblocks.client.renderer.tileentity; - -import com.google.common.collect.Maps; -import java.util.Map; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BlockRendererDispatcher; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; -import net.minecraftforge.client.MinecraftForgeClient; -import net.minecraftforge.client.event.ModelBakeEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import openblocks.client.renderer.SkyBlockRenderer; -import openblocks.common.block.BlockSky; -import openblocks.common.tileentity.TileEntitySky; -import openmods.renderer.CachedRendererFactory; -import openmods.renderer.CachedRendererFactory.CachedRenderer; -import openmods.utils.FakeBlockAccess; -import openmods.utils.render.RenderUtils; -import org.lwjgl.opengl.GL11; - -public class TileEntitySkyRenderer extends TileEntitySpecialRenderer { - - public TileEntitySkyRenderer() { - MinecraftForge.EVENT_BUS.register(this); - } - - private CachedRenderer skyTextureRenderer = null; - - @Override - public void render(TileEntitySky te, double x, double y, double z, float partialTickTime, int destroyStage, float alpha) { - BlockPos pos = te.getPos(); - IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos); - IBlockState state = world.getBlockState(pos).getActualState(world, pos); - - if (!(state.getBlock() instanceof BlockSky) || !BlockSky.isActive(state)) return; - - SkyBlockRenderer.INSTANCE.incrementUsers(); - - final int stencilMask = SkyBlockRenderer.INSTANCE.getStencilMask(); - final boolean stencilActive = stencilMask >= 0 && SkyBlockRenderer.INSTANCE.hasSkyTexture(); - if (stencilActive) { - GL11.glEnable(GL11.GL_STENCIL_TEST); - GL11.glStencilMask(stencilMask); - GL11.glStencilFunc(GL11.GL_ALWAYS, stencilMask, stencilMask); - GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); - - GL11.glColorMask(false, false, false, false); - } - - GlStateManager.enableTexture2D(); - renderModel(x, y, z, pos, world, state); - - if (stencilActive) { - GL11.glStencilFunc(GL11.GL_EQUAL, stencilMask, stencilMask); - // clears our bit - GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ZERO); - - SkyBlockRenderer.INSTANCE.bindSkyTexture(); - - if (skyTextureRenderer == null) { - skyTextureRenderer = createSkyTextureRenderer(); - } - - skyTextureRenderPre(); - skyTextureRenderer.render(); - skyTextureRenderPost(); - GL11.glDisable(GL11.GL_STENCIL_TEST); - } - } - - private static CachedRenderer createSkyTextureRenderer() { - final Tessellator tessellator = Tessellator.getInstance(); - final BufferBuilder bufferbuilder = tessellator.getBuffer(); - bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - bufferbuilder.pos(-1, -1, 0).tex(0, 0).endVertex(); - bufferbuilder.pos(-1, 1, 0).tex(0, 1).endVertex(); - bufferbuilder.pos(1, 1, 0).tex(1, 1).endVertex(); - bufferbuilder.pos(1, -1, 0).tex(1, 0).endVertex(); - - return new CachedRendererFactory().createRenderer(tessellator); - } - - private static void skyTextureRenderPre() { - GlStateManager.disableFog(); - RenderUtils.disableLightmap(); - - GlStateManager.colorMask(true, true, true, false); - GlStateManager.disableDepth(); - GlStateManager.depthMask(false); - - GlStateManager.disableBlend(); - - GlStateManager.disableLighting(); - GlStateManager.disableAlpha(); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - - GlStateManager.disableCull(); - - GlStateManager.matrixMode(GL11.GL_PROJECTION); - GlStateManager.pushMatrix(); - GlStateManager.loadIdentity(); - - GlStateManager.matrixMode(GL11.GL_MODELVIEW); - GlStateManager.pushMatrix(); - GlStateManager.loadIdentity(); - } - - private static void skyTextureRenderPost() { - GlStateManager.popMatrix(); - GlStateManager.matrixMode(GL11.GL_PROJECTION); - GlStateManager.popMatrix(); - GlStateManager.matrixMode(GL11.GL_MODELVIEW); - - GlStateManager.enableLighting(); - GlStateManager.enableAlpha(); - - GlStateManager.disableCull(); - GlStateManager.enableDepth(); - GlStateManager.depthMask(true); - GlStateManager.colorMask(true, true, true, true); - - RenderUtils.enableLightmap(); - GlStateManager.enableFog(); - } - - private final Map renderers = Maps.newHashMap(); - - private static CachedRenderer createRenderer(IBlockState state) { - final BlockRendererDispatcher blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher(); - final IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state); - - final Tessellator tessellator = Tessellator.getInstance(); - final BufferBuilder renderer = tessellator.getBuffer(); - renderer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - - final IBlockAccess fakeBlockAccess = new FakeBlockAccess(state); - blockRenderer.getBlockModelRenderer().renderModel(fakeBlockAccess, model, state, FakeBlockAccess.ORIGIN, renderer, false); - - return new CachedRendererFactory().createRenderer(tessellator); - } - - private void renderModel(double x, double y, double z, BlockPos pos, IBlockAccess world, IBlockState state) { - bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); - final CachedRenderer renderer = renderers.computeIfAbsent(state, TileEntitySkyRenderer::createRenderer); - - GL11.glPushMatrix(); - GL11.glTranslated(x, y, z); - renderer.render(); - GL11.glPopMatrix(); - } - - @SubscribeEvent - public void onModelBake(ModelBakeEvent evt) { - for (CachedRenderer renderer : renderers.values()) - renderer.dispose(); - renderers.clear(); - - if (skyTextureRenderer != null) { - skyTextureRenderer.dispose(); - skyTextureRenderer = null; - } - } -} diff --git a/src/main/java/openblocks/common/block/BlockSky.java b/src/main/java/openblocks/common/block/BlockSky.java index bd72850de..e3fcf4bb9 100644 --- a/src/main/java/openblocks/common/block/BlockSky.java +++ b/src/main/java/openblocks/common/block/BlockSky.java @@ -1,21 +1,25 @@ package openblocks.common.block; -import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumBlockRenderType; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import openblocks.client.renderer.skyblock.SkyBlockCustomLayer; +import openblocks.client.renderer.skyblock.SkyBlockRenderer; import openmods.block.OpenBlock; import openmods.infobook.BookDocumentation; +import java.util.Random; + @BookDocumentation(customName = "sky.normal") public class BlockSky extends OpenBlock { @@ -46,14 +50,14 @@ protected BlockStateContainer createBlockState() { @Override public IBlockState getStateFromMeta(int meta) { return getDefaultState() - .withProperty(POWERED, (meta & MASK_POWERED) != 0) - .withProperty(INVERTED, (meta & MASK_INVERTED) != 0); + .withProperty(POWERED, (meta & MASK_POWERED) != 0) + .withProperty(INVERTED, (meta & MASK_INVERTED) != 0); } @Override public int getMetaFromState(IBlockState state) { - final int isPowered = state.getValue(POWERED)? MASK_POWERED : 0; - final int isInverted = state.getValue(INVERTED)? MASK_INVERTED : 0; + final int isPowered = state.getValue(POWERED) ? MASK_POWERED : 0; + final int isInverted = state.getValue(INVERTED) ? MASK_INVERTED : 0; return isPowered | isInverted; } @@ -100,12 +104,19 @@ public static boolean isActive(IBlockState state) { @Override @SuppressWarnings("deprecation") public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World world, BlockPos pos) { - return isActive(state)? EMPTY : super.getSelectedBoundingBox(state, world, pos); + return isActive(state) ? EMPTY : super.getSelectedBoundingBox(state, world, pos); } @Override public EnumBlockRenderType getRenderType(IBlockState state) { - return isActive(state)? EnumBlockRenderType.ENTITYBLOCK_ANIMATED : EnumBlockRenderType.MODEL; + return EnumBlockRenderType.MODEL; + } + + @Override + public boolean canRenderInLayer(IBlockState state, BlockRenderLayer layer) { + return isActive(state) && SkyBlockRenderer.INSTANCE.isActive() + ? layer == SkyBlockCustomLayer.instance().getBlockRenderLayer() + : layer == BlockRenderLayer.SOLID; } @Override diff --git a/src/main/java/openblocks/common/tileentity/TileEntitySky.java b/src/main/java/openblocks/common/tileentity/TileEntitySky.java deleted file mode 100644 index 694b72c9a..000000000 --- a/src/main/java/openblocks/common/tileentity/TileEntitySky.java +++ /dev/null @@ -1,17 +0,0 @@ -package openblocks.common.tileentity; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import openmods.tileentity.OpenTileEntity; - -public class TileEntitySky extends OpenTileEntity { - - public TileEntitySky() {} - - @Override - @SideOnly(Side.CLIENT) - public double getMaxRenderDistanceSquared() { - return 256 * 256; - } - -} diff --git a/src/main/java/openblocks/mixins/skyblock/minecraft/EntityRendererMixin.java b/src/main/java/openblocks/mixins/skyblock/minecraft/EntityRendererMixin.java new file mode 100644 index 000000000..4946b26f8 --- /dev/null +++ b/src/main/java/openblocks/mixins/skyblock/minecraft/EntityRendererMixin.java @@ -0,0 +1,21 @@ +package openblocks.mixins.skyblock.minecraft; + +import net.minecraft.client.renderer.EntityRenderer; +import openblocks.client.renderer.skyblock.SkyBlockRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EntityRenderer.class) +public class EntityRendererMixin { + @Inject(method = "renderWorldPass", at = @At( + value = "INVOKE_STRING", + target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V", + args = "ldc=prepareterrain", + shift = At.Shift.AFTER + )) + private void onRenderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) { + SkyBlockRenderer.INSTANCE.preTerrainRenderHook(); + } +} diff --git a/src/main/java/openmods/config/simple/ConfigProcessor.java b/src/main/java/openmods/config/simple/ConfigProcessor.java index 1c7520550..b3d2edd79 100644 --- a/src/main/java/openmods/config/simple/ConfigProcessor.java +++ b/src/main/java/openmods/config/simple/ConfigProcessor.java @@ -7,9 +7,9 @@ import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import openmods.Log; + import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -17,16 +17,16 @@ import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; +import java.nio.file.Files; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Set; -import openmods.Log; public class ConfigProcessor { public interface UpdateListener { - public void valueSet(String value); + void valueSet(String value); } private static class EntryMeta { @@ -55,7 +55,7 @@ public String toString() { } } - private Map entries = Maps.newHashMap(); + private final Map entries = Maps.newHashMap(); public void addEntry(String name, int version, String defaultValue, UpdateListener listener, String... comment) { Preconditions.checkNotNull(listener); @@ -130,21 +130,10 @@ public void process(File config) { } private static void writeFile(File output, Map values) { - try { - OutputStream stream = new FileOutputStream(output); - - try { - Writer writer = new OutputStreamWriter(stream, Charsets.UTF_8); - - try { - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - gson.toJson(values, writer); - } finally { - writer.close(); - } - - } finally { - stream.close(); + try (OutputStream stream = Files.newOutputStream(output.toPath())) { + try (Writer writer = new OutputStreamWriter(stream, Charsets.UTF_8)) { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + gson.toJson(values, writer); } } catch (IOException e) { throw new RuntimeException(e); @@ -153,17 +142,10 @@ private static void writeFile(File output, Map values) { private static Map readFile(File input) { if (!input.exists()) return null; - try { - InputStream stream = new FileInputStream(input); - - try { - Reader reader = new InputStreamReader(stream, Charsets.UTF_8); - Gson gson = new Gson(); - return gson.fromJson(reader, EntryCollection.class); - - } finally { - stream.close(); - } + try (InputStream stream = Files.newInputStream(input.toPath())) { + Reader reader = new InputStreamReader(stream, Charsets.UTF_8); + Gson gson = new Gson(); + return gson.fromJson(reader, EntryCollection.class); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/openmods/core/OpenModsCorePlugin.java b/src/main/java/openmods/core/OpenModsCorePlugin.java index 2831980e9..921ee1562 100644 --- a/src/main/java/openmods/core/OpenModsCorePlugin.java +++ b/src/main/java/openmods/core/OpenModsCorePlugin.java @@ -1,19 +1,22 @@ package openmods.core; -import java.util.Map; - import info.openmods.openblocks.Tags; import net.minecraft.launchwrapper.Launch; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.SortingIndex; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; import openmods.Log; +import openmods.mixins.Mixins; +import zone.rong.mixinbooter.Context; +import zone.rong.mixinbooter.IEarlyMixinLoader; + +import java.util.List; +import java.util.Map; //must be lower than all dependent ones @SortingIndex(16) @TransformerExclusions({ "openmods.asm.", "openmods.include.", "openmods.core.", "openmods.injector.", "openmods.Log" }) -public class OpenModsCorePlugin implements IFMLLoadingPlugin { - +public class OpenModsCorePlugin implements IFMLLoadingPlugin, IEarlyMixinLoader { public static final String CORE_MARKER = "OpenModsCoreLoaded"; public OpenModsCorePlugin() { @@ -46,4 +49,13 @@ public String getAccessTransformerClass() { return null; } + @Override + public List getMixinConfigs() { + return Mixins.getEarlyMixinConfigs(); + } + + @Override + public boolean shouldMixinConfigQueue(Context context) { + return Mixins.shouldEarlyMixinConfigQueue(context); + } } diff --git a/src/main/java/openmods/core/OpenModsLateMixinLoader.java b/src/main/java/openmods/core/OpenModsLateMixinLoader.java new file mode 100644 index 000000000..724275652 --- /dev/null +++ b/src/main/java/openmods/core/OpenModsLateMixinLoader.java @@ -0,0 +1,19 @@ +package openmods.core; + +import openmods.mixins.Mixins; +import zone.rong.mixinbooter.Context; +import zone.rong.mixinbooter.ILateMixinLoader; + +import java.util.List; + +public class OpenModsLateMixinLoader implements ILateMixinLoader { + @Override + public List getMixinConfigs() { + return Mixins.getLateMixinConfigs(); + } + + @Override + public boolean shouldMixinConfigQueue(Context context) { + return Mixins.shouldLateMixinConfigQueue(context); + } +} diff --git a/src/main/java/openmods/mixins/EnumMixinUtil.java b/src/main/java/openmods/mixins/EnumMixinUtil.java new file mode 100644 index 000000000..004abe4ed --- /dev/null +++ b/src/main/java/openmods/mixins/EnumMixinUtil.java @@ -0,0 +1,72 @@ +package openmods.mixins; + +import info.openmods.openblocks.Tags; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.WeakHashMap; + +public final class EnumMixinUtil { + private static final Logger LOGGER = LogManager.getLogger(Tags.MOD_ID); + + private static class ServiceLoaderCache { + private final Map, ServiceLoader> cache = new WeakHashMap<>(); + + @SuppressWarnings("unchecked") + public ServiceLoader get(Class key) { + return (ServiceLoader) cache.computeIfAbsent(key, ServiceLoader::load); + } + } + + private static final ServiceLoaderCache SERVICE_LOADER_CACHE = new ServiceLoaderCache(); + + private EnumMixinUtil() {} + + public interface VariantGenerator, INTERFACE> { + ENUM createVariant(INTERFACE newVariant, int ordinal); + } + + public static , SERVICE> ENUM[] createNewVariantArray( + ENUM[] originalVariants, + Class serviceClass, + VariantGenerator generator + ) { + int ordinal = originalVariants[originalVariants.length - 1].ordinal() + 1; + ArrayList variants = new ArrayList<>(Arrays.asList(originalVariants)); + + ServiceLoader customServices = SERVICE_LOADER_CACHE.get(serviceClass); + Iterator customServiceIter = customServices.iterator(); + while (customServiceIter.hasNext()) { + SERVICE service; + try { + service = customServiceIter.next(); + } catch (Throwable throwable) { + LOGGER.error("Failed to load an enum extension service implementation, skipping it", throwable); + continue; + } + variants.add(generator.createVariant(service, ordinal)); + ordinal++; + } + + return variants.toArray(originalVariants); + } + + public static String upperSnakeCaseToTitleCase(String input) { + String[] words = input.toLowerCase(Locale.ROOT).split("_"); + + StringBuilder formattedName = new StringBuilder(); + for (String word : words) { + formattedName.append(Character.toUpperCase(word.charAt(0))) + .append(word.substring(1)) + .append(" "); + } + + return formattedName.toString().trim(); + } +} diff --git a/src/main/java/openmods/mixins/MixinBuilder.java b/src/main/java/openmods/mixins/MixinBuilder.java new file mode 100644 index 000000000..62a8d96c2 --- /dev/null +++ b/src/main/java/openmods/mixins/MixinBuilder.java @@ -0,0 +1,76 @@ +package openmods.mixins; + +import zone.rong.mixinbooter.Context; + +import java.util.HashMap; +import java.util.Map; + +public class MixinBuilder { + final Map earlyConfigs = new HashMap<>(); + final Map lateConfigs = new HashMap<>(); + + final String configName; + + boolean defaultEnabled = true; + String[] description = null; + + @FunctionalInterface + public interface ShouldMixinLoadCheck { + boolean shouldLoad(Context context); + } + + public enum Phase { + EARLY, + LATE, + } + + private MixinBuilder(String configName) { + this.configName = configName; + } + + static MixinBuilder create(String configName) { + return new MixinBuilder(configName); + } + + public MixinBuilder disableByDefault() { + this.defaultEnabled = false; + return this; + } + + public MixinBuilder setDescription(String... description) { + this.description = description; + return this; + } + + private MixinBuilder put(Phase phase, ShouldMixinLoadCheck condition, String... configNames) { + Map targetMap = phase == Phase.EARLY ? earlyConfigs : lateConfigs; + for (String configName : configNames) { + targetMap.put(configName, condition); + } + return this; + } + + public MixinBuilder early(ShouldMixinLoadCheck condition, String... configNames) { + return put(Phase.EARLY, condition, configNames); + } + + public MixinBuilder early(String... configNames) { + return early(ctx -> true, configNames); + } + + public MixinBuilder earlyMod(String modName, String... configNames) { + return early(ctx -> ctx.isModPresent(modName), configNames); + } + + public MixinBuilder late(ShouldMixinLoadCheck condition, String... configNames) { + return put(Phase.LATE, condition, configNames); + } + + public MixinBuilder late(String... configNames) { + return late(ctx -> true, configNames); + } + + public MixinBuilder lateMod(String modName, String... configNames) { + return late(ctx -> ctx.isModPresent(modName), configNames); + } +} diff --git a/src/main/java/openmods/mixins/Mixins.java b/src/main/java/openmods/mixins/Mixins.java new file mode 100644 index 000000000..3871ae0f2 --- /dev/null +++ b/src/main/java/openmods/mixins/Mixins.java @@ -0,0 +1,48 @@ +package openmods.mixins; + +import zone.rong.mixinbooter.Context; + +import java.util.List; + +public enum Mixins { + CUSTOM_RENDER_LAYERS( + Static.MIXIN_HANDLER.create("custom_render_layers") + .setDescription("Adds support for custom render layers") + .early("mixins.openmods.customrenderlayer.minecraft.json") + .lateMod(Mods.NOTHIRIUM, "mixins.openmods.customrenderlayer.nothirium.json") + ), + SKY_BLOCK_RENDERING( + Static.MIXIN_HANDLER.create("sky_block_rendering") + .setDescription("Adds skybox rendering for sky blocks", "Requires \"custom_render_layers\"") + .early("mixins.openblocks.skyblock.minecraft.json") + ), + ; + + private static class Static { + public static final OpenModsMixinHandler MIXIN_HANDLER = new OpenModsMixinHandler("openblocks-reopened.mixin.properties"); + } + + Mixins(MixinBuilder mixin) { + Static.MIXIN_HANDLER.registerMixin(mixin); + } + + static { + Static.MIXIN_HANDLER.generateDefaultConfigIfMissing(); + } + + public static List getEarlyMixinConfigs() { + return Static.MIXIN_HANDLER.getMixinConfigs(MixinBuilder.Phase.EARLY); + } + + public static List getLateMixinConfigs() { + return Static.MIXIN_HANDLER.getMixinConfigs(MixinBuilder.Phase.LATE); + } + + public static boolean shouldEarlyMixinConfigQueue(Context context) { + return Static.MIXIN_HANDLER.shouldMixinConfigQueue(MixinBuilder.Phase.EARLY, context); + } + + public static boolean shouldLateMixinConfigQueue(Context context) { + return Static.MIXIN_HANDLER.shouldMixinConfigQueue(MixinBuilder.Phase.LATE, context); + } +} diff --git a/src/main/java/openmods/mixins/Mods.java b/src/main/java/openmods/mixins/Mods.java new file mode 100644 index 000000000..ad0dc982f --- /dev/null +++ b/src/main/java/openmods/mixins/Mods.java @@ -0,0 +1,30 @@ +package openmods.mixins; + +import net.minecraftforge.fml.common.Loader; + +public class Mods { + public static final String MINECRAFT = "minecraft"; + public static final String NOTHIRIUM = "nothirium"; + + public static class Loaded { + private static final Loaded NOTHIRIUM = new Loaded(Mods.NOTHIRIUM); + + public static boolean nothirium() {return NOTHIRIUM.loaded();} + + private final String modId; + private boolean loaded = false; + private boolean initialized = false; + + Loaded(String modId) { + this.modId = modId; + } + + private boolean loaded() { + if (!initialized) { + initialized = true; + loaded = Loader.isModLoaded(modId); + } + return loaded; + } + } +} diff --git a/src/main/java/openmods/mixins/OpenModsMixinConfig.java b/src/main/java/openmods/mixins/OpenModsMixinConfig.java new file mode 100644 index 000000000..dc7732cdd --- /dev/null +++ b/src/main/java/openmods/mixins/OpenModsMixinConfig.java @@ -0,0 +1,74 @@ +package openmods.mixins; + +import info.openmods.openblocks.Tags; +import net.minecraft.launchwrapper.Launch; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +public class OpenModsMixinConfig { + private static final Logger LOGGER = LogManager.getLogger(Tags.MOD_ID); + + private final String configFileName; + private final Path propertiesFile; + private final Properties properties; + public final List defaultConfigLines = new ArrayList<>(); + + public OpenModsMixinConfig(String configFileName) { + this.configFileName = configFileName; + this.propertiesFile = Launch.minecraftHome.toPath() + .resolve("config") + .resolve(configFileName); + this.properties = loadEarlyConfig(); + this.defaultConfigLines.add("# " + configFileName + " - Mixin configuration file"); + } + + public boolean getBoolean(String key, boolean defaultValue) { + String value = properties.getProperty(key); + if (value == null) return defaultValue; + return Boolean.parseBoolean(value); + } + + public void registerConfig(String configName, boolean defaultEnabled, String... comments) { + defaultConfigLines.add("#"); + if (comments != null) { + for (String comment : comments) { + defaultConfigLines.add("# " + comment); + } + } + defaultConfigLines.add(configName + "=" + defaultEnabled); + } + + public void generateDefaultConfigIfMissing() { + if (Files.exists(propertiesFile)) return; + + try { + Files.write(propertiesFile, defaultConfigLines); + } catch (IOException e) { + LOGGER.warn("Failed to create {}, using default config values", configFileName, e); + } + } + + private Properties loadEarlyConfig() { + Properties properties = new Properties(); + if (!Files.exists(propertiesFile)) { + LOGGER.warn("{} not found, a default config will be generated", configFileName); + return properties; + } + + try { + properties.load(Files.newInputStream(propertiesFile)); + } catch (Exception e) { + LOGGER.warn("Failed to load {}, using default config values", configFileName, e); + } + + return properties; + } +} + diff --git a/src/main/java/openmods/mixins/OpenModsMixinHandler.java b/src/main/java/openmods/mixins/OpenModsMixinHandler.java new file mode 100644 index 000000000..46645c231 --- /dev/null +++ b/src/main/java/openmods/mixins/OpenModsMixinHandler.java @@ -0,0 +1,53 @@ +package openmods.mixins; + +import zone.rong.mixinbooter.Context; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OpenModsMixinHandler { + private final Map earlyConfigs = new HashMap<>(); + private final Map lateConfigs = new HashMap<>(); + + private final OpenModsMixinConfig mixinConfig; + + public OpenModsMixinHandler(String configFileName) { + this.mixinConfig = new OpenModsMixinConfig(configFileName); + } + + public MixinBuilder create(String configName) { + return MixinBuilder.create(configName); + } + + public void generateDefaultConfigIfMissing() { + mixinConfig.generateDefaultConfigIfMissing(); + } + + private Map getTargetMap(MixinBuilder.Phase phase) { + return phase == MixinBuilder.Phase.EARLY ? earlyConfigs : lateConfigs; + } + + public void registerMixin(MixinBuilder mixin) { + mixinConfig.registerConfig(mixin.configName, mixin.defaultEnabled, mixin.description); + + boolean configEnabled = mixinConfig.getBoolean(mixin.configName, mixin.defaultEnabled); + for (Map.Entry entry : mixin.earlyConfigs.entrySet()) { + earlyConfigs.put(entry.getKey(), context -> entry.getValue().shouldLoad(context) && configEnabled); + } + for (Map.Entry entry : mixin.lateConfigs.entrySet()) { + lateConfigs.put(entry.getKey(), context -> entry.getValue().shouldLoad(context) && configEnabled); + } + } + + public List getMixinConfigs(MixinBuilder.Phase phase) { + return new ArrayList<>(getTargetMap(phase).keySet()); + } + + public boolean shouldMixinConfigQueue(MixinBuilder.Phase phase, Context context) { + return getTargetMap(phase) + .getOrDefault(context.mixinConfig(), ctx -> false) + .shouldLoad(context); + } +} diff --git a/src/main/java/openmods/mixins/customrenderlayer/minecraft/BlockRenderLayerMixin.java b/src/main/java/openmods/mixins/customrenderlayer/minecraft/BlockRenderLayerMixin.java new file mode 100644 index 000000000..883fc0424 --- /dev/null +++ b/src/main/java/openmods/mixins/customrenderlayer/minecraft/BlockRenderLayerMixin.java @@ -0,0 +1,53 @@ +package openmods.mixins.customrenderlayer.minecraft; + +import net.minecraft.util.BlockRenderLayer; +import openmods.mixins.EnumMixinUtil; +import openmods.renderer.renderlayer.CustomLayerAccessor; +import openmods.renderer.renderlayer.ICustomRenderLayer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(value = BlockRenderLayer.class, priority = 100) +public class BlockRenderLayerMixin implements CustomLayerAccessor { + @Final + @Mutable + @Shadow(aliases = { "$VALUES", "ENUM$VALUES" }) + private static BlockRenderLayer[] $VALUES; + + @Unique + private ICustomRenderLayer openmods$customLayer; + + static { + $VALUES = EnumMixinUtil.createNewVariantArray( + $VALUES, + ICustomRenderLayer.class, + (ICustomRenderLayer layer, int ordinal) -> { + String variantName = layer.variantName(); + String layerName = EnumMixinUtil.upperSnakeCaseToTitleCase(variantName); + layer.setOrdinal(BlockRenderLayer.class, ordinal); + BlockRenderLayer newLayer = openmods$invokeInit(variantName, ordinal, layerName); + ((CustomLayerAccessor) (Object) newLayer).openmods$setCustomLayer(layer); + return newLayer; + } + ); + } + + @Invoker("") + private static BlockRenderLayer openmods$invokeInit(String internalName, int internalId, String layerName) { + throw new AssertionError(); + } + + @Override + public ICustomRenderLayer openmods$getCustomLayer() { + return openmods$customLayer; + } + + @Override + public void openmods$setCustomLayer(ICustomRenderLayer layer) { + this.openmods$customLayer = layer; + } +} diff --git a/src/main/java/openmods/mixins/customrenderlayer/minecraft/EntityRendererMixin.java b/src/main/java/openmods/mixins/customrenderlayer/minecraft/EntityRendererMixin.java new file mode 100644 index 000000000..5eded0fe2 --- /dev/null +++ b/src/main/java/openmods/mixins/customrenderlayer/minecraft/EntityRendererMixin.java @@ -0,0 +1,38 @@ +package openmods.mixins.customrenderlayer.minecraft; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.EntityRenderer; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.entity.Entity; +import openmods.renderer.renderlayer.CustomLayer; +import openmods.renderer.renderlayer.ICustomRenderLayer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EntityRenderer.class) +public class EntityRendererMixin { + @Inject( + method = "renderWorldPass", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/texture/ITextureObject;restoreLastBlurMipmap()V", + ordinal = 1, + shift = At.Shift.AFTER + ) + ) + private void openmods$renderCustomLayers(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) { + final Minecraft mc = Minecraft.getMinecraft(); + final Entity rwEntity = mc.getRenderViewEntity(); + if (rwEntity == null) return; + + for (ICustomRenderLayer layer : CustomLayer.LAYERS) { + if (layer.preRenderLayer()) { + mc.renderGlobal.renderBlockLayer(layer.getBlockRenderLayer(), partialTicks, pass, rwEntity); + mc.getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); + layer.postRenderLayer(); + } + } + } +} diff --git a/src/main/java/openmods/mixins/customrenderlayer/minecraft/RegionRenderCacheBuilderMixin.java b/src/main/java/openmods/mixins/customrenderlayer/minecraft/RegionRenderCacheBuilderMixin.java new file mode 100644 index 000000000..11f5d3471 --- /dev/null +++ b/src/main/java/openmods/mixins/customrenderlayer/minecraft/RegionRenderCacheBuilderMixin.java @@ -0,0 +1,28 @@ +package openmods.mixins.customrenderlayer.minecraft; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.RegionRenderCacheBuilder; +import net.minecraft.util.BlockRenderLayer; +import openmods.renderer.renderlayer.CustomLayer; +import openmods.renderer.renderlayer.ICustomRenderLayer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(RegionRenderCacheBuilder.class) +public class RegionRenderCacheBuilderMixin { + @Shadow + @Final + private BufferBuilder[] worldRenderers; + + @Inject(method = "", at = @At("RETURN")) + private void openmods$injectCustomLayerBuffers(CallbackInfo ci) { + for (ICustomRenderLayer layer : CustomLayer.LAYERS) { + int ordinal = layer.ordinal(BlockRenderLayer.class); + this.worldRenderers[ordinal] = new BufferBuilder(layer.initialBufferSize()); + } + } +} diff --git a/src/main/java/openmods/mixins/customrenderlayer/nothirium/ChunkRenderPassMixin.java b/src/main/java/openmods/mixins/customrenderlayer/nothirium/ChunkRenderPassMixin.java new file mode 100644 index 000000000..ef8801489 --- /dev/null +++ b/src/main/java/openmods/mixins/customrenderlayer/nothirium/ChunkRenderPassMixin.java @@ -0,0 +1,58 @@ +package openmods.mixins.customrenderlayer.nothirium; + +import meldexun.nothirium.api.renderer.chunk.ChunkRenderPass; +import openmods.mixins.EnumMixinUtil; +import openmods.renderer.renderlayer.CustomLayerAccessor; +import openmods.renderer.renderlayer.ICustomRenderLayer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(value = ChunkRenderPass.class, remap = false, priority = 100) +public class ChunkRenderPassMixin implements CustomLayerAccessor { + @Final + @Mutable + @Shadow(aliases = { "$VALUES", "ENUM$VALUES" }) + private static ChunkRenderPass[] $VALUES; + + @Shadow + @Final + @Mutable + public static ChunkRenderPass[] ALL; + + @Unique + private ICustomRenderLayer openmods$customLayer; + + static { + $VALUES = EnumMixinUtil.createNewVariantArray( + $VALUES, + ICustomRenderLayer.class, + (layer, ordinal) -> { + layer.setOrdinal(ChunkRenderPass.class, ordinal); + ChunkRenderPass newLayer = openmods$invokeInit(layer.variantName(), ordinal); + ((CustomLayerAccessor) (Object) newLayer).openmods$setCustomLayer(layer); + return newLayer; + } + ); + ALL = $VALUES; + } + + @Invoker("") + private static ChunkRenderPass openmods$invokeInit(String internalName, int internalId) { + throw new AssertionError(); + } + + @Override + public ICustomRenderLayer openmods$getCustomLayer() { + return openmods$customLayer; + } + + @Override + public void openmods$setCustomLayer(ICustomRenderLayer layer) { + this.openmods$customLayer = layer; + } +} + diff --git a/src/main/java/openmods/mixins/customrenderlayer/nothirium/ChunkRendererGLMixin.java b/src/main/java/openmods/mixins/customrenderlayer/nothirium/ChunkRendererGLMixin.java new file mode 100644 index 000000000..16dbae8f8 --- /dev/null +++ b/src/main/java/openmods/mixins/customrenderlayer/nothirium/ChunkRendererGLMixin.java @@ -0,0 +1,80 @@ +package openmods.mixins.customrenderlayer.nothirium; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import meldexun.nothirium.api.renderer.chunk.ChunkRenderPass; +import meldexun.nothirium.mc.renderer.chunk.ChunkRendererGL20; +import meldexun.nothirium.mc.renderer.chunk.ChunkRendererGL42; +import meldexun.nothirium.mc.renderer.chunk.ChunkRendererGL43; +import meldexun.nothirium.mc.renderer.chunk.RenderChunk; +import meldexun.nothirium.mc.util.BlockRenderLayerUtil; +import meldexun.nothirium.renderer.chunk.AbstractChunkRenderer; +import meldexun.renderlib.util.GLShader; +import net.minecraft.util.BlockRenderLayer; +import openmods.renderer.renderlayer.CustomLayerAccessor; +import openmods.renderer.renderlayer.ICustomRenderLayer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = { + ChunkRendererGL20.class, + ChunkRendererGL42.class, + ChunkRendererGL43.class, +}, remap = false) +public abstract class ChunkRendererGLMixin extends AbstractChunkRenderer { + @WrapOperation(method = "renderChunks", at = @At(value = "INVOKE", target = "Lmeldexun/renderlib/util/GLShader;use()V")) + private void openmods$overwriteCustomLayerShader( + GLShader instance, + Operation original, + ChunkRenderPass pass, + @Share("customRenderLayer") LocalRef customRenderLayer + ) { + BlockRenderLayer blockRenderLayer = BlockRenderLayerUtil.getBlockRenderLayer(pass); + ICustomRenderLayer layer = ((CustomLayerAccessor) (Object) blockRenderLayer).getCustomLayer(); + + if (layer != null && layer.preRenderLayer()) { + customRenderLayer.set(layer); + } else { + original.call(instance); + } + } + + @WrapOperation(method = "renderChunks", at = @At(value = "INVOKE", target = "Lmeldexun/renderlib/util/GLShader;getUniform(Ljava/lang/String;)I")) + private int openmods$redirectUniform( + GLShader instance, + String uniform, + Operation original, + ChunkRenderPass pass, + @Share("customRenderLayer") LocalRef customRenderLayer + ) { + if (customRenderLayer.get() != null) { + return customRenderLayer.get().shader().getUniformLocation(uniform); + } + return original.call(instance, uniform); + } + + @WrapWithCondition(method = "renderChunks", at = @At(value = "INVOKE", target = "Lmeldexun/nothirium/mc/util/FogUtil;setupFogFromGL(Lmeldexun/renderlib/util/GLShader;)V")) + private boolean openmods$customLayerUniforms( + GLShader fogMode, + ChunkRenderPass pass, + @Share("customRenderLayer") LocalRef customRenderLayer + ) { + return customRenderLayer.get() == null; + } + + @Inject(method = "renderChunks", at = @At(value = "INVOKE", target = "Lmeldexun/renderlib/util/GLShader;pop()V")) + private void openmods$postRenderCustomLayer( + ChunkRenderPass pass, + CallbackInfo ci, + @Share("customRenderLayer") LocalRef customRenderLayer + ) { + if (customRenderLayer.get() != null) { + customRenderLayer.get().postRenderLayer(); + } + } +} diff --git a/src/main/java/openmods/renderer/renderlayer/CustomLayer.java b/src/main/java/openmods/renderer/renderlayer/CustomLayer.java new file mode 100644 index 000000000..a50458575 --- /dev/null +++ b/src/main/java/openmods/renderer/renderlayer/CustomLayer.java @@ -0,0 +1,21 @@ +package openmods.renderer.renderlayer; + +import net.minecraft.util.BlockRenderLayer; + +import java.util.ArrayList; +import java.util.List; + +public class CustomLayer { + public static final ICustomRenderLayer[] LAYERS = findCustomBlockRenderLayers(); + + private static ICustomRenderLayer[] findCustomBlockRenderLayers() { + List customRenderLayers = new ArrayList<>(); + for (BlockRenderLayer layer : BlockRenderLayer.values()) { + ICustomRenderLayer customLayer = ((ICustomRenderLayer.OriginalLayer) (Object) layer).getCustomLayer(); + if (customLayer != null) { + customRenderLayers.add(customLayer); + } + } + return customRenderLayers.toArray(new ICustomRenderLayer[0]); + } +} diff --git a/src/main/java/openmods/renderer/renderlayer/CustomLayerAccessor.java b/src/main/java/openmods/renderer/renderlayer/CustomLayerAccessor.java new file mode 100644 index 000000000..cd5988309 --- /dev/null +++ b/src/main/java/openmods/renderer/renderlayer/CustomLayerAccessor.java @@ -0,0 +1,11 @@ +package openmods.renderer.renderlayer; + +public interface CustomLayerAccessor extends ICustomRenderLayer.OriginalLayer { + default ICustomRenderLayer getCustomLayer() { + return openmods$getCustomLayer(); + } + + ICustomRenderLayer openmods$getCustomLayer(); + + void openmods$setCustomLayer(ICustomRenderLayer layer); +} diff --git a/src/main/java/openmods/renderer/renderlayer/ICustomRenderLayer.java b/src/main/java/openmods/renderer/renderlayer/ICustomRenderLayer.java new file mode 100644 index 000000000..09ce8cc2f --- /dev/null +++ b/src/main/java/openmods/renderer/renderlayer/ICustomRenderLayer.java @@ -0,0 +1,32 @@ +package openmods.renderer.renderlayer; + +import net.minecraft.util.BlockRenderLayer; +import openmods.renderer.shaders.ShaderProgram; + +public interface ICustomRenderLayer { + interface OriginalLayer { + ICustomRenderLayer getCustomLayer(); + } + + /** + * Nothirium: Shader must have a
+ * uniform mat4 u_ModelViewProjectionMatrix + */ + ShaderProgram shader(); + + String variantName(); + + > void setOrdinal(Class enumClass, int ordinal); + + > int ordinal(Class enumClass); + + BlockRenderLayer getBlockRenderLayer(); + + default int initialBufferSize() { + return 131072; + } + + boolean preRenderLayer(); + + void postRenderLayer(); +} diff --git a/src/main/java/openmods/renderer/shaders/ShaderHelper.java b/src/main/java/openmods/renderer/shaders/ShaderHelper.java index 102af8ed0..846e8a4fd 100644 --- a/src/main/java/openmods/renderer/shaders/ShaderHelper.java +++ b/src/main/java/openmods/renderer/shaders/ShaderHelper.java @@ -6,13 +6,12 @@ import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GLContext; +/** + * Class for shader functions, calling ARB methods if GL20 is not supported + * A lot of this is already implemented in OpenGlHelper, but it misses some + * methods and is confusing in general. + */ public class ShaderHelper { - /** - * Class for shader functions, calling ARB methods if GL20 is not supported - * A lot of this is already implemented in OpenGlHelper, but it misses some - * methods and is confusing in general. - */ - static { initialize(); } @@ -34,52 +33,56 @@ public static IShaderMethods methods() { return methods; } - public static interface IShaderMethods { - public int glCreateProgram(); + public interface IShaderMethods { + int glCreateProgram(); + + int glCreateShader(int type); - public int glCreateShader(int type); + void glAttachShader(int program, int shader); - public void glAttachShader(int program, int shader); + void glDetachShader(int program, int shader); - public void glDetachShader(int program, int shader); + void glLinkProgram(int program); - public void glLinkProgram(int program); + void glValidateProgram(int program); - public void glValidateProgram(int program); + void glDeleteProgram(int program); - public void glDeleteProgram(int program); + void glDeleteShader(int shader); - public void glDeleteShader(int shader); + int glGetProgrami(int shader, int parameter); - public int glGetProgrami(int shader, int parameter); + int glGetShaderi(int program, int parameter); - public int glGetShaderi(int program, int parameter); + String getProgramLogInfo(int program); - public String getProgramLogInfo(int program); + String getShaderLogInfo(int shader); - public String getShaderLogInfo(int shader); + void glUseProgram(int program); - public void glUseProgram(int program); + void glShaderSource(int shader, String shaderSource); - public void glShaderSource(int shader, String shaderSource); + void glCompileShader(int shader); - public void glCompileShader(int shader); + int glGetUniformLocation(int program, String uniform); - public int glGetUniformLocation(int program, String uniform); + void glUniform1i(int loc, int val); - public void glUniform1i(int loc, int val); + void glUniform1f(int loc, float val); - public void glUniform1f(int loc, float val); + void glUniform2f(int loc, float u, float v); - public void glUniform3f(int loc, float x, float y, float z); + void glUniform3f(int loc, float x, float y, float z); - public int glGetAttribLocation(int program, String attrib); + int glGetAttribLocation(int program, String attrib); - public void glEnableVertexAttribArray(int index); + void glEnableVertexAttribArray(int index); - public void glDisableVertexAttribArray(int index); + void glDisableVertexAttribArray(int index); - public void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long offset); + void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long offset); + + void glBindAttribLocation(int program, int index, String name); } private static class GL20ShaderMethods implements IShaderMethods { @@ -177,6 +180,11 @@ public void glUniform1f(int loc, float val) { GL20.glUniform1f(loc, val); } + @Override + public void glUniform2f(int loc, float u, float v) { + GL20.glUniform2f(loc, u, v); + } + @Override public void glUniform3f(int loc, float x, float y, float z) { GL20.glUniform3f(loc, x, y, z); @@ -201,6 +209,11 @@ public void glDisableVertexAttribArray(int index) { public void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long offset) { GL20.glVertexAttribPointer(index, size, type, normalized, stride, offset); } + + @Override + public void glBindAttribLocation(int program, int index, String name) { + GL20.glBindAttribLocation(program, index, name); + } } private static class ARBShaderMethods implements IShaderMethods { @@ -298,6 +311,11 @@ public void glUniform1f(int loc, float val) { ARBShaderObjects.glUniform1fARB(loc, val); } + @Override + public void glUniform2f(int loc, float u, float v) { + ARBShaderObjects.glUniform2fARB(loc, u, v); + } + @Override public void glUniform3f(int loc, float x, float y, float z) { ARBShaderObjects.glUniform3fARB(loc, x, y, z); @@ -322,5 +340,10 @@ public void glDisableVertexAttribArray(int index) { public void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long offset) { ARBVertexShader.glVertexAttribPointerARB(index, size, type, normalized, stride, offset); } + + @Override + public void glBindAttribLocation(int program, int index, String name) { + ARBVertexShader.glBindAttribLocationARB(program, index, name); + } } } diff --git a/src/main/java/openmods/renderer/shaders/ShaderProgram.java b/src/main/java/openmods/renderer/shaders/ShaderProgram.java index d087e2f32..5bcfeac51 100644 --- a/src/main/java/openmods/renderer/shaders/ShaderProgram.java +++ b/src/main/java/openmods/renderer/shaders/ShaderProgram.java @@ -3,6 +3,7 @@ import com.google.common.collect.ImmutableList; import gnu.trove.map.TObjectIntMap; import gnu.trove.map.hash.TObjectIntHashMap; + import java.util.List; public class ShaderProgram { @@ -15,8 +16,7 @@ private abstract static class ComputingObjectIntMap extends TObjectIntHashMap public int get(Object key) { int index = index(key); if (index < 0) { - @SuppressWarnings("unchecked") - final T k = (T)key; + @SuppressWarnings("unchecked") final T k = (T) key; final int result = computeValue(k); put(k, result); return result; @@ -63,11 +63,11 @@ public void destroy() { ShaderHelper.methods().glDeleteProgram(program); } - private int getUniformLocation(String uniform) { + public int getUniformLocation(String uniform) { return uniforms.get(uniform); } - private int getAttributeLocation(String attribute) { + public int getAttributeLocation(String attribute) { return attributes.get(attribute); } @@ -81,6 +81,11 @@ public void uniform1f(String name, float val) { if (location >= 0) ShaderHelper.methods().glUniform1f(location, val); } + public void uniform2f(String name, float u, float v) { + final int location = getUniformLocation(name); + if (location >= 0) ShaderHelper.methods().glUniform2f(location, u, v); + } + public void uniform3f(String name, float x, float y, float z) { final int location = getUniformLocation(name); if (location >= 0) ShaderHelper.methods().glUniform3f(location, x, y, z); diff --git a/src/main/java/openmods/renderer/shaders/ShaderProgramBuilder.java b/src/main/java/openmods/renderer/shaders/ShaderProgramBuilder.java index 556a21455..4861a05ea 100644 --- a/src/main/java/openmods/renderer/shaders/ShaderProgramBuilder.java +++ b/src/main/java/openmods/renderer/shaders/ShaderProgramBuilder.java @@ -3,12 +3,8 @@ import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.util.ResourceLocation; import org.apache.commons.io.IOUtils; @@ -16,9 +12,16 @@ import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.OpenGLException; -public class ShaderProgramBuilder { +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +public class ShaderProgramBuilder { private final Map shadersToLoad = Maps.newLinkedHashMap(); + private final Object2IntMap attributes = new Object2IntOpenHashMap<>(); public ShaderProgramBuilder() {} @@ -26,6 +29,10 @@ public void addShader(ResourceLocation source, int type) { shadersToLoad.put(source, type); } + public void addAttribute(String name, int location) { + attributes.put(name, location); + } + public ShaderProgram build() { final int program = ShaderHelper.methods().glCreateProgram(); final List shaders = Lists.newArrayList(); @@ -37,14 +44,22 @@ public ShaderProgram build() { shaders.add(shader); } + for (Map.Entry entry : attributes.entrySet()) { + GL20.glBindAttribLocation(program, entry.getValue(), entry.getKey()); + } + ShaderHelper.methods().glLinkProgram(program); - if (ShaderHelper.methods().glGetProgrami(program, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) throw new OpenGLException("Shader link error: " + ShaderHelper.methods().getProgramLogInfo(program)); + if (ShaderHelper.methods().glGetProgrami(program, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) { + throw new OpenGLException("Shader link error: " + ShaderHelper.methods().getProgramLogInfo(program)); + } for (Integer shader : shaders) ShaderHelper.methods().glDetachShader(program, shader); ShaderHelper.methods().glValidateProgram(program); - if (ShaderHelper.methods().glGetProgrami(program, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE) throw new OpenGLException("Shader validate error: " + ShaderHelper.methods().getProgramLogInfo(program)); + if (ShaderHelper.methods().glGetProgrami(program, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE) { + throw new OpenGLException("Shader validate error: " + ShaderHelper.methods().getProgramLogInfo(program)); + } return new ShaderProgram(program, shaders); } @@ -57,7 +72,9 @@ private static int createShader(ResourceLocation source, int type) { ShaderHelper.methods().glShaderSource(shader, readShaderSource(source)); ShaderHelper.methods().glCompileShader(shader); - if (ShaderHelper.methods().glGetShaderi(shader, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) throw new OpenGLException("Shader compile error: " + ShaderHelper.methods().getShaderLogInfo(shader)); + if (ShaderHelper.methods().glGetShaderi(shader, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) { + throw new OpenGLException("Shader compile error: " + ShaderHelper.methods().getShaderLogInfo(shader)); + } return shader; } catch (Throwable t) { diff --git a/src/main/resources/META-INF/services/openmods.renderer.renderlayer.ICustomRenderLayer b/src/main/resources/META-INF/services/openmods.renderer.renderlayer.ICustomRenderLayer new file mode 100644 index 000000000..ae0003bb6 --- /dev/null +++ b/src/main/resources/META-INF/services/openmods.renderer.renderlayer.ICustomRenderLayer @@ -0,0 +1 @@ +openblocks.client.renderer.skyblock.SkyBlockCustomLayer diff --git a/src/main/resources/assets/openblocks/shaders/skyblock/minecraft/skyblock.frag b/src/main/resources/assets/openblocks/shaders/skyblock/minecraft/skyblock.frag new file mode 100644 index 000000000..5731ee31f --- /dev/null +++ b/src/main/resources/assets/openblocks/shaders/skyblock/minecraft/skyblock.frag @@ -0,0 +1,10 @@ +#version 120 + +uniform sampler2D skyboxTexture; +uniform vec2 screenSize; + +void main() { + vec2 uv = gl_FragCoord.xy / screenSize; + vec4 color = texture2D(skyboxTexture, uv); + gl_FragColor = vec4(color.xyz, 1.0); +} diff --git a/src/main/resources/assets/openblocks/shaders/skyblock/minecraft/skyblock.vert b/src/main/resources/assets/openblocks/shaders/skyblock/minecraft/skyblock.vert new file mode 100644 index 000000000..186e11e2d --- /dev/null +++ b/src/main/resources/assets/openblocks/shaders/skyblock/minecraft/skyblock.vert @@ -0,0 +1,8 @@ +#version 120 + +varying vec3 position; + +void main() { + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + position = gl_Position.xyz; +} diff --git a/src/main/resources/assets/openblocks/shaders/skyblock/nothirium/skyblock.frag b/src/main/resources/assets/openblocks/shaders/skyblock/nothirium/skyblock.frag new file mode 100644 index 000000000..5731ee31f --- /dev/null +++ b/src/main/resources/assets/openblocks/shaders/skyblock/nothirium/skyblock.frag @@ -0,0 +1,10 @@ +#version 120 + +uniform sampler2D skyboxTexture; +uniform vec2 screenSize; + +void main() { + vec2 uv = gl_FragCoord.xy / screenSize; + vec4 color = texture2D(skyboxTexture, uv); + gl_FragColor = vec4(color.xyz, 1.0); +} diff --git a/src/main/resources/assets/openblocks/shaders/skyblock/nothirium/skyblock.vert b/src/main/resources/assets/openblocks/shaders/skyblock/nothirium/skyblock.vert new file mode 100644 index 000000000..c8a1fee3e --- /dev/null +++ b/src/main/resources/assets/openblocks/shaders/skyblock/nothirium/skyblock.vert @@ -0,0 +1,16 @@ +#version 110 + +uniform mat4 u_ModelViewProjectionMatrix; + +attribute vec3 a_Pos; +attribute vec3 a_Offset; +attribute float shaderType; + +varying vec3 position; +varying float vShaderType; + +void main() { + gl_Position = u_ModelViewProjectionMatrix * vec4(a_Pos + a_Offset, 1.0); + position = gl_Position.xyz; + vShaderType = shaderType; +} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index f4007a779..aba953b28 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -16,6 +16,9 @@ "WaitingIdly" ], "useDependencyInformation": true, + "dependencies": [ + "mixinbooter" + ], "dependants": [ "openblocks" ] @@ -37,6 +40,7 @@ ], "useDependencyInformation": true, "dependencies": [ + "mixinbooter", "openmods" ] } diff --git a/src/main/resources/mixins.openblocks.skyblock.minecraft.json b/src/main/resources/mixins.openblocks.skyblock.minecraft.json new file mode 100644 index 000000000..171436b3d --- /dev/null +++ b/src/main/resources/mixins.openblocks.skyblock.minecraft.json @@ -0,0 +1,11 @@ +{ + "package": "openblocks.mixins.skyblock.minecraft", + "refmap": "openblocks.refmap.json", + "minVersion": "0.8", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "EntityRendererMixin" + ] +} diff --git a/src/main/resources/mixins.openmods.customrenderlayer.minecraft.json b/src/main/resources/mixins.openmods.customrenderlayer.minecraft.json new file mode 100644 index 000000000..d5b8e1019 --- /dev/null +++ b/src/main/resources/mixins.openmods.customrenderlayer.minecraft.json @@ -0,0 +1,13 @@ +{ + "package": "openmods.mixins.customrenderlayer.minecraft", + "refmap": "openblocks.refmap.json", + "minVersion": "0.8", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "BlockRenderLayerMixin" + ], + "client": [ + "EntityRendererMixin", + "RegionRenderCacheBuilderMixin" + ] +} diff --git a/src/main/resources/mixins.openmods.customrenderlayer.nothirium.json b/src/main/resources/mixins.openmods.customrenderlayer.nothirium.json new file mode 100644 index 000000000..76a78bec0 --- /dev/null +++ b/src/main/resources/mixins.openmods.customrenderlayer.nothirium.json @@ -0,0 +1,12 @@ +{ + "package": "openmods.mixins.customrenderlayer.nothirium", + "refmap": "openblocks.refmap.json", + "minVersion": "0.8", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "ChunkRendererGLMixin", + "ChunkRenderPassMixin" + ], + "client": [ + ] +}