3737import org .lwjgl .opengl .GL11 ;
3838import org .lwjgl .util .glu .GLU ;
3939
40+ import java .util .ArrayList ;
41+ import java .util .Iterator ;
42+ import java .util .List ;
43+
4044public class BaseSchemaRenderer implements IDrawable {
4145
4246 private static final Framebuffer FBO = new Framebuffer (1080 , 1080 , true );
@@ -163,23 +167,14 @@ private void renderWorld() {
163167 GlStateManager .disableLighting ();
164168 Platform .setupDrawGradient (); // needed for ambient occlusion
165169
170+ List <TileEntity > tesr = null ;
166171 try { // render block in each layer
167172 for (BlockRenderLayer layer : BlockRenderLayer .values ()) {
168- ForgeHooksClient .setRenderLayer (layer );
169- int pass = layer == BlockRenderLayer .TRANSLUCENT ? 1 : 0 ;
170- setDefaultPassRenderState (pass );
171- BufferBuilder buffer = Tessellator .getInstance ().getBuffer ();
172- buffer .begin (GL11 .GL_QUADS , DefaultVertexFormats .BLOCK );
173- BlockRendererDispatcher blockrendererdispatcher = mc .getBlockRendererDispatcher ();
174- this .schema .forEach (pair -> {
175- BlockPos pos = pair .getKey ();
176- IBlockState state = pair .getValue ().getBlockState ();
177- if (!state .getBlock ().isAir (state , this .renderWorld , pos ) && state .getBlock ().canRenderInLayer (state , layer )) {
178- blockrendererdispatcher .renderBlock (state , pos , this .renderWorld , buffer );
179- }
180- });
181- Tessellator .getInstance ().draw ();
182- Tessellator .getInstance ().getBuffer ().setTranslation (0 , 0 , 0 );
173+ if (layer .ordinal () == 0 && isTesrEnabled ()) {
174+ tesr = renderBlocksInLayer (mc , layer , true );
175+ } else {
176+ renderBlocksInLayer (mc , layer , false );
177+ }
183178 }
184179 } finally {
185180 ForgeHooksClient .setRenderLayer (oldRenderLayer );
@@ -188,29 +183,73 @@ private void renderWorld() {
188183 RenderHelper .enableStandardItemLighting ();
189184 GlStateManager .enableLighting ();
190185
191- // render TESR
192- if (isTesrEnabled ()) {
193- for (int pass = 0 ; pass < 2 ; pass ++) {
194- ForgeHooksClient .setRenderPass (pass );
195- int finalPass = pass ;
196- GlStateManager .color (1 , 1 , 1 , 1 );
197- setDefaultPassRenderState (pass );
198- this .schema .forEach (pair -> {
199- BlockPos pos = pair .getKey ();
200- TileEntity tile = pair .getValue ().getTileEntity ();
201- if (tile != null && tile .shouldRenderInPass (finalPass )) {
202- TileEntityRendererDispatcher .instance .render (tile , pos .getX (), pos .getY (), pos .getZ (), 0 );
203- }
204- });
186+ try { // render TESR
187+ if (tesr != null && !tesr .isEmpty ()) {
188+ renderTesr (tesr , 0 );
189+ if (!tesr .isEmpty ()) { // any tesr that don't render in pass 1 or 2 are removed from the list
190+ renderTesr (tesr , 1 );
191+ renderTesr (tesr , 2 );
192+ }
205193 }
194+ } finally {
195+ ForgeHooksClient .setRenderPass (-1 );
206196 }
197+
207198 Platform .endDrawGradient ();
208- ForgeHooksClient .setRenderPass (-1 );
209199 GlStateManager .enableDepth ();
210200 GlStateManager .disableBlend ();
211201 GlStateManager .depthMask (true );
212202 }
213203
204+ private List <TileEntity > renderBlocksInLayer (Minecraft mc , BlockRenderLayer layer , boolean collectTesr ) {
205+ List <TileEntity > tesr = collectTesr ? new ArrayList <>() : null ;
206+ ForgeHooksClient .setRenderLayer (layer );
207+ int pass = layer == BlockRenderLayer .TRANSLUCENT ? 1 : 0 ;
208+ setDefaultPassRenderState (pass );
209+ BufferBuilder buffer = Tessellator .getInstance ().getBuffer ();
210+ buffer .begin (GL11 .GL_QUADS , DefaultVertexFormats .BLOCK );
211+ BlockRendererDispatcher blockrendererdispatcher = mc .getBlockRendererDispatcher ();
212+ this .schema .forEach (pair -> {
213+ BlockPos pos = pair .getKey ();
214+ IBlockState state = pair .getValue ().getBlockState ();
215+ if (state .getBlock ().isAir (state , this .renderWorld , pos )) return ;
216+ if (collectTesr ) {
217+ TileEntity te = pair .getValue ().getTileEntity ();
218+ if (te != null && !te .isInvalid ()) {
219+ if (!te .getPos ().equals (pos )) te .setPos (pos .toImmutable ());
220+ if (TileEntityRendererDispatcher .instance .getRenderer (te .getClass ()) != null ) {
221+ // only collect tiles to render which actually have a tesr
222+ tesr .add (te );
223+ }
224+ }
225+ }
226+ if (state .getBlock ().canRenderInLayer (state , layer )) {
227+ blockrendererdispatcher .renderBlock (state , pos , this .renderWorld , buffer );
228+ }
229+ });
230+ Tessellator .getInstance ().draw ();
231+ Tessellator .getInstance ().getBuffer ().setTranslation (0 , 0 , 0 );
232+ return tesr ;
233+ }
234+
235+ private static void renderTesr (List <TileEntity > tileEntities , int pass ) {
236+ ForgeHooksClient .setRenderPass (pass );
237+ GlStateManager .color (1 , 1 , 1 , 1 );
238+ setDefaultPassRenderState (pass );
239+ for (Iterator <TileEntity > iterator = tileEntities .iterator (); iterator .hasNext (); ) {
240+ TileEntity tile = iterator .next ();
241+ if (tile == null || tile .isInvalid ()) continue ;
242+ if (pass == 0 && (!tile .shouldRenderInPass (1 ) || !tile .shouldRenderInPass (2 ))) {
243+ // remove tiles that don't render in further passes
244+ iterator .remove ();
245+ }
246+ if (tile .shouldRenderInPass (pass )) {
247+ BlockPos pos = tile .getPos ();
248+ TileEntityRendererDispatcher .instance .render (tile , pos .getX (), pos .getY (), pos .getZ (), 0 );
249+ }
250+ }
251+ }
252+
214253 private static void setDefaultPassRenderState (int pass ) {
215254 GlStateManager .color (1 , 1 , 1 , 1 );
216255 if (pass == 0 ) { // SOLID
0 commit comments