// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.protocol;

import java.util.Objects;
import java.util.Arrays;
import com.hypixel.hytale.protocol.io.ValidationResult;
import java.util.Iterator;
import java.util.HashMap;
import com.hypixel.hytale.protocol.io.ProtocolException;
import com.hypixel.hytale.protocol.io.VarInt;
import com.hypixel.hytale.protocol.io.PacketIO;
import io.netty.buffer.ByteBuf;
import javax.annotation.Nonnull;
import java.util.Map;
import javax.annotation.Nullable;

public class Weather
{
    public static final int NULLABLE_BIT_FIELD_SIZE = 4;
    public static final int FIXED_BLOCK_SIZE = 30;
    public static final int VARIABLE_FIELD_COUNT = 24;
    public static final int VARIABLE_BLOCK_START = 126;
    public static final int MAX_SIZE = 1677721600;
    @Nullable
    public String id;
    @Nullable
    public int[] tagIndexes;
    @Nullable
    public String stars;
    @Nullable
    public Map<Integer, String> moons;
    @Nullable
    public Cloud[] clouds;
    @Nullable
    public Map<Float, Float> sunlightDampingMultiplier;
    @Nullable
    public Map<Float, Color> sunlightColors;
    @Nullable
    public Map<Float, ColorAlpha> skyTopColors;
    @Nullable
    public Map<Float, ColorAlpha> skyBottomColors;
    @Nullable
    public Map<Float, ColorAlpha> skySunsetColors;
    @Nullable
    public Map<Float, Color> sunColors;
    @Nullable
    public Map<Float, Float> sunScales;
    @Nullable
    public Map<Float, ColorAlpha> sunGlowColors;
    @Nullable
    public Map<Float, ColorAlpha> moonColors;
    @Nullable
    public Map<Float, Float> moonScales;
    @Nullable
    public Map<Float, ColorAlpha> moonGlowColors;
    @Nullable
    public Map<Float, Color> fogColors;
    @Nullable
    public Map<Float, Float> fogHeightFalloffs;
    @Nullable
    public Map<Float, Float> fogDensities;
    @Nullable
    public String screenEffect;
    @Nullable
    public Map<Float, ColorAlpha> screenEffectColors;
    @Nullable
    public Map<Float, Color> colorFilters;
    @Nullable
    public Map<Float, Color> waterTints;
    @Nullable
    public WeatherParticle particle;
    @Nullable
    public NearFar fog;
    @Nullable
    public FogOptions fogOptions;
    
    public Weather() {
    }
    
    public Weather(@Nullable final String id, @Nullable final int[] tagIndexes, @Nullable final String stars, @Nullable final Map<Integer, String> moons, @Nullable final Cloud[] clouds, @Nullable final Map<Float, Float> sunlightDampingMultiplier, @Nullable final Map<Float, Color> sunlightColors, @Nullable final Map<Float, ColorAlpha> skyTopColors, @Nullable final Map<Float, ColorAlpha> skyBottomColors, @Nullable final Map<Float, ColorAlpha> skySunsetColors, @Nullable final Map<Float, Color> sunColors, @Nullable final Map<Float, Float> sunScales, @Nullable final Map<Float, ColorAlpha> sunGlowColors, @Nullable final Map<Float, ColorAlpha> moonColors, @Nullable final Map<Float, Float> moonScales, @Nullable final Map<Float, ColorAlpha> moonGlowColors, @Nullable final Map<Float, Color> fogColors, @Nullable final Map<Float, Float> fogHeightFalloffs, @Nullable final Map<Float, Float> fogDensities, @Nullable final String screenEffect, @Nullable final Map<Float, ColorAlpha> screenEffectColors, @Nullable final Map<Float, Color> colorFilters, @Nullable final Map<Float, Color> waterTints, @Nullable final WeatherParticle particle, @Nullable final NearFar fog, @Nullable final FogOptions fogOptions) {
        this.id = id;
        this.tagIndexes = tagIndexes;
        this.stars = stars;
        this.moons = moons;
        this.clouds = clouds;
        this.sunlightDampingMultiplier = sunlightDampingMultiplier;
        this.sunlightColors = sunlightColors;
        this.skyTopColors = skyTopColors;
        this.skyBottomColors = skyBottomColors;
        this.skySunsetColors = skySunsetColors;
        this.sunColors = sunColors;
        this.sunScales = sunScales;
        this.sunGlowColors = sunGlowColors;
        this.moonColors = moonColors;
        this.moonScales = moonScales;
        this.moonGlowColors = moonGlowColors;
        this.fogColors = fogColors;
        this.fogHeightFalloffs = fogHeightFalloffs;
        this.fogDensities = fogDensities;
        this.screenEffect = screenEffect;
        this.screenEffectColors = screenEffectColors;
        this.colorFilters = colorFilters;
        this.waterTints = waterTints;
        this.particle = particle;
        this.fog = fog;
        this.fogOptions = fogOptions;
    }
    
    public Weather(@Nonnull final Weather other) {
        this.id = other.id;
        this.tagIndexes = other.tagIndexes;
        this.stars = other.stars;
        this.moons = other.moons;
        this.clouds = other.clouds;
        this.sunlightDampingMultiplier = other.sunlightDampingMultiplier;
        this.sunlightColors = other.sunlightColors;
        this.skyTopColors = other.skyTopColors;
        this.skyBottomColors = other.skyBottomColors;
        this.skySunsetColors = other.skySunsetColors;
        this.sunColors = other.sunColors;
        this.sunScales = other.sunScales;
        this.sunGlowColors = other.sunGlowColors;
        this.moonColors = other.moonColors;
        this.moonScales = other.moonScales;
        this.moonGlowColors = other.moonGlowColors;
        this.fogColors = other.fogColors;
        this.fogHeightFalloffs = other.fogHeightFalloffs;
        this.fogDensities = other.fogDensities;
        this.screenEffect = other.screenEffect;
        this.screenEffectColors = other.screenEffectColors;
        this.colorFilters = other.colorFilters;
        this.waterTints = other.waterTints;
        this.particle = other.particle;
        this.fog = other.fog;
        this.fogOptions = other.fogOptions;
    }
    
    @Nonnull
    public static Weather deserialize(@Nonnull final ByteBuf buf, final int offset) {
        final Weather obj = new Weather();
        final byte[] nullBits = PacketIO.readBytes(buf, offset, 4);
        if ((nullBits[0] & 0x1) != 0x0) {
            obj.fog = NearFar.deserialize(buf, offset + 4);
        }
        if ((nullBits[0] & 0x2) != 0x0) {
            obj.fogOptions = FogOptions.deserialize(buf, offset + 12);
        }
        if ((nullBits[0] & 0x4) != 0x0) {
            final int varPos0 = offset + 126 + buf.getIntLE(offset + 30);
            final int idLen = VarInt.peek(buf, varPos0);
            if (idLen < 0) {
                throw ProtocolException.negativeLength("Id", idLen);
            }
            if (idLen > 4096000) {
                throw ProtocolException.stringTooLong("Id", idLen, 4096000);
            }
            obj.id = PacketIO.readVarString(buf, varPos0, PacketIO.UTF8);
        }
        if ((nullBits[0] & 0x8) != 0x0) {
            final int varPos2 = offset + 126 + buf.getIntLE(offset + 34);
            final int tagIndexesCount = VarInt.peek(buf, varPos2);
            if (tagIndexesCount < 0) {
                throw ProtocolException.negativeLength("TagIndexes", tagIndexesCount);
            }
            if (tagIndexesCount > 4096000) {
                throw ProtocolException.arrayTooLong("TagIndexes", tagIndexesCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos2);
            if (varPos2 + varIntLen + tagIndexesCount * 4L > buf.readableBytes()) {
                throw ProtocolException.bufferTooSmall("TagIndexes", varPos2 + varIntLen + tagIndexesCount * 4, buf.readableBytes());
            }
            obj.tagIndexes = new int[tagIndexesCount];
            for (int i = 0; i < tagIndexesCount; ++i) {
                obj.tagIndexes[i] = buf.getIntLE(varPos2 + varIntLen + i * 4);
            }
        }
        if ((nullBits[0] & 0x10) != 0x0) {
            final int varPos3 = offset + 126 + buf.getIntLE(offset + 38);
            final int starsLen = VarInt.peek(buf, varPos3);
            if (starsLen < 0) {
                throw ProtocolException.negativeLength("Stars", starsLen);
            }
            if (starsLen > 4096000) {
                throw ProtocolException.stringTooLong("Stars", starsLen, 4096000);
            }
            obj.stars = PacketIO.readVarString(buf, varPos3, PacketIO.UTF8);
        }
        if ((nullBits[0] & 0x20) != 0x0) {
            final int varPos4 = offset + 126 + buf.getIntLE(offset + 42);
            final int moonsCount = VarInt.peek(buf, varPos4);
            if (moonsCount < 0) {
                throw ProtocolException.negativeLength("Moons", moonsCount);
            }
            if (moonsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("Moons", moonsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos4);
            obj.moons = new HashMap<Integer, String>(moonsCount);
            int dictPos = varPos4 + varIntLen;
            for (int j = 0; j < moonsCount; ++j) {
                final int key = buf.getIntLE(dictPos);
                dictPos += 4;
                final int valLen = VarInt.peek(buf, dictPos);
                if (valLen < 0) {
                    throw ProtocolException.negativeLength("val", valLen);
                }
                if (valLen > 4096000) {
                    throw ProtocolException.stringTooLong("val", valLen, 4096000);
                }
                final int valVarLen = VarInt.length(buf, dictPos);
                final String val = PacketIO.readVarString(buf, dictPos);
                dictPos += valVarLen + valLen;
                if (obj.moons.put(key, val) != null) {
                    throw ProtocolException.duplicateKey("moons", key);
                }
            }
        }
        if ((nullBits[0] & 0x40) != 0x0) {
            final int varPos5 = offset + 126 + buf.getIntLE(offset + 46);
            final int cloudsCount = VarInt.peek(buf, varPos5);
            if (cloudsCount < 0) {
                throw ProtocolException.negativeLength("Clouds", cloudsCount);
            }
            if (cloudsCount > 4096000) {
                throw ProtocolException.arrayTooLong("Clouds", cloudsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos5);
            if (varPos5 + varIntLen + cloudsCount * 1L > buf.readableBytes()) {
                throw ProtocolException.bufferTooSmall("Clouds", varPos5 + varIntLen + cloudsCount * 1, buf.readableBytes());
            }
            obj.clouds = new Cloud[cloudsCount];
            int elemPos = varPos5 + varIntLen;
            for (int j = 0; j < cloudsCount; ++j) {
                obj.clouds[j] = Cloud.deserialize(buf, elemPos);
                elemPos += Cloud.computeBytesConsumed(buf, elemPos);
            }
        }
        if ((nullBits[0] & 0x80) != 0x0) {
            final int varPos6 = offset + 126 + buf.getIntLE(offset + 50);
            final int sunlightDampingMultiplierCount = VarInt.peek(buf, varPos6);
            if (sunlightDampingMultiplierCount < 0) {
                throw ProtocolException.negativeLength("SunlightDampingMultiplier", sunlightDampingMultiplierCount);
            }
            if (sunlightDampingMultiplierCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunlightDampingMultiplier", sunlightDampingMultiplierCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos6);
            obj.sunlightDampingMultiplier = new HashMap<Float, Float>(sunlightDampingMultiplierCount);
            int dictPos = varPos6 + varIntLen;
            for (int j = 0; j < sunlightDampingMultiplierCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final float val2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                if (obj.sunlightDampingMultiplier.put(key2, val2) != null) {
                    throw ProtocolException.duplicateKey("sunlightDampingMultiplier", key2);
                }
            }
        }
        if ((nullBits[1] & 0x1) != 0x0) {
            final int varPos7 = offset + 126 + buf.getIntLE(offset + 54);
            final int sunlightColorsCount = VarInt.peek(buf, varPos7);
            if (sunlightColorsCount < 0) {
                throw ProtocolException.negativeLength("SunlightColors", sunlightColorsCount);
            }
            if (sunlightColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunlightColors", sunlightColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos7);
            obj.sunlightColors = new HashMap<Float, Color>(sunlightColorsCount);
            int dictPos = varPos7 + varIntLen;
            for (int j = 0; j < sunlightColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final Color val3 = Color.deserialize(buf, dictPos);
                dictPos += Color.computeBytesConsumed(buf, dictPos);
                if (obj.sunlightColors.put(key2, val3) != null) {
                    throw ProtocolException.duplicateKey("sunlightColors", key2);
                }
            }
        }
        if ((nullBits[1] & 0x2) != 0x0) {
            final int varPos8 = offset + 126 + buf.getIntLE(offset + 58);
            final int skyTopColorsCount = VarInt.peek(buf, varPos8);
            if (skyTopColorsCount < 0) {
                throw ProtocolException.negativeLength("SkyTopColors", skyTopColorsCount);
            }
            if (skyTopColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SkyTopColors", skyTopColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos8);
            obj.skyTopColors = new HashMap<Float, ColorAlpha>(skyTopColorsCount);
            int dictPos = varPos8 + varIntLen;
            for (int j = 0; j < skyTopColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final ColorAlpha val4 = ColorAlpha.deserialize(buf, dictPos);
                dictPos += ColorAlpha.computeBytesConsumed(buf, dictPos);
                if (obj.skyTopColors.put(key2, val4) != null) {
                    throw ProtocolException.duplicateKey("skyTopColors", key2);
                }
            }
        }
        if ((nullBits[1] & 0x4) != 0x0) {
            final int varPos9 = offset + 126 + buf.getIntLE(offset + 62);
            final int skyBottomColorsCount = VarInt.peek(buf, varPos9);
            if (skyBottomColorsCount < 0) {
                throw ProtocolException.negativeLength("SkyBottomColors", skyBottomColorsCount);
            }
            if (skyBottomColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SkyBottomColors", skyBottomColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos9);
            obj.skyBottomColors = new HashMap<Float, ColorAlpha>(skyBottomColorsCount);
            int dictPos = varPos9 + varIntLen;
            for (int j = 0; j < skyBottomColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final ColorAlpha val4 = ColorAlpha.deserialize(buf, dictPos);
                dictPos += ColorAlpha.computeBytesConsumed(buf, dictPos);
                if (obj.skyBottomColors.put(key2, val4) != null) {
                    throw ProtocolException.duplicateKey("skyBottomColors", key2);
                }
            }
        }
        if ((nullBits[1] & 0x8) != 0x0) {
            final int varPos10 = offset + 126 + buf.getIntLE(offset + 66);
            final int skySunsetColorsCount = VarInt.peek(buf, varPos10);
            if (skySunsetColorsCount < 0) {
                throw ProtocolException.negativeLength("SkySunsetColors", skySunsetColorsCount);
            }
            if (skySunsetColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SkySunsetColors", skySunsetColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos10);
            obj.skySunsetColors = new HashMap<Float, ColorAlpha>(skySunsetColorsCount);
            int dictPos = varPos10 + varIntLen;
            for (int j = 0; j < skySunsetColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final ColorAlpha val4 = ColorAlpha.deserialize(buf, dictPos);
                dictPos += ColorAlpha.computeBytesConsumed(buf, dictPos);
                if (obj.skySunsetColors.put(key2, val4) != null) {
                    throw ProtocolException.duplicateKey("skySunsetColors", key2);
                }
            }
        }
        if ((nullBits[1] & 0x10) != 0x0) {
            final int varPos11 = offset + 126 + buf.getIntLE(offset + 70);
            final int sunColorsCount = VarInt.peek(buf, varPos11);
            if (sunColorsCount < 0) {
                throw ProtocolException.negativeLength("SunColors", sunColorsCount);
            }
            if (sunColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunColors", sunColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos11);
            obj.sunColors = new HashMap<Float, Color>(sunColorsCount);
            int dictPos = varPos11 + varIntLen;
            for (int j = 0; j < sunColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final Color val3 = Color.deserialize(buf, dictPos);
                dictPos += Color.computeBytesConsumed(buf, dictPos);
                if (obj.sunColors.put(key2, val3) != null) {
                    throw ProtocolException.duplicateKey("sunColors", key2);
                }
            }
        }
        if ((nullBits[1] & 0x20) != 0x0) {
            final int varPos12 = offset + 126 + buf.getIntLE(offset + 74);
            final int sunScalesCount = VarInt.peek(buf, varPos12);
            if (sunScalesCount < 0) {
                throw ProtocolException.negativeLength("SunScales", sunScalesCount);
            }
            if (sunScalesCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunScales", sunScalesCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos12);
            obj.sunScales = new HashMap<Float, Float>(sunScalesCount);
            int dictPos = varPos12 + varIntLen;
            for (int j = 0; j < sunScalesCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final float val2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                if (obj.sunScales.put(key2, val2) != null) {
                    throw ProtocolException.duplicateKey("sunScales", key2);
                }
            }
        }
        if ((nullBits[1] & 0x40) != 0x0) {
            final int varPos13 = offset + 126 + buf.getIntLE(offset + 78);
            final int sunGlowColorsCount = VarInt.peek(buf, varPos13);
            if (sunGlowColorsCount < 0) {
                throw ProtocolException.negativeLength("SunGlowColors", sunGlowColorsCount);
            }
            if (sunGlowColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunGlowColors", sunGlowColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos13);
            obj.sunGlowColors = new HashMap<Float, ColorAlpha>(sunGlowColorsCount);
            int dictPos = varPos13 + varIntLen;
            for (int j = 0; j < sunGlowColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final ColorAlpha val4 = ColorAlpha.deserialize(buf, dictPos);
                dictPos += ColorAlpha.computeBytesConsumed(buf, dictPos);
                if (obj.sunGlowColors.put(key2, val4) != null) {
                    throw ProtocolException.duplicateKey("sunGlowColors", key2);
                }
            }
        }
        if ((nullBits[1] & 0x80) != 0x0) {
            final int varPos14 = offset + 126 + buf.getIntLE(offset + 82);
            final int moonColorsCount = VarInt.peek(buf, varPos14);
            if (moonColorsCount < 0) {
                throw ProtocolException.negativeLength("MoonColors", moonColorsCount);
            }
            if (moonColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("MoonColors", moonColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos14);
            obj.moonColors = new HashMap<Float, ColorAlpha>(moonColorsCount);
            int dictPos = varPos14 + varIntLen;
            for (int j = 0; j < moonColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final ColorAlpha val4 = ColorAlpha.deserialize(buf, dictPos);
                dictPos += ColorAlpha.computeBytesConsumed(buf, dictPos);
                if (obj.moonColors.put(key2, val4) != null) {
                    throw ProtocolException.duplicateKey("moonColors", key2);
                }
            }
        }
        if ((nullBits[2] & 0x1) != 0x0) {
            final int varPos15 = offset + 126 + buf.getIntLE(offset + 86);
            final int moonScalesCount = VarInt.peek(buf, varPos15);
            if (moonScalesCount < 0) {
                throw ProtocolException.negativeLength("MoonScales", moonScalesCount);
            }
            if (moonScalesCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("MoonScales", moonScalesCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos15);
            obj.moonScales = new HashMap<Float, Float>(moonScalesCount);
            int dictPos = varPos15 + varIntLen;
            for (int j = 0; j < moonScalesCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final float val2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                if (obj.moonScales.put(key2, val2) != null) {
                    throw ProtocolException.duplicateKey("moonScales", key2);
                }
            }
        }
        if ((nullBits[2] & 0x2) != 0x0) {
            final int varPos16 = offset + 126 + buf.getIntLE(offset + 90);
            final int moonGlowColorsCount = VarInt.peek(buf, varPos16);
            if (moonGlowColorsCount < 0) {
                throw ProtocolException.negativeLength("MoonGlowColors", moonGlowColorsCount);
            }
            if (moonGlowColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("MoonGlowColors", moonGlowColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos16);
            obj.moonGlowColors = new HashMap<Float, ColorAlpha>(moonGlowColorsCount);
            int dictPos = varPos16 + varIntLen;
            for (int j = 0; j < moonGlowColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final ColorAlpha val4 = ColorAlpha.deserialize(buf, dictPos);
                dictPos += ColorAlpha.computeBytesConsumed(buf, dictPos);
                if (obj.moonGlowColors.put(key2, val4) != null) {
                    throw ProtocolException.duplicateKey("moonGlowColors", key2);
                }
            }
        }
        if ((nullBits[2] & 0x4) != 0x0) {
            final int varPos17 = offset + 126 + buf.getIntLE(offset + 94);
            final int fogColorsCount = VarInt.peek(buf, varPos17);
            if (fogColorsCount < 0) {
                throw ProtocolException.negativeLength("FogColors", fogColorsCount);
            }
            if (fogColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("FogColors", fogColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos17);
            obj.fogColors = new HashMap<Float, Color>(fogColorsCount);
            int dictPos = varPos17 + varIntLen;
            for (int j = 0; j < fogColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final Color val3 = Color.deserialize(buf, dictPos);
                dictPos += Color.computeBytesConsumed(buf, dictPos);
                if (obj.fogColors.put(key2, val3) != null) {
                    throw ProtocolException.duplicateKey("fogColors", key2);
                }
            }
        }
        if ((nullBits[2] & 0x8) != 0x0) {
            final int varPos18 = offset + 126 + buf.getIntLE(offset + 98);
            final int fogHeightFalloffsCount = VarInt.peek(buf, varPos18);
            if (fogHeightFalloffsCount < 0) {
                throw ProtocolException.negativeLength("FogHeightFalloffs", fogHeightFalloffsCount);
            }
            if (fogHeightFalloffsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("FogHeightFalloffs", fogHeightFalloffsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos18);
            obj.fogHeightFalloffs = new HashMap<Float, Float>(fogHeightFalloffsCount);
            int dictPos = varPos18 + varIntLen;
            for (int j = 0; j < fogHeightFalloffsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final float val2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                if (obj.fogHeightFalloffs.put(key2, val2) != null) {
                    throw ProtocolException.duplicateKey("fogHeightFalloffs", key2);
                }
            }
        }
        if ((nullBits[2] & 0x10) != 0x0) {
            final int varPos19 = offset + 126 + buf.getIntLE(offset + 102);
            final int fogDensitiesCount = VarInt.peek(buf, varPos19);
            if (fogDensitiesCount < 0) {
                throw ProtocolException.negativeLength("FogDensities", fogDensitiesCount);
            }
            if (fogDensitiesCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("FogDensities", fogDensitiesCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos19);
            obj.fogDensities = new HashMap<Float, Float>(fogDensitiesCount);
            int dictPos = varPos19 + varIntLen;
            for (int j = 0; j < fogDensitiesCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final float val2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                if (obj.fogDensities.put(key2, val2) != null) {
                    throw ProtocolException.duplicateKey("fogDensities", key2);
                }
            }
        }
        if ((nullBits[2] & 0x20) != 0x0) {
            final int varPos20 = offset + 126 + buf.getIntLE(offset + 106);
            final int screenEffectLen = VarInt.peek(buf, varPos20);
            if (screenEffectLen < 0) {
                throw ProtocolException.negativeLength("ScreenEffect", screenEffectLen);
            }
            if (screenEffectLen > 4096000) {
                throw ProtocolException.stringTooLong("ScreenEffect", screenEffectLen, 4096000);
            }
            obj.screenEffect = PacketIO.readVarString(buf, varPos20, PacketIO.UTF8);
        }
        if ((nullBits[2] & 0x40) != 0x0) {
            final int varPos21 = offset + 126 + buf.getIntLE(offset + 110);
            final int screenEffectColorsCount = VarInt.peek(buf, varPos21);
            if (screenEffectColorsCount < 0) {
                throw ProtocolException.negativeLength("ScreenEffectColors", screenEffectColorsCount);
            }
            if (screenEffectColorsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("ScreenEffectColors", screenEffectColorsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos21);
            obj.screenEffectColors = new HashMap<Float, ColorAlpha>(screenEffectColorsCount);
            int dictPos = varPos21 + varIntLen;
            for (int j = 0; j < screenEffectColorsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final ColorAlpha val4 = ColorAlpha.deserialize(buf, dictPos);
                dictPos += ColorAlpha.computeBytesConsumed(buf, dictPos);
                if (obj.screenEffectColors.put(key2, val4) != null) {
                    throw ProtocolException.duplicateKey("screenEffectColors", key2);
                }
            }
        }
        if ((nullBits[2] & 0x80) != 0x0) {
            final int varPos22 = offset + 126 + buf.getIntLE(offset + 114);
            final int colorFiltersCount = VarInt.peek(buf, varPos22);
            if (colorFiltersCount < 0) {
                throw ProtocolException.negativeLength("ColorFilters", colorFiltersCount);
            }
            if (colorFiltersCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("ColorFilters", colorFiltersCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos22);
            obj.colorFilters = new HashMap<Float, Color>(colorFiltersCount);
            int dictPos = varPos22 + varIntLen;
            for (int j = 0; j < colorFiltersCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final Color val3 = Color.deserialize(buf, dictPos);
                dictPos += Color.computeBytesConsumed(buf, dictPos);
                if (obj.colorFilters.put(key2, val3) != null) {
                    throw ProtocolException.duplicateKey("colorFilters", key2);
                }
            }
        }
        if ((nullBits[3] & 0x1) != 0x0) {
            final int varPos23 = offset + 126 + buf.getIntLE(offset + 118);
            final int waterTintsCount = VarInt.peek(buf, varPos23);
            if (waterTintsCount < 0) {
                throw ProtocolException.negativeLength("WaterTints", waterTintsCount);
            }
            if (waterTintsCount > 4096000) {
                throw ProtocolException.dictionaryTooLarge("WaterTints", waterTintsCount, 4096000);
            }
            final int varIntLen = VarInt.length(buf, varPos23);
            obj.waterTints = new HashMap<Float, Color>(waterTintsCount);
            int dictPos = varPos23 + varIntLen;
            for (int j = 0; j < waterTintsCount; ++j) {
                final float key2 = buf.getFloatLE(dictPos);
                dictPos += 4;
                final Color val3 = Color.deserialize(buf, dictPos);
                dictPos += Color.computeBytesConsumed(buf, dictPos);
                if (obj.waterTints.put(key2, val3) != null) {
                    throw ProtocolException.duplicateKey("waterTints", key2);
                }
            }
        }
        if ((nullBits[3] & 0x2) != 0x0) {
            final int varPos24 = offset + 126 + buf.getIntLE(offset + 122);
            obj.particle = WeatherParticle.deserialize(buf, varPos24);
        }
        return obj;
    }
    
    public static int computeBytesConsumed(@Nonnull final ByteBuf buf, final int offset) {
        final byte[] nullBits = PacketIO.readBytes(buf, offset, 4);
        int maxEnd = 126;
        if ((nullBits[0] & 0x4) != 0x0) {
            final int fieldOffset0 = buf.getIntLE(offset + 30);
            int pos0 = offset + 126 + fieldOffset0;
            final int sl = VarInt.peek(buf, pos0);
            pos0 += VarInt.length(buf, pos0) + sl;
            if (pos0 - offset > maxEnd) {
                maxEnd = pos0 - offset;
            }
        }
        if ((nullBits[0] & 0x8) != 0x0) {
            final int fieldOffset2 = buf.getIntLE(offset + 34);
            int pos2 = offset + 126 + fieldOffset2;
            final int arrLen = VarInt.peek(buf, pos2);
            pos2 += VarInt.length(buf, pos2) + arrLen * 4;
            if (pos2 - offset > maxEnd) {
                maxEnd = pos2 - offset;
            }
        }
        if ((nullBits[0] & 0x10) != 0x0) {
            final int fieldOffset3 = buf.getIntLE(offset + 38);
            int pos3 = offset + 126 + fieldOffset3;
            final int sl = VarInt.peek(buf, pos3);
            pos3 += VarInt.length(buf, pos3) + sl;
            if (pos3 - offset > maxEnd) {
                maxEnd = pos3 - offset;
            }
        }
        if ((nullBits[0] & 0x20) != 0x0) {
            final int fieldOffset4 = buf.getIntLE(offset + 42);
            int pos4 = offset + 126 + fieldOffset4;
            final int dictLen = VarInt.peek(buf, pos4);
            pos4 += VarInt.length(buf, pos4);
            for (int i = 0; i < dictLen; ++i) {
                pos4 += 4;
                final int sl2 = VarInt.peek(buf, pos4);
                pos4 += VarInt.length(buf, pos4) + sl2;
            }
            if (pos4 - offset > maxEnd) {
                maxEnd = pos4 - offset;
            }
        }
        if ((nullBits[0] & 0x40) != 0x0) {
            final int fieldOffset5 = buf.getIntLE(offset + 46);
            int pos5 = offset + 126 + fieldOffset5;
            final int arrLen = VarInt.peek(buf, pos5);
            pos5 += VarInt.length(buf, pos5);
            for (int i = 0; i < arrLen; ++i) {
                pos5 += Cloud.computeBytesConsumed(buf, pos5);
            }
            if (pos5 - offset > maxEnd) {
                maxEnd = pos5 - offset;
            }
        }
        if ((nullBits[0] & 0x80) != 0x0) {
            final int fieldOffset6 = buf.getIntLE(offset + 50);
            int pos6 = offset + 126 + fieldOffset6;
            final int dictLen = VarInt.peek(buf, pos6);
            pos6 += VarInt.length(buf, pos6);
            for (int i = 0; i < dictLen; ++i) {
                pos6 += 4;
                pos6 += 4;
            }
            if (pos6 - offset > maxEnd) {
                maxEnd = pos6 - offset;
            }
        }
        if ((nullBits[1] & 0x1) != 0x0) {
            final int fieldOffset7 = buf.getIntLE(offset + 54);
            int pos7 = offset + 126 + fieldOffset7;
            final int dictLen = VarInt.peek(buf, pos7);
            pos7 += VarInt.length(buf, pos7);
            for (int i = 0; i < dictLen; ++i) {
                pos7 += 4;
                pos7 += Color.computeBytesConsumed(buf, pos7);
            }
            if (pos7 - offset > maxEnd) {
                maxEnd = pos7 - offset;
            }
        }
        if ((nullBits[1] & 0x2) != 0x0) {
            final int fieldOffset8 = buf.getIntLE(offset + 58);
            int pos8 = offset + 126 + fieldOffset8;
            final int dictLen = VarInt.peek(buf, pos8);
            pos8 += VarInt.length(buf, pos8);
            for (int i = 0; i < dictLen; ++i) {
                pos8 += 4;
                pos8 += ColorAlpha.computeBytesConsumed(buf, pos8);
            }
            if (pos8 - offset > maxEnd) {
                maxEnd = pos8 - offset;
            }
        }
        if ((nullBits[1] & 0x4) != 0x0) {
            final int fieldOffset9 = buf.getIntLE(offset + 62);
            int pos9 = offset + 126 + fieldOffset9;
            final int dictLen = VarInt.peek(buf, pos9);
            pos9 += VarInt.length(buf, pos9);
            for (int i = 0; i < dictLen; ++i) {
                pos9 += 4;
                pos9 += ColorAlpha.computeBytesConsumed(buf, pos9);
            }
            if (pos9 - offset > maxEnd) {
                maxEnd = pos9 - offset;
            }
        }
        if ((nullBits[1] & 0x8) != 0x0) {
            final int fieldOffset10 = buf.getIntLE(offset + 66);
            int pos10 = offset + 126 + fieldOffset10;
            final int dictLen = VarInt.peek(buf, pos10);
            pos10 += VarInt.length(buf, pos10);
            for (int i = 0; i < dictLen; ++i) {
                pos10 += 4;
                pos10 += ColorAlpha.computeBytesConsumed(buf, pos10);
            }
            if (pos10 - offset > maxEnd) {
                maxEnd = pos10 - offset;
            }
        }
        if ((nullBits[1] & 0x10) != 0x0) {
            final int fieldOffset11 = buf.getIntLE(offset + 70);
            int pos11 = offset + 126 + fieldOffset11;
            final int dictLen = VarInt.peek(buf, pos11);
            pos11 += VarInt.length(buf, pos11);
            for (int i = 0; i < dictLen; ++i) {
                pos11 += 4;
                pos11 += Color.computeBytesConsumed(buf, pos11);
            }
            if (pos11 - offset > maxEnd) {
                maxEnd = pos11 - offset;
            }
        }
        if ((nullBits[1] & 0x20) != 0x0) {
            final int fieldOffset12 = buf.getIntLE(offset + 74);
            int pos12 = offset + 126 + fieldOffset12;
            final int dictLen = VarInt.peek(buf, pos12);
            pos12 += VarInt.length(buf, pos12);
            for (int i = 0; i < dictLen; ++i) {
                pos12 += 4;
                pos12 += 4;
            }
            if (pos12 - offset > maxEnd) {
                maxEnd = pos12 - offset;
            }
        }
        if ((nullBits[1] & 0x40) != 0x0) {
            final int fieldOffset13 = buf.getIntLE(offset + 78);
            int pos13 = offset + 126 + fieldOffset13;
            final int dictLen = VarInt.peek(buf, pos13);
            pos13 += VarInt.length(buf, pos13);
            for (int i = 0; i < dictLen; ++i) {
                pos13 += 4;
                pos13 += ColorAlpha.computeBytesConsumed(buf, pos13);
            }
            if (pos13 - offset > maxEnd) {
                maxEnd = pos13 - offset;
            }
        }
        if ((nullBits[1] & 0x80) != 0x0) {
            final int fieldOffset14 = buf.getIntLE(offset + 82);
            int pos14 = offset + 126 + fieldOffset14;
            final int dictLen = VarInt.peek(buf, pos14);
            pos14 += VarInt.length(buf, pos14);
            for (int i = 0; i < dictLen; ++i) {
                pos14 += 4;
                pos14 += ColorAlpha.computeBytesConsumed(buf, pos14);
            }
            if (pos14 - offset > maxEnd) {
                maxEnd = pos14 - offset;
            }
        }
        if ((nullBits[2] & 0x1) != 0x0) {
            final int fieldOffset15 = buf.getIntLE(offset + 86);
            int pos15 = offset + 126 + fieldOffset15;
            final int dictLen = VarInt.peek(buf, pos15);
            pos15 += VarInt.length(buf, pos15);
            for (int i = 0; i < dictLen; ++i) {
                pos15 += 4;
                pos15 += 4;
            }
            if (pos15 - offset > maxEnd) {
                maxEnd = pos15 - offset;
            }
        }
        if ((nullBits[2] & 0x2) != 0x0) {
            final int fieldOffset16 = buf.getIntLE(offset + 90);
            int pos16 = offset + 126 + fieldOffset16;
            final int dictLen = VarInt.peek(buf, pos16);
            pos16 += VarInt.length(buf, pos16);
            for (int i = 0; i < dictLen; ++i) {
                pos16 += 4;
                pos16 += ColorAlpha.computeBytesConsumed(buf, pos16);
            }
            if (pos16 - offset > maxEnd) {
                maxEnd = pos16 - offset;
            }
        }
        if ((nullBits[2] & 0x4) != 0x0) {
            final int fieldOffset17 = buf.getIntLE(offset + 94);
            int pos17 = offset + 126 + fieldOffset17;
            final int dictLen = VarInt.peek(buf, pos17);
            pos17 += VarInt.length(buf, pos17);
            for (int i = 0; i < dictLen; ++i) {
                pos17 += 4;
                pos17 += Color.computeBytesConsumed(buf, pos17);
            }
            if (pos17 - offset > maxEnd) {
                maxEnd = pos17 - offset;
            }
        }
        if ((nullBits[2] & 0x8) != 0x0) {
            final int fieldOffset18 = buf.getIntLE(offset + 98);
            int pos18 = offset + 126 + fieldOffset18;
            final int dictLen = VarInt.peek(buf, pos18);
            pos18 += VarInt.length(buf, pos18);
            for (int i = 0; i < dictLen; ++i) {
                pos18 += 4;
                pos18 += 4;
            }
            if (pos18 - offset > maxEnd) {
                maxEnd = pos18 - offset;
            }
        }
        if ((nullBits[2] & 0x10) != 0x0) {
            final int fieldOffset19 = buf.getIntLE(offset + 102);
            int pos19 = offset + 126 + fieldOffset19;
            final int dictLen = VarInt.peek(buf, pos19);
            pos19 += VarInt.length(buf, pos19);
            for (int i = 0; i < dictLen; ++i) {
                pos19 += 4;
                pos19 += 4;
            }
            if (pos19 - offset > maxEnd) {
                maxEnd = pos19 - offset;
            }
        }
        if ((nullBits[2] & 0x20) != 0x0) {
            final int fieldOffset20 = buf.getIntLE(offset + 106);
            int pos20 = offset + 126 + fieldOffset20;
            final int sl = VarInt.peek(buf, pos20);
            pos20 += VarInt.length(buf, pos20) + sl;
            if (pos20 - offset > maxEnd) {
                maxEnd = pos20 - offset;
            }
        }
        if ((nullBits[2] & 0x40) != 0x0) {
            final int fieldOffset21 = buf.getIntLE(offset + 110);
            int pos21 = offset + 126 + fieldOffset21;
            final int dictLen = VarInt.peek(buf, pos21);
            pos21 += VarInt.length(buf, pos21);
            for (int i = 0; i < dictLen; ++i) {
                pos21 += 4;
                pos21 += ColorAlpha.computeBytesConsumed(buf, pos21);
            }
            if (pos21 - offset > maxEnd) {
                maxEnd = pos21 - offset;
            }
        }
        if ((nullBits[2] & 0x80) != 0x0) {
            final int fieldOffset22 = buf.getIntLE(offset + 114);
            int pos22 = offset + 126 + fieldOffset22;
            final int dictLen = VarInt.peek(buf, pos22);
            pos22 += VarInt.length(buf, pos22);
            for (int i = 0; i < dictLen; ++i) {
                pos22 += 4;
                pos22 += Color.computeBytesConsumed(buf, pos22);
            }
            if (pos22 - offset > maxEnd) {
                maxEnd = pos22 - offset;
            }
        }
        if ((nullBits[3] & 0x1) != 0x0) {
            final int fieldOffset23 = buf.getIntLE(offset + 118);
            int pos23 = offset + 126 + fieldOffset23;
            final int dictLen = VarInt.peek(buf, pos23);
            pos23 += VarInt.length(buf, pos23);
            for (int i = 0; i < dictLen; ++i) {
                pos23 += 4;
                pos23 += Color.computeBytesConsumed(buf, pos23);
            }
            if (pos23 - offset > maxEnd) {
                maxEnd = pos23 - offset;
            }
        }
        if ((nullBits[3] & 0x2) != 0x0) {
            final int fieldOffset24 = buf.getIntLE(offset + 122);
            int pos24 = offset + 126 + fieldOffset24;
            pos24 += WeatherParticle.computeBytesConsumed(buf, pos24);
            if (pos24 - offset > maxEnd) {
                maxEnd = pos24 - offset;
            }
        }
        return maxEnd;
    }
    
    public void serialize(@Nonnull final ByteBuf buf) {
        final int startPos = buf.writerIndex();
        final byte[] nullBits = new byte[4];
        if (this.fog != null) {
            final byte[] array = nullBits;
            final int n = 0;
            array[n] |= 0x1;
        }
        if (this.fogOptions != null) {
            final byte[] array2 = nullBits;
            final int n2 = 0;
            array2[n2] |= 0x2;
        }
        if (this.id != null) {
            final byte[] array3 = nullBits;
            final int n3 = 0;
            array3[n3] |= 0x4;
        }
        if (this.tagIndexes != null) {
            final byte[] array4 = nullBits;
            final int n4 = 0;
            array4[n4] |= 0x8;
        }
        if (this.stars != null) {
            final byte[] array5 = nullBits;
            final int n5 = 0;
            array5[n5] |= 0x10;
        }
        if (this.moons != null) {
            final byte[] array6 = nullBits;
            final int n6 = 0;
            array6[n6] |= 0x20;
        }
        if (this.clouds != null) {
            final byte[] array7 = nullBits;
            final int n7 = 0;
            array7[n7] |= 0x40;
        }
        if (this.sunlightDampingMultiplier != null) {
            final byte[] array8 = nullBits;
            final int n8 = 0;
            array8[n8] |= (byte)128;
        }
        if (this.sunlightColors != null) {
            final byte[] array9 = nullBits;
            final int n9 = 1;
            array9[n9] |= 0x1;
        }
        if (this.skyTopColors != null) {
            final byte[] array10 = nullBits;
            final int n10 = 1;
            array10[n10] |= 0x2;
        }
        if (this.skyBottomColors != null) {
            final byte[] array11 = nullBits;
            final int n11 = 1;
            array11[n11] |= 0x4;
        }
        if (this.skySunsetColors != null) {
            final byte[] array12 = nullBits;
            final int n12 = 1;
            array12[n12] |= 0x8;
        }
        if (this.sunColors != null) {
            final byte[] array13 = nullBits;
            final int n13 = 1;
            array13[n13] |= 0x10;
        }
        if (this.sunScales != null) {
            final byte[] array14 = nullBits;
            final int n14 = 1;
            array14[n14] |= 0x20;
        }
        if (this.sunGlowColors != null) {
            final byte[] array15 = nullBits;
            final int n15 = 1;
            array15[n15] |= 0x40;
        }
        if (this.moonColors != null) {
            final byte[] array16 = nullBits;
            final int n16 = 1;
            array16[n16] |= (byte)128;
        }
        if (this.moonScales != null) {
            final byte[] array17 = nullBits;
            final int n17 = 2;
            array17[n17] |= 0x1;
        }
        if (this.moonGlowColors != null) {
            final byte[] array18 = nullBits;
            final int n18 = 2;
            array18[n18] |= 0x2;
        }
        if (this.fogColors != null) {
            final byte[] array19 = nullBits;
            final int n19 = 2;
            array19[n19] |= 0x4;
        }
        if (this.fogHeightFalloffs != null) {
            final byte[] array20 = nullBits;
            final int n20 = 2;
            array20[n20] |= 0x8;
        }
        if (this.fogDensities != null) {
            final byte[] array21 = nullBits;
            final int n21 = 2;
            array21[n21] |= 0x10;
        }
        if (this.screenEffect != null) {
            final byte[] array22 = nullBits;
            final int n22 = 2;
            array22[n22] |= 0x20;
        }
        if (this.screenEffectColors != null) {
            final byte[] array23 = nullBits;
            final int n23 = 2;
            array23[n23] |= 0x40;
        }
        if (this.colorFilters != null) {
            final byte[] array24 = nullBits;
            final int n24 = 2;
            array24[n24] |= (byte)128;
        }
        if (this.waterTints != null) {
            final byte[] array25 = nullBits;
            final int n25 = 3;
            array25[n25] |= 0x1;
        }
        if (this.particle != null) {
            final byte[] array26 = nullBits;
            final int n26 = 3;
            array26[n26] |= 0x2;
        }
        buf.writeBytes(nullBits);
        if (this.fog != null) {
            this.fog.serialize(buf);
        }
        else {
            buf.writeZero(8);
        }
        if (this.fogOptions != null) {
            this.fogOptions.serialize(buf);
        }
        else {
            buf.writeZero(18);
        }
        final int idOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int tagIndexesOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int starsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int moonsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int cloudsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int sunlightDampingMultiplierOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int sunlightColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int skyTopColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int skyBottomColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int skySunsetColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int sunColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int sunScalesOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int sunGlowColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int moonColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int moonScalesOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int moonGlowColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int fogColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int fogHeightFalloffsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int fogDensitiesOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int screenEffectOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int screenEffectColorsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int colorFiltersOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int waterTintsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int particleOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int varBlockStart = buf.writerIndex();
        if (this.id != null) {
            buf.setIntLE(idOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.id, 4096000);
        }
        else {
            buf.setIntLE(idOffsetSlot, -1);
        }
        if (this.tagIndexes != null) {
            buf.setIntLE(tagIndexesOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.tagIndexes.length > 4096000) {
                throw ProtocolException.arrayTooLong("TagIndexes", this.tagIndexes.length, 4096000);
            }
            VarInt.write(buf, this.tagIndexes.length);
            for (final int item : this.tagIndexes) {
                buf.writeIntLE(item);
            }
        }
        else {
            buf.setIntLE(tagIndexesOffsetSlot, -1);
        }
        if (this.stars != null) {
            buf.setIntLE(starsOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.stars, 4096000);
        }
        else {
            buf.setIntLE(starsOffsetSlot, -1);
        }
        if (this.moons != null) {
            buf.setIntLE(moonsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.moons.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("Moons", this.moons.size(), 4096000);
            }
            VarInt.write(buf, this.moons.size());
            for (final Map.Entry<Integer, String> e : this.moons.entrySet()) {
                buf.writeIntLE(e.getKey());
                PacketIO.writeVarString(buf, e.getValue(), 4096000);
            }
        }
        else {
            buf.setIntLE(moonsOffsetSlot, -1);
        }
        if (this.clouds != null) {
            buf.setIntLE(cloudsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.clouds.length > 4096000) {
                throw ProtocolException.arrayTooLong("Clouds", this.clouds.length, 4096000);
            }
            VarInt.write(buf, this.clouds.length);
            for (final Cloud item2 : this.clouds) {
                item2.serialize(buf);
            }
        }
        else {
            buf.setIntLE(cloudsOffsetSlot, -1);
        }
        if (this.sunlightDampingMultiplier != null) {
            buf.setIntLE(sunlightDampingMultiplierOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.sunlightDampingMultiplier.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunlightDampingMultiplier", this.sunlightDampingMultiplier.size(), 4096000);
            }
            VarInt.write(buf, this.sunlightDampingMultiplier.size());
            for (final Map.Entry<Float, Float> e2 : this.sunlightDampingMultiplier.entrySet()) {
                buf.writeFloatLE(e2.getKey());
                buf.writeFloatLE(e2.getValue());
            }
        }
        else {
            buf.setIntLE(sunlightDampingMultiplierOffsetSlot, -1);
        }
        if (this.sunlightColors != null) {
            buf.setIntLE(sunlightColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.sunlightColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunlightColors", this.sunlightColors.size(), 4096000);
            }
            VarInt.write(buf, this.sunlightColors.size());
            for (final Map.Entry<Float, Color> e3 : this.sunlightColors.entrySet()) {
                buf.writeFloatLE(e3.getKey());
                e3.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(sunlightColorsOffsetSlot, -1);
        }
        if (this.skyTopColors != null) {
            buf.setIntLE(skyTopColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.skyTopColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SkyTopColors", this.skyTopColors.size(), 4096000);
            }
            VarInt.write(buf, this.skyTopColors.size());
            for (final Map.Entry<Float, ColorAlpha> e4 : this.skyTopColors.entrySet()) {
                buf.writeFloatLE(e4.getKey());
                e4.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(skyTopColorsOffsetSlot, -1);
        }
        if (this.skyBottomColors != null) {
            buf.setIntLE(skyBottomColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.skyBottomColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SkyBottomColors", this.skyBottomColors.size(), 4096000);
            }
            VarInt.write(buf, this.skyBottomColors.size());
            for (final Map.Entry<Float, ColorAlpha> e4 : this.skyBottomColors.entrySet()) {
                buf.writeFloatLE(e4.getKey());
                e4.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(skyBottomColorsOffsetSlot, -1);
        }
        if (this.skySunsetColors != null) {
            buf.setIntLE(skySunsetColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.skySunsetColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SkySunsetColors", this.skySunsetColors.size(), 4096000);
            }
            VarInt.write(buf, this.skySunsetColors.size());
            for (final Map.Entry<Float, ColorAlpha> e4 : this.skySunsetColors.entrySet()) {
                buf.writeFloatLE(e4.getKey());
                e4.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(skySunsetColorsOffsetSlot, -1);
        }
        if (this.sunColors != null) {
            buf.setIntLE(sunColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.sunColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunColors", this.sunColors.size(), 4096000);
            }
            VarInt.write(buf, this.sunColors.size());
            for (final Map.Entry<Float, Color> e3 : this.sunColors.entrySet()) {
                buf.writeFloatLE(e3.getKey());
                e3.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(sunColorsOffsetSlot, -1);
        }
        if (this.sunScales != null) {
            buf.setIntLE(sunScalesOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.sunScales.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunScales", this.sunScales.size(), 4096000);
            }
            VarInt.write(buf, this.sunScales.size());
            for (final Map.Entry<Float, Float> e2 : this.sunScales.entrySet()) {
                buf.writeFloatLE(e2.getKey());
                buf.writeFloatLE(e2.getValue());
            }
        }
        else {
            buf.setIntLE(sunScalesOffsetSlot, -1);
        }
        if (this.sunGlowColors != null) {
            buf.setIntLE(sunGlowColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.sunGlowColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("SunGlowColors", this.sunGlowColors.size(), 4096000);
            }
            VarInt.write(buf, this.sunGlowColors.size());
            for (final Map.Entry<Float, ColorAlpha> e4 : this.sunGlowColors.entrySet()) {
                buf.writeFloatLE(e4.getKey());
                e4.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(sunGlowColorsOffsetSlot, -1);
        }
        if (this.moonColors != null) {
            buf.setIntLE(moonColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.moonColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("MoonColors", this.moonColors.size(), 4096000);
            }
            VarInt.write(buf, this.moonColors.size());
            for (final Map.Entry<Float, ColorAlpha> e4 : this.moonColors.entrySet()) {
                buf.writeFloatLE(e4.getKey());
                e4.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(moonColorsOffsetSlot, -1);
        }
        if (this.moonScales != null) {
            buf.setIntLE(moonScalesOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.moonScales.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("MoonScales", this.moonScales.size(), 4096000);
            }
            VarInt.write(buf, this.moonScales.size());
            for (final Map.Entry<Float, Float> e2 : this.moonScales.entrySet()) {
                buf.writeFloatLE(e2.getKey());
                buf.writeFloatLE(e2.getValue());
            }
        }
        else {
            buf.setIntLE(moonScalesOffsetSlot, -1);
        }
        if (this.moonGlowColors != null) {
            buf.setIntLE(moonGlowColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.moonGlowColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("MoonGlowColors", this.moonGlowColors.size(), 4096000);
            }
            VarInt.write(buf, this.moonGlowColors.size());
            for (final Map.Entry<Float, ColorAlpha> e4 : this.moonGlowColors.entrySet()) {
                buf.writeFloatLE(e4.getKey());
                e4.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(moonGlowColorsOffsetSlot, -1);
        }
        if (this.fogColors != null) {
            buf.setIntLE(fogColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.fogColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("FogColors", this.fogColors.size(), 4096000);
            }
            VarInt.write(buf, this.fogColors.size());
            for (final Map.Entry<Float, Color> e3 : this.fogColors.entrySet()) {
                buf.writeFloatLE(e3.getKey());
                e3.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(fogColorsOffsetSlot, -1);
        }
        if (this.fogHeightFalloffs != null) {
            buf.setIntLE(fogHeightFalloffsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.fogHeightFalloffs.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("FogHeightFalloffs", this.fogHeightFalloffs.size(), 4096000);
            }
            VarInt.write(buf, this.fogHeightFalloffs.size());
            for (final Map.Entry<Float, Float> e2 : this.fogHeightFalloffs.entrySet()) {
                buf.writeFloatLE(e2.getKey());
                buf.writeFloatLE(e2.getValue());
            }
        }
        else {
            buf.setIntLE(fogHeightFalloffsOffsetSlot, -1);
        }
        if (this.fogDensities != null) {
            buf.setIntLE(fogDensitiesOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.fogDensities.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("FogDensities", this.fogDensities.size(), 4096000);
            }
            VarInt.write(buf, this.fogDensities.size());
            for (final Map.Entry<Float, Float> e2 : this.fogDensities.entrySet()) {
                buf.writeFloatLE(e2.getKey());
                buf.writeFloatLE(e2.getValue());
            }
        }
        else {
            buf.setIntLE(fogDensitiesOffsetSlot, -1);
        }
        if (this.screenEffect != null) {
            buf.setIntLE(screenEffectOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.screenEffect, 4096000);
        }
        else {
            buf.setIntLE(screenEffectOffsetSlot, -1);
        }
        if (this.screenEffectColors != null) {
            buf.setIntLE(screenEffectColorsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.screenEffectColors.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("ScreenEffectColors", this.screenEffectColors.size(), 4096000);
            }
            VarInt.write(buf, this.screenEffectColors.size());
            for (final Map.Entry<Float, ColorAlpha> e4 : this.screenEffectColors.entrySet()) {
                buf.writeFloatLE(e4.getKey());
                e4.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(screenEffectColorsOffsetSlot, -1);
        }
        if (this.colorFilters != null) {
            buf.setIntLE(colorFiltersOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.colorFilters.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("ColorFilters", this.colorFilters.size(), 4096000);
            }
            VarInt.write(buf, this.colorFilters.size());
            for (final Map.Entry<Float, Color> e3 : this.colorFilters.entrySet()) {
                buf.writeFloatLE(e3.getKey());
                e3.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(colorFiltersOffsetSlot, -1);
        }
        if (this.waterTints != null) {
            buf.setIntLE(waterTintsOffsetSlot, buf.writerIndex() - varBlockStart);
            if (this.waterTints.size() > 4096000) {
                throw ProtocolException.dictionaryTooLarge("WaterTints", this.waterTints.size(), 4096000);
            }
            VarInt.write(buf, this.waterTints.size());
            for (final Map.Entry<Float, Color> e3 : this.waterTints.entrySet()) {
                buf.writeFloatLE(e3.getKey());
                e3.getValue().serialize(buf);
            }
        }
        else {
            buf.setIntLE(waterTintsOffsetSlot, -1);
        }
        if (this.particle != null) {
            buf.setIntLE(particleOffsetSlot, buf.writerIndex() - varBlockStart);
            this.particle.serialize(buf);
        }
        else {
            buf.setIntLE(particleOffsetSlot, -1);
        }
    }
    
    public int computeSize() {
        int size = 126;
        if (this.id != null) {
            size += PacketIO.stringSize(this.id);
        }
        if (this.tagIndexes != null) {
            size += VarInt.size(this.tagIndexes.length) + this.tagIndexes.length * 4;
        }
        if (this.stars != null) {
            size += PacketIO.stringSize(this.stars);
        }
        if (this.moons != null) {
            int moonsSize = 0;
            for (final Map.Entry<Integer, String> kvp : this.moons.entrySet()) {
                moonsSize += 4 + PacketIO.stringSize(kvp.getValue());
            }
            size += VarInt.size(this.moons.size()) + moonsSize;
        }
        if (this.clouds != null) {
            int cloudsSize = 0;
            for (final Cloud elem : this.clouds) {
                cloudsSize += elem.computeSize();
            }
            size += VarInt.size(this.clouds.length) + cloudsSize;
        }
        if (this.sunlightDampingMultiplier != null) {
            size += VarInt.size(this.sunlightDampingMultiplier.size()) + this.sunlightDampingMultiplier.size() * 8;
        }
        if (this.sunlightColors != null) {
            size += VarInt.size(this.sunlightColors.size()) + this.sunlightColors.size() * 7;
        }
        if (this.skyTopColors != null) {
            size += VarInt.size(this.skyTopColors.size()) + this.skyTopColors.size() * 8;
        }
        if (this.skyBottomColors != null) {
            size += VarInt.size(this.skyBottomColors.size()) + this.skyBottomColors.size() * 8;
        }
        if (this.skySunsetColors != null) {
            size += VarInt.size(this.skySunsetColors.size()) + this.skySunsetColors.size() * 8;
        }
        if (this.sunColors != null) {
            size += VarInt.size(this.sunColors.size()) + this.sunColors.size() * 7;
        }
        if (this.sunScales != null) {
            size += VarInt.size(this.sunScales.size()) + this.sunScales.size() * 8;
        }
        if (this.sunGlowColors != null) {
            size += VarInt.size(this.sunGlowColors.size()) + this.sunGlowColors.size() * 8;
        }
        if (this.moonColors != null) {
            size += VarInt.size(this.moonColors.size()) + this.moonColors.size() * 8;
        }
        if (this.moonScales != null) {
            size += VarInt.size(this.moonScales.size()) + this.moonScales.size() * 8;
        }
        if (this.moonGlowColors != null) {
            size += VarInt.size(this.moonGlowColors.size()) + this.moonGlowColors.size() * 8;
        }
        if (this.fogColors != null) {
            size += VarInt.size(this.fogColors.size()) + this.fogColors.size() * 7;
        }
        if (this.fogHeightFalloffs != null) {
            size += VarInt.size(this.fogHeightFalloffs.size()) + this.fogHeightFalloffs.size() * 8;
        }
        if (this.fogDensities != null) {
            size += VarInt.size(this.fogDensities.size()) + this.fogDensities.size() * 8;
        }
        if (this.screenEffect != null) {
            size += PacketIO.stringSize(this.screenEffect);
        }
        if (this.screenEffectColors != null) {
            size += VarInt.size(this.screenEffectColors.size()) + this.screenEffectColors.size() * 8;
        }
        if (this.colorFilters != null) {
            size += VarInt.size(this.colorFilters.size()) + this.colorFilters.size() * 7;
        }
        if (this.waterTints != null) {
            size += VarInt.size(this.waterTints.size()) + this.waterTints.size() * 7;
        }
        if (this.particle != null) {
            size += this.particle.computeSize();
        }
        return size;
    }
    
    public static ValidationResult validateStructure(@Nonnull final ByteBuf buffer, final int offset) {
        if (buffer.readableBytes() - offset < 126) {
            return ValidationResult.error("Buffer too small: expected at least 126 bytes");
        }
        final byte[] nullBits = PacketIO.readBytes(buffer, offset, 4);
        if ((nullBits[0] & 0x4) != 0x0) {
            final int idOffset = buffer.getIntLE(offset + 30);
            if (idOffset < 0) {
                return ValidationResult.error("Invalid offset for Id");
            }
            int pos = offset + 126 + idOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Id");
            }
            final int idLen = VarInt.peek(buffer, pos);
            if (idLen < 0) {
                return ValidationResult.error("Invalid string length for Id");
            }
            if (idLen > 4096000) {
                return ValidationResult.error("Id exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += idLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Id");
            }
        }
        if ((nullBits[0] & 0x8) != 0x0) {
            final int tagIndexesOffset = buffer.getIntLE(offset + 34);
            if (tagIndexesOffset < 0) {
                return ValidationResult.error("Invalid offset for TagIndexes");
            }
            int pos = offset + 126 + tagIndexesOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for TagIndexes");
            }
            final int tagIndexesCount = VarInt.peek(buffer, pos);
            if (tagIndexesCount < 0) {
                return ValidationResult.error("Invalid array count for TagIndexes");
            }
            if (tagIndexesCount > 4096000) {
                return ValidationResult.error("TagIndexes exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += tagIndexesCount * 4;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading TagIndexes");
            }
        }
        if ((nullBits[0] & 0x10) != 0x0) {
            final int starsOffset = buffer.getIntLE(offset + 38);
            if (starsOffset < 0) {
                return ValidationResult.error("Invalid offset for Stars");
            }
            int pos = offset + 126 + starsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Stars");
            }
            final int starsLen = VarInt.peek(buffer, pos);
            if (starsLen < 0) {
                return ValidationResult.error("Invalid string length for Stars");
            }
            if (starsLen > 4096000) {
                return ValidationResult.error("Stars exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += starsLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Stars");
            }
        }
        if ((nullBits[0] & 0x20) != 0x0) {
            final int moonsOffset = buffer.getIntLE(offset + 42);
            if (moonsOffset < 0) {
                return ValidationResult.error("Invalid offset for Moons");
            }
            int pos = offset + 126 + moonsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Moons");
            }
            final int moonsCount = VarInt.peek(buffer, pos);
            if (moonsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for Moons");
            }
            if (moonsCount > 4096000) {
                return ValidationResult.error("Moons exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < moonsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                final int valueLen = VarInt.peek(buffer, pos);
                if (valueLen < 0) {
                    return ValidationResult.error("Invalid string length for value");
                }
                if (valueLen > 4096000) {
                    return ValidationResult.error("value exceeds max length 4096000");
                }
                pos += VarInt.length(buffer, pos);
                pos += valueLen;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading value");
                }
            }
        }
        if ((nullBits[0] & 0x40) != 0x0) {
            final int cloudsOffset = buffer.getIntLE(offset + 46);
            if (cloudsOffset < 0) {
                return ValidationResult.error("Invalid offset for Clouds");
            }
            int pos = offset + 126 + cloudsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Clouds");
            }
            final int cloudsCount = VarInt.peek(buffer, pos);
            if (cloudsCount < 0) {
                return ValidationResult.error("Invalid array count for Clouds");
            }
            if (cloudsCount > 4096000) {
                return ValidationResult.error("Clouds exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < cloudsCount; ++i) {
                final ValidationResult structResult = Cloud.validateStructure(buffer, pos);
                if (!structResult.isValid()) {
                    return ValidationResult.error("Invalid Cloud in Clouds[" + i + "]: " + structResult.error());
                }
                pos += Cloud.computeBytesConsumed(buffer, pos);
            }
        }
        if ((nullBits[0] & 0x80) != 0x0) {
            final int sunlightDampingMultiplierOffset = buffer.getIntLE(offset + 50);
            if (sunlightDampingMultiplierOffset < 0) {
                return ValidationResult.error("Invalid offset for SunlightDampingMultiplier");
            }
            int pos = offset + 126 + sunlightDampingMultiplierOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SunlightDampingMultiplier");
            }
            final int sunlightDampingMultiplierCount = VarInt.peek(buffer, pos);
            if (sunlightDampingMultiplierCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SunlightDampingMultiplier");
            }
            if (sunlightDampingMultiplierCount > 4096000) {
                return ValidationResult.error("SunlightDampingMultiplier exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < sunlightDampingMultiplierCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading value");
                }
            }
        }
        if ((nullBits[1] & 0x1) != 0x0) {
            final int sunlightColorsOffset = buffer.getIntLE(offset + 54);
            if (sunlightColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for SunlightColors");
            }
            int pos = offset + 126 + sunlightColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SunlightColors");
            }
            final int sunlightColorsCount = VarInt.peek(buffer, pos);
            if (sunlightColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SunlightColors");
            }
            if (sunlightColorsCount > 4096000) {
                return ValidationResult.error("SunlightColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < sunlightColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 3;
            }
        }
        if ((nullBits[1] & 0x2) != 0x0) {
            final int skyTopColorsOffset = buffer.getIntLE(offset + 58);
            if (skyTopColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for SkyTopColors");
            }
            int pos = offset + 126 + skyTopColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SkyTopColors");
            }
            final int skyTopColorsCount = VarInt.peek(buffer, pos);
            if (skyTopColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SkyTopColors");
            }
            if (skyTopColorsCount > 4096000) {
                return ValidationResult.error("SkyTopColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < skyTopColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
            }
        }
        if ((nullBits[1] & 0x4) != 0x0) {
            final int skyBottomColorsOffset = buffer.getIntLE(offset + 62);
            if (skyBottomColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for SkyBottomColors");
            }
            int pos = offset + 126 + skyBottomColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SkyBottomColors");
            }
            final int skyBottomColorsCount = VarInt.peek(buffer, pos);
            if (skyBottomColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SkyBottomColors");
            }
            if (skyBottomColorsCount > 4096000) {
                return ValidationResult.error("SkyBottomColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < skyBottomColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
            }
        }
        if ((nullBits[1] & 0x8) != 0x0) {
            final int skySunsetColorsOffset = buffer.getIntLE(offset + 66);
            if (skySunsetColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for SkySunsetColors");
            }
            int pos = offset + 126 + skySunsetColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SkySunsetColors");
            }
            final int skySunsetColorsCount = VarInt.peek(buffer, pos);
            if (skySunsetColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SkySunsetColors");
            }
            if (skySunsetColorsCount > 4096000) {
                return ValidationResult.error("SkySunsetColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < skySunsetColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
            }
        }
        if ((nullBits[1] & 0x10) != 0x0) {
            final int sunColorsOffset = buffer.getIntLE(offset + 70);
            if (sunColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for SunColors");
            }
            int pos = offset + 126 + sunColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SunColors");
            }
            final int sunColorsCount = VarInt.peek(buffer, pos);
            if (sunColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SunColors");
            }
            if (sunColorsCount > 4096000) {
                return ValidationResult.error("SunColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < sunColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 3;
            }
        }
        if ((nullBits[1] & 0x20) != 0x0) {
            final int sunScalesOffset = buffer.getIntLE(offset + 74);
            if (sunScalesOffset < 0) {
                return ValidationResult.error("Invalid offset for SunScales");
            }
            int pos = offset + 126 + sunScalesOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SunScales");
            }
            final int sunScalesCount = VarInt.peek(buffer, pos);
            if (sunScalesCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SunScales");
            }
            if (sunScalesCount > 4096000) {
                return ValidationResult.error("SunScales exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < sunScalesCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading value");
                }
            }
        }
        if ((nullBits[1] & 0x40) != 0x0) {
            final int sunGlowColorsOffset = buffer.getIntLE(offset + 78);
            if (sunGlowColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for SunGlowColors");
            }
            int pos = offset + 126 + sunGlowColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for SunGlowColors");
            }
            final int sunGlowColorsCount = VarInt.peek(buffer, pos);
            if (sunGlowColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for SunGlowColors");
            }
            if (sunGlowColorsCount > 4096000) {
                return ValidationResult.error("SunGlowColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < sunGlowColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
            }
        }
        if ((nullBits[1] & 0x80) != 0x0) {
            final int moonColorsOffset = buffer.getIntLE(offset + 82);
            if (moonColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for MoonColors");
            }
            int pos = offset + 126 + moonColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for MoonColors");
            }
            final int moonColorsCount = VarInt.peek(buffer, pos);
            if (moonColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for MoonColors");
            }
            if (moonColorsCount > 4096000) {
                return ValidationResult.error("MoonColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < moonColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
            }
        }
        if ((nullBits[2] & 0x1) != 0x0) {
            final int moonScalesOffset = buffer.getIntLE(offset + 86);
            if (moonScalesOffset < 0) {
                return ValidationResult.error("Invalid offset for MoonScales");
            }
            int pos = offset + 126 + moonScalesOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for MoonScales");
            }
            final int moonScalesCount = VarInt.peek(buffer, pos);
            if (moonScalesCount < 0) {
                return ValidationResult.error("Invalid dictionary count for MoonScales");
            }
            if (moonScalesCount > 4096000) {
                return ValidationResult.error("MoonScales exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < moonScalesCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading value");
                }
            }
        }
        if ((nullBits[2] & 0x2) != 0x0) {
            final int moonGlowColorsOffset = buffer.getIntLE(offset + 90);
            if (moonGlowColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for MoonGlowColors");
            }
            int pos = offset + 126 + moonGlowColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for MoonGlowColors");
            }
            final int moonGlowColorsCount = VarInt.peek(buffer, pos);
            if (moonGlowColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for MoonGlowColors");
            }
            if (moonGlowColorsCount > 4096000) {
                return ValidationResult.error("MoonGlowColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < moonGlowColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
            }
        }
        if ((nullBits[2] & 0x4) != 0x0) {
            final int fogColorsOffset = buffer.getIntLE(offset + 94);
            if (fogColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for FogColors");
            }
            int pos = offset + 126 + fogColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for FogColors");
            }
            final int fogColorsCount = VarInt.peek(buffer, pos);
            if (fogColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for FogColors");
            }
            if (fogColorsCount > 4096000) {
                return ValidationResult.error("FogColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < fogColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 3;
            }
        }
        if ((nullBits[2] & 0x8) != 0x0) {
            final int fogHeightFalloffsOffset = buffer.getIntLE(offset + 98);
            if (fogHeightFalloffsOffset < 0) {
                return ValidationResult.error("Invalid offset for FogHeightFalloffs");
            }
            int pos = offset + 126 + fogHeightFalloffsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for FogHeightFalloffs");
            }
            final int fogHeightFalloffsCount = VarInt.peek(buffer, pos);
            if (fogHeightFalloffsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for FogHeightFalloffs");
            }
            if (fogHeightFalloffsCount > 4096000) {
                return ValidationResult.error("FogHeightFalloffs exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < fogHeightFalloffsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading value");
                }
            }
        }
        if ((nullBits[2] & 0x10) != 0x0) {
            final int fogDensitiesOffset = buffer.getIntLE(offset + 102);
            if (fogDensitiesOffset < 0) {
                return ValidationResult.error("Invalid offset for FogDensities");
            }
            int pos = offset + 126 + fogDensitiesOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for FogDensities");
            }
            final int fogDensitiesCount = VarInt.peek(buffer, pos);
            if (fogDensitiesCount < 0) {
                return ValidationResult.error("Invalid dictionary count for FogDensities");
            }
            if (fogDensitiesCount > 4096000) {
                return ValidationResult.error("FogDensities exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < fogDensitiesCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading value");
                }
            }
        }
        if ((nullBits[2] & 0x20) != 0x0) {
            final int screenEffectOffset = buffer.getIntLE(offset + 106);
            if (screenEffectOffset < 0) {
                return ValidationResult.error("Invalid offset for ScreenEffect");
            }
            int pos = offset + 126 + screenEffectOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for ScreenEffect");
            }
            final int screenEffectLen = VarInt.peek(buffer, pos);
            if (screenEffectLen < 0) {
                return ValidationResult.error("Invalid string length for ScreenEffect");
            }
            if (screenEffectLen > 4096000) {
                return ValidationResult.error("ScreenEffect exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += screenEffectLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading ScreenEffect");
            }
        }
        if ((nullBits[2] & 0x40) != 0x0) {
            final int screenEffectColorsOffset = buffer.getIntLE(offset + 110);
            if (screenEffectColorsOffset < 0) {
                return ValidationResult.error("Invalid offset for ScreenEffectColors");
            }
            int pos = offset + 126 + screenEffectColorsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for ScreenEffectColors");
            }
            final int screenEffectColorsCount = VarInt.peek(buffer, pos);
            if (screenEffectColorsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for ScreenEffectColors");
            }
            if (screenEffectColorsCount > 4096000) {
                return ValidationResult.error("ScreenEffectColors exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < screenEffectColorsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 4;
            }
        }
        if ((nullBits[2] & 0x80) != 0x0) {
            final int colorFiltersOffset = buffer.getIntLE(offset + 114);
            if (colorFiltersOffset < 0) {
                return ValidationResult.error("Invalid offset for ColorFilters");
            }
            int pos = offset + 126 + colorFiltersOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for ColorFilters");
            }
            final int colorFiltersCount = VarInt.peek(buffer, pos);
            if (colorFiltersCount < 0) {
                return ValidationResult.error("Invalid dictionary count for ColorFilters");
            }
            if (colorFiltersCount > 4096000) {
                return ValidationResult.error("ColorFilters exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < colorFiltersCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 3;
            }
        }
        if ((nullBits[3] & 0x1) != 0x0) {
            final int waterTintsOffset = buffer.getIntLE(offset + 118);
            if (waterTintsOffset < 0) {
                return ValidationResult.error("Invalid offset for WaterTints");
            }
            int pos = offset + 126 + waterTintsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for WaterTints");
            }
            final int waterTintsCount = VarInt.peek(buffer, pos);
            if (waterTintsCount < 0) {
                return ValidationResult.error("Invalid dictionary count for WaterTints");
            }
            if (waterTintsCount > 4096000) {
                return ValidationResult.error("WaterTints exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            for (int i = 0; i < waterTintsCount; ++i) {
                pos += 4;
                if (pos > buffer.writerIndex()) {
                    return ValidationResult.error("Buffer overflow reading key");
                }
                pos += 3;
            }
        }
        if ((nullBits[3] & 0x2) != 0x0) {
            final int particleOffset = buffer.getIntLE(offset + 122);
            if (particleOffset < 0) {
                return ValidationResult.error("Invalid offset for Particle");
            }
            int pos = offset + 126 + particleOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Particle");
            }
            final ValidationResult particleResult = WeatherParticle.validateStructure(buffer, pos);
            if (!particleResult.isValid()) {
                return ValidationResult.error("Invalid Particle: " + particleResult.error());
            }
            pos += WeatherParticle.computeBytesConsumed(buffer, pos);
        }
        return ValidationResult.OK;
    }
    
    public Weather clone() {
        final Weather copy = new Weather();
        copy.id = this.id;
        copy.tagIndexes = (int[])((this.tagIndexes != null) ? Arrays.copyOf(this.tagIndexes, this.tagIndexes.length) : null);
        copy.stars = this.stars;
        copy.moons = ((this.moons != null) ? new HashMap<Integer, String>(this.moons) : null);
        Map.Entry<Float, Color> e = null;
        copy.clouds = (Cloud[])((this.clouds != null) ? ((Cloud[])Arrays.stream(this.clouds).map(e -> e.clone()).toArray(Cloud[]::new)) : null);
        copy.sunlightDampingMultiplier = ((this.sunlightDampingMultiplier != null) ? new HashMap<Float, Float>(this.sunlightDampingMultiplier) : null);
        if (this.sunlightColors != null) {
            final Map<Float, Color> m = new HashMap<Float, Color>();
            final Iterator<Map.Entry<Float, Color>> iterator = this.sunlightColors.entrySet().iterator();
            while (iterator.hasNext()) {
                e = iterator.next();
                m.put(e.getKey(), e.getValue().clone());
            }
            copy.sunlightColors = m;
        }
        if (this.skyTopColors != null) {
            final Map<Float, ColorAlpha> i = new HashMap<Float, ColorAlpha>();
            for (final Map.Entry<Float, ColorAlpha> e2 : this.skyTopColors.entrySet()) {
                i.put(e2.getKey(), e2.getValue().clone());
            }
            copy.skyTopColors = i;
        }
        if (this.skyBottomColors != null) {
            final Map<Float, ColorAlpha> i = new HashMap<Float, ColorAlpha>();
            for (final Map.Entry<Float, ColorAlpha> e2 : this.skyBottomColors.entrySet()) {
                i.put(e2.getKey(), e2.getValue().clone());
            }
            copy.skyBottomColors = i;
        }
        if (this.skySunsetColors != null) {
            final Map<Float, ColorAlpha> i = new HashMap<Float, ColorAlpha>();
            for (final Map.Entry<Float, ColorAlpha> e2 : this.skySunsetColors.entrySet()) {
                i.put(e2.getKey(), e2.getValue().clone());
            }
            copy.skySunsetColors = i;
        }
        if (this.sunColors != null) {
            final Map<Float, Color> m = new HashMap<Float, Color>();
            final Iterator<Map.Entry<Float, Color>> iterator5 = this.sunColors.entrySet().iterator();
            while (iterator5.hasNext()) {
                e = iterator5.next();
                m.put(e.getKey(), e.getValue().clone());
            }
            copy.sunColors = m;
        }
        copy.sunScales = ((this.sunScales != null) ? new HashMap<Float, Float>(this.sunScales) : null);
        if (this.sunGlowColors != null) {
            final Map<Float, ColorAlpha> i = new HashMap<Float, ColorAlpha>();
            for (final Map.Entry<Float, ColorAlpha> e2 : this.sunGlowColors.entrySet()) {
                i.put(e2.getKey(), e2.getValue().clone());
            }
            copy.sunGlowColors = i;
        }
        if (this.moonColors != null) {
            final Map<Float, ColorAlpha> i = new HashMap<Float, ColorAlpha>();
            for (final Map.Entry<Float, ColorAlpha> e2 : this.moonColors.entrySet()) {
                i.put(e2.getKey(), e2.getValue().clone());
            }
            copy.moonColors = i;
        }
        copy.moonScales = ((this.moonScales != null) ? new HashMap<Float, Float>(this.moonScales) : null);
        if (this.moonGlowColors != null) {
            final Map<Float, ColorAlpha> i = new HashMap<Float, ColorAlpha>();
            for (final Map.Entry<Float, ColorAlpha> e2 : this.moonGlowColors.entrySet()) {
                i.put(e2.getKey(), e2.getValue().clone());
            }
            copy.moonGlowColors = i;
        }
        if (this.fogColors != null) {
            final Map<Float, Color> m = new HashMap<Float, Color>();
            final Iterator<Map.Entry<Float, Color>> iterator9 = this.fogColors.entrySet().iterator();
            while (iterator9.hasNext()) {
                e = iterator9.next();
                m.put(e.getKey(), e.getValue().clone());
            }
            copy.fogColors = m;
        }
        copy.fogHeightFalloffs = ((this.fogHeightFalloffs != null) ? new HashMap<Float, Float>(this.fogHeightFalloffs) : null);
        copy.fogDensities = ((this.fogDensities != null) ? new HashMap<Float, Float>(this.fogDensities) : null);
        copy.screenEffect = this.screenEffect;
        if (this.screenEffectColors != null) {
            final Map<Float, ColorAlpha> i = new HashMap<Float, ColorAlpha>();
            for (final Map.Entry<Float, ColorAlpha> e2 : this.screenEffectColors.entrySet()) {
                i.put(e2.getKey(), e2.getValue().clone());
            }
            copy.screenEffectColors = i;
        }
        if (this.colorFilters != null) {
            final Map<Float, Color> m = new HashMap<Float, Color>();
            final Iterator<Map.Entry<Float, Color>> iterator11 = this.colorFilters.entrySet().iterator();
            while (iterator11.hasNext()) {
                e = iterator11.next();
                m.put(e.getKey(), e.getValue().clone());
            }
            copy.colorFilters = m;
        }
        if (this.waterTints != null) {
            final Map<Float, Color> m = new HashMap<Float, Color>();
            final Iterator<Map.Entry<Float, Color>> iterator12 = this.waterTints.entrySet().iterator();
            while (iterator12.hasNext()) {
                e = iterator12.next();
                m.put(e.getKey(), e.getValue().clone());
            }
            copy.waterTints = m;
        }
        copy.particle = ((this.particle != null) ? this.particle.clone() : null);
        copy.fog = ((this.fog != null) ? this.fog.clone() : null);
        copy.fogOptions = ((this.fogOptions != null) ? this.fogOptions.clone() : null);
        return copy;
    }
    
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof final Weather other) {
            return Objects.equals(this.id, other.id) && Arrays.equals(this.tagIndexes, other.tagIndexes) && Objects.equals(this.stars, other.stars) && Objects.equals(this.moons, other.moons) && Arrays.equals(this.clouds, other.clouds) && Objects.equals(this.sunlightDampingMultiplier, other.sunlightDampingMultiplier) && Objects.equals(this.sunlightColors, other.sunlightColors) && Objects.equals(this.skyTopColors, other.skyTopColors) && Objects.equals(this.skyBottomColors, other.skyBottomColors) && Objects.equals(this.skySunsetColors, other.skySunsetColors) && Objects.equals(this.sunColors, other.sunColors) && Objects.equals(this.sunScales, other.sunScales) && Objects.equals(this.sunGlowColors, other.sunGlowColors) && Objects.equals(this.moonColors, other.moonColors) && Objects.equals(this.moonScales, other.moonScales) && Objects.equals(this.moonGlowColors, other.moonGlowColors) && Objects.equals(this.fogColors, other.fogColors) && Objects.equals(this.fogHeightFalloffs, other.fogHeightFalloffs) && Objects.equals(this.fogDensities, other.fogDensities) && Objects.equals(this.screenEffect, other.screenEffect) && Objects.equals(this.screenEffectColors, other.screenEffectColors) && Objects.equals(this.colorFilters, other.colorFilters) && Objects.equals(this.waterTints, other.waterTints) && Objects.equals(this.particle, other.particle) && Objects.equals(this.fog, other.fog) && Objects.equals(this.fogOptions, other.fogOptions);
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        int result = 1;
        result = 31 * result + Objects.hashCode(this.id);
        result = 31 * result + Arrays.hashCode(this.tagIndexes);
        result = 31 * result + Objects.hashCode(this.stars);
        result = 31 * result + Objects.hashCode(this.moons);
        result = 31 * result + Arrays.hashCode(this.clouds);
        result = 31 * result + Objects.hashCode(this.sunlightDampingMultiplier);
        result = 31 * result + Objects.hashCode(this.sunlightColors);
        result = 31 * result + Objects.hashCode(this.skyTopColors);
        result = 31 * result + Objects.hashCode(this.skyBottomColors);
        result = 31 * result + Objects.hashCode(this.skySunsetColors);
        result = 31 * result + Objects.hashCode(this.sunColors);
        result = 31 * result + Objects.hashCode(this.sunScales);
        result = 31 * result + Objects.hashCode(this.sunGlowColors);
        result = 31 * result + Objects.hashCode(this.moonColors);
        result = 31 * result + Objects.hashCode(this.moonScales);
        result = 31 * result + Objects.hashCode(this.moonGlowColors);
        result = 31 * result + Objects.hashCode(this.fogColors);
        result = 31 * result + Objects.hashCode(this.fogHeightFalloffs);
        result = 31 * result + Objects.hashCode(this.fogDensities);
        result = 31 * result + Objects.hashCode(this.screenEffect);
        result = 31 * result + Objects.hashCode(this.screenEffectColors);
        result = 31 * result + Objects.hashCode(this.colorFilters);
        result = 31 * result + Objects.hashCode(this.waterTints);
        result = 31 * result + Objects.hashCode(this.particle);
        result = 31 * result + Objects.hashCode(this.fog);
        result = 31 * result + Objects.hashCode(this.fogOptions);
        return result;
    }
}
