Tutorial - How to Customize the Behaviour of a Mob or Entity

Discussion in 'Resources' started by Jacek, Jan 13, 2012.

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

    Elimnator

    Jacek
    I am trying to follow your tutorial and I am doing everything it said to do, but it is not working.

    What am I doing wrong:
    Code:java
    1. public class trampling_creeper extends net.minecraft.server.v1_6_R2.EntityCreeper {
    2.  
    3. public trampling_creeper(World world) {
    4. super(world);
    5. }
    6.  
    7. @Override
    8. public void s_(){
    9. Creeper creeper = (Creeper) this.getBukkitEntity();
    10.  
    11. Location from = new Location(creeper.getWorld(), this.lastX, this.lastY, this.lastZ, this.lastYaw, this.lastPitch);
    12. Location to = new Location(creeper.getWorld(), this.locX, this.locY, this.locZ, this.yaw, this.pitch);
    13.  
    14. CreeperMoveEvent event = new CreeperMoveEvent(creeper, from, to);
    15.  
    16. this.world.getServer().getPluginManager().callEvent(event);
    17.  
    18. if (event.isCancelled() && creeper.isDead() == false){
    19. return;
    20. }
    21.  
    22. super.s_();
    23. }
    24. }
     
  2. Offline

    Cybermaxke

    Elimnator the s_() method is changed to l_() in the latest version.
     
  3. Offline

    Jacek

    Elimnator Copying the code is not the same as doing what is says.
     
  4. Offline

    Elimnator

  5. Offline

    Jacek

    Something that's been answered before.
     
  6. Offline

    bobacadodl

    Jacek
    How would I go about modifying a Mob's spawn rate? Or creating custom spawn conditions? I want sheep to be able to spawn naturally on any block
     
  7. Offline

    Jacek

    bobacadodl No idea, you'd have to work it out from the source like I did for the things I do know how to do.
     
  8. Offline

    bobacadodl

    Hm, anyways, I just cancelled all spawn events and wrote my own spawning algorithm. Its was inconvenient, and is probably less efficient/more laggy than minecraft's spawning algorithm, but whatever :/
     
  9. Offline

    Cybermaxke

    bobacadodl
    You can change the spawn rate of existing spawns and adding your own ones to any biome, here is the code I used: link
     
    bobacadodl likes this.
  10. Offline

    TomFromCollege

  11. Offline

    Jacek

    TomFromCollege It's bad to always cancel the event since the server tries to spawn the entity again on the next tick so you end up with a lot of even spam, in the set up here you actually do spawn the entity so the server won't call the event again on the next tick so it's not so bad. With that said I did realise you can do this without the entity replace thing which will help with performance a bit, not that it's that bad anyway, need to update the post.
     
  12. Offline

    slasheh

    How would I give potion effects to the custom entity?
     
  13. Offline

    xxNightlordx

    Just wondering, is this tutorial outdated? I seem to be getting errors :( even though I've been following the code on page 1
     
  14. Offline

    Jacek

    xxNightlordx Read, understand, implement. Don't just copy.
     
    mollekake likes this.
  15. Offline

    xxNightlordx

    I do not understand the methods at all. What does the method "a" do in
    Code:java
    1. @Override
    2. public void a(EntityLiving entityliving, float f){
    3. for (int i = 0; i < 2; ++i){
    4. super.a(entityliving, f);
    5. }
    6. }
     
  16. Offline

    RingOfStorms

    That's the point of obfuscation, you're not supposed to understand. You have to follow and read the code to understand it by yourself. There won't be pretty labels on everything for you like the bukkit API.
     
  17. Offline

    mcat95

    Is possible to do this with a MinecartRideable??. I've seen that MinecartRideable don't extend EntityInsentient
     
  18. Offline

    Rockon999

    Jacek
    Okay... so I got everything working almost. I'm trying to make undead horses behave like zombies, and when I try to add an if statement to the class checking the type I get a NullPointerException, and when I don't do the if statement only normal horses become like zombies... any ideas?
    Horse Class:
    Code:java
    1. package oh.custommobs;
    2. import java.lang.reflect.Field;
    3. import java.util.List;
    4.  
    5. import net.minecraft.server.v1_6_R2.DamageSource;
    6. import net.minecraft.server.v1_6_R2.Entity;
    7. import net.minecraft.server.v1_6_R2.EntityHorse;
    8. import net.minecraft.server.v1_6_R2.EntityHuman;
    9. import net.minecraft.server.v1_6_R2.GenericAttributes;
    10. import net.minecraft.server.v1_6_R2.Item;
    11. import net.minecraft.server.v1_6_R2.PathfinderGoalBreed;
    12. import net.minecraft.server.v1_6_R2.PathfinderGoalFloat;
    13. import net.minecraft.server.v1_6_R2.PathfinderGoalFollowParent;
    14. import net.minecraft.server.v1_6_R2.PathfinderGoalHurtByTarget;
    15. import net.minecraft.server.v1_6_R2.PathfinderGoalLookAtPlayer;
    16. import net.minecraft.server.v1_6_R2.PathfinderGoalMeleeAttack;
    17. import net.minecraft.server.v1_6_R2.PathfinderGoalNearestAttackableTarget;
    18. import net.minecraft.server.v1_6_R2.PathfinderGoalPanic;
    19. import net.minecraft.server.v1_6_R2.PathfinderGoalRandomLookaround;
    20. import net.minecraft.server.v1_6_R2.PathfinderGoalRandomStroll;
    21. import net.minecraft.server.v1_6_R2.PathfinderGoalSelector;
    22. import net.minecraft.server.v1_6_R2.PathfinderGoalTame;
    23. import net.minecraft.server.v1_6_R2.PathfinderGoalTempt;
    24. import net.minecraft.server.v1_6_R2.World;
    25.  
    26. public class Horse extends EntityHorse {
    27. @SuppressWarnings("rawtypes")
    28. public Horse(World world) {
    29. super(world);
    30. try {
    31. Field field = PathfinderGoalSelector.class.getDeclaredField("a");
    32. field.setAccessible(true);
    33. ((List) field.get(this.goalSelector)).clear();
    34. ((List) field.get(this.targetSelector)).clear();
    35. if (this.getType() > 2) {
    36. this.goalSelector.a(0, new PathfinderGoalFloat(this));
    37. this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, EntityHuman.class, 1.0D, false));
    38. this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D));
    39. this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, Item.SEEDS.id, false));
    40. this.goalSelector.a(4, new PathfinderGoalFollowParent(this, 1.1D));
    41. this.goalSelector.a(5, new PathfinderGoalRandomStroll(this, 1.0D));
    42. this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
    43. this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this));
    44. this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
    45. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true));
    46. } else {
    47. this.goalSelector.a(0, new PathfinderGoalFloat(this));
    48. this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.2D));
    49. this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D));
    50. this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D));
    51. this.goalSelector.a(4, new PathfinderGoalFollowParent(this, 1.0D));
    52. this.goalSelector.a(6, new PathfinderGoalRandomStroll(this, 0.7D));
    53. this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
    54. this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
    55. }
    56. } catch (Exception e) {
    57. e.printStackTrace();
    58. }
    59. }
    60.  
    61. public void ay() {
    62. if (getType() > 2) {
    63. super.ay();
    64. aW().b(GenericAttributes.e);
    65. getAttributeInstance(GenericAttributes.a).setValue(6.0D);
    66. getAttributeInstance(GenericAttributes.b).setValue(24.0D);
    67. getAttributeInstance(GenericAttributes.d).setValue(0.7D);
    68. getAttributeInstance(GenericAttributes.e).setValue(2.0D);
    69. } else {
    70. }
    71. }
    72.  
    73. public boolean m(Entity entity) {
    74. if (getType() > 2)
    75. return entity.damageEntity(DamageSource.mobAttack(this), (float) getAttributeInstance(GenericAttributes.e).getValue());
    76. return false;
    77. }
    78. }
    79.  

    Register Class:
    Code:java
    1. package oh.me;
    2.  
    3. import java.lang.reflect.Field;
    4. import java.lang.reflect.InvocationTargetException;
    5. import java.lang.reflect.Method;
    6. import java.util.List;
    7.  
    8. import net.minecraft.server.v1_6_R2.BiomeBase;
    9. import net.minecraft.server.v1_6_R2.BiomeMeta;
    10. import net.minecraft.server.v1_6_R2.EntityInsentient;
    11. import net.minecraft.server.v1_6_R2.EntityTypes;
    12.  
    13. import org.bukkit.entity.EntityType;
    14.  
    15. public enum Register {
    16.  
    17. HORSE("Horse", 100, EntityType.HORSE, net.minecraft.server.v1_6_R2.EntityHorse.class, oh.custommobs.Horse.class);
    18.  
    19. private String name;
    20. private int id;
    21. private EntityType entityType;
    22. private Class<? extends EntityInsentient> nmsClass;
    23. private Class<? extends EntityInsentient> customClass;
    24.  
    25. private Register(String name, int id, EntityType entityType, Class<? extends EntityInsentient> nmsClass, Class<? extends EntityInsentient> customClass) {
    26. this.name = name;
    27. this.id = id;
    28. this.entityType = entityType;
    29. this.nmsClass = nmsClass;
    30. this.customClass = customClass;
    31. }
    32.  
    33. for (Register entity : values()) {
    34. Method a = EntityTypes.class.getDeclaredMethod("a", new Class<?>[] { Class.class, String.class, int.class });
    35. a.setAccessible(true);
    36. a.invoke(null, entity.getCustomClass(), entity.getName(), entity.getID());
    37. }
    38.  
    39. for (BiomeBase biomeBase : BiomeBase.biomes) {
    40. if (biomeBase == null) {
    41. break;
    42. }
    43.  
    44. for (String field : new String[] { "K", "J", "L", "M" }) {
    45.  
    46. Field list = BiomeBase.class.getDeclaredField(field);
    47. list.setAccessible(true);
    48. @SuppressWarnings("unchecked")
    49. List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
    50. for (BiomeMeta meta : mobList) {
    51. for (Register entity : values()) {
    52. if (entity.getNMSClass().equals(meta.b)) {
    53. meta.b = entity.getCustomClass();
    54. }
    55. }
    56. }
    57.  
    58. }
    59. }
    60.  
    61. }
    62.  
    63. public String getName() {
    64. return this.name;
    65. }
    66.  
    67. public int getID() {
    68. return this.id;
    69. }
    70.  
    71. public EntityType getEntityType() {
    72. return this.entityType;
    73. }
    74.  
    75. public Class<? extends EntityInsentient> getNMSClass() {
    76. return this.nmsClass;
    77. }
    78.  
    79. public Class<? extends EntityInsentient> getCustomClass() {
    80. return this.customClass;
    81. }
    82.  
    83. }
    84.  

    Nice Exception (line is the super(world)):
    Code:
    01:24:45 [SEVERE] java.lang.reflect.InvocationTargetException
    01:24:45 [SEVERE]    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    01:24:45 [SEVERE]    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    01:24:45 [SEVERE]    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    01:24:45 [SEVERE]    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.EntityTypes.a(SourceFile:159)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.ItemMonsterEgg.a(ItemMonsterEgg.java:102)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.ItemMonsterEgg.interactWith(ItemMonsterEgg.java:37)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.ItemStack.placeItem(ItemStack.java:79)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.PlayerInteractManager.interact(PlayerInteractManager.java:390)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.PlayerConnection.a(PlayerConnection.java:628)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.Packet15Place.handle(SourceFile:58)
    01:24:45 [SEVERE]    at org.spigotmc.netty.NettyNetworkManager.b(NettyNetworkManager.java:230)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.PlayerConnection.e(PlayerConnection.java:116)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.ServerConnection.b(SourceFile:37)
    01:24:45 [SEVERE]    at org.spigotmc.netty.NettyServerConnection.b(NettyServerConnection.java:125)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.MinecraftServer.t(MinecraftServer.java:592)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.DedicatedServer.t(DedicatedServer.java:239)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.MinecraftServer.s(MinecraftServer.java:481)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.MinecraftServer.run(MinecraftServer.java:413)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.ThreadServerApplication.run(SourceFile:582)
    01:24:45 [SEVERE] Caused by: java.lang.NullPointerException
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.EntityLiving.<init>(EntityLiving.java:93)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.EntityInsentient.<init>(EntityInsentient.java:38)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.EntityCreature.<init>(EntityCreature.java:24)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.EntityAgeable.<init>(EntityAgeable.java:35)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.EntityAnimal.<init>(SourceFile:21)
    01:24:45 [SEVERE]    at net.minecraft.server.v1_6_R2.EntityHorse.<init>(EntityHorse.java:45)
    01:24:45 [SEVERE]    at oh.custommobs.Horse.<init>(Horse.java:39)
    01:24:45 [SEVERE]    ... 20 more
    01:24:45 [WARNING] Skipping Entity with id 100
    
     
  19. Offline

    Jacek

    Rockon999 Is this.targetSelector a PathfinderGoalSelector ? If not you are doing reflection wrong.
     
  20. Offline

    Rockon999

    Jacek
    I'm just trying to only override/make undead horses hostile... any ideas?
     
  21. Offline

    Jacek

    Yeah, try doing the reflection properly :p You can't use the same Field for multiple classes.
     
  22. Offline

    HelGod

    Jacek
    It it possible to "convert" a custom entity to a normal entity/living entity so I can change the name of my custom entity?
     
  23. Offline

    artish1

    @Jacek

    It looks like you've edited the last time i've seen this thread.
    Before you edited it i believe there was something saying about how to Spawn the entity. Now there's nothing here that says anything about it and now i'm not sure even how to put my entity into the server.
     
  24. Offline

    elraro

    Thx for this tuto!

    But i have a question, how can i set custom Max health?
     
  25. Offline

    elraro

    /bump my question
     
  26. Offline

    RingOfStorms

  27. Offline

    elraro

    i tried this code somedays ago and doesnt work:

    Multiple markers at this line
    - Cannot override the final method from EntityLiving
    - overrides net.minecraft.server.v1_6_R3.EntityLiving.getMaxHealth
     
  28. Offline

    RingOfStorms

    Ah derp it is final, well the original shows something about it's attributes, so maybe you can edit that to change it's max health.
     
  29. Offline

    MrOAriO

    My Problem, i created a Slime and want that the Slime didnt Attack any Players, but it dont work.
    Whats my mistake ?
    Error :
    Code:
    2013-10-23 15:38:50 [SEVERE] Caused by: java.lang.ClassCastException: me.oario.aPet.entitys.CustomEntitySlime cannot be cast to net.minecraft.server.v1_6_R2.EntityCreature
    
    Code:
    Code:java
    1. public class CustomEntitySlime extends net.minecraft.server.v1_6_R2.EntitySlime {
    2.  
    3. public CustomEntitySlime(World world) {
    4. super(world);
    5.  
    6. try {
    7.  
    8. java.lang.reflect.Field gsa = net.minecraft.server.v1_6_R2.PathfinderGoalSelector.class.getDeclaredField("a");
    9. ((AccessibleObject) gsa).setAccessible(true);
    10.  
    11.  
    12. gsa.set(this.goalSelector, new UnsafeList());
    13. gsa.set(this.targetSelector, new UnsafeList());
    14. }
    15. net.minecraft.server.v1_6_R2.Entity et = ((CraftEntity) this.getEntity()).getHandle();
    16. this.goalSelector.a(2, new PathfinderGoalMeleeAttack((EntityCreature) et, EntityHuman.class, (double) 0.0, false));
    17. this.targetSelector.a(1, new PathfinderGoalHurtByTarget((EntityCreature) et, false));
    18. }
    19. public Entity getEntity() {
    20. Slime Slime = (Slime) this.getBukkitEntity();
    21. return Slime;
    22. }
    23. }
     
  30. Offline

    RingOfStorms

    Slimes, as well as many other entities, don't use path finder goals. about half of all the mobs have custom pathing code within their class. This includes their targeting most of the time. This is one of the big reasons why there is no real support for adding a pathfinder API, and why it is so annoying to work with what we like to call "Mojang code, or Notch code". It is just overall annoying and a pain to deal with.
     
    CoderMusgrove likes this.
Thread Status:
Not open for further replies.

Share This Page