ImageBuilder class

Пакет: com.hypixel.hytale.server.core.universe.world.worldmap.provider.chunk

Файл: com/hypixel/hytale/server/core/universe/world/worldmap/provider/chunk/ImageBuilder.java

Поля (171)

МодификаторыТипИмя
final int POOL_MAX_SIZE
public int a
public int b
break
public int g
quantizationEnabled
public int r
CompletableFuture var1
int var1
int var1
int var1
int var1
int var10
var10
BitFieldArr var10
int var10
com.hypixel.hytale.protocol.Color var10
Fluid var11
var11
var11
var11
int var11
com.hypixel.hytale.protocol.Color var11
int var12
var12
var12
byte[] var12
float var12
float var12
int var13
float var13
int var13
var13
float var13
int var14
float var14
int var14
var14
int var15
float var15
int var15
var15
FluidSection var16
float var16
com.hypixel.hytale.protocol.Color var16
int var17
float var17
int var18
float var18
float var19
Store var2
CompletableFuture var2
int var2
var2
int var2
int var2
int var2
int var20
float var20
short var21
float var21
short var22
float var22
short var23
float var23
short var24
float var24
float var25
float var25
short[] var26
float var26
int var27
float var27
float var28
int var29
float var29
ChunkColumn var3
int var3
int var3
CompletableFuture var3
int var3
int var3
int var3
int var3
int var3
int var3
int var3
int var3
int var3
int var3
int var3
int var3
var3
var3
var3
BlockType var3
float var30
float var30
float var31
int var32
int var33
int var36
int var37
int var39
int var4
CompletableFuture var4
int var4
int var4
int var4
int var4
int var4
int var4
int var4
int var4
int var4
int var4
int var4
var4
var4
int var40
int var41
short var42
int var43
int var44
int[] var45
int var46
boolean var47
short var48
short var49
Ref var5
int var5
int var5
int var5
CompletableFuture var5
int var5
int var5
int var5
int var5
int var5
var5
var5
ImageBuilder var5
short var50
short var51
int var6
CompletableFuture var6
short var6
int var6
int var6
int var6
var6
var6
CompletableFuture var7
int var7
int var7
int var7
int[] var7
com.hypixel.hytale.protocol.Color[] var7
Fluid var7
CompletableFuture var8
int var8
int var8
int var8
int var8
boolean var8
boolean var8
int var9
var9
var9
int var9
Environment var9

Методы (67)

МодификаторыВозвратСигнатура
private Colorprivate Color()
static ImageBuilder acquireImageBuilder acquire(long var0, int var2, int var3, World var4)
static int calculateBitsRequiredint calculateBitsRequired(int var0)
static boolean colorNearBoundaryboolean colorNearBoundary(int var0)
for for(int var4 = 0; var4 < 10; var4++)
for for(int var4 = 0; var4 < this.sampleWidth; var4++)
for for(int var5 = 0; var5 < this.sampleWidth; var5++)
for for(int var4 = 0; var4 < this.sampleHeight; var4++)
for for(int var4 = 0; var4 < this.sampleHeight; var4++)
for for(int var1 = 0; var1 < this.sampleHeight; var1++)
for for(int var2 = 0; var2 < this.sampleWidth; var2++)
for for(int var19 = var18; var19 >= var17; var19--)
for for(int var34 = 0; var34 < this.sampleHeight; var34++)
for for(int var35 = 0; var35 < this.imageHeight; var35++)
for for(int var38 = 0; var38 < this.imageWidth; var38++)
for for(int var28 = var45.length - 1; var28 >= 0; var28--)
for for(int var5 = -2; var5 <= 2; var5++)
for for(int var6 = -2; var6 <= 2; var6++)
for for(int var2 = 0; var2 < var1; var2++)
for for(int var6 = 0; var6 < var1; var6++)
for for(int var9 = 0; var9 < var7.length; var9++)
for for(int var11 = 0; var11 < var1; var11++)
static void getBlockColorvoid getBlockColor(int var0, int var1, @Nonnull ImageBuilder.Color var2)
abstract getBlockColor getBlockColor(var44, var43, this.outColor)
static void getFluidColorvoid getFluidColor(int var0, int var1, int var2, @Nonnull ImageBuilder.Color var3)
abstract getFluidColor getFluidColor(var29, var27, var26[var28], this.outColor)
public long getIndexlong getIndex()
if if(var20 != var9)
if if(var9 != 0)
if if(var9 != 0)
if if(var10 == 320)
if if(var9 != 0)
if if(var9 != 0)
if if(var9 != 0)
if if(var13 > 0)
if if(var42 >= 0 && var44 != 0)
if if(var42 < 320 && var47)
if if(var29 != 0)
if if(var6 != 0 || var5 != 0)
if if(var7 >= 0 && var7 < this.imageWidth && var8 >= 0 && var8 < this.imageHeight && this.quantizedPixels[var8 * this.imageWidth + var7] != var2)
if if(quantizationEnabled)
if if(quantizationEnabled)
if if(var0 <= 16)
if if(var16 != null && var12 < 1.0F)
if if(var7 != null)
if if(var8)
if if(var10 != null)
if if(var11 != null)
if if(var8)
if if(var5 != null)
if if(var5.imageWidth == var2 && var5.imageHeight == var3)
private boolean isInTransitionZoneboolean isInTransitionZone(int var1)
static boolean isNearBoundaryboolean isNearBoundary(int var0)
static boolean isQuantizationEnabledboolean isQuantizationEnabled()
static boolean isWaterShadedboolean isWaterShaded(Fluid var0)
public void multiplypublic void multiply(float var1)
public int packpublic int pack()
private void packImageDatavoid packImageData(int var1, int var2)
static int quantizeChannelint quantizeChannel(int var0)
static int quantizeChannelWithDitherint quantizeChannelWithDither(int var0, int var1)
static int quantizeColorint quantizeColor(int var0)
static int quantizeColorWithDitherint quantizeColorWithDither(int var0, int var1, int var2)
public void releasevoid release()
private void resetvoid reset(long var1, World var3)
static float shadeFromHeightsfloat shadeFromHeights(int var0, int var1, int var2, int var3, short var4, short var5, short var6, short var7, short var8, short var9, short var10, short var11, short var12)
static boolean toggleQuantizationboolean toggleQuantization()
while while(var15 >= 0 && var15 >= var14)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.universe.world.worldmap.provider.chunk;

class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.protocol.ShaderType;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.MapImage;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
class="kw">import com.hypixel.hytale.server.core.asset.type.environment.config.Environment;
class="kw">import com.hypixel.hytale.server.core.asset.type.fluid.Fluid;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.ChunkColumn;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.palette.BitFieldArr;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
class="kw">import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
class="kw">import java.util.Arrays;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.ConcurrentLinkedQueue;
class="kw">import java.util.concurrent.atomic.AtomicInteger;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;

class="kw">public class ImageBuilder {
   class="kw">private class="kw">static class="kw">final int POOL_MAX_SIZE = 64;
   class="kw">private class="kw">static class="kw">final AtomicInteger POOL_SIZE = new AtomicInteger(0);
   class="kw">private class="kw">static class="kw">final ConcurrentLinkedQueue<ImageBuilder> POOL = new ConcurrentLinkedQueue<>();
   class="kw">private class="kw">static class="kw">volatile boolean quantizationEnabled = true;
   class="kw">private class="kw">static class="kw">final float LX = -0.2F;
   class="kw">private class="kw">static class="kw">final float LY = 0.8F;
   class="kw">private class="kw">static class="kw">final float LZ = 0.5F;
   class="kw">private class="kw">static class="kw">final float INV_L = 1.0F / (float)Math.sqrt(0.93000007F);
   class="kw">private class="kw">static class="kw">final float LIGHT_X = -0.2F * INV_L;
   class="kw">private class="kw">static class="kw">final float LIGHT_Y = 0.8F * INV_L;
   class="kw">private class="kw">static class="kw">final float LIGHT_Z = 0.5F * INV_L;
   class="kw">private long index;
   class="kw">private World world;
   class="kw">private class="kw">final int imageWidth;
   class="kw">private class="kw">final int imageHeight;
   @Nonnull
   class="kw">private class="kw">final int[] rawPixels;
   @Nullable
   class="kw">private MapImage image;
   class="kw">private class="kw">final int sampleWidth;
   class="kw">private class="kw">final int sampleHeight;
   class="kw">private class="kw">final int blockStepX;
   class="kw">private class="kw">final int blockStepZ;
   @Nonnull
   class="kw">private class="kw">final short[] heightSamples;
   @Nonnull
   class="kw">private class="kw">final int[] tintSamples;
   @Nonnull
   class="kw">private class="kw">final int[] blockSamples;
   @Nonnull
   class="kw">private class="kw">final short[] neighborHeightSamples;
   @Nonnull
   class="kw">private class="kw">final short[][] fluidDepthSamples;
   @Nonnull
   class="kw">private class="kw">final int[] environmentSamples;
   @Nonnull
   class="kw">private class="kw">final int[][] fluidSamples;
   @Nonnull
   class="kw">private class="kw">final int[] fluidIdBuffer;
   @Nonnull
   class="kw">private class="kw">final short[] fluidDepthBuffer;
   @Nonnull
   class="kw">private class="kw">final int[] processedPixels;
   @Nonnull
   class="kw">private class="kw">final int[] quantizedPixels;
   @Nonnull
   class="kw">private class="kw">final FluidSection[] fluidSections;
   @Nonnull
   class="kw">private class="kw">final IntOpenHashSet uniqueColors;
   @Nonnull
   class="kw">private class="kw">final Int2IntOpenHashMap colorToIndex;
   class="kw">private class="kw">final ImageBuilder.Color outColor = new ImageBuilder.Color();
   @Nullable
   class="kw">private BlockChunk blockChunk;
   class="kw">private class="kw">static class="kw">final int QUANTIZE_STEP = 8;
   class="kw">private class="kw">static class="kw">final int QUANTIZE_HALF = 4;
   class="kw">private class="kw">static class="kw">final int[][] BAYER_MATRIX = new int[][]{{0, 8, 2, 10}, {12, 4, 14, 6}, {3, 11, 1, 9}, {15, 7, 13, 5}};
   class="kw">private class="kw">static class="kw">final int GRADIENT_THRESHOLD = 2;

   class="kw">public class="kw">static boolean isQuantizationEnabled() {
      class="kw">return quantizationEnabled;
   }

   class="kw">public class="kw">static boolean toggleQuantization() {
      quantizationEnabled = !quantizationEnabled;
      class="kw">return quantizationEnabled;
   }

   class="kw">private void reset(long var1, World var3) {
      this.index = var1;
      this.world = var3;
      this.image = null;
      Arrays.fill(this.fluidSamples, null);
      Arrays.fill(this.fluidDepthSamples, null);
      Arrays.fill(this.fluidSections, null);
      Arrays.fill(this.neighborHeightSamples, (short)0);
      this.uniqueColors.clear();
      this.colorToIndex.clear();
   }

   class="kw">public ImageBuilder(long var1, int var3, int var4, World var5) {
      this.index = var1;
      this.world = var5;
      this.imageWidth = var3;
      this.imageHeight = var4;
      this.rawPixels = new int[var3 * var4];
      this.sampleWidth = Math.min(32, var3);
      this.sampleHeight = Math.min(32, var4);
      this.blockStepX = Math.max(1, 32 / var3);
      this.blockStepZ = Math.max(1, 32 / var4);
      this.heightSamples = new short[this.sampleWidth * this.sampleHeight];
      this.tintSamples = new int[this.sampleWidth * this.sampleHeight];
      this.blockSamples = new int[this.sampleWidth * this.sampleHeight];
      this.neighborHeightSamples = new short[(this.sampleWidth + 2) * (this.sampleHeight + 2)];
      this.fluidDepthSamples = new short[this.sampleWidth * this.sampleHeight][];
      this.environmentSamples = new int[this.sampleWidth * this.sampleHeight];
      this.fluidSamples = new int[this.sampleWidth * this.sampleHeight][];
      this.fluidIdBuffer = new int[320];
      this.fluidDepthBuffer = new short[320];
      this.fluidSections = new FluidSection[10];
      this.processedPixels = new int[var3 * var4];
      this.uniqueColors = new IntOpenHashSet();
      this.colorToIndex = new Int2IntOpenHashMap();
      this.quantizedPixels = new int[var3 * var4];
   }

   class="kw">public long getIndex() {
      class="kw">return this.index;
   }

   @Nonnull
   class="kw">public MapImage getImage() {
      class="kw">return this.image;
   }

   @Nonnull
   class="kw">private CompletableFuture<ImageBuilder> fetchChunk() {
      class="kw">return this.world.getChunkStore().getChunkReferenceAsync(this.index).thenApplyAsync(var1 -> {
         if (var1 != null && var1.isValid()) {
            Store var2 = var1.getStore();
            this.blockChunk = var2.getComponent((Ref<ChunkStore>)var1, BlockChunk.getComponentType());
            ChunkColumn var3 = var2.getComponent((Ref<ChunkStore>)var1, ChunkColumn.getComponentType());

            for (int var4 = 0; var4 < 10; var4++) {
               Ref var5 = var3.getSection(var4);
               this.fluidSections[var4] = this.world.getChunkStore().getStore().getComponent(var5, FluidSection.getComponentType());
            }

            class="kw">return this;
         } else {
            class="kw">return null;
         }
      }, this.world);
   }

   @Nonnull
   class="kw">private CompletableFuture<ImageBuilder> sampleNeighborsSync() {
      CompletableFuture var1 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX(), this.blockChunk.getZ() - 1))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = (this.sampleHeight - 1) * this.blockStepZ;

               for (int var4 = 0; var4 < this.sampleWidth; var4++) {
                  int var5 = var4 * this.blockStepX;
                  this.neighborHeightSamples[1 + var4] = var2.getHeight(var5, var3);
               }
            }
         }, this.world);
      CompletableFuture var2 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX(), this.blockChunk.getZ() + 1))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = 0;
               int var4 = (this.sampleHeight + 1) * (this.sampleWidth + 2) + 1;

               for (int var5 = 0; var5 < this.sampleWidth; var5++) {
                  int var6 = var5 * this.blockStepX;
                  this.neighborHeightSamples[var4 + var5] = var2.getHeight(var6, var3);
               }
            }
         }, this.world);
      CompletableFuture var3 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX() - 1, this.blockChunk.getZ()))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = (this.sampleWidth - 1) * this.blockStepX;

               for (int var4 = 0; var4 < this.sampleHeight; var4++) {
                  int var5 = var4 * this.blockStepZ;
                  this.neighborHeightSamples[(var4 + 1) * (this.sampleWidth + 2)] = var2.getHeight(var3, var5);
               }
            }
         }, this.world);
      CompletableFuture var4 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX() + 1, this.blockChunk.getZ()))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = 0;

               for (int var4 = 0; var4 < this.sampleHeight; var4++) {
                  int var5 = var4 * this.blockStepZ;
                  this.neighborHeightSamples[(var4 + 1) * (this.sampleWidth + 2) + this.sampleWidth + 1] = var2.getHeight(var3, var5);
               }
            }
         }, this.world);
      CompletableFuture var5 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX() + 1, this.blockChunk.getZ() - 1))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = 0;
               int var4 = (this.sampleHeight - 1) * this.blockStepZ;
               this.neighborHeightSamples[this.sampleWidth + 1] = var2.getHeight(var3, var4);
            }
         }, this.world);
      CompletableFuture var6 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX() - 1, this.blockChunk.getZ() - 1))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = (this.sampleWidth - 1) * this.blockStepX;
               int var4 = (this.sampleHeight - 1) * this.blockStepZ;
               this.neighborHeightSamples[0] = var2.getHeight(var3, var4);
            }
         }, this.world);
      CompletableFuture var7 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX() + 1, this.blockChunk.getZ() + 1))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = 0;
               int var4 = 0;
               this.neighborHeightSamples[(this.sampleHeight + 1) * (this.sampleWidth + 2) + this.sampleWidth + 1] = var2.getHeight(var3, var4);
            }
         }, this.world);
      CompletableFuture var8 = this.world
         .getChunkStore()
         .getChunkReferenceAsync(ChunkUtil.indexChunk(this.blockChunk.getX() - 1, this.blockChunk.getZ() + 1))
         .thenAcceptAsync(var1x -> {
            if (var1x != null && var1x.isValid()) {
               BlockChunk var2 = var1x.getStore().getComponent((Ref<ChunkStore>)var1x, BlockChunk.getComponentType());
               int var3 = (this.sampleWidth - 1) * this.blockStepX;
               int var4 = 0;
               this.neighborHeightSamples[(this.sampleHeight + 1) * (this.sampleWidth + 2)] = var2.getHeight(var3, var4);
            }
         }, this.world);
      class="kw">return CompletableFuture.allOf(var1, var2, var3, var4, var5, var6, var7, var8).thenApply(var1x -> this);
   }

   @Nonnull
   class="kw">private ImageBuilder generateImageAsync() {
      for (int var1 = 0; var1 < this.sampleHeight; var1++) {
         for (int var2 = 0; var2 < this.sampleWidth; var2++) {
            int var3 = var1 * this.sampleWidth + var2;
            int var4 = var2 * this.blockStepX;
            int var5 = var1 * this.blockStepZ;
            short var6 = this.blockChunk.getHeight(var4, var5);
            int var7 = this.blockChunk.getTint(var4, var5);
            this.heightSamples[var3] = var6;
            this.tintSamples[var3] = var7;
            int var8 = this.blockChunk.getBlock(var4, var6, var5);
            this.blockSamples[var3] = var8;
            int var9 = 0;
            int var10 = 320;
            Fluid var11 = null;
            int var12 = 0;
            int var13 = 0;
            int var14 = ChunkUtil.chunkCoordinate(var6);
            int var15 = 9;

            label160:
            while (var15 >= 0 && var15 >= var14) {
               FluidSection var16 = this.fluidSections[var15];
               if (var16 != null && !var16.isEmpty()) {
                  int var17 = Math.max(ChunkUtil.minBlock(var15), var6);
                  int var18 = ChunkUtil.maxBlock(var15);

                  for (int var19 = var18; var19 >= var17; var19--) {
                     int var20 = var16.getFluidId(var4, var19, var5);
                     if (var20 != var9) {
                        if (var9 != 0) {
                           this.fluidIdBuffer[var13] = var9;
                           this.fluidDepthBuffer[var13] = (short)var12;
                           var13++;
                           if (var11 != null && !isWaterShaded(var11)) {
                              break label160;
                           }
                        }

                        var9 = var20;
                        var12 = 0;
                        if (var9 != 0) {
                           var11 = Fluid.getAssetMap().getAsset(var9);
                           if (var10 == 320) {
                              var10 = var19;
                           }
                        } else {
                           var11 = null;
                        }
                     }

                     if (var9 != 0) {
                        var12++;
                     }
                  }

                  var15--;
               } else {
                  if (var9 != 0) {
                     this.fluidIdBuffer[var13] = var9;
                     this.fluidDepthBuffer[var13] = (short)var12;
                     var13++;
                     if (var11 != null && !isWaterShaded(var11)) {
                        break;
                     }

                     var9 = 0;
                     var12 = 0;
                     var11 = null;
                  }

                  var15--;
               }
            }

            if (var9 != 0) {
               this.fluidIdBuffer[var13] = var9;
               this.fluidDepthBuffer[var13] = (short)var12;
               var13++;
            }

            if (var13 > 0) {
               this.fluidSamples[var3] = Arrays.copyOf(this.fluidIdBuffer, var13);
               this.fluidDepthSamples[var3] = Arrays.copyOf(this.fluidDepthBuffer, var13);
            }

            int var46 = var13 > 0 ? this.blockChunk.getEnvironment(var4, var10, var5) : 0;
            this.environmentSamples[var3] = var46;
         }
      }

      float var30 = (float)this.sampleWidth / this.imageWidth;
      float var31 = (float)this.sampleHeight / this.imageHeight;
      int var32 = Math.max(1, this.imageWidth / this.sampleWidth);
      int var33 = Math.max(1, this.imageHeight / this.sampleHeight);

      for (int var34 = 0; var34 < this.sampleHeight; var34++) {
         System.arraycopy(this.heightSamples, var34 * this.sampleWidth, this.neighborHeightSamples, (var34 + 1) * (this.sampleWidth + 2) + 1, this.sampleWidth);
      }

      for (int var35 = 0; var35 < this.imageHeight; var35++) {
         int var36 = Math.min((int)(var35 * var31), this.sampleHeight - 1);
         int var37 = var35 % var33;

         for (int var38 = 0; var38 < this.imageWidth; var38++) {
            int var39 = Math.min((int)(var38 * var30), this.sampleWidth - 1);
            int var40 = var38 % var32;
            int var41 = var36 * this.sampleWidth + var39;
            short var42 = this.heightSamples[var41];
            int var43 = this.tintSamples[var41];
            int var44 = this.blockSamples[var41];
            int[] var45 = this.fluidSamples[var41];
            boolean var47 = var45 != null && var45.length > 0;
            if ((var42 < 0 || var44 == 0) && !var47) {
               this.outColor.r = this.outColor.g = this.outColor.b = this.outColor.a = 0;
               this.packImageData(var38, var35);
            } else {
               if (var42 >= 0 && var44 != 0) {
                  getBlockColor(var44, var43, this.outColor);
               } else {
                  this.outColor.r = this.outColor.g = this.outColor.b = 0;
                  this.outColor.a = 255;
               }

               short var48 = this.neighborHeightSamples[var36 * (this.sampleWidth + 2) + var39 + 1];
               short var49 = this.neighborHeightSamples[(var36 + 2) * (this.sampleWidth + 2) + var39 + 1];
               short var50 = this.neighborHeightSamples[(var36 + 1) * (this.sampleWidth + 2) + var39];
               short var51 = this.neighborHeightSamples[(var36 + 1) * (this.sampleWidth + 2) + var39 + 2];
               short var21 = this.neighborHeightSamples[var36 * (this.sampleWidth + 2) + var39];
               short var22 = this.neighborHeightSamples[var36 * (this.sampleWidth + 2) + var39 + 2];
               short var23 = this.neighborHeightSamples[(var36 + 2) * (this.sampleWidth + 2) + var39];
               short var24 = this.neighborHeightSamples[(var36 + 2) * (this.sampleWidth + 2) + var39 + 2];
               float var25 = shadeFromHeights(var40, var37, var32, var33, var42, var48, var49, var50, var51, var21, var22, var23, var24);
               this.outColor.multiply(var25);
               if (var42 < 320 && var47) {
                  short[] var26 = this.fluidDepthSamples[var41];
                  int var27 = this.environmentSamples[var41];

                  for (int var28 = var45.length - 1; var28 >= 0; var28--) {
                     int var29 = var45[var28];
                     if (var29 != 0) {
                        getFluidColor(var29, var27, var26[var28], this.outColor);
                     }
                  }
               }

               this.packImageData(var38, var35);
            }
         }
      }

      this.image = this.encodeToPalette();
      class="kw">return this;
   }

   class="kw">private class="kw">static int quantizeChannel(int var0) {
      class="kw">return Math.min(255, (var0 + 4) / 8 * 8);
   }

   class="kw">private class="kw">static boolean isNearBoundary(int var0) {
      int var1 = (var0 + 4) % 8;
      class="kw">return var1 <= 2 || var1 >= 6;
   }

   class="kw">private class="kw">static int quantizeChannelWithDither(int var0, int var1) {
      int var2 = var0 + var1;
      var2 = Math.clamp(var2, 0, 255);
      class="kw">return Math.min(255, (var2 + 4) / 8 * 8);
   }

   class="kw">private class="kw">static int quantizeColor(int var0) {
      int var1 = quantizeChannel(var0 >> 24 & 0xFF);
      int var2 = quantizeChannel(var0 >> 16 & 0xFF);
      int var3 = quantizeChannel(var0 >> 8 & 0xFF);
      int var4 = var0 & 0xFF;
      class="kw">return var1 << 24 | var2 << 16 | var3 << 8 | var4;
   }

   class="kw">private class="kw">static boolean colorNearBoundary(int var0) {
      int var1 = var0 >> 24 & 0xFF;
      int var2 = var0 >> 16 & 0xFF;
      int var3 = var0 >> 8 & 0xFF;
      class="kw">return isNearBoundary(var1) || isNearBoundary(var2) || isNearBoundary(var3);
   }

   class="kw">private class="kw">static int quantizeColorWithDither(int var0, int var1, int var2) {
      int var3 = BAYER_MATRIX[var2 & 3][var1 & 3];
      int var4 = (var3 - 8) * 8 / 16;
      int var5 = quantizeChannelWithDither(var0 >> 24 & 0xFF, var4);
      int var6 = quantizeChannelWithDither(var0 >> 16 & 0xFF, var4);
      int var7 = quantizeChannelWithDither(var0 >> 8 & 0xFF, var4);
      int var8 = var0 & 0xFF;
      class="kw">return var5 << 24 | var6 << 16 | var7 << 8 | var8;
   }

   class="kw">private boolean isInTransitionZone(int var1) {
      int var2 = this.quantizedPixels[var1];
      int var3 = var1 % this.imageWidth;
      int var4 = var1 / this.imageWidth;

      for (int var5 = -2; var5 <= 2; var5++) {
         for (int var6 = -2; var6 <= 2; var6++) {
            if (var6 != 0 || var5 != 0) {
               int var7 = var3 + var6;
               int var8 = var4 + var5;
               if (var7 >= 0 && var7 < this.imageWidth && var8 >= 0 && var8 < this.imageHeight && this.quantizedPixels[var8 * this.imageWidth + var7] != var2) {
                  class="kw">return true;
               }
            }
         }
      }

      class="kw">return false;
   }

   @Nonnull
   class="kw">private MapImage encodeToPalette() {
      int var1 = this.rawPixels.length;
      if (quantizationEnabled) {
         for (int var2 = 0; var2 < var1; var2++) {
            this.quantizedPixels[var2] = quantizeColor(this.rawPixels[var2]);
         }
      }

      for (int var6 = 0; var6 < var1; var6++) {
         int var3;
         if (quantizationEnabled) {
            if (this.isInTransitionZone(var6)) {
               int var4 = var6 % this.imageWidth;
               int var5 = var6 / this.imageWidth;
               var3 = quantizeColorWithDither(this.rawPixels[var6], var4, var5);
            } else {
               var3 = this.quantizedPixels[var6];
            }
         } else {
            var3 = this.rawPixels[var6];
         }

         this.processedPixels[var6] = var3;
         this.uniqueColors.add(var3);
      }

      int[] var7 = this.uniqueColors.toIntArray();
      int var8 = calculateBitsRequired(var7.length);

      for (int var9 = 0; var9 < var7.length; var9++) {
         this.colorToIndex.put(var7[var9], var9);
      }

      BitFieldArr var10 = new BitFieldArr(var8, var1);

      for (int var11 = 0; var11 < var1; var11++) {
         var10.set(var11, this.colorToIndex.get(this.processedPixels[var11]));
      }

      byte[] var12 = var10.get();
      class="kw">return new MapImage(this.imageWidth, this.imageHeight, var7, (byte)var8, var12);
   }

   class="kw">private class="kw">static boolean isWaterShaded(Fluid var0) {
      class="kw">return var0.hasEffect(ShaderType.Water);
   }

   class="kw">private class="kw">static int calculateBitsRequired(int var0) {
      if (var0 <= 16) {
         class="kw">return 4;
      } else if (var0 <= 256) {
         class="kw">return 8;
      } else {
         class="kw">return var0 <= 4096 ? 12 : 16;
      }
   }

   class="kw">private void packImageData(int var1, int var2) {
      this.rawPixels[var2 * this.imageWidth + var1] = this.outColor.pack();
   }

   class="kw">private class="kw">static float shadeFromHeights(
      int var0, int var1, int var2, int var3, short var4, short var5, short var6, short var7, short var8, short var9, short var10, short var11, short var12
   ) {
      float var13 = (var0 + 0.5F) / var2;
      float var14 = (var1 + 0.5F) / var3;
      float var15 = (var13 + var14) / 2.0F;
      float var16 = (1.0F - var13 + var14) / 2.0F;
      float var17 = (var4 - var7) * (1.0F - var13) + (var8 - var4) * var13;
      float var18 = (var4 - var5) * (1.0F - var14) + (var6 - var4) * var14;
      float var19 = (var4 - var9) * (1.0F - var15) + (var12 - var4) * var15;
      float var20 = (var4 - var10) * (1.0F - var16) + (var11 - var4) * var16;
      float var21 = var17 * 2.0F + var19;
      float var22 = var18 * 2.0F + var20;
      float var23 = 3.0F;
      float var24 = var21;
      float var25 = var23;
      float var26 = var22;
      float var27 = 1.0F / (float)Math.sqrt(var24 * var24 + var25 * var25 + var26 * var26);
      var24 *= var27;
      var25 *= var27;
      var26 *= var27;
      float var28 = Math.max(0.0F, var24 * LIGHT_X + var25 * LIGHT_Y + var26 * LIGHT_Z);
      float var29 = 0.4F;
      float var30 = 0.6F;
      class="kw">return var29 + var30 * var28;
   }

   class="kw">private class="kw">static void getBlockColor(int var0, int var1, @Nonnull ImageBuilder.Color var2) {
      BlockType var3 = BlockType.getAssetMap().getAsset(var0);
      int var4 = var1 >> 16 & 0xFF;
      int var5 = var1 >> 8 & 0xFF;
      int var6 = var1 >> 0 & 0xFF;
      com.hypixel.hytale.protocol.Color[] var7 = var3.getTintUp();
      boolean var8 = var7 != null && var7.length > 0;
      int var9 = var8 ? var7[0].red & 0xFF : 255;
      int var10 = var8 ? var7[0].green & 0xFF : 255;
      int var11 = var8 ? var7[0].blue & 0xFF : 255;
      float var12 = var3.getBiomeTintUp() / 100.0F;
      int var13 = (int)(var9 + (var4 - var9) * var12);
      int var14 = (int)(var10 + (var5 - var10) * var12);
      int var15 = (int)(var11 + (var6 - var11) * var12);
      com.hypixel.hytale.protocol.Color var16 = var3.getParticleColor();
      if (var16 != null && var12 < 1.0F) {
         var13 = var13 * (var16.red & 255) / 255;
         var14 = var14 * (var16.green & 255) / 255;
         var15 = var15 * (var16.blue & 255) / 255;
      }

      var2.r = var13 & 0xFF;
      var2.g = var14 & 0xFF;
      var2.b = var15 & 0xFF;
      var2.a = 255;
   }

   class="kw">private class="kw">static void getFluidColor(int var0, int var1, int var2, @Nonnull ImageBuilder.Color var3) {
      int var4 = 255;
      int var5 = 255;
      int var6 = 255;
      Fluid var7 = Fluid.getAssetMap().getAsset(var0);
      if (var7 != null) {
         boolean var8 = isWaterShaded(var7);
         if (var8) {
            Environment var9 = Environment.getAssetMap().getAsset(var1);
            com.hypixel.hytale.protocol.Color var10 = var9.getWaterTint();
            if (var10 != null) {
               var4 = var4 * (var10.red & 255) / 255;
               var5 = var5 * (var10.green & 255) / 255;
               var6 = var6 * (var10.blue & 255) / 255;
            }
         }

         com.hypixel.hytale.protocol.Color var11 = var7.getParticleColor();
         if (var11 != null) {
            var4 = var4 * (var11.red & 255) / 255;
            var5 = var5 * (var11.green & 255) / 255;
            var6 = var6 * (var11.blue & 255) / 255;
         }

         if (var8) {
            float var12 = 1.0F / (var2 + 1.0F);
            var3.r = (int)(var4 + ((var3.r & 0xFF) - var4) * var12) & 0xFF;
            var3.g = (int)(var5 + ((var3.g & 0xFF) - var5) * var12) & 0xFF;
            var3.b = (int)(var6 + ((var3.b & 0xFF) - var6) * var12) & 0xFF;
         } else {
            float var13 = Math.max(0.75F, 1.0F - var2 * 0.02F);
            var3.r = (int)((var4 & 0xFF) * var13);
            var3.g = (int)((var5 & 0xFF) * var13);
            var3.b = (int)((var6 & 0xFF) * var13);
         }
      }
   }

   class="kw">public void release() {
      if (POOL_SIZE.incrementAndGet() <= 64) {
         this.blockChunk = null;
         this.image = null;
         Arrays.fill(this.fluidSections, null);
         POOL.offer(this);
      } else {
         POOL_SIZE.decrementAndGet();
      }
   }

   class="kw">private class="kw">static ImageBuilder acquire(long var0, int var2, int var3, World var4) {
      ImageBuilder var5 = POOL.poll();
      if (var5 != null) {
         POOL_SIZE.decrementAndGet();
         if (var5.imageWidth == var2 && var5.imageHeight == var3) {
            var5.reset(var0, var4);
            class="kw">return var5;
         }
      }

      class="kw">return new ImageBuilder(var0, var2, var3, var4);
   }

   @Nonnull
   class="kw">public class="kw">static CompletableFuture<ImageBuilder> build(long var0, int var2, int var3, World var4) {
      class="kw">return CompletableFuture.completedFuture(acquire(var0, var2, var3, var4))
         .thenCompose(ImageBuilder::fetchChunk)
         .thenCompose(var0x -> var0x != null ? var0x.sampleNeighborsSync() : CompletableFuture.completedFuture(null))
         .thenApplyAsync(var0x -> var0x != null ? var0x.generateImageAsync() : null);
   }

   class="kw">private class="kw">static class Color {
      class="kw">public int r;
      class="kw">public int g;
      class="kw">public int b;
      class="kw">public int a;

      class="kw">private Color() {
      }

      class="kw">public int pack() {
         class="kw">return (this.r & 0xFF) << 24 | (this.g & 0xFF) << 16 | (this.b & 0xFF) << 8 | this.a & 0xFF;
      }

      class="kw">public void multiply(float var1) {
         this.r = Math.clamp((int)(this.r * var1), 0, 255);
         this.g = Math.clamp((int)(this.g * var1), 0, 255);
         this.b = Math.clamp((int)(this.b * var1), 0, 255);
      }
   }
}