--- a/net/minecraft/client/renderer/WorldRenderer.java
+++ b/net/minecraft/client/renderer/WorldRenderer.java
@@ -222,6 +222,11 @@
    }
 
    private void func_228438_a_(LightTexture p_228438_1_, float p_228438_2_, double p_228438_3_, double p_228438_5_, double p_228438_7_) {
+      net.minecraftforge.client.IWeatherRenderHandler renderHandler = field_72769_h.func_239132_a_().getWeatherRenderHandler();
+      if (renderHandler != null) {
+         renderHandler.render(field_72773_u, p_228438_2_, field_72769_h, field_72777_q, p_228438_1_, p_228438_3_, p_228438_5_, p_228438_7_);
+         return;
+      }
       float f = this.field_72777_q.field_71441_e.func_72867_j(p_228438_2_);
       if (!(f <= 0.0F)) {
          p_228438_1_.func_205109_c();
@@ -830,7 +835,7 @@
             this.field_147595_R = true;
             BlockPos blockpos2 = chunkrenderdispatcher$chunkrender4.func_178568_j().func_177982_a(8, 8, 8);
             boolean flag1 = blockpos2.func_177951_i(blockpos) < 768.0D;
-            if (!chunkrenderdispatcher$chunkrender4.func_188281_o() && !flag1) {
+            if (net.minecraftforge.common.ForgeConfig.CLIENT.alwaysSetupTerrainOffThread.get() || !chunkrenderdispatcher$chunkrender4.func_188281_o() && !flag1) {
                this.field_175009_l.add(chunkrenderdispatcher$chunkrender4);
             } else {
                this.field_72777_q.func_213239_aq().func_76320_a("build near");
@@ -915,13 +920,13 @@
       float f = p_228426_7_.func_205001_m();
       boolean flag1 = this.field_72777_q.field_71441_e.func_239132_a_().func_230493_a_(MathHelper.func_76128_c(d0), MathHelper.func_76128_c(d1)) || this.field_72777_q.field_71456_v.func_184046_j().func_184056_f();
       if (this.field_72777_q.field_71474_y.field_151451_c >= 4) {
-         FogRenderer.func_228372_a_(p_228426_6_, FogRenderer.FogType.FOG_SKY, f, flag1);
+         FogRenderer.setupFog(p_228426_6_, FogRenderer.FogType.FOG_SKY, f, flag1, p_228426_2_);
          iprofiler.func_219895_b("sky");
          this.func_228424_a_(p_228426_1_, p_228426_2_);
       }
 
       iprofiler.func_219895_b("fog");
-      FogRenderer.func_228372_a_(p_228426_6_, FogRenderer.FogType.FOG_TERRAIN, Math.max(f - 16.0F, 32.0F), flag1);
+      FogRenderer.setupFog(p_228426_6_, FogRenderer.FogType.FOG_TERRAIN, Math.max(f - 16.0F, 32.0F), flag1, p_228426_2_);
       iprofiler.func_219895_b("terrain_setup");
       this.func_228437_a_(p_228426_6_, clippinghelper, flag, this.field_228409_ai_++, this.field_72777_q.field_71439_g.func_175149_v());
       iprofiler.func_219895_b("updatechunks");
@@ -942,7 +947,9 @@
       this.func_174967_a(p_228426_3_ + l1);
       iprofiler.func_219895_b("terrain");
       this.func_228441_a_(RenderType.func_228639_c_(), p_228426_1_, d0, d1, d2);
+      this.field_72777_q.func_209506_al().func_229356_a_(AtlasTexture.field_110575_b).setBlurMipmap(false, this.field_72777_q.field_71474_y.field_151442_I > 0); // FORGE: fix flickering leaves when mods mess up the blurMipmap settings
       this.func_228441_a_(RenderType.func_228641_d_(), p_228426_1_, d0, d1, d2);
+      this.field_72777_q.func_209506_al().func_229356_a_(AtlasTexture.field_110575_b).restoreLastBlurMipmap();
       this.func_228441_a_(RenderType.func_228643_e_(), p_228426_1_, d0, d1, d2);
       if (this.field_72769_h.func_239132_a_().func_239217_c_()) {
          RenderHelper.func_237533_a_(p_228426_1_.func_227866_c_().func_227870_a_());
@@ -1010,6 +1017,7 @@
          List<TileEntity> list = worldrenderer$localrenderinformationcontainer.field_178036_a.func_178571_g().func_178485_b();
          if (!list.isEmpty()) {
             for(TileEntity tileentity1 : list) {
+               if(!clippinghelper.func_228957_a_(tileentity1.getRenderBoundingBox())) continue;
                BlockPos blockpos3 = tileentity1.func_174877_v();
                IRenderTypeBuffer irendertypebuffer1 = irendertypebuffer$impl;
                p_228426_1_.func_227860_a_();
@@ -1035,6 +1043,7 @@
 
       synchronized(this.field_181024_n) {
          for(TileEntity tileentity : this.field_181024_n) {
+            if(!clippinghelper.func_228957_a_(tileentity.getRenderBoundingBox())) continue;
             BlockPos blockpos2 = tileentity.func_174877_v();
             p_228426_1_.func_227860_a_();
             p_228426_1_.func_227861_a_((double)blockpos2.func_177958_n() - d0, (double)blockpos2.func_177956_o() - d1, (double)blockpos2.func_177952_p() - d2);
@@ -1084,10 +1093,13 @@
          iprofiler.func_219895_b("outline");
          BlockPos blockpos = ((BlockRayTraceResult)raytraceresult).func_216350_a();
          BlockState blockstate = this.field_72769_h.func_180495_p(blockpos);
-         if (!blockstate.func_196958_f() && this.field_72769_h.func_175723_af().func_177746_a(blockpos)) {
+         if (!net.minecraftforge.client.ForgeHooksClient.onDrawBlockHighlight(this, p_228426_6_, raytraceresult, p_228426_2_, p_228426_1_, irendertypebuffer$impl))
+         if (!blockstate.isAir(this.field_72769_h, blockpos) && this.field_72769_h.func_175723_af().func_177746_a(blockpos)) {
             IVertexBuilder ivertexbuilder2 = irendertypebuffer$impl.getBuffer(RenderType.func_228659_m_());
             this.func_228429_a_(p_228426_1_, ivertexbuilder2, p_228426_6_.func_216773_g(), d0, d1, d2, blockpos, blockstate);
          }
+      } else if (raytraceresult != null && raytraceresult.func_216346_c() == RayTraceResult.Type.ENTITY) {
+         net.minecraftforge.client.ForgeHooksClient.onDrawBlockHighlight(this, p_228426_6_, raytraceresult, p_228426_2_, p_228426_1_, irendertypebuffer$impl);
       }
 
       RenderSystem.pushMatrix();
@@ -1119,7 +1131,7 @@
          this.field_239224_H_.func_237506_a_(this.field_72777_q.func_147110_a());
          RenderState.field_239237_T_.func_228547_a_();
          iprofiler.func_219895_b("particles");
-         this.field_72777_q.field_71452_i.func_228345_a_(p_228426_1_, irendertypebuffer$impl, p_228426_8_, p_228426_6_, p_228426_2_);
+         this.field_72777_q.field_71452_i.renderParticles(p_228426_1_, irendertypebuffer$impl, p_228426_8_, p_228426_6_, p_228426_2_, clippinghelper);
          RenderState.field_239237_T_.func_228549_b_();
       } else {
          iprofiler.func_219895_b("translucent");
@@ -1129,7 +1141,7 @@
          iprofiler.func_219895_b("string");
          this.func_228441_a_(RenderType.func_241715_r_(), p_228426_1_, d0, d1, d2);
          iprofiler.func_219895_b("particles");
-         this.field_72777_q.field_71452_i.func_228345_a_(p_228426_1_, irendertypebuffer$impl, p_228426_8_, p_228426_6_, p_228426_2_);
+         this.field_72777_q.field_71452_i.renderParticles(p_228426_1_, irendertypebuffer$impl, p_228426_8_, p_228426_6_, p_228426_2_, clippinghelper);
       }
 
       RenderSystem.pushMatrix();
@@ -1481,6 +1493,11 @@
    }
 
    public void func_228424_a_(MatrixStack p_228424_1_, float p_228424_2_) {
+      net.minecraftforge.client.ISkyRenderHandler renderHandler = field_72769_h.func_239132_a_().getSkyRenderHandler();
+      if (renderHandler != null) {
+         renderHandler.render(field_72773_u, p_228424_2_, p_228424_1_, field_72769_h, field_72777_q);
+         return;
+      }
       if (this.field_72777_q.field_71441_e.func_239132_a_().func_241683_c_() == DimensionRenderInfo.FogType.END) {
          this.func_228444_b_(p_228424_1_);
       } else if (this.field_72777_q.field_71441_e.func_239132_a_().func_241683_c_() == DimensionRenderInfo.FogType.NORMAL) {
@@ -1609,6 +1626,11 @@
    }
 
    public void func_228425_a_(MatrixStack p_228425_1_, float p_228425_2_, double p_228425_3_, double p_228425_5_, double p_228425_7_) {
+      net.minecraftforge.client.ICloudRenderHandler renderHandler = field_72769_h.func_239132_a_().getCloudRenderHandler();
+      if (renderHandler != null) {
+         renderHandler.render(field_72773_u, p_228425_2_, p_228425_1_, field_72769_h, field_72777_q, p_228425_3_, p_228425_5_, p_228425_7_);
+         return;
+      }
       float f = this.field_72769_h.func_239132_a_().func_239213_a_();
       if (!Float.isNaN(f)) {
          RenderSystem.disableCull();
@@ -1792,7 +1814,7 @@
 
          while(iterator.hasNext()) {
             ChunkRenderDispatcher.ChunkRender chunkrenderdispatcher$chunkrender = iterator.next();
-            if (chunkrenderdispatcher$chunkrender.func_188281_o()) {
+            if (!net.minecraftforge.common.ForgeConfig.CLIENT.alwaysSetupTerrainOffThread.get() && chunkrenderdispatcher$chunkrender.func_188281_o()) {
                this.field_174995_M.func_228902_a_(chunkrenderdispatcher$chunkrender);
             } else {
                chunkrenderdispatcher$chunkrender.func_228929_a_(this.field_174995_M);
@@ -2076,7 +2098,12 @@
       this.field_175008_n.func_217628_a(p_215319_1_, p_215319_2_, p_215319_3_, p_215319_4_);
    }
 
+   @Deprecated // Forge: use item aware function below
    public void func_184377_a(@Nullable SoundEvent p_184377_1_, BlockPos p_184377_2_) {
+      this.playRecord(p_184377_1_, p_184377_2_, p_184377_1_ == null? null : MusicDiscItem.func_185074_a(p_184377_1_));
+   }
+
+   public void playRecord(@Nullable SoundEvent p_184377_1_, BlockPos p_184377_2_, @Nullable MusicDiscItem musicDiscItem) {
       ISound isound = this.field_147593_P.get(p_184377_2_);
       if (isound != null) {
          this.field_72777_q.func_147118_V().func_147683_b(isound);
@@ -2084,7 +2111,7 @@
       }
 
       if (p_184377_1_ != null) {
-         MusicDiscItem musicdiscitem = MusicDiscItem.func_185074_a(p_184377_1_);
+         MusicDiscItem musicdiscitem = musicDiscItem;
          if (musicdiscitem != null) {
             this.field_72777_q.field_71456_v.func_238451_a_(musicdiscitem.func_234801_g_());
          }
@@ -2232,7 +2259,7 @@
          break;
       case 1010:
          if (Item.func_150899_d(p_180439_4_) instanceof MusicDiscItem) {
-            this.func_184377_a(((MusicDiscItem)Item.func_150899_d(p_180439_4_)).func_185075_h(), p_180439_3_);
+            this.playRecord(((MusicDiscItem)Item.func_150899_d(p_180439_4_)).func_185075_h(), p_180439_3_, (MusicDiscItem) Item.func_150899_d(p_180439_4_));
          } else {
             this.func_184377_a((SoundEvent)null, p_180439_3_);
          }
@@ -2382,8 +2409,8 @@
          break;
       case 2001:
          BlockState blockstate = Block.func_196257_b(p_180439_4_);
-         if (!blockstate.func_196958_f()) {
-            SoundType soundtype = blockstate.func_215695_r();
+         if (!blockstate.isAir(this.field_72769_h, p_180439_3_)) {
+            SoundType soundtype = blockstate.getSoundType(this.field_72769_h, p_180439_3_, null);
             this.field_72769_h.func_184156_a(p_180439_3_, soundtype.func_185845_c(), SoundCategory.BLOCKS, (soundtype.func_185843_a() + 1.0F) / 2.0F, soundtype.func_185847_b() * 0.8F, false);
          }
 
@@ -2531,7 +2558,7 @@
       } else {
          int i = p_228420_0_.func_226658_a_(LightType.SKY, p_228420_2_);
          int j = p_228420_0_.func_226658_a_(LightType.BLOCK, p_228420_2_);
-         int k = p_228420_1_.func_185906_d();
+         int k = p_228420_1_.getLightValue(p_228420_0_, p_228420_2_);
          if (j < k) {
             j = k;
          }
@@ -2570,6 +2597,11 @@
       return this.field_239226_J_;
    }
 
+   @Override
+   public net.minecraftforge.resource.IResourceType getResourceType() {
+      return net.minecraftforge.resource.VanillaResourceType.MODELS;
+   }
+
    @OnlyIn(Dist.CLIENT)
    class LocalRenderInformationContainer {
       private final ChunkRenderDispatcher.ChunkRender field_178036_a;
