How should I go about doing this

Discussion in 'Plugin Development' started by Scullyking, Apr 17, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    Scullyking

    I'm building a plugin that has multiple mob regions. These regions defined an area of the world in which a certain mob is spawned.

    I would like to maintain a steady number of mobs within a region. Say I always want about 6 chickens in a chicken coop region I have defined.

    The question is how should I go about maintaining this number. Should each region have a repeating task that counts how many are in the region and spawns more if needed. Or should I have just one repeating task that governs all regions and counts all regions to spawn more if needed. Or is there an even better way of doing this?


    I'm open to suggestions,
    Thanks
     
  2. Offline

    mine-care

    @Scullyking or you should check per region each time EntitySpawnEvent is called instead of the task :3
     
  3. Offline

    Scullyking

    @mine-care
    All entities are spawned by code (not naturally), so EntitySpawnEvent isn't telling me anything new.
     
  4. Offline

    mine-care

    What you mean "Not naturally" if you use World#spanwEntity(params) the event will be fired. (This method actually ends up calling addEntity(params) method from nms class World)
    Here is the addEntity method:
    Code:
    /*  872:     */   public boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason)
    /*  873:     */   {
    /*  874: 872 */     if (entity == null) {
    /*  875: 872 */       return false;
    /*  876:     */     }
    /*  877: 875 */     int i = MathHelper.floor(entity.locX / 16.0D);
    /*  878: 876 */     int j = MathHelper.floor(entity.locZ / 16.0D);
    /*  879: 877 */     boolean flag = entity.n;
    /*  880: 879 */     if ((entity instanceof EntityHuman)) {
    /*  881: 880 */       flag = true;
    /*  882:     */     }
    /*  883: 884 */     Cancellable event = null;
    /*  884: 885 */     if (((entity instanceof EntityLiving)) && (!(entity instanceof EntityPlayer)))
    /*  885:     */     {
    /*  886: 886 */       boolean isAnimal = ((entity instanceof EntityAnimal)) || ((entity instanceof EntityWaterAnimal)) || ((entity instanceof EntityGolem));
    /*  887: 887 */       boolean isMonster = ((entity instanceof EntityMonster)) || ((entity instanceof EntityGhast)) || ((entity instanceof EntitySlime));
    /*  888: 889 */       if ((spawnReason != CreatureSpawnEvent.SpawnReason.CUSTOM) && (
    /*  889: 890 */         ((isAnimal) && (!this.allowAnimals)) || ((isMonster) && (!this.allowMonsters))))
    /*  890:     */       {
    /*  891: 891 */         entity.dead = true;
    /*  892: 892 */         return false;
    /*  893:     */       }
    /*  894: 896 */       event = CraftEventFactory.callCreatureSpawnEvent((EntityLiving)entity, spawnReason);
    /*  895:     */     }
    /*  896: 897 */     else if ((entity instanceof EntityItem))
    /*  897:     */     {
    /*  898: 898 */       event = CraftEventFactory.callItemSpawnEvent((EntityItem)entity);
    /*  899:     */     }
    /*  900: 899 */     else if ((entity.getBukkitEntity() instanceof Projectile))
    /*  901:     */     {
    /*  902: 901 */       event = CraftEventFactory.callProjectileLaunchEvent(entity);
    /*  903:     */     }
    /*  904: 904 */     if ((event != null) && ((event.isCancelled()) || (entity.dead)))
    /*  905:     */     {
    /*  906: 905 */       entity.dead = true;
    /*  907: 906 */       return false;
    /*  908:     */     }
    /*  909: 910 */     if ((!flag) && (!isChunkLoaded(i, j)))
    /*  910:     */     {
    /*  911: 911 */       entity.dead = true;
    /*  912: 912 */       return false;
    /*  913:     */     }
    /*  914: 914 */     if ((entity instanceof EntityHuman))
    /*  915:     */     {
    /*  916: 915 */       EntityHuman entityhuman = (EntityHuman)entity;
    /*  917:     */     
    /*  918: 917 */       this.players.add(entityhuman);
    /*  919: 918 */       everyoneSleeping();
    /*  920:     */     }
    /*  921: 921 */     getChunkAt(i, j).a(entity);
    /*  922: 922 */     this.entityList.add(entity);
    /*  923: 923 */     a(entity);
    /*  924: 924 */     return true;
    /*  925:     */   }
    Check out line 23
    so yes it is called :3
     
  5. Offline

    Scullyking

    @mine-care
    I know it's called. But since every mob in the world will be spawned through my plugin, an EntitySpawnEvent isn't telling me anything I didn't already know.

    I'm looking for a solution to maintaining steady levels of mobs within my regions. At the moment a repeating task looks like the best option.
     
  6. Offline

    mine-care

    @Scullyking Hmm, i still think it would work if you cancel it when the mob spawned is in the region where enough mobs already exist but... its just me. :- )
     
  7. Offline

    Scullyking

    @mine-care
    The regions are small compared to the entire world. The odds of a random spawn occurring in the region are tiny (given that some of these regions will be fully lit up). So I need to manually sort out the spawning in order to get the density (and type of mob) I want.
     
  8. Offline

    mine-care

    @Scullyking oh i thought you handle all mob spawns so thats why i sugested it but now it is clearly inefficient to call all those checks every time an entity spawns. the repeating task sounds better now.
    But i sugest you ask someone more experienced than me :p i am not the efficiency lord.
     
  9. Offline

    Scullyking

    @mine-care
    Thank you for trying to help, seems this isn't something many people know about!
     
  10. Offline

    1Rogue

    Listen to EntitySpawnEvent, and flag the "region" they are in via a mapping. From there monitor their current regions in move events, and have a sentinel thread that monitors the entity concencration and adjusts accordingly.
     
  11. Offline

    Scullyking

    The majority of entity spawn events wouldn't be in regions though. A region could be a chicken farm, which would always need say 10 chickens. It seems like natural entity spawning is inefficient because I would be cancelling 90% of the spawns. Entity spawn event doesn't naturally spawn my custom mobs either because I have so many I'm not overwriting default minecraft ones.

    I honestly think some kind of region manager that periodically spawns new mobs in each region would be much better.
     
  12. Offline

    1Rogue

    Or, y'know, you can just have something check through any regions at the given location, and then determine if it's applicable (assuming multiple regions can be in each location).
     
  13. Offline

    Scullyking

    @1Rogue
    Thanks. I've actually changed it to use the EntityDeathEvent to determine if, when and where new mobs within regions should spawn. It's working very well so far. The hardest part for me is going to be creating custom PathfinderGoals for the mobs to keep them from leaving the regions they spawn in. At the moment I'm fencing in the mobs to keep them from wondering away, any tips?
     
    Last edited: Apr 19, 2015
  14. Offline

    1Rogue

    instead of disallowing them to wander, just manage wandering like you would death. Keep the spawn amount up (or down) based on movement within reginos. Some flexibility is fine, you can go a little over or under the goal for the sake of easier management (e.g. have a minimum of 5 but a maximum of 15, so essentially a goal of 10 and a flexibility of 5)

    You can dynamically determine that amount as well based on the number of blocks in a region
     
    Scullyking likes this.
  15. Offline

    Scullyking

    @1Rogue
    So you're saying kill mobs that move too far from the region? That definitely seems easier, I'll give it a go. Since there's no EntityMoveEvent, how do I implement this? A repeating task that checks all mobs in the world? That seems like it would lag up the server.
     
    Last edited: Apr 20, 2015
  16. Offline

    1Rogue

    You can do it in a different thread as well, assuming you lock/clone any collections you use appropriately
     
  17. Offline

    Scullyking

    @1Rogue
    Just built it, works well but my checking if a mob is in a region is a bit iffy, will fix later.

    Do you happen to know if there is a PathFinderGoal that I need to remove/change so that when I attack a mob (such as a Zombie), other Zombies don't attack. In other words if there are three zombies chilling, and I punch one, I only want that one to get angry.

    Here is my custom zombie code.
     
Thread Status:
Not open for further replies.

Share This Page