Block as Entity-Target?

Discussion in 'Plugin Development' started by ServerfromMinecraft, Sep 14, 2012.

Thread Status:
Not open for further replies.
  1. Hi!

    how i can set a block as target for entitys? (like zombies..) So that the entitys move to the block :)

    And how i can aplly the EntityAIArrowAttack to a block?

    edit:Like the citizens "pathfinding" : The Player set a path, and the given entiys must follow the path from the debut to the end

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 28, 2016
  2. Anyone has a Idea :( ?
     
  3. Anyone :( ?

    Anyone? :(

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 28, 2016
  4. Hint: Search function for terms like mob ai, mob movement, ... we had many discusions about that some time ago, iirc some devs even wanted to write an API for that.
     
  5. Thanks :D ! Also with the PathObjet i can make that a entity walk along a path?
     
  6. I really don't know (yet). But atm I'm doing what you do: Collecting information. Then I'll try to write a quick&dirty API for that, let's see what we get from that. :)
     
  7. Ok ;) if i have more infos i say it here :)
     
  8. First test: Failed completely. Mobs spawn but you can click like crazy, they will ignore it. :(
    Code:java
    1. package de.V10lator.MobAPI;
    2.  
    3. import java.util.ArrayList;
    4.  
    5. import net.minecraft.server.EntityCreature;
    6. import net.minecraft.server.PathEntity;
    7.  
    8. import org.bukkit.Location;
    9. import org.bukkit.Material;
    10. import org.bukkit.block.Block;
    11. import org.bukkit.block.BlockFace;
    12. import org.bukkit.command.Command;
    13. import org.bukkit.command.CommandSender;
    14. import org.bukkit.craftbukkit.entity.CraftCreature;
    15. import org.bukkit.entity.Creature;
    16. import org.bukkit.entity.Entity;
    17. import org.bukkit.entity.EntityType;
    18. import org.bukkit.entity.Player;
    19. import org.bukkit.event.EventHandler;
    20. import org.bukkit.event.Listener;
    21. import org.bukkit.event.block.Action;
    22. import org.bukkit.event.player.PlayerInteractEvent;
    23. import org.bukkit.plugin.java.JavaPlugin;
    24.  
    25. public class MobAPI extends JavaPlugin implements Listener
    26. {
    27. private final ArrayList<Creature> entities = new ArrayList<Creature>();
    28.  
    29. public void moveMob(Creature mob, Location to, float speed)
    30. {
    31. System.out.print("Called!");
    32. EntityCreature notchMob = ((CraftCreature)mob).getHandle();
    33. PathEntity path = notchMob.world.a(notchMob, to.getBlockX(), to.getBlockY(), to.getBlockZ(), speed, true, false, false, true);
    34. notchMob.setPathEntity(path);
    35. }
    36.  
    37. @Override
    38. public void onEnable()
    39. {
    40. getServer().getPluginManager().registerEvents(this, this);
    41. }
    42.  
    43. @Override
    44. public boolean onCommand(CommandSender sender, Command command,
    45. String label, String[] args)
    46. {
    47. if(!(sender instanceof Player))
    48. return true;
    49. EntityType toSpawn;
    50. if(args.length < 1)
    51. toSpawn = EntityType.MUSHROOM_COW;
    52. else
    53. {
    54. if(args.length > 1)
    55. {
    56. StringBuilder sb = new StringBuilder(args[0]);
    57. for(int i = 1; i < args.length; i++)
    58. sb.append('_').append(args[i]);
    59. args[0] = sb.toString();
    60. }
    61. toSpawn = EntityType.fromName(args[0].toUpperCase());
    62. if(toSpawn == null)
    63. toSpawn = EntityType.COW;
    64. }
    65. Player p = (Player)sender;
    66. Block b = p.getTargetBlock(null, 100);
    67. if(b == null)
    68. {
    69. p.sendMessage("Don't look to far away!");
    70. return true;
    71. }
    72. while(b.getType() != Material.AIR)
    73. b = b.getRelative(BlockFace.UP);
    74. Entity spawned = p.getWorld().spawnEntity(b.getLocation(), toSpawn);
    75. if(!(spawned instanceof Creature))
    76. {
    77. p.sendMessage("Can't control that!");
    78. return true;
    79. }
    80. entities.add((Creature)spawned);
    81. return true;
    82. }
    83.  
    84. @EventHandler
    85. public void click(PlayerInteractEvent event)
    86. {
    87. if(event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR)
    88. return;
    89.  
    90. Block b = event.getPlayer().getTargetBlock(null, 100);
    91. if(b == null)
    92. {
    93. event.getPlayer().sendMessage("Don't look to far away!");
    94. return;
    95. }
    96. while(b.getType() != Material.AIR)
    97. b = b.getRelative(BlockFace.UP);
    98. Location to = b.getLocation();
    99.  
    100. for(Creature c: entities)
    101. moveMob(c, to, 0.3F);
    102. }
    103. }[/i]
     
  9. Hm, the Metohd "a" in world is this:
    Code:
    public PathEntity a(Entity entity, int i, int j, int k, float f, boolean flag, boolean flag1, boolean flag2, boolean flag3) {this.methodProfiler.a("pathfind");int l = MathHelper.floor(entity.locX);int i1 = MathHelper.floor(entity.locY);int j1 = MathHelper.floor(entity.locZ);int k1 = (int) (f + 8.0F);int l1 = l - k1;int i2 = i1 - k1;int j2 = j1 - k1;int k2 = l + k1;int l2 = i1 + k1;int i3 = j1 + k1;ChunkCache chunkcache = new ChunkCache(this, l1, i2, j2, k2, l2, i3);PathEntity pathentity = (new Pathfinder(chunkcache, flag, flag1, flag2, flag3)).a(entity, i, j, k, f);this.methodProfiler.b();return pathentity;}
    
    The 3 booleans, flag1,2,3 - for what is it?
    Sorry for my bad englisch :(
     
  10. If this information is up2date the first decides if a entity can open (or destroy?) wooden doors. The next one decides if the movement can be stopped, the next one if he can swim (?) and the next one if he can breath underwater.
    This may not be 100% correct, but something similar. ^^

    NP, where are you from?

    //EDIT: BTW: I also tried to rise the float (not sure if it's really speed) to 10.0F - no difference. :( But maybe CorrieKay knows what's wrong?
     
  11. Ah, ok, thanks :D !

    From German :)

    Hm.. But the given things are just the location, the entity, and this booleans - where are given all the path-points?
     
  12. Immer diese Deutschen überall... :p
    (Always that germans everywhere...)

    Maybe nisovin could help, too. He tells that the PathEntity is deprecated, but I see it everywhere in the AI: https://github.com/Bukkit/CraftBukk.../net/minecraft/server/EntityCreature.java#L23 and afaik be() isn't overwritten from higher implementions.

    Off topic: What the... ? https://github.com/Bukkit/mc-dev/blob/master/net/minecraft/server/IAnimal.java I want to know what that I* files are for... (see this thread if interested, too).

    //EDIT: ARRGH: https://github.com/Bukkit/CraftBukk.../net/minecraft/server/EntityLiving.java#L1089 - The good thing is that the API seems to be switchable, the bad thing is that we used the old one. :(

    Sorry for double post, but: WORKS!

    The new API also allows the use of PathEntities, so for the lazyness I just feed both with it:
    Code:java
    1. package de.V10lator.MobAPI;
    2.  
    3. import java.util.HashSet;
    4. import java.util.UUID;
    5.  
    6. import net.minecraft.server.EntityCreature;
    7. import net.minecraft.server.PathEntity;
    8.  
    9. import org.bukkit.Location;
    10. import org.bukkit.Material;
    11. import org.bukkit.block.Block;
    12. import org.bukkit.block.BlockFace;
    13. import org.bukkit.command.Command;
    14. import org.bukkit.command.CommandSender;
    15. import org.bukkit.craftbukkit.entity.CraftCreature;
    16. import org.bukkit.entity.Creature;
    17. import org.bukkit.entity.Entity;
    18. import org.bukkit.entity.EntityType;
    19. import org.bukkit.entity.Player;
    20. import org.bukkit.event.EventHandler;
    21. import org.bukkit.event.Listener;
    22. import org.bukkit.event.block.Action;
    23. import org.bukkit.event.entity.EntityTargetEvent;
    24. import org.bukkit.event.player.PlayerInteractEvent;
    25. import org.bukkit.plugin.java.JavaPlugin;
    26.  
    27. public class MobAPI extends JavaPlugin implements Listener
    28. {
    29. private final HashSet<UUID> entities = new HashSet<UUID>();
    30.  
    31. public void moveMob(Creature mob, Location to, float speed)
    32. {
    33. EntityCreature notchMob = ((CraftCreature)mob).getHandle();
    34. PathEntity path = notchMob.world.a(notchMob, to.getBlockX(), to.getBlockY(), to.getBlockZ(), 100.0F, true, false, false, true);
    35. notchMob.setPathEntity(path);
    36. notchMob.getNavigation().a(path, speed);
    37. }
    38.  
    39. @Override
    40. public void onEnable()
    41. {
    42. getServer().getPluginManager().registerEvents(this, this);
    43. }
    44.  
    45. @Override
    46. public boolean onCommand(CommandSender sender, Command command,
    47. String label, String[] args)
    48. {
    49. if(!(sender instanceof Player))
    50. return true;
    51. EntityType toSpawn;
    52. if(args.length < 1)
    53. toSpawn = EntityType.MUSHROOM_COW;
    54. else
    55. {
    56. if(args.length > 1)
    57. {
    58. StringBuilder sb = new StringBuilder(args[0]);
    59. for(int i = 1; i < args.length; i++)
    60. sb.append('_').append(args[i]);
    61. args[0] = sb.toString();
    62. }
    63. toSpawn = EntityType.fromName(args[0].toUpperCase());
    64. if(toSpawn == null)
    65. toSpawn = EntityType.COW;
    66. }
    67. Player p = (Player)sender;
    68. Block b = p.getTargetBlock(null, 100);
    69. if(b == null)
    70. {
    71. p.sendMessage("Don't look to far away!");
    72. return true;
    73. }
    74. while(b.getType() != Material.AIR)
    75. b = b.getRelative(BlockFace.UP);
    76. Entity spawned = p.getWorld().spawnEntity(b.getLocation(), toSpawn);
    77. if(!(spawned instanceof Creature))
    78. {
    79. p.sendMessage("Can't control that!");
    80. return true;
    81. }
    82. entities.add(spawned.getUniqueId());
    83. return true;
    84. }
    85.  
    86. @EventHandler(ignoreCancelled = false)
    87. public void click(PlayerInteractEvent event)
    88. {
    89. if(event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR)
    90. return;
    91.  
    92. Block b = event.getPlayer().getTargetBlock(null, 100);
    93. if(b == null)
    94. {
    95. event.getPlayer().sendMessage("Don't look to far away!");
    96. return;
    97. }
    98. while(b.getType() != Material.AIR)
    99. b = b.getRelative(BlockFace.UP);
    100. Location to = b.getLocation();
    101.  
    102. for(Entity e: to.getWorld().getEntities())
    103. if(entities.contains(e.getUniqueId()))
    104. moveMob((Creature)e, to, 0.3F);
    105. }
    106.  
    107. @EventHandler
    108. public void noTarget(EntityTargetEvent event)
    109. {
    110. if(entities.contains(event.getEntity().getUniqueId()))
    111. event.setCancelled(true);
    112. }
    113. }[/i]


    I'm still unsure what the floats are for and this is not meand to just copy&paste (will have side effects)
    //EDIT: Codes changed a bit. now the speed really is the speed. The 100.0F is the max. distance. :)


    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 28, 2016
  13. Wow :awesome:

    But, why, in your onCommand you not use a command.getName().equalsignorcase("thecommand") ?
    And can you explain your code please :eek: ?
    (If possible also in german :D ? )

    edit: I understand it :D ! thanks :D !
     
  14. I don't use it cause there's just one command registered in the plugin.yml, so it will always be the command I expect it to be.

    Good that you understand it. I could explain/comment it but if you still got it... :)
     
  15. Hm, another thing: I would that the entity go from path to path, registered in a arraylist - for that i have make a hasReach method and a for-loop, but its have a problem.

    The hasReach

    Code:
    public boolean hasReach(Entity e, Location end){
    boolean b;
    if(e.getLocation().distance(end) < 0.7){
    b = true;
    }else{
    b = false;
    }
    return b;
    }
    
    and the for loop:
    Code:
    for(int i = 0; i < pathlength; i++){
    if(hasReach(z, path.get(i))){
    moveMob(z, path.get(i), 0.3F);
    }
    }
    Problem: In my for loop, is check if the entity has reach the path, and then its remove on the same path - but how i can make that its move on the next path?
     
  16. First off I would set the old location again if the entity hasn't reached the end of that path, cause I saw some lines in NMS code which may remove your PathEntity randomly without informing you.
    Other than that you can't use a for loop, use the bukkit scheduler instead and check around every 10 ticks. Also you could use an array containing all the paths, like this:
    Code:java
    1. public class YourRunnable implements Runnable
    2. {
    3. private final Creature c;
    4. private final Location[] pathPoints;
    5. private final int step = 0;
    6.  
    7. public YourRunnable(Creature c, Location[] pathPoints)
    8. {
    9. this.c = c;
    10. this.pathPoints = pathPoints;
    11. }
    12.  
    13. public void run()
    14. {
    15. if(c.getLocation().distance(pathPoints[step]) < 0.7)
    16. {
    17. step++;
    18. if(step >= pathPoints.length)
    19. {
    20. //End goal reached! Do something to kill the task here!
    21. return;
    22. }
    23. }
    24. moveMob(c, pathPoints[step], 0.3F);
    25. }
    26. }

    For more informations about the scheduler and what to do with this (well, not this, again not meaned to be copy&pasted, contains bad coding) Runnable have a look here: http://wiki.bukkit.org/Scheduler_Programming ( http://wiki.bukkit.org/Scheduler_Programming/de ).
     
  17. Ah yes, thanks :D But why you use not just:

    getServer().getSheduler().sheduleAsyncRepeatingTask(this, new Runnable(){public void run(){the code }}, a Long);

    ?
     
  18. Cause first of Async is bad (may be threadsafe here, to lazy to check atm, but normally you always have to think "it isn't" till you know otherwise.
    Then: If you use new Runnable(){public void run(){the code }} or write the class in a extra file doesn't make a real difference. The first one is a new subclass, the second one a new class... ;) The second call would look like this:
    getServer().getSheduler().sheduleSyncRepeatingTask(this, new YourRunnable(c, pathPoints), a Long); - Personally I like the second more cause, well, I can read it better and I find it easier to give variables through a constructor than declaring them final (I learned it that way).

    //EDIT: Fun fact: Did you ever use:
    getServer().getPluginManager().registerEvents(this, new Listener(){the code});
    ? No? Why not? :p
     
  19. To your edit: Yes, i use that :p

    Code:
    getServer().getPluginManager().registerEvents(new thelistenr(this), this);
    And my constructor is EVER so:
    Code:
    nameofthemainclass main;
    public Tnameofthelistener(nameofthemainclass main) {
    this.main = main;
    }
     
  20. ServerfromMinecraft No, you don't use it. You use
    Code:java
    1. getServer().getPluginManager().registerEvents(new thelistenr(), this);

    and then a new class:
    Code:java
    1. public class thelistenr implements Listener
    2. {
    3. @EventHandler
    4. public void bla(ExampleEvent event)
    5. {
    6. event.Yay();
    7. }
    8. }

    But I asked you why you don't use a subclass instead:
    Code:java
    1. getServer().getPluginManager().registerEvents(new Listener(){
    2. @EventHandler
    3. public void bla(ExampleEvent event)
    4. {
    5. event.Yay();
    6. }
    7. }, this);


    Which is exactly the same question as yours:
    Why do I use
    Code:java
    1. getServer().getScheduler().scheduler*ync*Task(this, new therunnable(), this);

    and then a new class:
    Code:java
    1. public class therunnable implements Runnable
    2. {
    3. public void run()
    4. {
    5. Yay();
    6. }
    7. }

    instead of using a subclass instead:
    Code:java
    1. getServer().getScheduler().scheduler*ync*Task(this, new Runnable(){
    2. {
    3. public void run()
    4. {
    5. Yay();
    6. }
    7. }, this);


    ... merkst was? ;)
     
  21. Ach mist xD

    Yes.. But i found its easer to make a subclass with the sheduler, and a new class with the listener (and commandexecutor).. but i dont kno wwhy xD
    edit: one problem, why that give me ever time "0" ?

    Code:
    public void run() {
    int step = 0;
    if(hasReach(z, path.get(step)))
          {
    System.out.println(step);
              step++;
              if(step >= path.size())
              {
                    return;
              }
          }
    moveMob(z, path.get(step), 0.3F);
    
    }
    and the entity move to the position one, then to two, then to one, etc..

    V10lator
    edit: its ecause step is defined in the sheduler, oder? But i not woud have step final..
    edit: i have let work it :) No problem anymor :) / Hasb geaschafft
     
  22. ServerfromMinecraft it was because it was in the run() method. In my example above it was a global variable in the runnable which should work. But you still got it. Do you use a new class or a subclass now?
     
  23. I use subclass and class - from time to time subclass, from time to time class.
     
  24. I meaned at that specific Runnable... ;)
     
  25. Offline

    Cybran

Thread Status:
Not open for further replies.

Share This Page