Tutorial [1.8 ONLY]WASD Entity control

Discussion in 'Resources' started by Funergy, Feb 17, 2015.

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

    Funergy


    FOR 1.8.3 My post is a little further
    WASD Entity riding
    ---------------------------------------------------

    In this tutorial we are going to learn how we let players ride an
    Entity Living with WASD keys. This all will be done with NMS.
    Before you start this tutorial you need to have a custom entity
    class extending an entity thats a living entity. So let get started!

    A quick note!
    If you are here for WASD entity riding but you are using 1.7 or 1.7-1.8 protocol hack
    Then you should use this amazing tutorial from @DSH105!

    Code:
    @Override
    public void g(float sideMot, float forMot) {
    }
    Now, because we only want Players to control the entity whilst riding, add in a check to see if the passenger is a human.
    Code:
    if(this.passenger != null && this.passenger instanceof EntityHuman) {
    
    }
    And now you we do a lot of things in the check from the last step. Some comments are written in the code itself.
    Note: that the most of these code is copied from EntityHorse
    Code:
                this.lastYaw = this.yaw = this.passenger.yaw;
                this.pitch = this.passenger.pitch * 0.5F;
                this.setYawPitch(this.yaw, this.pitch);//Update the pitch and yaw
                this.aI = this.aG = this.yaw;
                sideMot = ((EntityLiving)this.passenger).aX * 0.5F;
                forMot = ((EntityLiving)this.passenger).aY;
                if(forMot <= 0.0F) {
                    forMot *= 0.25F;// Make backwards slower
                }
    
                Field jump = null; //Jumping
                try {
                    jump = EntityLiving.class.getDeclaredField("aW");
                } catch (NoSuchFieldException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (SecurityException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                jump.setAccessible(true);
    
                if (jump != null && this.onGround) {    // Wouldn't want it jumping while on the ground would we?
                    try {
                        if (jump.getBoolean(this.passenger)) {
                            double jumpHeight = 0.5D;//Here you can set the jumpHeight
                            this.motY = jumpHeight;    // Used all the time in NMS for entity jumping
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
    
                this.S = 1.0F;// The custom entity will now automatically climb up 1 high blocks
                this.aK = this.bH() * 0.1F;
                if(!this.world.isStatic) {
                    this.j(0.35F);//Here is the speed the entity will walk.
                    super.g(sideMot, forMot);
                }
    
    
                this.ay = this.az;//Some extra things
                double d0 = this.locX - this.lastX;
                double d1 = this.locZ - this.lastZ;
                float f4 = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F;
                if(f4 > 1.0F) {
                    f4 = 1.0F;
                }
    
                this.az += (f4 - this.az) * 0.4F;
                this.aA += this.az;
    }
    And the last thing we need to do is add an else statement after the check.
    Code:
    else {
                this.S = 0.5F;
                this.aK = 0.02F;
                super.g(sideMot, forMot);
            }
    This was all achieved by just looking in the EntityHorse class!

    Have a nice day further.

    And I hope there will be awesome stuff getting created with this!

    -Funergy

    PS: If this helped you please give this a like!
    Some people that needed this:
    @ChipDev


    And for people that just want the whole method here
    the whole method (open)

    Code:
        @Override
        public void g(float sideMot, float forMot) {
            if(this.passenger != null && this.passenger instanceof EntityHuman) {
                this.lastYaw = this.yaw = this.passenger.yaw;
                this.pitch = this.passenger.pitch * 0.5F;
                this.setYawPitch(this.yaw, this.pitch);//Update the pitch and yaw
                this.aI = this.aG = this.yaw;
                sideMot = ((EntityLiving)this.passenger).aX * 0.5F;
                forMot = ((EntityLiving)this.passenger).aY;
                if(forMot <= 0.0F) {
                    forMot *= 0.25F;// Make backwards slower
                }
    
                Field jump = null; //Jumping
                try {
                    jump = EntityLiving.class.getDeclaredField("aW");
                } catch (NoSuchFieldException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (SecurityException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                jump.setAccessible(true);
    
                if (jump != null && this.onGround) {    // Wouldn't want it jumping while on the ground would we?
                    try {
                        if (jump.getBoolean(this.passenger)) {
                            double jumpHeight = 0.5D;//Here you can set the jumpHeight
                            this.motY = jumpHeight;    // Used all the time in NMS for entity jumping
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
    
                this.S = 1.0F;// The custom entity will now automatically climb up 1 high blocks
                this.aK = this.bH() * 0.1F;
                if(!this.world.isStatic) {
                    this.j(0.35F);//Here is the speed the entity will walk.
                    super.g(sideMot, forMot);
                }
    
    
                this.ay = this.az;//Some extra things
                double d0 = this.locX - this.lastX;
                double d1 = this.locZ - this.lastZ;
                float f4 = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F;
                if(f4 > 1.0F) {
                    f4 = 1.0F;
                }
    
                this.az += (f4 - this.az) * 0.4F;
                this.aA += this.az;
            } else {
                this.S = 0.5F;
                this.aK = 0.02F;
                super.g(sideMot, forMot);
            }
    
    
        }
     
    Last edited: May 8, 2015
  2. Offline

    ninelives

    where do i paste this stuff
     
  3. Offline

    timtower Administrator Administrator Moderator

    In your IDE, start with small plugins first though like "hello world" ones
     
    CrystallFTW and KingFaris11 like this.
  4. Offline

    ninelives

    whats IDE
     
  5. Offline

    eyamaz

  6. Offline

    ChipDev

    I love it. I bet so many people will find this as a "Oh my god, I've been looking for this for an entire week" <-- *Ok, that actually may be me :p
    EDIT: I've been using public void e. xD
     
    Funergy likes this.
  7. Offline

    TGRHavoc

    And here I was thinking that the e method was the one to use :p
     
    Funergy likes this.
  8. Offline

    Funergy

    ChipDev likes this.
  9. Code:
        public boolean onCommand(final CommandSender d, Command cmd,
                String commandLabel, final String[] args) {
            if (commandLabel.equalsIgnoreCase("mounts") || commandLabel.equalsIgnoreCase("mt")) {
                if (d instanceof Player) {
                    Player p = (Player) d;
                   
                    WorldServer nmsWorld = ((CraftWorld) p.getLocation().getWorld()).getHandle();
                    PigEdited pE = new PigEdited(nmsWorld);
                    pE.setPosition(p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ());
                    pE.setSaddle(true);
                    nmsWorld.addEntity(pE);
                    Bukkit.broadcastMessage("Done.");
                   
                    p.getInventory().addItem(new ItemStack(Material.SADDLE, 1));
                }
            }
            return false;
        }
    @Funergy Hello, I have used this to try and create a custom pig... I get no errors, but when attempting to spawn the pig, it doesn't appear. Here is my code:

    Spawning method:


    Custom Entity:
    Code:
    package me.HeyAwesomePeople.Mounts;
    
    import java.lang.reflect.Field;
    
    import net.minecraft.server.v1_8_R1.EntityHuman;
    import net.minecraft.server.v1_8_R1.EntityLiving;
    import net.minecraft.server.v1_8_R1.EntityPig;
    import net.minecraft.server.v1_8_R1.MathHelper;
    import net.minecraft.server.v1_8_R1.PathfinderGoalSelector;
    import net.minecraft.server.v1_8_R1.World;
    
    import org.bukkit.craftbukkit.v1_8_R1.util.UnsafeList;
    
    public class PigEdited extends EntityPig {
    
        public PigEdited(World world) {
            super(world);
    
            try {
                Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
                bField.setAccessible(true);
                Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
                cField.setAccessible(true);
                bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
                bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
                cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
                cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
    
            } catch (Exception exc) {
                exc.printStackTrace();
            }
        }
    
        @Override
        public void g(float sideMot, float forMot) {
            if (this.passenger != null && this.passenger instanceof EntityHuman) {
                this.lastYaw = this.yaw = this.passenger.yaw;
                this.pitch = this.passenger.pitch * 0.5F;
                this.setYawPitch(this.yaw, this.pitch);
                this.aI = this.aG = this.yaw;
                sideMot = ((EntityLiving) this.passenger).aX * 0.5F;
                forMot = ((EntityLiving) this.passenger).aY;
                if (forMot <= 0.0F) {
                    forMot *= 0.25F;
                }
    
                Field jump = null;
                try {
                    jump = EntityLiving.class.getDeclaredField("aW");
                } catch (NoSuchFieldException e1) {
                    e1.printStackTrace();
                } catch (SecurityException e1) {
                    e1.printStackTrace();
                }
                jump.setAccessible(true);
    
                if (jump != null && this.onGround) {
                    try {
                        if (jump.getBoolean(this.passenger)) {
                            double jumpHeight = 0.5D;
                            this.motY = jumpHeight;
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
    
                this.S = 1.0F;
                this.aK = this.bH() * 0.1F;
                if (!this.world.isStatic) {
                    this.j(0.35F);
                    super.g(sideMot, forMot);
                }
    
                this.ay = this.az;//Some extra things
                double d0 = this.locX - this.lastX;
                double d1 = this.locZ - this.lastZ;
                float f4 = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F;
                if (f4 > 1.0F) {
                    f4 = 1.0F;
                }
    
                this.az += (f4 - this.az) * 0.4F;
                this.aA += this.az;
            } else {
                this.S = 0.5F;
                this.aK = 0.02F;
                super.g(sideMot, forMot);
            }
        }
    
    }
    Thanks,
    HeyAwesomePeople
     
  10. Offline

    Funergy

  11. I didn't, and I am trying now, but I keep getting an ID already registered error. I have tried with many ids.

    Register Enum Class:
    Code:
    package me.HeyAwesomePeople.Mounts;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.Map;
    
    import net.minecraft.server.v1_8_R1.EntityInsentient;
    import net.minecraft.server.v1_8_R1.EntityPig;
    import net.minecraft.server.v1_8_R1.EntityTypes;
    
    import org.bukkit.entity.EntityType;
    
    public enum Register {
        PIG("Pig", 121, EntityType.PIG, EntityPig.class, PigEdited.class);
    
        private String name;
        private int id;
        private EntityType entityType;
        private Class<? extends EntityInsentient> nmsClass;
        private Class<? extends EntityInsentient> customClass;
    
        private Register(String name, int id, EntityType entityType, Class<? extends EntityInsentient> nmsClass, Class<? extends EntityInsentient> customClass) {
            this.name = name;
            this.id = id;
            this.entityType = entityType;
            this.nmsClass = nmsClass;
            this.customClass = customClass;
        }
    
        public String getName() {
            return this.name;
        }
    
        public int getID() {
            return this.id;
        }
    
        public EntityType getEntityType() {
            return this.entityType;
        }
    
        public Class<? extends EntityInsentient> getNMSClass() {
            return this.nmsClass;
        }
    
        public Class<? extends EntityInsentient> getCustomClass() {
            return this.customClass;
        }
    
        public static void regissterEntities() {
            for (Register entity : values()) {
                try {
                    Method a = EntityTypes.class.getDeclaredMethod("a", new Class<?>[] { Class.class, String.class, int.class });
                    a.setAccessible(true);
                    a.invoke(null, entity.getCustomClass(), entity.getName(), entity.getID()); //error here, ID already registered
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        /*
        public static void registerEntities()
          {
            for (Register entity : values()) {
              a(entity.getCustomClass(), entity.getName(), entity.getID());
            }
            try
            {
             BiomeBase[]  biomes = (BiomeBase[])getPrivateStatic(BiomeBase.class, "biomes");
            }
            catch (Exception exc)
            {
              BiomeBase[] biomes;
              return;
            }
            BiomeBase[] biomes;
            BiomeBase[] arrayOfBiomeBase1 = biomes;int k = biomes.length;
            for (k = 0; biomes.length < k; k++)
            {
              BiomeBase biomeBase = arrayOfBiomeBase1[k];
              if (biomeBase == null) {
                break;
              }
              for (String field : new String[] { "as", "at", "au", "av" }) {
                try
                {
                  Field list = BiomeBase.class.getDeclaredField(field);
                  list.setAccessible(true);
                 
                  List<BiomeMeta> mobList = (List)list
                    .get(biomeBase);
                  int i2;
                  int i1;
                  for (Iterator localIterator = mobList.iterator(); localIterator.hasNext(); i1 > i2)
                  {
                    BiomeMeta meta = (BiomeMeta)localIterator.next();
                    Register[] arrayOfRideAbleEntityType2;
                    i2 = (arrayOfRideAbleEntityType2 = values()).length;i1 = 0; continue;Register entity = arrayOfRideAbleEntityType2[i1];
                    if (entity.getNMSClass().equals(meta.b)) {
                      meta.b = entity.getCustomClass();
                    }
                    i1++;
                  }
                }
                catch (Exception e)
                {
                  e.printStackTrace();
                }
              }
            }
          }
    */
        private static Object getPrivateStatic(
                @SuppressWarnings("rawtypes") Class clazz, String f)
                throws Exception {
            Field field = clazz.getDeclaredField(f);
            field.setAccessible(true);
            return field.get(null);
        }
    
        @SuppressWarnings({ "unchecked", "rawtypes", "unused" })
        private static void a(Class paramClass, String paramString, int paramInt) {
            try {
                ((Map) getPrivateStatic(EntityTypes.class, "c")).put(paramString, paramClass);
                ((Map) getPrivateStatic(EntityTypes.class, "d")).put(paramClass, paramString);
                ((Map) getPrivateStatic(EntityTypes.class, "e")).put(Integer.valueOf(paramInt), paramClass);
                ((Map) getPrivateStatic(EntityTypes.class, "f")).put(paramClass, Integer.valueOf(paramInt));
                ((Map) getPrivateStatic(EntityTypes.class, "g")).put(paramString, Integer.valueOf(paramInt));
            } catch (Exception localException) {
            }
        }
    }
    
    onEnable()
    Code:
        @Override
        public void onEnable() {
            instance = this;
           
            Register.regissterEntities();
        }
    Thanks.
     
  12. Offline

    Funergy

  13. @Funergy
    How do you unregister an id? I was told to unregister on disable, not before registering.
     
  14. Offline

    Funergy

  15. Thanks. I got it all working.

    @Funergy Actually one more odd thing. It seems the horse cannot climb 1 high blocks automatically, even though I have this:
    Code:
    this.S = 1.0F;
    It works with pigs fine.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 29, 2015
    Funergy likes this.
  16. Offline

    Funergy

    @HeyAwesomePeople A horse should automatically climb 1 block. Remove that line it should be unnecessary
     
  17. Deleting that line didn't work. I also tried to directly copy the example code you posted. Didn't work either.
     
  18. Offline

    Funergy

    HeyAwesomePeople likes this.
  19. Thanks. And I have a question. I know the methods for each class change every update, but how do I know what they change to? I have access to https://github.com/Bukkit/mc-dev/tree/master/net/minecraft/server but thats 1.7.10. Where can I get the 1.8 code? And more importantly, how do I know what each variable controls?

    EDIT: Nvm, after about an hour of searching for 1.8 NMS code I realized I could just decompile the spigot.jar...
     
    Last edited: Feb 22, 2015
    Europia79 and ChipDev like this.
  20. Offline

    ChipDev

    +1
     
  21. Last edited: Feb 24, 2015
  22. Offline

    ChipDev

    Yes, but also it would cause only the CUSTOM SPAWNED entities to have the custom entity effect.
     
  23. Works without registering the BIOMEMETA, or without doing this:

    Code:
                for (Field f : BiomeBase.class.getDeclaredFields()) {
                    if (f.getType().getSimpleName().equals(BiomeBase.class.getSimpleName())) {
                        if (f.get(null) != null) {
    
                            /*
                             * this peace of code is being called for every biome,
                             * we are going to loop through all fields in the
                             * BiomeBase class so we can detect which of them are
                             * Lists (again, to prevent problems when the field's
                             * name changes), by doing this we can easily get the 4
                             * required lists without using the name (which probably
                             * changes every version)
                             */
                            for (Field list : BiomeBase.class.getDeclaredFields()) {
                                if (list.getType().getSimpleName().equals(List.class.getSimpleName())) {
                                    list.setAccessible(true);
                                    @SuppressWarnings("unchecked")
                                    List<BiomeMeta> metaList = (List<BiomeMeta>) list.get(f.get(null));
    
                                    /*
                                     * now we are almost done. This peace of code
                                     * we're in now is called for every biome. Loop
                                     * though the list with BiomeMeta, if the
                                     * BiomeMeta's entity is the one you want to
                                     * change (for example if EntitySkeleton matches
                                     * EntitySkeleton) we will change it to our
                                     * custom entity class
                                     */
                                    for (BiomeMeta meta : metaList) {
                                        Field clazz = BiomeMeta.class.getDeclaredFields()[0];
                                        if (clazz.get(meta).equals(nmsClass)) {
                                            clazz.set(meta, customClass);
                                        }
                                    }
                                }
                            }
    
                        }
                    }
                }
    It works without that code. But will this cause problems?
     
  24. Offline

    DSH105

    This tutorial would be cooler if you acknowledged where you copied this from:

    [​IMG]

     
    ItsMattHogan, KingFaris11 and Goblom like this.
  25. Offline

    Funergy

    @DSH105 I just wanted to update your tutorial to 1.8 since you are retired right now and your thread isn't for 1.8 too.

    And I looked at the horse class for that code. Its really easy by doing that.
    So whats the problem?

    EDIT: edited the tutorial. And it doesn't look like your outdated one. Happy now?
     
    Last edited: Feb 25, 2015
  26. Offline

    ChipDev

    Nope!

    You never replied to the thread for our help, so I guess you didn't exactly help us.. @TGRHavoc did..

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 29, 2015
  27. Offline

    Funergy

    @ChipDev He helped us but it wasn't really needed since you just needed to look at the horse g(float arg1, float arg2) method and there was every field he told us. But I'm still happy that he tried to help us :)
     
    TGRHavoc and ChipDev like this.
  28. Offline

    ChipDev

    The methods are actually diff., He said e(float arg1, float arg2) :p
    But thanks @DSH105
     
  29. Everything should be good then?

    Hey any news on the horses not automatically climbing a block?
     
    ChipDev likes this.
  30. Offline

    TGRHavoc

    NMS Code for horses, maybe compare what you have to what Mojang has:
    Code:
      public void g(float f, float f1)
      {
        if ((this.passenger != null) && ((this.passenger instanceof EntityLiving)) && (cE()))
        {
          this.lastYaw = (this.yaw = this.passenger.yaw);
          this.pitch = (this.passenger.pitch * 0.5F);
          setYawPitch(this.yaw, this.pitch);
          this.aI = (this.aG = this.yaw);
          f = ((EntityLiving)this.passenger).aX * 0.5F;
          f1 = ((EntityLiving)this.passenger).aY;
          if (f1 <= 0.0F)
          {
            f1 *= 0.25F;
            this.bL = 0;
          }
          if ((this.onGround) && (this.bp == 0.0F) && (cx()) && (!this.bE))
          {
            f = 0.0F;
            f1 = 0.0F;
          }
          if ((this.bp > 0.0F) && (!ct()) && (this.onGround))
          {
            this.motY = (getJumpStrength() * this.bp);
            if (hasEffect(MobEffectList.JUMP)) {
              this.motY += (getEffect(MobEffectList.JUMP).getAmplifier() + 1) * 0.1F;
            }
            m(true);
            this.ai = true;
            if (f1 > 0.0F)
            {
              float f2 = MathHelper.sin(this.yaw * 3.141593F / 180.0F);
              float f3 = MathHelper.cos(this.yaw * 3.141593F / 180.0F);
             
              this.motX += -0.4F * f2 * this.bp;
              this.motZ += 0.4F * f3 * this.bp;
              makeSound("mob.horse.jump", 0.4F, 1.0F);
            }
            this.bp = 0.0F;
          }
          this.S = 1.0F;
          this.aK = (bH() * 0.1F);
          if (!this.world.isStatic)
          {
            j((float)getAttributeInstance(GenericAttributes.d).getValue());
            super.g(f, f1);
          }
          if (this.onGround)
          {
            this.bp = 0.0F;
            m(false);
          }
          this.ay = this.az;
          double d0 = this.locX - this.lastX;
          double d1 = this.locZ - this.lastZ;
          float f4 = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F;
          if (f4 > 1.0F) {
            f4 = 1.0F;
          }
          this.az += (f4 - this.az) * 0.4F;
          this.aA += this.az;
        }
        else
        {
          this.S = 0.5F;
          this.aK = 0.02F;
          super.g(f, f1);
        }
      }
    
     
Thread Status:
Not open for further replies.

Share This Page