Newer
Older
void-pack-super-server / work / nms.old.1585251758016 / minecraft / server / SpawnerCreature.java
package net.minecraft.server;

import java.util.List;
import java.util.Objects;
import java.util.Random;
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

// CraftBukkit start
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
// CraftBukkit end

public final class SpawnerCreature {

    private static final Logger LOGGER = LogManager.getLogger();

    public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, BlockPosition blockposition) {
        ChunkGenerator<?> chunkgenerator = worldserver.getChunkProvider().getChunkGenerator();
        int i = 0;
        BlockPosition blockposition1 = getRandomPosition(worldserver, chunk);
        int j = blockposition1.getX();
        int k = blockposition1.getY();
        int l = blockposition1.getZ();

        if (k >= 1) {
            IBlockData iblockdata = chunk.getType(blockposition1);

            if (!iblockdata.isOccluding(chunk, blockposition1)) {
                BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
                int i1 = 0;

                while (i1 < 3) {
                    int j1 = j;
                    int k1 = l;
                    boolean flag = true;
                    BiomeBase.BiomeMeta biomebase_biomemeta = null;
                    GroupDataEntity groupdataentity = null;
                    int l1 = MathHelper.f(Math.random() * 4.0D);
                    int i2 = 0;
                    int j2 = 0;

                    while (true) {
                        if (j2 < l1) {
                            label104:
                            {
                                j1 += worldserver.random.nextInt(6) - worldserver.random.nextInt(6);
                                k1 += worldserver.random.nextInt(6) - worldserver.random.nextInt(6);
                                blockposition_mutableblockposition.d(j1, k, k1);
                                float f = (float) j1 + 0.5F;
                                float f1 = (float) k1 + 0.5F;
                                EntityHuman entityhuman = worldserver.a((double) f, (double) f1, -1.0D);

                                if (entityhuman != null) {
                                    double d0 = entityhuman.g((double) f, (double) k, (double) f1);

                                    if (d0 > 576.0D && !blockposition.a((IPosition) (new Vec3D((double) f, (double) k, (double) f1)), 24.0D)) {
                                        ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(blockposition_mutableblockposition);

                                        if (Objects.equals(chunkcoordintpair, chunk.getPos()) || worldserver.getChunkProvider().a(chunkcoordintpair)) {
                                            if (biomebase_biomemeta == null) {
                                                biomebase_biomemeta = a(chunkgenerator, enumcreaturetype, worldserver.random, (BlockPosition) blockposition_mutableblockposition);
                                                if (biomebase_biomemeta == null) {
                                                    break label104;
                                                }

                                                l1 = biomebase_biomemeta.c + worldserver.random.nextInt(1 + biomebase_biomemeta.d - biomebase_biomemeta.c);
                                            }

                                            if (biomebase_biomemeta.b.e() != EnumCreatureType.MISC && (biomebase_biomemeta.b.d() || d0 <= 16384.0D)) {
                                                EntityTypes<?> entitytypes = biomebase_biomemeta.b;

                                                if (entitytypes.b() && a(chunkgenerator, enumcreaturetype, biomebase_biomemeta, (BlockPosition) blockposition_mutableblockposition)) {
                                                    EntityPositionTypes.Surface entitypositiontypes_surface = EntityPositionTypes.a(entitytypes);

                                                    if (a(entitypositiontypes_surface, (IWorldReader) worldserver, (BlockPosition) blockposition_mutableblockposition, entitytypes) && EntityPositionTypes.a(entitytypes, worldserver, EnumMobSpawn.NATURAL, blockposition_mutableblockposition, worldserver.random) && worldserver.a(entitytypes.a((double) f, (double) k, (double) f1))) {
                                                        EntityInsentient entityinsentient;

                                                        try {
                                                            Entity entity = entitytypes.a((World) worldserver);

                                                            if (!(entity instanceof EntityInsentient)) {
                                                                throw new IllegalStateException("Trying to spawn a non-mob: " + IRegistry.ENTITY_TYPE.getKey(entitytypes));
                                                            }

                                                            entityinsentient = (EntityInsentient) entity;
                                                        } catch (Exception exception) {
                                                            SpawnerCreature.LOGGER.warn("Failed to create mob", exception);
                                                            return;
                                                        }

                                                        entityinsentient.setPositionRotation((double) f, (double) k, (double) f1, worldserver.random.nextFloat() * 360.0F, 0.0F);
                                                        if ((d0 <= 16384.0D || !entityinsentient.isTypeNotPersistent(d0)) && entityinsentient.a((GeneratorAccess) worldserver, EnumMobSpawn.NATURAL) && entityinsentient.a((IWorldReader) worldserver)) {
                                                            groupdataentity = entityinsentient.prepare(worldserver, worldserver.getDamageScaler(new BlockPosition(entityinsentient)), EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null);
                                                            // CraftBukkit start
                                                            if (worldserver.addEntity(entityinsentient, SpawnReason.NATURAL)) {
                                                                ++i;
                                                                ++i2;
                                                            }
                                                            // CraftBukkit end
                                                            if (i >= entityinsentient.getMaxSpawnGroup()) {
                                                                return;
                                                            }

                                                            if (entityinsentient.c(i2)) {
                                                                break label104;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }

                                ++j2;
                                continue;
                            }
                        }

                        ++i1;
                        break;
                    }
                }

            }
        }
    }

    @Nullable
    private static BiomeBase.BiomeMeta a(ChunkGenerator<?> chunkgenerator, EnumCreatureType enumcreaturetype, Random random, BlockPosition blockposition) {
        List<BiomeBase.BiomeMeta> list = chunkgenerator.getMobsFor(enumcreaturetype, blockposition);

        return list.isEmpty() ? null : (BiomeBase.BiomeMeta) WeightedRandom.a(random, list);
    }

    private static boolean a(ChunkGenerator<?> chunkgenerator, EnumCreatureType enumcreaturetype, BiomeBase.BiomeMeta biomebase_biomemeta, BlockPosition blockposition) {
        List<BiomeBase.BiomeMeta> list = chunkgenerator.getMobsFor(enumcreaturetype, blockposition);

        return list.isEmpty() ? false : list.contains(biomebase_biomemeta);
    }

    private static BlockPosition getRandomPosition(World world, Chunk chunk) {
        ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
        int i = chunkcoordintpair.d() + world.random.nextInt(16);
        int j = chunkcoordintpair.e() + world.random.nextInt(16);
        int k = chunk.a(HeightMap.Type.WORLD_SURFACE, i, j) + 1;
        int l = world.random.nextInt(k + 1);

        return new BlockPosition(i, l, j);
    }

    public static boolean a(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid) {
        return iblockdata.p(iblockaccess, blockposition) ? false : (iblockdata.isPowerSource() ? false : (!fluid.isEmpty() ? false : !iblockdata.a(TagsBlock.RAILS)));
    }

    public static boolean a(EntityPositionTypes.Surface entitypositiontypes_surface, IWorldReader iworldreader, BlockPosition blockposition, @Nullable EntityTypes<?> entitytypes) {
        if (entitypositiontypes_surface == EntityPositionTypes.Surface.NO_RESTRICTIONS) {
            return true;
        } else if (entitytypes != null && iworldreader.getWorldBorder().a(blockposition)) {
            IBlockData iblockdata = iworldreader.getType(blockposition);
            Fluid fluid = iworldreader.getFluid(blockposition);
            BlockPosition blockposition1 = blockposition.up();
            BlockPosition blockposition2 = blockposition.down();

            switch (entitypositiontypes_surface) {
                case IN_WATER:
                    return fluid.a(TagsFluid.WATER) && iworldreader.getFluid(blockposition2).a(TagsFluid.WATER) && !iworldreader.getType(blockposition1).isOccluding(iworldreader, blockposition1);
                case ON_GROUND:
                default:
                    IBlockData iblockdata1 = iworldreader.getType(blockposition2);

                    return !iblockdata1.a((IBlockAccess) iworldreader, blockposition2, entitytypes) ? false : a((IBlockAccess) iworldreader, blockposition, iblockdata, fluid) && a((IBlockAccess) iworldreader, blockposition1, iworldreader.getType(blockposition1), iworldreader.getFluid(blockposition1));
            }
        } else {
            return false;
        }
    }

    public static void a(GeneratorAccess generatoraccess, BiomeBase biomebase, int i, int j, Random random) {
        List<BiomeBase.BiomeMeta> list = biomebase.getMobs(EnumCreatureType.CREATURE);

        if (!list.isEmpty()) {
            int k = i << 4;
            int l = j << 4;

            while (random.nextFloat() < biomebase.f()) {
                BiomeBase.BiomeMeta biomebase_biomemeta = (BiomeBase.BiomeMeta) WeightedRandom.a(random, list);
                int i1 = biomebase_biomemeta.c + random.nextInt(1 + biomebase_biomemeta.d - biomebase_biomemeta.c);
                GroupDataEntity groupdataentity = null;
                int j1 = k + random.nextInt(16);
                int k1 = l + random.nextInt(16);
                int l1 = j1;
                int i2 = k1;

                for (int j2 = 0; j2 < i1; ++j2) {
                    boolean flag = false;

                    for (int k2 = 0; !flag && k2 < 4; ++k2) {
                        BlockPosition blockposition = a(generatoraccess, biomebase_biomemeta.b, j1, k1);

                        if (biomebase_biomemeta.b.b() && a(EntityPositionTypes.Surface.ON_GROUND, (IWorldReader) generatoraccess, blockposition, biomebase_biomemeta.b)) {
                            float f = biomebase_biomemeta.b.i();
                            double d0 = MathHelper.a((double) j1, (double) k + (double) f, (double) k + 16.0D - (double) f);
                            double d1 = MathHelper.a((double) k1, (double) l + (double) f, (double) l + 16.0D - (double) f);

                            if (!generatoraccess.a(biomebase_biomemeta.b.a(d0, (double) blockposition.getY(), d1)) || !EntityPositionTypes.a(biomebase_biomemeta.b, generatoraccess, EnumMobSpawn.CHUNK_GENERATION, new BlockPosition(d0, (double) blockposition.getY(), d1), generatoraccess.getRandom())) {
                                continue;
                            }

                            Entity entity;

                            try {
                                entity = biomebase_biomemeta.b.a(generatoraccess.getMinecraftWorld());
                            } catch (Exception exception) {
                                SpawnerCreature.LOGGER.warn("Failed to create mob", exception);
                                continue;
                            }

                            entity.setPositionRotation(d0, (double) blockposition.getY(), d1, random.nextFloat() * 360.0F, 0.0F);
                            if (entity instanceof EntityInsentient) {
                                EntityInsentient entityinsentient = (EntityInsentient) entity;

                                if (entityinsentient.a(generatoraccess, EnumMobSpawn.CHUNK_GENERATION) && entityinsentient.a((IWorldReader) generatoraccess)) {
                                    groupdataentity = entityinsentient.prepare(generatoraccess, generatoraccess.getDamageScaler(new BlockPosition(entityinsentient)), EnumMobSpawn.CHUNK_GENERATION, groupdataentity, (NBTTagCompound) null);
                                    generatoraccess.addEntity(entityinsentient, SpawnReason.CHUNK_GEN); // CraftBukkit
                                    flag = true;
                                }
                            }
                        }

                        j1 += random.nextInt(5) - random.nextInt(5);

                        for (k1 += random.nextInt(5) - random.nextInt(5); j1 < k || j1 >= k + 16 || k1 < l || k1 >= l + 16; k1 = i2 + random.nextInt(5) - random.nextInt(5)) {
                            j1 = l1 + random.nextInt(5) - random.nextInt(5);
                        }
                    }
                }
            }

        }
    }

    private static BlockPosition a(IWorldReader iworldreader, @Nullable EntityTypes<?> entitytypes, int i, int j) {
        BlockPosition blockposition = new BlockPosition(i, iworldreader.a(EntityPositionTypes.b(entitytypes), i, j), j);
        BlockPosition blockposition1 = blockposition.down();

        return iworldreader.getType(blockposition1).a((IBlockAccess) iworldreader, blockposition1, PathMode.LAND) ? blockposition1 : blockposition;
    }
}