Spawning a Custom Villager with a Command

Discussion in 'Plugin Development' started by LordVakar, Nov 16, 2013.

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

    LordVakar

    I'm trying to spawn a custom villager with a command but I don't know how to.
    How would you look at a block where you want the villager to spawn and then do the command /spawnvil and it will spawn a villager there?
    But then how would you make it so the villager doesn't move and people can't push the villager away from its spot? Does it require NMS code to set the villager's speed?
    And lastly, how would you save the villager's position and make sure the villager doesn't despawn or something so when you go back, the villager is still there?

    Thanks if you can help.
     
  2. Offline

    Windy Day

    https://forums.bukkit.org/threads/how-do-i-get-the-location-of-where-the-player-is-looking.50696/
    and
    Code:
                    Entity npc= somewhere.getBlock().getWorld().spawn(a location, Villager.class);
                    ((Villager)npc).addPotionEffect(new PotionEffect(PotionEffectType.Slowness, integer, 128));
                    ((Villager)npc.addPotionEffect(new PotionEffect(PotionEffectType.Jump, integer, 6)
    Giving an entity slowness 6 and jump 128 effectively makes them unable to walk and doesn't require you to make an event listening for all the entity movements. Also Integer.MAX_VALUE would probably be a good idea for setting the duration. I think that will set it to something like 3 years long real time. Which should do the trick.
     
    NathanWolf likes this.
  3. Offline

    LordVakar

    Windy Day
    What would you put for somewhere?
    My friend said for me to do:
    Block somewhere = getSelectedBlock(p);

    So now I have this:
    Code:java
    1. public static Block getSelectedBlock(Player p) {
    2. Block b = p.getTargetBlock(null, 200);
    3. return b;
    4. }
    5. @Override
    6. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
    7. if(cmd.getName().equalsIgnoreCase("GuideVil")){
    8. Player p = (Player) sender;
    9. Block somewhere = getSelectedBlock(p);
    10. Entity npc= somewhere.getWorld().spawn(somewhere.getLocation(), Villager.class);
    11. ((Villager)npc).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 10000, 128));
    12. ((Villager)npc).addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 100000, 6));
    13. }
    14. return false;
    15. }


    It wants me to swap null and 200 in:
    Block b = p.getTargetBlock(null, 200);

    Would that do anything?

    Windy Day
    Also, as I stated in the OP:
    How would you save the villager's position and make sure the villager doesn't despawn or something so when you go back, the villager is still there?
    Thanks if you can help

    Bump

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  4. Offline

    Windy Day

    Getting the target block works fine. You can just add this above the getSelectedBlock method to get rid of the yellow warning:
    @SuppressWarnings("deprecation")
    As far as making them not despawn. I'm not sure how the mob despawning mechanics work but if they despawn when the chunk they are on unloads. What you could do is create an listener listening for chunkunload event. Then use something like this:
    Code:
                for (Entity entity : chunk.getEntities()) {
                    if (entity instanceof LivingEntity == false || entity instanceof HumanEntity) {
                        continue;
                    }
                    if (entity instanceof Villager) {
                       //save location code
                    }
                }
    To get the villagers on that chunk. Then save their locations in a hashmap that stores the chunk and an array of the villagers locations. Then create another event listening for chunkloads and if that chunk is in the hashmap loop through the location array and spawn a villager at each locations reapplying the potion effects. Then remove the chunk from the hashmap. If that is not how despawning works. Then maybe schedule an event the respawns them every so often.
     
  5. Offline

    LordVakar

    Thanks for the help.
    One question though, how would I make sure the villager was the villager that was spawned by the command, not some natural spawning villager?
    Could I assign villagers like a custom id somehow? :confused:
    MEH I think the above was a stupid question I just realized something...
    ;3
    So uh, I have another question, wait a moment, I'll edit this post and put it in
     
  6. Offline

    Windy Day

    You can make a list of entities. Next when spawning them just add the villager to that list. Then you can just check if the list contains the entity when getting the entities on the chunk. Also after you make sure they are on the list and they despawn you can remove them. Then just add them back when you spawn them again. This would help keep the list small.
     
  7. Offline

    LordVakar

    By a list, like an arraylist?
    And what code would you do to add a villager to the list?
     
  8. Offline

    Windy Day

    Yes, you should be able to just save them like this:
    Code:
          public List<Entity> villagerlist;
    
    Then add them to the list with this:
    Code:
                villagerlist.add(event.getEntity());
    
    Then check if they are in the list with this:
    Code:
                if (villagerlist.contains(event.getEntity()) {
                    //save them
                }
     
  9. Offline

    LordVakar

    I'm getting an error that I don't know how to fix.
    There's no entity methods in ChunkUnloadEvent, so I don't know how to check if they're in the list.
    This is my code:
    Code:java
    1. @EventHandler
    2. public void onChunkUnload(ChunkUnloadEvent event)
    3. {
    4. Chunk chunk = event.getChunk();
    5. for (Entity entity : chunk.getEntities()) {
    6. if (entity instanceof LivingEntity == false || entity instanceof HumanEntity) {
    7. continue;
    8. }
    9. if (entity instanceof Villager) {
    10. if (villagerlist.contains(event.getEntity())) {
    11. //save them
    12. }
    13. }
    14. }
    15. }

    I'm getting an error on event.getEntity() because there are no getEntity methods in ChunkUnloadEvent. How woudl you fix this?
     
  10. Offline

    Windy Day

    You don't need to use event.getEntity(); because in the for statement we have initialized an Entity called entity:
    for(Entity entity : chunk.getEntities()){
    and then for every entity on the chunk we are calling it entity and we are executing the code within the for statement. So lets say you have a arrow, a zombie, and a villager on the chunk . Suddenly the chunk unloads and the event is triggered. You get the chunk and initialize it as Chunk chunk. Then for that chunk you get the arrow entity and call it Entity entity next we check if it is living. Nope it isn't. Move on the the zombie and call it Entity entity. Check if it is living. Yes. Ok, is it a villager? Nope, get the next entity... and so on. So to get the entity you are currently on just use entity.whatever.
     
  11. Offline

    NathanWolf

    If you name an entity, doesn't it not ever despawn? Just a thought.... sounds easier than tracking it yourself.
     
  12. Offline

    Windy Day

    I'm not sure. I know if you use a nametag item on it ingame, that it won't despawn. But I'm not sure if setting it's name with a plugin has the same effect. However, you are probably right and LordVakar should atleast check into this.
     
Thread Status:
Not open for further replies.

Share This Page