Color class
Пакет: com.hypixel.hytale.server.core.universe.world.worldmap.provider.chunk
Файл: com/hypixel/hytale/server/core/universe/world/worldmap/provider/chunk/ImageBuilder.java
Поля (4)
| Модификаторы | Тип | Имя |
|---|---|---|
|
public int |
a |
|
public int |
b |
|
public int |
g |
|
public int |
r |
Методы (2)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
|
public void |
multiplypublic void multiply(float var1) |
|
public int |
packpublic int pack() |
Исходный код
Показать/скрыть
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);
}
}
}