33import com .cleanroommc .client .util .*;
44import com .cleanroommc .client .util .world .LRDummyWorld ;
55import github .kasuminova .mmce .client .util .BufferBuilderPool ;
6+ import it .unimi .dsi .fastutil .objects .Object2IntArrayMap ;
7+ import it .unimi .dsi .fastutil .objects .Object2IntMap ;
8+ import it .unimi .dsi .fastutil .objects .Object2IntOpenHashMap ;
69import net .minecraft .block .Block ;
710import net .minecraft .block .state .IBlockState ;
811import net .minecraft .client .Minecraft ;
3336import java .nio .IntBuffer ;
3437import java .util .*;
3538import java .util .concurrent .CompletableFuture ;
39+ import java .util .concurrent .ConcurrentHashMap ;
3640import java .util .concurrent .atomic .AtomicInteger ;
3741import java .util .concurrent .atomic .AtomicReference ;
3842import java .util .function .Consumer ;
@@ -56,7 +60,17 @@ public abstract class WorldSceneRenderer {
5660
5761 protected static final AtomicInteger THREAD_ID = new AtomicInteger (0 );
5862
59- protected Map <BlockRenderLayer , BufferBuilder > layerBufferBuilders = new EnumMap <>(BlockRenderLayer .class );
63+ protected static final Object2IntMap <BlockRenderLayer > LAYER_PROGRESS_UNITS = new Object2IntOpenHashMap <>();
64+
65+ protected volatile Map <BlockRenderLayer , BufferBuilder > layerBufferBuilders = new EnumMap <>(BlockRenderLayer .class );
66+
67+ static {
68+ LAYER_PROGRESS_UNITS .defaultReturnValue (1 );
69+ LAYER_PROGRESS_UNITS .put (BlockRenderLayer .SOLID , 4 );
70+ LAYER_PROGRESS_UNITS .put (BlockRenderLayer .CUTOUT_MIPPED , 1 );
71+ LAYER_PROGRESS_UNITS .put (BlockRenderLayer .CUTOUT , 3 );
72+ LAYER_PROGRESS_UNITS .put (BlockRenderLayer .TRANSLUCENT , 2 );
73+ }
6074
6175 enum CacheState {
6276 UNUSED ,
@@ -88,7 +102,7 @@ enum CacheState {
88102
89103 public WorldSceneRenderer (LRDummyWorld world ) {
90104 this .dummyWorld = world ;
91- renderedBlocksMap = new LRMap <>(new LinkedHashMap <>(), new LinkedHashMap <>());
105+ renderedBlocksMap = new LRMap <>(new ConcurrentHashMap <>(), new ConcurrentHashMap <>());
92106 cacheState = new AtomicReference <>(CacheState .UNUSED );
93107 }
94108
@@ -101,10 +115,7 @@ public WorldSceneRenderer useCacheBuffer(boolean useCache) {
101115 this .vertexBuffers .getBuffer ()[j ] = new VertexBuffer (DefaultVertexFormats .BLOCK );
102116 this .vertexBuffers .getAnotherBuffer ()[j ] = new VertexBuffer (DefaultVertexFormats .BLOCK );
103117 }
104- if (cacheState .get () == CacheState .COMPILING && thread != null ) {
105- thread .interrupt ();
106- thread = null ;
107- }
118+ stopCompileCache ();
108119 cacheState .set (CacheState .NEED );
109120 }
110121 this .useCache = useCache ;
@@ -114,16 +125,16 @@ public WorldSceneRenderer useCacheBuffer(boolean useCache) {
114125 public WorldSceneRenderer deleteCacheBuffer () {
115126 if (useCache ) {
116127 Thread thread = this .thread ;
117- if (cacheState .get () == CacheState .COMPILING && this .thread != null ) {
118- this .thread .interrupt ();
119- this .thread = null ;
120- }
128+ stopCompileCache ();
121129
122130 VertexBuffer [] bufferRef = this .vertexBuffers .getBuffer ();
123131 VertexBuffer [] anotherBufferRef = this .vertexBuffers .getAnotherBuffer ();
124132 this .vertexBuffers .setLeft (null );
125133 this .vertexBuffers .setRight (null );
126134
135+ Map <BlockRenderLayer , BufferBuilder > layerBufferBuilders = this .layerBufferBuilders ;
136+ this .layerBufferBuilders = new EnumMap <>(BlockRenderLayer .class );
137+
127138 CompletableFuture .runAsync (() -> {
128139 if (thread != null && thread .isAlive ()) {
129140 try {
@@ -152,14 +163,22 @@ public WorldSceneRenderer deleteCacheBuffer() {
152163 }
153164
154165 public WorldSceneRenderer needCompileCache () {
155- if (cacheState .get () == CacheState .COMPILING && thread != null ) {
156- thread .interrupt ();
157- thread = null ;
166+ if (useCache ) {
167+ stopCompileCache ();
168+ cacheState .set (CacheState .NEED );
169+ } else {
170+ switchLRRenderer (Minecraft .getMinecraft ());
158171 }
159- cacheState .set (CacheState .NEED );
160172 return this ;
161173 }
162174
175+ public void stopCompileCache () {
176+ if (cacheState .get () == CacheState .COMPILING ) {
177+ cacheState .set (CacheState .UNUSED );
178+ thread .interrupt ();
179+ }
180+ }
181+
163182 public WorldSceneRenderer setBeforeWorldRender (Consumer <WorldSceneRenderer > callback ) {
164183 this .beforeRender = callback ;
165184 return this ;
@@ -364,11 +383,22 @@ public boolean isCompiling() {
364383 return cacheState .get () == CacheState .COMPILING ;
365384 }
366385
367- public double getCompileProgress () {
368- if (maxProgress > 1000 ) {
369- return progress .get () * 1. / maxProgress ;
386+ public boolean isCompilerThreadAlive () {
387+ if (thread != null ) {
388+ if (thread .isAlive ()) {
389+ return true ;
390+ }
391+ thread = null ;
392+ }
393+ return false ;
394+ }
395+
396+ public float getCompileProgress () {
397+ // 1000 blocks, 11 is per block unit.
398+ if (maxProgress <= 1000 * 11 ) {
399+ return -1 ;
370400 }
371- return 0 ;
401+ return ( float ) progress . get () / maxProgress ;
372402 }
373403
374404 public World getWorld () {
@@ -403,19 +433,21 @@ public WorldSceneRenderer setVertexBuffers(VertexBuffer[] vertexBuffers) {
403433 }
404434
405435 public void refreshCache () {
406- if (cacheState . get () == CacheState . COMPILING ) {
436+ if (isCompiling () || isCompilerThreadAlive () ) {
407437 return ;
408438 }
409439 cacheState .set (CacheState .COMPILING );
410440 progress .set (0 );
411- maxProgress = renderedBlocksMap .getAnotherMap ().keySet ().stream ().map (Collection ::size ).reduce (0 , Integer ::sum ) * (BlockRenderLayer .values ().length + 1 );
441+ maxProgress = renderedBlocksMap .getAnotherMap ().keySet ().stream ()
442+ .map (Collection ::size )
443+ .reduce (0 , Integer ::sum ) * 11 ;
412444
413445 BlockRenderLayer oldRenderLayer = MinecraftForgeClient .getRenderLayer ();
414446 Minecraft mc = Minecraft .getMinecraft ();
415447 boolean checkDisabledModel = getWorld () == mc .world || (getWorld () instanceof TrackedDummyWorld && ((TrackedDummyWorld ) getWorld ()).proxyWorld == mc .world );
416448
417449 thread = new Thread (() -> compileCache (mc , oldRenderLayer , checkDisabledModel ));
418- thread .setName ("PreviewCompiler-" + THREAD_ID .getAndIncrement ());
450+ thread .setName ("MMCE- PreviewCompiler-" + THREAD_ID .getAndIncrement ());
419451 thread .start ();
420452 }
421453
@@ -428,7 +460,7 @@ protected void renderDefault(final Minecraft mc, final float particleTicks, fina
428460 if (pass == 1 ) {
429461 renderTESR (0 , particleTicks , checkDisabledModel );
430462 }
431- renderedBlocksMap .getMap ().forEach ((renderedBlocks , hook )-> {
463+ renderedBlocksMap .getMap ().forEach ((renderedBlocks , hook ) -> {
432464 if (hook != null ) {
433465 hook .apply (false , pass , layer );
434466 } else {
@@ -437,7 +469,7 @@ protected void renderDefault(final Minecraft mc, final float particleTicks, fina
437469 BufferBuilder buffer = Tessellator .getInstance ().getBuffer ();
438470 buffer .begin (GL11 .GL_QUADS , DefaultVertexFormats .BLOCK );
439471
440- renderBlocks (checkDisabledModel , blockrendererdispatcher , layer , buffer , renderedBlocks , getWorld ());
472+ renderBlocks (checkDisabledModel , blockrendererdispatcher , layer , buffer , renderedBlocks , getWorld (), 0 );
441473
442474 Tessellator .getInstance ().draw ();
443475 Tessellator .getInstance ().getBuffer ().setTranslation (0 , 0 , 0 );
@@ -451,14 +483,7 @@ protected void renderDefault(final Minecraft mc, final float particleTicks, fina
451483
452484 protected void renderCacheBuffer (Minecraft mc , BlockRenderLayer oldRenderLayer , float particleTicks , boolean checkDisabledModel ) {
453485 if (cacheState .get () == CacheState .NEED ) {
454- cacheState .set (CacheState .COMPILING );
455- progress .set (0 );
456- maxProgress = renderedBlocksMap .getAnotherMap ().keySet ().stream ()
457- .map (Collection ::size )
458- .reduce (0 , Integer ::sum ) * (BlockRenderLayer .values ().length + 1 );
459-
460- thread = new Thread (() -> compileCache (mc , oldRenderLayer , checkDisabledModel ));
461- thread .start ();
486+ refreshCache ();
462487 }
463488 for (BlockRenderLayer layer : BlockRenderLayer .values ()) {
464489 int pass = layer == BlockRenderLayer .TRANSLUCENT ? 1 : 0 ;
@@ -508,19 +533,20 @@ private void compileCache(final Minecraft mc, final BlockRenderLayer oldRenderLa
508533 Thread compilerThread = Thread .currentThread ();
509534 BlockRendererDispatcher blockrendererdispatcher = mc .getBlockRendererDispatcher ();
510535 Map <Collection <BlockPos >, ISceneRenderHook > renderedBlocksMap = this .renderedBlocksMap .getAnotherMap ();
511- Arrays .stream (BlockRenderLayer .values ()).parallel ().forEach (layer -> {
536+ for (final BlockRenderLayer layer : BlockRenderLayer .values ()) {
537+ int progressUnit = LAYER_PROGRESS_UNITS .get (layer );
512538 ForgeHooksClient .setRenderLayer (layer );
513539 BufferBuilder buffer = getLayerBufferBuilder (layer );
514540 synchronized (buffer ) {
515541 buffer .begin (GL11 .GL_QUADS , DefaultVertexFormats .BLOCK );
516542 for (final Collection <BlockPos > renderedBlocks : renderedBlocksMap .keySet ()) {
517- renderBlocks (checkDisabledModel , blockrendererdispatcher , layer , buffer , renderedBlocks , getLRDummyWorld ().getAnotherWorld ());
543+ renderBlocks (checkDisabledModel , blockrendererdispatcher , layer , buffer , renderedBlocks , getLRDummyWorld ().getAnotherWorld (), progressUnit );
518544 }
519545 buffer .finishDrawing ();
520546 buffer .reset ();
521547 }
522548 ForgeHooksClient .setRenderLayer (null );
523- if (compilerThread . isInterrupted ()) {
549+ if (! isCompiling ()) {
524550 return ;
525551 }
526552 mc .addScheduledTask (() -> {
@@ -530,15 +556,15 @@ private void compileCache(final Minecraft mc, final BlockRenderLayer oldRenderLa
530556 ByteBuffer buf = buffer .getByteBuffer ();
531557 vertexBuffers .getAnotherBuffer ()[layer .ordinal ()].bufferData (buf );
532558 });
533- });
534- if (compilerThread . isInterrupted ()) {
559+ }
560+ if (! isCompiling ()) {
535561 return ;
536562 }
537563 Set <BlockPos > poses = new HashSet <>();
538564 renderedBlocksMap .forEach ((renderedBlocks , hook ) -> {
539565 for (BlockPos pos : renderedBlocks ) {
540566 progress .getAndIncrement ();
541- if (compilerThread . isInterrupted ()) {
567+ if (! isCompiling ()) {
542568 return ;
543569 }
544570// if (checkDisabledModel && MultiblockWorldSavedData.modelDisabled.contains(pos)) {
@@ -550,32 +576,36 @@ private void compileCache(final Minecraft mc, final BlockRenderLayer oldRenderLa
550576 }
551577 }
552578 });
553- if (compilerThread . isInterrupted ()) {
579+ if (! isCompiling ()) {
554580 return ;
555581 }
556582
557583 tileEntities = poses ;
558584 cacheState .set (CacheState .COMPILED );
559- thread = null ;
560585 maxProgress = -1 ;
561586
587+ switchLRRenderer (mc );
588+
589+ thread = null ;
590+ }
591+
592+ protected void switchLRRenderer (final Minecraft mc ) {
562593 dummyWorld .setUseLeft (!dummyWorld .isUseLeft ());
563594 vertexBuffers .setUseLeft (!vertexBuffers .isUseLeft ());
564- this .renderedBlocksMap .setUseLeft (!this .renderedBlocksMap .isUseLeft ());
565- mc .addScheduledTask (() -> {
566- this .renderedBlocksMap .getAnotherMap ().clear ();
567- });
595+ renderedBlocksMap .setUseLeft (!renderedBlocksMap .isUseLeft ());
596+ renderedBlocksMap .getAnotherMap ().clear ();
568597 }
569598
570599 private void renderBlocks (final boolean checkDisabledModel ,
571600 final BlockRendererDispatcher rendererDispatcher ,
572601 final BlockRenderLayer layer ,
573602 final BufferBuilder buffer ,
574603 final Collection <BlockPos > renderedBlocks ,
575- final World world ) {
604+ final World world ,
605+ final int progressUnit ) {
576606 for (BlockPos pos : renderedBlocks ) {
577607 if (maxProgress > 0 ) {
578- progress .getAndIncrement ( );
608+ progress .getAndAdd ( progressUnit );
579609 }
580610// if (checkDisabledModel && MultiblockWorldSavedData.modelDisabled.contains(pos)) {
581611// continue;
@@ -636,7 +666,6 @@ private void renderTESR(final int pass, float particle, boolean checkDisabledMod
636666 }
637667 ForgeHooksClient .setRenderPass (-1 );
638668 RenderHelper .disableStandardItemLighting ();
639-
640669 }
641670
642671 public static void setDefaultPassRenderState (int pass ) {
0 commit comments