package net.minecraft.server; import com.mojang.datafixers.util.Pair; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectList; import it.unimi.dsi.fastutil.objects.ObjectListIterator; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.IntSupplier; import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class LightEngineThreaded extends LightEngine implements AutoCloseable { private static final Logger LOGGER = LogManager.getLogger(); private final ThreadedMailbox<Runnable> b; private final ObjectList<Pair<LightEngineThreaded.Update, Runnable>> c = new ObjectArrayList(); private final PlayerChunkMap d; private final Mailbox<ChunkTaskQueueSorter.a<Runnable>> e; private volatile int f = 5; private final AtomicBoolean g = new AtomicBoolean(); public LightEngineThreaded(ILightAccess ilightaccess, PlayerChunkMap playerchunkmap, boolean flag, ThreadedMailbox<Runnable> threadedmailbox, Mailbox<ChunkTaskQueueSorter.a<Runnable>> mailbox) { super(ilightaccess, true, flag); this.d = playerchunkmap; this.e = mailbox; this.b = threadedmailbox; } public void close() {} @Override public int a(int i, boolean flag, boolean flag1) { throw (UnsupportedOperationException) SystemUtils.c(new UnsupportedOperationException("Ran authomatically on a different thread!")); } @Override public void a(BlockPosition blockposition, int i) { throw (UnsupportedOperationException) SystemUtils.c(new UnsupportedOperationException("Ran authomatically on a different thread!")); } @Override public void a(BlockPosition blockposition) { BlockPosition blockposition1 = blockposition.immutableCopy(); this.a(blockposition.getX() >> 4, blockposition.getZ() >> 4, LightEngineThreaded.Update.POST_UPDATE, SystemUtils.a(() -> { super.a(blockposition1); }, () -> { return "checkBlock " + blockposition1; })); } protected void a(ChunkCoordIntPair chunkcoordintpair) { this.a(chunkcoordintpair.x, chunkcoordintpair.z, () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { super.b(chunkcoordintpair, false); super.a(chunkcoordintpair, false); int i; for (i = -1; i < 17; ++i) { super.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, i), (NibbleArray) null); super.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, i), (NibbleArray) null); } for (i = 0; i < 16; ++i) { super.a(SectionPosition.a(chunkcoordintpair, i), true); } }, () -> { return "updateChunkStatus " + chunkcoordintpair + " " + true; })); } @Override public void a(SectionPosition sectionposition, boolean flag) { this.a(sectionposition.a(), sectionposition.c(), () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { super.a(sectionposition, flag); }, () -> { return "updateSectionStatus " + sectionposition + " " + flag; })); } @Override public void a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { super.a(chunkcoordintpair, flag); }, () -> { return "enableLight " + chunkcoordintpair + " " + flag; })); } @Override public void a(EnumSkyBlock enumskyblock, SectionPosition sectionposition, @Nullable NibbleArray nibblearray) { this.a(sectionposition.a(), sectionposition.c(), () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { super.a(enumskyblock, sectionposition, nibblearray); }, () -> { return "queueData " + sectionposition; })); } private void a(int i, int j, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { this.a(i, j, this.d.c(ChunkCoordIntPair.pair(i, j)), lightenginethreaded_update, runnable); } private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { this.e.a((Object) ChunkTaskQueueSorter.a(() -> { this.c.add(Pair.of(lightenginethreaded_update, runnable)); if (this.c.size() >= this.f) { this.b(); } }, ChunkCoordIntPair.pair(i, j), intsupplier)); } @Override public void b(ChunkCoordIntPair chunkcoordintpair, boolean flag) { this.a(chunkcoordintpair.x, chunkcoordintpair.z, () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { super.b(chunkcoordintpair, flag); }, () -> { return "retainData " + chunkcoordintpair; })); } public CompletableFuture<IChunkAccess> a(IChunkAccess ichunkaccess, boolean flag) { ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); ichunkaccess.b(false); this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { ChunkSection[] achunksection = ichunkaccess.getSections(); for (int i = 0; i < 16; ++i) { ChunkSection chunksection = achunksection[i]; if (!ChunkSection.a(chunksection)) { super.a(SectionPosition.a(chunkcoordintpair, i), false); } } super.a(chunkcoordintpair, true); if (!flag) { ichunkaccess.m().forEach((blockposition) -> { super.a(blockposition, ichunkaccess.h(blockposition)); }); } this.d.c(chunkcoordintpair); }, () -> { return "lightChunk " + chunkcoordintpair + " " + flag; })); return CompletableFuture.supplyAsync(() -> { ichunkaccess.b(true); super.b(chunkcoordintpair, false); return ichunkaccess; }, (runnable) -> { this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.POST_UPDATE, runnable); }); } public void queueUpdate() { if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { this.b.a((Object) (() -> { this.b(); this.g.set(false); })); } } private void b() { int i = Math.min(this.c.size(), this.f); ObjectListIterator<Pair<LightEngineThreaded.Update, Runnable>> objectlistiterator = this.c.iterator(); Pair pair; int j; for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { pair = (Pair) objectlistiterator.next(); if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) { ((Runnable) pair.getSecond()).run(); } } objectlistiterator.back(j); super.a(Integer.MAX_VALUE, true, true); for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { pair = (Pair) objectlistiterator.next(); if (pair.getFirst() == LightEngineThreaded.Update.POST_UPDATE) { ((Runnable) pair.getSecond()).run(); } objectlistiterator.remove(); } } public void a(int i) { this.f = i; } static enum Update { PRE_UPDATE, POST_UPDATE; private Update() {} } }