getVelocity() doesn't seem to work correctly

Discussion in 'Plugin Development' started by petrifiednightmares, Apr 10, 2011.

Thread Status:
Not open for further replies.
  1. I am trying to make a plugin that makes the player walk faster if certain conditions are met, my code is as follows:

    Code:
    public void onPlayerMove(PlayerMoveEvent event) {
        Player player = event.getPlayer();
        if(<CONDITIONS>)
        {
            Vector dir=player.getVelocity().normalize().multiply(3);
            System.out.println("vel: "+player.getVelocity());
            System.out.println("normalized: "+player.getVelocity().normalize().length());
            System.out.println("dir: "+dir.length());
            System.out.println("dir: "+dir);
            player.setVelocity(dir);
        }
    }
    dir has a length of 3, but I do not move any faster.

    Instead I tried Vector dir2=player.getLocation().getDirection().multiply(2); which DOES move me faster, but the problem is that it simply pushes me in the direction im facing instead of boosting my movement speed.

    So my question is why doesnt my code up there work?
     
  2. Offline

    Relentless_x

    i am trying to do same as you if you find a solution please share <3 i'll do likewise :)
     
  3. Offline

    Evenprime

    I've worked extensively with velocity in the last days/weeks and can share my experiences with it.

    I'll start with what happens when you call "player.setVelocity(vector)": If you do that, the server sets the velocity vector of the player (obviously) and sends the player a message with that vector. That's it. The client/player then has the duty to include this vector in its future movement calculations. The server doesn't really use that vector for anything from now on.

    After that, the vector gets reduced in length (on the server) by a certain percentage with every PLAYER_MOVE event that comes from the player. But the vector isn't used in any actual calculations on the server and the client/player doesn't know the value of the vector of the server from now on, as it uses its completely independent velocity vector.

    Then there are certain situations that will cause the vectors length to "shrink" very fast on the server side, like a player touching a wall or walking on ground. Again, the client doesn't know or care about that when actually moving the player. Only the vertical y-velocity seems to be (halfway) reliable as a data source (depending on what you need it for).

    Eventually the vector will reach its default value ~(0.0, -0.00078, 0.0) and keep it until something sets the velocity to something else.

    Conclusion:

    - getVelocity() doesn't give any useful information about a players movement, as it is completely independent of the clients/players movement most of the time.
    - getVelocity() will only be different from ~(0,0,0) if something set the vector to a different value shortly before.
    - setVelocity() only sends the client/player the vector once. The client/player has to do movement calculations with it. That means depending on e.g. lag, the actual movement by the player can be very different from what one would expect.

    Think of setVelocity() as a method to punch a player into a specific direction once, but you can't perfectly control when your hand reaches the player.
    Forget about getVelocity() altogether, unless you call it immediatly after something else (e.g. another plugin) used setVelocity(). That is the only time when it actually provides useful information.

    Real life example:

    I need to know when other plugins/the game tell the player to move in a certain direction fast, e.g. when hit by an arrow, or using a superjump skill or stuff like that. Lets take for example the "dash" of the Vampire plugin. It will set the velocity vector to a vector of length 5.0 in the direction you currently face.

    What happens:

    a) Vampire mod does player.setVelocity() with vector (5, 0, 0)
    b) Server sends player the message: "Please move with velocity (5, 0, 0) asap"
    c) Server does some calculations for other events that cause the velocity vector to change to e.g. (0.32, 0, 0)
    d) The player receives the message, and moves with velocity (5, 0, 0)
    e) Server receives the players move message. I read player.getVelocity() and don't know why the player moved that far, because his velocity vector doesn't fit to his actual movement (anymore).

    The velocity vector only carries relevant information between a) and c), afterwards it is just a triple of almost arbitrary numbers.
     
    ne0nx3r0 likes this.
  4. EvenPrime, thank you so much for that detailed explanation, that seems to make a lot of sense now. I just wish that the documentation would say something more than "gets the entity's velocity" =.=

    So knowing this, have you found a way to reliably multiply the player's walking speed?
     
  5. Offline

    Evenprime

    Your alternative solution with dir2 is afaik (sadly) the best solution there is. Player velocity can't really be used for more than pushing a player around. Just increasing how fast he can walk, how high he can jump is not possible with setting velocity (and I don't know of anything else that could achieve that, maybe at some point Notch will make these things configurable).

    You could probably improve your solution at least a little bit by calculating the direction for the pushing based on event.getFrom and event.getTo location instead of just the direction the player is looking at.
     
  6. Ok, thanks a lot for your help, I will try your suggestion.
     
  7. Offline

    Deminetix

    I've been trying to fix this jump thing so it is more logical and happens without the need for shifting etc.

    The problem is that a player velocity never returns any sign that what happened was a jump, and is always a negative value the same as falling.

    Here is my code.

    Code:
    boolean isJumping = false;
    
        public APluginMoveListener(APlugin instance) {
            plugin = instance;
        }
    
        public void onPlayerMove(PlayerMoveEvent event) {
            Player player = event.getPlayer();
    
            if(player.getVelocity().getY() < -0.0784000015258789 && !isJumping && player.getLocation().getBlock().getRelative(BlockFace.DOWN).getTypeId() != 0){
                player.setVelocity(new Vector(0,1.0,0));
                isJumping = true;
            }
    
            if(isJumping && player.getLocation().getBlock().getRelative(BlockFace.DOWN).getTypeId() != 0 && player.getVelocity().getY() == -0.0784000015258789) {
                isJumping = false;
            }
            // Print a couple values to the log for reference to what is happening
            Traits.log.info("y: " + player.getVelocity().getY());
            Traits.log.info("id: " + player.getLocation().getBlock().getRelative(BlockFace.DOWN).getTypeId());
        }
    The jumping works great, you push space and you go flying into the air, but it also triggers when you walk off the edge of a block.... Anyone have any ideas how we can accurately determine whether the player is jumping or falling
     
  8. Offline

    nisovin

    The player is jumping if the "to" location has a higher Y value than the "from" location. Using getVelocity() is going to be weird because it's treated strangely. You should probably not rely on it.
     
  9. Offline

    Deminetix

    But the to location will have a higher value than the from location when walking up steps as well :(
     
  10. Offline

    SalamiJack

    Not the best solution, but you could have an if statement which checks to see if the block below or infront the player is a set of stairs.
     
Thread Status:
Not open for further replies.

Share This Page