Solved Stack Effects & Event in an Event

Discussion in 'Plugin Development' started by Zenya4, May 25, 2017.

Thread Status:
Not open for further replies.
  1. Offline

    Zenya4

    Hi all,

    I'm working on this plugin that allows the player to fly (levitation effect) for 15 seconds after eating a chorus fruit. So far I'm done with the levitation and cancel teleportation part. However, I also want to cancel the damage from fall event after the player loses the levitation effect. I think I need to put this in the same class as I only want it to cancel after the player falls from being levitated, and not cancel it all the time. Moreover, I realise the levitation effect cannot stack. That means the levitation effect time does not reset to 15 seconds after I eat a new chorus fruit while levitating. Any help would be appreciated. My code:
    Code:
    
    package com.Zenya4.FlyingChorus;
    
    
    
    import org.bukkit.Bukkit;
    
    import org.bukkit.Material;
    
    import org.bukkit.event.EventHandler;
    
    import org.bukkit.event.EventPriority;
    
    import org.bukkit.event.Listener;
    
    import org.bukkit.event.player.PlayerItemConsumeEvent;
    
    import org.bukkit.event.player.PlayerTeleportEvent;
    
    import org.bukkit.inventory.ItemStack;
    
    import org.bukkit.plugin.java.JavaPlugin;
    
    import org.bukkit.potion.PotionEffect;
    
    import org.bukkit.potion.PotionEffectType;
    
    
    
    public class Main extends JavaPlugin {
    
    @Override
    
    public void onEnable() {
    
    Bukkit.getServer().getPluginManager().registerEvents(new EatListener(), this);
    
    Bukkit.getServer().getPluginManager().registerEvents(new ChorusTPListener(), this);
    
    }
    
    
    public final class EatListener implements Listener {
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void eatChorus(PlayerItemConsumeEvent event) {
    
    ItemStack inHand = event.getPlayer().getInventory().getItemInMainHand();
    
    if(inHand.getType() == Material.CHORUS_FRUIT && event.getItem().isSimilar(inHand)) {
    
    event.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, 300, 0));
    
    }
    
    }
    
    
    }
    
    public final class ChorusTPListener implements Listener {
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void chorusTP(PlayerTeleportEvent event) {
    
    if(event.getCause().equals(PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT)) {
    
    event.setCancelled(true);
    
    }
    
    }
    
    }
    
    
    @Override
    
    public void onDisable() {
    
    }
    
    }
    
    So to put it in points, what I need is:

    1. For the damage event from falling to be cancelled if it is due to falling from levitation via Chorus Fruit (and not from other causes like normal falling)

    2. For the Chorus Fruit Levitation Effect to be stackable (reset to 15 seconds after eating a new one)

    Thanks in advance for anyone who can help me!
     
  2. Offline

    Zombie_Striker

    @Zenya4
    #1: This is what you need to do:
    1. Create an Arraylist of UUIDs
    2. After giving the potion effect, wait every tick/couple of ticks to see if the effect is over. If it is, and the player is not on the ground, add their UUID to the arraylist. After this, continue checking every tick if the player is on the ground. Only when they are on the ground should you cancel this task and remove their UUID from the arraylist.
    3. On PlayerDamageEvent, if the player got damaged by fall damage and the player's UUID is in the array, cancel the event.
    #2, do the same thing you are currently doing, but remove the effect before adding it again. Doing that will reset the time.
     
  3. Offline

    Zenya4

    Thanks @Zombie_Striker .

    But is it possible to use player names instead of UUIDs? I'm not really familiar with UUIDs.
     
  4. Offline

    Zombie_Striker

    @Zenya4
    You can do that, but I recommend you try to use UUIDs whenever you can. UUIDs are constant; one UUID will always be equal to one player. However, names can change. At any point, a player can register for a new name, which may break plugins that only store names. The chance a player will change there name within the 15 seconds of the effect is unlikely, however this happening for other plugins you may make may not be as unlikely.

    In case you want to use UUIDs for this or for another project, you can get the player's UUID using Player#getUniqueId().
     
  5. Offline

    Horsey

    @Zombie_Striker You need to restart minecraft to change your name. It is near impossible to change your name within the 15 seconds.
    @Zenya4 I do suggest you use UUID's, they are very easy to use, they act pretty much the same as player names, and if you need to convert a UUID to a name, it is fairly easy to do Bukkit.getOfflinePlayer(UUID); which would return the latest name the player has used on the server (it works on online players too)
     
  6. Offline

    Zenya4

    Thanks for the info, but since it's unlikely that the UUID will change within 15 seconds, I'll not use it for this particular plugin.

    And I'm trying out my own way in cancelling the fall damage.
    Code:
    package com.Zenya4.FlyingChorus;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.EntityDamageEvent;
    import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
    import org.bukkit.event.player.PlayerItemConsumeEvent;
    import org.bukkit.event.player.PlayerTeleportEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.bukkit.potion.PotionEffect;
    import org.bukkit.potion.PotionEffectType;
    
    public class Main extends JavaPlugin {
        @Override
        public void onEnable() {
            Bukkit.getServer().getPluginManager().registerEvents(new EatListener(), this);
            Bukkit.getServer().getPluginManager().registerEvents(new ChorusTPListener(), this);
            Bukkit.getServer().getPluginManager().registerEvents(new FallListener(), this);
        }
    
        public static class EatListener implements Listener {
            public static Player player;
        @EventHandler(priority = EventPriority.HIGHEST)
        public static void eatChorus(PlayerItemConsumeEvent event) {
        Player player = event.getPlayer();
        ItemStack inHand = event.getPlayer().getInventory().getItemInMainHand();
            if(inHand.getType() == Material.CHORUS_FRUIT && event.getItem().isSimilar(inHand)) {
                player.removePotionEffect(PotionEffectType.LEVITATION);
                    player.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, 300, 0));
             
                } 
            }
        }
        public class ChorusTPListener implements Listener {
            @EventHandler(priority = EventPriority.HIGHEST)
            public void chorusTP(PlayerTeleportEvent event) {
                if(event.getCause().equals(PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT)) {
                    event.setCancelled(true);
                }
            }
        }
        public class FallListener implements Listener {
            @EventHandler(priority = EventPriority.HIGHEST)
            public void onFall(EntityDamageEvent event) {
                if(EatListener.player.getActivePotionEffects().equals(PotionEffectType.LEVITATION)) {
                    long oldtime = System.currentTimeMillis();
                    if(!EatListener.player.getActivePotionEffects().equals(PotionEffectType.LEVITATION)) {
                    long newtime = System.currentTimeMillis();
                        if(newtime < oldtime + 5000 && event.getCause() == DamageCause.FALL) {
                                event.setCancelled(true);
                            }
                        }
                    }
                }
            }
    
        @Override
        public void onDisable() {
        }
    }
    
    Will it work if I do it like this? I'm trying to cancel the fall damage if it happens 5 seconds after a player falls from levitation. Thanks for anyone who can reply.

    EDIT: I think I did the
    Code:
    public static Player player;
    wrong. Can anyone comfirm if it is correct please? What I mean is does the
    Code:
    player
    in there refer to
    Code:
    event.getPlayer()
    ?
     
    Last edited: May 26, 2017
  7. Offline

    timtower Administrator Administrator Moderator

    @Zenya4 You should never need static in Bukkit.
    Please remove all static things.
    Move the listener classes to their own files.
     
  8. Offline

    FrostedSnowman

    Use a set implementation instead for this. They are faster in this case.

    Code:
    Set<UUID> inEffect = new HahSet<>();
     
  9. Offline

    Zenya4

    Code:
    
    
    package com.Zenya4.FlyingChorus;
    
    
    
    import java.util.HashSet;
    
    import java.util.Set;
    
    import java.util.UUID;
    
    import org.bukkit.Bukkit;
    
    import org.bukkit.Material;
    
    import org.bukkit.entity.Player;
    
    import org.bukkit.event.EventHandler;
    
    import org.bukkit.event.EventPriority;
    
    import org.bukkit.event.Listener;
    
    import org.bukkit.event.entity.EntityDamageEvent;
    
    import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
    
    import org.bukkit.event.player.PlayerItemConsumeEvent;
    
    import org.bukkit.event.player.PlayerTeleportEvent;
    
    import org.bukkit.inventory.ItemStack;
    
    import org.bukkit.plugin.java.JavaPlugin;
    
    import org.bukkit.potion.PotionEffect;
    
    import org.bukkit.potion.PotionEffectType;
    
    
    
    public class Main extends JavaPlugin {
    
    @Override
    
    public void onEnable() {
    
    Bukkit.getServer().getPluginManager().registerEvents(new EatListener(), this);
    
    Bukkit.getServer().getPluginManager().registerEvents(new ChorusTPListener(), this);
    
    Bukkit.getServer().getPluginManager().registerEvents(new FallListener(), this);
    
    }
    
    
    public class EatListener implements Listener {
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void eatChorus(PlayerItemConsumeEvent event) {
    
    Player player = event.getPlayer();
    
    ItemStack inHand = event.getPlayer().getInventory().getItemInMainHand();
    
    if(inHand.getType() == Material.CHORUS_FRUIT && event.getItem().isSimilar(inHand)) {
    
    player.removePotionEffect(PotionEffectType.LEVITATION);
    
    player.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, 300, 0));
    
    Set<UUID> hasEffect = new HashSet();
    
    hasEffect.add(player.getUniqueId());
    
    
    }
    
    }
    
    }
    
    public class ChorusTPListener implements Listener {
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void chorusTP(PlayerTeleportEvent event) {
    
    if(event.getCause().equals(PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT)) {
    
    event.setCancelled(true);
    
    }
    
    }
    
    }
    
    public class FallListener implements Listener {
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void onFall(EntityDamageEvent event) {
    
    //HOW DO I GET hasEffect FROM EATLISTENER???
    
    }
    
    }
    
    
    @Override
    
    public void onDisable() {
    
    }
    
    }
    
    That is my current code ^.

    2 Questions:

    1. Is it possible to set a boolean to true in EatListener, and check if its true and set it to false in FallListener instead of using HashSet() cause I'm not really familiar with it?

    2. How do I access the HashSet() from FallListener? Same question if it is possible to use boolean.

    Hope someone can answer. Thanks :D
     
    Last edited: May 29, 2017
  10. Offline

    Zenya4

    Ok I decided to stick with UUIDs anyways. So here is my current code.
    Code:
    
    package com.Zenya4.FlyingChorus;
    
    
    
    import java.util.HashSet;
    
    import java.util.Set;
    
    import java.util.UUID;
    
    import org.bukkit.Bukkit;
    
    import org.bukkit.Material;
    
    import org.bukkit.entity.Player;
    
    import org.bukkit.event.EventHandler;
    
    import org.bukkit.event.EventPriority;
    
    import org.bukkit.event.Listener;
    
    import org.bukkit.event.entity.EntityDamageEvent;
    
    import org.bukkit.event.player.PlayerItemConsumeEvent;
    
    import org.bukkit.event.player.PlayerTeleportEvent;
    
    import org.bukkit.inventory.ItemStack;
    
    import org.bukkit.plugin.java.JavaPlugin;
    
    import org.bukkit.potion.PotionEffect;
    
    import org.bukkit.potion.PotionEffectType;
    
    
    
    public class Main extends JavaPlugin {
    
    @Override
    
    public void onEnable() {
    
    Bukkit.getServer().getPluginManager().registerEvents(new EventListener(), this);
    
    }
    
    
    public class EventListener implements Listener {
    
    Set<UUID> disableFall = new HashSet<>();
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void eatChorus(PlayerItemConsumeEvent event) {
    
    ItemStack inHand = event.getPlayer().getInventory().getItemInMainHand();
    
    if(inHand.getType() == Material.CHORUS_FRUIT && event.getItem().isSimilar(inHand)) {
    
    event.getPlayer().removePotionEffect(PotionEffectType.LEVITATION);
    
    event.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, 300, 0));
    
    disableFall.add(event.getPlayer().getUniqueId());
    
    }
    
    }
    
    public void chorusTP(PlayerTeleportEvent event) {
    
    if(event.getCause().equals(PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT)) {
    
    event.setCancelled(true);
    
    }
    
    }
    
    public void onFall(Player player, EntityDamageEvent event) {
    
    if(event.getCause().equals(EntityDamageEvent.DamageCause.FALL)) {
    
    player.sendMessage("Fall Event Triggered"); //For debug
    
    if(disableFall.contains(player.getUniqueId())) {
    
    disableFall.remove(player.getUniqueId());
    
    event.setCancelled(true);
    
    }
    
    }
    
    }
    
    }
    
    @Override
    
    public void onDisable() {
    
    }
    
    }
    
    
    
    Why doesn't it work? Hope someone can answer thanks!
     
    Last edited: May 30, 2017
  11. Offline

    Caderape2

    @Zenya4 You don't need a new class for each event, you can put them all in the same class.

    You are creating a hashset everytime. just create it once as a field and use the add and remove method

    This is not an event. An event has only one parameters, the event class.

    - The hashset as to be a field, so you can access it between two events.
    - Check if the damage cause if fall_damage, and if the player is in the hashset, then you can cancel the event
    - You will have to create a scheduler for remove the player from the hashset after a certain amount of time
     
  12. Offline

    Zenya4

    @Caderape2 I are you referring to post #9 or #10?

    I realised some mistakes I made in #9 and fixed them in #10.

    As for the onFall, I will remove the player parameter. Thanks for the info!

    EDIT: Thank you all for your help! My plugin now works! Here is the code for future reference:
    Code:
    
    package com.Zenya4.FlyingChorus;
    
    
    
    import java.util.HashSet;
    
    import java.util.Set;
    
    import java.util.UUID;
    
    import org.bukkit.Bukkit;
    
    import org.bukkit.Material;
    
    import org.bukkit.event.EventHandler;
    
    import org.bukkit.event.EventPriority;
    
    import org.bukkit.event.Listener;
    
    import org.bukkit.event.entity.EntityDamageEvent;
    
    import org.bukkit.event.player.PlayerItemConsumeEvent;
    
    import org.bukkit.event.player.PlayerTeleportEvent;
    
    import org.bukkit.inventory.ItemStack;
    
    import org.bukkit.plugin.java.JavaPlugin;
    
    import org.bukkit.potion.PotionEffect;
    
    import org.bukkit.potion.PotionEffectType;
    
    
    
    public class Main extends JavaPlugin {
    
    @Override
    
    public void onEnable() {
    
    Bukkit.getServer().getPluginManager().registerEvents(new EventListener(), this);
    
    }
    
    
    public class EventListener implements Listener {
    
    Set<UUID> disableFall = new HashSet<>();
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void eatChorus(PlayerItemConsumeEvent event) {
    
    ItemStack inHand = event.getPlayer().getInventory().getItemInMainHand();
    
    if(inHand.getType() == Material.CHORUS_FRUIT && event.getItem().isSimilar(inHand)) {
    
    event.getPlayer().removePotionEffect(PotionEffectType.LEVITATION);
    
    event.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, 300, 0));
    
    disableFall.add(event.getPlayer().getUniqueId());
    
    Bukkit.getConsoleSender().sendMessage("Player's UUID is " + event.getPlayer().getUniqueId()); //Debug
    
    }
    
    }
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void chorusTP(PlayerTeleportEvent event) {
    
    if(event.getCause().equals(PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT)) {
    
    event.setCancelled(true);
    
    }
    
    }
    
    @EventHandler(priority = EventPriority.HIGHEST)
    
    public void onFall(EntityDamageEvent event) {
    
    if(event.getCause().equals(EntityDamageEvent.DamageCause.FALL)) {
    
    UUID playeruuid = event.getEntity().getUniqueId();
    
    if(disableFall.contains(playeruuid)) {
    
    disableFall.remove(playeruuid);
    
    event.setCancelled(true);
    
    }
    
    }
    
    }
    
    }
    
    @Override
    
    public void onDisable() {
    
    }
    
    }
    
    I will mark this as solved now. Thanks again, everyone!
     
    Last edited: May 30, 2017
Thread Status:
Not open for further replies.

Share This Page