Reflection Problem - "argument type mismatch"

Discussion in 'Spigot Plugin Development' started by ColonelHedgehog, May 28, 2015.

  1. I've been having a little trouble using reflection to change the speed of a horse.

    Here is what I'm using (with debug stuff):

    Code (Text):

    Logger l = plugin.getLogger(); // Plugin's logger

    Field genericAttributeD = Reflection.getNMSClass("GenericAttributes").getDeclaredField("d");
    genericAttributeD.setAccessible(true);
    l.info("genericAttributeD is " + genericAttributeD);

    Class<?> iAttribute = Reflection.getNMSClass("IAttribute");
    l.info("iAttribute is " + iAttribute);

    Class<?> craftLivingEntityClass = Reflection.getOBC("entity.CraftLivingEntity");
    l.info("craftLivingEntityClass is " + craftLivingEntityClass);

    Object craftLivingEntity = craftLivingEntityClass.cast(horse);
    l.info("craftLivingEntity is " + craftLivingEntity);

    Method getHandle = craftLivingEntity.getClass().getMethod("getHandle");
    getHandle.setAccessible(true);
    l.info("getHandle() is " + getHandle);

    Object entityLiving = getHandle.invoke(craftLivingEntity);
    l.info("entityLiving is " + entityLiving);

    Method getAttributeInstance = entityLiving.getClass().getMethod("getAttributeInstance", iAttribute);
    getAttributeInstance.setAccessible(true);
    l.info("getAttributeInstance() is " + getAttributeInstance);

    Object attributeInstance = getAttributeInstance.invoke(entityLiving, genericAttributeD);
    l.info("attributeInstance is " + attributeInstance);

    attributeInstance.getClass().getMethod("setValue").invoke(attributeInstance, speed); // Sets speed of horse, where "speed" is a double.
     
    This is supposed to do the same thing as the straight-out NMS alternative:

    Code (Text):

    ((CraftLivingEntity) horse)
        .getHandle()
       .getAttributeInstance(GenericAttributes.d)
       .setValue(speed);
    However, with version changes, the second method breaks. That's why I tried using reflection. It appears to work up to the "getAttributeInstance()" invocation, then it throws this exception:

    Code (Text):

    Caused by: java.lang.IllegalArgumentException: argument type mismatch
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_75]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_75]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_75]
        at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_75]
     
    getAttributeInstance(IAttribute) should be working. Any ideas as to why it's not? I haven't really messed around with Reflection a lot before. By the way, when is it necessary to use "setAccessible(boolean)"?
     
  2. @ColonelHedgehog I don't have time to look at all your code, but I do have enough time to explain setAccessible(boolean).

    setAccessible(boolean) is an inherited method from AccessibleObject. which allows you to avoid java's visibility checks. It's only set for that AccessibleObject instance, so setting it to true (or false) will not affect the underlying object in anyway.
     
  3. @ColonelHedgehog according to your getMethod call, the setter is not supposed to have any parameters
    Code (Java):
    getMethod("setValue")
    while in NMS, it has a double parameter (which you already knew, but didn't specify in the getMethod call). Simply add the parameters to the getMethod call (so double.class) and it should work.
     
  4. Usw getDeclaredMethode.
    I wrote ab API which wraps everything.
    Iattributes are dynamically loaded into my wrapper class.
     
  5. It's a public method, getMethod would function fine.
     
    • Agree Agree x 1
  6. @DarkSeraphim, @ysl3000, @not2excel:

    Thanks for the help, and while I'm sure that will prevent one problem, I still seem to be getting the error.

    Code (Text):

    Logger l = plugin.getLogger();

    Field genericAttributeD = Reflection.getNMSClass("GenericAttributes").getDeclaredField("d");
    l.info("genericAttributeD is " + genericAttributeD);

    Class<?> iAttribute = Reflection.getNMSClass("IAttribute");
    l.info("iAttribute is " + iAttribute);

    Class<?> craftLivingEntityClass = Reflection.getOBC("entity.CraftLivingEntity");
    l.info("craftLivingEntityClass is " + craftLivingEntityClass);

    Object craftLivingEntity = craftLivingEntityClass.cast(horse);
    l.info("craftLivingEntity is " + craftLivingEntity);

    Method getHandle = craftLivingEntity.getClass().getMethod("getHandle");
    l.info("getHandle() is " + getHandle);

    Object entityLiving = getHandle.invoke(craftLivingEntity);
    l.info("entityLiving is " + entityLiving);

    Method getAttributeInstance = entityLiving.getClass().getMethod("getAttributeInstance", iAttribute);
    l.info("getAttributeInstance() is " + getAttributeInstance);

    Object attributeInstance = getAttributeInstance.invoke(entityLiving, genericAttributeD); // ERROR POINT
    l.info("attributeInstance is " + attributeInstance);

    Method setValue = attributeInstance.getClass().getMethod("setValue", double.class);
    l.info("setValue() is " + setValue);
    setValue.invoke(attributeInstance.getClass().cast(attributeInstance), speed);
    I get the mismatched argument type where I commented "ERROR POINT." I don't see why I should be getting this since I'm calling all the right methods.

    These debug lines:
    Code (Text):

    l.info("genericAttributeD is " + genericAttributeD);
    ...
    l.info("getAttributeInstance() is " + getAttributeInstance);
     
    Tell me:
    Code (Text):

    [12:40:27 INFO]: [EquestrianDash] genericAttributeD is public static final net.minecraft.server.v1_8_R2.IAttribute net.minecraft.server.v1_8_R2.GenericAttributes.d
    ...
    [12:40:27 INFO]: [EquestrianDash] getAttributeInstance() is public net.minecraft.server.v1_8_R2.AttributeInstance net.minecraft.server.v1_8_R2.EntityLiving.getAttributeInstance(net.minecraft.server.v1_8_R2.IAttribute)
     
    And yet it says the argument types are mismatched. How can this be?
     
  7. @ColonelHedgehog generalAttributeD is a Field, you forgot to call Field#get() :p
     
    • Winner Winner x 1
  8. ...

    Gaaaaarrgh! Thank you. :p Fixed everything.