package net.minecraft.world.level; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; import java.util.Optional; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.InclusiveRange; import net.minecraft.util.random.WeightedList; import net.minecraft.world.entity.EquipmentTable; public record SpawnData(CompoundTag entityToSpawn, Optional customSpawnRules, Optional equipment) { public static final String ENTITY_TAG = "entity"; public static final Codec CODEC = RecordCodecBuilder.create( p_327238_ -> p_327238_.group( CompoundTag.CODEC.fieldOf("entity").forGetter(p_186576_ -> p_186576_.entityToSpawn), SpawnData.CustomSpawnRules.CODEC.optionalFieldOf("custom_spawn_rules").forGetter(p_186569_ -> p_186569_.customSpawnRules), EquipmentTable.CODEC.optionalFieldOf("equipment").forGetter(p_327239_ -> p_327239_.equipment) ) .apply(p_327238_, SpawnData::new) ); public static final Codec> LIST_CODEC = WeightedList.codec(CODEC); public SpawnData() { this(new CompoundTag(), Optional.empty(), Optional.empty()); } public SpawnData(CompoundTag entityToSpawn, Optional customSpawnRules, Optional equipment) { Optional optional = entityToSpawn.read("id", ResourceLocation.CODEC); if (optional.isPresent()) { entityToSpawn.store("id", ResourceLocation.CODEC, optional.get()); } else { entityToSpawn.remove("id"); } this.entityToSpawn = entityToSpawn; this.customSpawnRules = customSpawnRules; this.equipment = equipment; } public CompoundTag getEntityToSpawn() { return this.entityToSpawn; } public Optional getCustomSpawnRules() { return this.customSpawnRules; } public Optional getEquipment() { return this.equipment; } public record CustomSpawnRules(InclusiveRange blockLightLimit, InclusiveRange skyLightLimit) { private static final InclusiveRange LIGHT_RANGE = new InclusiveRange<>(0, 15); public static final Codec CODEC = RecordCodecBuilder.create( p_286217_ -> p_286217_.group( lightLimit("block_light_limit").forGetter(p_186600_ -> p_186600_.blockLightLimit), lightLimit("sky_light_limit").forGetter(p_186595_ -> p_186595_.skyLightLimit) ) .apply(p_286217_, SpawnData.CustomSpawnRules::new) ); private static DataResult> checkLightBoundaries(InclusiveRange p_186593_) { return !LIGHT_RANGE.contains(p_186593_) ? DataResult.error(() -> "Light values must be withing range " + LIGHT_RANGE) : DataResult.success(p_186593_); } private static MapCodec> lightLimit(String p_286409_) { return InclusiveRange.INT.lenientOptionalFieldOf(p_286409_, LIGHT_RANGE).validate(SpawnData.CustomSpawnRules::checkLightBoundaries); } public boolean isValidPosition(BlockPos p_327859_, ServerLevel p_328424_) { return this.blockLightLimit.isValueInRange(p_328424_.getBrightness(LightLayer.BLOCK, p_327859_)) && this.skyLightLimit.isValueInRange(p_328424_.getBrightness(LightLayer.SKY, p_327859_)); } } }