NMS How to override default Minecraft mobs

Discussion in 'Resources' started by TeeePeee, Jan 6, 2014.

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

    TeeePeee

    marwzoor
    Hmm, I've never personally overridden a spider so I'm not sure exactly but I'll look into it when I get a chance for you.
    bennie3211
    Minecraft itself has a nearly identical method called getNearbyVulnerablePlayer (or similar). It's called every game tick until the mob has acquired a target. It doesn't cause any lag though, as Minecraft stores the online players in a list style, it doesn't nee to make any extraneous calls to acquire a new player object for each player each time.
     
    bennie3211 likes this.
  2. Offline

    Jalau

    What does this little piece do?
    this.bc().b(bp).setValue(this.random.nextDouble() * 0.10000000149011612D);
     
  3. Offline

    bennie3211

    Me 2 :) And I´ve an error, it gives me a InvocationTargetException and says the attribute is already registered, But i did what you said in the tutorial :s
     
  4. Offline

    TeeePeee

    this.bc().b(YOUR ATTRIBUTE) will fix this issue. Just insert it before the part where you register the attribute.
     
  5. Offline

    tylersyme

    On the subject of unregistering attributes, I did as you said and made sure that I used the code you wanted me to use. But, I'm still getting the same error everyone else is getting
    This is my code

    Code:java
    1. @Override
    2. protected void aD() {
    3.  
    4. super.aD();
    5.  
    6. this.bc().b(GenericAttributes.b);
    7. this.getAttributeInstance(GenericAttributes.b).setValue(40.0D);
    8. this.bc().b(GenericAttributes.d);
    9. this.getAttributeInstance(GenericAttributes.d).setValue(0.23000000417232513D);
    10. this.bc().b(GenericAttributes.e);
    11. this.getAttributeInstance(GenericAttributes.e).setValue(3.0D);
    12.  
    13. this.bc().b(bp).setValue(this.random.nextDouble() * 0.10000000149011612D);
    14. }


    I get and error at "this.bc().b(GenericAttributes.b);", which is the first time I attempt to unregister that attribute
    Am I being an idiot about something or what? Thanks for listening :D
     
  6. Offline

    TeeePeee

    tylersyme
    If the attribute isn't already registered, I believe bc().b will throw an error. Additionally note that the call to super.aD() will run the method from the superclass. Since this happens, you don't need to call the attributes you haven't changed - only the ones you have. Only include in your aD method the call to super and any attributes that are unique to your custom mob.
     
  7. Offline

    bobnixon1

    How do I only override CERTAIN entities?
     
  8. Offline

    SourceForums

    bobnixon1
    Have a look at the code again. It definitely tells you.
     
    Garris0n likes this.
  9. Offline

    Garris0n

    That's literally what the tutorial teaches you to do...
     
  10. Offline

    SourceForums

  11. Offline

    bobnixon1

    no no no, i want to override only certain zombie, not all of them.
     
  12. Offline

    Garris0n

    This simply creates a new zombie type, only spawn this zombie if you only want to override this zombie.
     
  13. Offline

    bobnixon1

    oh, then how do I only override certain zombies?
     
  14. Offline

    Garris0n

    Spawn normal zombies for normal zombies and spawn custom zombies for custom zombies.
     
  15. Offline

    bobnixon1

    But when I used the method from the tutorial, exported the plugin and reloaded, all of the zombies were attacking skeletons. I didn't do anything to spawn custom zombies, but maybe the CustomEntityType.registerEntities() method did.
     
  16. Offline

    SourceForums

    bobnixon1
    Well, you can use creature spawn event, etc. to control that I think.
     
  17. Offline

    Garris0n

    I went poking around in the server code.
    https://gist.github.com/Garris0n-/8691314

    I also noticed DSH105 only appears to use 'd' and 'f' in EchoPet, perhaps he could elaborate on his findings.
     
  18. Offline

    DSH105 Retired Staff

    It keeps the original Minecraft entity stored in the EntityTypes hashmaps so that normal mobs spawned don't become pets. I'm assuming that this tutorial provides a way to replace the original mobs, not keep them alongside (maybe TeeePeee could confirm this).
     
  19. Offline

    Garris0n

    Alright, it seems I was correct then. Thanks :)

    bobnixon1 So only use the d and f values when registering and it won't override Minecraft's mobs, though you will have to spawn them manually.
     
  20. Offline

    bobnixon1

    ok, thanks. would I use only d and f for entering parameters in the enum, because the registerEntities method has no parameters.
     
  21. Offline

    TeeePeee

    That is correct. Although normal mobs can still be spawned in via. creating the normal entity and spawning it with NMS.
     
    DSH105 likes this.
  22. Offline

    iiHeroo

    I don't get this :p



    Although, is it possible for it not to spawn naturally and only via the code?

    My custom attributes seem to not be working, I'm putting

    this.bc().b(GenericAttributes.b);
    this.bc().b(GenericAttributes.d);

    But still doesn't work, here's my full class

    Code:java
    1. package org.horrgs.projone.util;
    2.  
    3. import net.minecraft.server.v1_7_R1.*;
    4. import org.bukkit.craftbukkit.v1_7_R1.util.UnsafeList;
    5. import org.horrgs.projone.tasks.Round;
    6.  
    7. import java.lang.reflect.Field;
    8.  
    9. /**
    10. * Created by Horrgs on 1/31/14.
    11. */
    12.  
    13. public class CustomEntityZombie extends EntityZombie {
    14.  
    15.  
    16. public CustomEntityZombie(World world) {
    17. super(world);
    18.  
    19. try {
    20. Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
    21. bField.setAccessible(true);
    22. Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
    23. cField.setAccessible(true);
    24. bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    25. bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    26. cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    27. cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    28. } catch (Exception e) {
    29. e.printStackTrace();
    30. }
    31.  
    32. this.goalSelector.a(0, new PathfinderGoalFloat(this));
    33. this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityHuman.class, 1.0D, false));
    34. this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, true));
    35. this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
    36. this.goalSelector.a(6, new PathfinderGoalMoveThroughVillage(this, 1.0D, false));
    37. this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D));
    38. this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
    39. this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
    40. this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
    41. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true));
    42. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, 0, false));
    43. }
    44.  
    45.  
    46.  
    47. @Override
    48. protected void aD() {
    49. this.bc().b(GenericAttributes.b);
    50. this.bc().b(GenericAttributes.d);
    51. super.aD();
    52. this.getAttributeInstance(GenericAttributes.b).setValue(400.0D); // Original 3.0D
    53. getAttributeInstance(GenericAttributes.d).setValue(Round.roundNumber + .5);
    54. }
    55. }
    56.  



    TeeePeee
     
  23. Offline

    TeeePeee

    iiHeroo
    Sorry for the late reply. I'll assume you've already figured out the BiomeBase is what overrides the default Minecraft spawns with custom ones, so I'll skip over to your second question about the GenericAttributes.
    Instead of what you have (see below)
    Code:java
    1. this.bc().b(GenericAttributes.b);
    2. this.bc().b(GenericAttributes.d);
    3. super.aD();

    Try this
    Code:java
    1. super.aD();
    2. this.bc().b(GenericAttributes.b);
    3. this.bc().b(GenericAttributes.d);

    The call to super.aD() registers all the default attributes for the mob, so before that, clearing the attribute won't do anything (as it won't be set yet).
     
  24. Offline

    iiHeroo


    Did as you said, got a stack trace same as you said before here
    If I'm correct, so here's the stacktrace

    Code:
    [23:43:23] [Server thread/WARN]: Caused by: java.lang.IllegalArgumentException: Attribute is already registered!
    [23:43:23] [Server thread/WARN]:    at net.minecraft.server.v1_7_R1.AttributeMapServer.b(SourceFile:28)
    [23:43:23] [Server thread/WARN]:    at org.horrgs.projone.util.CustomEntityZombie.aD(CustomEntityZombie.java:50)
    [23:43:23] [Server thread/WARN]:    at net.minecraft.server.v1_7_R1.EntityLiving.<init>(EntityLiving.java:84)
    [23:43:23] [Server thread/WARN]:    at net.minecraft.server.v1_7_R1.EntityInsentient.<init>(EntityInsentient.java:38)
    [23:43:23] [Server thread/WARN]:    at net.minecraft.server.v1_7_R1.EntityCreature.<init>(EntityCreature.java:25)
    [23:43:23] [Server thread/WARN]:    at net.minecraft.server.v1_7_R1.EntityMonster.<init>(EntityMonster.java:8)
    [23:43:23] [Server thread/WARN]:    at net.minecraft.server.v1_7_R1.EntityZombie.<init>(EntityZombie.java:25)
    [23:43:23] [Server thread/WARN]:    at org.horrgs.projone.util.CustomEntityZombie.<init>(CustomEntityZombie.java:17)
    [23:43:23] [Server thread/WARN]:    ... 11 more
    Here's my new class

    Code:java
    1. package org.horrgs.projone.util;
    2.  
    3. import net.minecraft.server.v1_7_R1.*;
    4. import org.bukkit.craftbukkit.v1_7_R1.util.UnsafeList;
    5. import org.horrgs.projone.tasks.Round;
    6.  
    7. import java.lang.reflect.Field;
    8.  
    9. /**
    10. * Created by Horrgs on 1/31/14.
    11. */
    12.  
    13. public class CustomEntityZombie extends EntityZombie {
    14.  
    15.  
    16. public CustomEntityZombie(World world) {
    17. super(world);
    18.  
    19. try {
    20. Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
    21. bField.setAccessible(true);
    22. Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
    23. cField.setAccessible(true);
    24. bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    25. bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    26. cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    27. cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    28. } catch (Exception e) {
    29. e.printStackTrace();
    30. }
    31.  
    32. this.goalSelector.a(0, new PathfinderGoalFloat(this));
    33. this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityHuman.class, 1.0D, false));
    34. this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, true));
    35. this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
    36. this.goalSelector.a(6, new PathfinderGoalMoveThroughVillage(this, 1.0D, false));
    37. this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D));
    38. this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
    39. this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
    40. this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
    41. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true));
    42. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, 0, false));
    43. }
    44.  
    45.  
    46.  
    47. @Override
    48. protected void aD() {
    49. super.aD();
    50. this.bc().b(GenericAttributes.b);
    51. this.bc().b(GenericAttributes.d);
    52. this.getAttributeInstance(GenericAttributes.b).setValue(400.0D); // Original 3.0D
    53. getAttributeInstance(GenericAttributes.d).setValue(Round.roundNumber + .5);
    54. }
    55. }
    56.  
     
  25. Offline

    TeeePeee

    iiHeroo
    Him, that's strange. If you haven't already, try it without the calls to bc.b and see if that changes anything. Your error is being thrown on the first call to bc.b which should be unregistering the attribute - I will have to look into the code to see what it does in more detail.
     
  26. Offline

    iiHeroo


    I tried it, no errors, although, it seems like my goalSelectors & targetSelectors aren't 'working'. The zombies are suppose to attack the villagers, and not humans, but they still attack me, here's the current code:

    Code:java
    1. package org.horrgs.projone.util;
    2.  
    3. import net.minecraft.server.v1_7_R1.*;
    4. import org.bukkit.craftbukkit.v1_7_R1.util.UnsafeList;
    5. import org.horrgs.projone.tasks.Round;
    6.  
    7. import java.lang.reflect.Field;
    8.  
    9. /**
    10. * Created by Horrgs on 1/31/14.
    11. */
    12.  
    13. public class CustomEntityZombie extends EntityZombie {
    14.  
    15.  
    16. public CustomEntityZombie(World world) {
    17. super(world);
    18.  
    19. try {
    20. Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
    21. bField.setAccessible(true);
    22. Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
    23. cField.setAccessible(true);
    24. bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    25. bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    26. cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
    27. cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    28. } catch (Exception e) {
    29. e.printStackTrace();
    30. }
    31.  
    32. this.goalSelector.a(0, new PathfinderGoalFloat(this));
    33. this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityHuman.class, 1.0D, false));
    34. this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, true));
    35. this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
    36. this.goalSelector.a(6, new PathfinderGoalMoveThroughVillage(this, 1.0D, false));
    37. this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D));
    38. this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
    39. this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
    40. this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
    41. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true));
    42. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, 0, false));
    43. }
    44.  
    45.  
    46.  
    47. @Override
    48. protected void aD() {
    49. super.aD();
    50. this.getAttributeInstance(GenericAttributes.b).setValue(400.0D); // Original 3.0D
    51. getAttributeInstance(GenericAttributes.d).setValue(Round.roundNumber + .5);
    52. }
    53. }
    54.  
     
  27. Offline

    TeeePeee

    iiHeroo
    Remove the PathfinderMeleeAttack and PathfinderNearestAttackableTarget with EntityHuman.class as a parameter.
     
  28. Offline

    iiHeroo


    So I believe I'm doing this wrong because I got pretty confused by what you said by the wording, although, I tried multiple things like removing the EntityHuman.class line completely, setting it to true, false, etc,. When I remove it completely, there's a zombie that spawns with like speed 30 (Something like that)

    Code:
            this.goalSelector.a(0, new PathfinderGoalFloat(this));
            this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, false));
            this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
            this.goalSelector.a(6, new PathfinderGoalMoveThroughVillage(this, 1.0D, false));
            this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D));
            this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
            this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
            this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
            this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, 0, false));
    I've done this too:

    Code:java
    1. this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true/false));
    2. this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, true/false));
    3.  
    4.  
    5.  
    6.  
     
  29. Offline

    TeeePeee

    iiHeroo
    The upper code you posted is correct. I'm not sure what your intent is exactly but as you have written it, your zombie will exhibit normal behaviour but will not target or attack humans, will be faster (depending on the round) and follow at a great distance.
     
  30. Offline

    iiHeroo


    The zombie was attacking me, although, I think I discovered why, I was spawning a normal zombie through the code instead of a a custom, haven't tested it though.

    Yeah, I was just spawning them completely wrong xD, now it works :D! Thanks.
     
Thread Status:
Not open for further replies.

Share This Page