Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-263340

Incorrect Protochunk#setStatus call on chunk generate

XMLWordPrintable

    • Confirmed
    • Chunk loading
    • Platform

      In 1.20, the ChunkStatus#generate method is implemented differently from in 1.19.4. It seems like there is a mistake with using the incorrect ChunkAccess when setting the status on a chunk being upgraded in the new implementation. While this is an issue with all chunk statuses, it's most relevant for the FULL status as it replaces the ChunkAccess when doing it's work.

       

      Here is ChunkStatus#generate in 1.20:

      public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> generate(Executor $$0, ServerLevel $$1, ChunkGenerator $$2, StructureTemplateManager $$3, ThreadedLevelLightEngine $$4, Function<ChunkAccess, CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> $$5, List<ChunkAccess> $$6) {
          ChunkAccess $$7 = $$6.get($$6.size() / 2);
          ProfiledDuration $$8 = JvmProfiler.INSTANCE.onChunkGenerate($$7.getPos(), $$1.dimension(), this.toString());
          return this.generationTask.doWork(this, $$0, $$1, $$2, $$3, $$4, $$5, $$6, $$7).thenApply(($$2x) -> {
              if ($$7 instanceof ProtoChunk) {
                  ProtoChunk $$3x = (ProtoChunk)$$7;
                  if (!$$3x.getStatus().isOrAfter(this)) {
                      $$3x.setStatus(this);
                  }
              }
      
              if ($$8 != null) {
                  $$8.finish();
              }
      
              return $$2x;
          });
      }

      We can see the $$7 ChunkAccess has it's status set, however we should be setting the status on the chunk wrapped by the result either $$2x (if present). This is because in the case of full chunks, doWork will replace the ChunkAccess, meaning the list retrieved before doing work, and the chunk gotten from it, are no longer up to date.

       

      I noticed this issue when I saw that the visible chunk map in 1.20 contained non-imposter ProtoChunks that had a FULL status, which never happened in previous versions.

       

      Switching the use of $$7/$$3x to $$2x with the following mixin resolved the issue:

      @Mixin(ChunkStatus.class)
      public class ChunkStatusMixin {
          @Shadow @Final private ChunkStatus.GenerationTask generationTask;
      
          /**
           * @author
           * @reason
           */
          @Overwrite
          public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> generate(Executor $$0, ServerLevel $$1, ChunkGenerator $$2, StructureTemplateManager $$3, ThreadedLevelLightEngine $$4, Function<ChunkAccess, CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> $$5, List<ChunkAccess> $$6) {
              ChunkAccess $$7 = $$6.get($$6.size() / 2);
              ProfiledDuration $$8 = JvmProfiler.INSTANCE.onChunkGenerate($$7.getPos(), $$1.dimension(), this.toString());
              return this.generationTask.doWork((ChunkStatus) (Object) this, $$0, $$1, $$2, $$3, $$4, $$5, $$6, $$7).thenApply(($$2x) -> {
                  // Use result instead of chunk from list computed before doing work.
                  $$2x.ifLeft(chunkAccess -> {
                      if (chunkAccess instanceof ProtoChunk protoChunk) {
                          if (!protoChunk.getStatus().isOrAfter((ChunkStatus) (Object) this)) {
                              protoChunk.setStatus((ChunkStatus) (Object) this);
                          }
                      }
                  });
      
                  if ($$8 != null) {
                      $$8.finish();
                  }
      
                  return $$2x;
              });
          }
      } 

            gegy1000 [Mojang] Gegy
            Spottedleaf Spottedleaf
            Votes:
            6 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:
              CHK: