Solved Armor Stand - No Gravity + Velocity

Discussion in 'Spigot Plugin Development' started by mattrick, Mar 28, 2016.

  1. Hi there,

    I'm aware that (currently) in Minecraft, setting the NoGravity tag on Armor Stands not only prevents them from being affected by gravity, but also any velocity. My goal is to have a floating Armor Stand that can also be moved using setVelocity (constantly teleporting it is an option I'd like to avoid if possible). I've also tried using corrupt levitation effects (a levitation potion effect with an amplifier of 255), but that only seems to work on players (any other entity flies off into space).

    Is there a way to achieve this that you know of? Possibly if there's an entity that floats by itself already I can set the armor stand riding that, but I'm not sure of any that will work.
     
  2. Two options I can think of...

    Create a levitating effect by setting the velocity each tick (like jumping in mid air) - probably a not wanted option

    Make it ride a noAI bat? I'm sure they still float with no AI right?
     
  3. That would make an odd jittering effect though.

    NoAI also prevents movement through velocity.
     
  4. Tbh it seems silly that no AI would stop manually setting velocity :( we should just put a vote and see how many people would love to see it changed xD
     
  5. Hey,

    This problem can't be fixed esay. Probably, you have to create a custom entity basing on the armorstand. Did you ever heard of custom entities?
     
  6. Maybe just set the y velocity to 0 if you don't want it to move down.
     
  7. That is not a good possibility, because NMS does update the velocity every tick
     
  8. You could just set the gravity tag to true and then quickly give the armorstand velocity. The only problem is checking when the velocity movement is over and you he to set the gravity tag back to false
     
  9. @mattrick
    When the armor stands have velocity, do they constantly fly into a target direction, or do they slowly fall down again?
     
  10. Mojang decided it was intended and it was given a won'tfix tag.

    Velocities are still calculated client side. I considered extending the Shulker mob and making it invisible, but it's head is still rendered.

    Gravity is still calculated client side. In Minecraft, there's really only three states if most mobs: moving up, moving down, or on the ground.

    It will then be affected by gravity when it is moving, though.

    They fall, gravity is applied regardless.
     
  11. NathanWolf

    Supporter

    There is actually an easy way around this, if you're willing to do a little NMS.

    Simply call the NMS version of ArmorStand.setGravity(false). That's it :D

    The Spigot API version also sets "noclip", which is what prevents the AS from respecting velocity. This is to adhere to vanilla mechanics, where "no gravity" and noclip go hand in hand, but with a bit of hacking you can set one and not the other.
     
    • Agree Agree x 2
  12. I'll look into it when I get home. Thank you!
     
    • Friendly Friendly x 1
  13. @NathanWolf
    After digging a little through NMS and some research I had done before, I noticed that entity velocity is handled through the g(float, float) method. The AS class overrides this, and checks that hasGravity() method and if it does have gravity, it calls the super version of that method.

    @mattrick
    Oops, I formulated that sentence a bit weird. I ment should it fall down, or move in a constant direction?
     
  14. Ideally, it should move in a constant direction, not affected by other forces.
     
  15. NathanWolf

    Supporter

    I can say for sure that turning off the gravity flag while keeping noclip off gives you an armor stand that you can push around in the air, and teleport- I use this in my plugin for ArmorStand-based projectiles, like throwing swords and such.

    I also use it for broomsticks, players ride horses riding armor stands and I push the armor stand around.
     
  16. Okay, in my custom armor stand class, I have this:
    Code (Text):
    package me.mattrick.test;

    import net.minecraft.server.v1_9_R1.EntityArmorStand;
    import org.bukkit.ChatColor;
    import org.bukkit.World;
    import org.bukkit.craftbukkit.v1_9_R1.CraftWorld;

    public class EntityCustomArmorStand extends EntityArmorStand {

        public EntityCustomArmorStand(World world) {
            super(((CraftWorld) world).getHandle());
            this.setGravity(false);
        }

    }
     
    But it is still affected by gravity (the velocity is applied, however).
     
  17. NathanWolf

    Supporter

    Have you tried *not* using a custom armor stand, just spawning a normal one?

    I honestly haven't done this without either constantly applying velocity or teleporting the ArmorStand, but when I do that I haven't noticed it falling slightly each tick or anything like that.

    If this happens with a normal armor stand I can try out spawning one with gravity=false and noclip=false and see what happens.

    I have to assume there's a reason for setting noclip in setGravity....
     
  18. Yes, in the case of a non-custom Armor Stand, it will either: a) fall if setGravity(true), but still apply gravity or b) not move at all if setGravity(false).

    I've tried that also, it doesn't seem to work.

    I'm *guessing* its so it can't be pushed by other entities?
     
  19. @mattrick
    armor stands can never be pushed, though. There's a move(double, double, double) method inside the Entity class. If the entity has noclip enabled, the method doesn't do what it has to do so velocity isn't handled. After a little playing around, I found this solution which worked perfectly for me (I extended the EntityArmorStand class and overrid these methods):
    Code (Java):
    @Override
    public void g(float f, float f1) {
        if (!hasGravity()) { // hasGravity() actually means hasNoGravity(), probably a mistake in deobfuscating.
            super.g(f, f1);
        } else {
            move(motX, motY, motZ); // Give them some velocity anyways ;3
        }
    }
    @Override
    public void n() { // This method is called each tick. This also slowly multiplies each velocity by 0.98, so I just reset those values.
        if (hasGravity()) {
            double motX = this.motX, motY = this.motY, motZ = this.motZ;
            super.n();
            this.motX = motX;
            this.motY = motY;
            this.motZ = motZ;
        } else super.n();
    }
     
    • Winner Winner x 1
    • Useful Useful x 1
  20. You know levitation would work... The "bugged" lev does work - its just not 255...
    Its 137/138 I don't remeber