public void setMobLimit(final int initialLimit, final int addPerPlayer, final int largestLimit) { this.mobLimit = world -> Math.min( largestLimit, initialLimit + EntitySelector.players(world, area.toAABB()).size() * addPerPlayer); }
@Override public void tick(World world, NBTCompound nbt) { if (++tickLimiter > tickRate) { tickLimiter = 0; List<EntityLiving> mobs = EntitySelector.mobs(world, area.toAABB()); if (mobs.size() >= mobLimit.applyAsInt(world)) return; final Map<Class<? extends EntityLiving>, Integer> mobCounts = new HashMap<>(4); final boolean isPeaceful = world.difficultySetting == EnumDifficulty.PEACEFUL; for (int attempt = 0; attempt < attemptsPerTick; attempt++) { final SpawnEntry<? extends EntityLiving> entry = spawnEntries.getRandomItem(world.rand); final Class<? extends EntityLiving> mobClass = entry.getMobClass(); if (!isPeaceful || !entry.isHostile) { int limit = mobClassLimit.get(mobClass); if (limit == 0 || mobCounts.computeIfAbsent( mobClass, cls -> (int) mobs.stream().filter(entity -> entity.getClass() == mobClass).count()) < limit) { entry.trySpawn(world, attemptsPerMob); } } } } }
/** * Checks whether the area between two points is inside the structure and does not intersect any * existing pieces. */ protected boolean canPlaceArea(Pos pos1, Pos pos2) { final BoundingBox box = new BoundingBox(pos1, pos2); return box.isInside(dungeon.boundingBox) && !generated.stream().anyMatch(inst -> inst.boundingBox.intersects(box)); }