1.17.x Cancel lava damage if pvp is off

Discussion in 'Spigot Plugin Development' started by yashc2025, Jul 17, 2021.

  1. So I am making a plugin in which if someone types "/pvp off" then he doesn't take damage from other players but I also need to stop it for lava.
    So if person A's pvp is turned off then he won't take damage if person B puts lava on him

    But he should still take damage if he walks into lava

    I am a beginner so any suggestions would make a big difference.
  2. Listen to EntityDamageEvent, check if the cause (using #getCause) is LAVA, then check if the player has PVP off (however you did that in your plugin) and then cancel it if all of that is true.
  3. But with this, he will be able to swim in lava pools and stuff
    What I want to do is that: if the lava is placed by a player on the block on which the other player (whose PVP is off) is standing then he wont take damage
  4. In that case, you'll have to create a database to keep in memory every lava block placed by a player, and when listening EntityDamageEvent you'll have to check if the location is in that database.
    But for how long will you keep it? Meaning, what is the window of time which afterward you decide "This lava block the player placed is no longer considered a player placed lava block"?
  5. You need to check if a player places Lava, store that data then check if the player with combat turned off has just taken damage from that lava. A database shouldn't be necessary as you could do this Asynchronously, this would also save server performance rather than writing and deleting from a database. however in the event of a Server Restart, anything stored ASynchronously will be voided so you could output to a data file then have the plugin read the data file then delete the file after the server has started again.
  6. A database can be anything from MySQL/MariaDB to a HashMap - I just meant he needs to store the info somehow and not ignore it.
  7. I only want the player to not take damage if lava is placed on the block on which he is standing. But if the lava is placed somewhere and then this player walks into it then I want him to take damage(Even if he walks into players placed lava).
  8. You could listen for block place event and in the event set a boolean connected to a location true for like 1 second or half a second using bukkit runnables

    To summarize:
    Hashmap<Location, boolean>
    put location and true into hashmap if block placed is lava
    and then you could set up a bukkit runnable that removed the entry or sets it false after 1 second or whatever you want

    Then in the playerdmgevent check if the hahshmap contains the player's location, check for lava dmg and then cancel if true
  9. I would just listen to the PlayerBucketEmptyEvent. If a player is within 1m of the block and has pvp disabled, cancel the event. Would be a lot easier than having to cancel damage events and it would also be more user friendly, in my opinion.
    • Like Like x 2
  10. people are going to find ways to abuse that
    abusing cancel the event within 1m: let it flow.. place it above them, etc
    abusing cancel the event within blocks: nonpvp player chases around a pvp player and prevents them from placing lava during pvp

    use a set that contains a custom object that holds 3 ints that properly overrides #equals and hashcode, when a player places a bucket of lava, record that the three coordinates of that block. when lava flows, check the source flow block to see if its in the set, and if so add the destination flow block to the set as well. remove the coordinates from the set if the lava is picked up, fizzles out, gets a block placed inside of it, water changes it to stone, etc

    /e just read what the guy wants. give a player lava immortality if they arent moving. they cant walk/swim into natural occuring lava. but someone cant harm another with lava if they arent moving at all. i dont think flowing lava would push a player, and this may or may not call playermoveevent in the event that it did, might need some testing tho
  11. I guess this would be easier to do
    And even if the lava is flowing the user will have enough time to RUN
    So I have to check if the cords of where lava is placed are near another player whose PVP is off and if so then it will not let anyone empty their bucket.

    Can you help me with the code for this? I mean the logic to use with spigot since I am a beginner

    Thank Youu!
  12. Some people would opt in for saving all disabled-pvp users' UUIDs in a file/database, but for this instance it is much less complicated to use a Player's PersistentDataContainer, which allows you to store keys (strings) and values (strings, doubles, etc.). For any player with pvp disabled, add a premade NamespacedKey to their persistent data container and check whether or not they have it. If they have it, pvp is disabled. If not, it is enabled. In your command to toggle pvp, simply add or remove this key, or change the value associated to it to differentiate.

    In the listener, just check if the location of where the bucket was emptied has a distance less than 1m (should be able to use Location#distanceSquared(Location loc) and see if it is <1) to all players (there may be a more efficient way to get all nearby players, maybe through getting all entities of Player.class through world, but nothing at the top of my mind :shrug:). If the player nearby has pvp disabled, cancel the event.
    • Like Like x 1
  13. Thank You SO MUCH!!!

    Also is there a way I can get the name of the person who placed the lava and the person on which lava was placed?
    So for example John has his pvp off and Mark comes and places lava near him
    If this happens i want to send a message to both of them
    So John will get a message saying "Mark" tried to kill you with lava (This message should be only visible to John and not other players on the server)

    And Mark will get a message saying Ayo don't try to kill "John" with lava he has his pvp off (This message should be only visible to mark and not other players on the server)
  14. I imagine you mean the player's names? Yes, players have a getName() method which returns the Mojang username and a getDisplayName() method that returns their display name (set by plugins, could have color, etc...)
    • Useful Useful x 1
  15. But how would i know who placed the lava and on whom was the lava placed?
  16. Use the event I linked in my original post. It has a PlayerEvent#getPlayer() method that allows you to get the player who placed the bukkit. From there, use World#getNearbyEntities(location, 1, 1, 1, e -> e instanceof Player) to get all players within 1m of the block placed. This returns a Collection<Player> that you can use to iterate through and check if they have pvp disabled.
    • Winner Winner x 1
  17. Ah ok gotcha

    Thank YOU!!