Prevent a player from swimming.

Discussion in 'Plugin Development' started by sebcio98, Feb 9, 2018.

  1. Offline

    sebcio98

    Hello fellow developer person.

    I'm looking for a way to prevent players from swiming upwards while in water (without affecting other.. features of underwater movement). By the underlined prevent I mean to not let the client swim up with some Minecraft/Bukkit tricks or even black magic.
    One of the easiest solutions that instantly comes to most minds is "just cancel PlayerMoveEvent", which I don't want to use, as this would make the effect much less smooth (and make adding other underwater features harder).

    If no such magic exists, I'm fine with any solution. It just needs to work.

    Context/What I'm also planning to do (but not asking how to):
    What I want to accomplish is to have some players walk, jump, etc, on the bottom of any watery area and completely remove their swimming ability.

    Thanks in advance,
    me.
     
  2. Offline

    NukeDude

    If you haven't tried this already, using the PlayerMoveEvent detect a positive change in the y value and cancel it instead of just canceling the entire thing.

    You can also try using vectors.
     
  3. Offline

    MemeplexOwner

    Question, how do I use vectors?
     
  4. Online

    Nostos

    @MemeplexOwner Currently working on a solution to this I'll tell you when done. but this might help you, it's what I have so far:
    Code:
    @EventHandler
             
               public void onPlayerSwim(Player event) {
                 
                   Player player = (Player) event.getPlayer();
                 
                   Location playerloc = player.getLocation();
                   Location playerloc2 = playerloc.subtract(0, 1, 0);
                 
                   if(player.getLocation().getBlock().getRelative(BlockFace.UP).getType() == Material.WATER || player.getLocation().getBlock().getRelative(BlockFace.UP).getType() == Material.STATIONARY_WATER) {
                     
                       playerloc.getBlock().setType(Material.AIR);
                       playerloc2.getBlock().setType(Material.AIR);
                      
                   }
                 
               }
    it's laggy but if you were to expand how many blocks are replaced it might work
     
  5. Offline

    NukeDude

    Currently in the car, but codecademy has a very nice course on them. Sorry I can't help more, I'd need to get on my computer, which I won't have for the rest of the day.
     
  6. Offline

    MemeplexOwner

    I'll be sure to look into that and find that, thanks!
     
  7. Offline

    sebcio98

    @NukeDude I have literally said in my post that cancelling PlayerMoveEvent is one of the easiest solutions and I don't want to use it.
    Thanks for trying, but please read the whole post before replying.

    @Nostos Thanks, though I see a few problems with your solution:
    1. Lag. Lots. If I were to tun this kind of code for hundreds of players the server would probably die. That's because when you actually remove the block it often (almost always, actually) causes a lighting update and that, depending on the terrain, may be one of the most calculation-heavy events. And that's only one kind of event it calls among many.
    2. It is not as seamless as I'd like it to be.
    3. When there is a bugged water block, which doesnt flow down, put there by a map maker on purpouse, your idea will update it breaking the prepared map.


    Overall update on the idea:
    I think I found another interesting way of doing this: removing the water and sending players something that reasembles it instead. With that idea, all I need is a way to inform players that there's water in a certain spot. I thought of putting 8th flowing water block just on the surface, but then there's a problem with 1-block deep spots, because players still can swim in those. Maybe a ghost block of water is somehow possible? I couldn't get it to work, but I'm not very experienced with ghost blocks.


    Update 2:
    I have found a seamless and satisfying solution, however it is not the most efficient one, so I will leave this thread open for further ideas in case anyone has a good one to share.
    Here's what I did - save the areas where the water is, then remove it and replace the surface with a custom-modeled entity with disabled gravity that's just a flat square with stationary water's texture on 50% transparency. When player is submerged completely (eyes below water level) a visual effect is applied (either through custom texture of equipped pumpkin or packets; I have not checked yet whether it can be done through packets).
    About applying the feature only to certain players: All of the above can be used on an exclusive set of players either through sending direct world updates or packet filter.
    Then of course just a small adjustment of natural anti-cheat is needed, so the players with the effect are not kicked/teleported back from moving too fast underwater.

    Update 3:
    Of course keeping one entity per surface block in an ocean is a very bad idea, so multiple sizes of fake water would be made, up to 16x16 or even more, depending on what are the limitations of custom models in resource packs.
     
    Last edited: Feb 11, 2018
  8. Offline

    Protophite

    @sebcio98
    Try giving them jump potion effect with an amplifier of -5.
     
  9. Offline

    sebcio98

    @Protophite That was literally my first idea and unfortunately it doesn't work, because there's no potion effect that modifies the ability to swim. And lifting off from the ground underwater doesn't count as jumping.
     
  10. Offline

    Horsey

    Oof thats way too complex.

    Instead of cancelling the PlayerMoveEvent, try this:
    Code:java
    1. @EventHandler
    2. public void onMove(PlayerMoveEvent event){
    3. Location to = event.getTo().clone();
    4. to.setY(event.getFrom().getY());
    5. event.setTo(to);
    6. }
     
  11. Offline

    timtower Ninja on the waves Moderator

    Can't jump with that either.
     
  12. Offline

    Horsey

    It was an example.

    I don't really want to facilitate copy + pasting code with no effort and it actually working as expected.
     
  13. Offline

    sebcio98

    @Horsey I had this idea before and it would work with calculating player's jump trajectory and not letting them swim above it, but there's a problem. As I said a few times, it wouldn't be as smooth as I'd like it to be. When player would try swimming up your code would just slam him back down creating a jiggling effect, because of server-client interaction delay, over which we don't have any control. Again, that's not preventing the client from jumping.
     
  14. Offline

    Proxygames14

    I got two question for you @sebcio98
    1. Do you mean swimming in the newest snapshot or just being in the water.
    2. So I'm trying to understand what you are asking for, Do you wan't to let the player go down but block when it's trying to press (up) in the water?
     
  15. Offline

    sebcio98

    @Proxygames14 I was thinking about the current version, not 1.13, though the idea stays exactly the same there. I said I want to prevent player from swimming up, leaving their ability to walk on the ground underwater and adding jumping. Not sure if I want them to fall normally or glide down, but that's easy to add no matter the solution of current problem.

    For now, I want a way to have a player behave underwater exactly the same way they would on the ground. That's why in my solution I removed the water completely for some players.


    Overall update 4 (alternative idea):
    Another incomplete idea I had is having a player ride some entity that keeps the player's WASD controls (client side) and jumps underwater (doesn't swim). I have no idea whether that's possible, so I'm just throwing this here in case someone has more experience with modifying entity behaviour.
    Or I could be completely wrong and all of the passenger-entity interactions are server-side. In that case, that's a bad idea.
     
    Last edited: Feb 16, 2018
  16. Offline

    Horsey

    @sebcio98 Ah I understand. So what you do is see if the player's Y is 1 greater than the top most solid block under the player. So, the player is swimming up more than one block. Then just get their velocity and set its Y to, say, -1. This will result in the player experiencing a downward "force" like gravity above ground.
     
  17. Offline

    Proxygames14

    one sentence
    : Changing gravity under water
     
  18. Offline

    timtower Ninja on the waves Moderator

    @Proxygames14 1. How is that 1 word?
    2. Could you explain some more? How would it work? How would it feel for the player?
     
  19. Offline

    Proxygames14

    I was thinking of the fact that Bukkit has a function whichs check if you are in the water and then it will change the gravity + velocity, And I thought that if we change that in some kind of way by adding the exact same amount of power in the gravity it would go back to normal
     
  20. Offline

    sebcio98

    @Proxygames14
    1. Lifting off the ground underwater is much slower than jumping, I don't see how gravity would prevent the first one and enable the second.
    2. A Bukkit function checking whether player is underwater doesn't help, since it's very easy to do your own one. An event would be much more helpful, but that doesn't exist. Just as the function you're talking about I believe, never saw such thing.
    3. With that you're shooting people towards the ground when they get too high instead of preventing the action of swimming. Surely this works, but the effect it brings isn't really what we're looking for. The player has to feel like they're walking and jumping.
     
    Last edited: Feb 16, 2018
  21. Offline

    Proxygames14

    Ok I mean: Bukkit made a system that if a player is under water the movement will be slower ect. If you turn that back like on the surface you are done.

    Sent from my SM-G920F using Tapatalk
     
  22. Offline

    sebcio98

    @Proxygames14 You see, that's not true, because Bukkit has no such thing. All of the underwater effects are client-side.
     
  23. Offline

    Proxygames14

    Seriously? That kinda make no sence at all

    Sent from my SM-G920F using Tapatalk
    But if you slow down that progress with velocity you might be able to do that.
     
  24. Offline

    timtower Ninja on the waves Moderator

    A lot is handled client side like that, there is also a lot checked on both sides.
     
  25. Offline

    Proxygames14

    Ok and what if can try to duplicate the normal gravity system and copy it into the jar and apply it underwater?

    Sent from my SM-G920F using Tapatalk
     
  26. Offline

    timtower Ninja on the waves Moderator

    Then you will be working for a long time for a small thing.
    You need to modify the server and the client after finding it.
     

Share This Page