package net.minecraft.world.effect; import com.google.common.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; import java.util.function.ToIntFunction; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.monster.Slime; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; class OozingMobEffect extends MobEffect { private static final int RADIUS_TO_CHECK_SLIMES = 2; public static final int SLIME_SIZE = 2; private final ToIntFunction spawnedCount; protected OozingMobEffect(MobEffectCategory category, int color, ToIntFunction spawnedCount) { super(category, color, ParticleTypes.ITEM_SLIME); this.spawnedCount = spawnedCount; } @VisibleForTesting protected static int numberOfSlimesToSpawn(int maxEntityCramming, OozingMobEffect.NearbySlimes nearbySlimes, int spawnCount) { return maxEntityCramming < 1 ? spawnCount : Mth.clamp(0, maxEntityCramming - nearbySlimes.count(maxEntityCramming), spawnCount); } @Override public void onMobRemoved(ServerLevel level, LivingEntity entity, int amplifier, Entity.RemovalReason reason) { if (reason == Entity.RemovalReason.KILLED) { int i = this.spawnedCount.applyAsInt(entity.getRandom()); int j = level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); int k = numberOfSlimesToSpawn(j, OozingMobEffect.NearbySlimes.closeTo(entity), i); for (int l = 0; l < k; l++) { this.spawnSlimeOffspring(entity.level(), entity.getX(), entity.getY() + 0.5, entity.getZ()); } } } private void spawnSlimeOffspring(Level level, double x, double y, double z) { Slime slime = EntityType.SLIME.create(level, EntitySpawnReason.TRIGGERED); if (slime != null) { slime.setSize(2, true); slime.snapTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F); level.addFreshEntity(slime); } } @FunctionalInterface protected interface NearbySlimes { int count(int i); static OozingMobEffect.NearbySlimes closeTo(LivingEntity entity) { return i -> { List list = new ArrayList(); entity.level().getEntities(EntityType.SLIME, entity.getBoundingBox().inflate(2.0), slime -> slime != entity, list, i); return list.size(); }; } } }