1.17.x How can I reduce spawns of a certain mob (eg. Creepers)?

Discussion in 'Spigot Plugin Development' started by Noni, Jun 13, 2021.

  1. I want to reduce the spawn rate of certain mobs (creepers and skeletons).

    I use the CreatueSpawnEvent and then check in a forach loop if the entity about to spawn is an instanceof any of the entities in my list. If yes, I generated a random number between 0 and 1 and if the number is bigger than 0.5, I cancel the event.
    This should reduce spawns of the mobs specified by 50%. And as far as I can tell it's working just fine.

    Is this the correct way or is there a better approach?
     
  2. Why are you running a foreach? Just check it like
    Code (Java):

    if (e.getEntityOrStuff() instanceof Skeleton || e.getEntityOrStuff() instanceof Creeper) {
        //do your thing
    }
     
     
  3. No, just check if your list contains the entity type (much more expandable if you want to add more entities). Even better use a Set (EnumSet is best if you store EntityTypes), as that has O(1) lookup time.
     
    • Like Like x 1
  4. Thanks alot for the replies! But would you say it is correct to use the CreatueSpawnEvent, or is there a better way?
    And will this approach cause issues if I would set it 0 (so all spawns of a certain type would get canceled)?

    The list is coming from a config file, I forgot to mention that. So yeah you're generally right but in my case I need to check a list :D

    You mean like this? (Please disregard the poor variable naming)
    Code (Java):

    EntityType entityType = e.getEntity().getType();
    List<EntityType> entities = new ArrayList<>();
    entities.add(EntityType.SKELETON);
    entities.add(EntityType.CREEPER);

    if(entities.contains(entityType)) {
        e.setCancelled(true);
    }
     
     
  5. Well the event is the correct place I think, unless you use Paper, which actually has a Pre-spawn event. And no, as I said, you should use an (Enum)Set not a list (contains is correct).. It also doesn’t make sense to create/populate this list each time the event is called, do so once in your class for example.
     
    • Like Like x 1
  6. You can change spawn rate in bukkit.yml
    Code (Text):
    settings:
    delay-chunk-unloads-by: 30s
    spawn-limits:
    monsters: 70
    animals: 10
    water-animals: 15
    water-ambient: 20
    ambient: 15
    chunk-gc:
    period-in-ticks: 600
     
    • Agree Agree x 1
    • Funny Funny x 1
  7. Good idea, I might check on plugin startup what server implementation is used and then either register the PreCreatureSpawnEvent or CreatureSpawnEvent. Thank you.

    The problem is that I might need both an EntityType and a float value that indicates the spawn rate multiplier (so basically HashMap<EntityType, Float>. Do you think it's more performant to use an Enum Set to quickly check whether the EntityType is in there at all and if that's true, look up the multiplier in a hashmap or shall I just check the hashmap immediately using containsKey() ?

    And yes, I will of course cache the hashmap / enum set.

    You either haven't read my post or copypasted incorrectly. I was unable to find a setting that works for my purpose in the yml config files.
     
    • Like Like x 1
  8. I've only given comments that can be edited in bukkit.yml as well.
     
  9. In thar case just use the hashmap. Its keys form a set anyway, so that has almost the same performance and is way simpler than separating the two.

    And ignore that guy, I don’t think he ever reads a single thread he posts on.
     
    • Agree Agree x 1
  10. EnumMap
     
    • Informative Informative x 1
    • Useful Useful x 1