Make players bounce back from zone

Discussion in 'Spigot Plugin Development' started by kreashenz, May 30, 2018.

  1. I have built a safezone, basically I need players to be bounce away from edge of the safezone if their name is not in a hashmap.

    I've look at so, so, so many different resources, tried using their code ect but instead the player just goes crazy, jumping back, left and right, just random directions, even farther away from the safezone.
    I put in a timer to hopefully stop the spam messages, but for some reason the "Can't enter this yet" message doubles up?

    What could I be doing wrong here?
    Code (Text):
        @EventHandler
        public void onPlayerMove(PlayerMoveEvent e) {
            Player p = e.getPlayer();
            if(p.getWorld().getName().equalsIgnoreCase(ins.getConfig().getString("safezone.world"))) {
                if(!getSafezone().contains(p.getLocation().getBlock())) {
                    if(!ins.map.contains(p.getName()) && !cool.contains(p.getName())) {
                        bounceBack(p, e.getFrom(), e.getTo());
                    }
                }
            }
        }

        private void timer() {
            ins.getServer().getScheduler().scheduleSyncRepeatingTask(ins, new Runnable() {
                @Override
                public void run() {
                    cool.clear();
                }
            }, 0l, 2l);
        }

        private void bounceBack(Player p, Location from, Location to) {
            if(!cool.contains(p.getName())) {
                double x = from.getX() - to.getX();
                double y= from.getY() - to.getY();
                double z = from.getZ() - to.getZ();

                Vector v = new Vector(x, y ,z);
                v.normalize();
                v.multiply(1.5D);
                v.setY(0.5D);
             
                p.setVelocity(v);
             
                /*
                p.teleport(from);
                p.setVelocity(new Vector(from.getX() - to.getX(), (from.getY() - to.getY()) * 0.5D, from.getZ() - to.getZ()).multiply(2.3D));
                 */
                cool.add(p.getName());
                Functions.tell(p, "§cCan't leave §bSafezone §cyet!");
            }
        }
    It is insane how much time I've put into this and still can't find a viable solution to it.
    [EDIT] I mistakenly put had "farther into the safezone" when I meant "farther away from the safezone". I want them to be kept INSIDE the safezone, if their name is not in a hashmap.
     
    #1 kreashenz, May 30, 2018
    Last edited: May 30, 2018
  2. You might want to use a Map with epoch millis instead of having a timer task clearing the cooldown.

    I think Location has a to vector method so you can get two vectors. After that subtract from vector and to vector in order to bounce the player in the right direction. If you're unsure about the direction do some vector drawing on paper
     
  3. Your math is a little wrong
    You should just do to.subtract(from).toVector(), then multiply it by something such as 0.05. you need to experiment to find a number that works for you. That should really be it. You can also set y to a small number to give a bounce effect like you did there.
     
  4. Sorry for my ignorance, I've never heard of "epoch millis". What difference would using a new Map in a timer of ms have compared to the original timer() method I have?

    If I change the
    double x = from.getX() - to.getX() to double x = to.getX() - from.getX()
    It sends me flying forward, like I'm flying in steps.
     
  5. Ah sorry, that makes sense. I thought U wanted the player to go to the 'to' location not the from location. Then just invert what I said. But use the functions built into bukkit instead of doing it manually.
     
  6. Epoch millisecond is the amount of milliseconds passed since January 1st 1970, so it's a timestamp you can use for a lot of things.
    You get it with
    Code (Text):
    System.currentTimeMillis()
    Which I've heard is accurate to 15ms (1 Bukkit tick is 50ms)

    In order to make a cooldown you can add an amount of milliseconds, say a second (1000ms) to it, and check against the current time next time the thing is run, eg
    Code (Text):
    if (System.currentTimeMillis() > storedCooldownEndTime)
    https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#currentTimeMillis()
     
    • Informative Informative x 1
  7. Code (Java):
    public void bounceBack(Player p, Location loc){
            double dX = loc.getX() - p.getLocation().getX();
            double dY = loc.getY() - p.getLocation().getY();
            double dZ = loc.getZ() - p.getLocation().getZ();
            double yaw = Math.atan2(dZ, dX);
            double pitch = Math.atan2(Math.sqrt(dZ * dZ + dX * dX), dY) + Math.PI;
            double X = Math.sin(pitch) * Math.cos(yaw);
            double Y = Math.sin(pitch) * Math.sin(yaw);
            double Z = Math.cos(pitch);
                     
            Vector vector = new Vector(X, Z, Y);
            p.setVelocity(vector)
    }
     
  8. This one does not seem to work either. Seems that it sends the player the opposite way from where I want them.
    I need them to bounce away from the edge of the safezone, (not exactly, just direction wise) towards the center of the safezone.
     
  9. Just invert the equation then ;)
     
  10. Do not teleport the player in the PlayerMoveEvent! Doing so will trigger a 2nd PlayerMoveEvent to fire, which can lead to undesired results.

    Instead, use PlayerMoveEvent#setTo(someLocation) to redirect where they should be moving to. If you want something like what WorldGuard does when trying to walk passed a region border you're not allowed to use event.setTo(event.getFrom()). If you want more of a "bounce" then make a vector to -> from (not from -> to) then multiply it and setTo the vector's multiplied end location.
     
  11. Keep in mind that I have the p.teleport(from) commented out.
    I don't think I understand what you're saying. It seems even if I change that current code to event.setTo then I get even more erratic movements, again seeming to trigger the PlayerMoveEvent more than once. If I set the vector to -> from, I get pushed farther away from the safezone, that's not what I want to achieve. And when I set the setTo to a new vector, derived from using to.vector - from.vector I get sent straight into the floor (coords 0, 0, 0). It's quite strange what's happening, to be honest.

    I've even had a look at the way that WorldGuard does it, and it seems that they "test" the movement ahead and approve it, basically. And that complexity is what I don't particularly want to get in to.

    Thanks for your info too mate, I'll keep that info in mind for future plugins :D
     
  12. I tried, I probably did it wrong (I'm not 100% sure on the Java Math class), I swapped the Math.sqrt(dz * dz + dx * dx) to Math.sqrt(dz * dz - dx * dx) and didn't get anywhere with that. I think I'm a bit silly because I know that's pretty far from saying "I inverted this equation" haha.
     
  13. That's too logical to be considered a solution.
     
  14. You're a funny one. As I did say, in the comment above your post, I am not sure how to invert an equation using the Java Math class. So, please, enlighten me.
     
  15. You could maybe invert it by swapping the locations instead
     
  16. The inversion of an equation is the opposite, means the same thing. If you don't understand that concept I believe you should scrub up on your Java skills first before even thinking about touching any API's.
     
  17. I do understand the concept of inversion. And I believe if you're not going to contribute any helpful information, then please remove yourself from this thread. I don't understand why people like you get satisfaction from saying "oh you're clearly don't understand the Java language because you can't put one small concept into practice". No one needs your sarcastic, condescending comments especially when they're not helpful.
    FYI, been doing Java for 5 years and still learn something new nearly every day. No one is perfect, especially not you or me. Go away.